diff --git a/llvm/lib/VMCore/ConstantFold.cpp b/llvm/lib/VMCore/ConstantFold.cpp index a26198067c6a..2f2c61812902 100644 --- a/llvm/lib/VMCore/ConstantFold.cpp +++ b/llvm/lib/VMCore/ConstantFold.cpp @@ -450,14 +450,20 @@ Constant *llvm::ConstantFoldShuffleVectorInstruction(const Constant *V1, /// EvalVectorOp - Given two vector constants and a function pointer, apply the /// function pointer to each element pair, producing a new ConstantVector -/// constant. +/// constant. Either or both of V1 and V2 may be NULL, meaning a +/// ConstantAggregateZero operand. static Constant *EvalVectorOp(const ConstantVector *V1, const ConstantVector *V2, + const VectorType *VTy, Constant *(*FP)(Constant*, Constant*)) { std::vector Res; - for (unsigned i = 0, e = V1->getNumOperands(); i != e; ++i) - Res.push_back(FP(const_cast(V1->getOperand(i)), - const_cast(V2->getOperand(i)))); + const Type *EltTy = VTy->getElementType(); + for (unsigned i = 0, e = VTy->getNumElements(); i != e; ++i) { + const Constant *C1 = V1 ? V1->getOperand(i) : Constant::getNullValue(EltTy); + const Constant *C2 = V2 ? V2->getOperand(i) : Constant::getNullValue(EltTy); + Res.push_back(FP(const_cast(C1), + const_cast(C2))); + } return ConstantVector::get(Res); } @@ -707,36 +713,40 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode, return ConstantFP::get(CFP1->getType(), C3V); } } - } else if (const ConstantVector *CP1 = dyn_cast(C1)) { - if (const ConstantVector *CP2 = dyn_cast(C2)) { + } else if (const VectorType *VTy = dyn_cast(C1->getType())) { + const ConstantVector *CP1 = dyn_cast(C1); + const ConstantVector *CP2 = dyn_cast(C2); + assert((CP1 != NULL || isa(C1)) && + "Unexpected kind of vector constant!"); + assert((CP2 != NULL || isa(C2)) && + "Unexpected kind of vector constant!"); switch (Opcode) { default: break; case Instruction::Add: - return EvalVectorOp(CP1, CP2, ConstantExpr::getAdd); + return EvalVectorOp(CP1, CP2, VTy, ConstantExpr::getAdd); case Instruction::Sub: - return EvalVectorOp(CP1, CP2, ConstantExpr::getSub); + return EvalVectorOp(CP1, CP2, VTy, ConstantExpr::getSub); case Instruction::Mul: - return EvalVectorOp(CP1, CP2, ConstantExpr::getMul); + return EvalVectorOp(CP1, CP2, VTy, ConstantExpr::getMul); case Instruction::UDiv: - return EvalVectorOp(CP1, CP2, ConstantExpr::getUDiv); + return EvalVectorOp(CP1, CP2, VTy, ConstantExpr::getUDiv); case Instruction::SDiv: - return EvalVectorOp(CP1, CP2, ConstantExpr::getSDiv); + return EvalVectorOp(CP1, CP2, VTy, ConstantExpr::getSDiv); case Instruction::FDiv: - return EvalVectorOp(CP1, CP2, ConstantExpr::getFDiv); + return EvalVectorOp(CP1, CP2, VTy, ConstantExpr::getFDiv); case Instruction::URem: - return EvalVectorOp(CP1, CP2, ConstantExpr::getURem); + return EvalVectorOp(CP1, CP2, VTy, ConstantExpr::getURem); case Instruction::SRem: - return EvalVectorOp(CP1, CP2, ConstantExpr::getSRem); + return EvalVectorOp(CP1, CP2, VTy, ConstantExpr::getSRem); case Instruction::FRem: - return EvalVectorOp(CP1, CP2, ConstantExpr::getFRem); + return EvalVectorOp(CP1, CP2, VTy, ConstantExpr::getFRem); case Instruction::And: - return EvalVectorOp(CP1, CP2, ConstantExpr::getAnd); + return EvalVectorOp(CP1, CP2, VTy, ConstantExpr::getAnd); case Instruction::Or: - return EvalVectorOp(CP1, CP2, ConstantExpr::getOr); + return EvalVectorOp(CP1, CP2, VTy, ConstantExpr::getOr); case Instruction::Xor: - return EvalVectorOp(CP1, CP2, ConstantExpr::getXor); - } + return EvalVectorOp(CP1, CP2, VTy, ConstantExpr::getXor); } } diff --git a/llvm/test/Transforms/InstCombine/fold-vector-zero.ll b/llvm/test/Transforms/InstCombine/fold-vector-zero.ll new file mode 100644 index 000000000000..0b5b30a5c6e7 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/fold-vector-zero.ll @@ -0,0 +1,35 @@ +; RUN: llvm-as < %s | opt -instcombine | llvm-dis | not grep zeroinitializer + +define void @foo(i64 %A, i64 %B) { +bb8: + br label %bb30 + +bb30: + %s0 = phi i64 [ 0, %bb8 ], [ %r21, %bb30 ] + %l0 = phi i64 [ -2222, %bb8 ], [ %r23, %bb30 ] + %r2 = add i64 %s0, %B + %r3 = inttoptr i64 %r2 to <2 x double>* + %r4 = load <2 x double>* %r3, align 8 + %r6 = bitcast <2 x double> %r4 to <2 x i64> + %r7 = bitcast <2 x double> zeroinitializer to <2 x i64> + %r8 = insertelement <2 x i64> undef, i64 9223372036854775807, i32 0 + %r9 = insertelement <2 x i64> undef, i64 -9223372036854775808, i32 0 + %r10 = insertelement <2 x i64> %r8, i64 9223372036854775807, i32 1 + %r11 = insertelement <2 x i64> %r9, i64 -9223372036854775808, i32 1 + %r12 = and <2 x i64> %r6, %r10 + %r13 = and <2 x i64> %r7, %r11 + %r14 = or <2 x i64> %r12, %r13 + %r15 = bitcast <2 x i64> %r14 to <2 x double> + %r18 = add i64 %s0, %A + %r19 = inttoptr i64 %r18 to <2 x double>* + store <2 x double> %r15, <2 x double>* %r19, align 8 + %r21 = add i64 16, %s0 + %r23 = add i64 1, %l0 + %r25 = icmp slt i64 %r23, 0 + %r26 = zext i1 %r25 to i64 + %r27 = icmp ne i64 %r26, 0 + br i1 %r27, label %bb30, label %bb5 + +bb5: + ret void +}