diff options
Diffstat (limited to 'llvm/lib/Transforms/Utils/SCCPSolver.cpp')
| -rw-r--r-- | llvm/lib/Transforms/Utils/SCCPSolver.cpp | 204 | 
1 files changed, 59 insertions, 145 deletions
| diff --git a/llvm/lib/Transforms/Utils/SCCPSolver.cpp b/llvm/lib/Transforms/Utils/SCCPSolver.cpp index d7e8eaf677c6..eee91e70292e 100644 --- a/llvm/lib/Transforms/Utils/SCCPSolver.cpp +++ b/llvm/lib/Transforms/Utils/SCCPSolver.cpp @@ -15,14 +15,12 @@  #include "llvm/Transforms/Utils/SCCPSolver.h"  #include "llvm/Analysis/ConstantFolding.h"  #include "llvm/Analysis/InstructionSimplify.h" -#include "llvm/Analysis/ValueTracking.h" -#include "llvm/InitializePasses.h" -#include "llvm/Pass.h" +#include "llvm/Analysis/ValueLattice.h" +#include "llvm/IR/InstVisitor.h"  #include "llvm/Support/Casting.h"  #include "llvm/Support/Debug.h"  #include "llvm/Support/ErrorHandling.h"  #include "llvm/Support/raw_ostream.h" -#include "llvm/Transforms/Utils/Local.h"  #include <cassert>  #include <utility>  #include <vector> @@ -452,7 +450,8 @@ public:      return TrackingIncomingArguments;    } -  void markArgInFuncSpecialization(Function *F, Argument *A, Constant *C); +  void markArgInFuncSpecialization(Function *F, +                                   const SmallVectorImpl<ArgInfo> &Args);    void markFunctionUnreachable(Function *F) {      for (auto &BB : *F) @@ -526,29 +525,38 @@ Constant *SCCPInstVisitor::getConstant(const ValueLatticeElement &LV) const {    return nullptr;  } -void SCCPInstVisitor::markArgInFuncSpecialization(Function *F, Argument *A, -                                                  Constant *C) { -  assert(F->arg_size() == A->getParent()->arg_size() && +void SCCPInstVisitor::markArgInFuncSpecialization( +    Function *F, const SmallVectorImpl<ArgInfo> &Args) { +  assert(!Args.empty() && "Specialization without arguments"); +  assert(F->arg_size() == Args[0].Formal->getParent()->arg_size() &&           "Functions should have the same number of arguments"); -  // Mark the argument constant in the new function. -  markConstant(A, C); - -  // For the remaining arguments in the new function, copy the lattice state -  // over from the old function. -  for (auto I = F->arg_begin(), J = A->getParent()->arg_begin(), -            E = F->arg_end(); -       I != E; ++I, ++J) -    if (J != A && ValueState.count(I)) { +  auto Iter = Args.begin(); +  Argument *NewArg = F->arg_begin(); +  Argument *OldArg = Args[0].Formal->getParent()->arg_begin(); +  for (auto End = F->arg_end(); NewArg != End; ++NewArg, ++OldArg) { + +    LLVM_DEBUG(dbgs() << "SCCP: Marking argument " +                      << NewArg->getNameOrAsOperand() << "\n"); + +    if (Iter != Args.end() && OldArg == Iter->Formal) { +      // Mark the argument constants in the new function. +      markConstant(NewArg, Iter->Actual); +      ++Iter; +    } else if (ValueState.count(OldArg)) { +      // For the remaining arguments in the new function, copy the lattice state +      // over from the old function. +      //        // Note: This previously looked like this: -      // ValueState[J] = ValueState[I]; +      // ValueState[NewArg] = ValueState[OldArg];        // This is incorrect because the DenseMap class may resize the underlying -      // memory when inserting `J`, which will invalidate the reference to `I`. -      // Instead, we make sure `J` exists, then set it to `I` afterwards. -      auto &NewValue = ValueState[J]; -      NewValue = ValueState[I]; -      pushToWorkList(NewValue, J); +      // memory when inserting `NewArg`, which will invalidate the reference to +      // `OldArg`. Instead, we make sure `NewArg` exists before setting it. +      auto &NewValue = ValueState[NewArg]; +      NewValue = ValueState[OldArg]; +      pushToWorkList(NewValue, NewArg);      } +  }  }  void SCCPInstVisitor::visitInstruction(Instruction &I) { @@ -988,7 +996,7 @@ void SCCPInstVisitor::visitBinaryOperator(Instruction &I) {    if ((V1State.isConstant() || V2State.isConstant())) {      Value *V1 = isConstant(V1State) ? getConstant(V1State) : I.getOperand(0);      Value *V2 = isConstant(V2State) ? getConstant(V2State) : I.getOperand(1); -    Value *R = SimplifyBinOp(I.getOpcode(), V1, V2, SimplifyQuery(DL)); +    Value *R = simplifyBinOp(I.getOpcode(), V1, V2, SimplifyQuery(DL));      auto *C = dyn_cast_or_null<Constant>(R);      if (C) {        // X op Y -> undef. @@ -1287,17 +1295,6 @@ void SCCPInstVisitor::handleCallResult(CallBase &CB) {          return;        } -      // TODO: Actually filp MayIncludeUndef for the created range to false, -      // once most places in the optimizer respect the branches on -      // undef/poison are UB rule. The reason why the new range cannot be -      // undef is as follows below: -      // The new range is based on a branch condition. That guarantees that -      // neither of the compare operands can be undef in the branch targets, -      // unless we have conditions that are always true/false (e.g. icmp ule -      // i32, %a, i32_max). For the latter overdefined/empty range will be -      // inferred, but the branch will get folded accordingly anyways. -      bool MayIncludeUndef = !isa<PredicateAssume>(PI); -        ValueLatticeElement CondVal = getValueState(OtherOp);        ValueLatticeElement &IV = ValueState[&CB];        if (CondVal.isConstantRange() || CopyOfVal.isConstantRange()) { @@ -1322,9 +1319,15 @@ void SCCPInstVisitor::handleCallResult(CallBase &CB) {          if (!CopyOfCR.contains(NewCR) && CopyOfCR.getSingleMissingElement())            NewCR = CopyOfCR; +        // The new range is based on a branch condition. That guarantees that +        // neither of the compare operands can be undef in the branch targets, +        // unless we have conditions that are always true/false (e.g. icmp ule +        // i32, %a, i32_max). For the latter overdefined/empty range will be +        // inferred, but the branch will get folded accordingly anyways.          addAdditionalUser(OtherOp, &CB); -        mergeInValue(IV, &CB, -                     ValueLatticeElement::getRange(NewCR, MayIncludeUndef)); +        mergeInValue( +            IV, &CB, +            ValueLatticeElement::getRange(NewCR, /*MayIncludeUndef*/ false));          return;        } else if (Pred == CmpInst::ICMP_EQ && CondVal.isConstant()) {          // For non-integer values or integer constant expressions, only @@ -1332,8 +1335,7 @@ void SCCPInstVisitor::handleCallResult(CallBase &CB) {          addAdditionalUser(OtherOp, &CB);          mergeInValue(IV, &CB, CondVal);          return; -      } else if (Pred == CmpInst::ICMP_NE && CondVal.isConstant() && -                 !MayIncludeUndef) { +      } else if (Pred == CmpInst::ICMP_NE && CondVal.isConstant()) {          // Propagate inequalities.          addAdditionalUser(OtherOp, &CB);          mergeInValue(IV, &CB, @@ -1442,22 +1444,19 @@ void SCCPInstVisitor::solve() {    }  } -/// resolvedUndefsIn - While solving the dataflow for a function, we assume -/// that branches on undef values cannot reach any of their successors. -/// However, this is not a safe assumption.  After we solve dataflow, this -/// method should be use to handle this.  If this returns true, the solver -/// should be rerun. +/// While solving the dataflow for a function, we don't compute a result for +/// operations with an undef operand, to allow undef to be lowered to a +/// constant later. For example, constant folding of "zext i8 undef to i16" +/// would result in "i16 0", and if undef is later lowered to "i8 1", then the +/// zext result would become "i16 1" and would result into an overdefined +/// lattice value once merged with the previous result. Not computing the +/// result of the zext (treating undef the same as unknown) allows us to handle +/// a later undef->constant lowering more optimally.  /// -/// This method handles this by finding an unresolved branch and marking it one -/// of the edges from the block as being feasible, even though the condition -/// doesn't say it would otherwise be.  This allows SCCP to find the rest of the -/// CFG and only slightly pessimizes the analysis results (by marking one, -/// potentially infeasible, edge feasible).  This cannot usefully modify the -/// constraints on the condition of the branch, as that would impact other users -/// of the value. -/// -/// This scan also checks for values that use undefs. It conservatively marks -/// them as overdefined. +/// However, if the operand remains undef when the solver returns, we do need +/// to assign some result to the instruction (otherwise we would treat it as +/// unreachable). For simplicity, we mark any instructions that are still +/// unknown as overdefined.  bool SCCPInstVisitor::resolvedUndefsIn(Function &F) {    bool MadeChange = false;    for (BasicBlock &BB : F) { @@ -1486,7 +1485,7 @@ bool SCCPInstVisitor::resolvedUndefsIn(Function &F) {          // more precise than this but it isn't worth bothering.          for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {            ValueLatticeElement &LV = getStructValueState(&I, i); -          if (LV.isUnknownOrUndef()) { +          if (LV.isUnknown()) {              markOverdefined(LV, &I);              MadeChange = true;            } @@ -1495,7 +1494,7 @@ bool SCCPInstVisitor::resolvedUndefsIn(Function &F) {        }        ValueLatticeElement &LV = getValueState(&I); -      if (!LV.isUnknownOrUndef()) +      if (!LV.isUnknown())          continue;        // There are two reasons a call can have an undef result @@ -1518,91 +1517,6 @@ bool SCCPInstVisitor::resolvedUndefsIn(Function &F) {        markOverdefined(&I);        MadeChange = true;      } - -    // Check to see if we have a branch or switch on an undefined value.  If so -    // we force the branch to go one way or the other to make the successor -    // values live.  It doesn't really matter which way we force it. -    Instruction *TI = BB.getTerminator(); -    if (auto *BI = dyn_cast<BranchInst>(TI)) { -      if (!BI->isConditional()) -        continue; -      if (!getValueState(BI->getCondition()).isUnknownOrUndef()) -        continue; - -      // If the input to SCCP is actually branch on undef, fix the undef to -      // false. -      if (isa<UndefValue>(BI->getCondition())) { -        BI->setCondition(ConstantInt::getFalse(BI->getContext())); -        markEdgeExecutable(&BB, TI->getSuccessor(1)); -        MadeChange = true; -        continue; -      } - -      // Otherwise, it is a branch on a symbolic value which is currently -      // considered to be undef.  Make sure some edge is executable, so a -      // branch on "undef" always flows somewhere. -      // FIXME: Distinguish between dead code and an LLVM "undef" value. -      BasicBlock *DefaultSuccessor = TI->getSuccessor(1); -      if (markEdgeExecutable(&BB, DefaultSuccessor)) -        MadeChange = true; - -      continue; -    } - -    if (auto *IBR = dyn_cast<IndirectBrInst>(TI)) { -      // Indirect branch with no successor ?. Its ok to assume it branches -      // to no target. -      if (IBR->getNumSuccessors() < 1) -        continue; - -      if (!getValueState(IBR->getAddress()).isUnknownOrUndef()) -        continue; - -      // If the input to SCCP is actually branch on undef, fix the undef to -      // the first successor of the indirect branch. -      if (isa<UndefValue>(IBR->getAddress())) { -        IBR->setAddress(BlockAddress::get(IBR->getSuccessor(0))); -        markEdgeExecutable(&BB, IBR->getSuccessor(0)); -        MadeChange = true; -        continue; -      } - -      // Otherwise, it is a branch on a symbolic value which is currently -      // considered to be undef.  Make sure some edge is executable, so a -      // branch on "undef" always flows somewhere. -      // FIXME: IndirectBr on "undef" doesn't actually need to go anywhere: -      // we can assume the branch has undefined behavior instead. -      BasicBlock *DefaultSuccessor = IBR->getSuccessor(0); -      if (markEdgeExecutable(&BB, DefaultSuccessor)) -        MadeChange = true; - -      continue; -    } - -    if (auto *SI = dyn_cast<SwitchInst>(TI)) { -      if (!SI->getNumCases() || -          !getValueState(SI->getCondition()).isUnknownOrUndef()) -        continue; - -      // If the input to SCCP is actually switch on undef, fix the undef to -      // the first constant. -      if (isa<UndefValue>(SI->getCondition())) { -        SI->setCondition(SI->case_begin()->getCaseValue()); -        markEdgeExecutable(&BB, SI->case_begin()->getCaseSuccessor()); -        MadeChange = true; -        continue; -      } - -      // Otherwise, it is a branch on a symbolic value which is currently -      // considered to be undef.  Make sure some edge is executable, so a -      // branch on "undef" always flows somewhere. -      // FIXME: Distinguish between dead code and an LLVM "undef" value. -      BasicBlock *DefaultSuccessor = SI->case_begin()->getCaseSuccessor(); -      if (markEdgeExecutable(&BB, DefaultSuccessor)) -        MadeChange = true; - -      continue; -    }    }    return MadeChange; @@ -1618,7 +1532,7 @@ SCCPSolver::SCCPSolver(      LLVMContext &Ctx)      : Visitor(new SCCPInstVisitor(DL, std::move(GetTLI), Ctx)) {} -SCCPSolver::~SCCPSolver() {} +SCCPSolver::~SCCPSolver() = default;  void SCCPSolver::addAnalysis(Function &F, AnalysisResultsForFn A) {    return Visitor->addAnalysis(F, std::move(A)); @@ -1713,9 +1627,9 @@ SmallPtrSetImpl<Function *> &SCCPSolver::getArgumentTrackedFunctions() {    return Visitor->getArgumentTrackedFunctions();  } -void SCCPSolver::markArgInFuncSpecialization(Function *F, Argument *A, -                                             Constant *C) { -  Visitor->markArgInFuncSpecialization(F, A, C); +void SCCPSolver::markArgInFuncSpecialization( +    Function *F, const SmallVectorImpl<ArgInfo> &Args) { +  Visitor->markArgInFuncSpecialization(F, Args);  }  void SCCPSolver::markFunctionUnreachable(Function *F) { | 
