diff options
Diffstat (limited to 'lib/Transforms/InstCombine/InstCombineAddSub.cpp')
-rw-r--r-- | lib/Transforms/InstCombine/InstCombineAddSub.cpp | 320 |
1 files changed, 160 insertions, 160 deletions
diff --git a/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/lib/Transforms/InstCombine/InstCombineAddSub.cpp index 809471cfd74f..688897644848 100644 --- a/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -12,12 +12,26 @@ //===----------------------------------------------------------------------===// #include "InstCombineInternal.h" +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/APInt.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/Analysis/InstructionSimplify.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/GetElementPtrTypeIterator.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/IR/Constant.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/InstrTypes.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Operator.h" #include "llvm/IR/PatternMatch.h" +#include "llvm/IR/Type.h" +#include "llvm/IR/Value.h" +#include "llvm/Support/AlignOf.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/KnownBits.h" +#include <cassert> +#include <utility> using namespace llvm; using namespace PatternMatch; @@ -39,10 +53,15 @@ namespace { // is expensive. In order to avoid the cost of the constructor, we should // reuse some instances whenever possible. The pre-created instances // FAddCombine::Add[0-5] embodies this idea. - // - FAddendCoef() : IsFp(false), BufHasFpVal(false), IntVal(0) {} + FAddendCoef() = default; ~FAddendCoef(); + // If possible, don't define operator+/operator- etc because these + // operators inevitably call FAddendCoef's constructor which is not cheap. + void operator=(const FAddendCoef &A); + void operator+=(const FAddendCoef &A); + void operator*=(const FAddendCoef &S); + void set(short C) { assert(!insaneIntVal(C) && "Insane coefficient"); IsFp = false; IntVal = C; @@ -55,12 +74,6 @@ namespace { bool isZero() const { return isInt() ? !IntVal : getFpVal().isZero(); } Value *getValue(Type *) const; - // If possible, don't define operator+/operator- etc because these - // operators inevitably call FAddendCoef's constructor which is not cheap. - void operator=(const FAddendCoef &A); - void operator+=(const FAddendCoef &A); - void operator*=(const FAddendCoef &S); - bool isOne() const { return isInt() && IntVal == 1; } bool isTwo() const { return isInt() && IntVal == 2; } bool isMinusOne() const { return isInt() && IntVal == -1; } @@ -68,10 +81,12 @@ namespace { private: bool insaneIntVal(int V) { return V > 4 || V < -4; } + APFloat *getFpValPtr() - { return reinterpret_cast<APFloat*>(&FpValBuf.buffer[0]); } + { return reinterpret_cast<APFloat *>(&FpValBuf.buffer[0]); } + const APFloat *getFpValPtr() const - { return reinterpret_cast<const APFloat*>(&FpValBuf.buffer[0]); } + { return reinterpret_cast<const APFloat *>(&FpValBuf.buffer[0]); } const APFloat &getFpVal() const { assert(IsFp && BufHasFpVal && "Incorret state"); @@ -94,17 +109,16 @@ namespace { // from an *SIGNED* integer. APFloat createAPFloatFromInt(const fltSemantics &Sem, int Val); - private: - bool IsFp; + bool IsFp = false; // True iff FpValBuf contains an instance of APFloat. - bool BufHasFpVal; + bool BufHasFpVal = false; // The integer coefficient of an individual addend is either 1 or -1, // and we try to simplify at most 4 addends from neighboring at most // two instructions. So the range of <IntVal> falls in [-4, 4]. APInt // is overkill of this end. - short IntVal; + short IntVal = 0; AlignedCharArrayUnion<APFloat> FpValBuf; }; @@ -112,10 +126,14 @@ namespace { /// FAddend is used to represent floating-point addend. An addend is /// represented as <C, V>, where the V is a symbolic value, and C is a /// constant coefficient. A constant addend is represented as <C, 0>. - /// class FAddend { public: - FAddend() : Val(nullptr) {} + FAddend() = default; + + void operator+=(const FAddend &T) { + assert((Val == T.Val) && "Symbolic-values disagree"); + Coeff += T.Coeff; + } Value *getSymVal() const { return Val; } const FAddendCoef &getCoef() const { return Coeff; } @@ -146,16 +164,11 @@ namespace { /// splitted is the addend itself. unsigned drillAddendDownOneStep(FAddend &Addend0, FAddend &Addend1) const; - void operator+=(const FAddend &T) { - assert((Val == T.Val) && "Symbolic-values disagree"); - Coeff += T.Coeff; - } - private: void Scale(const FAddendCoef& ScaleAmt) { Coeff *= ScaleAmt; } // This addend has the value of "Coeff * Val". - Value *Val; + Value *Val = nullptr; FAddendCoef Coeff; }; @@ -164,11 +177,12 @@ namespace { /// class FAddCombine { public: - FAddCombine(InstCombiner::BuilderTy &B) : Builder(B), Instr(nullptr) {} + FAddCombine(InstCombiner::BuilderTy &B) : Builder(B) {} + Value *simplify(Instruction *FAdd); private: - typedef SmallVector<const FAddend*, 4> AddendVect; + using AddendVect = SmallVector<const FAddend *, 4>; Value *simplifyFAdd(AddendVect& V, unsigned InstrQuota); @@ -179,6 +193,7 @@ namespace { /// Return the number of instructions needed to emit the N-ary addition. unsigned calcInstrNumber(const AddendVect& Vect); + Value *createFSub(Value *Opnd0, Value *Opnd1); Value *createFAdd(Value *Opnd0, Value *Opnd1); Value *createFMul(Value *Opnd0, Value *Opnd1); @@ -187,9 +202,6 @@ namespace { Value *createNaryFAdd(const AddendVect& Opnds, unsigned InstrQuota); void createInstPostProc(Instruction *NewInst, bool NoNumber = false); - InstCombiner::BuilderTy &Builder; - Instruction *Instr; - // Debugging stuff are clustered here. #ifndef NDEBUG unsigned CreateInstrNum; @@ -199,9 +211,12 @@ namespace { void initCreateInstNum() {} void incCreateInstNum() {} #endif + + InstCombiner::BuilderTy &Builder; + Instruction *Instr = nullptr; }; -} // anonymous namespace +} // end anonymous namespace //===----------------------------------------------------------------------===// // @@ -332,7 +347,6 @@ Value *FAddendCoef::getValue(Type *Ty) const { // 0 +/- 0 <0, NULL> (corner case) // // Legend: A and B are not constant, C is constant -// unsigned FAddend::drillValueDownOneStep (Value *Val, FAddend &Addend0, FAddend &Addend1) { Instruction *I = nullptr; @@ -396,7 +410,6 @@ unsigned FAddend::drillValueDownOneStep // Try to break *this* addend into two addends. e.g. Suppose this addend is // <2.3, V>, and V = X + Y, by calling this function, we obtain two addends, // i.e. <2.3, X> and <2.3, Y>. -// unsigned FAddend::drillAddendDownOneStep (FAddend &Addend0, FAddend &Addend1) const { if (isConstant()) @@ -421,7 +434,6 @@ unsigned FAddend::drillAddendDownOneStep // ------------------------------------------------------- // (x * y) +/- (x * z) x * (y +/- z) // (y / x) +/- (z / x) (y +/- z) / x -// Value *FAddCombine::performFactorization(Instruction *I) { assert((I->getOpcode() == Instruction::FAdd || I->getOpcode() == Instruction::FSub) && "Expect add/sub"); @@ -447,7 +459,6 @@ Value *FAddCombine::performFactorization(Instruction *I) { // ---------------------------------------------- // (x*y) +/- (x*z) x y z // (y/x) +/- (z/x) x y z - // Value *Factor = nullptr; Value *AddSub0 = nullptr, *AddSub1 = nullptr; @@ -471,7 +482,7 @@ Value *FAddCombine::performFactorization(Instruction *I) { return nullptr; FastMathFlags Flags; - Flags.setUnsafeAlgebra(); + Flags.setFast(); if (I0) Flags &= I->getFastMathFlags(); if (I1) Flags &= I->getFastMathFlags(); @@ -500,7 +511,7 @@ Value *FAddCombine::performFactorization(Instruction *I) { } Value *FAddCombine::simplify(Instruction *I) { - assert(I->hasUnsafeAlgebra() && "Should be in unsafe mode"); + assert(I->isFast() && "Expected 'fast' instruction"); // Currently we are not able to handle vector type. if (I->getType()->isVectorTy()) @@ -599,7 +610,6 @@ Value *FAddCombine::simplifyFAdd(AddendVect& Addends, unsigned InstrQuota) { // desirable to reside at the top of the resulting expression tree. Placing // constant close to supper-expr(s) will potentially reveal some optimization // opportunities in super-expr(s). - // const FAddend *ConstAdd = nullptr; // Simplified addends are placed <SimpVect>. @@ -608,7 +618,6 @@ Value *FAddCombine::simplifyFAdd(AddendVect& Addends, unsigned InstrQuota) { // The outer loop works on one symbolic-value at a time. Suppose the input // addends are : <a1, x>, <b1, y>, <a2, x>, <c1, z>, <b2, y>, ... // The symbolic-values will be processed in this order: x, y, z. - // for (unsigned SymIdx = 0; SymIdx < AddendNum; SymIdx++) { const FAddend *ThisAddend = Addends[SymIdx]; @@ -626,7 +635,6 @@ Value *FAddCombine::simplifyFAdd(AddendVect& Addends, unsigned InstrQuota) { // example, if the symbolic value "y" is being processed, the inner loop // will collect two addends "<b1,y>" and "<b2,Y>". These two addends will // be later on folded into "<b1+b2, y>". - // for (unsigned SameSymIdx = SymIdx + 1; SameSymIdx < AddendNum; SameSymIdx++) { const FAddend *T = Addends[SameSymIdx]; @@ -681,7 +689,7 @@ Value *FAddCombine::createNaryFAdd assert(!Opnds.empty() && "Expect at least one addend"); // Step 1: Check if the # of instructions needed exceeds the quota. - // + unsigned InstrNeeded = calcInstrNumber(Opnds); if (InstrNeeded > InstrQuota) return nullptr; @@ -726,10 +734,10 @@ Value *FAddCombine::createNaryFAdd LastVal = createFNeg(LastVal); } - #ifndef NDEBUG - assert(CreateInstrNum == InstrNeeded && - "Inconsistent in instruction numbers"); - #endif +#ifndef NDEBUG + assert(CreateInstrNum == InstrNeeded && + "Inconsistent in instruction numbers"); +#endif return LastVal; } @@ -950,9 +958,25 @@ static Value *checkForNegativeOperand(BinaryOperator &I, return nullptr; } -static Instruction *foldAddWithConstant(BinaryOperator &Add, - InstCombiner::BuilderTy &Builder) { +Instruction *InstCombiner::foldAddWithConstant(BinaryOperator &Add) { Value *Op0 = Add.getOperand(0), *Op1 = Add.getOperand(1); + Constant *Op1C; + if (!match(Op1, m_Constant(Op1C))) + return nullptr; + + if (Instruction *NV = foldOpWithConstantIntoOperand(Add)) + return NV; + + Value *X; + // zext(bool) + C -> bool ? C + 1 : C + if (match(Op0, m_ZExt(m_Value(X))) && + X->getType()->getScalarSizeInBits() == 1) + return SelectInst::Create(X, AddOne(Op1C), Op1); + + // ~X + C --> (C-1) - X + if (match(Op0, m_Not(m_Value(X)))) + return BinaryOperator::CreateSub(SubOne(Op1C), X); + const APInt *C; if (!match(Op1, m_APInt(C))) return nullptr; @@ -968,21 +992,17 @@ static Instruction *foldAddWithConstant(BinaryOperator &Add, return BinaryOperator::CreateXor(Op0, Op1); } - Value *X; - const APInt *C2; - Type *Ty = Add.getType(); - // Is this add the last step in a convoluted sext? // add(zext(xor i16 X, -32768), -32768) --> sext X + Type *Ty = Add.getType(); + const APInt *C2; if (match(Op0, m_ZExt(m_Xor(m_Value(X), m_APInt(C2)))) && C2->isMinSignedValue() && C2->sext(Ty->getScalarSizeInBits()) == *C) return CastInst::Create(Instruction::SExt, X, Ty); // (add (zext (add nuw X, C2)), C) --> (zext (add nuw X, C2 + C)) - // FIXME: This should check hasOneUse to not increase the instruction count? - if (C->isNegative() && - match(Op0, m_ZExt(m_NUWAdd(m_Value(X), m_APInt(C2)))) && - C->sge(-C2->sext(C->getBitWidth()))) { + if (match(Op0, m_OneUse(m_ZExt(m_NUWAdd(m_Value(X), m_APInt(C2))))) && + C->isNegative() && C->sge(-C2->sext(C->getBitWidth()))) { Constant *NewC = ConstantInt::get(X->getType(), *C2 + C->trunc(C2->getBitWidth())); return new ZExtInst(Builder.CreateNUWAdd(X, NewC), Ty); @@ -1013,34 +1033,29 @@ static Instruction *foldAddWithConstant(BinaryOperator &Add, Instruction *InstCombiner::visitAdd(BinaryOperator &I) { bool Changed = SimplifyAssociativeOrCommutative(I); - Value *LHS = I.getOperand(0), *RHS = I.getOperand(1); - if (Value *V = SimplifyVectorOp(I)) return replaceInstUsesWith(I, V); + Value *LHS = I.getOperand(0), *RHS = I.getOperand(1); if (Value *V = SimplifyAddInst(LHS, RHS, I.hasNoSignedWrap(), I.hasNoUnsignedWrap(), SQ.getWithInstruction(&I))) return replaceInstUsesWith(I, V); - // (A*B)+(A*C) -> A*(B+C) etc + // (A*B)+(A*C) -> A*(B+C) etc if (Value *V = SimplifyUsingDistributiveLaws(I)) return replaceInstUsesWith(I, V); - if (Instruction *X = foldAddWithConstant(I, Builder)) + if (Instruction *X = foldAddWithConstant(I)) return X; // FIXME: This should be moved into the above helper function to allow these - // transforms for splat vectors. + // transforms for general constant or constant splat vectors. + Type *Ty = I.getType(); if (ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) { - // zext(bool) + C -> bool ? C + 1 : C - if (ZExtInst *ZI = dyn_cast<ZExtInst>(LHS)) - if (ZI->getSrcTy()->isIntegerTy(1)) - return SelectInst::Create(ZI->getOperand(0), AddOne(CI), CI); - Value *XorLHS = nullptr; ConstantInt *XorRHS = nullptr; if (match(LHS, m_Xor(m_Value(XorLHS), m_ConstantInt(XorRHS)))) { - uint32_t TySizeBits = I.getType()->getScalarSizeInBits(); + unsigned TySizeBits = Ty->getScalarSizeInBits(); const APInt &RHSVal = CI->getValue(); unsigned ExtendAmt = 0; // If we have ADD(XOR(AND(X, 0xFF), 0x80), 0xF..F80), it's a sext. @@ -1059,7 +1074,7 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) { } if (ExtendAmt) { - Constant *ShAmt = ConstantInt::get(I.getType(), ExtendAmt); + Constant *ShAmt = ConstantInt::get(Ty, ExtendAmt); Value *NewShl = Builder.CreateShl(XorLHS, ShAmt, "sext"); return BinaryOperator::CreateAShr(NewShl, ShAmt); } @@ -1080,38 +1095,30 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) { } } - if (isa<Constant>(RHS)) - if (Instruction *NV = foldOpWithConstantIntoOperand(I)) - return NV; - - if (I.getType()->isIntOrIntVectorTy(1)) + if (Ty->isIntOrIntVectorTy(1)) return BinaryOperator::CreateXor(LHS, RHS); // X + X --> X << 1 if (LHS == RHS) { - BinaryOperator *New = - BinaryOperator::CreateShl(LHS, ConstantInt::get(I.getType(), 1)); - New->setHasNoSignedWrap(I.hasNoSignedWrap()); - New->setHasNoUnsignedWrap(I.hasNoUnsignedWrap()); - return New; + auto *Shl = BinaryOperator::CreateShl(LHS, ConstantInt::get(Ty, 1)); + Shl->setHasNoSignedWrap(I.hasNoSignedWrap()); + Shl->setHasNoUnsignedWrap(I.hasNoUnsignedWrap()); + return Shl; } - // -A + B --> B - A - // -A + -B --> -(A + B) - if (Value *LHSV = dyn_castNegVal(LHS)) { - if (!isa<Constant>(RHS)) - if (Value *RHSV = dyn_castNegVal(RHS)) { - Value *NewAdd = Builder.CreateAdd(LHSV, RHSV, "sum"); - return BinaryOperator::CreateNeg(NewAdd); - } + Value *A, *B; + if (match(LHS, m_Neg(m_Value(A)))) { + // -A + -B --> -(A + B) + if (match(RHS, m_Neg(m_Value(B)))) + return BinaryOperator::CreateNeg(Builder.CreateAdd(A, B)); - return BinaryOperator::CreateSub(RHS, LHSV); + // -A + B --> B - A + return BinaryOperator::CreateSub(RHS, A); } // A + -B --> A - B - if (!isa<Constant>(RHS)) - if (Value *V = dyn_castNegVal(RHS)) - return BinaryOperator::CreateSub(LHS, V); + if (match(RHS, m_Neg(m_Value(B)))) + return BinaryOperator::CreateSub(LHS, B); if (Value *V = checkForNegativeOperand(I, Builder)) return replaceInstUsesWith(I, V); @@ -1120,12 +1127,6 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) { if (haveNoCommonBitsSet(LHS, RHS, DL, &AC, &I, &DT)) return BinaryOperator::CreateOr(LHS, RHS); - if (Constant *CRHS = dyn_cast<Constant>(RHS)) { - Value *X; - if (match(LHS, m_Not(m_Value(X)))) // ~X + C --> (C-1) - X - return BinaryOperator::CreateSub(SubOne(CRHS), X); - } - // FIXME: We already did a check for ConstantInt RHS above this. // FIXME: Is this pattern covered by another fold? No regression tests fail on // removal. @@ -1187,12 +1188,12 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) { if (LHSConv->hasOneUse()) { Constant *CI = ConstantExpr::getTrunc(RHSC, LHSConv->getOperand(0)->getType()); - if (ConstantExpr::getSExt(CI, I.getType()) == RHSC && + if (ConstantExpr::getSExt(CI, Ty) == RHSC && willNotOverflowSignedAdd(LHSConv->getOperand(0), CI, I)) { // Insert the new, smaller add. Value *NewAdd = Builder.CreateNSWAdd(LHSConv->getOperand(0), CI, "addconv"); - return new SExtInst(NewAdd, I.getType()); + return new SExtInst(NewAdd, Ty); } } } @@ -1210,7 +1211,7 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) { // Insert the new integer add. Value *NewAdd = Builder.CreateNSWAdd(LHSConv->getOperand(0), RHSConv->getOperand(0), "addconv"); - return new SExtInst(NewAdd, I.getType()); + return new SExtInst(NewAdd, Ty); } } } @@ -1223,12 +1224,12 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) { if (LHSConv->hasOneUse()) { Constant *CI = ConstantExpr::getTrunc(RHSC, LHSConv->getOperand(0)->getType()); - if (ConstantExpr::getZExt(CI, I.getType()) == RHSC && + if (ConstantExpr::getZExt(CI, Ty) == RHSC && willNotOverflowUnsignedAdd(LHSConv->getOperand(0), CI, I)) { // Insert the new, smaller add. Value *NewAdd = Builder.CreateNUWAdd(LHSConv->getOperand(0), CI, "addconv"); - return new ZExtInst(NewAdd, I.getType()); + return new ZExtInst(NewAdd, Ty); } } } @@ -1246,41 +1247,35 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) { // Insert the new integer add. Value *NewAdd = Builder.CreateNUWAdd( LHSConv->getOperand(0), RHSConv->getOperand(0), "addconv"); - return new ZExtInst(NewAdd, I.getType()); + return new ZExtInst(NewAdd, Ty); } } } // (add (xor A, B) (and A, B)) --> (or A, B) - { - Value *A = nullptr, *B = nullptr; - if (match(RHS, m_Xor(m_Value(A), m_Value(B))) && - match(LHS, m_c_And(m_Specific(A), m_Specific(B)))) - return BinaryOperator::CreateOr(A, B); - - if (match(LHS, m_Xor(m_Value(A), m_Value(B))) && - match(RHS, m_c_And(m_Specific(A), m_Specific(B)))) - return BinaryOperator::CreateOr(A, B); - } + if (match(LHS, m_Xor(m_Value(A), m_Value(B))) && + match(RHS, m_c_And(m_Specific(A), m_Specific(B)))) + return BinaryOperator::CreateOr(A, B); + + // (add (and A, B) (xor A, B)) --> (or A, B) + if (match(RHS, m_Xor(m_Value(A), m_Value(B))) && + match(LHS, m_c_And(m_Specific(A), m_Specific(B)))) + return BinaryOperator::CreateOr(A, B); // (add (or A, B) (and A, B)) --> (add A, B) - { - Value *A = nullptr, *B = nullptr; - if (match(RHS, m_Or(m_Value(A), m_Value(B))) && - match(LHS, m_c_And(m_Specific(A), m_Specific(B)))) { - auto *New = BinaryOperator::CreateAdd(A, B); - New->setHasNoSignedWrap(I.hasNoSignedWrap()); - New->setHasNoUnsignedWrap(I.hasNoUnsignedWrap()); - return New; - } + if (match(LHS, m_Or(m_Value(A), m_Value(B))) && + match(RHS, m_c_And(m_Specific(A), m_Specific(B)))) { + I.setOperand(0, A); + I.setOperand(1, B); + return &I; + } - if (match(LHS, m_Or(m_Value(A), m_Value(B))) && - match(RHS, m_c_And(m_Specific(A), m_Specific(B)))) { - auto *New = BinaryOperator::CreateAdd(A, B); - New->setHasNoSignedWrap(I.hasNoSignedWrap()); - New->setHasNoUnsignedWrap(I.hasNoUnsignedWrap()); - return New; - } + // (add (and A, B) (or A, B)) --> (add A, B) + if (match(RHS, m_Or(m_Value(A), m_Value(B))) && + match(LHS, m_c_And(m_Specific(A), m_Specific(B)))) { + I.setOperand(0, A); + I.setOperand(1, B); + return &I; } // TODO(jingyue): Consider willNotOverflowSignedAdd and @@ -1387,32 +1382,11 @@ Instruction *InstCombiner::visitFAdd(BinaryOperator &I) { } } - // select C, 0, B + select C, A, 0 -> select C, A, B - { - Value *A1, *B1, *C1, *A2, *B2, *C2; - if (match(LHS, m_Select(m_Value(C1), m_Value(A1), m_Value(B1))) && - match(RHS, m_Select(m_Value(C2), m_Value(A2), m_Value(B2)))) { - if (C1 == C2) { - Constant *Z1=nullptr, *Z2=nullptr; - Value *A, *B, *C=C1; - if (match(A1, m_AnyZero()) && match(B2, m_AnyZero())) { - Z1 = dyn_cast<Constant>(A1); A = A2; - Z2 = dyn_cast<Constant>(B2); B = B1; - } else if (match(B1, m_AnyZero()) && match(A2, m_AnyZero())) { - Z1 = dyn_cast<Constant>(B1); B = B2; - Z2 = dyn_cast<Constant>(A2); A = A1; - } - - if (Z1 && Z2 && - (I.hasNoSignedZeros() || - (Z1->isNegativeZeroValue() && Z2->isNegativeZeroValue()))) { - return SelectInst::Create(C, A, B); - } - } - } - } + // Handle specials cases for FAdd with selects feeding the operation + if (Value *V = SimplifySelectsFeedingBinaryOp(I, LHS, RHS)) + return replaceInstUsesWith(I, V); - if (I.hasUnsafeAlgebra()) { + if (I.isFast()) { if (Value *V = FAddCombine(Builder).simplify(&I)) return replaceInstUsesWith(I, V); } @@ -1423,7 +1397,6 @@ Instruction *InstCombiner::visitFAdd(BinaryOperator &I) { /// Optimize pointer differences into the same array into a size. Consider: /// &A[10] - &A[0]: we should compile this to "10". LHS/RHS are the pointer /// operands to the ptrtoint instructions for the LHS/RHS of the subtract. -/// Value *InstCombiner::OptimizePointerDifference(Value *LHS, Value *RHS, Type *Ty) { // If LHS is a gep based on RHS or RHS is a gep based on LHS, we can optimize @@ -1465,12 +1438,31 @@ Value *InstCombiner::OptimizePointerDifference(Value *LHS, Value *RHS, } } - // Avoid duplicating the arithmetic if GEP2 has non-constant indices and - // multiple users. - if (!GEP1 || - (GEP2 && !GEP2->hasAllConstantIndices() && !GEP2->hasOneUse())) + if (!GEP1) + // No GEP found. return nullptr; + if (GEP2) { + // (gep X, ...) - (gep X, ...) + // + // Avoid duplicating the arithmetic if there are more than one non-constant + // indices between the two GEPs and either GEP has a non-constant index and + // multiple users. If zero non-constant index, the result is a constant and + // there is no duplication. If one non-constant index, the result is an add + // or sub with a constant, which is no larger than the original code, and + // there's no duplicated arithmetic, even if either GEP has multiple + // users. If more than one non-constant indices combined, as long as the GEP + // with at least one non-constant index doesn't have multiple users, there + // is no duplication. + unsigned NumNonConstantIndices1 = GEP1->countNonConstantIndices(); + unsigned NumNonConstantIndices2 = GEP2->countNonConstantIndices(); + if (NumNonConstantIndices1 + NumNonConstantIndices2 > 1 && + ((NumNonConstantIndices1 > 0 && !GEP1->hasOneUse()) || + (NumNonConstantIndices2 > 0 && !GEP2->hasOneUse()))) { + return nullptr; + } + } + // Emit the offset of the GEP and an intptr_t. Value *Result = EmitGEPOffset(GEP1); @@ -1528,8 +1520,13 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) { return BinaryOperator::CreateNot(Op1); if (Constant *C = dyn_cast<Constant>(Op0)) { + Value *X; + // C - zext(bool) -> bool ? C - 1 : C + if (match(Op1, m_ZExt(m_Value(X))) && + X->getType()->getScalarSizeInBits() == 1) + return SelectInst::Create(X, SubOne(C), C); + // C - ~X == X + (1+C) - Value *X = nullptr; if (match(Op1, m_Not(m_Value(X)))) return BinaryOperator::CreateAdd(X, AddOne(C)); @@ -1600,7 +1597,7 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) { return BinaryOperator::CreateNeg(Y); } - // (sub (or A, B) (xor A, B)) --> (and A, B) + // (sub (or A, B), (xor A, B)) --> (and A, B) { Value *A, *B; if (match(Op1, m_Xor(m_Value(A), m_Value(B))) && @@ -1626,7 +1623,6 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) { Builder.CreateSub(Z, Y, Op1->getName())); // (X - (X & Y)) --> (X & ~Y) - // if (match(Op1, m_c_And(m_Value(Y), m_Specific(Op0)))) return BinaryOperator::CreateAnd(Op0, Builder.CreateNot(Y, Y->getName() + ".not")); @@ -1741,7 +1737,11 @@ Instruction *InstCombiner::visitFSub(BinaryOperator &I) { } } - if (I.hasUnsafeAlgebra()) { + // Handle specials cases for FSub with selects feeding the operation + if (Value *V = SimplifySelectsFeedingBinaryOp(I, Op0, Op1)) + return replaceInstUsesWith(I, V); + + if (I.isFast()) { if (Value *V = FAddCombine(Builder).simplify(&I)) return replaceInstUsesWith(I, V); } |