diff -wu include/llvm/Support/ConstantFolder.h include/llvm/Support/ConstantFolder.h --- include/llvm/Support/ConstantFolder.h (working copy) +++ include/llvm/Support/ConstantFolder.h (working copy) @@ -79,146 +79,14 @@ Constant *LHS, Constant *RHS) const { return ConstantExpr::get(Opc, LHS, RHS); } + /// Try to find an instruction identical to this one in the current BB, /// and return it. - Value *findBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, - Value *LRHS, const BasicBlock *BB) const - { - unsigned maxUses = 8; // Maximum number of uses to inspect - // Loop over all uses of operand to find an identical binop, with - // same operands. - for (Value::use_iterator i = LRHS->use_begin(), e = LRHS->use_end(); - i != e && maxUses; ++i, --maxUses) { - Instruction *UI = dyn_cast(i); - if (!UI || UI->getOpcode() != static_cast(Opc) || - UI->getNumOperands() != 2) - continue; - Value *iLHS = UI->getOperand(0); - Value *iRHS = UI->getOperand(1); - if (iLHS != LHS || iRHS != RHS) { - if (Instruction::isCommutative(Opc)) { - if (iLHS != RHS || iRHS != LHS) - continue; - } else - continue; - } - // Only accept instructions in same BB. - // Caller will need to ensure it doesn't move the insertion point - // backwards. - if (UI->getParent() == BB) - return UI; - } - return 0; - } + Value *FindBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, + Value *LRHS, const BasicBlock *BB) const; Value *SimplifyBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, - Constant *LC, Constant *RC, const BasicBlock *BB) const { - - // Can only simplify if one of the operands is a constant. - if (!(LC || RC)) - return 0; - - ConstantInt *CLHS = dyn_cast_or_null(LC), - *CRHS = dyn_cast_or_null(RC); - if (!(CLHS || CRHS)) - return 0; - - if (Instruction::isCommutative(Opc)) { - ConstantInt *C = CLHS ? CLHS : CRHS; - Value *V = CLHS ? RHS : LHS; - - assert(C && V && "Values cannot be NULL"); - - switch (Opc) { - case Instruction::Add: - // add 0, X; add X, 0 -> X - if (C->isZero()) - return V; - break; - case Instruction::Mul: - // mul 0, X; mul X, 0 -> 0 - if (C->isZero()) - return V; - break; - case Instruction::And: - // and 0, X; and X, 0 -> 0 - if (C->isZero()) - return C; - // and X, ~0; and ~0, X -> X - if (C->isAllOnesValue()) - return V; - break; - case Instruction::Or: - // or 0, X; or X, 0 -> 0 - if (C->isZero()) - return V; - // or ~0, X; or X, ~0 -> ~0 - if (C->isAllOnesValue()) - return C; - break; - case Instruction::Xor: - // xor 0, X; xor X, 0 -> X - if (C->isZero()) - return V; - // Simplify repeated xoring with same constant - // A^C^C -> A - // This can happen due to repeated negation: - // !!A -> A - if (const BinaryOperator *BO = dyn_cast(V)) { - if (ConstantInt *CI = dyn_cast(BO->getOperand(1))) - if (CI == C) - return BO->getOperand(0); - if (ConstantInt *CI = dyn_cast(BO->getOperand(0))) - if (CI == C) - return BO->getOperand(1); - } - break; - default: - break; - } - } else { - switch (Opc) { - case Instruction::Sub: - // sub X, 0 -> X - if (CRHS && CRHS->isZero()) - return CRHS; - break; - case Instruction::UDiv: - case Instruction::SDiv: - // udiv/sdiv 0, X -> 0 - // This also transforms udiv 0, 0 (undefined behaviour) -> 0. - if (CLHS && CLHS->isZero()) - return CLHS; - // udiv/sdiv X, 1 -> X - if (CRHS && CRHS->isOne()) - return LHS; - // Don't simplify udiv X, 0 at this point, because it could be used - // to knowingly generate a SIGFPE. - break; - case Instruction::URem: - case Instruction::SRem: - // urem/srem X, 1 -> 0 - if (CRHS && CRHS->isOne()) - return CRHS->getNullValue(CRHS->getType()); - break; - case Instruction::Shl: - case Instruction::LShr: - case Instruction::AShr: - // shl/lshr/ashr X, 0 -> X - if (CRHS && CRHS->isZero()) - return LHS; - break; - default: - break; - } - } - - if (BB) - // We'll iterate on uses of LHS/RHS to find an identical instruction. - // Choose the non-constant one (constant one may have too many uses). - return findBinOp(Opc, LHS, RHS, LC ? RHS : LHS, BB); - return 0; - } + Constant *LC, Constant *RC, const BasicBlock *BB) const; /// Attempts to simplify the BinOp if one of the operands is a constant. /// If it can't simplify it, NULL is returned. @@ -236,7 +104,6 @@ return SimplifyBinOp(Opc, LHS, RHS, LC, RC, BB); } - //===--------------------------------------------------------------------===// // Unary Operators //===--------------------------------------------------------------------===// @@ -247,33 +114,6 @@ Constant *CreateNot(Constant *C) const { return ConstantExpr::getNot(C); } - Value *CreateNeg(Value *V, const BasicBlock *BB) const { - if (Constant *C = dyn_cast(V)) - return ConstantExpr::getNeg(C); - if (BB) { - Value *zero = ConstantExpr::getZeroValueForNegationExpr(V->getType()); - if (Value *R = findBinOp(Instruction::Sub, zero, V, V, BB)) - return R; - } - return 0; - } - - Value *CreateNot(Value *V, const BasicBlock *BB) const { - if (Constant *C = dyn_cast(V)) - return ConstantExpr::getNot(C); - if (BB) { - Constant *C; - if (const VectorType *PTy = dyn_cast(V->getType())) { - C = ConstantInt::getAllOnesValue(PTy->getElementType()); - C = ConstantVector::get(std::vector(PTy->getNumElements(), C)); - } else { - C = ConstantInt::getAllOnesValue(V->getType()); - } - if (Value *R = findBinOp(Instruction::Xor, V, C, V, BB)) - return R; - } - return 0; - } //===--------------------------------------------------------------------===// // Memory Instructions diff -wu include/llvm/Support/IRBuilder.h include/llvm/Support/IRBuilder.h --- include/llvm/Support/IRBuilder.h (working copy) +++ include/llvm/Support/IRBuilder.h (working copy) @@ -49,8 +49,7 @@ // Returns the BB in which to search for an instruction to reuse, // or NULL if this is not desired. - const BasicBlock *getReuse() const - { + const BasicBlock *getReuse() const { return reuseOps && (InsertPt == BB->end()) ? BB : 0; } public: @@ -259,13 +258,30 @@ } Value *CreateNeg(Value *V, const char *Name = "") { - if (Value *R = Folder.CreateNeg( V, getReuse())) + if (Constant *VC = dyn_cast(V)) + return Folder.CreateNeg(VC); + if (const BasicBlock *BB = getReuse()) { + Value *zero = ConstantExpr::getZeroValueForNegationExpr(V->getType()); + if (Value *R = Folder.FindBinOp(Instruction::Sub, zero, V, V, BB)) return R; + } return Insert(BinaryOperator::CreateNeg(V), Name); } Value *CreateNot(Value *V, const char *Name = "") { - if (Value *R = Folder.CreateNot(V, getReuse())) + if (Constant *VC = dyn_cast(V)) + return Folder.CreateNot(VC); + if (const BasicBlock *BB = getReuse()) { + Constant *C; + if (const VectorType *PTy = dyn_cast(V->getType())) { + C = ConstantInt::getAllOnesValue(PTy->getElementType()); + C = ConstantVector::get(std::vector(PTy->getNumElements(), + C)); + } else { + C = ConstantInt::getAllOnesValue(V->getType()); + } + if (Value *R = Folder.FindBinOp(Instruction::Xor, V, C, V, BB)) return R; + } return Insert(BinaryOperator::CreateNot(V), Name); } diff -wu include/llvm/Support/NoFolder.h include/llvm/Support/NoFolder.h --- include/llvm/Support/NoFolder.h (working copy) +++ include/llvm/Support/NoFolder.h (working copy) @@ -46,12 +46,11 @@ // Unary Operators //===--------------------------------------------------------------------===// - Value *CreateNeg(Constant *C, const BasicBlock *BB) const { - return 0; + Value *CreateNeg(Constant *C) const { + return BinaryOperator::CreateNeg(C); } - - Value *CreateNot(Constant *C, const BasicBlock *BB) const { - return 0; + Value *CreateNot(Constant *C) const { + return BinaryOperator::CreateNot(C); } //===--------------------------------------------------------------------===// diff -wu include/llvm/Support/TargetFolder.h include/llvm/Support/TargetFolder.h --- include/llvm/Support/TargetFolder.h (working copy) +++ include/llvm/Support/TargetFolder.h (working copy) @@ -115,34 +115,6 @@ return Fold(ConstantExpr::getNot(C)); } - Value *CreateNeg(Value *V, const BasicBlock *BB) const { - if (Constant *C = dyn_cast(V)) - return Fold(ConstantExpr::getNeg(C)); - if (BB) { - Value *zero = ConstantExpr::getZeroValueForNegationExpr(V->getType()); - if (Value *R = findBinOp(Instruction::Sub, zero, V, V, BB)) - return R; - } - return 0; - } - - Value *CreateNot(Value *V, const BasicBlock *BB) const { - if (Constant *C = dyn_cast(V)) - return Fold(ConstantExpr::getNot(C)); - if (BB) { - Constant *C; - if (const VectorType *PTy = dyn_cast(V->getType())) { - C = ConstantInt::getAllOnesValue(PTy->getElementType()); - C = ConstantVector::get(std::vector(PTy->getNumElements(), C)); - } else { - C = ConstantInt::getAllOnesValue(V->getType()); - } - if (Value *R = findBinOp(Instruction::Xor, V, C, V, BB)) - return R; - } - return 0; - } - //===--------------------------------------------------------------------===// // Memory Instructions //===--------------------------------------------------------------------===// only in patch2: --- lib/VMCore/ConstantFold.cpp (revision 62460) +++ lib/VMCore/ConstantFold.cpp (working copy) @@ -27,2 +27,3 @@ #include "llvm/ADT/SmallVector.h" +#include "llvm/Support/ConstantFolder.h" #include "llvm/Support/Compiler.h" @@ -1691 +1692,137 @@ +Value *ConstantFolder::FindBinOp(Instruction::BinaryOps Opc, Value *LHS, + Value *RHS, Value *LRHS, + const BasicBlock *BB) const { + unsigned maxUses = 8; // Maximum number of uses to inspect + // Loop over all uses of operand to find an identical binop, with + // same operands. + for (Value::use_iterator i = LRHS->use_begin(), e = LRHS->use_end(); + i != e && maxUses; ++i, --maxUses) { + Instruction *UI = dyn_cast(i); + if (!UI || UI->getOpcode() != static_cast(Opc) || + UI->getNumOperands() != 2) + continue; + Value *iLHS = UI->getOperand(0); + Value *iRHS = UI->getOperand(1); + if (iLHS != LHS || iRHS != RHS) { + if (Instruction::isCommutative(Opc)) { + if (iLHS != RHS || iRHS != LHS) + continue; + } else + continue; + } + // Only accept instructions in same BB. + // Caller will need to ensure it doesn't move the insertion point + // backwards. + if (UI->getParent() == BB) + return UI; + } + return 0; +} + +Value *ConstantFolder::SimplifyBinOp(Instruction::BinaryOps Opc, Value *LHS, + Value *RHS, Constant *LC, Constant *RC, + const BasicBlock *BB) const { + // Can only simplify if one of the operands is a constant. + if (!(LC || RC)) + return 0; + + ConstantInt *CLHS = dyn_cast_or_null(LC), + *CRHS = dyn_cast_or_null(RC); + if (!(CLHS || CRHS)) + return 0; + + if (Instruction::isCommutative(Opc)) { + ConstantInt *C = CLHS ? CLHS : CRHS; + Value *V = CLHS ? RHS : LHS; + + assert(C && V && "Values cannot be NULL"); + + switch (Opc) { + case Instruction::Add: + // add 0, X; add X, 0 -> X + if (C->isZero()) + return V; + break; + case Instruction::Mul: + // mul 0, X; mul X, 0 -> 0 + if (C->isZero()) + return V; + break; + case Instruction::And: + // and 0, X; and X, 0 -> 0 + if (C->isZero()) + return C; + // and X, ~0; and ~0, X -> X + if (C->isAllOnesValue()) + return V; + break; + case Instruction::Or: + // or 0, X; or X, 0 -> 0 + if (C->isZero()) + return V; + // or ~0, X; or X, ~0 -> ~0 + if (C->isAllOnesValue()) + return C; + break; + case Instruction::Xor: + // xor 0, X; xor X, 0 -> X + if (C->isZero()) + return V; + // Simplify repeated xoring with same constant + // A^C^C -> A + // This can happen due to repeated negation: + // !!A -> A + if (const BinaryOperator *BO = dyn_cast(V)) { + if (ConstantInt *CI = dyn_cast(BO->getOperand(1))) + if (CI == C) + return BO->getOperand(0); + if (ConstantInt *CI = dyn_cast(BO->getOperand(0))) + if (CI == C) + return BO->getOperand(1); + } + break; + default: + break; + } + } else { + switch (Opc) { + case Instruction::Sub: + // sub X, 0 -> X + if (CRHS && CRHS->isZero()) + return CRHS; + break; + case Instruction::UDiv: + case Instruction::SDiv: + // udiv/sdiv 0, X -> 0 + // This also transforms udiv 0, 0 (undefined behaviour) -> 0. + if (CLHS && CLHS->isZero()) + return CLHS; + // udiv/sdiv X, 1 -> X + if (CRHS && CRHS->isOne()) + return LHS; + break; + case Instruction::URem: + case Instruction::SRem: + // urem/srem X, 1 -> 0 + if (CRHS && CRHS->isOne()) + return CRHS->getNullValue(CRHS->getType()); + break; + case Instruction::Shl: + case Instruction::LShr: + case Instruction::AShr: + // shl/lshr/ashr X, 0 -> X + if (CRHS && CRHS->isZero()) + return LHS; + break; + default: + break; + } + } + + if (BB) + // We'll iterate on uses of LHS/RHS to find an identical instruction. + // Choose the non-constant one (constant one may have too many uses). + return FindBinOp(Opc, LHS, RHS, LC ? RHS : LHS, BB); + return 0; +}