diff options
| author | Florian Hahn <florian.hahn@arm.com> | 2018-06-21 07:15:08 +0000 | 
|---|---|---|
| committer | Florian Hahn <florian.hahn@arm.com> | 2018-06-21 07:15:08 +0000 | 
| commit | d36aa1f7633b5450c9939fe8aaa0da1605042868 (patch) | |
| tree | 72ed1152e56e05d1c8275366b950c661a0b14017 /llvm/lib | |
| parent | 57b33f6aac852d6f8d154d574b05b7689afc8e2b (diff) | |
| download | bcm5719-llvm-d36aa1f7633b5450c9939fe8aaa0da1605042868.tar.gz bcm5719-llvm-d36aa1f7633b5450c9939fe8aaa0da1605042868.zip  | |
Recommit r333268: [IPSCCP] Use PredicateInfo to propagate facts from cmp instructions.
r335150 should resolve the issues with the clang-with-thin-lto-ubuntu
and clang-with-lto-ubuntu builders.
Original message:
This patch updates IPSCCP to use PredicateInfo to propagate
facts to true branches predicated by EQ and to false branches
predicated by NE.
As a follow up, we should be able to extend it to also propagate additional
facts about nonnull.
Reviewers: davide, mssimpso, dberlin, efriedma
Reviewed By: davide, dberlin
llvm-svn: 335206
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/Transforms/IPO/SCCP.cpp | 24 | ||||
| -rw-r--r-- | llvm/lib/Transforms/Scalar/SCCP.cpp | 120 | 
2 files changed, 134 insertions, 10 deletions
diff --git a/llvm/lib/Transforms/IPO/SCCP.cpp b/llvm/lib/Transforms/IPO/SCCP.cpp index cc53c4b8c46..e2bb6f185c3 100644 --- a/llvm/lib/Transforms/IPO/SCCP.cpp +++ b/llvm/lib/Transforms/IPO/SCCP.cpp @@ -1,4 +1,5 @@  #include "llvm/Transforms/IPO/SCCP.h" +#include "llvm/Analysis/AssumptionCache.h"  #include "llvm/Analysis/TargetLibraryInfo.h"  #include "llvm/Transforms/IPO.h"  #include "llvm/Transforms/Scalar/SCCP.h" @@ -8,7 +9,15 @@ using namespace llvm;  PreservedAnalyses IPSCCPPass::run(Module &M, ModuleAnalysisManager &AM) {    const DataLayout &DL = M.getDataLayout();    auto &TLI = AM.getResult<TargetLibraryAnalysis>(M); -  if (!runIPSCCP(M, DL, &TLI)) +  auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); +  auto getPredicateInfo = +      [&FAM](Function &F) -> std::unique_ptr<PredicateInfo> { +    return make_unique<PredicateInfo>(F, +                                      FAM.getResult<DominatorTreeAnalysis>(F), +                                      FAM.getResult<AssumptionAnalysis>(F)); +  }; + +  if (!runIPSCCP(M, DL, &TLI, getPredicateInfo))      return PreservedAnalyses::all();    return PreservedAnalyses::none();  } @@ -34,10 +43,20 @@ public:      const DataLayout &DL = M.getDataLayout();      const TargetLibraryInfo *TLI =          &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(); -    return runIPSCCP(M, DL, TLI); + +    auto getPredicateInfo = +        [this](Function &F) -> std::unique_ptr<PredicateInfo> { +      return make_unique<PredicateInfo>( +          F, this->getAnalysis<DominatorTreeWrapperPass>(F).getDomTree(), +          this->getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F)); +    }; + +    return runIPSCCP(M, DL, TLI, getPredicateInfo);    }    void getAnalysisUsage(AnalysisUsage &AU) const override { +    AU.addRequired<AssumptionCacheTracker>(); +    AU.addRequired<DominatorTreeWrapperPass>();      AU.addRequired<TargetLibraryInfoWrapperPass>();    }  }; @@ -49,6 +68,7 @@ char IPSCCPLegacyPass::ID = 0;  INITIALIZE_PASS_BEGIN(IPSCCPLegacyPass, "ipsccp",                        "Interprocedural Sparse Conditional Constant Propagation",                        false, false) +INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)  INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)  INITIALIZE_PASS_END(IPSCCPLegacyPass, "ipsccp",                      "Interprocedural Sparse Conditional Constant Propagation", diff --git a/llvm/lib/Transforms/Scalar/SCCP.cpp b/llvm/lib/Transforms/Scalar/SCCP.cpp index 345b030ddc1..445e0babb3c 100644 --- a/llvm/lib/Transforms/Scalar/SCCP.cpp +++ b/llvm/lib/Transforms/Scalar/SCCP.cpp @@ -55,6 +55,7 @@  #include "llvm/Support/ErrorHandling.h"  #include "llvm/Support/raw_ostream.h"  #include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Utils/PredicateInfo.h"  #include <cassert>  #include <utility>  #include <vector> @@ -248,7 +249,21 @@ class SCCPSolver : public InstVisitor<SCCPSolver> {    using Edge = std::pair<BasicBlock *, BasicBlock *>;    DenseSet<Edge> KnownFeasibleEdges; +  DenseMap<Function *, std::unique_ptr<PredicateInfo>> PredInfos; +  DenseMap<Value *, SmallPtrSet<User *, 2>> AdditionalUsers; +  public: +  void addPredInfo(Function &F, std::unique_ptr<PredicateInfo> PI) { +    PredInfos[&F] = std::move(PI); +  } + +  const PredicateBase *getPredicateInfoFor(Instruction *I) { +    auto PI = PredInfos.find(I->getParent()->getParent()); +    if (PI == PredInfos.end()) +      return nullptr; +    return PI->second->getPredicateInfoFor(I); +  } +    SCCPSolver(const DataLayout &DL, const TargetLibraryInfo *tli)        : DL(DL), TLI(tli) {} @@ -563,6 +578,26 @@ private:        visit(*I);    } +  // Add U as additional user of V. +  void addAdditionalUser(Value *V, User *U) { +    auto Iter = AdditionalUsers.insert({V, {}}); +    Iter.first->second.insert(U); +  } + +  // Mark I's users as changed, including AdditionalUsers. +  void markUsersAsChanged(Value *I) { +    for (User *U : I->users()) +      if (auto *UI = dyn_cast<Instruction>(U)) +        OperandChangedState(UI); + +    auto Iter = AdditionalUsers.find(I); +    if (Iter != AdditionalUsers.end()) { +      for (User *U : Iter->second) +        if (auto *UI = dyn_cast<Instruction>(U)) +          OperandChangedState(UI); +    } +  } +  private:    friend class InstVisitor<SCCPSolver>; @@ -1157,6 +1192,59 @@ void SCCPSolver::visitCallSite(CallSite CS) {    Function *F = CS.getCalledFunction();    Instruction *I = CS.getInstruction(); +  if (auto *II = dyn_cast<IntrinsicInst>(I)) { +    if (II->getIntrinsicID() == Intrinsic::ssa_copy) { +      if (ValueState[I].isOverdefined()) +        return; + +      auto *PI = getPredicateInfoFor(I); +      if (!PI) +        return; + +      auto *PBranch = dyn_cast<PredicateBranch>(getPredicateInfoFor(I)); +      if (!PBranch) +        return mergeInValue(ValueState[I], I, getValueState(PI->OriginalOp)); + +      Value *CopyOf = I->getOperand(0); +      Value *Cond = PBranch->Condition; + +      // Everything below relies on the condition being a comparison. +      auto *Cmp = dyn_cast<CmpInst>(Cond); +      if (!Cmp) +        return mergeInValue(ValueState[I], I, getValueState(PI->OriginalOp)); + +      Value *CmpOp0 = Cmp->getOperand(0); +      Value *CmpOp1 = Cmp->getOperand(1); +      if (CopyOf != CmpOp0 && CopyOf != CmpOp1) +        return mergeInValue(ValueState[I], I, getValueState(PI->OriginalOp)); + +      if (CmpOp0 != CopyOf) +        std::swap(CmpOp0, CmpOp1); + +      LatticeVal OriginalVal = getValueState(CopyOf); +      LatticeVal EqVal = getValueState(CmpOp1); +      LatticeVal &IV = ValueState[I]; +      if (PBranch->TrueEdge && Cmp->getPredicate() == CmpInst::ICMP_EQ) { +        addAdditionalUser(CmpOp1, I); +        if (OriginalVal.isConstant()) +          mergeInValue(IV, I, OriginalVal); +        else +          mergeInValue(IV, I, EqVal); +        return; +      } +      if (!PBranch->TrueEdge && Cmp->getPredicate() == CmpInst::ICMP_NE) { +        addAdditionalUser(CmpOp1, I); +        if (OriginalVal.isConstant()) +          mergeInValue(IV, I, OriginalVal); +        else +          mergeInValue(IV, I, EqVal); +        return; +      } + +      return mergeInValue(IV, I, getValueState(PBranch->OriginalOp)); +    } +  } +    // The common case is that we aren't tracking the callee, either because we    // are not doing interprocedural analysis or the callee is indirect, or is    // external.  Handle these cases first. @@ -1268,9 +1356,7 @@ void SCCPSolver::Solve() {        // since all of its users will have already been marked as overdefined        // Update all of the users of this instruction's value.        // -      for (User *U : I->users()) -        if (auto *UI = dyn_cast<Instruction>(U)) -          OperandChangedState(UI); +      markUsersAsChanged(I);      }      // Process the instruction work list. @@ -1287,9 +1373,7 @@ void SCCPSolver::Solve() {        // Update all of the users of this instruction's value.        //        if (I->getType()->isStructTy() || !getValueState(I).isOverdefined()) -        for (User *U : I->users()) -          if (auto *UI = dyn_cast<Instruction>(U)) -            OperandChangedState(UI); +        markUsersAsChanged(I);      }      // Process the basic block work list. @@ -1855,8 +1939,9 @@ static void findReturnsToZap(Function &F,    }  } -bool llvm::runIPSCCP(Module &M, const DataLayout &DL, -                     const TargetLibraryInfo *TLI) { +bool llvm::runIPSCCP( +    Module &M, const DataLayout &DL, const TargetLibraryInfo *TLI, +    function_ref<std::unique_ptr<PredicateInfo>(Function &)> getPredicateInfo) {    SCCPSolver Solver(DL, TLI);    // Loop over all functions, marking arguments to those with their addresses @@ -1865,6 +1950,7 @@ bool llvm::runIPSCCP(Module &M, const DataLayout &DL,      if (F.isDeclaration())        continue; +    Solver.addPredInfo(F, getPredicateInfo(F));      // Determine if we can track the function's return values. If so, add the      // function to the solver's set of return-tracked functions.      if (canTrackReturnsInterprocedurally(&F)) @@ -1983,6 +2069,24 @@ bool llvm::runIPSCCP(Module &M, const DataLayout &DL,        F.getBasicBlockList().erase(DeadBB);      }      BlocksToErase.clear(); + +    for (BasicBlock &BB : F) { +      for (BasicBlock::iterator BI = BB.begin(), E = BB.end(); BI != E;) { +        Instruction *Inst = &*BI++; +        if (const PredicateBase *PI = Solver.getPredicateInfoFor(Inst)) { +          if (auto *II = dyn_cast<IntrinsicInst>(Inst)) { +            if (II->getIntrinsicID() == Intrinsic::ssa_copy) { +              Value *Op = II->getOperand(0); +              Inst->replaceAllUsesWith(Op); +              Inst->eraseFromParent(); +              continue; +            } +          } +          Inst->replaceAllUsesWith(PI->OriginalOp); +          Inst->eraseFromParent(); +        } +      } +    }    }    // If we inferred constant or undef return values for a function, we replaced  | 

