xref: /freebsd-src/contrib/llvm-project/llvm/lib/Transforms/Utils/SCCPSolver.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1fe6060f1SDimitry Andric //===- SCCPSolver.cpp - SCCP Utility --------------------------- *- C++ -*-===//
2fe6060f1SDimitry Andric //
3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fe6060f1SDimitry Andric //
7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
8fe6060f1SDimitry Andric //
9fe6060f1SDimitry Andric // \file
10fe6060f1SDimitry Andric // This file implements the Sparse Conditional Constant Propagation (SCCP)
11fe6060f1SDimitry Andric // utility.
12fe6060f1SDimitry Andric //
13fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
14fe6060f1SDimitry Andric 
15fe6060f1SDimitry Andric #include "llvm/Transforms/Utils/SCCPSolver.h"
16fe6060f1SDimitry Andric #include "llvm/Analysis/ConstantFolding.h"
17fe6060f1SDimitry Andric #include "llvm/Analysis/InstructionSimplify.h"
1881ad6265SDimitry Andric #include "llvm/Analysis/ValueLattice.h"
19bdd1243dSDimitry Andric #include "llvm/Analysis/ValueLatticeUtils.h"
2006c3fb27SDimitry Andric #include "llvm/Analysis/ValueTracking.h"
2181ad6265SDimitry Andric #include "llvm/IR/InstVisitor.h"
22fe6060f1SDimitry Andric #include "llvm/Support/Casting.h"
23fe6060f1SDimitry Andric #include "llvm/Support/Debug.h"
24fe6060f1SDimitry Andric #include "llvm/Support/ErrorHandling.h"
25fe6060f1SDimitry Andric #include "llvm/Support/raw_ostream.h"
26bdd1243dSDimitry Andric #include "llvm/Transforms/Utils/Local.h"
27fe6060f1SDimitry Andric #include <cassert>
28fe6060f1SDimitry Andric #include <utility>
29fe6060f1SDimitry Andric #include <vector>
30fe6060f1SDimitry Andric 
31fe6060f1SDimitry Andric using namespace llvm;
32fe6060f1SDimitry Andric 
33fe6060f1SDimitry Andric #define DEBUG_TYPE "sccp"
34fe6060f1SDimitry Andric 
35fe6060f1SDimitry Andric // The maximum number of range extensions allowed for operations requiring
36fe6060f1SDimitry Andric // widening.
37fe6060f1SDimitry Andric static const unsigned MaxNumRangeExtensions = 10;
38fe6060f1SDimitry Andric 
39fe6060f1SDimitry Andric /// Returns MergeOptions with MaxWidenSteps set to MaxNumRangeExtensions.
40fe6060f1SDimitry Andric static ValueLatticeElement::MergeOptions getMaxWidenStepsOpts() {
41fe6060f1SDimitry Andric   return ValueLatticeElement::MergeOptions().setMaxWidenSteps(
42fe6060f1SDimitry Andric       MaxNumRangeExtensions);
43fe6060f1SDimitry Andric }
44fe6060f1SDimitry Andric 
45bdd1243dSDimitry Andric namespace llvm {
46fe6060f1SDimitry Andric 
47bdd1243dSDimitry Andric bool SCCPSolver::isConstant(const ValueLatticeElement &LV) {
48fe6060f1SDimitry Andric   return LV.isConstant() ||
49fe6060f1SDimitry Andric          (LV.isConstantRange() && LV.getConstantRange().isSingleElement());
50fe6060f1SDimitry Andric }
51fe6060f1SDimitry Andric 
52bdd1243dSDimitry Andric bool SCCPSolver::isOverdefined(const ValueLatticeElement &LV) {
53bdd1243dSDimitry Andric   return !LV.isUnknownOrUndef() && !SCCPSolver::isConstant(LV);
54fe6060f1SDimitry Andric }
55fe6060f1SDimitry Andric 
56bdd1243dSDimitry Andric static bool canRemoveInstruction(Instruction *I) {
57bdd1243dSDimitry Andric   if (wouldInstructionBeTriviallyDead(I))
58bdd1243dSDimitry Andric     return true;
59fe6060f1SDimitry Andric 
60bdd1243dSDimitry Andric   // Some instructions can be handled but are rejected above. Catch
61bdd1243dSDimitry Andric   // those cases by falling through to here.
62bdd1243dSDimitry Andric   // TODO: Mark globals as being constant earlier, so
63bdd1243dSDimitry Andric   // TODO: wouldInstructionBeTriviallyDead() knows that atomic loads
64bdd1243dSDimitry Andric   // TODO: are safe to remove.
65bdd1243dSDimitry Andric   return isa<LoadInst>(I);
66bdd1243dSDimitry Andric }
67bdd1243dSDimitry Andric 
68bdd1243dSDimitry Andric bool SCCPSolver::tryToReplaceWithConstant(Value *V) {
6906c3fb27SDimitry Andric   Constant *Const = getConstantOrNull(V);
7006c3fb27SDimitry Andric   if (!Const)
71bdd1243dSDimitry Andric     return false;
72bdd1243dSDimitry Andric   // Replacing `musttail` instructions with constant breaks `musttail` invariant
73bdd1243dSDimitry Andric   // unless the call itself can be removed.
74bdd1243dSDimitry Andric   // Calls with "clang.arc.attachedcall" implicitly use the return value and
75bdd1243dSDimitry Andric   // those uses cannot be updated with a constant.
76bdd1243dSDimitry Andric   CallBase *CB = dyn_cast<CallBase>(V);
77bdd1243dSDimitry Andric   if (CB && ((CB->isMustTailCall() &&
78bdd1243dSDimitry Andric               !canRemoveInstruction(CB)) ||
79bdd1243dSDimitry Andric              CB->getOperandBundle(LLVMContext::OB_clang_arc_attachedcall))) {
80bdd1243dSDimitry Andric     Function *F = CB->getCalledFunction();
81bdd1243dSDimitry Andric 
82bdd1243dSDimitry Andric     // Don't zap returns of the callee
83bdd1243dSDimitry Andric     if (F)
84bdd1243dSDimitry Andric       addToMustPreserveReturnsInFunctions(F);
85bdd1243dSDimitry Andric 
86bdd1243dSDimitry Andric     LLVM_DEBUG(dbgs() << "  Can\'t treat the result of call " << *CB
87bdd1243dSDimitry Andric                       << " as a constant\n");
88bdd1243dSDimitry Andric     return false;
89bdd1243dSDimitry Andric   }
90bdd1243dSDimitry Andric 
91bdd1243dSDimitry Andric   LLVM_DEBUG(dbgs() << "  Constant: " << *Const << " = " << *V << '\n');
92bdd1243dSDimitry Andric 
93bdd1243dSDimitry Andric   // Replaces all of the uses of a variable with uses of the constant.
94bdd1243dSDimitry Andric   V->replaceAllUsesWith(Const);
95bdd1243dSDimitry Andric   return true;
96bdd1243dSDimitry Andric }
97bdd1243dSDimitry Andric 
9806c3fb27SDimitry Andric /// Try to use \p Inst's value range from \p Solver to infer the NUW flag.
9906c3fb27SDimitry Andric static bool refineInstruction(SCCPSolver &Solver,
10006c3fb27SDimitry Andric                               const SmallPtrSetImpl<Value *> &InsertedValues,
10106c3fb27SDimitry Andric                               Instruction &Inst) {
1025f757f3fSDimitry Andric   bool Changed = false;
10306c3fb27SDimitry Andric   auto GetRange = [&Solver, &InsertedValues](Value *Op) {
104*0fca6ea1SDimitry Andric     if (auto *Const = dyn_cast<Constant>(Op))
105*0fca6ea1SDimitry Andric       return Const->toConstantRange();
106*0fca6ea1SDimitry Andric     if (InsertedValues.contains(Op)) {
10706c3fb27SDimitry Andric       unsigned Bitwidth = Op->getType()->getScalarSizeInBits();
10806c3fb27SDimitry Andric       return ConstantRange::getFull(Bitwidth);
10906c3fb27SDimitry Andric     }
110*0fca6ea1SDimitry Andric     return Solver.getLatticeValueFor(Op).asConstantRange(
111*0fca6ea1SDimitry Andric         Op->getType(), /*UndefAllowed=*/false);
11206c3fb27SDimitry Andric   };
1135f757f3fSDimitry Andric 
1145f757f3fSDimitry Andric   if (isa<OverflowingBinaryOperator>(Inst)) {
115*0fca6ea1SDimitry Andric     if (Inst.hasNoSignedWrap() && Inst.hasNoUnsignedWrap())
116*0fca6ea1SDimitry Andric       return false;
117*0fca6ea1SDimitry Andric 
11806c3fb27SDimitry Andric     auto RangeA = GetRange(Inst.getOperand(0));
11906c3fb27SDimitry Andric     auto RangeB = GetRange(Inst.getOperand(1));
12006c3fb27SDimitry Andric     if (!Inst.hasNoUnsignedWrap()) {
12106c3fb27SDimitry Andric       auto NUWRange = ConstantRange::makeGuaranteedNoWrapRegion(
12206c3fb27SDimitry Andric           Instruction::BinaryOps(Inst.getOpcode()), RangeB,
12306c3fb27SDimitry Andric           OverflowingBinaryOperator::NoUnsignedWrap);
12406c3fb27SDimitry Andric       if (NUWRange.contains(RangeA)) {
12506c3fb27SDimitry Andric         Inst.setHasNoUnsignedWrap();
12606c3fb27SDimitry Andric         Changed = true;
12706c3fb27SDimitry Andric       }
12806c3fb27SDimitry Andric     }
12906c3fb27SDimitry Andric     if (!Inst.hasNoSignedWrap()) {
13006c3fb27SDimitry Andric       auto NSWRange = ConstantRange::makeGuaranteedNoWrapRegion(
1315f757f3fSDimitry Andric           Instruction::BinaryOps(Inst.getOpcode()), RangeB,
1325f757f3fSDimitry Andric           OverflowingBinaryOperator::NoSignedWrap);
13306c3fb27SDimitry Andric       if (NSWRange.contains(RangeA)) {
13406c3fb27SDimitry Andric         Inst.setHasNoSignedWrap();
13506c3fb27SDimitry Andric         Changed = true;
13606c3fb27SDimitry Andric       }
13706c3fb27SDimitry Andric     }
138*0fca6ea1SDimitry Andric   } else if (isa<PossiblyNonNegInst>(Inst) && !Inst.hasNonNeg()) {
1395f757f3fSDimitry Andric     auto Range = GetRange(Inst.getOperand(0));
1405f757f3fSDimitry Andric     if (Range.isAllNonNegative()) {
1415f757f3fSDimitry Andric       Inst.setNonNeg();
1425f757f3fSDimitry Andric       Changed = true;
1435f757f3fSDimitry Andric     }
144*0fca6ea1SDimitry Andric   } else if (TruncInst *TI = dyn_cast<TruncInst>(&Inst)) {
145*0fca6ea1SDimitry Andric     if (TI->hasNoSignedWrap() && TI->hasNoUnsignedWrap())
146*0fca6ea1SDimitry Andric       return false;
147*0fca6ea1SDimitry Andric 
148*0fca6ea1SDimitry Andric     auto Range = GetRange(Inst.getOperand(0));
149*0fca6ea1SDimitry Andric     uint64_t DestWidth = TI->getDestTy()->getScalarSizeInBits();
150*0fca6ea1SDimitry Andric     if (!TI->hasNoUnsignedWrap()) {
151*0fca6ea1SDimitry Andric       if (Range.getActiveBits() <= DestWidth) {
152*0fca6ea1SDimitry Andric         TI->setHasNoUnsignedWrap(true);
153*0fca6ea1SDimitry Andric         Changed = true;
154*0fca6ea1SDimitry Andric       }
155*0fca6ea1SDimitry Andric     }
156*0fca6ea1SDimitry Andric     if (!TI->hasNoSignedWrap()) {
157*0fca6ea1SDimitry Andric       if (Range.getMinSignedBits() <= DestWidth) {
158*0fca6ea1SDimitry Andric         TI->setHasNoSignedWrap(true);
159*0fca6ea1SDimitry Andric         Changed = true;
160*0fca6ea1SDimitry Andric       }
161*0fca6ea1SDimitry Andric     }
1625f757f3fSDimitry Andric   }
16306c3fb27SDimitry Andric 
16406c3fb27SDimitry Andric   return Changed;
16506c3fb27SDimitry Andric }
16606c3fb27SDimitry Andric 
167bdd1243dSDimitry Andric /// Try to replace signed instructions with their unsigned equivalent.
168bdd1243dSDimitry Andric static bool replaceSignedInst(SCCPSolver &Solver,
169bdd1243dSDimitry Andric                               SmallPtrSetImpl<Value *> &InsertedValues,
170bdd1243dSDimitry Andric                               Instruction &Inst) {
171bdd1243dSDimitry Andric   // Determine if a signed value is known to be >= 0.
172bdd1243dSDimitry Andric   auto isNonNegative = [&Solver](Value *V) {
173bdd1243dSDimitry Andric     // If this value was constant-folded, it may not have a solver entry.
174bdd1243dSDimitry Andric     // Handle integers. Otherwise, return false.
175bdd1243dSDimitry Andric     if (auto *C = dyn_cast<Constant>(V)) {
176bdd1243dSDimitry Andric       auto *CInt = dyn_cast<ConstantInt>(C);
177bdd1243dSDimitry Andric       return CInt && !CInt->isNegative();
178bdd1243dSDimitry Andric     }
179bdd1243dSDimitry Andric     const ValueLatticeElement &IV = Solver.getLatticeValueFor(V);
180bdd1243dSDimitry Andric     return IV.isConstantRange(/*UndefAllowed=*/false) &&
181bdd1243dSDimitry Andric            IV.getConstantRange().isAllNonNegative();
182bdd1243dSDimitry Andric   };
183bdd1243dSDimitry Andric 
184bdd1243dSDimitry Andric   Instruction *NewInst = nullptr;
185bdd1243dSDimitry Andric   switch (Inst.getOpcode()) {
186*0fca6ea1SDimitry Andric   case Instruction::SIToFP:
187bdd1243dSDimitry Andric   case Instruction::SExt: {
188*0fca6ea1SDimitry Andric     // If the source value is not negative, this is a zext/uitofp.
189bdd1243dSDimitry Andric     Value *Op0 = Inst.getOperand(0);
190bdd1243dSDimitry Andric     if (InsertedValues.count(Op0) || !isNonNegative(Op0))
191bdd1243dSDimitry Andric       return false;
192*0fca6ea1SDimitry Andric     NewInst = CastInst::Create(Inst.getOpcode() == Instruction::SExt
193*0fca6ea1SDimitry Andric                                    ? Instruction::ZExt
194*0fca6ea1SDimitry Andric                                    : Instruction::UIToFP,
195*0fca6ea1SDimitry Andric                                Op0, Inst.getType(), "", Inst.getIterator());
1965f757f3fSDimitry Andric     NewInst->setNonNeg();
197bdd1243dSDimitry Andric     break;
198bdd1243dSDimitry Andric   }
199bdd1243dSDimitry Andric   case Instruction::AShr: {
200bdd1243dSDimitry Andric     // If the shifted value is not negative, this is a logical shift right.
201bdd1243dSDimitry Andric     Value *Op0 = Inst.getOperand(0);
202bdd1243dSDimitry Andric     if (InsertedValues.count(Op0) || !isNonNegative(Op0))
203bdd1243dSDimitry Andric       return false;
204*0fca6ea1SDimitry Andric     NewInst = BinaryOperator::CreateLShr(Op0, Inst.getOperand(1), "", Inst.getIterator());
2055f757f3fSDimitry Andric     NewInst->setIsExact(Inst.isExact());
206bdd1243dSDimitry Andric     break;
207bdd1243dSDimitry Andric   }
208bdd1243dSDimitry Andric   case Instruction::SDiv:
209bdd1243dSDimitry Andric   case Instruction::SRem: {
210bdd1243dSDimitry Andric     // If both operands are not negative, this is the same as udiv/urem.
211bdd1243dSDimitry Andric     Value *Op0 = Inst.getOperand(0), *Op1 = Inst.getOperand(1);
212bdd1243dSDimitry Andric     if (InsertedValues.count(Op0) || InsertedValues.count(Op1) ||
213bdd1243dSDimitry Andric         !isNonNegative(Op0) || !isNonNegative(Op1))
214bdd1243dSDimitry Andric       return false;
215bdd1243dSDimitry Andric     auto NewOpcode = Inst.getOpcode() == Instruction::SDiv ? Instruction::UDiv
216bdd1243dSDimitry Andric                                                            : Instruction::URem;
217*0fca6ea1SDimitry Andric     NewInst = BinaryOperator::Create(NewOpcode, Op0, Op1, "", Inst.getIterator());
2185f757f3fSDimitry Andric     if (Inst.getOpcode() == Instruction::SDiv)
2195f757f3fSDimitry Andric       NewInst->setIsExact(Inst.isExact());
220bdd1243dSDimitry Andric     break;
221bdd1243dSDimitry Andric   }
222bdd1243dSDimitry Andric   default:
223bdd1243dSDimitry Andric     return false;
224bdd1243dSDimitry Andric   }
225bdd1243dSDimitry Andric 
226bdd1243dSDimitry Andric   // Wire up the new instruction and update state.
227bdd1243dSDimitry Andric   assert(NewInst && "Expected replacement instruction");
228bdd1243dSDimitry Andric   NewInst->takeName(&Inst);
229bdd1243dSDimitry Andric   InsertedValues.insert(NewInst);
230bdd1243dSDimitry Andric   Inst.replaceAllUsesWith(NewInst);
231*0fca6ea1SDimitry Andric   NewInst->setDebugLoc(Inst.getDebugLoc());
232bdd1243dSDimitry Andric   Solver.removeLatticeValueFor(&Inst);
233bdd1243dSDimitry Andric   Inst.eraseFromParent();
234bdd1243dSDimitry Andric   return true;
235bdd1243dSDimitry Andric }
236bdd1243dSDimitry Andric 
237bdd1243dSDimitry Andric bool SCCPSolver::simplifyInstsInBlock(BasicBlock &BB,
238bdd1243dSDimitry Andric                                       SmallPtrSetImpl<Value *> &InsertedValues,
239bdd1243dSDimitry Andric                                       Statistic &InstRemovedStat,
240bdd1243dSDimitry Andric                                       Statistic &InstReplacedStat) {
241bdd1243dSDimitry Andric   bool MadeChanges = false;
242bdd1243dSDimitry Andric   for (Instruction &Inst : make_early_inc_range(BB)) {
243bdd1243dSDimitry Andric     if (Inst.getType()->isVoidTy())
244bdd1243dSDimitry Andric       continue;
245bdd1243dSDimitry Andric     if (tryToReplaceWithConstant(&Inst)) {
246bdd1243dSDimitry Andric       if (canRemoveInstruction(&Inst))
247bdd1243dSDimitry Andric         Inst.eraseFromParent();
248bdd1243dSDimitry Andric 
249bdd1243dSDimitry Andric       MadeChanges = true;
250bdd1243dSDimitry Andric       ++InstRemovedStat;
251bdd1243dSDimitry Andric     } else if (replaceSignedInst(*this, InsertedValues, Inst)) {
252bdd1243dSDimitry Andric       MadeChanges = true;
253bdd1243dSDimitry Andric       ++InstReplacedStat;
25406c3fb27SDimitry Andric     } else if (refineInstruction(*this, InsertedValues, Inst)) {
25506c3fb27SDimitry Andric       MadeChanges = true;
256bdd1243dSDimitry Andric     }
257bdd1243dSDimitry Andric   }
258bdd1243dSDimitry Andric   return MadeChanges;
259bdd1243dSDimitry Andric }
260bdd1243dSDimitry Andric 
261bdd1243dSDimitry Andric bool SCCPSolver::removeNonFeasibleEdges(BasicBlock *BB, DomTreeUpdater &DTU,
262bdd1243dSDimitry Andric                                         BasicBlock *&NewUnreachableBB) const {
263bdd1243dSDimitry Andric   SmallPtrSet<BasicBlock *, 8> FeasibleSuccessors;
264bdd1243dSDimitry Andric   bool HasNonFeasibleEdges = false;
265bdd1243dSDimitry Andric   for (BasicBlock *Succ : successors(BB)) {
266bdd1243dSDimitry Andric     if (isEdgeFeasible(BB, Succ))
267bdd1243dSDimitry Andric       FeasibleSuccessors.insert(Succ);
268bdd1243dSDimitry Andric     else
269bdd1243dSDimitry Andric       HasNonFeasibleEdges = true;
270bdd1243dSDimitry Andric   }
271bdd1243dSDimitry Andric 
272bdd1243dSDimitry Andric   // All edges feasible, nothing to do.
273bdd1243dSDimitry Andric   if (!HasNonFeasibleEdges)
274bdd1243dSDimitry Andric     return false;
275bdd1243dSDimitry Andric 
276bdd1243dSDimitry Andric   // SCCP can only determine non-feasible edges for br, switch and indirectbr.
277bdd1243dSDimitry Andric   Instruction *TI = BB->getTerminator();
278bdd1243dSDimitry Andric   assert((isa<BranchInst>(TI) || isa<SwitchInst>(TI) ||
279bdd1243dSDimitry Andric           isa<IndirectBrInst>(TI)) &&
280bdd1243dSDimitry Andric          "Terminator must be a br, switch or indirectbr");
281bdd1243dSDimitry Andric 
282bdd1243dSDimitry Andric   if (FeasibleSuccessors.size() == 0) {
283bdd1243dSDimitry Andric     // Branch on undef/poison, replace with unreachable.
284bdd1243dSDimitry Andric     SmallPtrSet<BasicBlock *, 8> SeenSuccs;
285bdd1243dSDimitry Andric     SmallVector<DominatorTree::UpdateType, 8> Updates;
286bdd1243dSDimitry Andric     for (BasicBlock *Succ : successors(BB)) {
287bdd1243dSDimitry Andric       Succ->removePredecessor(BB);
288bdd1243dSDimitry Andric       if (SeenSuccs.insert(Succ).second)
289bdd1243dSDimitry Andric         Updates.push_back({DominatorTree::Delete, BB, Succ});
290bdd1243dSDimitry Andric     }
291bdd1243dSDimitry Andric     TI->eraseFromParent();
292bdd1243dSDimitry Andric     new UnreachableInst(BB->getContext(), BB);
293bdd1243dSDimitry Andric     DTU.applyUpdatesPermissive(Updates);
294bdd1243dSDimitry Andric   } else if (FeasibleSuccessors.size() == 1) {
295bdd1243dSDimitry Andric     // Replace with an unconditional branch to the only feasible successor.
296bdd1243dSDimitry Andric     BasicBlock *OnlyFeasibleSuccessor = *FeasibleSuccessors.begin();
297bdd1243dSDimitry Andric     SmallVector<DominatorTree::UpdateType, 8> Updates;
298bdd1243dSDimitry Andric     bool HaveSeenOnlyFeasibleSuccessor = false;
299bdd1243dSDimitry Andric     for (BasicBlock *Succ : successors(BB)) {
300bdd1243dSDimitry Andric       if (Succ == OnlyFeasibleSuccessor && !HaveSeenOnlyFeasibleSuccessor) {
301bdd1243dSDimitry Andric         // Don't remove the edge to the only feasible successor the first time
302bdd1243dSDimitry Andric         // we see it. We still do need to remove any multi-edges to it though.
303bdd1243dSDimitry Andric         HaveSeenOnlyFeasibleSuccessor = true;
304bdd1243dSDimitry Andric         continue;
305bdd1243dSDimitry Andric       }
306bdd1243dSDimitry Andric 
307bdd1243dSDimitry Andric       Succ->removePredecessor(BB);
308bdd1243dSDimitry Andric       Updates.push_back({DominatorTree::Delete, BB, Succ});
309bdd1243dSDimitry Andric     }
310bdd1243dSDimitry Andric 
311*0fca6ea1SDimitry Andric     Instruction *BI = BranchInst::Create(OnlyFeasibleSuccessor, BB);
312*0fca6ea1SDimitry Andric     BI->setDebugLoc(TI->getDebugLoc());
313bdd1243dSDimitry Andric     TI->eraseFromParent();
314bdd1243dSDimitry Andric     DTU.applyUpdatesPermissive(Updates);
315bdd1243dSDimitry Andric   } else if (FeasibleSuccessors.size() > 1) {
316bdd1243dSDimitry Andric     SwitchInstProfUpdateWrapper SI(*cast<SwitchInst>(TI));
317bdd1243dSDimitry Andric     SmallVector<DominatorTree::UpdateType, 8> Updates;
318bdd1243dSDimitry Andric 
319bdd1243dSDimitry Andric     // If the default destination is unfeasible it will never be taken. Replace
320bdd1243dSDimitry Andric     // it with a new block with a single Unreachable instruction.
321bdd1243dSDimitry Andric     BasicBlock *DefaultDest = SI->getDefaultDest();
322bdd1243dSDimitry Andric     if (!FeasibleSuccessors.contains(DefaultDest)) {
323bdd1243dSDimitry Andric       if (!NewUnreachableBB) {
324bdd1243dSDimitry Andric         NewUnreachableBB =
325bdd1243dSDimitry Andric             BasicBlock::Create(DefaultDest->getContext(), "default.unreachable",
326bdd1243dSDimitry Andric                                DefaultDest->getParent(), DefaultDest);
327bdd1243dSDimitry Andric         new UnreachableInst(DefaultDest->getContext(), NewUnreachableBB);
328bdd1243dSDimitry Andric       }
329bdd1243dSDimitry Andric 
3301db9f3b2SDimitry Andric       DefaultDest->removePredecessor(BB);
331bdd1243dSDimitry Andric       SI->setDefaultDest(NewUnreachableBB);
332bdd1243dSDimitry Andric       Updates.push_back({DominatorTree::Delete, BB, DefaultDest});
333bdd1243dSDimitry Andric       Updates.push_back({DominatorTree::Insert, BB, NewUnreachableBB});
334bdd1243dSDimitry Andric     }
335bdd1243dSDimitry Andric 
336bdd1243dSDimitry Andric     for (auto CI = SI->case_begin(); CI != SI->case_end();) {
337bdd1243dSDimitry Andric       if (FeasibleSuccessors.contains(CI->getCaseSuccessor())) {
338bdd1243dSDimitry Andric         ++CI;
339bdd1243dSDimitry Andric         continue;
340bdd1243dSDimitry Andric       }
341bdd1243dSDimitry Andric 
342bdd1243dSDimitry Andric       BasicBlock *Succ = CI->getCaseSuccessor();
343bdd1243dSDimitry Andric       Succ->removePredecessor(BB);
344bdd1243dSDimitry Andric       Updates.push_back({DominatorTree::Delete, BB, Succ});
345bdd1243dSDimitry Andric       SI.removeCase(CI);
346bdd1243dSDimitry Andric       // Don't increment CI, as we removed a case.
347bdd1243dSDimitry Andric     }
348bdd1243dSDimitry Andric 
349bdd1243dSDimitry Andric     DTU.applyUpdatesPermissive(Updates);
350bdd1243dSDimitry Andric   } else {
351bdd1243dSDimitry Andric     llvm_unreachable("Must have at least one feasible successor");
352bdd1243dSDimitry Andric   }
353bdd1243dSDimitry Andric   return true;
354bdd1243dSDimitry Andric }
355fe6060f1SDimitry Andric 
356fe6060f1SDimitry Andric /// Helper class for SCCPSolver. This implements the instruction visitor and
357fe6060f1SDimitry Andric /// holds all the state.
358fe6060f1SDimitry Andric class SCCPInstVisitor : public InstVisitor<SCCPInstVisitor> {
359fe6060f1SDimitry Andric   const DataLayout &DL;
360fe6060f1SDimitry Andric   std::function<const TargetLibraryInfo &(Function &)> GetTLI;
361fe6060f1SDimitry Andric   SmallPtrSet<BasicBlock *, 8> BBExecutable; // The BBs that are executable.
362fe6060f1SDimitry Andric   DenseMap<Value *, ValueLatticeElement>
363fe6060f1SDimitry Andric       ValueState; // The state each value is in.
364fe6060f1SDimitry Andric 
365fe6060f1SDimitry Andric   /// StructValueState - This maintains ValueState for values that have
366fe6060f1SDimitry Andric   /// StructType, for example for formal arguments, calls, insertelement, etc.
367fe6060f1SDimitry Andric   DenseMap<std::pair<Value *, unsigned>, ValueLatticeElement> StructValueState;
368fe6060f1SDimitry Andric 
369fe6060f1SDimitry Andric   /// GlobalValue - If we are tracking any values for the contents of a global
370fe6060f1SDimitry Andric   /// variable, we keep a mapping from the constant accessor to the element of
371fe6060f1SDimitry Andric   /// the global, to the currently known value.  If the value becomes
372fe6060f1SDimitry Andric   /// overdefined, it's entry is simply removed from this map.
373fe6060f1SDimitry Andric   DenseMap<GlobalVariable *, ValueLatticeElement> TrackedGlobals;
374fe6060f1SDimitry Andric 
375fe6060f1SDimitry Andric   /// TrackedRetVals - If we are tracking arguments into and the return
376fe6060f1SDimitry Andric   /// value out of a function, it will have an entry in this map, indicating
377fe6060f1SDimitry Andric   /// what the known return value for the function is.
378fe6060f1SDimitry Andric   MapVector<Function *, ValueLatticeElement> TrackedRetVals;
379fe6060f1SDimitry Andric 
380fe6060f1SDimitry Andric   /// TrackedMultipleRetVals - Same as TrackedRetVals, but used for functions
381fe6060f1SDimitry Andric   /// that return multiple values.
382fe6060f1SDimitry Andric   MapVector<std::pair<Function *, unsigned>, ValueLatticeElement>
383fe6060f1SDimitry Andric       TrackedMultipleRetVals;
384fe6060f1SDimitry Andric 
38506c3fb27SDimitry Andric   /// The set of values whose lattice has been invalidated.
38606c3fb27SDimitry Andric   /// Populated by resetLatticeValueFor(), cleared after resolving undefs.
38706c3fb27SDimitry Andric   DenseSet<Value *> Invalidated;
38806c3fb27SDimitry Andric 
389fe6060f1SDimitry Andric   /// MRVFunctionsTracked - Each function in TrackedMultipleRetVals is
390fe6060f1SDimitry Andric   /// represented here for efficient lookup.
391fe6060f1SDimitry Andric   SmallPtrSet<Function *, 16> MRVFunctionsTracked;
392fe6060f1SDimitry Andric 
393fe6060f1SDimitry Andric   /// A list of functions whose return cannot be modified.
394fe6060f1SDimitry Andric   SmallPtrSet<Function *, 16> MustPreserveReturnsInFunctions;
395fe6060f1SDimitry Andric 
396fe6060f1SDimitry Andric   /// TrackingIncomingArguments - This is the set of functions for whose
397fe6060f1SDimitry Andric   /// arguments we make optimistic assumptions about and try to prove as
398fe6060f1SDimitry Andric   /// constants.
399fe6060f1SDimitry Andric   SmallPtrSet<Function *, 16> TrackingIncomingArguments;
400fe6060f1SDimitry Andric 
401fe6060f1SDimitry Andric   /// The reason for two worklists is that overdefined is the lowest state
402fe6060f1SDimitry Andric   /// on the lattice, and moving things to overdefined as fast as possible
403fe6060f1SDimitry Andric   /// makes SCCP converge much faster.
404fe6060f1SDimitry Andric   ///
405fe6060f1SDimitry Andric   /// By having a separate worklist, we accomplish this because everything
406fe6060f1SDimitry Andric   /// possibly overdefined will become overdefined at the soonest possible
407fe6060f1SDimitry Andric   /// point.
408fe6060f1SDimitry Andric   SmallVector<Value *, 64> OverdefinedInstWorkList;
409fe6060f1SDimitry Andric   SmallVector<Value *, 64> InstWorkList;
410fe6060f1SDimitry Andric 
411fe6060f1SDimitry Andric   // The BasicBlock work list
412fe6060f1SDimitry Andric   SmallVector<BasicBlock *, 64> BBWorkList;
413fe6060f1SDimitry Andric 
414fe6060f1SDimitry Andric   /// KnownFeasibleEdges - Entries in this set are edges which have already had
415fe6060f1SDimitry Andric   /// PHI nodes retriggered.
416fe6060f1SDimitry Andric   using Edge = std::pair<BasicBlock *, BasicBlock *>;
417fe6060f1SDimitry Andric   DenseSet<Edge> KnownFeasibleEdges;
418fe6060f1SDimitry Andric 
41906c3fb27SDimitry Andric   DenseMap<Function *, std::unique_ptr<PredicateInfo>> FnPredicateInfo;
42006c3fb27SDimitry Andric 
421fe6060f1SDimitry Andric   DenseMap<Value *, SmallPtrSet<User *, 2>> AdditionalUsers;
422fe6060f1SDimitry Andric 
423fe6060f1SDimitry Andric   LLVMContext &Ctx;
424fe6060f1SDimitry Andric 
425fe6060f1SDimitry Andric private:
42606c3fb27SDimitry Andric   ConstantInt *getConstantInt(const ValueLatticeElement &IV, Type *Ty) const {
42706c3fb27SDimitry Andric     return dyn_cast_or_null<ConstantInt>(getConstant(IV, Ty));
428fe6060f1SDimitry Andric   }
429fe6060f1SDimitry Andric 
430fe6060f1SDimitry Andric   // pushToWorkList - Helper for markConstant/markOverdefined
431fe6060f1SDimitry Andric   void pushToWorkList(ValueLatticeElement &IV, Value *V);
432fe6060f1SDimitry Andric 
433fe6060f1SDimitry Andric   // Helper to push \p V to the worklist, after updating it to \p IV. Also
434fe6060f1SDimitry Andric   // prints a debug message with the updated value.
435fe6060f1SDimitry Andric   void pushToWorkListMsg(ValueLatticeElement &IV, Value *V);
436fe6060f1SDimitry Andric 
437fe6060f1SDimitry Andric   // markConstant - Make a value be marked as "constant".  If the value
438fe6060f1SDimitry Andric   // is not already a constant, add it to the instruction work list so that
439fe6060f1SDimitry Andric   // the users of the instruction are updated later.
440fe6060f1SDimitry Andric   bool markConstant(ValueLatticeElement &IV, Value *V, Constant *C,
441fe6060f1SDimitry Andric                     bool MayIncludeUndef = false);
442fe6060f1SDimitry Andric 
443fe6060f1SDimitry Andric   bool markConstant(Value *V, Constant *C) {
444fe6060f1SDimitry Andric     assert(!V->getType()->isStructTy() && "structs should use mergeInValue");
445fe6060f1SDimitry Andric     return markConstant(ValueState[V], V, C);
446fe6060f1SDimitry Andric   }
447fe6060f1SDimitry Andric 
448*0fca6ea1SDimitry Andric   /// markConstantRange - Mark the object as constant range with \p CR. If the
449*0fca6ea1SDimitry Andric   /// object is not a constant range with the range \p CR, add it to the
450*0fca6ea1SDimitry Andric   /// instruction work list so that the users of the instruction are updated
451*0fca6ea1SDimitry Andric   /// later.
452*0fca6ea1SDimitry Andric   bool markConstantRange(ValueLatticeElement &IV, Value *V,
453*0fca6ea1SDimitry Andric                          const ConstantRange &CR);
454*0fca6ea1SDimitry Andric 
455fe6060f1SDimitry Andric   // markOverdefined - Make a value be marked as "overdefined". If the
456fe6060f1SDimitry Andric   // value is not already overdefined, add it to the overdefined instruction
457fe6060f1SDimitry Andric   // work list so that the users of the instruction are updated later.
458fe6060f1SDimitry Andric   bool markOverdefined(ValueLatticeElement &IV, Value *V);
459fe6060f1SDimitry Andric 
460fe6060f1SDimitry Andric   /// Merge \p MergeWithV into \p IV and push \p V to the worklist, if \p IV
461fe6060f1SDimitry Andric   /// changes.
462fe6060f1SDimitry Andric   bool mergeInValue(ValueLatticeElement &IV, Value *V,
463fe6060f1SDimitry Andric                     ValueLatticeElement MergeWithV,
464fe6060f1SDimitry Andric                     ValueLatticeElement::MergeOptions Opts = {
465fe6060f1SDimitry Andric                         /*MayIncludeUndef=*/false, /*CheckWiden=*/false});
466fe6060f1SDimitry Andric 
467fe6060f1SDimitry Andric   bool mergeInValue(Value *V, ValueLatticeElement MergeWithV,
468fe6060f1SDimitry Andric                     ValueLatticeElement::MergeOptions Opts = {
469fe6060f1SDimitry Andric                         /*MayIncludeUndef=*/false, /*CheckWiden=*/false}) {
470fe6060f1SDimitry Andric     assert(!V->getType()->isStructTy() &&
471fe6060f1SDimitry Andric            "non-structs should use markConstant");
472fe6060f1SDimitry Andric     return mergeInValue(ValueState[V], V, MergeWithV, Opts);
473fe6060f1SDimitry Andric   }
474fe6060f1SDimitry Andric 
475fe6060f1SDimitry Andric   /// getValueState - Return the ValueLatticeElement object that corresponds to
476fe6060f1SDimitry Andric   /// the value.  This function handles the case when the value hasn't been seen
477fe6060f1SDimitry Andric   /// yet by properly seeding constants etc.
478fe6060f1SDimitry Andric   ValueLatticeElement &getValueState(Value *V) {
479fe6060f1SDimitry Andric     assert(!V->getType()->isStructTy() && "Should use getStructValueState");
480fe6060f1SDimitry Andric 
481fe6060f1SDimitry Andric     auto I = ValueState.insert(std::make_pair(V, ValueLatticeElement()));
482fe6060f1SDimitry Andric     ValueLatticeElement &LV = I.first->second;
483fe6060f1SDimitry Andric 
484fe6060f1SDimitry Andric     if (!I.second)
485fe6060f1SDimitry Andric       return LV; // Common case, already in the map.
486fe6060f1SDimitry Andric 
487fe6060f1SDimitry Andric     if (auto *C = dyn_cast<Constant>(V))
488fe6060f1SDimitry Andric       LV.markConstant(C); // Constants are constant
489fe6060f1SDimitry Andric 
490fe6060f1SDimitry Andric     // All others are unknown by default.
491fe6060f1SDimitry Andric     return LV;
492fe6060f1SDimitry Andric   }
493fe6060f1SDimitry Andric 
494fe6060f1SDimitry Andric   /// getStructValueState - Return the ValueLatticeElement object that
495fe6060f1SDimitry Andric   /// corresponds to the value/field pair.  This function handles the case when
496fe6060f1SDimitry Andric   /// the value hasn't been seen yet by properly seeding constants etc.
497fe6060f1SDimitry Andric   ValueLatticeElement &getStructValueState(Value *V, unsigned i) {
498fe6060f1SDimitry Andric     assert(V->getType()->isStructTy() && "Should use getValueState");
499fe6060f1SDimitry Andric     assert(i < cast<StructType>(V->getType())->getNumElements() &&
500fe6060f1SDimitry Andric            "Invalid element #");
501fe6060f1SDimitry Andric 
502fe6060f1SDimitry Andric     auto I = StructValueState.insert(
503fe6060f1SDimitry Andric         std::make_pair(std::make_pair(V, i), ValueLatticeElement()));
504fe6060f1SDimitry Andric     ValueLatticeElement &LV = I.first->second;
505fe6060f1SDimitry Andric 
506fe6060f1SDimitry Andric     if (!I.second)
507fe6060f1SDimitry Andric       return LV; // Common case, already in the map.
508fe6060f1SDimitry Andric 
509fe6060f1SDimitry Andric     if (auto *C = dyn_cast<Constant>(V)) {
510fe6060f1SDimitry Andric       Constant *Elt = C->getAggregateElement(i);
511fe6060f1SDimitry Andric 
512fe6060f1SDimitry Andric       if (!Elt)
513fe6060f1SDimitry Andric         LV.markOverdefined(); // Unknown sort of constant.
514fe6060f1SDimitry Andric       else
515fe6060f1SDimitry Andric         LV.markConstant(Elt); // Constants are constant.
516fe6060f1SDimitry Andric     }
517fe6060f1SDimitry Andric 
518fe6060f1SDimitry Andric     // All others are underdefined by default.
519fe6060f1SDimitry Andric     return LV;
520fe6060f1SDimitry Andric   }
521fe6060f1SDimitry Andric 
52206c3fb27SDimitry Andric   /// Traverse the use-def chain of \p Call, marking itself and its users as
52306c3fb27SDimitry Andric   /// "unknown" on the way.
52406c3fb27SDimitry Andric   void invalidate(CallBase *Call) {
52506c3fb27SDimitry Andric     SmallVector<Instruction *, 64> ToInvalidate;
52606c3fb27SDimitry Andric     ToInvalidate.push_back(Call);
52706c3fb27SDimitry Andric 
52806c3fb27SDimitry Andric     while (!ToInvalidate.empty()) {
52906c3fb27SDimitry Andric       Instruction *Inst = ToInvalidate.pop_back_val();
53006c3fb27SDimitry Andric 
53106c3fb27SDimitry Andric       if (!Invalidated.insert(Inst).second)
53206c3fb27SDimitry Andric         continue;
53306c3fb27SDimitry Andric 
53406c3fb27SDimitry Andric       if (!BBExecutable.count(Inst->getParent()))
53506c3fb27SDimitry Andric         continue;
53606c3fb27SDimitry Andric 
53706c3fb27SDimitry Andric       Value *V = nullptr;
53806c3fb27SDimitry Andric       // For return instructions we need to invalidate the tracked returns map.
53906c3fb27SDimitry Andric       // Anything else has its lattice in the value map.
54006c3fb27SDimitry Andric       if (auto *RetInst = dyn_cast<ReturnInst>(Inst)) {
54106c3fb27SDimitry Andric         Function *F = RetInst->getParent()->getParent();
54206c3fb27SDimitry Andric         if (auto It = TrackedRetVals.find(F); It != TrackedRetVals.end()) {
54306c3fb27SDimitry Andric           It->second = ValueLatticeElement();
54406c3fb27SDimitry Andric           V = F;
54506c3fb27SDimitry Andric         } else if (MRVFunctionsTracked.count(F)) {
54606c3fb27SDimitry Andric           auto *STy = cast<StructType>(F->getReturnType());
54706c3fb27SDimitry Andric           for (unsigned I = 0, E = STy->getNumElements(); I != E; ++I)
54806c3fb27SDimitry Andric             TrackedMultipleRetVals[{F, I}] = ValueLatticeElement();
54906c3fb27SDimitry Andric           V = F;
55006c3fb27SDimitry Andric         }
55106c3fb27SDimitry Andric       } else if (auto *STy = dyn_cast<StructType>(Inst->getType())) {
55206c3fb27SDimitry Andric         for (unsigned I = 0, E = STy->getNumElements(); I != E; ++I) {
55306c3fb27SDimitry Andric           if (auto It = StructValueState.find({Inst, I});
55406c3fb27SDimitry Andric               It != StructValueState.end()) {
55506c3fb27SDimitry Andric             It->second = ValueLatticeElement();
55606c3fb27SDimitry Andric             V = Inst;
55706c3fb27SDimitry Andric           }
55806c3fb27SDimitry Andric         }
55906c3fb27SDimitry Andric       } else if (auto It = ValueState.find(Inst); It != ValueState.end()) {
56006c3fb27SDimitry Andric         It->second = ValueLatticeElement();
56106c3fb27SDimitry Andric         V = Inst;
56206c3fb27SDimitry Andric       }
56306c3fb27SDimitry Andric 
56406c3fb27SDimitry Andric       if (V) {
56506c3fb27SDimitry Andric         LLVM_DEBUG(dbgs() << "Invalidated lattice for " << *V << "\n");
56606c3fb27SDimitry Andric 
56706c3fb27SDimitry Andric         for (User *U : V->users())
56806c3fb27SDimitry Andric           if (auto *UI = dyn_cast<Instruction>(U))
56906c3fb27SDimitry Andric             ToInvalidate.push_back(UI);
57006c3fb27SDimitry Andric 
57106c3fb27SDimitry Andric         auto It = AdditionalUsers.find(V);
57206c3fb27SDimitry Andric         if (It != AdditionalUsers.end())
57306c3fb27SDimitry Andric           for (User *U : It->second)
57406c3fb27SDimitry Andric             if (auto *UI = dyn_cast<Instruction>(U))
57506c3fb27SDimitry Andric               ToInvalidate.push_back(UI);
57606c3fb27SDimitry Andric       }
57706c3fb27SDimitry Andric     }
57806c3fb27SDimitry Andric   }
57906c3fb27SDimitry Andric 
580fe6060f1SDimitry Andric   /// markEdgeExecutable - Mark a basic block as executable, adding it to the BB
581fe6060f1SDimitry Andric   /// work list if it is not already executable.
582fe6060f1SDimitry Andric   bool markEdgeExecutable(BasicBlock *Source, BasicBlock *Dest);
583fe6060f1SDimitry Andric 
584fe6060f1SDimitry Andric   // getFeasibleSuccessors - Return a vector of booleans to indicate which
585fe6060f1SDimitry Andric   // successors are reachable from a given terminator instruction.
586fe6060f1SDimitry Andric   void getFeasibleSuccessors(Instruction &TI, SmallVectorImpl<bool> &Succs);
587fe6060f1SDimitry Andric 
588fe6060f1SDimitry Andric   // OperandChangedState - This method is invoked on all of the users of an
589fe6060f1SDimitry Andric   // instruction that was just changed state somehow.  Based on this
590fe6060f1SDimitry Andric   // information, we need to update the specified user of this instruction.
591fe6060f1SDimitry Andric   void operandChangedState(Instruction *I) {
592fe6060f1SDimitry Andric     if (BBExecutable.count(I->getParent())) // Inst is executable?
593fe6060f1SDimitry Andric       visit(*I);
594fe6060f1SDimitry Andric   }
595fe6060f1SDimitry Andric 
596fe6060f1SDimitry Andric   // Add U as additional user of V.
597fe6060f1SDimitry Andric   void addAdditionalUser(Value *V, User *U) {
598fe6060f1SDimitry Andric     auto Iter = AdditionalUsers.insert({V, {}});
599fe6060f1SDimitry Andric     Iter.first->second.insert(U);
600fe6060f1SDimitry Andric   }
601fe6060f1SDimitry Andric 
602fe6060f1SDimitry Andric   // Mark I's users as changed, including AdditionalUsers.
603fe6060f1SDimitry Andric   void markUsersAsChanged(Value *I) {
604fe6060f1SDimitry Andric     // Functions include their arguments in the use-list. Changed function
605fe6060f1SDimitry Andric     // values mean that the result of the function changed. We only need to
606fe6060f1SDimitry Andric     // update the call sites with the new function result and do not have to
607fe6060f1SDimitry Andric     // propagate the call arguments.
608fe6060f1SDimitry Andric     if (isa<Function>(I)) {
609fe6060f1SDimitry Andric       for (User *U : I->users()) {
610fe6060f1SDimitry Andric         if (auto *CB = dyn_cast<CallBase>(U))
611fe6060f1SDimitry Andric           handleCallResult(*CB);
612fe6060f1SDimitry Andric       }
613fe6060f1SDimitry Andric     } else {
614fe6060f1SDimitry Andric       for (User *U : I->users())
615fe6060f1SDimitry Andric         if (auto *UI = dyn_cast<Instruction>(U))
616fe6060f1SDimitry Andric           operandChangedState(UI);
617fe6060f1SDimitry Andric     }
618fe6060f1SDimitry Andric 
619fe6060f1SDimitry Andric     auto Iter = AdditionalUsers.find(I);
620fe6060f1SDimitry Andric     if (Iter != AdditionalUsers.end()) {
621fe6060f1SDimitry Andric       // Copy additional users before notifying them of changes, because new
622fe6060f1SDimitry Andric       // users may be added, potentially invalidating the iterator.
623fe6060f1SDimitry Andric       SmallVector<Instruction *, 2> ToNotify;
624fe6060f1SDimitry Andric       for (User *U : Iter->second)
625fe6060f1SDimitry Andric         if (auto *UI = dyn_cast<Instruction>(U))
626fe6060f1SDimitry Andric           ToNotify.push_back(UI);
627fe6060f1SDimitry Andric       for (Instruction *UI : ToNotify)
628fe6060f1SDimitry Andric         operandChangedState(UI);
629fe6060f1SDimitry Andric     }
630fe6060f1SDimitry Andric   }
631fe6060f1SDimitry Andric   void handleCallOverdefined(CallBase &CB);
632fe6060f1SDimitry Andric   void handleCallResult(CallBase &CB);
633fe6060f1SDimitry Andric   void handleCallArguments(CallBase &CB);
634bdd1243dSDimitry Andric   void handleExtractOfWithOverflow(ExtractValueInst &EVI,
635bdd1243dSDimitry Andric                                    const WithOverflowInst *WO, unsigned Idx);
636fe6060f1SDimitry Andric 
637fe6060f1SDimitry Andric private:
638fe6060f1SDimitry Andric   friend class InstVisitor<SCCPInstVisitor>;
639fe6060f1SDimitry Andric 
640fe6060f1SDimitry Andric   // visit implementations - Something changed in this instruction.  Either an
641fe6060f1SDimitry Andric   // operand made a transition, or the instruction is newly executable.  Change
642fe6060f1SDimitry Andric   // the value type of I to reflect these changes if appropriate.
643fe6060f1SDimitry Andric   void visitPHINode(PHINode &I);
644fe6060f1SDimitry Andric 
645fe6060f1SDimitry Andric   // Terminators
646fe6060f1SDimitry Andric 
647fe6060f1SDimitry Andric   void visitReturnInst(ReturnInst &I);
648fe6060f1SDimitry Andric   void visitTerminator(Instruction &TI);
649fe6060f1SDimitry Andric 
650fe6060f1SDimitry Andric   void visitCastInst(CastInst &I);
651fe6060f1SDimitry Andric   void visitSelectInst(SelectInst &I);
652fe6060f1SDimitry Andric   void visitUnaryOperator(Instruction &I);
65306c3fb27SDimitry Andric   void visitFreezeInst(FreezeInst &I);
654fe6060f1SDimitry Andric   void visitBinaryOperator(Instruction &I);
655fe6060f1SDimitry Andric   void visitCmpInst(CmpInst &I);
656fe6060f1SDimitry Andric   void visitExtractValueInst(ExtractValueInst &EVI);
657fe6060f1SDimitry Andric   void visitInsertValueInst(InsertValueInst &IVI);
658fe6060f1SDimitry Andric 
659fe6060f1SDimitry Andric   void visitCatchSwitchInst(CatchSwitchInst &CPI) {
660fe6060f1SDimitry Andric     markOverdefined(&CPI);
661fe6060f1SDimitry Andric     visitTerminator(CPI);
662fe6060f1SDimitry Andric   }
663fe6060f1SDimitry Andric 
664fe6060f1SDimitry Andric   // Instructions that cannot be folded away.
665fe6060f1SDimitry Andric 
666fe6060f1SDimitry Andric   void visitStoreInst(StoreInst &I);
667fe6060f1SDimitry Andric   void visitLoadInst(LoadInst &I);
668fe6060f1SDimitry Andric   void visitGetElementPtrInst(GetElementPtrInst &I);
669fe6060f1SDimitry Andric 
670fe6060f1SDimitry Andric   void visitInvokeInst(InvokeInst &II) {
671fe6060f1SDimitry Andric     visitCallBase(II);
672fe6060f1SDimitry Andric     visitTerminator(II);
673fe6060f1SDimitry Andric   }
674fe6060f1SDimitry Andric 
675fe6060f1SDimitry Andric   void visitCallBrInst(CallBrInst &CBI) {
676fe6060f1SDimitry Andric     visitCallBase(CBI);
677fe6060f1SDimitry Andric     visitTerminator(CBI);
678fe6060f1SDimitry Andric   }
679fe6060f1SDimitry Andric 
680fe6060f1SDimitry Andric   void visitCallBase(CallBase &CB);
681fe6060f1SDimitry Andric   void visitResumeInst(ResumeInst &I) { /*returns void*/
682fe6060f1SDimitry Andric   }
683fe6060f1SDimitry Andric   void visitUnreachableInst(UnreachableInst &I) { /*returns void*/
684fe6060f1SDimitry Andric   }
685fe6060f1SDimitry Andric   void visitFenceInst(FenceInst &I) { /*returns void*/
686fe6060f1SDimitry Andric   }
687fe6060f1SDimitry Andric 
688fe6060f1SDimitry Andric   void visitInstruction(Instruction &I);
689fe6060f1SDimitry Andric 
690fe6060f1SDimitry Andric public:
69106c3fb27SDimitry Andric   void addPredicateInfo(Function &F, DominatorTree &DT, AssumptionCache &AC) {
69206c3fb27SDimitry Andric     FnPredicateInfo.insert({&F, std::make_unique<PredicateInfo>(F, DT, AC)});
693fe6060f1SDimitry Andric   }
694fe6060f1SDimitry Andric 
695fe6060f1SDimitry Andric   void visitCallInst(CallInst &I) { visitCallBase(I); }
696fe6060f1SDimitry Andric 
697fe6060f1SDimitry Andric   bool markBlockExecutable(BasicBlock *BB);
698fe6060f1SDimitry Andric 
699fe6060f1SDimitry Andric   const PredicateBase *getPredicateInfoFor(Instruction *I) {
70006c3fb27SDimitry Andric     auto It = FnPredicateInfo.find(I->getParent()->getParent());
70106c3fb27SDimitry Andric     if (It == FnPredicateInfo.end())
702fe6060f1SDimitry Andric       return nullptr;
70306c3fb27SDimitry Andric     return It->second->getPredicateInfoFor(I);
704fe6060f1SDimitry Andric   }
705fe6060f1SDimitry Andric 
706fe6060f1SDimitry Andric   SCCPInstVisitor(const DataLayout &DL,
707fe6060f1SDimitry Andric                   std::function<const TargetLibraryInfo &(Function &)> GetTLI,
708fe6060f1SDimitry Andric                   LLVMContext &Ctx)
709fe6060f1SDimitry Andric       : DL(DL), GetTLI(GetTLI), Ctx(Ctx) {}
710fe6060f1SDimitry Andric 
711fe6060f1SDimitry Andric   void trackValueOfGlobalVariable(GlobalVariable *GV) {
712fe6060f1SDimitry Andric     // We only track the contents of scalar globals.
713fe6060f1SDimitry Andric     if (GV->getValueType()->isSingleValueType()) {
714fe6060f1SDimitry Andric       ValueLatticeElement &IV = TrackedGlobals[GV];
715fe6060f1SDimitry Andric       IV.markConstant(GV->getInitializer());
716fe6060f1SDimitry Andric     }
717fe6060f1SDimitry Andric   }
718fe6060f1SDimitry Andric 
719fe6060f1SDimitry Andric   void addTrackedFunction(Function *F) {
720fe6060f1SDimitry Andric     // Add an entry, F -> undef.
721fe6060f1SDimitry Andric     if (auto *STy = dyn_cast<StructType>(F->getReturnType())) {
722fe6060f1SDimitry Andric       MRVFunctionsTracked.insert(F);
723fe6060f1SDimitry Andric       for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i)
724fe6060f1SDimitry Andric         TrackedMultipleRetVals.insert(
725fe6060f1SDimitry Andric             std::make_pair(std::make_pair(F, i), ValueLatticeElement()));
726fe6060f1SDimitry Andric     } else if (!F->getReturnType()->isVoidTy())
727fe6060f1SDimitry Andric       TrackedRetVals.insert(std::make_pair(F, ValueLatticeElement()));
728fe6060f1SDimitry Andric   }
729fe6060f1SDimitry Andric 
730fe6060f1SDimitry Andric   void addToMustPreserveReturnsInFunctions(Function *F) {
731fe6060f1SDimitry Andric     MustPreserveReturnsInFunctions.insert(F);
732fe6060f1SDimitry Andric   }
733fe6060f1SDimitry Andric 
734fe6060f1SDimitry Andric   bool mustPreserveReturn(Function *F) {
735fe6060f1SDimitry Andric     return MustPreserveReturnsInFunctions.count(F);
736fe6060f1SDimitry Andric   }
737fe6060f1SDimitry Andric 
738fe6060f1SDimitry Andric   void addArgumentTrackedFunction(Function *F) {
739fe6060f1SDimitry Andric     TrackingIncomingArguments.insert(F);
740fe6060f1SDimitry Andric   }
741fe6060f1SDimitry Andric 
742fe6060f1SDimitry Andric   bool isArgumentTrackedFunction(Function *F) {
743fe6060f1SDimitry Andric     return TrackingIncomingArguments.count(F);
744fe6060f1SDimitry Andric   }
745fe6060f1SDimitry Andric 
746fe6060f1SDimitry Andric   void solve();
747fe6060f1SDimitry Andric 
74806c3fb27SDimitry Andric   bool resolvedUndef(Instruction &I);
74906c3fb27SDimitry Andric 
750fe6060f1SDimitry Andric   bool resolvedUndefsIn(Function &F);
751fe6060f1SDimitry Andric 
752fe6060f1SDimitry Andric   bool isBlockExecutable(BasicBlock *BB) const {
753fe6060f1SDimitry Andric     return BBExecutable.count(BB);
754fe6060f1SDimitry Andric   }
755fe6060f1SDimitry Andric 
756fe6060f1SDimitry Andric   bool isEdgeFeasible(BasicBlock *From, BasicBlock *To) const;
757fe6060f1SDimitry Andric 
758fe6060f1SDimitry Andric   std::vector<ValueLatticeElement> getStructLatticeValueFor(Value *V) const {
759fe6060f1SDimitry Andric     std::vector<ValueLatticeElement> StructValues;
760fe6060f1SDimitry Andric     auto *STy = dyn_cast<StructType>(V->getType());
761fe6060f1SDimitry Andric     assert(STy && "getStructLatticeValueFor() can be called only on structs");
762fe6060f1SDimitry Andric     for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
763fe6060f1SDimitry Andric       auto I = StructValueState.find(std::make_pair(V, i));
764fe6060f1SDimitry Andric       assert(I != StructValueState.end() && "Value not in valuemap!");
765fe6060f1SDimitry Andric       StructValues.push_back(I->second);
766fe6060f1SDimitry Andric     }
767fe6060f1SDimitry Andric     return StructValues;
768fe6060f1SDimitry Andric   }
769fe6060f1SDimitry Andric 
770fe6060f1SDimitry Andric   void removeLatticeValueFor(Value *V) { ValueState.erase(V); }
771fe6060f1SDimitry Andric 
77206c3fb27SDimitry Andric   /// Invalidate the Lattice Value of \p Call and its users after specializing
77306c3fb27SDimitry Andric   /// the call. Then recompute it.
77406c3fb27SDimitry Andric   void resetLatticeValueFor(CallBase *Call) {
77506c3fb27SDimitry Andric     // Calls to void returning functions do not need invalidation.
77606c3fb27SDimitry Andric     Function *F = Call->getCalledFunction();
77706c3fb27SDimitry Andric     (void)F;
77806c3fb27SDimitry Andric     assert(!F->getReturnType()->isVoidTy() &&
77906c3fb27SDimitry Andric            (TrackedRetVals.count(F) || MRVFunctionsTracked.count(F)) &&
78006c3fb27SDimitry Andric            "All non void specializations should be tracked");
78106c3fb27SDimitry Andric     invalidate(Call);
78206c3fb27SDimitry Andric     handleCallResult(*Call);
78306c3fb27SDimitry Andric   }
78406c3fb27SDimitry Andric 
785fe6060f1SDimitry Andric   const ValueLatticeElement &getLatticeValueFor(Value *V) const {
786fe6060f1SDimitry Andric     assert(!V->getType()->isStructTy() &&
787fe6060f1SDimitry Andric            "Should use getStructLatticeValueFor");
788fe6060f1SDimitry Andric     DenseMap<Value *, ValueLatticeElement>::const_iterator I =
789fe6060f1SDimitry Andric         ValueState.find(V);
790fe6060f1SDimitry Andric     assert(I != ValueState.end() &&
791fe6060f1SDimitry Andric            "V not found in ValueState nor Paramstate map!");
792fe6060f1SDimitry Andric     return I->second;
793fe6060f1SDimitry Andric   }
794fe6060f1SDimitry Andric 
795fe6060f1SDimitry Andric   const MapVector<Function *, ValueLatticeElement> &getTrackedRetVals() {
796fe6060f1SDimitry Andric     return TrackedRetVals;
797fe6060f1SDimitry Andric   }
798fe6060f1SDimitry Andric 
799fe6060f1SDimitry Andric   const DenseMap<GlobalVariable *, ValueLatticeElement> &getTrackedGlobals() {
800fe6060f1SDimitry Andric     return TrackedGlobals;
801fe6060f1SDimitry Andric   }
802fe6060f1SDimitry Andric 
803fe6060f1SDimitry Andric   const SmallPtrSet<Function *, 16> getMRVFunctionsTracked() {
804fe6060f1SDimitry Andric     return MRVFunctionsTracked;
805fe6060f1SDimitry Andric   }
806fe6060f1SDimitry Andric 
807fe6060f1SDimitry Andric   void markOverdefined(Value *V) {
808fe6060f1SDimitry Andric     if (auto *STy = dyn_cast<StructType>(V->getType()))
809fe6060f1SDimitry Andric       for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i)
810fe6060f1SDimitry Andric         markOverdefined(getStructValueState(V, i), V);
811fe6060f1SDimitry Andric     else
812fe6060f1SDimitry Andric       markOverdefined(ValueState[V], V);
813fe6060f1SDimitry Andric   }
814fe6060f1SDimitry Andric 
815*0fca6ea1SDimitry Andric   void trackValueOfArgument(Argument *A) {
816*0fca6ea1SDimitry Andric     if (A->getType()->isIntOrIntVectorTy()) {
817*0fca6ea1SDimitry Andric       if (std::optional<ConstantRange> Range = A->getRange()) {
818*0fca6ea1SDimitry Andric         markConstantRange(ValueState[A], A, *Range);
819*0fca6ea1SDimitry Andric         return;
820*0fca6ea1SDimitry Andric       }
821*0fca6ea1SDimitry Andric     }
822*0fca6ea1SDimitry Andric     // Assume nothing about the incoming arguments without range.
823*0fca6ea1SDimitry Andric     markOverdefined(A);
824*0fca6ea1SDimitry Andric   }
825*0fca6ea1SDimitry Andric 
826fe6060f1SDimitry Andric   bool isStructLatticeConstant(Function *F, StructType *STy);
827fe6060f1SDimitry Andric 
82806c3fb27SDimitry Andric   Constant *getConstant(const ValueLatticeElement &LV, Type *Ty) const;
82906c3fb27SDimitry Andric 
83006c3fb27SDimitry Andric   Constant *getConstantOrNull(Value *V) const;
831fe6060f1SDimitry Andric 
832fe6060f1SDimitry Andric   SmallPtrSetImpl<Function *> &getArgumentTrackedFunctions() {
833fe6060f1SDimitry Andric     return TrackingIncomingArguments;
834fe6060f1SDimitry Andric   }
835fe6060f1SDimitry Andric 
83606c3fb27SDimitry Andric   void setLatticeValueForSpecializationArguments(Function *F,
83781ad6265SDimitry Andric                                        const SmallVectorImpl<ArgInfo> &Args);
838fe6060f1SDimitry Andric 
839fe6060f1SDimitry Andric   void markFunctionUnreachable(Function *F) {
840fe6060f1SDimitry Andric     for (auto &BB : *F)
841fe6060f1SDimitry Andric       BBExecutable.erase(&BB);
842fe6060f1SDimitry Andric   }
843bdd1243dSDimitry Andric 
844bdd1243dSDimitry Andric   void solveWhileResolvedUndefsIn(Module &M) {
845bdd1243dSDimitry Andric     bool ResolvedUndefs = true;
846bdd1243dSDimitry Andric     while (ResolvedUndefs) {
847bdd1243dSDimitry Andric       solve();
848bdd1243dSDimitry Andric       ResolvedUndefs = false;
849bdd1243dSDimitry Andric       for (Function &F : M)
850bdd1243dSDimitry Andric         ResolvedUndefs |= resolvedUndefsIn(F);
851bdd1243dSDimitry Andric     }
852bdd1243dSDimitry Andric   }
853bdd1243dSDimitry Andric 
854bdd1243dSDimitry Andric   void solveWhileResolvedUndefsIn(SmallVectorImpl<Function *> &WorkList) {
855bdd1243dSDimitry Andric     bool ResolvedUndefs = true;
856bdd1243dSDimitry Andric     while (ResolvedUndefs) {
857bdd1243dSDimitry Andric       solve();
858bdd1243dSDimitry Andric       ResolvedUndefs = false;
859bdd1243dSDimitry Andric       for (Function *F : WorkList)
860bdd1243dSDimitry Andric         ResolvedUndefs |= resolvedUndefsIn(*F);
861bdd1243dSDimitry Andric     }
862bdd1243dSDimitry Andric   }
86306c3fb27SDimitry Andric 
86406c3fb27SDimitry Andric   void solveWhileResolvedUndefs() {
86506c3fb27SDimitry Andric     bool ResolvedUndefs = true;
86606c3fb27SDimitry Andric     while (ResolvedUndefs) {
86706c3fb27SDimitry Andric       solve();
86806c3fb27SDimitry Andric       ResolvedUndefs = false;
86906c3fb27SDimitry Andric       for (Value *V : Invalidated)
87006c3fb27SDimitry Andric         if (auto *I = dyn_cast<Instruction>(V))
87106c3fb27SDimitry Andric           ResolvedUndefs |= resolvedUndef(*I);
87206c3fb27SDimitry Andric     }
87306c3fb27SDimitry Andric     Invalidated.clear();
87406c3fb27SDimitry Andric   }
875fe6060f1SDimitry Andric };
876fe6060f1SDimitry Andric 
877fe6060f1SDimitry Andric } // namespace llvm
878fe6060f1SDimitry Andric 
879fe6060f1SDimitry Andric bool SCCPInstVisitor::markBlockExecutable(BasicBlock *BB) {
880fe6060f1SDimitry Andric   if (!BBExecutable.insert(BB).second)
881fe6060f1SDimitry Andric     return false;
882fe6060f1SDimitry Andric   LLVM_DEBUG(dbgs() << "Marking Block Executable: " << BB->getName() << '\n');
883fe6060f1SDimitry Andric   BBWorkList.push_back(BB); // Add the block to the work list!
884fe6060f1SDimitry Andric   return true;
885fe6060f1SDimitry Andric }
886fe6060f1SDimitry Andric 
887fe6060f1SDimitry Andric void SCCPInstVisitor::pushToWorkList(ValueLatticeElement &IV, Value *V) {
88806c3fb27SDimitry Andric   if (IV.isOverdefined()) {
88906c3fb27SDimitry Andric     if (OverdefinedInstWorkList.empty() || OverdefinedInstWorkList.back() != V)
89006c3fb27SDimitry Andric       OverdefinedInstWorkList.push_back(V);
89106c3fb27SDimitry Andric     return;
89206c3fb27SDimitry Andric   }
89306c3fb27SDimitry Andric   if (InstWorkList.empty() || InstWorkList.back() != V)
894fe6060f1SDimitry Andric     InstWorkList.push_back(V);
895fe6060f1SDimitry Andric }
896fe6060f1SDimitry Andric 
897fe6060f1SDimitry Andric void SCCPInstVisitor::pushToWorkListMsg(ValueLatticeElement &IV, Value *V) {
898fe6060f1SDimitry Andric   LLVM_DEBUG(dbgs() << "updated " << IV << ": " << *V << '\n');
899fe6060f1SDimitry Andric   pushToWorkList(IV, V);
900fe6060f1SDimitry Andric }
901fe6060f1SDimitry Andric 
902fe6060f1SDimitry Andric bool SCCPInstVisitor::markConstant(ValueLatticeElement &IV, Value *V,
903fe6060f1SDimitry Andric                                    Constant *C, bool MayIncludeUndef) {
904fe6060f1SDimitry Andric   if (!IV.markConstant(C, MayIncludeUndef))
905fe6060f1SDimitry Andric     return false;
906fe6060f1SDimitry Andric   LLVM_DEBUG(dbgs() << "markConstant: " << *C << ": " << *V << '\n');
907fe6060f1SDimitry Andric   pushToWorkList(IV, V);
908fe6060f1SDimitry Andric   return true;
909fe6060f1SDimitry Andric }
910fe6060f1SDimitry Andric 
911*0fca6ea1SDimitry Andric bool SCCPInstVisitor::markConstantRange(ValueLatticeElement &IV, Value *V,
912*0fca6ea1SDimitry Andric                                         const ConstantRange &CR) {
913*0fca6ea1SDimitry Andric   if (!IV.markConstantRange(CR))
914*0fca6ea1SDimitry Andric     return false;
915*0fca6ea1SDimitry Andric   LLVM_DEBUG(dbgs() << "markConstantRange: " << CR << ": " << *V << '\n');
916*0fca6ea1SDimitry Andric   pushToWorkList(IV, V);
917*0fca6ea1SDimitry Andric   return true;
918*0fca6ea1SDimitry Andric }
919*0fca6ea1SDimitry Andric 
920fe6060f1SDimitry Andric bool SCCPInstVisitor::markOverdefined(ValueLatticeElement &IV, Value *V) {
921fe6060f1SDimitry Andric   if (!IV.markOverdefined())
922fe6060f1SDimitry Andric     return false;
923fe6060f1SDimitry Andric 
924fe6060f1SDimitry Andric   LLVM_DEBUG(dbgs() << "markOverdefined: ";
925fe6060f1SDimitry Andric              if (auto *F = dyn_cast<Function>(V)) dbgs()
926fe6060f1SDimitry Andric              << "Function '" << F->getName() << "'\n";
927fe6060f1SDimitry Andric              else dbgs() << *V << '\n');
928fe6060f1SDimitry Andric   // Only instructions go on the work list
929fe6060f1SDimitry Andric   pushToWorkList(IV, V);
930fe6060f1SDimitry Andric   return true;
931fe6060f1SDimitry Andric }
932fe6060f1SDimitry Andric 
933fe6060f1SDimitry Andric bool SCCPInstVisitor::isStructLatticeConstant(Function *F, StructType *STy) {
934fe6060f1SDimitry Andric   for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
935fe6060f1SDimitry Andric     const auto &It = TrackedMultipleRetVals.find(std::make_pair(F, i));
936fe6060f1SDimitry Andric     assert(It != TrackedMultipleRetVals.end());
937fe6060f1SDimitry Andric     ValueLatticeElement LV = It->second;
938bdd1243dSDimitry Andric     if (!SCCPSolver::isConstant(LV))
939fe6060f1SDimitry Andric       return false;
940fe6060f1SDimitry Andric   }
941fe6060f1SDimitry Andric   return true;
942fe6060f1SDimitry Andric }
943fe6060f1SDimitry Andric 
94406c3fb27SDimitry Andric Constant *SCCPInstVisitor::getConstant(const ValueLatticeElement &LV,
94506c3fb27SDimitry Andric                                        Type *Ty) const {
94606c3fb27SDimitry Andric   if (LV.isConstant()) {
94706c3fb27SDimitry Andric     Constant *C = LV.getConstant();
94806c3fb27SDimitry Andric     assert(C->getType() == Ty && "Type mismatch");
94906c3fb27SDimitry Andric     return C;
95006c3fb27SDimitry Andric   }
951fe6060f1SDimitry Andric 
952fe6060f1SDimitry Andric   if (LV.isConstantRange()) {
953fe6060f1SDimitry Andric     const auto &CR = LV.getConstantRange();
954fe6060f1SDimitry Andric     if (CR.getSingleElement())
95506c3fb27SDimitry Andric       return ConstantInt::get(Ty, *CR.getSingleElement());
956fe6060f1SDimitry Andric   }
957fe6060f1SDimitry Andric   return nullptr;
958fe6060f1SDimitry Andric }
959fe6060f1SDimitry Andric 
96006c3fb27SDimitry Andric Constant *SCCPInstVisitor::getConstantOrNull(Value *V) const {
96106c3fb27SDimitry Andric   Constant *Const = nullptr;
96206c3fb27SDimitry Andric   if (V->getType()->isStructTy()) {
96306c3fb27SDimitry Andric     std::vector<ValueLatticeElement> LVs = getStructLatticeValueFor(V);
96406c3fb27SDimitry Andric     if (any_of(LVs, SCCPSolver::isOverdefined))
96506c3fb27SDimitry Andric       return nullptr;
96606c3fb27SDimitry Andric     std::vector<Constant *> ConstVals;
96706c3fb27SDimitry Andric     auto *ST = cast<StructType>(V->getType());
96806c3fb27SDimitry Andric     for (unsigned I = 0, E = ST->getNumElements(); I != E; ++I) {
96906c3fb27SDimitry Andric       ValueLatticeElement LV = LVs[I];
97006c3fb27SDimitry Andric       ConstVals.push_back(SCCPSolver::isConstant(LV)
97106c3fb27SDimitry Andric                               ? getConstant(LV, ST->getElementType(I))
97206c3fb27SDimitry Andric                               : UndefValue::get(ST->getElementType(I)));
97306c3fb27SDimitry Andric     }
97406c3fb27SDimitry Andric     Const = ConstantStruct::get(ST, ConstVals);
97506c3fb27SDimitry Andric   } else {
97606c3fb27SDimitry Andric     const ValueLatticeElement &LV = getLatticeValueFor(V);
97706c3fb27SDimitry Andric     if (SCCPSolver::isOverdefined(LV))
97806c3fb27SDimitry Andric       return nullptr;
97906c3fb27SDimitry Andric     Const = SCCPSolver::isConstant(LV) ? getConstant(LV, V->getType())
98006c3fb27SDimitry Andric                                        : UndefValue::get(V->getType());
98106c3fb27SDimitry Andric   }
98206c3fb27SDimitry Andric   assert(Const && "Constant is nullptr here!");
98306c3fb27SDimitry Andric   return Const;
984bdd1243dSDimitry Andric }
985bdd1243dSDimitry Andric 
98606c3fb27SDimitry Andric void SCCPInstVisitor::setLatticeValueForSpecializationArguments(Function *F,
98706c3fb27SDimitry Andric                                         const SmallVectorImpl<ArgInfo> &Args) {
98881ad6265SDimitry Andric   assert(!Args.empty() && "Specialization without arguments");
98981ad6265SDimitry Andric   assert(F->arg_size() == Args[0].Formal->getParent()->arg_size() &&
990fe6060f1SDimitry Andric          "Functions should have the same number of arguments");
991fe6060f1SDimitry Andric 
99281ad6265SDimitry Andric   auto Iter = Args.begin();
99306c3fb27SDimitry Andric   Function::arg_iterator NewArg = F->arg_begin();
99406c3fb27SDimitry Andric   Function::arg_iterator OldArg = Args[0].Formal->getParent()->arg_begin();
99581ad6265SDimitry Andric   for (auto End = F->arg_end(); NewArg != End; ++NewArg, ++OldArg) {
996fe6060f1SDimitry Andric 
99781ad6265SDimitry Andric     LLVM_DEBUG(dbgs() << "SCCP: Marking argument "
99881ad6265SDimitry Andric                       << NewArg->getNameOrAsOperand() << "\n");
99981ad6265SDimitry Andric 
100006c3fb27SDimitry Andric     // Mark the argument constants in the new function
100106c3fb27SDimitry Andric     // or copy the lattice state over from the old function.
100206c3fb27SDimitry Andric     if (Iter != Args.end() && Iter->Formal == &*OldArg) {
100306c3fb27SDimitry Andric       if (auto *STy = dyn_cast<StructType>(NewArg->getType())) {
100406c3fb27SDimitry Andric         for (unsigned I = 0, E = STy->getNumElements(); I != E; ++I) {
100506c3fb27SDimitry Andric           ValueLatticeElement &NewValue = StructValueState[{&*NewArg, I}];
100606c3fb27SDimitry Andric           NewValue.markConstant(Iter->Actual->getAggregateElement(I));
100706c3fb27SDimitry Andric         }
100806c3fb27SDimitry Andric       } else {
100906c3fb27SDimitry Andric         ValueState[&*NewArg].markConstant(Iter->Actual);
101006c3fb27SDimitry Andric       }
101181ad6265SDimitry Andric       ++Iter;
101206c3fb27SDimitry Andric     } else {
101306c3fb27SDimitry Andric       if (auto *STy = dyn_cast<StructType>(NewArg->getType())) {
101406c3fb27SDimitry Andric         for (unsigned I = 0, E = STy->getNumElements(); I != E; ++I) {
101506c3fb27SDimitry Andric           ValueLatticeElement &NewValue = StructValueState[{&*NewArg, I}];
101606c3fb27SDimitry Andric           NewValue = StructValueState[{&*OldArg, I}];
101706c3fb27SDimitry Andric         }
101806c3fb27SDimitry Andric       } else {
101906c3fb27SDimitry Andric         ValueLatticeElement &NewValue = ValueState[&*NewArg];
102006c3fb27SDimitry Andric         NewValue = ValueState[&*OldArg];
102106c3fb27SDimitry Andric       }
102281ad6265SDimitry Andric     }
1023fe6060f1SDimitry Andric   }
1024fe6060f1SDimitry Andric }
1025fe6060f1SDimitry Andric 
1026fe6060f1SDimitry Andric void SCCPInstVisitor::visitInstruction(Instruction &I) {
1027fe6060f1SDimitry Andric   // All the instructions we don't do any special handling for just
1028fe6060f1SDimitry Andric   // go to overdefined.
1029fe6060f1SDimitry Andric   LLVM_DEBUG(dbgs() << "SCCP: Don't know how to handle: " << I << '\n');
1030fe6060f1SDimitry Andric   markOverdefined(&I);
1031fe6060f1SDimitry Andric }
1032fe6060f1SDimitry Andric 
1033fe6060f1SDimitry Andric bool SCCPInstVisitor::mergeInValue(ValueLatticeElement &IV, Value *V,
1034fe6060f1SDimitry Andric                                    ValueLatticeElement MergeWithV,
1035fe6060f1SDimitry Andric                                    ValueLatticeElement::MergeOptions Opts) {
1036fe6060f1SDimitry Andric   if (IV.mergeIn(MergeWithV, Opts)) {
1037fe6060f1SDimitry Andric     pushToWorkList(IV, V);
1038fe6060f1SDimitry Andric     LLVM_DEBUG(dbgs() << "Merged " << MergeWithV << " into " << *V << " : "
1039fe6060f1SDimitry Andric                       << IV << "\n");
1040fe6060f1SDimitry Andric     return true;
1041fe6060f1SDimitry Andric   }
1042fe6060f1SDimitry Andric   return false;
1043fe6060f1SDimitry Andric }
1044fe6060f1SDimitry Andric 
1045fe6060f1SDimitry Andric bool SCCPInstVisitor::markEdgeExecutable(BasicBlock *Source, BasicBlock *Dest) {
1046fe6060f1SDimitry Andric   if (!KnownFeasibleEdges.insert(Edge(Source, Dest)).second)
1047fe6060f1SDimitry Andric     return false; // This edge is already known to be executable!
1048fe6060f1SDimitry Andric 
1049fe6060f1SDimitry Andric   if (!markBlockExecutable(Dest)) {
1050fe6060f1SDimitry Andric     // If the destination is already executable, we just made an *edge*
1051fe6060f1SDimitry Andric     // feasible that wasn't before.  Revisit the PHI nodes in the block
1052fe6060f1SDimitry Andric     // because they have potentially new operands.
1053fe6060f1SDimitry Andric     LLVM_DEBUG(dbgs() << "Marking Edge Executable: " << Source->getName()
1054fe6060f1SDimitry Andric                       << " -> " << Dest->getName() << '\n');
1055fe6060f1SDimitry Andric 
1056fe6060f1SDimitry Andric     for (PHINode &PN : Dest->phis())
1057fe6060f1SDimitry Andric       visitPHINode(PN);
1058fe6060f1SDimitry Andric   }
1059fe6060f1SDimitry Andric   return true;
1060fe6060f1SDimitry Andric }
1061fe6060f1SDimitry Andric 
1062fe6060f1SDimitry Andric // getFeasibleSuccessors - Return a vector of booleans to indicate which
1063fe6060f1SDimitry Andric // successors are reachable from a given terminator instruction.
1064fe6060f1SDimitry Andric void SCCPInstVisitor::getFeasibleSuccessors(Instruction &TI,
1065fe6060f1SDimitry Andric                                             SmallVectorImpl<bool> &Succs) {
1066fe6060f1SDimitry Andric   Succs.resize(TI.getNumSuccessors());
1067fe6060f1SDimitry Andric   if (auto *BI = dyn_cast<BranchInst>(&TI)) {
1068fe6060f1SDimitry Andric     if (BI->isUnconditional()) {
1069fe6060f1SDimitry Andric       Succs[0] = true;
1070fe6060f1SDimitry Andric       return;
1071fe6060f1SDimitry Andric     }
1072fe6060f1SDimitry Andric 
1073fe6060f1SDimitry Andric     ValueLatticeElement BCValue = getValueState(BI->getCondition());
107406c3fb27SDimitry Andric     ConstantInt *CI = getConstantInt(BCValue, BI->getCondition()->getType());
1075fe6060f1SDimitry Andric     if (!CI) {
1076fe6060f1SDimitry Andric       // Overdefined condition variables, and branches on unfoldable constant
1077fe6060f1SDimitry Andric       // conditions, mean the branch could go either way.
1078fe6060f1SDimitry Andric       if (!BCValue.isUnknownOrUndef())
1079fe6060f1SDimitry Andric         Succs[0] = Succs[1] = true;
1080fe6060f1SDimitry Andric       return;
1081fe6060f1SDimitry Andric     }
1082fe6060f1SDimitry Andric 
1083fe6060f1SDimitry Andric     // Constant condition variables mean the branch can only go a single way.
1084fe6060f1SDimitry Andric     Succs[CI->isZero()] = true;
1085fe6060f1SDimitry Andric     return;
1086fe6060f1SDimitry Andric   }
1087fe6060f1SDimitry Andric 
10885f757f3fSDimitry Andric   // We cannot analyze special terminators, so consider all successors
10895f757f3fSDimitry Andric   // executable.
10905f757f3fSDimitry Andric   if (TI.isSpecialTerminator()) {
1091fe6060f1SDimitry Andric     Succs.assign(TI.getNumSuccessors(), true);
1092fe6060f1SDimitry Andric     return;
1093fe6060f1SDimitry Andric   }
1094fe6060f1SDimitry Andric 
1095fe6060f1SDimitry Andric   if (auto *SI = dyn_cast<SwitchInst>(&TI)) {
1096fe6060f1SDimitry Andric     if (!SI->getNumCases()) {
1097fe6060f1SDimitry Andric       Succs[0] = true;
1098fe6060f1SDimitry Andric       return;
1099fe6060f1SDimitry Andric     }
1100fe6060f1SDimitry Andric     const ValueLatticeElement &SCValue = getValueState(SI->getCondition());
110106c3fb27SDimitry Andric     if (ConstantInt *CI =
110206c3fb27SDimitry Andric             getConstantInt(SCValue, SI->getCondition()->getType())) {
1103fe6060f1SDimitry Andric       Succs[SI->findCaseValue(CI)->getSuccessorIndex()] = true;
1104fe6060f1SDimitry Andric       return;
1105fe6060f1SDimitry Andric     }
1106fe6060f1SDimitry Andric 
1107fe6060f1SDimitry Andric     // TODO: Switch on undef is UB. Stop passing false once the rest of LLVM
1108fe6060f1SDimitry Andric     // is ready.
1109fe6060f1SDimitry Andric     if (SCValue.isConstantRange(/*UndefAllowed=*/false)) {
1110fe6060f1SDimitry Andric       const ConstantRange &Range = SCValue.getConstantRange();
11111db9f3b2SDimitry Andric       unsigned ReachableCaseCount = 0;
1112fe6060f1SDimitry Andric       for (const auto &Case : SI->cases()) {
1113fe6060f1SDimitry Andric         const APInt &CaseValue = Case.getCaseValue()->getValue();
11141db9f3b2SDimitry Andric         if (Range.contains(CaseValue)) {
1115fe6060f1SDimitry Andric           Succs[Case.getSuccessorIndex()] = true;
11161db9f3b2SDimitry Andric           ++ReachableCaseCount;
11171db9f3b2SDimitry Andric         }
1118fe6060f1SDimitry Andric       }
1119fe6060f1SDimitry Andric 
11201db9f3b2SDimitry Andric       Succs[SI->case_default()->getSuccessorIndex()] =
11211db9f3b2SDimitry Andric           Range.isSizeLargerThan(ReachableCaseCount);
1122fe6060f1SDimitry Andric       return;
1123fe6060f1SDimitry Andric     }
1124fe6060f1SDimitry Andric 
1125fe6060f1SDimitry Andric     // Overdefined or unknown condition? All destinations are executable!
1126fe6060f1SDimitry Andric     if (!SCValue.isUnknownOrUndef())
1127fe6060f1SDimitry Andric       Succs.assign(TI.getNumSuccessors(), true);
1128fe6060f1SDimitry Andric     return;
1129fe6060f1SDimitry Andric   }
1130fe6060f1SDimitry Andric 
1131fe6060f1SDimitry Andric   // In case of indirect branch and its address is a blockaddress, we mark
1132fe6060f1SDimitry Andric   // the target as executable.
1133fe6060f1SDimitry Andric   if (auto *IBR = dyn_cast<IndirectBrInst>(&TI)) {
1134fe6060f1SDimitry Andric     // Casts are folded by visitCastInst.
1135fe6060f1SDimitry Andric     ValueLatticeElement IBRValue = getValueState(IBR->getAddress());
113606c3fb27SDimitry Andric     BlockAddress *Addr = dyn_cast_or_null<BlockAddress>(
113706c3fb27SDimitry Andric         getConstant(IBRValue, IBR->getAddress()->getType()));
1138fe6060f1SDimitry Andric     if (!Addr) { // Overdefined or unknown condition?
1139fe6060f1SDimitry Andric       // All destinations are executable!
1140fe6060f1SDimitry Andric       if (!IBRValue.isUnknownOrUndef())
1141fe6060f1SDimitry Andric         Succs.assign(TI.getNumSuccessors(), true);
1142fe6060f1SDimitry Andric       return;
1143fe6060f1SDimitry Andric     }
1144fe6060f1SDimitry Andric 
1145fe6060f1SDimitry Andric     BasicBlock *T = Addr->getBasicBlock();
1146fe6060f1SDimitry Andric     assert(Addr->getFunction() == T->getParent() &&
1147fe6060f1SDimitry Andric            "Block address of a different function ?");
1148fe6060f1SDimitry Andric     for (unsigned i = 0; i < IBR->getNumSuccessors(); ++i) {
1149fe6060f1SDimitry Andric       // This is the target.
1150fe6060f1SDimitry Andric       if (IBR->getDestination(i) == T) {
1151fe6060f1SDimitry Andric         Succs[i] = true;
1152fe6060f1SDimitry Andric         return;
1153fe6060f1SDimitry Andric       }
1154fe6060f1SDimitry Andric     }
1155fe6060f1SDimitry Andric 
1156fe6060f1SDimitry Andric     // If we didn't find our destination in the IBR successor list, then we
1157fe6060f1SDimitry Andric     // have undefined behavior. Its ok to assume no successor is executable.
1158fe6060f1SDimitry Andric     return;
1159fe6060f1SDimitry Andric   }
1160fe6060f1SDimitry Andric 
1161fe6060f1SDimitry Andric   LLVM_DEBUG(dbgs() << "Unknown terminator instruction: " << TI << '\n');
1162fe6060f1SDimitry Andric   llvm_unreachable("SCCP: Don't know how to handle this terminator!");
1163fe6060f1SDimitry Andric }
1164fe6060f1SDimitry Andric 
1165fe6060f1SDimitry Andric // isEdgeFeasible - Return true if the control flow edge from the 'From' basic
1166fe6060f1SDimitry Andric // block to the 'To' basic block is currently feasible.
1167fe6060f1SDimitry Andric bool SCCPInstVisitor::isEdgeFeasible(BasicBlock *From, BasicBlock *To) const {
1168fe6060f1SDimitry Andric   // Check if we've called markEdgeExecutable on the edge yet. (We could
1169fe6060f1SDimitry Andric   // be more aggressive and try to consider edges which haven't been marked
1170fe6060f1SDimitry Andric   // yet, but there isn't any need.)
1171fe6060f1SDimitry Andric   return KnownFeasibleEdges.count(Edge(From, To));
1172fe6060f1SDimitry Andric }
1173fe6060f1SDimitry Andric 
1174fe6060f1SDimitry Andric // visit Implementations - Something changed in this instruction, either an
1175fe6060f1SDimitry Andric // operand made a transition, or the instruction is newly executable.  Change
1176fe6060f1SDimitry Andric // the value type of I to reflect these changes if appropriate.  This method
1177fe6060f1SDimitry Andric // makes sure to do the following actions:
1178fe6060f1SDimitry Andric //
1179fe6060f1SDimitry Andric // 1. If a phi node merges two constants in, and has conflicting value coming
1180fe6060f1SDimitry Andric //    from different branches, or if the PHI node merges in an overdefined
1181fe6060f1SDimitry Andric //    value, then the PHI node becomes overdefined.
1182fe6060f1SDimitry Andric // 2. If a phi node merges only constants in, and they all agree on value, the
1183fe6060f1SDimitry Andric //    PHI node becomes a constant value equal to that.
1184fe6060f1SDimitry Andric // 3. If V <- x (op) y && isConstant(x) && isConstant(y) V = Constant
1185fe6060f1SDimitry Andric // 4. If V <- x (op) y && (isOverdefined(x) || isOverdefined(y)) V = Overdefined
1186fe6060f1SDimitry Andric // 5. If V <- MEM or V <- CALL or V <- (unknown) then V = Overdefined
1187fe6060f1SDimitry Andric // 6. If a conditional branch has a value that is constant, make the selected
1188fe6060f1SDimitry Andric //    destination executable
1189fe6060f1SDimitry Andric // 7. If a conditional branch has a value that is overdefined, make all
1190fe6060f1SDimitry Andric //    successors executable.
1191fe6060f1SDimitry Andric void SCCPInstVisitor::visitPHINode(PHINode &PN) {
1192fe6060f1SDimitry Andric   // If this PN returns a struct, just mark the result overdefined.
1193fe6060f1SDimitry Andric   // TODO: We could do a lot better than this if code actually uses this.
1194fe6060f1SDimitry Andric   if (PN.getType()->isStructTy())
1195fe6060f1SDimitry Andric     return (void)markOverdefined(&PN);
1196fe6060f1SDimitry Andric 
1197fe6060f1SDimitry Andric   if (getValueState(&PN).isOverdefined())
1198fe6060f1SDimitry Andric     return; // Quick exit
1199fe6060f1SDimitry Andric 
1200fe6060f1SDimitry Andric   // Super-extra-high-degree PHI nodes are unlikely to ever be marked constant,
1201fe6060f1SDimitry Andric   // and slow us down a lot.  Just mark them overdefined.
1202fe6060f1SDimitry Andric   if (PN.getNumIncomingValues() > 64)
1203fe6060f1SDimitry Andric     return (void)markOverdefined(&PN);
1204fe6060f1SDimitry Andric 
1205fe6060f1SDimitry Andric   unsigned NumActiveIncoming = 0;
1206fe6060f1SDimitry Andric 
1207fe6060f1SDimitry Andric   // Look at all of the executable operands of the PHI node.  If any of them
1208fe6060f1SDimitry Andric   // are overdefined, the PHI becomes overdefined as well.  If they are all
1209fe6060f1SDimitry Andric   // constant, and they agree with each other, the PHI becomes the identical
1210fe6060f1SDimitry Andric   // constant.  If they are constant and don't agree, the PHI is a constant
1211fe6060f1SDimitry Andric   // range. If there are no executable operands, the PHI remains unknown.
1212fe6060f1SDimitry Andric   ValueLatticeElement PhiState = getValueState(&PN);
1213fe6060f1SDimitry Andric   for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) {
1214fe6060f1SDimitry Andric     if (!isEdgeFeasible(PN.getIncomingBlock(i), PN.getParent()))
1215fe6060f1SDimitry Andric       continue;
1216fe6060f1SDimitry Andric 
1217fe6060f1SDimitry Andric     ValueLatticeElement IV = getValueState(PN.getIncomingValue(i));
1218fe6060f1SDimitry Andric     PhiState.mergeIn(IV);
1219fe6060f1SDimitry Andric     NumActiveIncoming++;
1220fe6060f1SDimitry Andric     if (PhiState.isOverdefined())
1221fe6060f1SDimitry Andric       break;
1222fe6060f1SDimitry Andric   }
1223fe6060f1SDimitry Andric 
1224fe6060f1SDimitry Andric   // We allow up to 1 range extension per active incoming value and one
1225fe6060f1SDimitry Andric   // additional extension. Note that we manually adjust the number of range
1226fe6060f1SDimitry Andric   // extensions to match the number of active incoming values. This helps to
1227fe6060f1SDimitry Andric   // limit multiple extensions caused by the same incoming value, if other
1228fe6060f1SDimitry Andric   // incoming values are equal.
1229fe6060f1SDimitry Andric   mergeInValue(&PN, PhiState,
1230fe6060f1SDimitry Andric                ValueLatticeElement::MergeOptions().setMaxWidenSteps(
1231fe6060f1SDimitry Andric                    NumActiveIncoming + 1));
1232fe6060f1SDimitry Andric   ValueLatticeElement &PhiStateRef = getValueState(&PN);
1233fe6060f1SDimitry Andric   PhiStateRef.setNumRangeExtensions(
1234fe6060f1SDimitry Andric       std::max(NumActiveIncoming, PhiStateRef.getNumRangeExtensions()));
1235fe6060f1SDimitry Andric }
1236fe6060f1SDimitry Andric 
1237fe6060f1SDimitry Andric void SCCPInstVisitor::visitReturnInst(ReturnInst &I) {
1238fe6060f1SDimitry Andric   if (I.getNumOperands() == 0)
1239fe6060f1SDimitry Andric     return; // ret void
1240fe6060f1SDimitry Andric 
1241fe6060f1SDimitry Andric   Function *F = I.getParent()->getParent();
1242fe6060f1SDimitry Andric   Value *ResultOp = I.getOperand(0);
1243fe6060f1SDimitry Andric 
1244fe6060f1SDimitry Andric   // If we are tracking the return value of this function, merge it in.
1245fe6060f1SDimitry Andric   if (!TrackedRetVals.empty() && !ResultOp->getType()->isStructTy()) {
1246fe6060f1SDimitry Andric     auto TFRVI = TrackedRetVals.find(F);
1247fe6060f1SDimitry Andric     if (TFRVI != TrackedRetVals.end()) {
1248fe6060f1SDimitry Andric       mergeInValue(TFRVI->second, F, getValueState(ResultOp));
1249fe6060f1SDimitry Andric       return;
1250fe6060f1SDimitry Andric     }
1251fe6060f1SDimitry Andric   }
1252fe6060f1SDimitry Andric 
1253fe6060f1SDimitry Andric   // Handle functions that return multiple values.
1254fe6060f1SDimitry Andric   if (!TrackedMultipleRetVals.empty()) {
1255fe6060f1SDimitry Andric     if (auto *STy = dyn_cast<StructType>(ResultOp->getType()))
1256fe6060f1SDimitry Andric       if (MRVFunctionsTracked.count(F))
1257fe6060f1SDimitry Andric         for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i)
1258fe6060f1SDimitry Andric           mergeInValue(TrackedMultipleRetVals[std::make_pair(F, i)], F,
1259fe6060f1SDimitry Andric                        getStructValueState(ResultOp, i));
1260fe6060f1SDimitry Andric   }
1261fe6060f1SDimitry Andric }
1262fe6060f1SDimitry Andric 
1263fe6060f1SDimitry Andric void SCCPInstVisitor::visitTerminator(Instruction &TI) {
1264fe6060f1SDimitry Andric   SmallVector<bool, 16> SuccFeasible;
1265fe6060f1SDimitry Andric   getFeasibleSuccessors(TI, SuccFeasible);
1266fe6060f1SDimitry Andric 
1267fe6060f1SDimitry Andric   BasicBlock *BB = TI.getParent();
1268fe6060f1SDimitry Andric 
1269fe6060f1SDimitry Andric   // Mark all feasible successors executable.
1270fe6060f1SDimitry Andric   for (unsigned i = 0, e = SuccFeasible.size(); i != e; ++i)
1271fe6060f1SDimitry Andric     if (SuccFeasible[i])
1272fe6060f1SDimitry Andric       markEdgeExecutable(BB, TI.getSuccessor(i));
1273fe6060f1SDimitry Andric }
1274fe6060f1SDimitry Andric 
1275fe6060f1SDimitry Andric void SCCPInstVisitor::visitCastInst(CastInst &I) {
1276fe6060f1SDimitry Andric   // ResolvedUndefsIn might mark I as overdefined. Bail out, even if we would
1277fe6060f1SDimitry Andric   // discover a concrete value later.
1278fe6060f1SDimitry Andric   if (ValueState[&I].isOverdefined())
1279fe6060f1SDimitry Andric     return;
1280fe6060f1SDimitry Andric 
1281fe6060f1SDimitry Andric   ValueLatticeElement OpSt = getValueState(I.getOperand(0));
1282349cc55cSDimitry Andric   if (OpSt.isUnknownOrUndef())
1283349cc55cSDimitry Andric     return;
1284349cc55cSDimitry Andric 
128506c3fb27SDimitry Andric   if (Constant *OpC = getConstant(OpSt, I.getOperand(0)->getType())) {
1286fe6060f1SDimitry Andric     // Fold the constant as we build.
12875f757f3fSDimitry Andric     if (Constant *C =
12885f757f3fSDimitry Andric             ConstantFoldCastOperand(I.getOpcode(), OpC, I.getType(), DL))
12895f757f3fSDimitry Andric       return (void)markConstant(&I, C);
12905f757f3fSDimitry Andric   }
12915f757f3fSDimitry Andric 
1292*0fca6ea1SDimitry Andric   // Ignore bitcasts, as they may change the number of vector elements.
1293*0fca6ea1SDimitry Andric   if (I.getDestTy()->isIntOrIntVectorTy() &&
1294*0fca6ea1SDimitry Andric       I.getSrcTy()->isIntOrIntVectorTy() &&
1295*0fca6ea1SDimitry Andric       I.getOpcode() != Instruction::BitCast) {
1296fe6060f1SDimitry Andric     auto &LV = getValueState(&I);
1297*0fca6ea1SDimitry Andric     ConstantRange OpRange =
1298*0fca6ea1SDimitry Andric         OpSt.asConstantRange(I.getSrcTy(), /*UndefAllowed=*/false);
1299349cc55cSDimitry Andric 
1300fe6060f1SDimitry Andric     Type *DestTy = I.getDestTy();
1301fe6060f1SDimitry Andric     ConstantRange Res =
1302*0fca6ea1SDimitry Andric         OpRange.castOp(I.getOpcode(), DestTy->getScalarSizeInBits());
1303fe6060f1SDimitry Andric     mergeInValue(LV, &I, ValueLatticeElement::getRange(Res));
1304349cc55cSDimitry Andric   } else
1305fe6060f1SDimitry Andric     markOverdefined(&I);
1306fe6060f1SDimitry Andric }
1307fe6060f1SDimitry Andric 
1308bdd1243dSDimitry Andric void SCCPInstVisitor::handleExtractOfWithOverflow(ExtractValueInst &EVI,
1309bdd1243dSDimitry Andric                                                   const WithOverflowInst *WO,
1310bdd1243dSDimitry Andric                                                   unsigned Idx) {
1311bdd1243dSDimitry Andric   Value *LHS = WO->getLHS(), *RHS = WO->getRHS();
1312bdd1243dSDimitry Andric   ValueLatticeElement L = getValueState(LHS);
1313bdd1243dSDimitry Andric   ValueLatticeElement R = getValueState(RHS);
1314bdd1243dSDimitry Andric   addAdditionalUser(LHS, &EVI);
1315bdd1243dSDimitry Andric   addAdditionalUser(RHS, &EVI);
1316bdd1243dSDimitry Andric   if (L.isUnknownOrUndef() || R.isUnknownOrUndef())
1317bdd1243dSDimitry Andric     return; // Wait to resolve.
1318bdd1243dSDimitry Andric 
1319bdd1243dSDimitry Andric   Type *Ty = LHS->getType();
1320*0fca6ea1SDimitry Andric   ConstantRange LR = L.asConstantRange(Ty, /*UndefAllowed=*/false);
1321*0fca6ea1SDimitry Andric   ConstantRange RR = R.asConstantRange(Ty, /*UndefAllowed=*/false);
1322bdd1243dSDimitry Andric   if (Idx == 0) {
1323bdd1243dSDimitry Andric     ConstantRange Res = LR.binaryOp(WO->getBinaryOp(), RR);
1324bdd1243dSDimitry Andric     mergeInValue(&EVI, ValueLatticeElement::getRange(Res));
1325bdd1243dSDimitry Andric   } else {
1326bdd1243dSDimitry Andric     assert(Idx == 1 && "Index can only be 0 or 1");
1327bdd1243dSDimitry Andric     ConstantRange NWRegion = ConstantRange::makeGuaranteedNoWrapRegion(
1328bdd1243dSDimitry Andric         WO->getBinaryOp(), RR, WO->getNoWrapKind());
1329bdd1243dSDimitry Andric     if (NWRegion.contains(LR))
1330bdd1243dSDimitry Andric       return (void)markConstant(&EVI, ConstantInt::getFalse(EVI.getType()));
1331bdd1243dSDimitry Andric     markOverdefined(&EVI);
1332bdd1243dSDimitry Andric   }
1333bdd1243dSDimitry Andric }
1334bdd1243dSDimitry Andric 
1335fe6060f1SDimitry Andric void SCCPInstVisitor::visitExtractValueInst(ExtractValueInst &EVI) {
1336fe6060f1SDimitry Andric   // If this returns a struct, mark all elements over defined, we don't track
1337fe6060f1SDimitry Andric   // structs in structs.
1338fe6060f1SDimitry Andric   if (EVI.getType()->isStructTy())
1339fe6060f1SDimitry Andric     return (void)markOverdefined(&EVI);
1340fe6060f1SDimitry Andric 
1341fe6060f1SDimitry Andric   // resolvedUndefsIn might mark I as overdefined. Bail out, even if we would
1342fe6060f1SDimitry Andric   // discover a concrete value later.
1343fe6060f1SDimitry Andric   if (ValueState[&EVI].isOverdefined())
1344fe6060f1SDimitry Andric     return (void)markOverdefined(&EVI);
1345fe6060f1SDimitry Andric 
1346fe6060f1SDimitry Andric   // If this is extracting from more than one level of struct, we don't know.
1347fe6060f1SDimitry Andric   if (EVI.getNumIndices() != 1)
1348fe6060f1SDimitry Andric     return (void)markOverdefined(&EVI);
1349fe6060f1SDimitry Andric 
1350fe6060f1SDimitry Andric   Value *AggVal = EVI.getAggregateOperand();
1351fe6060f1SDimitry Andric   if (AggVal->getType()->isStructTy()) {
1352fe6060f1SDimitry Andric     unsigned i = *EVI.idx_begin();
1353bdd1243dSDimitry Andric     if (auto *WO = dyn_cast<WithOverflowInst>(AggVal))
1354bdd1243dSDimitry Andric       return handleExtractOfWithOverflow(EVI, WO, i);
1355fe6060f1SDimitry Andric     ValueLatticeElement EltVal = getStructValueState(AggVal, i);
1356fe6060f1SDimitry Andric     mergeInValue(getValueState(&EVI), &EVI, EltVal);
1357fe6060f1SDimitry Andric   } else {
1358fe6060f1SDimitry Andric     // Otherwise, must be extracting from an array.
1359fe6060f1SDimitry Andric     return (void)markOverdefined(&EVI);
1360fe6060f1SDimitry Andric   }
1361fe6060f1SDimitry Andric }
1362fe6060f1SDimitry Andric 
1363fe6060f1SDimitry Andric void SCCPInstVisitor::visitInsertValueInst(InsertValueInst &IVI) {
1364fe6060f1SDimitry Andric   auto *STy = dyn_cast<StructType>(IVI.getType());
1365fe6060f1SDimitry Andric   if (!STy)
1366fe6060f1SDimitry Andric     return (void)markOverdefined(&IVI);
1367fe6060f1SDimitry Andric 
1368fe6060f1SDimitry Andric   // resolvedUndefsIn might mark I as overdefined. Bail out, even if we would
1369fe6060f1SDimitry Andric   // discover a concrete value later.
1370bdd1243dSDimitry Andric   if (SCCPSolver::isOverdefined(ValueState[&IVI]))
1371fe6060f1SDimitry Andric     return (void)markOverdefined(&IVI);
1372fe6060f1SDimitry Andric 
1373fe6060f1SDimitry Andric   // If this has more than one index, we can't handle it, drive all results to
1374fe6060f1SDimitry Andric   // undef.
1375fe6060f1SDimitry Andric   if (IVI.getNumIndices() != 1)
1376fe6060f1SDimitry Andric     return (void)markOverdefined(&IVI);
1377fe6060f1SDimitry Andric 
1378fe6060f1SDimitry Andric   Value *Aggr = IVI.getAggregateOperand();
1379fe6060f1SDimitry Andric   unsigned Idx = *IVI.idx_begin();
1380fe6060f1SDimitry Andric 
1381fe6060f1SDimitry Andric   // Compute the result based on what we're inserting.
1382fe6060f1SDimitry Andric   for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
1383fe6060f1SDimitry Andric     // This passes through all values that aren't the inserted element.
1384fe6060f1SDimitry Andric     if (i != Idx) {
1385fe6060f1SDimitry Andric       ValueLatticeElement EltVal = getStructValueState(Aggr, i);
1386fe6060f1SDimitry Andric       mergeInValue(getStructValueState(&IVI, i), &IVI, EltVal);
1387fe6060f1SDimitry Andric       continue;
1388fe6060f1SDimitry Andric     }
1389fe6060f1SDimitry Andric 
1390fe6060f1SDimitry Andric     Value *Val = IVI.getInsertedValueOperand();
1391fe6060f1SDimitry Andric     if (Val->getType()->isStructTy())
1392fe6060f1SDimitry Andric       // We don't track structs in structs.
1393fe6060f1SDimitry Andric       markOverdefined(getStructValueState(&IVI, i), &IVI);
1394fe6060f1SDimitry Andric     else {
1395fe6060f1SDimitry Andric       ValueLatticeElement InVal = getValueState(Val);
1396fe6060f1SDimitry Andric       mergeInValue(getStructValueState(&IVI, i), &IVI, InVal);
1397fe6060f1SDimitry Andric     }
1398fe6060f1SDimitry Andric   }
1399fe6060f1SDimitry Andric }
1400fe6060f1SDimitry Andric 
1401fe6060f1SDimitry Andric void SCCPInstVisitor::visitSelectInst(SelectInst &I) {
1402fe6060f1SDimitry Andric   // If this select returns a struct, just mark the result overdefined.
1403fe6060f1SDimitry Andric   // TODO: We could do a lot better than this if code actually uses this.
1404fe6060f1SDimitry Andric   if (I.getType()->isStructTy())
1405fe6060f1SDimitry Andric     return (void)markOverdefined(&I);
1406fe6060f1SDimitry Andric 
1407fe6060f1SDimitry Andric   // resolvedUndefsIn might mark I as overdefined. Bail out, even if we would
1408fe6060f1SDimitry Andric   // discover a concrete value later.
1409fe6060f1SDimitry Andric   if (ValueState[&I].isOverdefined())
1410fe6060f1SDimitry Andric     return (void)markOverdefined(&I);
1411fe6060f1SDimitry Andric 
1412fe6060f1SDimitry Andric   ValueLatticeElement CondValue = getValueState(I.getCondition());
1413fe6060f1SDimitry Andric   if (CondValue.isUnknownOrUndef())
1414fe6060f1SDimitry Andric     return;
1415fe6060f1SDimitry Andric 
141606c3fb27SDimitry Andric   if (ConstantInt *CondCB =
141706c3fb27SDimitry Andric           getConstantInt(CondValue, I.getCondition()->getType())) {
1418fe6060f1SDimitry Andric     Value *OpVal = CondCB->isZero() ? I.getFalseValue() : I.getTrueValue();
1419fe6060f1SDimitry Andric     mergeInValue(&I, getValueState(OpVal));
1420fe6060f1SDimitry Andric     return;
1421fe6060f1SDimitry Andric   }
1422fe6060f1SDimitry Andric 
1423fe6060f1SDimitry Andric   // Otherwise, the condition is overdefined or a constant we can't evaluate.
1424fe6060f1SDimitry Andric   // See if we can produce something better than overdefined based on the T/F
1425fe6060f1SDimitry Andric   // value.
1426fe6060f1SDimitry Andric   ValueLatticeElement TVal = getValueState(I.getTrueValue());
1427fe6060f1SDimitry Andric   ValueLatticeElement FVal = getValueState(I.getFalseValue());
1428fe6060f1SDimitry Andric 
1429fe6060f1SDimitry Andric   bool Changed = ValueState[&I].mergeIn(TVal);
1430fe6060f1SDimitry Andric   Changed |= ValueState[&I].mergeIn(FVal);
1431fe6060f1SDimitry Andric   if (Changed)
1432fe6060f1SDimitry Andric     pushToWorkListMsg(ValueState[&I], &I);
1433fe6060f1SDimitry Andric }
1434fe6060f1SDimitry Andric 
1435fe6060f1SDimitry Andric // Handle Unary Operators.
1436fe6060f1SDimitry Andric void SCCPInstVisitor::visitUnaryOperator(Instruction &I) {
1437fe6060f1SDimitry Andric   ValueLatticeElement V0State = getValueState(I.getOperand(0));
1438fe6060f1SDimitry Andric 
1439fe6060f1SDimitry Andric   ValueLatticeElement &IV = ValueState[&I];
1440fe6060f1SDimitry Andric   // resolvedUndefsIn might mark I as overdefined. Bail out, even if we would
1441fe6060f1SDimitry Andric   // discover a concrete value later.
1442bdd1243dSDimitry Andric   if (SCCPSolver::isOverdefined(IV))
1443fe6060f1SDimitry Andric     return (void)markOverdefined(&I);
1444fe6060f1SDimitry Andric 
1445753f127fSDimitry Andric   // If something is unknown/undef, wait for it to resolve.
1446753f127fSDimitry Andric   if (V0State.isUnknownOrUndef())
1447fe6060f1SDimitry Andric     return;
1448753f127fSDimitry Andric 
1449bdd1243dSDimitry Andric   if (SCCPSolver::isConstant(V0State))
145006c3fb27SDimitry Andric     if (Constant *C = ConstantFoldUnaryOpOperand(
145106c3fb27SDimitry Andric             I.getOpcode(), getConstant(V0State, I.getType()), DL))
1452fe6060f1SDimitry Andric       return (void)markConstant(IV, &I, C);
1453fe6060f1SDimitry Andric 
1454fe6060f1SDimitry Andric   markOverdefined(&I);
1455fe6060f1SDimitry Andric }
1456fe6060f1SDimitry Andric 
145706c3fb27SDimitry Andric void SCCPInstVisitor::visitFreezeInst(FreezeInst &I) {
145806c3fb27SDimitry Andric   // If this freeze returns a struct, just mark the result overdefined.
145906c3fb27SDimitry Andric   // TODO: We could do a lot better than this.
146006c3fb27SDimitry Andric   if (I.getType()->isStructTy())
146106c3fb27SDimitry Andric     return (void)markOverdefined(&I);
146206c3fb27SDimitry Andric 
146306c3fb27SDimitry Andric   ValueLatticeElement V0State = getValueState(I.getOperand(0));
146406c3fb27SDimitry Andric   ValueLatticeElement &IV = ValueState[&I];
146506c3fb27SDimitry Andric   // resolvedUndefsIn might mark I as overdefined. Bail out, even if we would
146606c3fb27SDimitry Andric   // discover a concrete value later.
146706c3fb27SDimitry Andric   if (SCCPSolver::isOverdefined(IV))
146806c3fb27SDimitry Andric     return (void)markOverdefined(&I);
146906c3fb27SDimitry Andric 
147006c3fb27SDimitry Andric   // If something is unknown/undef, wait for it to resolve.
147106c3fb27SDimitry Andric   if (V0State.isUnknownOrUndef())
147206c3fb27SDimitry Andric     return;
147306c3fb27SDimitry Andric 
147406c3fb27SDimitry Andric   if (SCCPSolver::isConstant(V0State) &&
147506c3fb27SDimitry Andric       isGuaranteedNotToBeUndefOrPoison(getConstant(V0State, I.getType())))
147606c3fb27SDimitry Andric     return (void)markConstant(IV, &I, getConstant(V0State, I.getType()));
147706c3fb27SDimitry Andric 
147806c3fb27SDimitry Andric   markOverdefined(&I);
147906c3fb27SDimitry Andric }
148006c3fb27SDimitry Andric 
1481fe6060f1SDimitry Andric // Handle Binary Operators.
1482fe6060f1SDimitry Andric void SCCPInstVisitor::visitBinaryOperator(Instruction &I) {
1483fe6060f1SDimitry Andric   ValueLatticeElement V1State = getValueState(I.getOperand(0));
1484fe6060f1SDimitry Andric   ValueLatticeElement V2State = getValueState(I.getOperand(1));
1485fe6060f1SDimitry Andric 
1486fe6060f1SDimitry Andric   ValueLatticeElement &IV = ValueState[&I];
1487fe6060f1SDimitry Andric   if (IV.isOverdefined())
1488fe6060f1SDimitry Andric     return;
1489fe6060f1SDimitry Andric 
1490fe6060f1SDimitry Andric   // If something is undef, wait for it to resolve.
1491fe6060f1SDimitry Andric   if (V1State.isUnknownOrUndef() || V2State.isUnknownOrUndef())
1492fe6060f1SDimitry Andric     return;
1493fe6060f1SDimitry Andric 
1494fe6060f1SDimitry Andric   if (V1State.isOverdefined() && V2State.isOverdefined())
1495fe6060f1SDimitry Andric     return (void)markOverdefined(&I);
1496fe6060f1SDimitry Andric 
1497fe6060f1SDimitry Andric   // If either of the operands is a constant, try to fold it to a constant.
1498fe6060f1SDimitry Andric   // TODO: Use information from notconstant better.
1499fe6060f1SDimitry Andric   if ((V1State.isConstant() || V2State.isConstant())) {
150006c3fb27SDimitry Andric     Value *V1 = SCCPSolver::isConstant(V1State)
150106c3fb27SDimitry Andric                     ? getConstant(V1State, I.getOperand(0)->getType())
1502bdd1243dSDimitry Andric                     : I.getOperand(0);
150306c3fb27SDimitry Andric     Value *V2 = SCCPSolver::isConstant(V2State)
150406c3fb27SDimitry Andric                     ? getConstant(V2State, I.getOperand(1)->getType())
1505bdd1243dSDimitry Andric                     : I.getOperand(1);
150681ad6265SDimitry Andric     Value *R = simplifyBinOp(I.getOpcode(), V1, V2, SimplifyQuery(DL));
1507fe6060f1SDimitry Andric     auto *C = dyn_cast_or_null<Constant>(R);
1508fe6060f1SDimitry Andric     if (C) {
1509fe6060f1SDimitry Andric       // Conservatively assume that the result may be based on operands that may
1510fe6060f1SDimitry Andric       // be undef. Note that we use mergeInValue to combine the constant with
1511fe6060f1SDimitry Andric       // the existing lattice value for I, as different constants might be found
1512fe6060f1SDimitry Andric       // after one of the operands go to overdefined, e.g. due to one operand
1513fe6060f1SDimitry Andric       // being a special floating value.
1514fe6060f1SDimitry Andric       ValueLatticeElement NewV;
1515fe6060f1SDimitry Andric       NewV.markConstant(C, /*MayIncludeUndef=*/true);
1516fe6060f1SDimitry Andric       return (void)mergeInValue(&I, NewV);
1517fe6060f1SDimitry Andric     }
1518fe6060f1SDimitry Andric   }
1519fe6060f1SDimitry Andric 
1520fe6060f1SDimitry Andric   // Only use ranges for binary operators on integers.
1521*0fca6ea1SDimitry Andric   if (!I.getType()->isIntOrIntVectorTy())
1522fe6060f1SDimitry Andric     return markOverdefined(&I);
1523fe6060f1SDimitry Andric 
1524fe6060f1SDimitry Andric   // Try to simplify to a constant range.
1525*0fca6ea1SDimitry Andric   ConstantRange A =
1526*0fca6ea1SDimitry Andric       V1State.asConstantRange(I.getType(), /*UndefAllowed=*/false);
1527*0fca6ea1SDimitry Andric   ConstantRange B =
1528*0fca6ea1SDimitry Andric       V2State.asConstantRange(I.getType(), /*UndefAllowed=*/false);
1529*0fca6ea1SDimitry Andric 
1530*0fca6ea1SDimitry Andric   auto *BO = cast<BinaryOperator>(&I);
1531*0fca6ea1SDimitry Andric   ConstantRange R = ConstantRange::getEmpty(I.getType()->getScalarSizeInBits());
1532*0fca6ea1SDimitry Andric   if (auto *OBO = dyn_cast<OverflowingBinaryOperator>(BO))
1533*0fca6ea1SDimitry Andric     R = A.overflowingBinaryOp(BO->getOpcode(), B, OBO->getNoWrapKind());
1534*0fca6ea1SDimitry Andric   else
1535*0fca6ea1SDimitry Andric     R = A.binaryOp(BO->getOpcode(), B);
1536fe6060f1SDimitry Andric   mergeInValue(&I, ValueLatticeElement::getRange(R));
1537fe6060f1SDimitry Andric 
1538fe6060f1SDimitry Andric   // TODO: Currently we do not exploit special values that produce something
1539fe6060f1SDimitry Andric   // better than overdefined with an overdefined operand for vector or floating
1540fe6060f1SDimitry Andric   // point types, like and <4 x i32> overdefined, zeroinitializer.
1541fe6060f1SDimitry Andric }
1542fe6060f1SDimitry Andric 
1543fe6060f1SDimitry Andric // Handle ICmpInst instruction.
1544fe6060f1SDimitry Andric void SCCPInstVisitor::visitCmpInst(CmpInst &I) {
1545fe6060f1SDimitry Andric   // Do not cache this lookup, getValueState calls later in the function might
1546fe6060f1SDimitry Andric   // invalidate the reference.
1547bdd1243dSDimitry Andric   if (SCCPSolver::isOverdefined(ValueState[&I]))
1548fe6060f1SDimitry Andric     return (void)markOverdefined(&I);
1549fe6060f1SDimitry Andric 
1550fe6060f1SDimitry Andric   Value *Op1 = I.getOperand(0);
1551fe6060f1SDimitry Andric   Value *Op2 = I.getOperand(1);
1552fe6060f1SDimitry Andric 
1553fe6060f1SDimitry Andric   // For parameters, use ParamState which includes constant range info if
1554fe6060f1SDimitry Andric   // available.
1555fe6060f1SDimitry Andric   auto V1State = getValueState(Op1);
1556fe6060f1SDimitry Andric   auto V2State = getValueState(Op2);
1557fe6060f1SDimitry Andric 
1558bdd1243dSDimitry Andric   Constant *C = V1State.getCompare(I.getPredicate(), I.getType(), V2State, DL);
1559fe6060f1SDimitry Andric   if (C) {
1560fe6060f1SDimitry Andric     ValueLatticeElement CV;
1561fe6060f1SDimitry Andric     CV.markConstant(C);
1562fe6060f1SDimitry Andric     mergeInValue(&I, CV);
1563fe6060f1SDimitry Andric     return;
1564fe6060f1SDimitry Andric   }
1565fe6060f1SDimitry Andric 
1566fe6060f1SDimitry Andric   // If operands are still unknown, wait for it to resolve.
1567fe6060f1SDimitry Andric   if ((V1State.isUnknownOrUndef() || V2State.isUnknownOrUndef()) &&
1568bdd1243dSDimitry Andric       !SCCPSolver::isConstant(ValueState[&I]))
1569fe6060f1SDimitry Andric     return;
1570fe6060f1SDimitry Andric 
1571fe6060f1SDimitry Andric   markOverdefined(&I);
1572fe6060f1SDimitry Andric }
1573fe6060f1SDimitry Andric 
1574fe6060f1SDimitry Andric // Handle getelementptr instructions.  If all operands are constants then we
1575fe6060f1SDimitry Andric // can turn this into a getelementptr ConstantExpr.
1576fe6060f1SDimitry Andric void SCCPInstVisitor::visitGetElementPtrInst(GetElementPtrInst &I) {
1577bdd1243dSDimitry Andric   if (SCCPSolver::isOverdefined(ValueState[&I]))
1578fe6060f1SDimitry Andric     return (void)markOverdefined(&I);
1579fe6060f1SDimitry Andric 
1580fe6060f1SDimitry Andric   SmallVector<Constant *, 8> Operands;
1581fe6060f1SDimitry Andric   Operands.reserve(I.getNumOperands());
1582fe6060f1SDimitry Andric 
1583fe6060f1SDimitry Andric   for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) {
1584fe6060f1SDimitry Andric     ValueLatticeElement State = getValueState(I.getOperand(i));
1585fe6060f1SDimitry Andric     if (State.isUnknownOrUndef())
1586fe6060f1SDimitry Andric       return; // Operands are not resolved yet.
1587fe6060f1SDimitry Andric 
1588bdd1243dSDimitry Andric     if (SCCPSolver::isOverdefined(State))
1589fe6060f1SDimitry Andric       return (void)markOverdefined(&I);
1590fe6060f1SDimitry Andric 
159106c3fb27SDimitry Andric     if (Constant *C = getConstant(State, I.getOperand(i)->getType())) {
1592fe6060f1SDimitry Andric       Operands.push_back(C);
1593fe6060f1SDimitry Andric       continue;
1594fe6060f1SDimitry Andric     }
1595fe6060f1SDimitry Andric 
1596fe6060f1SDimitry Andric     return (void)markOverdefined(&I);
1597fe6060f1SDimitry Andric   }
1598fe6060f1SDimitry Andric 
15995f757f3fSDimitry Andric   if (Constant *C = ConstantFoldInstOperands(&I, Operands, DL))
1600fe6060f1SDimitry Andric     markConstant(&I, C);
1601fe6060f1SDimitry Andric }
1602fe6060f1SDimitry Andric 
1603fe6060f1SDimitry Andric void SCCPInstVisitor::visitStoreInst(StoreInst &SI) {
1604fe6060f1SDimitry Andric   // If this store is of a struct, ignore it.
1605fe6060f1SDimitry Andric   if (SI.getOperand(0)->getType()->isStructTy())
1606fe6060f1SDimitry Andric     return;
1607fe6060f1SDimitry Andric 
1608fe6060f1SDimitry Andric   if (TrackedGlobals.empty() || !isa<GlobalVariable>(SI.getOperand(1)))
1609fe6060f1SDimitry Andric     return;
1610fe6060f1SDimitry Andric 
1611fe6060f1SDimitry Andric   GlobalVariable *GV = cast<GlobalVariable>(SI.getOperand(1));
1612fe6060f1SDimitry Andric   auto I = TrackedGlobals.find(GV);
1613fe6060f1SDimitry Andric   if (I == TrackedGlobals.end())
1614fe6060f1SDimitry Andric     return;
1615fe6060f1SDimitry Andric 
1616fe6060f1SDimitry Andric   // Get the value we are storing into the global, then merge it.
1617fe6060f1SDimitry Andric   mergeInValue(I->second, GV, getValueState(SI.getOperand(0)),
1618fe6060f1SDimitry Andric                ValueLatticeElement::MergeOptions().setCheckWiden(false));
1619fe6060f1SDimitry Andric   if (I->second.isOverdefined())
1620fe6060f1SDimitry Andric     TrackedGlobals.erase(I); // No need to keep tracking this!
1621fe6060f1SDimitry Andric }
1622fe6060f1SDimitry Andric 
1623fe6060f1SDimitry Andric static ValueLatticeElement getValueFromMetadata(const Instruction *I) {
1624*0fca6ea1SDimitry Andric   if (I->getType()->isIntOrIntVectorTy()) {
1625fe6060f1SDimitry Andric     if (MDNode *Ranges = I->getMetadata(LLVMContext::MD_range))
1626fe6060f1SDimitry Andric       return ValueLatticeElement::getRange(
1627fe6060f1SDimitry Andric           getConstantRangeFromMetadata(*Ranges));
1628*0fca6ea1SDimitry Andric 
1629*0fca6ea1SDimitry Andric     if (const auto *CB = dyn_cast<CallBase>(I))
1630*0fca6ea1SDimitry Andric       if (std::optional<ConstantRange> Range = CB->getRange())
1631*0fca6ea1SDimitry Andric         return ValueLatticeElement::getRange(*Range);
1632*0fca6ea1SDimitry Andric   }
1633fe6060f1SDimitry Andric   if (I->hasMetadata(LLVMContext::MD_nonnull))
1634fe6060f1SDimitry Andric     return ValueLatticeElement::getNot(
1635fe6060f1SDimitry Andric         ConstantPointerNull::get(cast<PointerType>(I->getType())));
1636fe6060f1SDimitry Andric   return ValueLatticeElement::getOverdefined();
1637fe6060f1SDimitry Andric }
1638fe6060f1SDimitry Andric 
1639fe6060f1SDimitry Andric // Handle load instructions.  If the operand is a constant pointer to a constant
1640fe6060f1SDimitry Andric // global, we can replace the load with the loaded constant value!
1641fe6060f1SDimitry Andric void SCCPInstVisitor::visitLoadInst(LoadInst &I) {
1642fe6060f1SDimitry Andric   // If this load is of a struct or the load is volatile, just mark the result
1643fe6060f1SDimitry Andric   // as overdefined.
1644fe6060f1SDimitry Andric   if (I.getType()->isStructTy() || I.isVolatile())
1645fe6060f1SDimitry Andric     return (void)markOverdefined(&I);
1646fe6060f1SDimitry Andric 
1647fe6060f1SDimitry Andric   // resolvedUndefsIn might mark I as overdefined. Bail out, even if we would
1648fe6060f1SDimitry Andric   // discover a concrete value later.
1649fe6060f1SDimitry Andric   if (ValueState[&I].isOverdefined())
1650fe6060f1SDimitry Andric     return (void)markOverdefined(&I);
1651fe6060f1SDimitry Andric 
1652fe6060f1SDimitry Andric   ValueLatticeElement PtrVal = getValueState(I.getOperand(0));
1653fe6060f1SDimitry Andric   if (PtrVal.isUnknownOrUndef())
1654fe6060f1SDimitry Andric     return; // The pointer is not resolved yet!
1655fe6060f1SDimitry Andric 
1656fe6060f1SDimitry Andric   ValueLatticeElement &IV = ValueState[&I];
1657fe6060f1SDimitry Andric 
1658bdd1243dSDimitry Andric   if (SCCPSolver::isConstant(PtrVal)) {
165906c3fb27SDimitry Andric     Constant *Ptr = getConstant(PtrVal, I.getOperand(0)->getType());
1660fe6060f1SDimitry Andric 
1661fe6060f1SDimitry Andric     // load null is undefined.
1662fe6060f1SDimitry Andric     if (isa<ConstantPointerNull>(Ptr)) {
1663fe6060f1SDimitry Andric       if (NullPointerIsDefined(I.getFunction(), I.getPointerAddressSpace()))
1664fe6060f1SDimitry Andric         return (void)markOverdefined(IV, &I);
1665fe6060f1SDimitry Andric       else
1666fe6060f1SDimitry Andric         return;
1667fe6060f1SDimitry Andric     }
1668fe6060f1SDimitry Andric 
1669fe6060f1SDimitry Andric     // Transform load (constant global) into the value loaded.
1670fe6060f1SDimitry Andric     if (auto *GV = dyn_cast<GlobalVariable>(Ptr)) {
1671fe6060f1SDimitry Andric       if (!TrackedGlobals.empty()) {
1672fe6060f1SDimitry Andric         // If we are tracking this global, merge in the known value for it.
1673fe6060f1SDimitry Andric         auto It = TrackedGlobals.find(GV);
1674fe6060f1SDimitry Andric         if (It != TrackedGlobals.end()) {
1675fe6060f1SDimitry Andric           mergeInValue(IV, &I, It->second, getMaxWidenStepsOpts());
1676fe6060f1SDimitry Andric           return;
1677fe6060f1SDimitry Andric         }
1678fe6060f1SDimitry Andric       }
1679fe6060f1SDimitry Andric     }
1680fe6060f1SDimitry Andric 
1681fe6060f1SDimitry Andric     // Transform load from a constant into a constant if possible.
1682753f127fSDimitry Andric     if (Constant *C = ConstantFoldLoadFromConstPtr(Ptr, I.getType(), DL))
1683fe6060f1SDimitry Andric       return (void)markConstant(IV, &I, C);
1684fe6060f1SDimitry Andric   }
1685fe6060f1SDimitry Andric 
1686fe6060f1SDimitry Andric   // Fall back to metadata.
1687fe6060f1SDimitry Andric   mergeInValue(&I, getValueFromMetadata(&I));
1688fe6060f1SDimitry Andric }
1689fe6060f1SDimitry Andric 
1690fe6060f1SDimitry Andric void SCCPInstVisitor::visitCallBase(CallBase &CB) {
1691fe6060f1SDimitry Andric   handleCallResult(CB);
1692fe6060f1SDimitry Andric   handleCallArguments(CB);
1693fe6060f1SDimitry Andric }
1694fe6060f1SDimitry Andric 
1695fe6060f1SDimitry Andric void SCCPInstVisitor::handleCallOverdefined(CallBase &CB) {
1696fe6060f1SDimitry Andric   Function *F = CB.getCalledFunction();
1697fe6060f1SDimitry Andric 
1698fe6060f1SDimitry Andric   // Void return and not tracking callee, just bail.
1699fe6060f1SDimitry Andric   if (CB.getType()->isVoidTy())
1700fe6060f1SDimitry Andric     return;
1701fe6060f1SDimitry Andric 
1702fe6060f1SDimitry Andric   // Always mark struct return as overdefined.
1703fe6060f1SDimitry Andric   if (CB.getType()->isStructTy())
1704fe6060f1SDimitry Andric     return (void)markOverdefined(&CB);
1705fe6060f1SDimitry Andric 
1706fe6060f1SDimitry Andric   // Otherwise, if we have a single return value case, and if the function is
1707fe6060f1SDimitry Andric   // a declaration, maybe we can constant fold it.
1708fe6060f1SDimitry Andric   if (F && F->isDeclaration() && canConstantFoldCallTo(&CB, F)) {
1709fe6060f1SDimitry Andric     SmallVector<Constant *, 8> Operands;
1710349cc55cSDimitry Andric     for (const Use &A : CB.args()) {
1711349cc55cSDimitry Andric       if (A.get()->getType()->isStructTy())
1712fe6060f1SDimitry Andric         return markOverdefined(&CB); // Can't handle struct args.
1713bdd1243dSDimitry Andric       if (A.get()->getType()->isMetadataTy())
1714bdd1243dSDimitry Andric         continue;                    // Carried in CB, not allowed in Operands.
1715349cc55cSDimitry Andric       ValueLatticeElement State = getValueState(A);
1716fe6060f1SDimitry Andric 
1717fe6060f1SDimitry Andric       if (State.isUnknownOrUndef())
1718fe6060f1SDimitry Andric         return; // Operands are not resolved yet.
1719bdd1243dSDimitry Andric       if (SCCPSolver::isOverdefined(State))
1720fe6060f1SDimitry Andric         return (void)markOverdefined(&CB);
1721bdd1243dSDimitry Andric       assert(SCCPSolver::isConstant(State) && "Unknown state!");
172206c3fb27SDimitry Andric       Operands.push_back(getConstant(State, A->getType()));
1723fe6060f1SDimitry Andric     }
1724fe6060f1SDimitry Andric 
1725bdd1243dSDimitry Andric     if (SCCPSolver::isOverdefined(getValueState(&CB)))
1726fe6060f1SDimitry Andric       return (void)markOverdefined(&CB);
1727fe6060f1SDimitry Andric 
1728fe6060f1SDimitry Andric     // If we can constant fold this, mark the result of the call as a
1729fe6060f1SDimitry Andric     // constant.
1730753f127fSDimitry Andric     if (Constant *C = ConstantFoldCall(&CB, F, Operands, &GetTLI(*F)))
1731fe6060f1SDimitry Andric       return (void)markConstant(&CB, C);
1732fe6060f1SDimitry Andric   }
1733fe6060f1SDimitry Andric 
1734fe6060f1SDimitry Andric   // Fall back to metadata.
1735fe6060f1SDimitry Andric   mergeInValue(&CB, getValueFromMetadata(&CB));
1736fe6060f1SDimitry Andric }
1737fe6060f1SDimitry Andric 
1738fe6060f1SDimitry Andric void SCCPInstVisitor::handleCallArguments(CallBase &CB) {
1739fe6060f1SDimitry Andric   Function *F = CB.getCalledFunction();
1740fe6060f1SDimitry Andric   // If this is a local function that doesn't have its address taken, mark its
1741fe6060f1SDimitry Andric   // entry block executable and merge in the actual arguments to the call into
1742fe6060f1SDimitry Andric   // the formal arguments of the function.
1743bdd1243dSDimitry Andric   if (TrackingIncomingArguments.count(F)) {
1744fe6060f1SDimitry Andric     markBlockExecutable(&F->front());
1745fe6060f1SDimitry Andric 
1746fe6060f1SDimitry Andric     // Propagate information from this call site into the callee.
1747fe6060f1SDimitry Andric     auto CAI = CB.arg_begin();
1748fe6060f1SDimitry Andric     for (Function::arg_iterator AI = F->arg_begin(), E = F->arg_end(); AI != E;
1749fe6060f1SDimitry Andric          ++AI, ++CAI) {
1750fe6060f1SDimitry Andric       // If this argument is byval, and if the function is not readonly, there
1751fe6060f1SDimitry Andric       // will be an implicit copy formed of the input aggregate.
1752fe6060f1SDimitry Andric       if (AI->hasByValAttr() && !F->onlyReadsMemory()) {
1753fe6060f1SDimitry Andric         markOverdefined(&*AI);
1754fe6060f1SDimitry Andric         continue;
1755fe6060f1SDimitry Andric       }
1756fe6060f1SDimitry Andric 
1757fe6060f1SDimitry Andric       if (auto *STy = dyn_cast<StructType>(AI->getType())) {
1758fe6060f1SDimitry Andric         for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
1759fe6060f1SDimitry Andric           ValueLatticeElement CallArg = getStructValueState(*CAI, i);
1760fe6060f1SDimitry Andric           mergeInValue(getStructValueState(&*AI, i), &*AI, CallArg,
1761fe6060f1SDimitry Andric                        getMaxWidenStepsOpts());
1762fe6060f1SDimitry Andric         }
1763fe6060f1SDimitry Andric       } else
1764fe6060f1SDimitry Andric         mergeInValue(&*AI, getValueState(*CAI), getMaxWidenStepsOpts());
1765fe6060f1SDimitry Andric     }
1766fe6060f1SDimitry Andric   }
1767fe6060f1SDimitry Andric }
1768fe6060f1SDimitry Andric 
1769fe6060f1SDimitry Andric void SCCPInstVisitor::handleCallResult(CallBase &CB) {
1770fe6060f1SDimitry Andric   Function *F = CB.getCalledFunction();
1771fe6060f1SDimitry Andric 
1772fe6060f1SDimitry Andric   if (auto *II = dyn_cast<IntrinsicInst>(&CB)) {
1773fe6060f1SDimitry Andric     if (II->getIntrinsicID() == Intrinsic::ssa_copy) {
1774fe6060f1SDimitry Andric       if (ValueState[&CB].isOverdefined())
1775fe6060f1SDimitry Andric         return;
1776fe6060f1SDimitry Andric 
1777fe6060f1SDimitry Andric       Value *CopyOf = CB.getOperand(0);
1778fe6060f1SDimitry Andric       ValueLatticeElement CopyOfVal = getValueState(CopyOf);
1779fe6060f1SDimitry Andric       const auto *PI = getPredicateInfoFor(&CB);
1780fe6060f1SDimitry Andric       assert(PI && "Missing predicate info for ssa.copy");
1781fe6060f1SDimitry Andric 
1782bdd1243dSDimitry Andric       const std::optional<PredicateConstraint> &Constraint =
1783bdd1243dSDimitry Andric           PI->getConstraint();
1784fe6060f1SDimitry Andric       if (!Constraint) {
1785fe6060f1SDimitry Andric         mergeInValue(ValueState[&CB], &CB, CopyOfVal);
1786fe6060f1SDimitry Andric         return;
1787fe6060f1SDimitry Andric       }
1788fe6060f1SDimitry Andric 
1789fe6060f1SDimitry Andric       CmpInst::Predicate Pred = Constraint->Predicate;
1790fe6060f1SDimitry Andric       Value *OtherOp = Constraint->OtherOp;
1791fe6060f1SDimitry Andric 
1792fe6060f1SDimitry Andric       // Wait until OtherOp is resolved.
1793fe6060f1SDimitry Andric       if (getValueState(OtherOp).isUnknown()) {
1794fe6060f1SDimitry Andric         addAdditionalUser(OtherOp, &CB);
1795fe6060f1SDimitry Andric         return;
1796fe6060f1SDimitry Andric       }
1797fe6060f1SDimitry Andric 
1798fe6060f1SDimitry Andric       ValueLatticeElement CondVal = getValueState(OtherOp);
1799fe6060f1SDimitry Andric       ValueLatticeElement &IV = ValueState[&CB];
1800fe6060f1SDimitry Andric       if (CondVal.isConstantRange() || CopyOfVal.isConstantRange()) {
1801fe6060f1SDimitry Andric         auto ImposedCR =
1802fe6060f1SDimitry Andric             ConstantRange::getFull(DL.getTypeSizeInBits(CopyOf->getType()));
1803fe6060f1SDimitry Andric 
1804fe6060f1SDimitry Andric         // Get the range imposed by the condition.
1805fe6060f1SDimitry Andric         if (CondVal.isConstantRange())
1806fe6060f1SDimitry Andric           ImposedCR = ConstantRange::makeAllowedICmpRegion(
1807fe6060f1SDimitry Andric               Pred, CondVal.getConstantRange());
1808fe6060f1SDimitry Andric 
1809fe6060f1SDimitry Andric         // Combine range info for the original value with the new range from the
1810fe6060f1SDimitry Andric         // condition.
1811*0fca6ea1SDimitry Andric         auto CopyOfCR = CopyOfVal.asConstantRange(CopyOf->getType(),
1812*0fca6ea1SDimitry Andric                                                   /*UndefAllowed=*/true);
1813*0fca6ea1SDimitry Andric         // Treat an unresolved input like a full range.
1814*0fca6ea1SDimitry Andric         if (CopyOfCR.isEmptySet())
1815*0fca6ea1SDimitry Andric           CopyOfCR = ConstantRange::getFull(CopyOfCR.getBitWidth());
1816fe6060f1SDimitry Andric         auto NewCR = ImposedCR.intersectWith(CopyOfCR);
1817fe6060f1SDimitry Andric         // If the existing information is != x, do not use the information from
1818fe6060f1SDimitry Andric         // a chained predicate, as the != x information is more likely to be
1819fe6060f1SDimitry Andric         // helpful in practice.
1820fe6060f1SDimitry Andric         if (!CopyOfCR.contains(NewCR) && CopyOfCR.getSingleMissingElement())
1821fe6060f1SDimitry Andric           NewCR = CopyOfCR;
1822fe6060f1SDimitry Andric 
182381ad6265SDimitry Andric         // The new range is based on a branch condition. That guarantees that
182481ad6265SDimitry Andric         // neither of the compare operands can be undef in the branch targets,
182581ad6265SDimitry Andric         // unless we have conditions that are always true/false (e.g. icmp ule
182681ad6265SDimitry Andric         // i32, %a, i32_max). For the latter overdefined/empty range will be
182781ad6265SDimitry Andric         // inferred, but the branch will get folded accordingly anyways.
1828fe6060f1SDimitry Andric         addAdditionalUser(OtherOp, &CB);
182981ad6265SDimitry Andric         mergeInValue(
183081ad6265SDimitry Andric             IV, &CB,
183181ad6265SDimitry Andric             ValueLatticeElement::getRange(NewCR, /*MayIncludeUndef*/ false));
1832fe6060f1SDimitry Andric         return;
1833bdd1243dSDimitry Andric       } else if (Pred == CmpInst::ICMP_EQ &&
1834bdd1243dSDimitry Andric                  (CondVal.isConstant() || CondVal.isNotConstant())) {
1835fe6060f1SDimitry Andric         // For non-integer values or integer constant expressions, only
1836bdd1243dSDimitry Andric         // propagate equal constants or not-constants.
1837fe6060f1SDimitry Andric         addAdditionalUser(OtherOp, &CB);
1838fe6060f1SDimitry Andric         mergeInValue(IV, &CB, CondVal);
1839fe6060f1SDimitry Andric         return;
184081ad6265SDimitry Andric       } else if (Pred == CmpInst::ICMP_NE && CondVal.isConstant()) {
1841fe6060f1SDimitry Andric         // Propagate inequalities.
1842fe6060f1SDimitry Andric         addAdditionalUser(OtherOp, &CB);
1843fe6060f1SDimitry Andric         mergeInValue(IV, &CB,
1844fe6060f1SDimitry Andric                      ValueLatticeElement::getNot(CondVal.getConstant()));
1845fe6060f1SDimitry Andric         return;
1846fe6060f1SDimitry Andric       }
1847fe6060f1SDimitry Andric 
1848fe6060f1SDimitry Andric       return (void)mergeInValue(IV, &CB, CopyOfVal);
1849fe6060f1SDimitry Andric     }
1850fe6060f1SDimitry Andric 
1851fe6060f1SDimitry Andric     if (ConstantRange::isIntrinsicSupported(II->getIntrinsicID())) {
1852fe6060f1SDimitry Andric       // Compute result range for intrinsics supported by ConstantRange.
1853fe6060f1SDimitry Andric       // Do this even if we don't know a range for all operands, as we may
1854fe6060f1SDimitry Andric       // still know something about the result range, e.g. of abs(x).
1855fe6060f1SDimitry Andric       SmallVector<ConstantRange, 2> OpRanges;
1856fe6060f1SDimitry Andric       for (Value *Op : II->args()) {
1857fe6060f1SDimitry Andric         const ValueLatticeElement &State = getValueState(Op);
185806c3fb27SDimitry Andric         if (State.isUnknownOrUndef())
185906c3fb27SDimitry Andric           return;
1860*0fca6ea1SDimitry Andric         OpRanges.push_back(
1861*0fca6ea1SDimitry Andric             State.asConstantRange(Op->getType(), /*UndefAllowed=*/false));
1862fe6060f1SDimitry Andric       }
1863fe6060f1SDimitry Andric 
1864fe6060f1SDimitry Andric       ConstantRange Result =
1865fe6060f1SDimitry Andric           ConstantRange::intrinsic(II->getIntrinsicID(), OpRanges);
1866fe6060f1SDimitry Andric       return (void)mergeInValue(II, ValueLatticeElement::getRange(Result));
1867fe6060f1SDimitry Andric     }
1868fe6060f1SDimitry Andric   }
1869fe6060f1SDimitry Andric 
1870fe6060f1SDimitry Andric   // The common case is that we aren't tracking the callee, either because we
1871fe6060f1SDimitry Andric   // are not doing interprocedural analysis or the callee is indirect, or is
1872fe6060f1SDimitry Andric   // external.  Handle these cases first.
1873fe6060f1SDimitry Andric   if (!F || F->isDeclaration())
1874fe6060f1SDimitry Andric     return handleCallOverdefined(CB);
1875fe6060f1SDimitry Andric 
1876fe6060f1SDimitry Andric   // If this is a single/zero retval case, see if we're tracking the function.
1877fe6060f1SDimitry Andric   if (auto *STy = dyn_cast<StructType>(F->getReturnType())) {
1878fe6060f1SDimitry Andric     if (!MRVFunctionsTracked.count(F))
1879fe6060f1SDimitry Andric       return handleCallOverdefined(CB); // Not tracking this callee.
1880fe6060f1SDimitry Andric 
1881fe6060f1SDimitry Andric     // If we are tracking this callee, propagate the result of the function
1882fe6060f1SDimitry Andric     // into this call site.
1883fe6060f1SDimitry Andric     for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i)
1884fe6060f1SDimitry Andric       mergeInValue(getStructValueState(&CB, i), &CB,
1885fe6060f1SDimitry Andric                    TrackedMultipleRetVals[std::make_pair(F, i)],
1886fe6060f1SDimitry Andric                    getMaxWidenStepsOpts());
1887fe6060f1SDimitry Andric   } else {
1888fe6060f1SDimitry Andric     auto TFRVI = TrackedRetVals.find(F);
1889fe6060f1SDimitry Andric     if (TFRVI == TrackedRetVals.end())
1890fe6060f1SDimitry Andric       return handleCallOverdefined(CB); // Not tracking this callee.
1891fe6060f1SDimitry Andric 
1892fe6060f1SDimitry Andric     // If so, propagate the return value of the callee into this call result.
1893fe6060f1SDimitry Andric     mergeInValue(&CB, TFRVI->second, getMaxWidenStepsOpts());
1894fe6060f1SDimitry Andric   }
1895fe6060f1SDimitry Andric }
1896fe6060f1SDimitry Andric 
1897fe6060f1SDimitry Andric void SCCPInstVisitor::solve() {
1898fe6060f1SDimitry Andric   // Process the work lists until they are empty!
1899fe6060f1SDimitry Andric   while (!BBWorkList.empty() || !InstWorkList.empty() ||
1900fe6060f1SDimitry Andric          !OverdefinedInstWorkList.empty()) {
1901fe6060f1SDimitry Andric     // Process the overdefined instruction's work list first, which drives other
1902fe6060f1SDimitry Andric     // things to overdefined more quickly.
1903fe6060f1SDimitry Andric     while (!OverdefinedInstWorkList.empty()) {
1904fe6060f1SDimitry Andric       Value *I = OverdefinedInstWorkList.pop_back_val();
190506c3fb27SDimitry Andric       Invalidated.erase(I);
1906fe6060f1SDimitry Andric 
1907fe6060f1SDimitry Andric       LLVM_DEBUG(dbgs() << "\nPopped off OI-WL: " << *I << '\n');
1908fe6060f1SDimitry Andric 
1909fe6060f1SDimitry Andric       // "I" got into the work list because it either made the transition from
1910fe6060f1SDimitry Andric       // bottom to constant, or to overdefined.
1911fe6060f1SDimitry Andric       //
1912fe6060f1SDimitry Andric       // Anything on this worklist that is overdefined need not be visited
1913fe6060f1SDimitry Andric       // since all of its users will have already been marked as overdefined
1914fe6060f1SDimitry Andric       // Update all of the users of this instruction's value.
1915fe6060f1SDimitry Andric       //
1916fe6060f1SDimitry Andric       markUsersAsChanged(I);
1917fe6060f1SDimitry Andric     }
1918fe6060f1SDimitry Andric 
1919fe6060f1SDimitry Andric     // Process the instruction work list.
1920fe6060f1SDimitry Andric     while (!InstWorkList.empty()) {
1921fe6060f1SDimitry Andric       Value *I = InstWorkList.pop_back_val();
192206c3fb27SDimitry Andric       Invalidated.erase(I);
1923fe6060f1SDimitry Andric 
1924fe6060f1SDimitry Andric       LLVM_DEBUG(dbgs() << "\nPopped off I-WL: " << *I << '\n');
1925fe6060f1SDimitry Andric 
1926fe6060f1SDimitry Andric       // "I" got into the work list because it made the transition from undef to
1927fe6060f1SDimitry Andric       // constant.
1928fe6060f1SDimitry Andric       //
1929fe6060f1SDimitry Andric       // Anything on this worklist that is overdefined need not be visited
1930fe6060f1SDimitry Andric       // since all of its users will have already been marked as overdefined.
1931fe6060f1SDimitry Andric       // Update all of the users of this instruction's value.
1932fe6060f1SDimitry Andric       //
1933fe6060f1SDimitry Andric       if (I->getType()->isStructTy() || !getValueState(I).isOverdefined())
1934fe6060f1SDimitry Andric         markUsersAsChanged(I);
1935fe6060f1SDimitry Andric     }
1936fe6060f1SDimitry Andric 
1937fe6060f1SDimitry Andric     // Process the basic block work list.
1938fe6060f1SDimitry Andric     while (!BBWorkList.empty()) {
1939fe6060f1SDimitry Andric       BasicBlock *BB = BBWorkList.pop_back_val();
1940fe6060f1SDimitry Andric 
1941fe6060f1SDimitry Andric       LLVM_DEBUG(dbgs() << "\nPopped off BBWL: " << *BB << '\n');
1942fe6060f1SDimitry Andric 
1943fe6060f1SDimitry Andric       // Notify all instructions in this basic block that they are newly
1944fe6060f1SDimitry Andric       // executable.
1945fe6060f1SDimitry Andric       visit(BB);
1946fe6060f1SDimitry Andric     }
1947fe6060f1SDimitry Andric   }
1948fe6060f1SDimitry Andric }
1949fe6060f1SDimitry Andric 
195006c3fb27SDimitry Andric bool SCCPInstVisitor::resolvedUndef(Instruction &I) {
195106c3fb27SDimitry Andric   // Look for instructions which produce undef values.
195206c3fb27SDimitry Andric   if (I.getType()->isVoidTy())
195306c3fb27SDimitry Andric     return false;
195406c3fb27SDimitry Andric 
195506c3fb27SDimitry Andric   if (auto *STy = dyn_cast<StructType>(I.getType())) {
195606c3fb27SDimitry Andric     // Only a few things that can be structs matter for undef.
195706c3fb27SDimitry Andric 
195806c3fb27SDimitry Andric     // Tracked calls must never be marked overdefined in resolvedUndefsIn.
195906c3fb27SDimitry Andric     if (auto *CB = dyn_cast<CallBase>(&I))
196006c3fb27SDimitry Andric       if (Function *F = CB->getCalledFunction())
196106c3fb27SDimitry Andric         if (MRVFunctionsTracked.count(F))
196206c3fb27SDimitry Andric           return false;
196306c3fb27SDimitry Andric 
196406c3fb27SDimitry Andric     // extractvalue and insertvalue don't need to be marked; they are
196506c3fb27SDimitry Andric     // tracked as precisely as their operands.
196606c3fb27SDimitry Andric     if (isa<ExtractValueInst>(I) || isa<InsertValueInst>(I))
196706c3fb27SDimitry Andric       return false;
196806c3fb27SDimitry Andric     // Send the results of everything else to overdefined.  We could be
196906c3fb27SDimitry Andric     // more precise than this but it isn't worth bothering.
197006c3fb27SDimitry Andric     for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
197106c3fb27SDimitry Andric       ValueLatticeElement &LV = getStructValueState(&I, i);
197206c3fb27SDimitry Andric       if (LV.isUnknown()) {
197306c3fb27SDimitry Andric         markOverdefined(LV, &I);
197406c3fb27SDimitry Andric         return true;
197506c3fb27SDimitry Andric       }
197606c3fb27SDimitry Andric     }
197706c3fb27SDimitry Andric     return false;
197806c3fb27SDimitry Andric   }
197906c3fb27SDimitry Andric 
198006c3fb27SDimitry Andric   ValueLatticeElement &LV = getValueState(&I);
198106c3fb27SDimitry Andric   if (!LV.isUnknown())
198206c3fb27SDimitry Andric     return false;
198306c3fb27SDimitry Andric 
198406c3fb27SDimitry Andric   // There are two reasons a call can have an undef result
198506c3fb27SDimitry Andric   // 1. It could be tracked.
198606c3fb27SDimitry Andric   // 2. It could be constant-foldable.
198706c3fb27SDimitry Andric   // Because of the way we solve return values, tracked calls must
198806c3fb27SDimitry Andric   // never be marked overdefined in resolvedUndefsIn.
198906c3fb27SDimitry Andric   if (auto *CB = dyn_cast<CallBase>(&I))
199006c3fb27SDimitry Andric     if (Function *F = CB->getCalledFunction())
199106c3fb27SDimitry Andric       if (TrackedRetVals.count(F))
199206c3fb27SDimitry Andric         return false;
199306c3fb27SDimitry Andric 
199406c3fb27SDimitry Andric   if (isa<LoadInst>(I)) {
199506c3fb27SDimitry Andric     // A load here means one of two things: a load of undef from a global,
199606c3fb27SDimitry Andric     // a load from an unknown pointer.  Either way, having it return undef
199706c3fb27SDimitry Andric     // is okay.
199806c3fb27SDimitry Andric     return false;
199906c3fb27SDimitry Andric   }
200006c3fb27SDimitry Andric 
200106c3fb27SDimitry Andric   markOverdefined(&I);
200206c3fb27SDimitry Andric   return true;
200306c3fb27SDimitry Andric }
200406c3fb27SDimitry Andric 
200581ad6265SDimitry Andric /// While solving the dataflow for a function, we don't compute a result for
200681ad6265SDimitry Andric /// operations with an undef operand, to allow undef to be lowered to a
200781ad6265SDimitry Andric /// constant later. For example, constant folding of "zext i8 undef to i16"
200881ad6265SDimitry Andric /// would result in "i16 0", and if undef is later lowered to "i8 1", then the
200981ad6265SDimitry Andric /// zext result would become "i16 1" and would result into an overdefined
201081ad6265SDimitry Andric /// lattice value once merged with the previous result. Not computing the
201181ad6265SDimitry Andric /// result of the zext (treating undef the same as unknown) allows us to handle
201281ad6265SDimitry Andric /// a later undef->constant lowering more optimally.
2013fe6060f1SDimitry Andric ///
201481ad6265SDimitry Andric /// However, if the operand remains undef when the solver returns, we do need
201581ad6265SDimitry Andric /// to assign some result to the instruction (otherwise we would treat it as
201681ad6265SDimitry Andric /// unreachable). For simplicity, we mark any instructions that are still
201781ad6265SDimitry Andric /// unknown as overdefined.
2018fe6060f1SDimitry Andric bool SCCPInstVisitor::resolvedUndefsIn(Function &F) {
2019fe6060f1SDimitry Andric   bool MadeChange = false;
2020fe6060f1SDimitry Andric   for (BasicBlock &BB : F) {
2021fe6060f1SDimitry Andric     if (!BBExecutable.count(&BB))
2022fe6060f1SDimitry Andric       continue;
2023fe6060f1SDimitry Andric 
202406c3fb27SDimitry Andric     for (Instruction &I : BB)
202506c3fb27SDimitry Andric       MadeChange |= resolvedUndef(I);
2026fe6060f1SDimitry Andric   }
2027fe6060f1SDimitry Andric 
2028bdd1243dSDimitry Andric   LLVM_DEBUG(if (MadeChange) dbgs()
2029bdd1243dSDimitry Andric              << "\nResolved undefs in " << F.getName() << '\n');
2030bdd1243dSDimitry Andric 
2031fe6060f1SDimitry Andric   return MadeChange;
2032fe6060f1SDimitry Andric }
2033fe6060f1SDimitry Andric 
2034fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
2035fe6060f1SDimitry Andric //
2036fe6060f1SDimitry Andric // SCCPSolver implementations
2037fe6060f1SDimitry Andric //
2038fe6060f1SDimitry Andric SCCPSolver::SCCPSolver(
2039fe6060f1SDimitry Andric     const DataLayout &DL,
2040fe6060f1SDimitry Andric     std::function<const TargetLibraryInfo &(Function &)> GetTLI,
2041fe6060f1SDimitry Andric     LLVMContext &Ctx)
2042fe6060f1SDimitry Andric     : Visitor(new SCCPInstVisitor(DL, std::move(GetTLI), Ctx)) {}
2043fe6060f1SDimitry Andric 
204481ad6265SDimitry Andric SCCPSolver::~SCCPSolver() = default;
2045fe6060f1SDimitry Andric 
204606c3fb27SDimitry Andric void SCCPSolver::addPredicateInfo(Function &F, DominatorTree &DT,
204706c3fb27SDimitry Andric                                   AssumptionCache &AC) {
204806c3fb27SDimitry Andric   Visitor->addPredicateInfo(F, DT, AC);
2049fe6060f1SDimitry Andric }
2050fe6060f1SDimitry Andric 
2051fe6060f1SDimitry Andric bool SCCPSolver::markBlockExecutable(BasicBlock *BB) {
2052fe6060f1SDimitry Andric   return Visitor->markBlockExecutable(BB);
2053fe6060f1SDimitry Andric }
2054fe6060f1SDimitry Andric 
2055fe6060f1SDimitry Andric const PredicateBase *SCCPSolver::getPredicateInfoFor(Instruction *I) {
2056fe6060f1SDimitry Andric   return Visitor->getPredicateInfoFor(I);
2057fe6060f1SDimitry Andric }
2058fe6060f1SDimitry Andric 
2059fe6060f1SDimitry Andric void SCCPSolver::trackValueOfGlobalVariable(GlobalVariable *GV) {
2060fe6060f1SDimitry Andric   Visitor->trackValueOfGlobalVariable(GV);
2061fe6060f1SDimitry Andric }
2062fe6060f1SDimitry Andric 
2063fe6060f1SDimitry Andric void SCCPSolver::addTrackedFunction(Function *F) {
2064fe6060f1SDimitry Andric   Visitor->addTrackedFunction(F);
2065fe6060f1SDimitry Andric }
2066fe6060f1SDimitry Andric 
2067fe6060f1SDimitry Andric void SCCPSolver::addToMustPreserveReturnsInFunctions(Function *F) {
2068fe6060f1SDimitry Andric   Visitor->addToMustPreserveReturnsInFunctions(F);
2069fe6060f1SDimitry Andric }
2070fe6060f1SDimitry Andric 
2071fe6060f1SDimitry Andric bool SCCPSolver::mustPreserveReturn(Function *F) {
2072fe6060f1SDimitry Andric   return Visitor->mustPreserveReturn(F);
2073fe6060f1SDimitry Andric }
2074fe6060f1SDimitry Andric 
2075fe6060f1SDimitry Andric void SCCPSolver::addArgumentTrackedFunction(Function *F) {
2076fe6060f1SDimitry Andric   Visitor->addArgumentTrackedFunction(F);
2077fe6060f1SDimitry Andric }
2078fe6060f1SDimitry Andric 
2079fe6060f1SDimitry Andric bool SCCPSolver::isArgumentTrackedFunction(Function *F) {
2080fe6060f1SDimitry Andric   return Visitor->isArgumentTrackedFunction(F);
2081fe6060f1SDimitry Andric }
2082fe6060f1SDimitry Andric 
2083fe6060f1SDimitry Andric void SCCPSolver::solve() { Visitor->solve(); }
2084fe6060f1SDimitry Andric 
2085fe6060f1SDimitry Andric bool SCCPSolver::resolvedUndefsIn(Function &F) {
2086fe6060f1SDimitry Andric   return Visitor->resolvedUndefsIn(F);
2087fe6060f1SDimitry Andric }
2088fe6060f1SDimitry Andric 
2089bdd1243dSDimitry Andric void SCCPSolver::solveWhileResolvedUndefsIn(Module &M) {
2090bdd1243dSDimitry Andric   Visitor->solveWhileResolvedUndefsIn(M);
2091bdd1243dSDimitry Andric }
2092bdd1243dSDimitry Andric 
2093bdd1243dSDimitry Andric void
2094bdd1243dSDimitry Andric SCCPSolver::solveWhileResolvedUndefsIn(SmallVectorImpl<Function *> &WorkList) {
2095bdd1243dSDimitry Andric   Visitor->solveWhileResolvedUndefsIn(WorkList);
2096bdd1243dSDimitry Andric }
2097bdd1243dSDimitry Andric 
209806c3fb27SDimitry Andric void SCCPSolver::solveWhileResolvedUndefs() {
209906c3fb27SDimitry Andric   Visitor->solveWhileResolvedUndefs();
210006c3fb27SDimitry Andric }
210106c3fb27SDimitry Andric 
2102fe6060f1SDimitry Andric bool SCCPSolver::isBlockExecutable(BasicBlock *BB) const {
2103fe6060f1SDimitry Andric   return Visitor->isBlockExecutable(BB);
2104fe6060f1SDimitry Andric }
2105fe6060f1SDimitry Andric 
2106fe6060f1SDimitry Andric bool SCCPSolver::isEdgeFeasible(BasicBlock *From, BasicBlock *To) const {
2107fe6060f1SDimitry Andric   return Visitor->isEdgeFeasible(From, To);
2108fe6060f1SDimitry Andric }
2109fe6060f1SDimitry Andric 
2110fe6060f1SDimitry Andric std::vector<ValueLatticeElement>
2111fe6060f1SDimitry Andric SCCPSolver::getStructLatticeValueFor(Value *V) const {
2112fe6060f1SDimitry Andric   return Visitor->getStructLatticeValueFor(V);
2113fe6060f1SDimitry Andric }
2114fe6060f1SDimitry Andric 
2115fe6060f1SDimitry Andric void SCCPSolver::removeLatticeValueFor(Value *V) {
2116fe6060f1SDimitry Andric   return Visitor->removeLatticeValueFor(V);
2117fe6060f1SDimitry Andric }
2118fe6060f1SDimitry Andric 
211906c3fb27SDimitry Andric void SCCPSolver::resetLatticeValueFor(CallBase *Call) {
212006c3fb27SDimitry Andric   Visitor->resetLatticeValueFor(Call);
212106c3fb27SDimitry Andric }
212206c3fb27SDimitry Andric 
2123fe6060f1SDimitry Andric const ValueLatticeElement &SCCPSolver::getLatticeValueFor(Value *V) const {
2124fe6060f1SDimitry Andric   return Visitor->getLatticeValueFor(V);
2125fe6060f1SDimitry Andric }
2126fe6060f1SDimitry Andric 
2127fe6060f1SDimitry Andric const MapVector<Function *, ValueLatticeElement> &
2128fe6060f1SDimitry Andric SCCPSolver::getTrackedRetVals() {
2129fe6060f1SDimitry Andric   return Visitor->getTrackedRetVals();
2130fe6060f1SDimitry Andric }
2131fe6060f1SDimitry Andric 
2132fe6060f1SDimitry Andric const DenseMap<GlobalVariable *, ValueLatticeElement> &
2133fe6060f1SDimitry Andric SCCPSolver::getTrackedGlobals() {
2134fe6060f1SDimitry Andric   return Visitor->getTrackedGlobals();
2135fe6060f1SDimitry Andric }
2136fe6060f1SDimitry Andric 
2137fe6060f1SDimitry Andric const SmallPtrSet<Function *, 16> SCCPSolver::getMRVFunctionsTracked() {
2138fe6060f1SDimitry Andric   return Visitor->getMRVFunctionsTracked();
2139fe6060f1SDimitry Andric }
2140fe6060f1SDimitry Andric 
2141fe6060f1SDimitry Andric void SCCPSolver::markOverdefined(Value *V) { Visitor->markOverdefined(V); }
2142fe6060f1SDimitry Andric 
2143*0fca6ea1SDimitry Andric void SCCPSolver::trackValueOfArgument(Argument *V) {
2144*0fca6ea1SDimitry Andric   Visitor->trackValueOfArgument(V);
2145*0fca6ea1SDimitry Andric }
2146*0fca6ea1SDimitry Andric 
2147fe6060f1SDimitry Andric bool SCCPSolver::isStructLatticeConstant(Function *F, StructType *STy) {
2148fe6060f1SDimitry Andric   return Visitor->isStructLatticeConstant(F, STy);
2149fe6060f1SDimitry Andric }
2150fe6060f1SDimitry Andric 
215106c3fb27SDimitry Andric Constant *SCCPSolver::getConstant(const ValueLatticeElement &LV,
215206c3fb27SDimitry Andric                                   Type *Ty) const {
215306c3fb27SDimitry Andric   return Visitor->getConstant(LV, Ty);
215406c3fb27SDimitry Andric }
215506c3fb27SDimitry Andric 
215606c3fb27SDimitry Andric Constant *SCCPSolver::getConstantOrNull(Value *V) const {
215706c3fb27SDimitry Andric   return Visitor->getConstantOrNull(V);
2158fe6060f1SDimitry Andric }
2159fe6060f1SDimitry Andric 
2160fe6060f1SDimitry Andric SmallPtrSetImpl<Function *> &SCCPSolver::getArgumentTrackedFunctions() {
2161fe6060f1SDimitry Andric   return Visitor->getArgumentTrackedFunctions();
2162fe6060f1SDimitry Andric }
2163fe6060f1SDimitry Andric 
216406c3fb27SDimitry Andric void SCCPSolver::setLatticeValueForSpecializationArguments(Function *F,
216506c3fb27SDimitry Andric                                    const SmallVectorImpl<ArgInfo> &Args) {
216606c3fb27SDimitry Andric   Visitor->setLatticeValueForSpecializationArguments(F, Args);
2167fe6060f1SDimitry Andric }
2168fe6060f1SDimitry Andric 
2169fe6060f1SDimitry Andric void SCCPSolver::markFunctionUnreachable(Function *F) {
2170fe6060f1SDimitry Andric   Visitor->markFunctionUnreachable(F);
2171fe6060f1SDimitry Andric }
2172fe6060f1SDimitry Andric 
2173fe6060f1SDimitry Andric void SCCPSolver::visit(Instruction *I) { Visitor->visit(I); }
2174fe6060f1SDimitry Andric 
2175fe6060f1SDimitry Andric void SCCPSolver::visitCall(CallInst &I) { Visitor->visitCall(I); }
2176