diff --git a/llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp b/llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp --- a/llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp +++ b/llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp @@ -246,7 +246,8 @@ /// it. It returns the numeric value of the extracted constant offset (0 if /// failed). The meaning of the arguments are the same as Extract. static int64_t Find(Value *Idx, GetElementPtrInst *GEP, - const DominatorTree *DT, Value *&NonConstantBaseValue); + const DominatorTree *DT, Value *&NonConstantBaseValue, + bool CheckProfitability = false); private: ConstantOffsetExtractor(Instruction *InsertionPt, const DominatorTree *DT) @@ -270,11 +271,12 @@ /// \p NonConstantBaseValue The second non-constant operand if V is binary /// operator. APInt find(Value *V, bool SignExtended, bool ZeroExtended, bool NonNegative, - Value *&NonConstantBaseValue); + Value *&NonConstantBaseValue, bool CheckProfitability = false); /// A helper function to look into both operands of a binary operator. APInt findInEitherOperand(BinaryOperator *BO, bool SignExtended, - bool ZeroExtended, Value *&NonConstantBaseValue); + bool ZeroExtended, Value *&NonConstantBaseValue, + bool CheckProfitability = false); /// After finding the constant offset C from the GEP index I, we build a new /// index I' s.t. I' + C = I. This function builds and returns the new @@ -637,16 +639,30 @@ return true; } -APInt ConstantOffsetExtractor::findInEitherOperand( - BinaryOperator *BO, bool SignExtended, bool ZeroExtended, - Value *&NonConstantBaseValue) { +APInt ConstantOffsetExtractor::findInEitherOperand(BinaryOperator *BO, + bool SignExtended, + bool ZeroExtended, + Value *&NonConstantBaseValue, + bool CheckProfitability) { // Save off the current height of the chain, in case we need to restore it. size_t ChainLength = UserChain.size(); // BO being non-negative does not shed light on whether its operands are // non-negative. Clear the NonNegative flag here. - APInt ConstantOffset = find(BO->getOperand(0), SignExtended, ZeroExtended, - /* NonNegative */ false, NonConstantBaseValue); + APInt ConstantOffset = + find(BO->getOperand(0), SignExtended, ZeroExtended, + /* NonNegative */ false, NonConstantBaseValue, CheckProfitability); + + // Only sub and add instructions don't need adding extra instructions. + if (CheckProfitability && (BO->getOpcode() != Instruction::Sub || + BO->getOpcode() != Instruction::Add)) { + LLVM_DEBUG(dbgs() << "Reset ConstantOffset\n"); + NonConstantBaseValue = nullptr; + ConstantOffset = 0; + UserChain.resize(ChainLength); + return ConstantOffset; + } + // If we found a constant offset in the left operand, stop and return that. // This shortcut might cause us to miss opportunities of combining the // constant offsets in both operands, e.g., (a + 4) + (b + 5) => (a + b) + 9. @@ -663,8 +679,9 @@ // since visiting the LHS didn't pan out. UserChain.resize(ChainLength); - ConstantOffset = find(BO->getOperand(1), SignExtended, ZeroExtended, - /* NonNegative */ false, NonConstantBaseValue); + ConstantOffset = + find(BO->getOperand(1), SignExtended, ZeroExtended, + /* NonNegative */ false, NonConstantBaseValue, CheckProfitability); // If U is a sub operator, negate the constant offset found in the right // operand. if (BO->getOpcode() == Instruction::Sub) @@ -683,7 +700,8 @@ APInt ConstantOffsetExtractor::find(Value *V, bool SignExtended, bool ZeroExtended, bool NonNegative, - Value *&NonConstantBaseValue) { + Value *&NonConstantBaseValue, + bool CheckProfitability) { // TODO(jingyue): We could trace into integer/pointer casts, such as // inttoptr, ptrtoint, bitcast, and addrspacecast. We choose to handle only // integers because it gives good enough results for our benchmarks. @@ -700,16 +718,18 @@ } else if (BinaryOperator *BO = dyn_cast(V)) { // Trace into subexpressions for more hoisting opportunities. if (CanTraceInto(SignExtended, ZeroExtended, BO, NonNegative)) - ConstantOffset = findInEitherOperand(BO, SignExtended, ZeroExtended, - NonConstantBaseValue); + ConstantOffset = + findInEitherOperand(BO, SignExtended, ZeroExtended, + NonConstantBaseValue, CheckProfitability); } else if (isa(V)) { ConstantOffset = find(U->getOperand(0), SignExtended, ZeroExtended, - NonNegative, NonConstantBaseValue) + NonNegative, NonConstantBaseValue, CheckProfitability) .trunc(BitWidth); } else if (isa(V)) { - ConstantOffset = find(U->getOperand(0), /* SignExtended */ true, - ZeroExtended, NonNegative, NonConstantBaseValue) - .sext(BitWidth); + ConstantOffset = + find(U->getOperand(0), /* SignExtended */ true, ZeroExtended, + NonNegative, NonConstantBaseValue, CheckProfitability) + .sext(BitWidth); } else if (isa(V)) { // As an optimization, we can clear the SignExtended flag because // sext(zext(a)) = zext(a). Verified in @sext_zext in split-gep.ll. @@ -717,7 +737,7 @@ // Clear the NonNegative flag, because zext(a) >= 0 does not imply a >= 0. ConstantOffset = find(U->getOperand(0), /* SignExtended */ false, /* ZeroExtended */ true, /* NonNegative */ false, - NonConstantBaseValue) + NonConstantBaseValue, CheckProfitability) .zext(BitWidth); } @@ -871,11 +891,12 @@ int64_t ConstantOffsetExtractor::Find(Value *Idx, GetElementPtrInst *GEP, const DominatorTree *DT, - Value *&NonConstantBaseValue) { + Value *&NonConstantBaseValue, + bool CheckProfitability) { // If Idx is an index of an inbound GEP, Idx is guaranteed to be non-negative. return ConstantOffsetExtractor(GEP, DT) .find(Idx, /* SignExtended */ false, /* ZeroExtended */ false, - GEP->isInBounds(), NonConstantBaseValue) + GEP->isInBounds(), NonConstantBaseValue, CheckProfitability) .getSExtValue(); } @@ -908,7 +929,8 @@ if (GTI.isSequential()) { // Tries to extract a constant offset from this GEP index. int64_t ConstantOffset = ConstantOffsetExtractor::Find( - GEP->getOperand(I), GEP, DT, NonConstantBaseValue); + GEP->getOperand(I), GEP, DT, NonConstantBaseValue, + CheckProfitability); if (ConstantOffset != 0) { if (CheckProfitability || PossibleBases.empty()) { PossibleBases.emplace_back(