diff options
Diffstat (limited to 'llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp')
| -rw-r--r-- | llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp | 62 | 
1 files changed, 48 insertions, 14 deletions
diff --git a/llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp b/llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp index 2a1a040bf83ee..f1d2e3c1ecfad 100644 --- a/llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp +++ b/llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp @@ -431,8 +431,10 @@ private:    bool reuniteExts(Instruction *I);    /// Find the closest dominator of <Dominatee> that is equivalent to <Key>. -  Instruction *findClosestMatchingDominator(const SCEV *Key, -                                            Instruction *Dominatee); +  Instruction *findClosestMatchingDominator( +      const SCEV *Key, Instruction *Dominatee, +      DenseMap<const SCEV *, SmallVector<Instruction *, 2>> &DominatingExprs); +    /// Verify F is free of dead code.    void verifyNoDeadCode(Function &F); @@ -456,7 +458,8 @@ private:    /// multiple GEPs with a single index.    bool LowerGEP; -  DenseMap<const SCEV *, SmallVector<Instruction *, 2>> DominatingExprs; +  DenseMap<const SCEV *, SmallVector<Instruction *, 2>> DominatingAdds; +  DenseMap<const SCEV *, SmallVector<Instruction *, 2>> DominatingSubs;  };  } // end anonymous namespace @@ -519,7 +522,7 @@ bool ConstantOffsetExtractor::CanTraceInto(bool SignExtended,      //   sext(a + b) = sext(a) + sext(b)      // even if the addition is not marked nsw.      // -    // Leveraging this invarient, we can trace into an sext'ed inbound GEP +    // Leveraging this invariant, we can trace into an sext'ed inbound GEP      // index if the constant offset is non-negative.      //      // Verified in @sext_add in split-gep.ll. @@ -549,6 +552,9 @@ bool ConstantOffsetExtractor::CanTraceInto(bool SignExtended,  APInt ConstantOffsetExtractor::findInEitherOperand(BinaryOperator *BO,                                                     bool SignExtended,                                                     bool ZeroExtended) { +  // 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, @@ -559,12 +565,22 @@ APInt ConstantOffsetExtractor::findInEitherOperand(BinaryOperator *BO,    // However, such cases are probably already handled by -instcombine,    // given this pass runs after the standard optimizations.    if (ConstantOffset != 0) return ConstantOffset; + +  // Reset the chain back to where it was when we started exploring this node, +  // since visiting the LHS didn't pan out. +  UserChain.resize(ChainLength); +    ConstantOffset = find(BO->getOperand(1), SignExtended, ZeroExtended,                          /* NonNegative */ false);    // If U is a sub operator, negate the constant offset found in the right    // operand.    if (BO->getOpcode() == Instruction::Sub)      ConstantOffset = -ConstantOffset; + +  // If RHS wasn't a suitable candidate either, reset the chain again. +  if (ConstantOffset == 0) +    UserChain.resize(ChainLength); +    return ConstantOffset;  } @@ -688,7 +704,7 @@ Value *ConstantOffsetExtractor::removeConstOffset(unsigned ChainIndex) {    }    BinaryOperator *BO = cast<BinaryOperator>(UserChain[ChainIndex]); -  assert(BO->getNumUses() <= 1 && +  assert((BO->use_empty() || BO->hasOneUse()) &&           "distributeExtsAndCloneChain clones each BinaryOperator in "           "UserChain, so no one should be used more than "           "once"); @@ -1141,7 +1157,8 @@ bool SeparateConstOffsetFromGEP::runOnFunction(Function &F) {  }  Instruction *SeparateConstOffsetFromGEP::findClosestMatchingDominator( -    const SCEV *Key, Instruction *Dominatee) { +    const SCEV *Key, Instruction *Dominatee, +    DenseMap<const SCEV *, SmallVector<Instruction *, 2>> &DominatingExprs) {    auto Pos = DominatingExprs.find(Key);    if (Pos == DominatingExprs.end())      return nullptr; @@ -1169,12 +1186,23 @@ bool SeparateConstOffsetFromGEP::reuniteExts(Instruction *I) {    // If Dom can't sign overflow and Dom dominates I, optimize I to sext(Dom).    // TODO: handle zext    Value *LHS = nullptr, *RHS = nullptr; -  if (match(I, m_Add(m_SExt(m_Value(LHS)), m_SExt(m_Value(RHS)))) || -      match(I, m_Sub(m_SExt(m_Value(LHS)), m_SExt(m_Value(RHS))))) { +  if (match(I, m_Add(m_SExt(m_Value(LHS)), m_SExt(m_Value(RHS))))) {      if (LHS->getType() == RHS->getType()) {        const SCEV *Key =            SE->getAddExpr(SE->getUnknown(LHS), SE->getUnknown(RHS)); -      if (auto *Dom = findClosestMatchingDominator(Key, I)) { +      if (auto *Dom = findClosestMatchingDominator(Key, I, DominatingAdds)) { +        Instruction *NewSExt = new SExtInst(Dom, I->getType(), "", I); +        NewSExt->takeName(I); +        I->replaceAllUsesWith(NewSExt); +        RecursivelyDeleteTriviallyDeadInstructions(I); +        return true; +      } +    } +  } else if (match(I, m_Sub(m_SExt(m_Value(LHS)), m_SExt(m_Value(RHS))))) { +    if (LHS->getType() == RHS->getType()) { +      const SCEV *Key = +          SE->getAddExpr(SE->getUnknown(LHS), SE->getUnknown(RHS)); +      if (auto *Dom = findClosestMatchingDominator(Key, I, DominatingSubs)) {          Instruction *NewSExt = new SExtInst(Dom, I->getType(), "", I);          NewSExt->takeName(I);          I->replaceAllUsesWith(NewSExt); @@ -1185,12 +1213,17 @@ bool SeparateConstOffsetFromGEP::reuniteExts(Instruction *I) {    }    // Add I to DominatingExprs if it's an add/sub that can't sign overflow. -  if (match(I, m_NSWAdd(m_Value(LHS), m_Value(RHS))) || -      match(I, m_NSWSub(m_Value(LHS), m_Value(RHS)))) { -    if (programUndefinedIfFullPoison(I)) { +  if (match(I, m_NSWAdd(m_Value(LHS), m_Value(RHS)))) { +    if (programUndefinedIfPoison(I)) { +      const SCEV *Key = +          SE->getAddExpr(SE->getUnknown(LHS), SE->getUnknown(RHS)); +      DominatingAdds[Key].push_back(I); +    } +  } else if (match(I, m_NSWSub(m_Value(LHS), m_Value(RHS)))) { +    if (programUndefinedIfPoison(I)) {        const SCEV *Key =            SE->getAddExpr(SE->getUnknown(LHS), SE->getUnknown(RHS)); -      DominatingExprs[Key].push_back(I); +      DominatingSubs[Key].push_back(I);      }    }    return false; @@ -1198,7 +1231,8 @@ bool SeparateConstOffsetFromGEP::reuniteExts(Instruction *I) {  bool SeparateConstOffsetFromGEP::reuniteExts(Function &F) {    bool Changed = false; -  DominatingExprs.clear(); +  DominatingAdds.clear(); +  DominatingSubs.clear();    for (const auto Node : depth_first(DT)) {      BasicBlock *BB = Node->getBlock();      for (auto I = BB->begin(); I != BB->end(); ) {  | 
