diff options
-rw-r--r-- | llvm/lib/IR/ConstantFold.cpp | 18 | ||||
-rw-r--r-- | llvm/test/Analysis/ConstantFolding/vector-undef-elts.ll | 16 |
2 files changed, 17 insertions, 17 deletions
diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp index 90a8366d169..107975df1e7 100644 --- a/llvm/lib/IR/ConstantFold.cpp +++ b/llvm/lib/IR/ConstantFold.cpp @@ -916,13 +916,14 @@ Constant *llvm::ConstantFoldInsertValueInstruction(Constant *Agg, return ConstantVector::get(Result); } - -Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode, - Constant *C1, Constant *C2) { +Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode, Constant *C1, + Constant *C2) { assert(Instruction::isBinaryOp(Opcode) && "Non-binary instruction detected"); - // Handle UndefValue up front. - if (isa<UndefValue>(C1) || isa<UndefValue>(C2)) { + // Handle scalar UndefValue. Vectors are always evaluated per element. + bool HasScalarUndef = !C1->getType()->isVectorTy() && + (isa<UndefValue>(C1) || isa<UndefValue>(C2)); + if (HasScalarUndef) { switch (static_cast<Instruction::BinaryOps>(Opcode)) { case Instruction::Xor: if (isa<UndefValue>(C1) && isa<UndefValue>(C2)) @@ -1024,9 +1025,8 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode, } } - // At this point neither constant should be an UndefValue. - assert(!isa<UndefValue>(C1) && !isa<UndefValue>(C2) && - "Unexpected UndefValue"); + // Neither constant should be UndefValue, unless these are vector constants. + assert(!HasScalarUndef && "Unexpected UndefValue"); // Handle simplifications when the RHS is a constant int. if (ConstantInt *CI2 = dyn_cast<ConstantInt>(C2)) { @@ -1218,7 +1218,7 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode, } } } else if (VectorType *VTy = dyn_cast<VectorType>(C1->getType())) { - // Perform elementwise folding. + // Fold each element and create a vector constant from those constants. SmallVector<Constant*, 16> Result; Type *Ty = IntegerType::get(VTy->getContext(), 32); for (unsigned i = 0, e = VTy->getNumElements(); i != e; ++i) { diff --git a/llvm/test/Analysis/ConstantFolding/vector-undef-elts.ll b/llvm/test/Analysis/ConstantFolding/vector-undef-elts.ll index c590dd3cdf7..f6969d83fce 100644 --- a/llvm/test/Analysis/ConstantFolding/vector-undef-elts.ll +++ b/llvm/test/Analysis/ConstantFolding/vector-undef-elts.ll @@ -1,11 +1,11 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -constprop -S -o - | FileCheck %s -; FIXME: When both operands are undef in a lane, that lane should produce an undef result. +; When both operands are undef in a lane, that lane should produce an undef result. define <3 x i8> @shl() { ; CHECK-LABEL: @shl( -; CHECK-NEXT: ret <3 x i8> zeroinitializer +; CHECK-NEXT: ret <3 x i8> <i8 undef, i8 0, i8 0> ; %c = shl <3 x i8> undef, <i8 undef, i8 4, i8 1> ret <3 x i8> %c @@ -13,7 +13,7 @@ define <3 x i8> @shl() { define <3 x i8> @and() { ; CHECK-LABEL: @and( -; CHECK-NEXT: ret <3 x i8> zeroinitializer +; CHECK-NEXT: ret <3 x i8> <i8 undef, i8 0, i8 undef> ; %c = and <3 x i8> <i8 undef, i8 42, i8 undef>, undef ret <3 x i8> %c @@ -21,7 +21,7 @@ define <3 x i8> @and() { define <3 x i8> @and_commute() { ; CHECK-LABEL: @and_commute( -; CHECK-NEXT: ret <3 x i8> zeroinitializer +; CHECK-NEXT: ret <3 x i8> <i8 0, i8 0, i8 undef> ; %c = and <3 x i8> undef, <i8 -42, i8 42, i8 undef> ret <3 x i8> %c @@ -29,7 +29,7 @@ define <3 x i8> @and_commute() { define <3 x i8> @or() { ; CHECK-LABEL: @or( -; CHECK-NEXT: ret <3 x i8> <i8 -1, i8 -1, i8 -1> +; CHECK-NEXT: ret <3 x i8> <i8 undef, i8 -1, i8 undef> ; %c = or <3 x i8> <i8 undef, i8 42, i8 undef>, undef ret <3 x i8> %c @@ -37,7 +37,7 @@ define <3 x i8> @or() { define <3 x i8> @or_commute() { ; CHECK-LABEL: @or_commute( -; CHECK-NEXT: ret <3 x i8> <i8 -1, i8 -1, i8 -1> +; CHECK-NEXT: ret <3 x i8> <i8 -1, i8 -1, i8 undef> ; %c = or <3 x i8> undef, <i8 -42, i8 42, i8 undef> ret <3 x i8> %c @@ -45,7 +45,7 @@ define <3 x i8> @or_commute() { define <3 x float> @fadd() { ; CHECK-LABEL: @fadd( -; CHECK-NEXT: ret <3 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000, float 0x7FF8000000000000> +; CHECK-NEXT: ret <3 x float> <float undef, float 0x7FF8000000000000, float undef> ; %c = fadd <3 x float> <float undef, float 42.0, float undef>, undef ret <3 x float> %c @@ -53,7 +53,7 @@ define <3 x float> @fadd() { define <3 x float> @fadd_commute() { ; CHECK-LABEL: @fadd_commute( -; CHECK-NEXT: ret <3 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000, float 0x7FF8000000000000> +; CHECK-NEXT: ret <3 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000, float undef> ; %c = fadd <3 x float> undef, <float -42.0, float 42.0, float undef> ret <3 x float> %c |