Index: include/llvm/Analysis/ConstantFolding.h =================================================================== --- include/llvm/Analysis/ConstantFolding.h +++ include/llvm/Analysis/ConstantFolding.h @@ -65,6 +65,12 @@ Constant *RHS, const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr); +/// \brief Attempt to constant fold a binary operation with the specified +/// operands. If it fails, it returns a constant expression of the specified +/// operands. +Constant *ConstantFoldBinaryOpOperands(unsigned Opcode, Constant *LHS, + Constant *RHS, const DataLayout &DL); + /// ConstantFoldInsertValueInstruction - Attempt to constant fold an insertvalue /// instruction with the specified operands and indices. The constant result is /// returned if successful; if not, null is returned. Index: lib/Analysis/ConstantFolding.cpp =================================================================== --- lib/Analysis/ConstantFolding.cpp +++ lib/Analysis/ConstantFolding.cpp @@ -1010,14 +1010,8 @@ const DataLayout &DL, const TargetLibraryInfo *TLI) { // Handle easy binops first. - if (Instruction::isBinaryOp(Opcode)) { - if (isa(Ops[0]) || isa(Ops[1])) { - if (Constant *C = SymbolicallyEvaluateBinop(Opcode, Ops[0], Ops[1], DL)) - return C; - } - - return ConstantExpr::get(Opcode, Ops[0], Ops[1]); - } + if (Instruction::isBinaryOp(Opcode)) + return ConstantFoldBinaryOpOperands(Opcode, Ops[0], Ops[1], DL); switch (Opcode) { default: return nullptr; @@ -1176,14 +1170,23 @@ Predicate, CE0->getOperand(1), Ops1, DL, TLI); unsigned OpC = Predicate == ICmpInst::ICMP_EQ ? Instruction::And : Instruction::Or; - Constant *Ops[] = { LHS, RHS }; - return ConstantFoldInstOperands(OpC, LHS->getType(), Ops, DL, TLI); + return ConstantFoldBinaryOpOperands(OpC, LHS, RHS, DL); } } return ConstantExpr::getCompare(Predicate, Ops0, Ops1); } +Constant *llvm::ConstantFoldBinaryOpOperands(unsigned Opcode, Constant *LHS, + Constant *RHS, const DataLayout &DL) { + assert(Instruction::isBinaryOp(Opcode)); + assert(LHS->getType() == RHS->getType()); + if (isa(LHS) || isa(RHS)) + if (Constant *C = SymbolicallyEvaluateBinop(Opcode, LHS, RHS, DL)) + return C; + + return ConstantExpr::get(Opcode, LHS, RHS); +} /// Given a constant and a getelementptr constantexpr, return the constant value /// being addressed by the constant expression, or null if something is funny Index: lib/Analysis/InstructionSimplify.cpp =================================================================== --- lib/Analysis/InstructionSimplify.cpp +++ lib/Analysis/InstructionSimplify.cpp @@ -528,11 +528,8 @@ static Value *SimplifyAddInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW, const Query &Q, unsigned MaxRecurse) { if (Constant *CLHS = dyn_cast(Op0)) { - if (Constant *CRHS = dyn_cast(Op1)) { - Constant *Ops[] = { CLHS, CRHS }; - return ConstantFoldInstOperands(Instruction::Add, CLHS->getType(), Ops, - Q.DL, Q.TLI); - } + if (Constant *CRHS = dyn_cast(Op1)) + return ConstantFoldBinaryOpOperands(Instruction::Add, CLHS, CRHS, Q.DL); // Canonicalize the constant to the RHS. std::swap(Op0, Op1); @@ -660,11 +657,8 @@ static Value *SimplifySubInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW, const Query &Q, unsigned MaxRecurse) { if (Constant *CLHS = dyn_cast(Op0)) - if (Constant *CRHS = dyn_cast(Op1)) { - Constant *Ops[] = { CLHS, CRHS }; - return ConstantFoldInstOperands(Instruction::Sub, CLHS->getType(), - Ops, Q.DL, Q.TLI); - } + if (Constant *CRHS = dyn_cast(Op1)) + return ConstantFoldBinaryOpOperands(Instruction::Sub, CLHS, CRHS, Q.DL); // X - undef -> undef // undef - X -> undef @@ -787,11 +781,8 @@ static Value *SimplifyFAddInst(Value *Op0, Value *Op1, FastMathFlags FMF, const Query &Q, unsigned MaxRecurse) { if (Constant *CLHS = dyn_cast(Op0)) { - if (Constant *CRHS = dyn_cast(Op1)) { - Constant *Ops[] = { CLHS, CRHS }; - return ConstantFoldInstOperands(Instruction::FAdd, CLHS->getType(), - Ops, Q.DL, Q.TLI); - } + if (Constant *CRHS = dyn_cast(Op1)) + return ConstantFoldBinaryOpOperands(Instruction::FAdd, CLHS, CRHS, Q.DL); // Canonicalize the constant to the RHS. std::swap(Op0, Op1); @@ -829,11 +820,8 @@ static Value *SimplifyFSubInst(Value *Op0, Value *Op1, FastMathFlags FMF, const Query &Q, unsigned MaxRecurse) { if (Constant *CLHS = dyn_cast(Op0)) { - if (Constant *CRHS = dyn_cast(Op1)) { - Constant *Ops[] = { CLHS, CRHS }; - return ConstantFoldInstOperands(Instruction::FSub, CLHS->getType(), - Ops, Q.DL, Q.TLI); - } + if (Constant *CRHS = dyn_cast(Op1)) + return ConstantFoldBinaryOpOperands(Instruction::FSub, CLHS, CRHS, Q.DL); } // fsub X, 0 ==> X @@ -867,11 +855,8 @@ const Query &Q, unsigned MaxRecurse) { if (Constant *CLHS = dyn_cast(Op0)) { - if (Constant *CRHS = dyn_cast(Op1)) { - Constant *Ops[] = { CLHS, CRHS }; - return ConstantFoldInstOperands(Instruction::FMul, CLHS->getType(), - Ops, Q.DL, Q.TLI); - } + if (Constant *CRHS = dyn_cast(Op1)) + return ConstantFoldBinaryOpOperands(Instruction::FMul, CLHS, CRHS, Q.DL); // Canonicalize the constant to the RHS. std::swap(Op0, Op1); @@ -893,11 +878,8 @@ static Value *SimplifyMulInst(Value *Op0, Value *Op1, const Query &Q, unsigned MaxRecurse) { if (Constant *CLHS = dyn_cast(Op0)) { - if (Constant *CRHS = dyn_cast(Op1)) { - Constant *Ops[] = { CLHS, CRHS }; - return ConstantFoldInstOperands(Instruction::Mul, CLHS->getType(), - Ops, Q.DL, Q.TLI); - } + if (Constant *CRHS = dyn_cast(Op1)) + return ConstantFoldBinaryOpOperands(Instruction::Mul, CLHS, CRHS, Q.DL); // Canonicalize the constant to the RHS. std::swap(Op0, Op1); @@ -992,12 +974,9 @@ /// If not, this returns null. static Value *SimplifyDiv(Instruction::BinaryOps Opcode, Value *Op0, Value *Op1, const Query &Q, unsigned MaxRecurse) { - if (Constant *C0 = dyn_cast(Op0)) { - if (Constant *C1 = dyn_cast(Op1)) { - Constant *Ops[] = { C0, C1 }; - return ConstantFoldInstOperands(Opcode, C0->getType(), Ops, Q.DL, Q.TLI); - } - } + if (Constant *C0 = dyn_cast(Op0)) + if (Constant *C1 = dyn_cast(Op1)) + return ConstantFoldBinaryOpOperands(Opcode, C0, C1, Q.DL); bool isSigned = Opcode == Instruction::SDiv; @@ -1157,12 +1136,9 @@ /// If not, this returns null. static Value *SimplifyRem(Instruction::BinaryOps Opcode, Value *Op0, Value *Op1, const Query &Q, unsigned MaxRecurse) { - if (Constant *C0 = dyn_cast(Op0)) { - if (Constant *C1 = dyn_cast(Op1)) { - Constant *Ops[] = { C0, C1 }; - return ConstantFoldInstOperands(Opcode, C0->getType(), Ops, Q.DL, Q.TLI); - } - } + if (Constant *C0 = dyn_cast(Op0)) + if (Constant *C1 = dyn_cast(Op1)) + return ConstantFoldBinaryOpOperands(Opcode, C0, C1, Q.DL); // X % undef -> undef if (match(Op1, m_Undef())) @@ -1309,12 +1285,9 @@ /// If not, this returns null. static Value *SimplifyShift(unsigned Opcode, Value *Op0, Value *Op1, const Query &Q, unsigned MaxRecurse) { - if (Constant *C0 = dyn_cast(Op0)) { - if (Constant *C1 = dyn_cast(Op1)) { - Constant *Ops[] = { C0, C1 }; - return ConstantFoldInstOperands(Opcode, C0->getType(), Ops, Q.DL, Q.TLI); - } - } + if (Constant *C0 = dyn_cast(Op0)) + if (Constant *C1 = dyn_cast(Op1)) + return ConstantFoldBinaryOpOperands(Opcode, C0, C1, Q.DL); // 0 shift by X -> 0 if (match(Op0, m_Zero())) @@ -1558,11 +1531,8 @@ static Value *SimplifyAndInst(Value *Op0, Value *Op1, const Query &Q, unsigned MaxRecurse) { if (Constant *CLHS = dyn_cast(Op0)) { - if (Constant *CRHS = dyn_cast(Op1)) { - Constant *Ops[] = { CLHS, CRHS }; - return ConstantFoldInstOperands(Instruction::And, CLHS->getType(), - Ops, Q.DL, Q.TLI); - } + if (Constant *CRHS = dyn_cast(Op1)) + return ConstantFoldBinaryOpOperands(Instruction::And, CLHS, CRHS, Q.DL); // Canonicalize the constant to the RHS. std::swap(Op0, Op1); @@ -1717,11 +1687,8 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const Query &Q, unsigned MaxRecurse) { if (Constant *CLHS = dyn_cast(Op0)) { - if (Constant *CRHS = dyn_cast(Op1)) { - Constant *Ops[] = { CLHS, CRHS }; - return ConstantFoldInstOperands(Instruction::Or, CLHS->getType(), - Ops, Q.DL, Q.TLI); - } + if (Constant *CRHS = dyn_cast(Op1)) + return ConstantFoldBinaryOpOperands(Instruction::Or, CLHS, CRHS, Q.DL); // Canonicalize the constant to the RHS. std::swap(Op0, Op1); @@ -1853,11 +1820,8 @@ static Value *SimplifyXorInst(Value *Op0, Value *Op1, const Query &Q, unsigned MaxRecurse) { if (Constant *CLHS = dyn_cast(Op0)) { - if (Constant *CRHS = dyn_cast(Op1)) { - Constant *Ops[] = { CLHS, CRHS }; - return ConstantFoldInstOperands(Instruction::Xor, CLHS->getType(), - Ops, Q.DL, Q.TLI); - } + if (Constant *CRHS = dyn_cast(Op1)) + return ConstantFoldBinaryOpOperands(Instruction::Xor, CLHS, CRHS, Q.DL); // Canonicalize the constant to the RHS. std::swap(Op0, Op1); @@ -3730,11 +3694,8 @@ case Instruction::Xor: return SimplifyXorInst(LHS, RHS, Q, MaxRecurse); default: if (Constant *CLHS = dyn_cast(LHS)) - if (Constant *CRHS = dyn_cast(RHS)) { - Constant *COps[] = {CLHS, CRHS}; - return ConstantFoldInstOperands(Opcode, LHS->getType(), COps, Q.DL, - Q.TLI); - } + if (Constant *CRHS = dyn_cast(RHS)) + return ConstantFoldBinaryOpOperands(Opcode, CLHS, CRHS, Q.DL); // If the operation is associative, try some generic simplifications. if (Instruction::isAssociative(Opcode))