xref: /src/contrib/llvm-project/llvm/lib/Transforms/Utils/SCCPSolver.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1344a3780SDimitry Andric //===- SCCPSolver.cpp - SCCP Utility --------------------------- *- C++ -*-===//
2344a3780SDimitry Andric //
3344a3780SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4344a3780SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5344a3780SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6344a3780SDimitry Andric //
7344a3780SDimitry Andric //===----------------------------------------------------------------------===//
8344a3780SDimitry Andric //
9344a3780SDimitry Andric // \file
10344a3780SDimitry Andric // This file implements the Sparse Conditional Constant Propagation (SCCP)
11344a3780SDimitry Andric // utility.
12344a3780SDimitry Andric //
13344a3780SDimitry Andric //===----------------------------------------------------------------------===//
14344a3780SDimitry Andric 
15344a3780SDimitry Andric #include "llvm/Transforms/Utils/SCCPSolver.h"
16344a3780SDimitry Andric #include "llvm/Analysis/ConstantFolding.h"
17344a3780SDimitry Andric #include "llvm/Analysis/InstructionSimplify.h"
18145449b1SDimitry Andric #include "llvm/Analysis/ValueLattice.h"
19e3b55780SDimitry Andric #include "llvm/Analysis/ValueLatticeUtils.h"
207fa27ce4SDimitry Andric #include "llvm/Analysis/ValueTracking.h"
21145449b1SDimitry Andric #include "llvm/IR/InstVisitor.h"
22344a3780SDimitry Andric #include "llvm/Support/Casting.h"
23344a3780SDimitry Andric #include "llvm/Support/Debug.h"
24344a3780SDimitry Andric #include "llvm/Support/ErrorHandling.h"
25344a3780SDimitry Andric #include "llvm/Support/raw_ostream.h"
26e3b55780SDimitry Andric #include "llvm/Transforms/Utils/Local.h"
27344a3780SDimitry Andric #include <cassert>
28344a3780SDimitry Andric #include <utility>
29344a3780SDimitry Andric #include <vector>
30344a3780SDimitry Andric 
31344a3780SDimitry Andric using namespace llvm;
32344a3780SDimitry Andric 
33344a3780SDimitry Andric #define DEBUG_TYPE "sccp"
34344a3780SDimitry Andric 
35344a3780SDimitry Andric // The maximum number of range extensions allowed for operations requiring
36344a3780SDimitry Andric // widening.
37344a3780SDimitry Andric static const unsigned MaxNumRangeExtensions = 10;
38344a3780SDimitry Andric 
39344a3780SDimitry Andric /// Returns MergeOptions with MaxWidenSteps set to MaxNumRangeExtensions.
getMaxWidenStepsOpts()40344a3780SDimitry Andric static ValueLatticeElement::MergeOptions getMaxWidenStepsOpts() {
41344a3780SDimitry Andric   return ValueLatticeElement::MergeOptions().setMaxWidenSteps(
42344a3780SDimitry Andric       MaxNumRangeExtensions);
43344a3780SDimitry Andric }
44344a3780SDimitry Andric 
45e3b55780SDimitry Andric namespace llvm {
46344a3780SDimitry Andric 
isConstant(const ValueLatticeElement & LV)47e3b55780SDimitry Andric bool SCCPSolver::isConstant(const ValueLatticeElement &LV) {
48344a3780SDimitry Andric   return LV.isConstant() ||
49344a3780SDimitry Andric          (LV.isConstantRange() && LV.getConstantRange().isSingleElement());
50344a3780SDimitry Andric }
51344a3780SDimitry Andric 
isOverdefined(const ValueLatticeElement & LV)52e3b55780SDimitry Andric bool SCCPSolver::isOverdefined(const ValueLatticeElement &LV) {
53e3b55780SDimitry Andric   return !LV.isUnknownOrUndef() && !SCCPSolver::isConstant(LV);
54344a3780SDimitry Andric }
55344a3780SDimitry Andric 
canRemoveInstruction(Instruction * I)56e3b55780SDimitry Andric static bool canRemoveInstruction(Instruction *I) {
57e3b55780SDimitry Andric   if (wouldInstructionBeTriviallyDead(I))
58e3b55780SDimitry Andric     return true;
59344a3780SDimitry Andric 
60e3b55780SDimitry Andric   // Some instructions can be handled but are rejected above. Catch
61e3b55780SDimitry Andric   // those cases by falling through to here.
62e3b55780SDimitry Andric   // TODO: Mark globals as being constant earlier, so
63e3b55780SDimitry Andric   // TODO: wouldInstructionBeTriviallyDead() knows that atomic loads
64e3b55780SDimitry Andric   // TODO: are safe to remove.
65e3b55780SDimitry Andric   return isa<LoadInst>(I);
66e3b55780SDimitry Andric }
67e3b55780SDimitry Andric 
tryToReplaceWithConstant(Value * V)68e3b55780SDimitry Andric bool SCCPSolver::tryToReplaceWithConstant(Value *V) {
697fa27ce4SDimitry Andric   Constant *Const = getConstantOrNull(V);
707fa27ce4SDimitry Andric   if (!Const)
71e3b55780SDimitry Andric     return false;
72e3b55780SDimitry Andric   // Replacing `musttail` instructions with constant breaks `musttail` invariant
73e3b55780SDimitry Andric   // unless the call itself can be removed.
74e3b55780SDimitry Andric   // Calls with "clang.arc.attachedcall" implicitly use the return value and
75e3b55780SDimitry Andric   // those uses cannot be updated with a constant.
76e3b55780SDimitry Andric   CallBase *CB = dyn_cast<CallBase>(V);
77e3b55780SDimitry Andric   if (CB && ((CB->isMustTailCall() &&
78e3b55780SDimitry Andric               !canRemoveInstruction(CB)) ||
79e3b55780SDimitry Andric              CB->getOperandBundle(LLVMContext::OB_clang_arc_attachedcall))) {
80e3b55780SDimitry Andric     Function *F = CB->getCalledFunction();
81e3b55780SDimitry Andric 
82e3b55780SDimitry Andric     // Don't zap returns of the callee
83e3b55780SDimitry Andric     if (F)
84e3b55780SDimitry Andric       addToMustPreserveReturnsInFunctions(F);
85e3b55780SDimitry Andric 
86e3b55780SDimitry Andric     LLVM_DEBUG(dbgs() << "  Can\'t treat the result of call " << *CB
87e3b55780SDimitry Andric                       << " as a constant\n");
88e3b55780SDimitry Andric     return false;
89e3b55780SDimitry Andric   }
90e3b55780SDimitry Andric 
91e3b55780SDimitry Andric   LLVM_DEBUG(dbgs() << "  Constant: " << *Const << " = " << *V << '\n');
92e3b55780SDimitry Andric 
93e3b55780SDimitry Andric   // Replaces all of the uses of a variable with uses of the constant.
94e3b55780SDimitry Andric   V->replaceAllUsesWith(Const);
95e3b55780SDimitry Andric   return true;
96e3b55780SDimitry Andric }
97e3b55780SDimitry Andric 
987fa27ce4SDimitry Andric /// Try to use \p Inst's value range from \p Solver to infer the NUW flag.
refineInstruction(SCCPSolver & Solver,const SmallPtrSetImpl<Value * > & InsertedValues,Instruction & Inst)997fa27ce4SDimitry Andric static bool refineInstruction(SCCPSolver &Solver,
1007fa27ce4SDimitry Andric                               const SmallPtrSetImpl<Value *> &InsertedValues,
1017fa27ce4SDimitry Andric                               Instruction &Inst) {
102b1c73532SDimitry Andric   bool Changed = false;
1037fa27ce4SDimitry Andric   auto GetRange = [&Solver, &InsertedValues](Value *Op) {
104ac9a064cSDimitry Andric     if (auto *Const = dyn_cast<Constant>(Op))
105ac9a064cSDimitry Andric       return Const->toConstantRange();
106ac9a064cSDimitry Andric     if (InsertedValues.contains(Op)) {
1077fa27ce4SDimitry Andric       unsigned Bitwidth = Op->getType()->getScalarSizeInBits();
1087fa27ce4SDimitry Andric       return ConstantRange::getFull(Bitwidth);
1097fa27ce4SDimitry Andric     }
110ac9a064cSDimitry Andric     return Solver.getLatticeValueFor(Op).asConstantRange(
111ac9a064cSDimitry Andric         Op->getType(), /*UndefAllowed=*/false);
1127fa27ce4SDimitry Andric   };
113b1c73532SDimitry Andric 
114b1c73532SDimitry Andric   if (isa<OverflowingBinaryOperator>(Inst)) {
115ac9a064cSDimitry Andric     if (Inst.hasNoSignedWrap() && Inst.hasNoUnsignedWrap())
116ac9a064cSDimitry Andric       return false;
117ac9a064cSDimitry Andric 
1187fa27ce4SDimitry Andric     auto RangeA = GetRange(Inst.getOperand(0));
1197fa27ce4SDimitry Andric     auto RangeB = GetRange(Inst.getOperand(1));
1207fa27ce4SDimitry Andric     if (!Inst.hasNoUnsignedWrap()) {
1217fa27ce4SDimitry Andric       auto NUWRange = ConstantRange::makeGuaranteedNoWrapRegion(
1227fa27ce4SDimitry Andric           Instruction::BinaryOps(Inst.getOpcode()), RangeB,
1237fa27ce4SDimitry Andric           OverflowingBinaryOperator::NoUnsignedWrap);
1247fa27ce4SDimitry Andric       if (NUWRange.contains(RangeA)) {
1257fa27ce4SDimitry Andric         Inst.setHasNoUnsignedWrap();
1267fa27ce4SDimitry Andric         Changed = true;
1277fa27ce4SDimitry Andric       }
1287fa27ce4SDimitry Andric     }
1297fa27ce4SDimitry Andric     if (!Inst.hasNoSignedWrap()) {
1307fa27ce4SDimitry Andric       auto NSWRange = ConstantRange::makeGuaranteedNoWrapRegion(
131b1c73532SDimitry Andric           Instruction::BinaryOps(Inst.getOpcode()), RangeB,
132b1c73532SDimitry Andric           OverflowingBinaryOperator::NoSignedWrap);
1337fa27ce4SDimitry Andric       if (NSWRange.contains(RangeA)) {
1347fa27ce4SDimitry Andric         Inst.setHasNoSignedWrap();
1357fa27ce4SDimitry Andric         Changed = true;
1367fa27ce4SDimitry Andric       }
1377fa27ce4SDimitry Andric     }
138ac9a064cSDimitry Andric   } else if (isa<PossiblyNonNegInst>(Inst) && !Inst.hasNonNeg()) {
139b1c73532SDimitry Andric     auto Range = GetRange(Inst.getOperand(0));
140b1c73532SDimitry Andric     if (Range.isAllNonNegative()) {
141b1c73532SDimitry Andric       Inst.setNonNeg();
142b1c73532SDimitry Andric       Changed = true;
143b1c73532SDimitry Andric     }
144ac9a064cSDimitry Andric   } else if (TruncInst *TI = dyn_cast<TruncInst>(&Inst)) {
145ac9a064cSDimitry Andric     if (TI->hasNoSignedWrap() && TI->hasNoUnsignedWrap())
146ac9a064cSDimitry Andric       return false;
147ac9a064cSDimitry Andric 
148ac9a064cSDimitry Andric     auto Range = GetRange(Inst.getOperand(0));
149ac9a064cSDimitry Andric     uint64_t DestWidth = TI->getDestTy()->getScalarSizeInBits();
150ac9a064cSDimitry Andric     if (!TI->hasNoUnsignedWrap()) {
151ac9a064cSDimitry Andric       if (Range.getActiveBits() <= DestWidth) {
152ac9a064cSDimitry Andric         TI->setHasNoUnsignedWrap(true);
153ac9a064cSDimitry Andric         Changed = true;
154ac9a064cSDimitry Andric       }
155ac9a064cSDimitry Andric     }
156ac9a064cSDimitry Andric     if (!TI->hasNoSignedWrap()) {
157ac9a064cSDimitry Andric       if (Range.getMinSignedBits() <= DestWidth) {
158ac9a064cSDimitry Andric         TI->setHasNoSignedWrap(true);
159ac9a064cSDimitry Andric         Changed = true;
160ac9a064cSDimitry Andric       }
161ac9a064cSDimitry Andric     }
162b1c73532SDimitry Andric   }
1637fa27ce4SDimitry Andric 
1647fa27ce4SDimitry Andric   return Changed;
1657fa27ce4SDimitry Andric }
1667fa27ce4SDimitry Andric 
167e3b55780SDimitry Andric /// Try to replace signed instructions with their unsigned equivalent.
replaceSignedInst(SCCPSolver & Solver,SmallPtrSetImpl<Value * > & InsertedValues,Instruction & Inst)168e3b55780SDimitry Andric static bool replaceSignedInst(SCCPSolver &Solver,
169e3b55780SDimitry Andric                               SmallPtrSetImpl<Value *> &InsertedValues,
170e3b55780SDimitry Andric                               Instruction &Inst) {
171e3b55780SDimitry Andric   // Determine if a signed value is known to be >= 0.
172e3b55780SDimitry Andric   auto isNonNegative = [&Solver](Value *V) {
173e3b55780SDimitry Andric     // If this value was constant-folded, it may not have a solver entry.
174e3b55780SDimitry Andric     // Handle integers. Otherwise, return false.
175e3b55780SDimitry Andric     if (auto *C = dyn_cast<Constant>(V)) {
176e3b55780SDimitry Andric       auto *CInt = dyn_cast<ConstantInt>(C);
177e3b55780SDimitry Andric       return CInt && !CInt->isNegative();
178e3b55780SDimitry Andric     }
179e3b55780SDimitry Andric     const ValueLatticeElement &IV = Solver.getLatticeValueFor(V);
180e3b55780SDimitry Andric     return IV.isConstantRange(/*UndefAllowed=*/false) &&
181e3b55780SDimitry Andric            IV.getConstantRange().isAllNonNegative();
182e3b55780SDimitry Andric   };
183e3b55780SDimitry Andric 
184e3b55780SDimitry Andric   Instruction *NewInst = nullptr;
185e3b55780SDimitry Andric   switch (Inst.getOpcode()) {
186ac9a064cSDimitry Andric   case Instruction::SIToFP:
187e3b55780SDimitry Andric   case Instruction::SExt: {
188ac9a064cSDimitry Andric     // If the source value is not negative, this is a zext/uitofp.
189e3b55780SDimitry Andric     Value *Op0 = Inst.getOperand(0);
190e3b55780SDimitry Andric     if (InsertedValues.count(Op0) || !isNonNegative(Op0))
191e3b55780SDimitry Andric       return false;
192ac9a064cSDimitry Andric     NewInst = CastInst::Create(Inst.getOpcode() == Instruction::SExt
193ac9a064cSDimitry Andric                                    ? Instruction::ZExt
194ac9a064cSDimitry Andric                                    : Instruction::UIToFP,
195ac9a064cSDimitry Andric                                Op0, Inst.getType(), "", Inst.getIterator());
196b1c73532SDimitry Andric     NewInst->setNonNeg();
197e3b55780SDimitry Andric     break;
198e3b55780SDimitry Andric   }
199e3b55780SDimitry Andric   case Instruction::AShr: {
200e3b55780SDimitry Andric     // If the shifted value is not negative, this is a logical shift right.
201e3b55780SDimitry Andric     Value *Op0 = Inst.getOperand(0);
202e3b55780SDimitry Andric     if (InsertedValues.count(Op0) || !isNonNegative(Op0))
203e3b55780SDimitry Andric       return false;
204ac9a064cSDimitry Andric     NewInst = BinaryOperator::CreateLShr(Op0, Inst.getOperand(1), "", Inst.getIterator());
205b1c73532SDimitry Andric     NewInst->setIsExact(Inst.isExact());
206e3b55780SDimitry Andric     break;
207e3b55780SDimitry Andric   }
208e3b55780SDimitry Andric   case Instruction::SDiv:
209e3b55780SDimitry Andric   case Instruction::SRem: {
210e3b55780SDimitry Andric     // If both operands are not negative, this is the same as udiv/urem.
211e3b55780SDimitry Andric     Value *Op0 = Inst.getOperand(0), *Op1 = Inst.getOperand(1);
212e3b55780SDimitry Andric     if (InsertedValues.count(Op0) || InsertedValues.count(Op1) ||
213e3b55780SDimitry Andric         !isNonNegative(Op0) || !isNonNegative(Op1))
214e3b55780SDimitry Andric       return false;
215e3b55780SDimitry Andric     auto NewOpcode = Inst.getOpcode() == Instruction::SDiv ? Instruction::UDiv
216e3b55780SDimitry Andric                                                            : Instruction::URem;
217ac9a064cSDimitry Andric     NewInst = BinaryOperator::Create(NewOpcode, Op0, Op1, "", Inst.getIterator());
218b1c73532SDimitry Andric     if (Inst.getOpcode() == Instruction::SDiv)
219b1c73532SDimitry Andric       NewInst->setIsExact(Inst.isExact());
220e3b55780SDimitry Andric     break;
221e3b55780SDimitry Andric   }
222e3b55780SDimitry Andric   default:
223e3b55780SDimitry Andric     return false;
224e3b55780SDimitry Andric   }
225e3b55780SDimitry Andric 
226e3b55780SDimitry Andric   // Wire up the new instruction and update state.
227e3b55780SDimitry Andric   assert(NewInst && "Expected replacement instruction");
228e3b55780SDimitry Andric   NewInst->takeName(&Inst);
229e3b55780SDimitry Andric   InsertedValues.insert(NewInst);
230e3b55780SDimitry Andric   Inst.replaceAllUsesWith(NewInst);
231ac9a064cSDimitry Andric   NewInst->setDebugLoc(Inst.getDebugLoc());
232e3b55780SDimitry Andric   Solver.removeLatticeValueFor(&Inst);
233e3b55780SDimitry Andric   Inst.eraseFromParent();
234e3b55780SDimitry Andric   return true;
235e3b55780SDimitry Andric }
236e3b55780SDimitry Andric 
simplifyInstsInBlock(BasicBlock & BB,SmallPtrSetImpl<Value * > & InsertedValues,Statistic & InstRemovedStat,Statistic & InstReplacedStat)237e3b55780SDimitry Andric bool SCCPSolver::simplifyInstsInBlock(BasicBlock &BB,
238e3b55780SDimitry Andric                                       SmallPtrSetImpl<Value *> &InsertedValues,
239e3b55780SDimitry Andric                                       Statistic &InstRemovedStat,
240e3b55780SDimitry Andric                                       Statistic &InstReplacedStat) {
241e3b55780SDimitry Andric   bool MadeChanges = false;
242e3b55780SDimitry Andric   for (Instruction &Inst : make_early_inc_range(BB)) {
243e3b55780SDimitry Andric     if (Inst.getType()->isVoidTy())
244e3b55780SDimitry Andric       continue;
245e3b55780SDimitry Andric     if (tryToReplaceWithConstant(&Inst)) {
246e3b55780SDimitry Andric       if (canRemoveInstruction(&Inst))
247e3b55780SDimitry Andric         Inst.eraseFromParent();
248e3b55780SDimitry Andric 
249e3b55780SDimitry Andric       MadeChanges = true;
250e3b55780SDimitry Andric       ++InstRemovedStat;
251e3b55780SDimitry Andric     } else if (replaceSignedInst(*this, InsertedValues, Inst)) {
252e3b55780SDimitry Andric       MadeChanges = true;
253e3b55780SDimitry Andric       ++InstReplacedStat;
2547fa27ce4SDimitry Andric     } else if (refineInstruction(*this, InsertedValues, Inst)) {
2557fa27ce4SDimitry Andric       MadeChanges = true;
256e3b55780SDimitry Andric     }
257e3b55780SDimitry Andric   }
258e3b55780SDimitry Andric   return MadeChanges;
259e3b55780SDimitry Andric }
260e3b55780SDimitry Andric 
removeNonFeasibleEdges(BasicBlock * BB,DomTreeUpdater & DTU,BasicBlock * & NewUnreachableBB) const261e3b55780SDimitry Andric bool SCCPSolver::removeNonFeasibleEdges(BasicBlock *BB, DomTreeUpdater &DTU,
262e3b55780SDimitry Andric                                         BasicBlock *&NewUnreachableBB) const {
263e3b55780SDimitry Andric   SmallPtrSet<BasicBlock *, 8> FeasibleSuccessors;
264e3b55780SDimitry Andric   bool HasNonFeasibleEdges = false;
265e3b55780SDimitry Andric   for (BasicBlock *Succ : successors(BB)) {
266e3b55780SDimitry Andric     if (isEdgeFeasible(BB, Succ))
267e3b55780SDimitry Andric       FeasibleSuccessors.insert(Succ);
268e3b55780SDimitry Andric     else
269e3b55780SDimitry Andric       HasNonFeasibleEdges = true;
270e3b55780SDimitry Andric   }
271e3b55780SDimitry Andric 
272e3b55780SDimitry Andric   // All edges feasible, nothing to do.
273e3b55780SDimitry Andric   if (!HasNonFeasibleEdges)
274e3b55780SDimitry Andric     return false;
275e3b55780SDimitry Andric 
276e3b55780SDimitry Andric   // SCCP can only determine non-feasible edges for br, switch and indirectbr.
277e3b55780SDimitry Andric   Instruction *TI = BB->getTerminator();
278e3b55780SDimitry Andric   assert((isa<BranchInst>(TI) || isa<SwitchInst>(TI) ||
279e3b55780SDimitry Andric           isa<IndirectBrInst>(TI)) &&
280e3b55780SDimitry Andric          "Terminator must be a br, switch or indirectbr");
281e3b55780SDimitry Andric 
282e3b55780SDimitry Andric   if (FeasibleSuccessors.size() == 0) {
283e3b55780SDimitry Andric     // Branch on undef/poison, replace with unreachable.
284e3b55780SDimitry Andric     SmallPtrSet<BasicBlock *, 8> SeenSuccs;
285e3b55780SDimitry Andric     SmallVector<DominatorTree::UpdateType, 8> Updates;
286e3b55780SDimitry Andric     for (BasicBlock *Succ : successors(BB)) {
287e3b55780SDimitry Andric       Succ->removePredecessor(BB);
288e3b55780SDimitry Andric       if (SeenSuccs.insert(Succ).second)
289e3b55780SDimitry Andric         Updates.push_back({DominatorTree::Delete, BB, Succ});
290e3b55780SDimitry Andric     }
291e3b55780SDimitry Andric     TI->eraseFromParent();
292e3b55780SDimitry Andric     new UnreachableInst(BB->getContext(), BB);
293e3b55780SDimitry Andric     DTU.applyUpdatesPermissive(Updates);
294e3b55780SDimitry Andric   } else if (FeasibleSuccessors.size() == 1) {
295e3b55780SDimitry Andric     // Replace with an unconditional branch to the only feasible successor.
296e3b55780SDimitry Andric     BasicBlock *OnlyFeasibleSuccessor = *FeasibleSuccessors.begin();
297e3b55780SDimitry Andric     SmallVector<DominatorTree::UpdateType, 8> Updates;
298e3b55780SDimitry Andric     bool HaveSeenOnlyFeasibleSuccessor = false;
299e3b55780SDimitry Andric     for (BasicBlock *Succ : successors(BB)) {
300e3b55780SDimitry Andric       if (Succ == OnlyFeasibleSuccessor && !HaveSeenOnlyFeasibleSuccessor) {
301e3b55780SDimitry Andric         // Don't remove the edge to the only feasible successor the first time
302e3b55780SDimitry Andric         // we see it. We still do need to remove any multi-edges to it though.
303e3b55780SDimitry Andric         HaveSeenOnlyFeasibleSuccessor = true;
304e3b55780SDimitry Andric         continue;
305e3b55780SDimitry Andric       }
306e3b55780SDimitry Andric 
307e3b55780SDimitry Andric       Succ->removePredecessor(BB);
308e3b55780SDimitry Andric       Updates.push_back({DominatorTree::Delete, BB, Succ});
309e3b55780SDimitry Andric     }
310e3b55780SDimitry Andric 
311ac9a064cSDimitry Andric     Instruction *BI = BranchInst::Create(OnlyFeasibleSuccessor, BB);
312ac9a064cSDimitry Andric     BI->setDebugLoc(TI->getDebugLoc());
313e3b55780SDimitry Andric     TI->eraseFromParent();
314e3b55780SDimitry Andric     DTU.applyUpdatesPermissive(Updates);
315e3b55780SDimitry Andric   } else if (FeasibleSuccessors.size() > 1) {
316e3b55780SDimitry Andric     SwitchInstProfUpdateWrapper SI(*cast<SwitchInst>(TI));
317e3b55780SDimitry Andric     SmallVector<DominatorTree::UpdateType, 8> Updates;
318e3b55780SDimitry Andric 
319e3b55780SDimitry Andric     // If the default destination is unfeasible it will never be taken. Replace
320e3b55780SDimitry Andric     // it with a new block with a single Unreachable instruction.
321e3b55780SDimitry Andric     BasicBlock *DefaultDest = SI->getDefaultDest();
322e3b55780SDimitry Andric     if (!FeasibleSuccessors.contains(DefaultDest)) {
323e3b55780SDimitry Andric       if (!NewUnreachableBB) {
324e3b55780SDimitry Andric         NewUnreachableBB =
325e3b55780SDimitry Andric             BasicBlock::Create(DefaultDest->getContext(), "default.unreachable",
326e3b55780SDimitry Andric                                DefaultDest->getParent(), DefaultDest);
327e3b55780SDimitry Andric         new UnreachableInst(DefaultDest->getContext(), NewUnreachableBB);
328e3b55780SDimitry Andric       }
329e3b55780SDimitry Andric 
330aca2e42cSDimitry Andric       DefaultDest->removePredecessor(BB);
331e3b55780SDimitry Andric       SI->setDefaultDest(NewUnreachableBB);
332e3b55780SDimitry Andric       Updates.push_back({DominatorTree::Delete, BB, DefaultDest});
333e3b55780SDimitry Andric       Updates.push_back({DominatorTree::Insert, BB, NewUnreachableBB});
334e3b55780SDimitry Andric     }
335e3b55780SDimitry Andric 
336e3b55780SDimitry Andric     for (auto CI = SI->case_begin(); CI != SI->case_end();) {
337e3b55780SDimitry Andric       if (FeasibleSuccessors.contains(CI->getCaseSuccessor())) {
338e3b55780SDimitry Andric         ++CI;
339e3b55780SDimitry Andric         continue;
340e3b55780SDimitry Andric       }
341e3b55780SDimitry Andric 
342e3b55780SDimitry Andric       BasicBlock *Succ = CI->getCaseSuccessor();
343e3b55780SDimitry Andric       Succ->removePredecessor(BB);
344e3b55780SDimitry Andric       Updates.push_back({DominatorTree::Delete, BB, Succ});
345e3b55780SDimitry Andric       SI.removeCase(CI);
346e3b55780SDimitry Andric       // Don't increment CI, as we removed a case.
347e3b55780SDimitry Andric     }
348e3b55780SDimitry Andric 
349e3b55780SDimitry Andric     DTU.applyUpdatesPermissive(Updates);
350e3b55780SDimitry Andric   } else {
351e3b55780SDimitry Andric     llvm_unreachable("Must have at least one feasible successor");
352e3b55780SDimitry Andric   }
353e3b55780SDimitry Andric   return true;
354e3b55780SDimitry Andric }
355344a3780SDimitry Andric 
356344a3780SDimitry Andric /// Helper class for SCCPSolver. This implements the instruction visitor and
357344a3780SDimitry Andric /// holds all the state.
358344a3780SDimitry Andric class SCCPInstVisitor : public InstVisitor<SCCPInstVisitor> {
359344a3780SDimitry Andric   const DataLayout &DL;
360344a3780SDimitry Andric   std::function<const TargetLibraryInfo &(Function &)> GetTLI;
361344a3780SDimitry Andric   SmallPtrSet<BasicBlock *, 8> BBExecutable; // The BBs that are executable.
362344a3780SDimitry Andric   DenseMap<Value *, ValueLatticeElement>
363344a3780SDimitry Andric       ValueState; // The state each value is in.
364344a3780SDimitry Andric 
365344a3780SDimitry Andric   /// StructValueState - This maintains ValueState for values that have
366344a3780SDimitry Andric   /// StructType, for example for formal arguments, calls, insertelement, etc.
367344a3780SDimitry Andric   DenseMap<std::pair<Value *, unsigned>, ValueLatticeElement> StructValueState;
368344a3780SDimitry Andric 
369344a3780SDimitry Andric   /// GlobalValue - If we are tracking any values for the contents of a global
370344a3780SDimitry Andric   /// variable, we keep a mapping from the constant accessor to the element of
371344a3780SDimitry Andric   /// the global, to the currently known value.  If the value becomes
372344a3780SDimitry Andric   /// overdefined, it's entry is simply removed from this map.
373344a3780SDimitry Andric   DenseMap<GlobalVariable *, ValueLatticeElement> TrackedGlobals;
374344a3780SDimitry Andric 
375344a3780SDimitry Andric   /// TrackedRetVals - If we are tracking arguments into and the return
376344a3780SDimitry Andric   /// value out of a function, it will have an entry in this map, indicating
377344a3780SDimitry Andric   /// what the known return value for the function is.
378344a3780SDimitry Andric   MapVector<Function *, ValueLatticeElement> TrackedRetVals;
379344a3780SDimitry Andric 
380344a3780SDimitry Andric   /// TrackedMultipleRetVals - Same as TrackedRetVals, but used for functions
381344a3780SDimitry Andric   /// that return multiple values.
382344a3780SDimitry Andric   MapVector<std::pair<Function *, unsigned>, ValueLatticeElement>
383344a3780SDimitry Andric       TrackedMultipleRetVals;
384344a3780SDimitry Andric 
3857fa27ce4SDimitry Andric   /// The set of values whose lattice has been invalidated.
3867fa27ce4SDimitry Andric   /// Populated by resetLatticeValueFor(), cleared after resolving undefs.
3877fa27ce4SDimitry Andric   DenseSet<Value *> Invalidated;
3887fa27ce4SDimitry Andric 
389344a3780SDimitry Andric   /// MRVFunctionsTracked - Each function in TrackedMultipleRetVals is
390344a3780SDimitry Andric   /// represented here for efficient lookup.
391344a3780SDimitry Andric   SmallPtrSet<Function *, 16> MRVFunctionsTracked;
392344a3780SDimitry Andric 
393344a3780SDimitry Andric   /// A list of functions whose return cannot be modified.
394344a3780SDimitry Andric   SmallPtrSet<Function *, 16> MustPreserveReturnsInFunctions;
395344a3780SDimitry Andric 
396344a3780SDimitry Andric   /// TrackingIncomingArguments - This is the set of functions for whose
397344a3780SDimitry Andric   /// arguments we make optimistic assumptions about and try to prove as
398344a3780SDimitry Andric   /// constants.
399344a3780SDimitry Andric   SmallPtrSet<Function *, 16> TrackingIncomingArguments;
400344a3780SDimitry Andric 
401344a3780SDimitry Andric   /// The reason for two worklists is that overdefined is the lowest state
402344a3780SDimitry Andric   /// on the lattice, and moving things to overdefined as fast as possible
403344a3780SDimitry Andric   /// makes SCCP converge much faster.
404344a3780SDimitry Andric   ///
405344a3780SDimitry Andric   /// By having a separate worklist, we accomplish this because everything
406344a3780SDimitry Andric   /// possibly overdefined will become overdefined at the soonest possible
407344a3780SDimitry Andric   /// point.
408344a3780SDimitry Andric   SmallVector<Value *, 64> OverdefinedInstWorkList;
409344a3780SDimitry Andric   SmallVector<Value *, 64> InstWorkList;
410344a3780SDimitry Andric 
411344a3780SDimitry Andric   // The BasicBlock work list
412344a3780SDimitry Andric   SmallVector<BasicBlock *, 64> BBWorkList;
413344a3780SDimitry Andric 
414344a3780SDimitry Andric   /// KnownFeasibleEdges - Entries in this set are edges which have already had
415344a3780SDimitry Andric   /// PHI nodes retriggered.
416344a3780SDimitry Andric   using Edge = std::pair<BasicBlock *, BasicBlock *>;
417344a3780SDimitry Andric   DenseSet<Edge> KnownFeasibleEdges;
418344a3780SDimitry Andric 
4197fa27ce4SDimitry Andric   DenseMap<Function *, std::unique_ptr<PredicateInfo>> FnPredicateInfo;
4207fa27ce4SDimitry Andric 
421344a3780SDimitry Andric   DenseMap<Value *, SmallPtrSet<User *, 2>> AdditionalUsers;
422344a3780SDimitry Andric 
423344a3780SDimitry Andric   LLVMContext &Ctx;
424344a3780SDimitry Andric 
425344a3780SDimitry Andric private:
getConstantInt(const ValueLatticeElement & IV,Type * Ty) const4267fa27ce4SDimitry Andric   ConstantInt *getConstantInt(const ValueLatticeElement &IV, Type *Ty) const {
4277fa27ce4SDimitry Andric     return dyn_cast_or_null<ConstantInt>(getConstant(IV, Ty));
428344a3780SDimitry Andric   }
429344a3780SDimitry Andric 
430344a3780SDimitry Andric   // pushToWorkList - Helper for markConstant/markOverdefined
431344a3780SDimitry Andric   void pushToWorkList(ValueLatticeElement &IV, Value *V);
432344a3780SDimitry Andric 
433344a3780SDimitry Andric   // Helper to push \p V to the worklist, after updating it to \p IV. Also
434344a3780SDimitry Andric   // prints a debug message with the updated value.
435344a3780SDimitry Andric   void pushToWorkListMsg(ValueLatticeElement &IV, Value *V);
436344a3780SDimitry Andric 
437344a3780SDimitry Andric   // markConstant - Make a value be marked as "constant".  If the value
438344a3780SDimitry Andric   // is not already a constant, add it to the instruction work list so that
439344a3780SDimitry Andric   // the users of the instruction are updated later.
440344a3780SDimitry Andric   bool markConstant(ValueLatticeElement &IV, Value *V, Constant *C,
441344a3780SDimitry Andric                     bool MayIncludeUndef = false);
442344a3780SDimitry Andric 
markConstant(Value * V,Constant * C)443344a3780SDimitry Andric   bool markConstant(Value *V, Constant *C) {
444344a3780SDimitry Andric     assert(!V->getType()->isStructTy() && "structs should use mergeInValue");
445344a3780SDimitry Andric     return markConstant(ValueState[V], V, C);
446344a3780SDimitry Andric   }
447344a3780SDimitry Andric 
448ac9a064cSDimitry Andric   /// markConstantRange - Mark the object as constant range with \p CR. If the
449ac9a064cSDimitry Andric   /// object is not a constant range with the range \p CR, add it to the
450ac9a064cSDimitry Andric   /// instruction work list so that the users of the instruction are updated
451ac9a064cSDimitry Andric   /// later.
452ac9a064cSDimitry Andric   bool markConstantRange(ValueLatticeElement &IV, Value *V,
453ac9a064cSDimitry Andric                          const ConstantRange &CR);
454ac9a064cSDimitry Andric 
455344a3780SDimitry Andric   // markOverdefined - Make a value be marked as "overdefined". If the
456344a3780SDimitry Andric   // value is not already overdefined, add it to the overdefined instruction
457344a3780SDimitry Andric   // work list so that the users of the instruction are updated later.
458344a3780SDimitry Andric   bool markOverdefined(ValueLatticeElement &IV, Value *V);
459344a3780SDimitry Andric 
460344a3780SDimitry Andric   /// Merge \p MergeWithV into \p IV and push \p V to the worklist, if \p IV
461344a3780SDimitry Andric   /// changes.
462344a3780SDimitry Andric   bool mergeInValue(ValueLatticeElement &IV, Value *V,
463344a3780SDimitry Andric                     ValueLatticeElement MergeWithV,
464344a3780SDimitry Andric                     ValueLatticeElement::MergeOptions Opts = {
465344a3780SDimitry Andric                         /*MayIncludeUndef=*/false, /*CheckWiden=*/false});
466344a3780SDimitry Andric 
mergeInValue(Value * V,ValueLatticeElement MergeWithV,ValueLatticeElement::MergeOptions Opts={ false, false})467344a3780SDimitry Andric   bool mergeInValue(Value *V, ValueLatticeElement MergeWithV,
468344a3780SDimitry Andric                     ValueLatticeElement::MergeOptions Opts = {
469344a3780SDimitry Andric                         /*MayIncludeUndef=*/false, /*CheckWiden=*/false}) {
470344a3780SDimitry Andric     assert(!V->getType()->isStructTy() &&
471344a3780SDimitry Andric            "non-structs should use markConstant");
472344a3780SDimitry Andric     return mergeInValue(ValueState[V], V, MergeWithV, Opts);
473344a3780SDimitry Andric   }
474344a3780SDimitry Andric 
475344a3780SDimitry Andric   /// getValueState - Return the ValueLatticeElement object that corresponds to
476344a3780SDimitry Andric   /// the value.  This function handles the case when the value hasn't been seen
477344a3780SDimitry Andric   /// yet by properly seeding constants etc.
getValueState(Value * V)478344a3780SDimitry Andric   ValueLatticeElement &getValueState(Value *V) {
479344a3780SDimitry Andric     assert(!V->getType()->isStructTy() && "Should use getStructValueState");
480344a3780SDimitry Andric 
481344a3780SDimitry Andric     auto I = ValueState.insert(std::make_pair(V, ValueLatticeElement()));
482344a3780SDimitry Andric     ValueLatticeElement &LV = I.first->second;
483344a3780SDimitry Andric 
484344a3780SDimitry Andric     if (!I.second)
485344a3780SDimitry Andric       return LV; // Common case, already in the map.
486344a3780SDimitry Andric 
487344a3780SDimitry Andric     if (auto *C = dyn_cast<Constant>(V))
488344a3780SDimitry Andric       LV.markConstant(C); // Constants are constant
489344a3780SDimitry Andric 
490344a3780SDimitry Andric     // All others are unknown by default.
491344a3780SDimitry Andric     return LV;
492344a3780SDimitry Andric   }
493344a3780SDimitry Andric 
494344a3780SDimitry Andric   /// getStructValueState - Return the ValueLatticeElement object that
495344a3780SDimitry Andric   /// corresponds to the value/field pair.  This function handles the case when
496344a3780SDimitry Andric   /// the value hasn't been seen yet by properly seeding constants etc.
getStructValueState(Value * V,unsigned i)497344a3780SDimitry Andric   ValueLatticeElement &getStructValueState(Value *V, unsigned i) {
498344a3780SDimitry Andric     assert(V->getType()->isStructTy() && "Should use getValueState");
499344a3780SDimitry Andric     assert(i < cast<StructType>(V->getType())->getNumElements() &&
500344a3780SDimitry Andric            "Invalid element #");
501344a3780SDimitry Andric 
502344a3780SDimitry Andric     auto I = StructValueState.insert(
503344a3780SDimitry Andric         std::make_pair(std::make_pair(V, i), ValueLatticeElement()));
504344a3780SDimitry Andric     ValueLatticeElement &LV = I.first->second;
505344a3780SDimitry Andric 
506344a3780SDimitry Andric     if (!I.second)
507344a3780SDimitry Andric       return LV; // Common case, already in the map.
508344a3780SDimitry Andric 
509344a3780SDimitry Andric     if (auto *C = dyn_cast<Constant>(V)) {
510344a3780SDimitry Andric       Constant *Elt = C->getAggregateElement(i);
511344a3780SDimitry Andric 
512344a3780SDimitry Andric       if (!Elt)
513344a3780SDimitry Andric         LV.markOverdefined(); // Unknown sort of constant.
514344a3780SDimitry Andric       else
515344a3780SDimitry Andric         LV.markConstant(Elt); // Constants are constant.
516344a3780SDimitry Andric     }
517344a3780SDimitry Andric 
518344a3780SDimitry Andric     // All others are underdefined by default.
519344a3780SDimitry Andric     return LV;
520344a3780SDimitry Andric   }
521344a3780SDimitry Andric 
5227fa27ce4SDimitry Andric   /// Traverse the use-def chain of \p Call, marking itself and its users as
5237fa27ce4SDimitry Andric   /// "unknown" on the way.
invalidate(CallBase * Call)5247fa27ce4SDimitry Andric   void invalidate(CallBase *Call) {
5257fa27ce4SDimitry Andric     SmallVector<Instruction *, 64> ToInvalidate;
5267fa27ce4SDimitry Andric     ToInvalidate.push_back(Call);
5277fa27ce4SDimitry Andric 
5287fa27ce4SDimitry Andric     while (!ToInvalidate.empty()) {
5297fa27ce4SDimitry Andric       Instruction *Inst = ToInvalidate.pop_back_val();
5307fa27ce4SDimitry Andric 
5317fa27ce4SDimitry Andric       if (!Invalidated.insert(Inst).second)
5327fa27ce4SDimitry Andric         continue;
5337fa27ce4SDimitry Andric 
5347fa27ce4SDimitry Andric       if (!BBExecutable.count(Inst->getParent()))
5357fa27ce4SDimitry Andric         continue;
5367fa27ce4SDimitry Andric 
5377fa27ce4SDimitry Andric       Value *V = nullptr;
5387fa27ce4SDimitry Andric       // For return instructions we need to invalidate the tracked returns map.
5397fa27ce4SDimitry Andric       // Anything else has its lattice in the value map.
5407fa27ce4SDimitry Andric       if (auto *RetInst = dyn_cast<ReturnInst>(Inst)) {
5417fa27ce4SDimitry Andric         Function *F = RetInst->getParent()->getParent();
5427fa27ce4SDimitry Andric         if (auto It = TrackedRetVals.find(F); It != TrackedRetVals.end()) {
5437fa27ce4SDimitry Andric           It->second = ValueLatticeElement();
5447fa27ce4SDimitry Andric           V = F;
5457fa27ce4SDimitry Andric         } else if (MRVFunctionsTracked.count(F)) {
5467fa27ce4SDimitry Andric           auto *STy = cast<StructType>(F->getReturnType());
5477fa27ce4SDimitry Andric           for (unsigned I = 0, E = STy->getNumElements(); I != E; ++I)
5487fa27ce4SDimitry Andric             TrackedMultipleRetVals[{F, I}] = ValueLatticeElement();
5497fa27ce4SDimitry Andric           V = F;
5507fa27ce4SDimitry Andric         }
5517fa27ce4SDimitry Andric       } else if (auto *STy = dyn_cast<StructType>(Inst->getType())) {
5527fa27ce4SDimitry Andric         for (unsigned I = 0, E = STy->getNumElements(); I != E; ++I) {
5537fa27ce4SDimitry Andric           if (auto It = StructValueState.find({Inst, I});
5547fa27ce4SDimitry Andric               It != StructValueState.end()) {
5557fa27ce4SDimitry Andric             It->second = ValueLatticeElement();
5567fa27ce4SDimitry Andric             V = Inst;
5577fa27ce4SDimitry Andric           }
5587fa27ce4SDimitry Andric         }
5597fa27ce4SDimitry Andric       } else if (auto It = ValueState.find(Inst); It != ValueState.end()) {
5607fa27ce4SDimitry Andric         It->second = ValueLatticeElement();
5617fa27ce4SDimitry Andric         V = Inst;
5627fa27ce4SDimitry Andric       }
5637fa27ce4SDimitry Andric 
5647fa27ce4SDimitry Andric       if (V) {
5657fa27ce4SDimitry Andric         LLVM_DEBUG(dbgs() << "Invalidated lattice for " << *V << "\n");
5667fa27ce4SDimitry Andric 
5677fa27ce4SDimitry Andric         for (User *U : V->users())
5687fa27ce4SDimitry Andric           if (auto *UI = dyn_cast<Instruction>(U))
5697fa27ce4SDimitry Andric             ToInvalidate.push_back(UI);
5707fa27ce4SDimitry Andric 
5717fa27ce4SDimitry Andric         auto It = AdditionalUsers.find(V);
5727fa27ce4SDimitry Andric         if (It != AdditionalUsers.end())
5737fa27ce4SDimitry Andric           for (User *U : It->second)
5747fa27ce4SDimitry Andric             if (auto *UI = dyn_cast<Instruction>(U))
5757fa27ce4SDimitry Andric               ToInvalidate.push_back(UI);
5767fa27ce4SDimitry Andric       }
5777fa27ce4SDimitry Andric     }
5787fa27ce4SDimitry Andric   }
5797fa27ce4SDimitry Andric 
580344a3780SDimitry Andric   /// markEdgeExecutable - Mark a basic block as executable, adding it to the BB
581344a3780SDimitry Andric   /// work list if it is not already executable.
582344a3780SDimitry Andric   bool markEdgeExecutable(BasicBlock *Source, BasicBlock *Dest);
583344a3780SDimitry Andric 
584344a3780SDimitry Andric   // getFeasibleSuccessors - Return a vector of booleans to indicate which
585344a3780SDimitry Andric   // successors are reachable from a given terminator instruction.
586344a3780SDimitry Andric   void getFeasibleSuccessors(Instruction &TI, SmallVectorImpl<bool> &Succs);
587344a3780SDimitry Andric 
588344a3780SDimitry Andric   // OperandChangedState - This method is invoked on all of the users of an
589344a3780SDimitry Andric   // instruction that was just changed state somehow.  Based on this
590344a3780SDimitry Andric   // information, we need to update the specified user of this instruction.
operandChangedState(Instruction * I)591344a3780SDimitry Andric   void operandChangedState(Instruction *I) {
592344a3780SDimitry Andric     if (BBExecutable.count(I->getParent())) // Inst is executable?
593344a3780SDimitry Andric       visit(*I);
594344a3780SDimitry Andric   }
595344a3780SDimitry Andric 
596344a3780SDimitry Andric   // Add U as additional user of V.
addAdditionalUser(Value * V,User * U)597344a3780SDimitry Andric   void addAdditionalUser(Value *V, User *U) {
598344a3780SDimitry Andric     auto Iter = AdditionalUsers.insert({V, {}});
599344a3780SDimitry Andric     Iter.first->second.insert(U);
600344a3780SDimitry Andric   }
601344a3780SDimitry Andric 
602344a3780SDimitry Andric   // Mark I's users as changed, including AdditionalUsers.
markUsersAsChanged(Value * I)603344a3780SDimitry Andric   void markUsersAsChanged(Value *I) {
604344a3780SDimitry Andric     // Functions include their arguments in the use-list. Changed function
605344a3780SDimitry Andric     // values mean that the result of the function changed. We only need to
606344a3780SDimitry Andric     // update the call sites with the new function result and do not have to
607344a3780SDimitry Andric     // propagate the call arguments.
608344a3780SDimitry Andric     if (isa<Function>(I)) {
609344a3780SDimitry Andric       for (User *U : I->users()) {
610344a3780SDimitry Andric         if (auto *CB = dyn_cast<CallBase>(U))
611344a3780SDimitry Andric           handleCallResult(*CB);
612344a3780SDimitry Andric       }
613344a3780SDimitry Andric     } else {
614344a3780SDimitry Andric       for (User *U : I->users())
615344a3780SDimitry Andric         if (auto *UI = dyn_cast<Instruction>(U))
616344a3780SDimitry Andric           operandChangedState(UI);
617344a3780SDimitry Andric     }
618344a3780SDimitry Andric 
619344a3780SDimitry Andric     auto Iter = AdditionalUsers.find(I);
620344a3780SDimitry Andric     if (Iter != AdditionalUsers.end()) {
621344a3780SDimitry Andric       // Copy additional users before notifying them of changes, because new
622344a3780SDimitry Andric       // users may be added, potentially invalidating the iterator.
623344a3780SDimitry Andric       SmallVector<Instruction *, 2> ToNotify;
624344a3780SDimitry Andric       for (User *U : Iter->second)
625344a3780SDimitry Andric         if (auto *UI = dyn_cast<Instruction>(U))
626344a3780SDimitry Andric           ToNotify.push_back(UI);
627344a3780SDimitry Andric       for (Instruction *UI : ToNotify)
628344a3780SDimitry Andric         operandChangedState(UI);
629344a3780SDimitry Andric     }
630344a3780SDimitry Andric   }
631344a3780SDimitry Andric   void handleCallOverdefined(CallBase &CB);
632344a3780SDimitry Andric   void handleCallResult(CallBase &CB);
633344a3780SDimitry Andric   void handleCallArguments(CallBase &CB);
634e3b55780SDimitry Andric   void handleExtractOfWithOverflow(ExtractValueInst &EVI,
635e3b55780SDimitry Andric                                    const WithOverflowInst *WO, unsigned Idx);
636344a3780SDimitry Andric 
637344a3780SDimitry Andric private:
638344a3780SDimitry Andric   friend class InstVisitor<SCCPInstVisitor>;
639344a3780SDimitry Andric 
640344a3780SDimitry Andric   // visit implementations - Something changed in this instruction.  Either an
641344a3780SDimitry Andric   // operand made a transition, or the instruction is newly executable.  Change
642344a3780SDimitry Andric   // the value type of I to reflect these changes if appropriate.
643344a3780SDimitry Andric   void visitPHINode(PHINode &I);
644344a3780SDimitry Andric 
645344a3780SDimitry Andric   // Terminators
646344a3780SDimitry Andric 
647344a3780SDimitry Andric   void visitReturnInst(ReturnInst &I);
648344a3780SDimitry Andric   void visitTerminator(Instruction &TI);
649344a3780SDimitry Andric 
650344a3780SDimitry Andric   void visitCastInst(CastInst &I);
651344a3780SDimitry Andric   void visitSelectInst(SelectInst &I);
652344a3780SDimitry Andric   void visitUnaryOperator(Instruction &I);
6537fa27ce4SDimitry Andric   void visitFreezeInst(FreezeInst &I);
654344a3780SDimitry Andric   void visitBinaryOperator(Instruction &I);
655344a3780SDimitry Andric   void visitCmpInst(CmpInst &I);
656344a3780SDimitry Andric   void visitExtractValueInst(ExtractValueInst &EVI);
657344a3780SDimitry Andric   void visitInsertValueInst(InsertValueInst &IVI);
658344a3780SDimitry Andric 
visitCatchSwitchInst(CatchSwitchInst & CPI)659344a3780SDimitry Andric   void visitCatchSwitchInst(CatchSwitchInst &CPI) {
660344a3780SDimitry Andric     markOverdefined(&CPI);
661344a3780SDimitry Andric     visitTerminator(CPI);
662344a3780SDimitry Andric   }
663344a3780SDimitry Andric 
664344a3780SDimitry Andric   // Instructions that cannot be folded away.
665344a3780SDimitry Andric 
666344a3780SDimitry Andric   void visitStoreInst(StoreInst &I);
667344a3780SDimitry Andric   void visitLoadInst(LoadInst &I);
668344a3780SDimitry Andric   void visitGetElementPtrInst(GetElementPtrInst &I);
669344a3780SDimitry Andric 
visitInvokeInst(InvokeInst & II)670344a3780SDimitry Andric   void visitInvokeInst(InvokeInst &II) {
671344a3780SDimitry Andric     visitCallBase(II);
672344a3780SDimitry Andric     visitTerminator(II);
673344a3780SDimitry Andric   }
674344a3780SDimitry Andric 
visitCallBrInst(CallBrInst & CBI)675344a3780SDimitry Andric   void visitCallBrInst(CallBrInst &CBI) {
676344a3780SDimitry Andric     visitCallBase(CBI);
677344a3780SDimitry Andric     visitTerminator(CBI);
678344a3780SDimitry Andric   }
679344a3780SDimitry Andric 
680344a3780SDimitry Andric   void visitCallBase(CallBase &CB);
visitResumeInst(ResumeInst & I)681344a3780SDimitry Andric   void visitResumeInst(ResumeInst &I) { /*returns void*/
682344a3780SDimitry Andric   }
visitUnreachableInst(UnreachableInst & I)683344a3780SDimitry Andric   void visitUnreachableInst(UnreachableInst &I) { /*returns void*/
684344a3780SDimitry Andric   }
visitFenceInst(FenceInst & I)685344a3780SDimitry Andric   void visitFenceInst(FenceInst &I) { /*returns void*/
686344a3780SDimitry Andric   }
687344a3780SDimitry Andric 
688344a3780SDimitry Andric   void visitInstruction(Instruction &I);
689344a3780SDimitry Andric 
690344a3780SDimitry Andric public:
addPredicateInfo(Function & F,DominatorTree & DT,AssumptionCache & AC)6917fa27ce4SDimitry Andric   void addPredicateInfo(Function &F, DominatorTree &DT, AssumptionCache &AC) {
6927fa27ce4SDimitry Andric     FnPredicateInfo.insert({&F, std::make_unique<PredicateInfo>(F, DT, AC)});
693344a3780SDimitry Andric   }
694344a3780SDimitry Andric 
visitCallInst(CallInst & I)695344a3780SDimitry Andric   void visitCallInst(CallInst &I) { visitCallBase(I); }
696344a3780SDimitry Andric 
697344a3780SDimitry Andric   bool markBlockExecutable(BasicBlock *BB);
698344a3780SDimitry Andric 
getPredicateInfoFor(Instruction * I)699344a3780SDimitry Andric   const PredicateBase *getPredicateInfoFor(Instruction *I) {
7007fa27ce4SDimitry Andric     auto It = FnPredicateInfo.find(I->getParent()->getParent());
7017fa27ce4SDimitry Andric     if (It == FnPredicateInfo.end())
702344a3780SDimitry Andric       return nullptr;
7037fa27ce4SDimitry Andric     return It->second->getPredicateInfoFor(I);
704344a3780SDimitry Andric   }
705344a3780SDimitry Andric 
SCCPInstVisitor(const DataLayout & DL,std::function<const TargetLibraryInfo & (Function &)> GetTLI,LLVMContext & Ctx)706344a3780SDimitry Andric   SCCPInstVisitor(const DataLayout &DL,
707344a3780SDimitry Andric                   std::function<const TargetLibraryInfo &(Function &)> GetTLI,
708344a3780SDimitry Andric                   LLVMContext &Ctx)
709344a3780SDimitry Andric       : DL(DL), GetTLI(GetTLI), Ctx(Ctx) {}
710344a3780SDimitry Andric 
trackValueOfGlobalVariable(GlobalVariable * GV)711344a3780SDimitry Andric   void trackValueOfGlobalVariable(GlobalVariable *GV) {
712344a3780SDimitry Andric     // We only track the contents of scalar globals.
713344a3780SDimitry Andric     if (GV->getValueType()->isSingleValueType()) {
714344a3780SDimitry Andric       ValueLatticeElement &IV = TrackedGlobals[GV];
715344a3780SDimitry Andric       IV.markConstant(GV->getInitializer());
716344a3780SDimitry Andric     }
717344a3780SDimitry Andric   }
718344a3780SDimitry Andric 
addTrackedFunction(Function * F)719344a3780SDimitry Andric   void addTrackedFunction(Function *F) {
720344a3780SDimitry Andric     // Add an entry, F -> undef.
721344a3780SDimitry Andric     if (auto *STy = dyn_cast<StructType>(F->getReturnType())) {
722344a3780SDimitry Andric       MRVFunctionsTracked.insert(F);
723344a3780SDimitry Andric       for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i)
724344a3780SDimitry Andric         TrackedMultipleRetVals.insert(
725344a3780SDimitry Andric             std::make_pair(std::make_pair(F, i), ValueLatticeElement()));
726344a3780SDimitry Andric     } else if (!F->getReturnType()->isVoidTy())
727344a3780SDimitry Andric       TrackedRetVals.insert(std::make_pair(F, ValueLatticeElement()));
728344a3780SDimitry Andric   }
729344a3780SDimitry Andric 
addToMustPreserveReturnsInFunctions(Function * F)730344a3780SDimitry Andric   void addToMustPreserveReturnsInFunctions(Function *F) {
731344a3780SDimitry Andric     MustPreserveReturnsInFunctions.insert(F);
732344a3780SDimitry Andric   }
733344a3780SDimitry Andric 
mustPreserveReturn(Function * F)734344a3780SDimitry Andric   bool mustPreserveReturn(Function *F) {
735344a3780SDimitry Andric     return MustPreserveReturnsInFunctions.count(F);
736344a3780SDimitry Andric   }
737344a3780SDimitry Andric 
addArgumentTrackedFunction(Function * F)738344a3780SDimitry Andric   void addArgumentTrackedFunction(Function *F) {
739344a3780SDimitry Andric     TrackingIncomingArguments.insert(F);
740344a3780SDimitry Andric   }
741344a3780SDimitry Andric 
isArgumentTrackedFunction(Function * F)742344a3780SDimitry Andric   bool isArgumentTrackedFunction(Function *F) {
743344a3780SDimitry Andric     return TrackingIncomingArguments.count(F);
744344a3780SDimitry Andric   }
745344a3780SDimitry Andric 
746344a3780SDimitry Andric   void solve();
747344a3780SDimitry Andric 
7487fa27ce4SDimitry Andric   bool resolvedUndef(Instruction &I);
7497fa27ce4SDimitry Andric 
750344a3780SDimitry Andric   bool resolvedUndefsIn(Function &F);
751344a3780SDimitry Andric 
isBlockExecutable(BasicBlock * BB) const752344a3780SDimitry Andric   bool isBlockExecutable(BasicBlock *BB) const {
753344a3780SDimitry Andric     return BBExecutable.count(BB);
754344a3780SDimitry Andric   }
755344a3780SDimitry Andric 
756344a3780SDimitry Andric   bool isEdgeFeasible(BasicBlock *From, BasicBlock *To) const;
757344a3780SDimitry Andric 
getStructLatticeValueFor(Value * V) const758344a3780SDimitry Andric   std::vector<ValueLatticeElement> getStructLatticeValueFor(Value *V) const {
759344a3780SDimitry Andric     std::vector<ValueLatticeElement> StructValues;
760344a3780SDimitry Andric     auto *STy = dyn_cast<StructType>(V->getType());
761344a3780SDimitry Andric     assert(STy && "getStructLatticeValueFor() can be called only on structs");
762344a3780SDimitry Andric     for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
763344a3780SDimitry Andric       auto I = StructValueState.find(std::make_pair(V, i));
764344a3780SDimitry Andric       assert(I != StructValueState.end() && "Value not in valuemap!");
765344a3780SDimitry Andric       StructValues.push_back(I->second);
766344a3780SDimitry Andric     }
767344a3780SDimitry Andric     return StructValues;
768344a3780SDimitry Andric   }
769344a3780SDimitry Andric 
removeLatticeValueFor(Value * V)770344a3780SDimitry Andric   void removeLatticeValueFor(Value *V) { ValueState.erase(V); }
771344a3780SDimitry Andric 
7727fa27ce4SDimitry Andric   /// Invalidate the Lattice Value of \p Call and its users after specializing
7737fa27ce4SDimitry Andric   /// the call. Then recompute it.
resetLatticeValueFor(CallBase * Call)7747fa27ce4SDimitry Andric   void resetLatticeValueFor(CallBase *Call) {
7757fa27ce4SDimitry Andric     // Calls to void returning functions do not need invalidation.
7767fa27ce4SDimitry Andric     Function *F = Call->getCalledFunction();
7777fa27ce4SDimitry Andric     (void)F;
7787fa27ce4SDimitry Andric     assert(!F->getReturnType()->isVoidTy() &&
7797fa27ce4SDimitry Andric            (TrackedRetVals.count(F) || MRVFunctionsTracked.count(F)) &&
7807fa27ce4SDimitry Andric            "All non void specializations should be tracked");
7817fa27ce4SDimitry Andric     invalidate(Call);
7827fa27ce4SDimitry Andric     handleCallResult(*Call);
7837fa27ce4SDimitry Andric   }
7847fa27ce4SDimitry Andric 
getLatticeValueFor(Value * V) const785344a3780SDimitry Andric   const ValueLatticeElement &getLatticeValueFor(Value *V) const {
786344a3780SDimitry Andric     assert(!V->getType()->isStructTy() &&
787344a3780SDimitry Andric            "Should use getStructLatticeValueFor");
788344a3780SDimitry Andric     DenseMap<Value *, ValueLatticeElement>::const_iterator I =
789344a3780SDimitry Andric         ValueState.find(V);
790344a3780SDimitry Andric     assert(I != ValueState.end() &&
791344a3780SDimitry Andric            "V not found in ValueState nor Paramstate map!");
792344a3780SDimitry Andric     return I->second;
793344a3780SDimitry Andric   }
794344a3780SDimitry Andric 
getTrackedRetVals()795344a3780SDimitry Andric   const MapVector<Function *, ValueLatticeElement> &getTrackedRetVals() {
796344a3780SDimitry Andric     return TrackedRetVals;
797344a3780SDimitry Andric   }
798344a3780SDimitry Andric 
getTrackedGlobals()799344a3780SDimitry Andric   const DenseMap<GlobalVariable *, ValueLatticeElement> &getTrackedGlobals() {
800344a3780SDimitry Andric     return TrackedGlobals;
801344a3780SDimitry Andric   }
802344a3780SDimitry Andric 
getMRVFunctionsTracked()803344a3780SDimitry Andric   const SmallPtrSet<Function *, 16> getMRVFunctionsTracked() {
804344a3780SDimitry Andric     return MRVFunctionsTracked;
805344a3780SDimitry Andric   }
806344a3780SDimitry Andric 
markOverdefined(Value * V)807344a3780SDimitry Andric   void markOverdefined(Value *V) {
808344a3780SDimitry Andric     if (auto *STy = dyn_cast<StructType>(V->getType()))
809344a3780SDimitry Andric       for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i)
810344a3780SDimitry Andric         markOverdefined(getStructValueState(V, i), V);
811344a3780SDimitry Andric     else
812344a3780SDimitry Andric       markOverdefined(ValueState[V], V);
813344a3780SDimitry Andric   }
814344a3780SDimitry Andric 
trackValueOfArgument(Argument * A)815ac9a064cSDimitry Andric   void trackValueOfArgument(Argument *A) {
816ac9a064cSDimitry Andric     if (A->getType()->isIntOrIntVectorTy()) {
817ac9a064cSDimitry Andric       if (std::optional<ConstantRange> Range = A->getRange()) {
818ac9a064cSDimitry Andric         markConstantRange(ValueState[A], A, *Range);
819ac9a064cSDimitry Andric         return;
820ac9a064cSDimitry Andric       }
821ac9a064cSDimitry Andric     }
822ac9a064cSDimitry Andric     // Assume nothing about the incoming arguments without range.
823ac9a064cSDimitry Andric     markOverdefined(A);
824ac9a064cSDimitry Andric   }
825ac9a064cSDimitry Andric 
826344a3780SDimitry Andric   bool isStructLatticeConstant(Function *F, StructType *STy);
827344a3780SDimitry Andric 
8287fa27ce4SDimitry Andric   Constant *getConstant(const ValueLatticeElement &LV, Type *Ty) const;
8297fa27ce4SDimitry Andric 
8307fa27ce4SDimitry Andric   Constant *getConstantOrNull(Value *V) const;
831344a3780SDimitry Andric 
getArgumentTrackedFunctions()832344a3780SDimitry Andric   SmallPtrSetImpl<Function *> &getArgumentTrackedFunctions() {
833344a3780SDimitry Andric     return TrackingIncomingArguments;
834344a3780SDimitry Andric   }
835344a3780SDimitry Andric 
8367fa27ce4SDimitry Andric   void setLatticeValueForSpecializationArguments(Function *F,
837145449b1SDimitry Andric                                        const SmallVectorImpl<ArgInfo> &Args);
838344a3780SDimitry Andric 
markFunctionUnreachable(Function * F)839344a3780SDimitry Andric   void markFunctionUnreachable(Function *F) {
840344a3780SDimitry Andric     for (auto &BB : *F)
841344a3780SDimitry Andric       BBExecutable.erase(&BB);
842344a3780SDimitry Andric   }
843e3b55780SDimitry Andric 
solveWhileResolvedUndefsIn(Module & M)844e3b55780SDimitry Andric   void solveWhileResolvedUndefsIn(Module &M) {
845e3b55780SDimitry Andric     bool ResolvedUndefs = true;
846e3b55780SDimitry Andric     while (ResolvedUndefs) {
847e3b55780SDimitry Andric       solve();
848e3b55780SDimitry Andric       ResolvedUndefs = false;
849e3b55780SDimitry Andric       for (Function &F : M)
850e3b55780SDimitry Andric         ResolvedUndefs |= resolvedUndefsIn(F);
851e3b55780SDimitry Andric     }
852e3b55780SDimitry Andric   }
853e3b55780SDimitry Andric 
solveWhileResolvedUndefsIn(SmallVectorImpl<Function * > & WorkList)854e3b55780SDimitry Andric   void solveWhileResolvedUndefsIn(SmallVectorImpl<Function *> &WorkList) {
855e3b55780SDimitry Andric     bool ResolvedUndefs = true;
856e3b55780SDimitry Andric     while (ResolvedUndefs) {
857e3b55780SDimitry Andric       solve();
858e3b55780SDimitry Andric       ResolvedUndefs = false;
859e3b55780SDimitry Andric       for (Function *F : WorkList)
860e3b55780SDimitry Andric         ResolvedUndefs |= resolvedUndefsIn(*F);
861e3b55780SDimitry Andric     }
862e3b55780SDimitry Andric   }
8637fa27ce4SDimitry Andric 
solveWhileResolvedUndefs()8647fa27ce4SDimitry Andric   void solveWhileResolvedUndefs() {
8657fa27ce4SDimitry Andric     bool ResolvedUndefs = true;
8667fa27ce4SDimitry Andric     while (ResolvedUndefs) {
8677fa27ce4SDimitry Andric       solve();
8687fa27ce4SDimitry Andric       ResolvedUndefs = false;
8697fa27ce4SDimitry Andric       for (Value *V : Invalidated)
8707fa27ce4SDimitry Andric         if (auto *I = dyn_cast<Instruction>(V))
8717fa27ce4SDimitry Andric           ResolvedUndefs |= resolvedUndef(*I);
8727fa27ce4SDimitry Andric     }
8737fa27ce4SDimitry Andric     Invalidated.clear();
8747fa27ce4SDimitry Andric   }
875344a3780SDimitry Andric };
876344a3780SDimitry Andric 
877344a3780SDimitry Andric } // namespace llvm
878344a3780SDimitry Andric 
markBlockExecutable(BasicBlock * BB)879344a3780SDimitry Andric bool SCCPInstVisitor::markBlockExecutable(BasicBlock *BB) {
880344a3780SDimitry Andric   if (!BBExecutable.insert(BB).second)
881344a3780SDimitry Andric     return false;
882344a3780SDimitry Andric   LLVM_DEBUG(dbgs() << "Marking Block Executable: " << BB->getName() << '\n');
883344a3780SDimitry Andric   BBWorkList.push_back(BB); // Add the block to the work list!
884344a3780SDimitry Andric   return true;
885344a3780SDimitry Andric }
886344a3780SDimitry Andric 
pushToWorkList(ValueLatticeElement & IV,Value * V)887344a3780SDimitry Andric void SCCPInstVisitor::pushToWorkList(ValueLatticeElement &IV, Value *V) {
8887fa27ce4SDimitry Andric   if (IV.isOverdefined()) {
8897fa27ce4SDimitry Andric     if (OverdefinedInstWorkList.empty() || OverdefinedInstWorkList.back() != V)
8907fa27ce4SDimitry Andric       OverdefinedInstWorkList.push_back(V);
8917fa27ce4SDimitry Andric     return;
8927fa27ce4SDimitry Andric   }
8937fa27ce4SDimitry Andric   if (InstWorkList.empty() || InstWorkList.back() != V)
894344a3780SDimitry Andric     InstWorkList.push_back(V);
895344a3780SDimitry Andric }
896344a3780SDimitry Andric 
pushToWorkListMsg(ValueLatticeElement & IV,Value * V)897344a3780SDimitry Andric void SCCPInstVisitor::pushToWorkListMsg(ValueLatticeElement &IV, Value *V) {
898344a3780SDimitry Andric   LLVM_DEBUG(dbgs() << "updated " << IV << ": " << *V << '\n');
899344a3780SDimitry Andric   pushToWorkList(IV, V);
900344a3780SDimitry Andric }
901344a3780SDimitry Andric 
markConstant(ValueLatticeElement & IV,Value * V,Constant * C,bool MayIncludeUndef)902344a3780SDimitry Andric bool SCCPInstVisitor::markConstant(ValueLatticeElement &IV, Value *V,
903344a3780SDimitry Andric                                    Constant *C, bool MayIncludeUndef) {
904344a3780SDimitry Andric   if (!IV.markConstant(C, MayIncludeUndef))
905344a3780SDimitry Andric     return false;
906344a3780SDimitry Andric   LLVM_DEBUG(dbgs() << "markConstant: " << *C << ": " << *V << '\n');
907344a3780SDimitry Andric   pushToWorkList(IV, V);
908344a3780SDimitry Andric   return true;
909344a3780SDimitry Andric }
910344a3780SDimitry Andric 
markConstantRange(ValueLatticeElement & IV,Value * V,const ConstantRange & CR)911ac9a064cSDimitry Andric bool SCCPInstVisitor::markConstantRange(ValueLatticeElement &IV, Value *V,
912ac9a064cSDimitry Andric                                         const ConstantRange &CR) {
913ac9a064cSDimitry Andric   if (!IV.markConstantRange(CR))
914ac9a064cSDimitry Andric     return false;
915ac9a064cSDimitry Andric   LLVM_DEBUG(dbgs() << "markConstantRange: " << CR << ": " << *V << '\n');
916ac9a064cSDimitry Andric   pushToWorkList(IV, V);
917ac9a064cSDimitry Andric   return true;
918ac9a064cSDimitry Andric }
919ac9a064cSDimitry Andric 
markOverdefined(ValueLatticeElement & IV,Value * V)920344a3780SDimitry Andric bool SCCPInstVisitor::markOverdefined(ValueLatticeElement &IV, Value *V) {
921344a3780SDimitry Andric   if (!IV.markOverdefined())
922344a3780SDimitry Andric     return false;
923344a3780SDimitry Andric 
924344a3780SDimitry Andric   LLVM_DEBUG(dbgs() << "markOverdefined: ";
925344a3780SDimitry Andric              if (auto *F = dyn_cast<Function>(V)) dbgs()
926344a3780SDimitry Andric              << "Function '" << F->getName() << "'\n";
927344a3780SDimitry Andric              else dbgs() << *V << '\n');
928344a3780SDimitry Andric   // Only instructions go on the work list
929344a3780SDimitry Andric   pushToWorkList(IV, V);
930344a3780SDimitry Andric   return true;
931344a3780SDimitry Andric }
932344a3780SDimitry Andric 
isStructLatticeConstant(Function * F,StructType * STy)933344a3780SDimitry Andric bool SCCPInstVisitor::isStructLatticeConstant(Function *F, StructType *STy) {
934344a3780SDimitry Andric   for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
935344a3780SDimitry Andric     const auto &It = TrackedMultipleRetVals.find(std::make_pair(F, i));
936344a3780SDimitry Andric     assert(It != TrackedMultipleRetVals.end());
937344a3780SDimitry Andric     ValueLatticeElement LV = It->second;
938e3b55780SDimitry Andric     if (!SCCPSolver::isConstant(LV))
939344a3780SDimitry Andric       return false;
940344a3780SDimitry Andric   }
941344a3780SDimitry Andric   return true;
942344a3780SDimitry Andric }
943344a3780SDimitry Andric 
getConstant(const ValueLatticeElement & LV,Type * Ty) const9447fa27ce4SDimitry Andric Constant *SCCPInstVisitor::getConstant(const ValueLatticeElement &LV,
9457fa27ce4SDimitry Andric                                        Type *Ty) const {
9467fa27ce4SDimitry Andric   if (LV.isConstant()) {
9477fa27ce4SDimitry Andric     Constant *C = LV.getConstant();
9487fa27ce4SDimitry Andric     assert(C->getType() == Ty && "Type mismatch");
9497fa27ce4SDimitry Andric     return C;
9507fa27ce4SDimitry Andric   }
951344a3780SDimitry Andric 
952344a3780SDimitry Andric   if (LV.isConstantRange()) {
953344a3780SDimitry Andric     const auto &CR = LV.getConstantRange();
954344a3780SDimitry Andric     if (CR.getSingleElement())
9557fa27ce4SDimitry Andric       return ConstantInt::get(Ty, *CR.getSingleElement());
956344a3780SDimitry Andric   }
957344a3780SDimitry Andric   return nullptr;
958344a3780SDimitry Andric }
959344a3780SDimitry Andric 
getConstantOrNull(Value * V) const9607fa27ce4SDimitry Andric Constant *SCCPInstVisitor::getConstantOrNull(Value *V) const {
9617fa27ce4SDimitry Andric   Constant *Const = nullptr;
9627fa27ce4SDimitry Andric   if (V->getType()->isStructTy()) {
9637fa27ce4SDimitry Andric     std::vector<ValueLatticeElement> LVs = getStructLatticeValueFor(V);
9647fa27ce4SDimitry Andric     if (any_of(LVs, SCCPSolver::isOverdefined))
9657fa27ce4SDimitry Andric       return nullptr;
9667fa27ce4SDimitry Andric     std::vector<Constant *> ConstVals;
9677fa27ce4SDimitry Andric     auto *ST = cast<StructType>(V->getType());
9687fa27ce4SDimitry Andric     for (unsigned I = 0, E = ST->getNumElements(); I != E; ++I) {
9697fa27ce4SDimitry Andric       ValueLatticeElement LV = LVs[I];
9707fa27ce4SDimitry Andric       ConstVals.push_back(SCCPSolver::isConstant(LV)
9717fa27ce4SDimitry Andric                               ? getConstant(LV, ST->getElementType(I))
9727fa27ce4SDimitry Andric                               : UndefValue::get(ST->getElementType(I)));
9737fa27ce4SDimitry Andric     }
9747fa27ce4SDimitry Andric     Const = ConstantStruct::get(ST, ConstVals);
9757fa27ce4SDimitry Andric   } else {
9767fa27ce4SDimitry Andric     const ValueLatticeElement &LV = getLatticeValueFor(V);
9777fa27ce4SDimitry Andric     if (SCCPSolver::isOverdefined(LV))
9787fa27ce4SDimitry Andric       return nullptr;
9797fa27ce4SDimitry Andric     Const = SCCPSolver::isConstant(LV) ? getConstant(LV, V->getType())
9807fa27ce4SDimitry Andric                                        : UndefValue::get(V->getType());
9817fa27ce4SDimitry Andric   }
9827fa27ce4SDimitry Andric   assert(Const && "Constant is nullptr here!");
9837fa27ce4SDimitry Andric   return Const;
984e3b55780SDimitry Andric }
985e3b55780SDimitry Andric 
setLatticeValueForSpecializationArguments(Function * F,const SmallVectorImpl<ArgInfo> & Args)9867fa27ce4SDimitry Andric void SCCPInstVisitor::setLatticeValueForSpecializationArguments(Function *F,
9877fa27ce4SDimitry Andric                                         const SmallVectorImpl<ArgInfo> &Args) {
988145449b1SDimitry Andric   assert(!Args.empty() && "Specialization without arguments");
989145449b1SDimitry Andric   assert(F->arg_size() == Args[0].Formal->getParent()->arg_size() &&
990344a3780SDimitry Andric          "Functions should have the same number of arguments");
991344a3780SDimitry Andric 
992145449b1SDimitry Andric   auto Iter = Args.begin();
9937fa27ce4SDimitry Andric   Function::arg_iterator NewArg = F->arg_begin();
9947fa27ce4SDimitry Andric   Function::arg_iterator OldArg = Args[0].Formal->getParent()->arg_begin();
995145449b1SDimitry Andric   for (auto End = F->arg_end(); NewArg != End; ++NewArg, ++OldArg) {
996344a3780SDimitry Andric 
997145449b1SDimitry Andric     LLVM_DEBUG(dbgs() << "SCCP: Marking argument "
998145449b1SDimitry Andric                       << NewArg->getNameOrAsOperand() << "\n");
999145449b1SDimitry Andric 
10007fa27ce4SDimitry Andric     // Mark the argument constants in the new function
10017fa27ce4SDimitry Andric     // or copy the lattice state over from the old function.
10027fa27ce4SDimitry Andric     if (Iter != Args.end() && Iter->Formal == &*OldArg) {
10037fa27ce4SDimitry Andric       if (auto *STy = dyn_cast<StructType>(NewArg->getType())) {
10047fa27ce4SDimitry Andric         for (unsigned I = 0, E = STy->getNumElements(); I != E; ++I) {
10057fa27ce4SDimitry Andric           ValueLatticeElement &NewValue = StructValueState[{&*NewArg, I}];
10067fa27ce4SDimitry Andric           NewValue.markConstant(Iter->Actual->getAggregateElement(I));
10077fa27ce4SDimitry Andric         }
10087fa27ce4SDimitry Andric       } else {
10097fa27ce4SDimitry Andric         ValueState[&*NewArg].markConstant(Iter->Actual);
10107fa27ce4SDimitry Andric       }
1011145449b1SDimitry Andric       ++Iter;
10127fa27ce4SDimitry Andric     } else {
10137fa27ce4SDimitry Andric       if (auto *STy = dyn_cast<StructType>(NewArg->getType())) {
10147fa27ce4SDimitry Andric         for (unsigned I = 0, E = STy->getNumElements(); I != E; ++I) {
10157fa27ce4SDimitry Andric           ValueLatticeElement &NewValue = StructValueState[{&*NewArg, I}];
10167fa27ce4SDimitry Andric           NewValue = StructValueState[{&*OldArg, I}];
10177fa27ce4SDimitry Andric         }
10187fa27ce4SDimitry Andric       } else {
10197fa27ce4SDimitry Andric         ValueLatticeElement &NewValue = ValueState[&*NewArg];
10207fa27ce4SDimitry Andric         NewValue = ValueState[&*OldArg];
10217fa27ce4SDimitry Andric       }
1022145449b1SDimitry Andric     }
1023344a3780SDimitry Andric   }
1024344a3780SDimitry Andric }
1025344a3780SDimitry Andric 
visitInstruction(Instruction & I)1026344a3780SDimitry Andric void SCCPInstVisitor::visitInstruction(Instruction &I) {
1027344a3780SDimitry Andric   // All the instructions we don't do any special handling for just
1028344a3780SDimitry Andric   // go to overdefined.
1029344a3780SDimitry Andric   LLVM_DEBUG(dbgs() << "SCCP: Don't know how to handle: " << I << '\n');
1030344a3780SDimitry Andric   markOverdefined(&I);
1031344a3780SDimitry Andric }
1032344a3780SDimitry Andric 
mergeInValue(ValueLatticeElement & IV,Value * V,ValueLatticeElement MergeWithV,ValueLatticeElement::MergeOptions Opts)1033344a3780SDimitry Andric bool SCCPInstVisitor::mergeInValue(ValueLatticeElement &IV, Value *V,
1034344a3780SDimitry Andric                                    ValueLatticeElement MergeWithV,
1035344a3780SDimitry Andric                                    ValueLatticeElement::MergeOptions Opts) {
1036344a3780SDimitry Andric   if (IV.mergeIn(MergeWithV, Opts)) {
1037344a3780SDimitry Andric     pushToWorkList(IV, V);
1038344a3780SDimitry Andric     LLVM_DEBUG(dbgs() << "Merged " << MergeWithV << " into " << *V << " : "
1039344a3780SDimitry Andric                       << IV << "\n");
1040344a3780SDimitry Andric     return true;
1041344a3780SDimitry Andric   }
1042344a3780SDimitry Andric   return false;
1043344a3780SDimitry Andric }
1044344a3780SDimitry Andric 
markEdgeExecutable(BasicBlock * Source,BasicBlock * Dest)1045344a3780SDimitry Andric bool SCCPInstVisitor::markEdgeExecutable(BasicBlock *Source, BasicBlock *Dest) {
1046344a3780SDimitry Andric   if (!KnownFeasibleEdges.insert(Edge(Source, Dest)).second)
1047344a3780SDimitry Andric     return false; // This edge is already known to be executable!
1048344a3780SDimitry Andric 
1049344a3780SDimitry Andric   if (!markBlockExecutable(Dest)) {
1050344a3780SDimitry Andric     // If the destination is already executable, we just made an *edge*
1051344a3780SDimitry Andric     // feasible that wasn't before.  Revisit the PHI nodes in the block
1052344a3780SDimitry Andric     // because they have potentially new operands.
1053344a3780SDimitry Andric     LLVM_DEBUG(dbgs() << "Marking Edge Executable: " << Source->getName()
1054344a3780SDimitry Andric                       << " -> " << Dest->getName() << '\n');
1055344a3780SDimitry Andric 
1056344a3780SDimitry Andric     for (PHINode &PN : Dest->phis())
1057344a3780SDimitry Andric       visitPHINode(PN);
1058344a3780SDimitry Andric   }
1059344a3780SDimitry Andric   return true;
1060344a3780SDimitry Andric }
1061344a3780SDimitry Andric 
1062344a3780SDimitry Andric // getFeasibleSuccessors - Return a vector of booleans to indicate which
1063344a3780SDimitry Andric // successors are reachable from a given terminator instruction.
getFeasibleSuccessors(Instruction & TI,SmallVectorImpl<bool> & Succs)1064344a3780SDimitry Andric void SCCPInstVisitor::getFeasibleSuccessors(Instruction &TI,
1065344a3780SDimitry Andric                                             SmallVectorImpl<bool> &Succs) {
1066344a3780SDimitry Andric   Succs.resize(TI.getNumSuccessors());
1067344a3780SDimitry Andric   if (auto *BI = dyn_cast<BranchInst>(&TI)) {
1068344a3780SDimitry Andric     if (BI->isUnconditional()) {
1069344a3780SDimitry Andric       Succs[0] = true;
1070344a3780SDimitry Andric       return;
1071344a3780SDimitry Andric     }
1072344a3780SDimitry Andric 
1073344a3780SDimitry Andric     ValueLatticeElement BCValue = getValueState(BI->getCondition());
10747fa27ce4SDimitry Andric     ConstantInt *CI = getConstantInt(BCValue, BI->getCondition()->getType());
1075344a3780SDimitry Andric     if (!CI) {
1076344a3780SDimitry Andric       // Overdefined condition variables, and branches on unfoldable constant
1077344a3780SDimitry Andric       // conditions, mean the branch could go either way.
1078344a3780SDimitry Andric       if (!BCValue.isUnknownOrUndef())
1079344a3780SDimitry Andric         Succs[0] = Succs[1] = true;
1080344a3780SDimitry Andric       return;
1081344a3780SDimitry Andric     }
1082344a3780SDimitry Andric 
1083344a3780SDimitry Andric     // Constant condition variables mean the branch can only go a single way.
1084344a3780SDimitry Andric     Succs[CI->isZero()] = true;
1085344a3780SDimitry Andric     return;
1086344a3780SDimitry Andric   }
1087344a3780SDimitry Andric 
1088b1c73532SDimitry Andric   // We cannot analyze special terminators, so consider all successors
1089b1c73532SDimitry Andric   // executable.
1090b1c73532SDimitry Andric   if (TI.isSpecialTerminator()) {
1091344a3780SDimitry Andric     Succs.assign(TI.getNumSuccessors(), true);
1092344a3780SDimitry Andric     return;
1093344a3780SDimitry Andric   }
1094344a3780SDimitry Andric 
1095344a3780SDimitry Andric   if (auto *SI = dyn_cast<SwitchInst>(&TI)) {
1096344a3780SDimitry Andric     if (!SI->getNumCases()) {
1097344a3780SDimitry Andric       Succs[0] = true;
1098344a3780SDimitry Andric       return;
1099344a3780SDimitry Andric     }
1100344a3780SDimitry Andric     const ValueLatticeElement &SCValue = getValueState(SI->getCondition());
11017fa27ce4SDimitry Andric     if (ConstantInt *CI =
11027fa27ce4SDimitry Andric             getConstantInt(SCValue, SI->getCondition()->getType())) {
1103344a3780SDimitry Andric       Succs[SI->findCaseValue(CI)->getSuccessorIndex()] = true;
1104344a3780SDimitry Andric       return;
1105344a3780SDimitry Andric     }
1106344a3780SDimitry Andric 
1107344a3780SDimitry Andric     // TODO: Switch on undef is UB. Stop passing false once the rest of LLVM
1108344a3780SDimitry Andric     // is ready.
1109344a3780SDimitry Andric     if (SCValue.isConstantRange(/*UndefAllowed=*/false)) {
1110344a3780SDimitry Andric       const ConstantRange &Range = SCValue.getConstantRange();
1111aca2e42cSDimitry Andric       unsigned ReachableCaseCount = 0;
1112344a3780SDimitry Andric       for (const auto &Case : SI->cases()) {
1113344a3780SDimitry Andric         const APInt &CaseValue = Case.getCaseValue()->getValue();
1114aca2e42cSDimitry Andric         if (Range.contains(CaseValue)) {
1115344a3780SDimitry Andric           Succs[Case.getSuccessorIndex()] = true;
1116aca2e42cSDimitry Andric           ++ReachableCaseCount;
1117aca2e42cSDimitry Andric         }
1118344a3780SDimitry Andric       }
1119344a3780SDimitry Andric 
1120aca2e42cSDimitry Andric       Succs[SI->case_default()->getSuccessorIndex()] =
1121aca2e42cSDimitry Andric           Range.isSizeLargerThan(ReachableCaseCount);
1122344a3780SDimitry Andric       return;
1123344a3780SDimitry Andric     }
1124344a3780SDimitry Andric 
1125344a3780SDimitry Andric     // Overdefined or unknown condition? All destinations are executable!
1126344a3780SDimitry Andric     if (!SCValue.isUnknownOrUndef())
1127344a3780SDimitry Andric       Succs.assign(TI.getNumSuccessors(), true);
1128344a3780SDimitry Andric     return;
1129344a3780SDimitry Andric   }
1130344a3780SDimitry Andric 
1131344a3780SDimitry Andric   // In case of indirect branch and its address is a blockaddress, we mark
1132344a3780SDimitry Andric   // the target as executable.
1133344a3780SDimitry Andric   if (auto *IBR = dyn_cast<IndirectBrInst>(&TI)) {
1134344a3780SDimitry Andric     // Casts are folded by visitCastInst.
1135344a3780SDimitry Andric     ValueLatticeElement IBRValue = getValueState(IBR->getAddress());
11367fa27ce4SDimitry Andric     BlockAddress *Addr = dyn_cast_or_null<BlockAddress>(
11377fa27ce4SDimitry Andric         getConstant(IBRValue, IBR->getAddress()->getType()));
1138344a3780SDimitry Andric     if (!Addr) { // Overdefined or unknown condition?
1139344a3780SDimitry Andric       // All destinations are executable!
1140344a3780SDimitry Andric       if (!IBRValue.isUnknownOrUndef())
1141344a3780SDimitry Andric         Succs.assign(TI.getNumSuccessors(), true);
1142344a3780SDimitry Andric       return;
1143344a3780SDimitry Andric     }
1144344a3780SDimitry Andric 
1145344a3780SDimitry Andric     BasicBlock *T = Addr->getBasicBlock();
1146344a3780SDimitry Andric     assert(Addr->getFunction() == T->getParent() &&
1147344a3780SDimitry Andric            "Block address of a different function ?");
1148344a3780SDimitry Andric     for (unsigned i = 0; i < IBR->getNumSuccessors(); ++i) {
1149344a3780SDimitry Andric       // This is the target.
1150344a3780SDimitry Andric       if (IBR->getDestination(i) == T) {
1151344a3780SDimitry Andric         Succs[i] = true;
1152344a3780SDimitry Andric         return;
1153344a3780SDimitry Andric       }
1154344a3780SDimitry Andric     }
1155344a3780SDimitry Andric 
1156344a3780SDimitry Andric     // If we didn't find our destination in the IBR successor list, then we
1157344a3780SDimitry Andric     // have undefined behavior. Its ok to assume no successor is executable.
1158344a3780SDimitry Andric     return;
1159344a3780SDimitry Andric   }
1160344a3780SDimitry Andric 
1161344a3780SDimitry Andric   LLVM_DEBUG(dbgs() << "Unknown terminator instruction: " << TI << '\n');
1162344a3780SDimitry Andric   llvm_unreachable("SCCP: Don't know how to handle this terminator!");
1163344a3780SDimitry Andric }
1164344a3780SDimitry Andric 
1165344a3780SDimitry Andric // isEdgeFeasible - Return true if the control flow edge from the 'From' basic
1166344a3780SDimitry Andric // block to the 'To' basic block is currently feasible.
isEdgeFeasible(BasicBlock * From,BasicBlock * To) const1167344a3780SDimitry Andric bool SCCPInstVisitor::isEdgeFeasible(BasicBlock *From, BasicBlock *To) const {
1168344a3780SDimitry Andric   // Check if we've called markEdgeExecutable on the edge yet. (We could
1169344a3780SDimitry Andric   // be more aggressive and try to consider edges which haven't been marked
1170344a3780SDimitry Andric   // yet, but there isn't any need.)
1171344a3780SDimitry Andric   return KnownFeasibleEdges.count(Edge(From, To));
1172344a3780SDimitry Andric }
1173344a3780SDimitry Andric 
1174344a3780SDimitry Andric // visit Implementations - Something changed in this instruction, either an
1175344a3780SDimitry Andric // operand made a transition, or the instruction is newly executable.  Change
1176344a3780SDimitry Andric // the value type of I to reflect these changes if appropriate.  This method
1177344a3780SDimitry Andric // makes sure to do the following actions:
1178344a3780SDimitry Andric //
1179344a3780SDimitry Andric // 1. If a phi node merges two constants in, and has conflicting value coming
1180344a3780SDimitry Andric //    from different branches, or if the PHI node merges in an overdefined
1181344a3780SDimitry Andric //    value, then the PHI node becomes overdefined.
1182344a3780SDimitry Andric // 2. If a phi node merges only constants in, and they all agree on value, the
1183344a3780SDimitry Andric //    PHI node becomes a constant value equal to that.
1184344a3780SDimitry Andric // 3. If V <- x (op) y && isConstant(x) && isConstant(y) V = Constant
1185344a3780SDimitry Andric // 4. If V <- x (op) y && (isOverdefined(x) || isOverdefined(y)) V = Overdefined
1186344a3780SDimitry Andric // 5. If V <- MEM or V <- CALL or V <- (unknown) then V = Overdefined
1187344a3780SDimitry Andric // 6. If a conditional branch has a value that is constant, make the selected
1188344a3780SDimitry Andric //    destination executable
1189344a3780SDimitry Andric // 7. If a conditional branch has a value that is overdefined, make all
1190344a3780SDimitry Andric //    successors executable.
visitPHINode(PHINode & PN)1191344a3780SDimitry Andric void SCCPInstVisitor::visitPHINode(PHINode &PN) {
1192344a3780SDimitry Andric   // If this PN returns a struct, just mark the result overdefined.
1193344a3780SDimitry Andric   // TODO: We could do a lot better than this if code actually uses this.
1194344a3780SDimitry Andric   if (PN.getType()->isStructTy())
1195344a3780SDimitry Andric     return (void)markOverdefined(&PN);
1196344a3780SDimitry Andric 
1197344a3780SDimitry Andric   if (getValueState(&PN).isOverdefined())
1198344a3780SDimitry Andric     return; // Quick exit
1199344a3780SDimitry Andric 
1200344a3780SDimitry Andric   // Super-extra-high-degree PHI nodes are unlikely to ever be marked constant,
1201344a3780SDimitry Andric   // and slow us down a lot.  Just mark them overdefined.
1202344a3780SDimitry Andric   if (PN.getNumIncomingValues() > 64)
1203344a3780SDimitry Andric     return (void)markOverdefined(&PN);
1204344a3780SDimitry Andric 
1205344a3780SDimitry Andric   unsigned NumActiveIncoming = 0;
1206344a3780SDimitry Andric 
1207344a3780SDimitry Andric   // Look at all of the executable operands of the PHI node.  If any of them
1208344a3780SDimitry Andric   // are overdefined, the PHI becomes overdefined as well.  If they are all
1209344a3780SDimitry Andric   // constant, and they agree with each other, the PHI becomes the identical
1210344a3780SDimitry Andric   // constant.  If they are constant and don't agree, the PHI is a constant
1211344a3780SDimitry Andric   // range. If there are no executable operands, the PHI remains unknown.
1212344a3780SDimitry Andric   ValueLatticeElement PhiState = getValueState(&PN);
1213344a3780SDimitry Andric   for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) {
1214344a3780SDimitry Andric     if (!isEdgeFeasible(PN.getIncomingBlock(i), PN.getParent()))
1215344a3780SDimitry Andric       continue;
1216344a3780SDimitry Andric 
1217344a3780SDimitry Andric     ValueLatticeElement IV = getValueState(PN.getIncomingValue(i));
1218344a3780SDimitry Andric     PhiState.mergeIn(IV);
1219344a3780SDimitry Andric     NumActiveIncoming++;
1220344a3780SDimitry Andric     if (PhiState.isOverdefined())
1221344a3780SDimitry Andric       break;
1222344a3780SDimitry Andric   }
1223344a3780SDimitry Andric 
1224344a3780SDimitry Andric   // We allow up to 1 range extension per active incoming value and one
1225344a3780SDimitry Andric   // additional extension. Note that we manually adjust the number of range
1226344a3780SDimitry Andric   // extensions to match the number of active incoming values. This helps to
1227344a3780SDimitry Andric   // limit multiple extensions caused by the same incoming value, if other
1228344a3780SDimitry Andric   // incoming values are equal.
1229344a3780SDimitry Andric   mergeInValue(&PN, PhiState,
1230344a3780SDimitry Andric                ValueLatticeElement::MergeOptions().setMaxWidenSteps(
1231344a3780SDimitry Andric                    NumActiveIncoming + 1));
1232344a3780SDimitry Andric   ValueLatticeElement &PhiStateRef = getValueState(&PN);
1233344a3780SDimitry Andric   PhiStateRef.setNumRangeExtensions(
1234344a3780SDimitry Andric       std::max(NumActiveIncoming, PhiStateRef.getNumRangeExtensions()));
1235344a3780SDimitry Andric }
1236344a3780SDimitry Andric 
visitReturnInst(ReturnInst & I)1237344a3780SDimitry Andric void SCCPInstVisitor::visitReturnInst(ReturnInst &I) {
1238344a3780SDimitry Andric   if (I.getNumOperands() == 0)
1239344a3780SDimitry Andric     return; // ret void
1240344a3780SDimitry Andric 
1241344a3780SDimitry Andric   Function *F = I.getParent()->getParent();
1242344a3780SDimitry Andric   Value *ResultOp = I.getOperand(0);
1243344a3780SDimitry Andric 
1244344a3780SDimitry Andric   // If we are tracking the return value of this function, merge it in.
1245344a3780SDimitry Andric   if (!TrackedRetVals.empty() && !ResultOp->getType()->isStructTy()) {
1246344a3780SDimitry Andric     auto TFRVI = TrackedRetVals.find(F);
1247344a3780SDimitry Andric     if (TFRVI != TrackedRetVals.end()) {
1248344a3780SDimitry Andric       mergeInValue(TFRVI->second, F, getValueState(ResultOp));
1249344a3780SDimitry Andric       return;
1250344a3780SDimitry Andric     }
1251344a3780SDimitry Andric   }
1252344a3780SDimitry Andric 
1253344a3780SDimitry Andric   // Handle functions that return multiple values.
1254344a3780SDimitry Andric   if (!TrackedMultipleRetVals.empty()) {
1255344a3780SDimitry Andric     if (auto *STy = dyn_cast<StructType>(ResultOp->getType()))
1256344a3780SDimitry Andric       if (MRVFunctionsTracked.count(F))
1257344a3780SDimitry Andric         for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i)
1258344a3780SDimitry Andric           mergeInValue(TrackedMultipleRetVals[std::make_pair(F, i)], F,
1259344a3780SDimitry Andric                        getStructValueState(ResultOp, i));
1260344a3780SDimitry Andric   }
1261344a3780SDimitry Andric }
1262344a3780SDimitry Andric 
visitTerminator(Instruction & TI)1263344a3780SDimitry Andric void SCCPInstVisitor::visitTerminator(Instruction &TI) {
1264344a3780SDimitry Andric   SmallVector<bool, 16> SuccFeasible;
1265344a3780SDimitry Andric   getFeasibleSuccessors(TI, SuccFeasible);
1266344a3780SDimitry Andric 
1267344a3780SDimitry Andric   BasicBlock *BB = TI.getParent();
1268344a3780SDimitry Andric 
1269344a3780SDimitry Andric   // Mark all feasible successors executable.
1270344a3780SDimitry Andric   for (unsigned i = 0, e = SuccFeasible.size(); i != e; ++i)
1271344a3780SDimitry Andric     if (SuccFeasible[i])
1272344a3780SDimitry Andric       markEdgeExecutable(BB, TI.getSuccessor(i));
1273344a3780SDimitry Andric }
1274344a3780SDimitry Andric 
visitCastInst(CastInst & I)1275344a3780SDimitry Andric void SCCPInstVisitor::visitCastInst(CastInst &I) {
1276344a3780SDimitry Andric   // ResolvedUndefsIn might mark I as overdefined. Bail out, even if we would
1277344a3780SDimitry Andric   // discover a concrete value later.
1278344a3780SDimitry Andric   if (ValueState[&I].isOverdefined())
1279344a3780SDimitry Andric     return;
1280344a3780SDimitry Andric 
1281344a3780SDimitry Andric   ValueLatticeElement OpSt = getValueState(I.getOperand(0));
1282c0981da4SDimitry Andric   if (OpSt.isUnknownOrUndef())
1283c0981da4SDimitry Andric     return;
1284c0981da4SDimitry Andric 
12857fa27ce4SDimitry Andric   if (Constant *OpC = getConstant(OpSt, I.getOperand(0)->getType())) {
1286344a3780SDimitry Andric     // Fold the constant as we build.
1287b1c73532SDimitry Andric     if (Constant *C =
1288b1c73532SDimitry Andric             ConstantFoldCastOperand(I.getOpcode(), OpC, I.getType(), DL))
1289b1c73532SDimitry Andric       return (void)markConstant(&I, C);
1290b1c73532SDimitry Andric   }
1291b1c73532SDimitry Andric 
1292ac9a064cSDimitry Andric   // Ignore bitcasts, as they may change the number of vector elements.
1293ac9a064cSDimitry Andric   if (I.getDestTy()->isIntOrIntVectorTy() &&
1294ac9a064cSDimitry Andric       I.getSrcTy()->isIntOrIntVectorTy() &&
1295ac9a064cSDimitry Andric       I.getOpcode() != Instruction::BitCast) {
1296344a3780SDimitry Andric     auto &LV = getValueState(&I);
1297ac9a064cSDimitry Andric     ConstantRange OpRange =
1298ac9a064cSDimitry Andric         OpSt.asConstantRange(I.getSrcTy(), /*UndefAllowed=*/false);
1299c0981da4SDimitry Andric 
1300344a3780SDimitry Andric     Type *DestTy = I.getDestTy();
1301344a3780SDimitry Andric     ConstantRange Res =
1302ac9a064cSDimitry Andric         OpRange.castOp(I.getOpcode(), DestTy->getScalarSizeInBits());
1303344a3780SDimitry Andric     mergeInValue(LV, &I, ValueLatticeElement::getRange(Res));
1304c0981da4SDimitry Andric   } else
1305344a3780SDimitry Andric     markOverdefined(&I);
1306344a3780SDimitry Andric }
1307344a3780SDimitry Andric 
handleExtractOfWithOverflow(ExtractValueInst & EVI,const WithOverflowInst * WO,unsigned Idx)1308e3b55780SDimitry Andric void SCCPInstVisitor::handleExtractOfWithOverflow(ExtractValueInst &EVI,
1309e3b55780SDimitry Andric                                                   const WithOverflowInst *WO,
1310e3b55780SDimitry Andric                                                   unsigned Idx) {
1311e3b55780SDimitry Andric   Value *LHS = WO->getLHS(), *RHS = WO->getRHS();
1312e3b55780SDimitry Andric   ValueLatticeElement L = getValueState(LHS);
1313e3b55780SDimitry Andric   ValueLatticeElement R = getValueState(RHS);
1314e3b55780SDimitry Andric   addAdditionalUser(LHS, &EVI);
1315e3b55780SDimitry Andric   addAdditionalUser(RHS, &EVI);
1316e3b55780SDimitry Andric   if (L.isUnknownOrUndef() || R.isUnknownOrUndef())
1317e3b55780SDimitry Andric     return; // Wait to resolve.
1318e3b55780SDimitry Andric 
1319e3b55780SDimitry Andric   Type *Ty = LHS->getType();
1320ac9a064cSDimitry Andric   ConstantRange LR = L.asConstantRange(Ty, /*UndefAllowed=*/false);
1321ac9a064cSDimitry Andric   ConstantRange RR = R.asConstantRange(Ty, /*UndefAllowed=*/false);
1322e3b55780SDimitry Andric   if (Idx == 0) {
1323e3b55780SDimitry Andric     ConstantRange Res = LR.binaryOp(WO->getBinaryOp(), RR);
1324e3b55780SDimitry Andric     mergeInValue(&EVI, ValueLatticeElement::getRange(Res));
1325e3b55780SDimitry Andric   } else {
1326e3b55780SDimitry Andric     assert(Idx == 1 && "Index can only be 0 or 1");
1327e3b55780SDimitry Andric     ConstantRange NWRegion = ConstantRange::makeGuaranteedNoWrapRegion(
1328e3b55780SDimitry Andric         WO->getBinaryOp(), RR, WO->getNoWrapKind());
1329e3b55780SDimitry Andric     if (NWRegion.contains(LR))
1330e3b55780SDimitry Andric       return (void)markConstant(&EVI, ConstantInt::getFalse(EVI.getType()));
1331e3b55780SDimitry Andric     markOverdefined(&EVI);
1332e3b55780SDimitry Andric   }
1333e3b55780SDimitry Andric }
1334e3b55780SDimitry Andric 
visitExtractValueInst(ExtractValueInst & EVI)1335344a3780SDimitry Andric void SCCPInstVisitor::visitExtractValueInst(ExtractValueInst &EVI) {
1336344a3780SDimitry Andric   // If this returns a struct, mark all elements over defined, we don't track
1337344a3780SDimitry Andric   // structs in structs.
1338344a3780SDimitry Andric   if (EVI.getType()->isStructTy())
1339344a3780SDimitry Andric     return (void)markOverdefined(&EVI);
1340344a3780SDimitry Andric 
1341344a3780SDimitry Andric   // resolvedUndefsIn might mark I as overdefined. Bail out, even if we would
1342344a3780SDimitry Andric   // discover a concrete value later.
1343344a3780SDimitry Andric   if (ValueState[&EVI].isOverdefined())
1344344a3780SDimitry Andric     return (void)markOverdefined(&EVI);
1345344a3780SDimitry Andric 
1346344a3780SDimitry Andric   // If this is extracting from more than one level of struct, we don't know.
1347344a3780SDimitry Andric   if (EVI.getNumIndices() != 1)
1348344a3780SDimitry Andric     return (void)markOverdefined(&EVI);
1349344a3780SDimitry Andric 
1350344a3780SDimitry Andric   Value *AggVal = EVI.getAggregateOperand();
1351344a3780SDimitry Andric   if (AggVal->getType()->isStructTy()) {
1352344a3780SDimitry Andric     unsigned i = *EVI.idx_begin();
1353e3b55780SDimitry Andric     if (auto *WO = dyn_cast<WithOverflowInst>(AggVal))
1354e3b55780SDimitry Andric       return handleExtractOfWithOverflow(EVI, WO, i);
1355344a3780SDimitry Andric     ValueLatticeElement EltVal = getStructValueState(AggVal, i);
1356344a3780SDimitry Andric     mergeInValue(getValueState(&EVI), &EVI, EltVal);
1357344a3780SDimitry Andric   } else {
1358344a3780SDimitry Andric     // Otherwise, must be extracting from an array.
1359344a3780SDimitry Andric     return (void)markOverdefined(&EVI);
1360344a3780SDimitry Andric   }
1361344a3780SDimitry Andric }
1362344a3780SDimitry Andric 
visitInsertValueInst(InsertValueInst & IVI)1363344a3780SDimitry Andric void SCCPInstVisitor::visitInsertValueInst(InsertValueInst &IVI) {
1364344a3780SDimitry Andric   auto *STy = dyn_cast<StructType>(IVI.getType());
1365344a3780SDimitry Andric   if (!STy)
1366344a3780SDimitry Andric     return (void)markOverdefined(&IVI);
1367344a3780SDimitry Andric 
1368344a3780SDimitry Andric   // resolvedUndefsIn might mark I as overdefined. Bail out, even if we would
1369344a3780SDimitry Andric   // discover a concrete value later.
1370e3b55780SDimitry Andric   if (SCCPSolver::isOverdefined(ValueState[&IVI]))
1371344a3780SDimitry Andric     return (void)markOverdefined(&IVI);
1372344a3780SDimitry Andric 
1373344a3780SDimitry Andric   // If this has more than one index, we can't handle it, drive all results to
1374344a3780SDimitry Andric   // undef.
1375344a3780SDimitry Andric   if (IVI.getNumIndices() != 1)
1376344a3780SDimitry Andric     return (void)markOverdefined(&IVI);
1377344a3780SDimitry Andric 
1378344a3780SDimitry Andric   Value *Aggr = IVI.getAggregateOperand();
1379344a3780SDimitry Andric   unsigned Idx = *IVI.idx_begin();
1380344a3780SDimitry Andric 
1381344a3780SDimitry Andric   // Compute the result based on what we're inserting.
1382344a3780SDimitry Andric   for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
1383344a3780SDimitry Andric     // This passes through all values that aren't the inserted element.
1384344a3780SDimitry Andric     if (i != Idx) {
1385344a3780SDimitry Andric       ValueLatticeElement EltVal = getStructValueState(Aggr, i);
1386344a3780SDimitry Andric       mergeInValue(getStructValueState(&IVI, i), &IVI, EltVal);
1387344a3780SDimitry Andric       continue;
1388344a3780SDimitry Andric     }
1389344a3780SDimitry Andric 
1390344a3780SDimitry Andric     Value *Val = IVI.getInsertedValueOperand();
1391344a3780SDimitry Andric     if (Val->getType()->isStructTy())
1392344a3780SDimitry Andric       // We don't track structs in structs.
1393344a3780SDimitry Andric       markOverdefined(getStructValueState(&IVI, i), &IVI);
1394344a3780SDimitry Andric     else {
1395344a3780SDimitry Andric       ValueLatticeElement InVal = getValueState(Val);
1396344a3780SDimitry Andric       mergeInValue(getStructValueState(&IVI, i), &IVI, InVal);
1397344a3780SDimitry Andric     }
1398344a3780SDimitry Andric   }
1399344a3780SDimitry Andric }
1400344a3780SDimitry Andric 
visitSelectInst(SelectInst & I)1401344a3780SDimitry Andric void SCCPInstVisitor::visitSelectInst(SelectInst &I) {
1402344a3780SDimitry Andric   // If this select returns a struct, just mark the result overdefined.
1403344a3780SDimitry Andric   // TODO: We could do a lot better than this if code actually uses this.
1404344a3780SDimitry Andric   if (I.getType()->isStructTy())
1405344a3780SDimitry Andric     return (void)markOverdefined(&I);
1406344a3780SDimitry Andric 
1407344a3780SDimitry Andric   // resolvedUndefsIn might mark I as overdefined. Bail out, even if we would
1408344a3780SDimitry Andric   // discover a concrete value later.
1409344a3780SDimitry Andric   if (ValueState[&I].isOverdefined())
1410344a3780SDimitry Andric     return (void)markOverdefined(&I);
1411344a3780SDimitry Andric 
1412344a3780SDimitry Andric   ValueLatticeElement CondValue = getValueState(I.getCondition());
1413344a3780SDimitry Andric   if (CondValue.isUnknownOrUndef())
1414344a3780SDimitry Andric     return;
1415344a3780SDimitry Andric 
14167fa27ce4SDimitry Andric   if (ConstantInt *CondCB =
14177fa27ce4SDimitry Andric           getConstantInt(CondValue, I.getCondition()->getType())) {
1418344a3780SDimitry Andric     Value *OpVal = CondCB->isZero() ? I.getFalseValue() : I.getTrueValue();
1419344a3780SDimitry Andric     mergeInValue(&I, getValueState(OpVal));
1420344a3780SDimitry Andric     return;
1421344a3780SDimitry Andric   }
1422344a3780SDimitry Andric 
1423344a3780SDimitry Andric   // Otherwise, the condition is overdefined or a constant we can't evaluate.
1424344a3780SDimitry Andric   // See if we can produce something better than overdefined based on the T/F
1425344a3780SDimitry Andric   // value.
1426344a3780SDimitry Andric   ValueLatticeElement TVal = getValueState(I.getTrueValue());
1427344a3780SDimitry Andric   ValueLatticeElement FVal = getValueState(I.getFalseValue());
1428344a3780SDimitry Andric 
1429344a3780SDimitry Andric   bool Changed = ValueState[&I].mergeIn(TVal);
1430344a3780SDimitry Andric   Changed |= ValueState[&I].mergeIn(FVal);
1431344a3780SDimitry Andric   if (Changed)
1432344a3780SDimitry Andric     pushToWorkListMsg(ValueState[&I], &I);
1433344a3780SDimitry Andric }
1434344a3780SDimitry Andric 
1435344a3780SDimitry Andric // Handle Unary Operators.
visitUnaryOperator(Instruction & I)1436344a3780SDimitry Andric void SCCPInstVisitor::visitUnaryOperator(Instruction &I) {
1437344a3780SDimitry Andric   ValueLatticeElement V0State = getValueState(I.getOperand(0));
1438344a3780SDimitry Andric 
1439344a3780SDimitry Andric   ValueLatticeElement &IV = ValueState[&I];
1440344a3780SDimitry Andric   // resolvedUndefsIn might mark I as overdefined. Bail out, even if we would
1441344a3780SDimitry Andric   // discover a concrete value later.
1442e3b55780SDimitry Andric   if (SCCPSolver::isOverdefined(IV))
1443344a3780SDimitry Andric     return (void)markOverdefined(&I);
1444344a3780SDimitry Andric 
14451f917f69SDimitry Andric   // If something is unknown/undef, wait for it to resolve.
14461f917f69SDimitry Andric   if (V0State.isUnknownOrUndef())
1447344a3780SDimitry Andric     return;
14481f917f69SDimitry Andric 
1449e3b55780SDimitry Andric   if (SCCPSolver::isConstant(V0State))
14507fa27ce4SDimitry Andric     if (Constant *C = ConstantFoldUnaryOpOperand(
14517fa27ce4SDimitry Andric             I.getOpcode(), getConstant(V0State, I.getType()), DL))
1452344a3780SDimitry Andric       return (void)markConstant(IV, &I, C);
1453344a3780SDimitry Andric 
1454344a3780SDimitry Andric   markOverdefined(&I);
1455344a3780SDimitry Andric }
1456344a3780SDimitry Andric 
visitFreezeInst(FreezeInst & I)14577fa27ce4SDimitry Andric void SCCPInstVisitor::visitFreezeInst(FreezeInst &I) {
14587fa27ce4SDimitry Andric   // If this freeze returns a struct, just mark the result overdefined.
14597fa27ce4SDimitry Andric   // TODO: We could do a lot better than this.
14607fa27ce4SDimitry Andric   if (I.getType()->isStructTy())
14617fa27ce4SDimitry Andric     return (void)markOverdefined(&I);
14627fa27ce4SDimitry Andric 
14637fa27ce4SDimitry Andric   ValueLatticeElement V0State = getValueState(I.getOperand(0));
14647fa27ce4SDimitry Andric   ValueLatticeElement &IV = ValueState[&I];
14657fa27ce4SDimitry Andric   // resolvedUndefsIn might mark I as overdefined. Bail out, even if we would
14667fa27ce4SDimitry Andric   // discover a concrete value later.
14677fa27ce4SDimitry Andric   if (SCCPSolver::isOverdefined(IV))
14687fa27ce4SDimitry Andric     return (void)markOverdefined(&I);
14697fa27ce4SDimitry Andric 
14707fa27ce4SDimitry Andric   // If something is unknown/undef, wait for it to resolve.
14717fa27ce4SDimitry Andric   if (V0State.isUnknownOrUndef())
14727fa27ce4SDimitry Andric     return;
14737fa27ce4SDimitry Andric 
14747fa27ce4SDimitry Andric   if (SCCPSolver::isConstant(V0State) &&
14757fa27ce4SDimitry Andric       isGuaranteedNotToBeUndefOrPoison(getConstant(V0State, I.getType())))
14767fa27ce4SDimitry Andric     return (void)markConstant(IV, &I, getConstant(V0State, I.getType()));
14777fa27ce4SDimitry Andric 
14787fa27ce4SDimitry Andric   markOverdefined(&I);
14797fa27ce4SDimitry Andric }
14807fa27ce4SDimitry Andric 
1481344a3780SDimitry Andric // Handle Binary Operators.
visitBinaryOperator(Instruction & I)1482344a3780SDimitry Andric void SCCPInstVisitor::visitBinaryOperator(Instruction &I) {
1483344a3780SDimitry Andric   ValueLatticeElement V1State = getValueState(I.getOperand(0));
1484344a3780SDimitry Andric   ValueLatticeElement V2State = getValueState(I.getOperand(1));
1485344a3780SDimitry Andric 
1486344a3780SDimitry Andric   ValueLatticeElement &IV = ValueState[&I];
1487344a3780SDimitry Andric   if (IV.isOverdefined())
1488344a3780SDimitry Andric     return;
1489344a3780SDimitry Andric 
1490344a3780SDimitry Andric   // If something is undef, wait for it to resolve.
1491344a3780SDimitry Andric   if (V1State.isUnknownOrUndef() || V2State.isUnknownOrUndef())
1492344a3780SDimitry Andric     return;
1493344a3780SDimitry Andric 
1494344a3780SDimitry Andric   if (V1State.isOverdefined() && V2State.isOverdefined())
1495344a3780SDimitry Andric     return (void)markOverdefined(&I);
1496344a3780SDimitry Andric 
1497344a3780SDimitry Andric   // If either of the operands is a constant, try to fold it to a constant.
1498344a3780SDimitry Andric   // TODO: Use information from notconstant better.
1499344a3780SDimitry Andric   if ((V1State.isConstant() || V2State.isConstant())) {
15007fa27ce4SDimitry Andric     Value *V1 = SCCPSolver::isConstant(V1State)
15017fa27ce4SDimitry Andric                     ? getConstant(V1State, I.getOperand(0)->getType())
1502e3b55780SDimitry Andric                     : I.getOperand(0);
15037fa27ce4SDimitry Andric     Value *V2 = SCCPSolver::isConstant(V2State)
15047fa27ce4SDimitry Andric                     ? getConstant(V2State, I.getOperand(1)->getType())
1505e3b55780SDimitry Andric                     : I.getOperand(1);
1506145449b1SDimitry Andric     Value *R = simplifyBinOp(I.getOpcode(), V1, V2, SimplifyQuery(DL));
1507344a3780SDimitry Andric     auto *C = dyn_cast_or_null<Constant>(R);
1508344a3780SDimitry Andric     if (C) {
1509344a3780SDimitry Andric       // Conservatively assume that the result may be based on operands that may
1510344a3780SDimitry Andric       // be undef. Note that we use mergeInValue to combine the constant with
1511344a3780SDimitry Andric       // the existing lattice value for I, as different constants might be found
1512344a3780SDimitry Andric       // after one of the operands go to overdefined, e.g. due to one operand
1513344a3780SDimitry Andric       // being a special floating value.
1514344a3780SDimitry Andric       ValueLatticeElement NewV;
1515344a3780SDimitry Andric       NewV.markConstant(C, /*MayIncludeUndef=*/true);
1516344a3780SDimitry Andric       return (void)mergeInValue(&I, NewV);
1517344a3780SDimitry Andric     }
1518344a3780SDimitry Andric   }
1519344a3780SDimitry Andric 
1520344a3780SDimitry Andric   // Only use ranges for binary operators on integers.
1521ac9a064cSDimitry Andric   if (!I.getType()->isIntOrIntVectorTy())
1522344a3780SDimitry Andric     return markOverdefined(&I);
1523344a3780SDimitry Andric 
1524344a3780SDimitry Andric   // Try to simplify to a constant range.
1525ac9a064cSDimitry Andric   ConstantRange A =
1526ac9a064cSDimitry Andric       V1State.asConstantRange(I.getType(), /*UndefAllowed=*/false);
1527ac9a064cSDimitry Andric   ConstantRange B =
1528ac9a064cSDimitry Andric       V2State.asConstantRange(I.getType(), /*UndefAllowed=*/false);
1529ac9a064cSDimitry Andric 
1530ac9a064cSDimitry Andric   auto *BO = cast<BinaryOperator>(&I);
1531ac9a064cSDimitry Andric   ConstantRange R = ConstantRange::getEmpty(I.getType()->getScalarSizeInBits());
1532ac9a064cSDimitry Andric   if (auto *OBO = dyn_cast<OverflowingBinaryOperator>(BO))
1533ac9a064cSDimitry Andric     R = A.overflowingBinaryOp(BO->getOpcode(), B, OBO->getNoWrapKind());
1534ac9a064cSDimitry Andric   else
1535ac9a064cSDimitry Andric     R = A.binaryOp(BO->getOpcode(), B);
1536344a3780SDimitry Andric   mergeInValue(&I, ValueLatticeElement::getRange(R));
1537344a3780SDimitry Andric 
1538344a3780SDimitry Andric   // TODO: Currently we do not exploit special values that produce something
1539344a3780SDimitry Andric   // better than overdefined with an overdefined operand for vector or floating
1540344a3780SDimitry Andric   // point types, like and <4 x i32> overdefined, zeroinitializer.
1541344a3780SDimitry Andric }
1542344a3780SDimitry Andric 
1543344a3780SDimitry Andric // Handle ICmpInst instruction.
visitCmpInst(CmpInst & I)1544344a3780SDimitry Andric void SCCPInstVisitor::visitCmpInst(CmpInst &I) {
1545344a3780SDimitry Andric   // Do not cache this lookup, getValueState calls later in the function might
1546344a3780SDimitry Andric   // invalidate the reference.
1547e3b55780SDimitry Andric   if (SCCPSolver::isOverdefined(ValueState[&I]))
1548344a3780SDimitry Andric     return (void)markOverdefined(&I);
1549344a3780SDimitry Andric 
1550344a3780SDimitry Andric   Value *Op1 = I.getOperand(0);
1551344a3780SDimitry Andric   Value *Op2 = I.getOperand(1);
1552344a3780SDimitry Andric 
1553344a3780SDimitry Andric   // For parameters, use ParamState which includes constant range info if
1554344a3780SDimitry Andric   // available.
1555344a3780SDimitry Andric   auto V1State = getValueState(Op1);
1556344a3780SDimitry Andric   auto V2State = getValueState(Op2);
1557344a3780SDimitry Andric 
1558e3b55780SDimitry Andric   Constant *C = V1State.getCompare(I.getPredicate(), I.getType(), V2State, DL);
1559344a3780SDimitry Andric   if (C) {
1560344a3780SDimitry Andric     ValueLatticeElement CV;
1561344a3780SDimitry Andric     CV.markConstant(C);
1562344a3780SDimitry Andric     mergeInValue(&I, CV);
1563344a3780SDimitry Andric     return;
1564344a3780SDimitry Andric   }
1565344a3780SDimitry Andric 
1566344a3780SDimitry Andric   // If operands are still unknown, wait for it to resolve.
1567344a3780SDimitry Andric   if ((V1State.isUnknownOrUndef() || V2State.isUnknownOrUndef()) &&
1568e3b55780SDimitry Andric       !SCCPSolver::isConstant(ValueState[&I]))
1569344a3780SDimitry Andric     return;
1570344a3780SDimitry Andric 
1571344a3780SDimitry Andric   markOverdefined(&I);
1572344a3780SDimitry Andric }
1573344a3780SDimitry Andric 
1574344a3780SDimitry Andric // Handle getelementptr instructions.  If all operands are constants then we
1575344a3780SDimitry Andric // can turn this into a getelementptr ConstantExpr.
visitGetElementPtrInst(GetElementPtrInst & I)1576344a3780SDimitry Andric void SCCPInstVisitor::visitGetElementPtrInst(GetElementPtrInst &I) {
1577e3b55780SDimitry Andric   if (SCCPSolver::isOverdefined(ValueState[&I]))
1578344a3780SDimitry Andric     return (void)markOverdefined(&I);
1579344a3780SDimitry Andric 
1580344a3780SDimitry Andric   SmallVector<Constant *, 8> Operands;
1581344a3780SDimitry Andric   Operands.reserve(I.getNumOperands());
1582344a3780SDimitry Andric 
1583344a3780SDimitry Andric   for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) {
1584344a3780SDimitry Andric     ValueLatticeElement State = getValueState(I.getOperand(i));
1585344a3780SDimitry Andric     if (State.isUnknownOrUndef())
1586344a3780SDimitry Andric       return; // Operands are not resolved yet.
1587344a3780SDimitry Andric 
1588e3b55780SDimitry Andric     if (SCCPSolver::isOverdefined(State))
1589344a3780SDimitry Andric       return (void)markOverdefined(&I);
1590344a3780SDimitry Andric 
15917fa27ce4SDimitry Andric     if (Constant *C = getConstant(State, I.getOperand(i)->getType())) {
1592344a3780SDimitry Andric       Operands.push_back(C);
1593344a3780SDimitry Andric       continue;
1594344a3780SDimitry Andric     }
1595344a3780SDimitry Andric 
1596344a3780SDimitry Andric     return (void)markOverdefined(&I);
1597344a3780SDimitry Andric   }
1598344a3780SDimitry Andric 
1599b1c73532SDimitry Andric   if (Constant *C = ConstantFoldInstOperands(&I, Operands, DL))
1600344a3780SDimitry Andric     markConstant(&I, C);
1601344a3780SDimitry Andric }
1602344a3780SDimitry Andric 
visitStoreInst(StoreInst & SI)1603344a3780SDimitry Andric void SCCPInstVisitor::visitStoreInst(StoreInst &SI) {
1604344a3780SDimitry Andric   // If this store is of a struct, ignore it.
1605344a3780SDimitry Andric   if (SI.getOperand(0)->getType()->isStructTy())
1606344a3780SDimitry Andric     return;
1607344a3780SDimitry Andric 
1608344a3780SDimitry Andric   if (TrackedGlobals.empty() || !isa<GlobalVariable>(SI.getOperand(1)))
1609344a3780SDimitry Andric     return;
1610344a3780SDimitry Andric 
1611344a3780SDimitry Andric   GlobalVariable *GV = cast<GlobalVariable>(SI.getOperand(1));
1612344a3780SDimitry Andric   auto I = TrackedGlobals.find(GV);
1613344a3780SDimitry Andric   if (I == TrackedGlobals.end())
1614344a3780SDimitry Andric     return;
1615344a3780SDimitry Andric 
1616344a3780SDimitry Andric   // Get the value we are storing into the global, then merge it.
1617344a3780SDimitry Andric   mergeInValue(I->second, GV, getValueState(SI.getOperand(0)),
1618344a3780SDimitry Andric                ValueLatticeElement::MergeOptions().setCheckWiden(false));
1619344a3780SDimitry Andric   if (I->second.isOverdefined())
1620344a3780SDimitry Andric     TrackedGlobals.erase(I); // No need to keep tracking this!
1621344a3780SDimitry Andric }
1622344a3780SDimitry Andric 
getValueFromMetadata(const Instruction * I)1623344a3780SDimitry Andric static ValueLatticeElement getValueFromMetadata(const Instruction *I) {
1624ac9a064cSDimitry Andric   if (I->getType()->isIntOrIntVectorTy()) {
1625344a3780SDimitry Andric     if (MDNode *Ranges = I->getMetadata(LLVMContext::MD_range))
1626344a3780SDimitry Andric       return ValueLatticeElement::getRange(
1627344a3780SDimitry Andric           getConstantRangeFromMetadata(*Ranges));
1628ac9a064cSDimitry Andric 
1629ac9a064cSDimitry Andric     if (const auto *CB = dyn_cast<CallBase>(I))
1630ac9a064cSDimitry Andric       if (std::optional<ConstantRange> Range = CB->getRange())
1631ac9a064cSDimitry Andric         return ValueLatticeElement::getRange(*Range);
1632ac9a064cSDimitry Andric   }
1633344a3780SDimitry Andric   if (I->hasMetadata(LLVMContext::MD_nonnull))
1634344a3780SDimitry Andric     return ValueLatticeElement::getNot(
1635344a3780SDimitry Andric         ConstantPointerNull::get(cast<PointerType>(I->getType())));
1636344a3780SDimitry Andric   return ValueLatticeElement::getOverdefined();
1637344a3780SDimitry Andric }
1638344a3780SDimitry Andric 
1639344a3780SDimitry Andric // Handle load instructions.  If the operand is a constant pointer to a constant
1640344a3780SDimitry Andric // global, we can replace the load with the loaded constant value!
visitLoadInst(LoadInst & I)1641344a3780SDimitry Andric void SCCPInstVisitor::visitLoadInst(LoadInst &I) {
1642344a3780SDimitry Andric   // If this load is of a struct or the load is volatile, just mark the result
1643344a3780SDimitry Andric   // as overdefined.
1644344a3780SDimitry Andric   if (I.getType()->isStructTy() || I.isVolatile())
1645344a3780SDimitry Andric     return (void)markOverdefined(&I);
1646344a3780SDimitry Andric 
1647344a3780SDimitry Andric   // resolvedUndefsIn might mark I as overdefined. Bail out, even if we would
1648344a3780SDimitry Andric   // discover a concrete value later.
1649344a3780SDimitry Andric   if (ValueState[&I].isOverdefined())
1650344a3780SDimitry Andric     return (void)markOverdefined(&I);
1651344a3780SDimitry Andric 
1652344a3780SDimitry Andric   ValueLatticeElement PtrVal = getValueState(I.getOperand(0));
1653344a3780SDimitry Andric   if (PtrVal.isUnknownOrUndef())
1654344a3780SDimitry Andric     return; // The pointer is not resolved yet!
1655344a3780SDimitry Andric 
1656344a3780SDimitry Andric   ValueLatticeElement &IV = ValueState[&I];
1657344a3780SDimitry Andric 
1658e3b55780SDimitry Andric   if (SCCPSolver::isConstant(PtrVal)) {
16597fa27ce4SDimitry Andric     Constant *Ptr = getConstant(PtrVal, I.getOperand(0)->getType());
1660344a3780SDimitry Andric 
1661344a3780SDimitry Andric     // load null is undefined.
1662344a3780SDimitry Andric     if (isa<ConstantPointerNull>(Ptr)) {
1663344a3780SDimitry Andric       if (NullPointerIsDefined(I.getFunction(), I.getPointerAddressSpace()))
1664344a3780SDimitry Andric         return (void)markOverdefined(IV, &I);
1665344a3780SDimitry Andric       else
1666344a3780SDimitry Andric         return;
1667344a3780SDimitry Andric     }
1668344a3780SDimitry Andric 
1669344a3780SDimitry Andric     // Transform load (constant global) into the value loaded.
1670344a3780SDimitry Andric     if (auto *GV = dyn_cast<GlobalVariable>(Ptr)) {
1671344a3780SDimitry Andric       if (!TrackedGlobals.empty()) {
1672344a3780SDimitry Andric         // If we are tracking this global, merge in the known value for it.
1673344a3780SDimitry Andric         auto It = TrackedGlobals.find(GV);
1674344a3780SDimitry Andric         if (It != TrackedGlobals.end()) {
1675344a3780SDimitry Andric           mergeInValue(IV, &I, It->second, getMaxWidenStepsOpts());
1676344a3780SDimitry Andric           return;
1677344a3780SDimitry Andric         }
1678344a3780SDimitry Andric       }
1679344a3780SDimitry Andric     }
1680344a3780SDimitry Andric 
1681344a3780SDimitry Andric     // Transform load from a constant into a constant if possible.
16821f917f69SDimitry Andric     if (Constant *C = ConstantFoldLoadFromConstPtr(Ptr, I.getType(), DL))
1683344a3780SDimitry Andric       return (void)markConstant(IV, &I, C);
1684344a3780SDimitry Andric   }
1685344a3780SDimitry Andric 
1686344a3780SDimitry Andric   // Fall back to metadata.
1687344a3780SDimitry Andric   mergeInValue(&I, getValueFromMetadata(&I));
1688344a3780SDimitry Andric }
1689344a3780SDimitry Andric 
visitCallBase(CallBase & CB)1690344a3780SDimitry Andric void SCCPInstVisitor::visitCallBase(CallBase &CB) {
1691344a3780SDimitry Andric   handleCallResult(CB);
1692344a3780SDimitry Andric   handleCallArguments(CB);
1693344a3780SDimitry Andric }
1694344a3780SDimitry Andric 
handleCallOverdefined(CallBase & CB)1695344a3780SDimitry Andric void SCCPInstVisitor::handleCallOverdefined(CallBase &CB) {
1696344a3780SDimitry Andric   Function *F = CB.getCalledFunction();
1697344a3780SDimitry Andric 
1698344a3780SDimitry Andric   // Void return and not tracking callee, just bail.
1699344a3780SDimitry Andric   if (CB.getType()->isVoidTy())
1700344a3780SDimitry Andric     return;
1701344a3780SDimitry Andric 
1702344a3780SDimitry Andric   // Always mark struct return as overdefined.
1703344a3780SDimitry Andric   if (CB.getType()->isStructTy())
1704344a3780SDimitry Andric     return (void)markOverdefined(&CB);
1705344a3780SDimitry Andric 
1706344a3780SDimitry Andric   // Otherwise, if we have a single return value case, and if the function is
1707344a3780SDimitry Andric   // a declaration, maybe we can constant fold it.
1708344a3780SDimitry Andric   if (F && F->isDeclaration() && canConstantFoldCallTo(&CB, F)) {
1709344a3780SDimitry Andric     SmallVector<Constant *, 8> Operands;
1710c0981da4SDimitry Andric     for (const Use &A : CB.args()) {
1711c0981da4SDimitry Andric       if (A.get()->getType()->isStructTy())
1712344a3780SDimitry Andric         return markOverdefined(&CB); // Can't handle struct args.
1713e3b55780SDimitry Andric       if (A.get()->getType()->isMetadataTy())
1714e3b55780SDimitry Andric         continue;                    // Carried in CB, not allowed in Operands.
1715c0981da4SDimitry Andric       ValueLatticeElement State = getValueState(A);
1716344a3780SDimitry Andric 
1717344a3780SDimitry Andric       if (State.isUnknownOrUndef())
1718344a3780SDimitry Andric         return; // Operands are not resolved yet.
1719e3b55780SDimitry Andric       if (SCCPSolver::isOverdefined(State))
1720344a3780SDimitry Andric         return (void)markOverdefined(&CB);
1721e3b55780SDimitry Andric       assert(SCCPSolver::isConstant(State) && "Unknown state!");
17227fa27ce4SDimitry Andric       Operands.push_back(getConstant(State, A->getType()));
1723344a3780SDimitry Andric     }
1724344a3780SDimitry Andric 
1725e3b55780SDimitry Andric     if (SCCPSolver::isOverdefined(getValueState(&CB)))
1726344a3780SDimitry Andric       return (void)markOverdefined(&CB);
1727344a3780SDimitry Andric 
1728344a3780SDimitry Andric     // If we can constant fold this, mark the result of the call as a
1729344a3780SDimitry Andric     // constant.
17301f917f69SDimitry Andric     if (Constant *C = ConstantFoldCall(&CB, F, Operands, &GetTLI(*F)))
1731344a3780SDimitry Andric       return (void)markConstant(&CB, C);
1732344a3780SDimitry Andric   }
1733344a3780SDimitry Andric 
1734344a3780SDimitry Andric   // Fall back to metadata.
1735344a3780SDimitry Andric   mergeInValue(&CB, getValueFromMetadata(&CB));
1736344a3780SDimitry Andric }
1737344a3780SDimitry Andric 
handleCallArguments(CallBase & CB)1738344a3780SDimitry Andric void SCCPInstVisitor::handleCallArguments(CallBase &CB) {
1739344a3780SDimitry Andric   Function *F = CB.getCalledFunction();
1740344a3780SDimitry Andric   // If this is a local function that doesn't have its address taken, mark its
1741344a3780SDimitry Andric   // entry block executable and merge in the actual arguments to the call into
1742344a3780SDimitry Andric   // the formal arguments of the function.
1743e3b55780SDimitry Andric   if (TrackingIncomingArguments.count(F)) {
1744344a3780SDimitry Andric     markBlockExecutable(&F->front());
1745344a3780SDimitry Andric 
1746344a3780SDimitry Andric     // Propagate information from this call site into the callee.
1747344a3780SDimitry Andric     auto CAI = CB.arg_begin();
1748344a3780SDimitry Andric     for (Function::arg_iterator AI = F->arg_begin(), E = F->arg_end(); AI != E;
1749344a3780SDimitry Andric          ++AI, ++CAI) {
1750344a3780SDimitry Andric       // If this argument is byval, and if the function is not readonly, there
1751344a3780SDimitry Andric       // will be an implicit copy formed of the input aggregate.
1752344a3780SDimitry Andric       if (AI->hasByValAttr() && !F->onlyReadsMemory()) {
1753344a3780SDimitry Andric         markOverdefined(&*AI);
1754344a3780SDimitry Andric         continue;
1755344a3780SDimitry Andric       }
1756344a3780SDimitry Andric 
1757344a3780SDimitry Andric       if (auto *STy = dyn_cast<StructType>(AI->getType())) {
1758344a3780SDimitry Andric         for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
1759344a3780SDimitry Andric           ValueLatticeElement CallArg = getStructValueState(*CAI, i);
1760344a3780SDimitry Andric           mergeInValue(getStructValueState(&*AI, i), &*AI, CallArg,
1761344a3780SDimitry Andric                        getMaxWidenStepsOpts());
1762344a3780SDimitry Andric         }
1763344a3780SDimitry Andric       } else
1764344a3780SDimitry Andric         mergeInValue(&*AI, getValueState(*CAI), getMaxWidenStepsOpts());
1765344a3780SDimitry Andric     }
1766344a3780SDimitry Andric   }
1767344a3780SDimitry Andric }
1768344a3780SDimitry Andric 
handleCallResult(CallBase & CB)1769344a3780SDimitry Andric void SCCPInstVisitor::handleCallResult(CallBase &CB) {
1770344a3780SDimitry Andric   Function *F = CB.getCalledFunction();
1771344a3780SDimitry Andric 
1772344a3780SDimitry Andric   if (auto *II = dyn_cast<IntrinsicInst>(&CB)) {
1773344a3780SDimitry Andric     if (II->getIntrinsicID() == Intrinsic::ssa_copy) {
1774344a3780SDimitry Andric       if (ValueState[&CB].isOverdefined())
1775344a3780SDimitry Andric         return;
1776344a3780SDimitry Andric 
1777344a3780SDimitry Andric       Value *CopyOf = CB.getOperand(0);
1778344a3780SDimitry Andric       ValueLatticeElement CopyOfVal = getValueState(CopyOf);
1779344a3780SDimitry Andric       const auto *PI = getPredicateInfoFor(&CB);
1780344a3780SDimitry Andric       assert(PI && "Missing predicate info for ssa.copy");
1781344a3780SDimitry Andric 
1782e3b55780SDimitry Andric       const std::optional<PredicateConstraint> &Constraint =
1783e3b55780SDimitry Andric           PI->getConstraint();
1784344a3780SDimitry Andric       if (!Constraint) {
1785344a3780SDimitry Andric         mergeInValue(ValueState[&CB], &CB, CopyOfVal);
1786344a3780SDimitry Andric         return;
1787344a3780SDimitry Andric       }
1788344a3780SDimitry Andric 
1789344a3780SDimitry Andric       CmpInst::Predicate Pred = Constraint->Predicate;
1790344a3780SDimitry Andric       Value *OtherOp = Constraint->OtherOp;
1791344a3780SDimitry Andric 
1792344a3780SDimitry Andric       // Wait until OtherOp is resolved.
1793344a3780SDimitry Andric       if (getValueState(OtherOp).isUnknown()) {
1794344a3780SDimitry Andric         addAdditionalUser(OtherOp, &CB);
1795344a3780SDimitry Andric         return;
1796344a3780SDimitry Andric       }
1797344a3780SDimitry Andric 
1798344a3780SDimitry Andric       ValueLatticeElement CondVal = getValueState(OtherOp);
1799344a3780SDimitry Andric       ValueLatticeElement &IV = ValueState[&CB];
1800344a3780SDimitry Andric       if (CondVal.isConstantRange() || CopyOfVal.isConstantRange()) {
1801344a3780SDimitry Andric         auto ImposedCR =
1802344a3780SDimitry Andric             ConstantRange::getFull(DL.getTypeSizeInBits(CopyOf->getType()));
1803344a3780SDimitry Andric 
1804344a3780SDimitry Andric         // Get the range imposed by the condition.
1805344a3780SDimitry Andric         if (CondVal.isConstantRange())
1806344a3780SDimitry Andric           ImposedCR = ConstantRange::makeAllowedICmpRegion(
1807344a3780SDimitry Andric               Pred, CondVal.getConstantRange());
1808344a3780SDimitry Andric 
1809344a3780SDimitry Andric         // Combine range info for the original value with the new range from the
1810344a3780SDimitry Andric         // condition.
1811ac9a064cSDimitry Andric         auto CopyOfCR = CopyOfVal.asConstantRange(CopyOf->getType(),
1812ac9a064cSDimitry Andric                                                   /*UndefAllowed=*/true);
1813ac9a064cSDimitry Andric         // Treat an unresolved input like a full range.
1814ac9a064cSDimitry Andric         if (CopyOfCR.isEmptySet())
1815ac9a064cSDimitry Andric           CopyOfCR = ConstantRange::getFull(CopyOfCR.getBitWidth());
1816344a3780SDimitry Andric         auto NewCR = ImposedCR.intersectWith(CopyOfCR);
1817344a3780SDimitry Andric         // If the existing information is != x, do not use the information from
1818344a3780SDimitry Andric         // a chained predicate, as the != x information is more likely to be
1819344a3780SDimitry Andric         // helpful in practice.
1820344a3780SDimitry Andric         if (!CopyOfCR.contains(NewCR) && CopyOfCR.getSingleMissingElement())
1821344a3780SDimitry Andric           NewCR = CopyOfCR;
1822344a3780SDimitry Andric 
1823145449b1SDimitry Andric         // The new range is based on a branch condition. That guarantees that
1824145449b1SDimitry Andric         // neither of the compare operands can be undef in the branch targets,
1825145449b1SDimitry Andric         // unless we have conditions that are always true/false (e.g. icmp ule
1826145449b1SDimitry Andric         // i32, %a, i32_max). For the latter overdefined/empty range will be
1827145449b1SDimitry Andric         // inferred, but the branch will get folded accordingly anyways.
1828344a3780SDimitry Andric         addAdditionalUser(OtherOp, &CB);
1829145449b1SDimitry Andric         mergeInValue(
1830145449b1SDimitry Andric             IV, &CB,
1831145449b1SDimitry Andric             ValueLatticeElement::getRange(NewCR, /*MayIncludeUndef*/ false));
1832344a3780SDimitry Andric         return;
1833e3b55780SDimitry Andric       } else if (Pred == CmpInst::ICMP_EQ &&
1834e3b55780SDimitry Andric                  (CondVal.isConstant() || CondVal.isNotConstant())) {
1835344a3780SDimitry Andric         // For non-integer values or integer constant expressions, only
1836e3b55780SDimitry Andric         // propagate equal constants or not-constants.
1837344a3780SDimitry Andric         addAdditionalUser(OtherOp, &CB);
1838344a3780SDimitry Andric         mergeInValue(IV, &CB, CondVal);
1839344a3780SDimitry Andric         return;
1840145449b1SDimitry Andric       } else if (Pred == CmpInst::ICMP_NE && CondVal.isConstant()) {
1841344a3780SDimitry Andric         // Propagate inequalities.
1842344a3780SDimitry Andric         addAdditionalUser(OtherOp, &CB);
1843344a3780SDimitry Andric         mergeInValue(IV, &CB,
1844344a3780SDimitry Andric                      ValueLatticeElement::getNot(CondVal.getConstant()));
1845344a3780SDimitry Andric         return;
1846344a3780SDimitry Andric       }
1847344a3780SDimitry Andric 
1848344a3780SDimitry Andric       return (void)mergeInValue(IV, &CB, CopyOfVal);
1849344a3780SDimitry Andric     }
1850344a3780SDimitry Andric 
1851344a3780SDimitry Andric     if (ConstantRange::isIntrinsicSupported(II->getIntrinsicID())) {
1852344a3780SDimitry Andric       // Compute result range for intrinsics supported by ConstantRange.
1853344a3780SDimitry Andric       // Do this even if we don't know a range for all operands, as we may
1854344a3780SDimitry Andric       // still know something about the result range, e.g. of abs(x).
1855344a3780SDimitry Andric       SmallVector<ConstantRange, 2> OpRanges;
1856344a3780SDimitry Andric       for (Value *Op : II->args()) {
1857344a3780SDimitry Andric         const ValueLatticeElement &State = getValueState(Op);
18587fa27ce4SDimitry Andric         if (State.isUnknownOrUndef())
18597fa27ce4SDimitry Andric           return;
1860ac9a064cSDimitry Andric         OpRanges.push_back(
1861ac9a064cSDimitry Andric             State.asConstantRange(Op->getType(), /*UndefAllowed=*/false));
1862344a3780SDimitry Andric       }
1863344a3780SDimitry Andric 
1864344a3780SDimitry Andric       ConstantRange Result =
1865344a3780SDimitry Andric           ConstantRange::intrinsic(II->getIntrinsicID(), OpRanges);
1866344a3780SDimitry Andric       return (void)mergeInValue(II, ValueLatticeElement::getRange(Result));
1867344a3780SDimitry Andric     }
1868344a3780SDimitry Andric   }
1869344a3780SDimitry Andric 
1870344a3780SDimitry Andric   // The common case is that we aren't tracking the callee, either because we
1871344a3780SDimitry Andric   // are not doing interprocedural analysis or the callee is indirect, or is
1872344a3780SDimitry Andric   // external.  Handle these cases first.
1873344a3780SDimitry Andric   if (!F || F->isDeclaration())
1874344a3780SDimitry Andric     return handleCallOverdefined(CB);
1875344a3780SDimitry Andric 
1876344a3780SDimitry Andric   // If this is a single/zero retval case, see if we're tracking the function.
1877344a3780SDimitry Andric   if (auto *STy = dyn_cast<StructType>(F->getReturnType())) {
1878344a3780SDimitry Andric     if (!MRVFunctionsTracked.count(F))
1879344a3780SDimitry Andric       return handleCallOverdefined(CB); // Not tracking this callee.
1880344a3780SDimitry Andric 
1881344a3780SDimitry Andric     // If we are tracking this callee, propagate the result of the function
1882344a3780SDimitry Andric     // into this call site.
1883344a3780SDimitry Andric     for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i)
1884344a3780SDimitry Andric       mergeInValue(getStructValueState(&CB, i), &CB,
1885344a3780SDimitry Andric                    TrackedMultipleRetVals[std::make_pair(F, i)],
1886344a3780SDimitry Andric                    getMaxWidenStepsOpts());
1887344a3780SDimitry Andric   } else {
1888344a3780SDimitry Andric     auto TFRVI = TrackedRetVals.find(F);
1889344a3780SDimitry Andric     if (TFRVI == TrackedRetVals.end())
1890344a3780SDimitry Andric       return handleCallOverdefined(CB); // Not tracking this callee.
1891344a3780SDimitry Andric 
1892344a3780SDimitry Andric     // If so, propagate the return value of the callee into this call result.
1893344a3780SDimitry Andric     mergeInValue(&CB, TFRVI->second, getMaxWidenStepsOpts());
1894344a3780SDimitry Andric   }
1895344a3780SDimitry Andric }
1896344a3780SDimitry Andric 
solve()1897344a3780SDimitry Andric void SCCPInstVisitor::solve() {
1898344a3780SDimitry Andric   // Process the work lists until they are empty!
1899344a3780SDimitry Andric   while (!BBWorkList.empty() || !InstWorkList.empty() ||
1900344a3780SDimitry Andric          !OverdefinedInstWorkList.empty()) {
1901344a3780SDimitry Andric     // Process the overdefined instruction's work list first, which drives other
1902344a3780SDimitry Andric     // things to overdefined more quickly.
1903344a3780SDimitry Andric     while (!OverdefinedInstWorkList.empty()) {
1904344a3780SDimitry Andric       Value *I = OverdefinedInstWorkList.pop_back_val();
19057fa27ce4SDimitry Andric       Invalidated.erase(I);
1906344a3780SDimitry Andric 
1907344a3780SDimitry Andric       LLVM_DEBUG(dbgs() << "\nPopped off OI-WL: " << *I << '\n');
1908344a3780SDimitry Andric 
1909344a3780SDimitry Andric       // "I" got into the work list because it either made the transition from
1910344a3780SDimitry Andric       // bottom to constant, or to overdefined.
1911344a3780SDimitry Andric       //
1912344a3780SDimitry Andric       // Anything on this worklist that is overdefined need not be visited
1913344a3780SDimitry Andric       // since all of its users will have already been marked as overdefined
1914344a3780SDimitry Andric       // Update all of the users of this instruction's value.
1915344a3780SDimitry Andric       //
1916344a3780SDimitry Andric       markUsersAsChanged(I);
1917344a3780SDimitry Andric     }
1918344a3780SDimitry Andric 
1919344a3780SDimitry Andric     // Process the instruction work list.
1920344a3780SDimitry Andric     while (!InstWorkList.empty()) {
1921344a3780SDimitry Andric       Value *I = InstWorkList.pop_back_val();
19227fa27ce4SDimitry Andric       Invalidated.erase(I);
1923344a3780SDimitry Andric 
1924344a3780SDimitry Andric       LLVM_DEBUG(dbgs() << "\nPopped off I-WL: " << *I << '\n');
1925344a3780SDimitry Andric 
1926344a3780SDimitry Andric       // "I" got into the work list because it made the transition from undef to
1927344a3780SDimitry Andric       // constant.
1928344a3780SDimitry Andric       //
1929344a3780SDimitry Andric       // Anything on this worklist that is overdefined need not be visited
1930344a3780SDimitry Andric       // since all of its users will have already been marked as overdefined.
1931344a3780SDimitry Andric       // Update all of the users of this instruction's value.
1932344a3780SDimitry Andric       //
1933344a3780SDimitry Andric       if (I->getType()->isStructTy() || !getValueState(I).isOverdefined())
1934344a3780SDimitry Andric         markUsersAsChanged(I);
1935344a3780SDimitry Andric     }
1936344a3780SDimitry Andric 
1937344a3780SDimitry Andric     // Process the basic block work list.
1938344a3780SDimitry Andric     while (!BBWorkList.empty()) {
1939344a3780SDimitry Andric       BasicBlock *BB = BBWorkList.pop_back_val();
1940344a3780SDimitry Andric 
1941344a3780SDimitry Andric       LLVM_DEBUG(dbgs() << "\nPopped off BBWL: " << *BB << '\n');
1942344a3780SDimitry Andric 
1943344a3780SDimitry Andric       // Notify all instructions in this basic block that they are newly
1944344a3780SDimitry Andric       // executable.
1945344a3780SDimitry Andric       visit(BB);
1946344a3780SDimitry Andric     }
1947344a3780SDimitry Andric   }
1948344a3780SDimitry Andric }
1949344a3780SDimitry Andric 
resolvedUndef(Instruction & I)19507fa27ce4SDimitry Andric bool SCCPInstVisitor::resolvedUndef(Instruction &I) {
19517fa27ce4SDimitry Andric   // Look for instructions which produce undef values.
19527fa27ce4SDimitry Andric   if (I.getType()->isVoidTy())
19537fa27ce4SDimitry Andric     return false;
19547fa27ce4SDimitry Andric 
19557fa27ce4SDimitry Andric   if (auto *STy = dyn_cast<StructType>(I.getType())) {
19567fa27ce4SDimitry Andric     // Only a few things that can be structs matter for undef.
19577fa27ce4SDimitry Andric 
19587fa27ce4SDimitry Andric     // Tracked calls must never be marked overdefined in resolvedUndefsIn.
19597fa27ce4SDimitry Andric     if (auto *CB = dyn_cast<CallBase>(&I))
19607fa27ce4SDimitry Andric       if (Function *F = CB->getCalledFunction())
19617fa27ce4SDimitry Andric         if (MRVFunctionsTracked.count(F))
19627fa27ce4SDimitry Andric           return false;
19637fa27ce4SDimitry Andric 
19647fa27ce4SDimitry Andric     // extractvalue and insertvalue don't need to be marked; they are
19657fa27ce4SDimitry Andric     // tracked as precisely as their operands.
19667fa27ce4SDimitry Andric     if (isa<ExtractValueInst>(I) || isa<InsertValueInst>(I))
19677fa27ce4SDimitry Andric       return false;
19687fa27ce4SDimitry Andric     // Send the results of everything else to overdefined.  We could be
19697fa27ce4SDimitry Andric     // more precise than this but it isn't worth bothering.
19707fa27ce4SDimitry Andric     for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
19717fa27ce4SDimitry Andric       ValueLatticeElement &LV = getStructValueState(&I, i);
19727fa27ce4SDimitry Andric       if (LV.isUnknown()) {
19737fa27ce4SDimitry Andric         markOverdefined(LV, &I);
19747fa27ce4SDimitry Andric         return true;
19757fa27ce4SDimitry Andric       }
19767fa27ce4SDimitry Andric     }
19777fa27ce4SDimitry Andric     return false;
19787fa27ce4SDimitry Andric   }
19797fa27ce4SDimitry Andric 
19807fa27ce4SDimitry Andric   ValueLatticeElement &LV = getValueState(&I);
19817fa27ce4SDimitry Andric   if (!LV.isUnknown())
19827fa27ce4SDimitry Andric     return false;
19837fa27ce4SDimitry Andric 
19847fa27ce4SDimitry Andric   // There are two reasons a call can have an undef result
19857fa27ce4SDimitry Andric   // 1. It could be tracked.
19867fa27ce4SDimitry Andric   // 2. It could be constant-foldable.
19877fa27ce4SDimitry Andric   // Because of the way we solve return values, tracked calls must
19887fa27ce4SDimitry Andric   // never be marked overdefined in resolvedUndefsIn.
19897fa27ce4SDimitry Andric   if (auto *CB = dyn_cast<CallBase>(&I))
19907fa27ce4SDimitry Andric     if (Function *F = CB->getCalledFunction())
19917fa27ce4SDimitry Andric       if (TrackedRetVals.count(F))
19927fa27ce4SDimitry Andric         return false;
19937fa27ce4SDimitry Andric 
19947fa27ce4SDimitry Andric   if (isa<LoadInst>(I)) {
19957fa27ce4SDimitry Andric     // A load here means one of two things: a load of undef from a global,
19967fa27ce4SDimitry Andric     // a load from an unknown pointer.  Either way, having it return undef
19977fa27ce4SDimitry Andric     // is okay.
19987fa27ce4SDimitry Andric     return false;
19997fa27ce4SDimitry Andric   }
20007fa27ce4SDimitry Andric 
20017fa27ce4SDimitry Andric   markOverdefined(&I);
20027fa27ce4SDimitry Andric   return true;
20037fa27ce4SDimitry Andric }
20047fa27ce4SDimitry Andric 
2005145449b1SDimitry Andric /// While solving the dataflow for a function, we don't compute a result for
2006145449b1SDimitry Andric /// operations with an undef operand, to allow undef to be lowered to a
2007145449b1SDimitry Andric /// constant later. For example, constant folding of "zext i8 undef to i16"
2008145449b1SDimitry Andric /// would result in "i16 0", and if undef is later lowered to "i8 1", then the
2009145449b1SDimitry Andric /// zext result would become "i16 1" and would result into an overdefined
2010145449b1SDimitry Andric /// lattice value once merged with the previous result. Not computing the
2011145449b1SDimitry Andric /// result of the zext (treating undef the same as unknown) allows us to handle
2012145449b1SDimitry Andric /// a later undef->constant lowering more optimally.
2013344a3780SDimitry Andric ///
2014145449b1SDimitry Andric /// However, if the operand remains undef when the solver returns, we do need
2015145449b1SDimitry Andric /// to assign some result to the instruction (otherwise we would treat it as
2016145449b1SDimitry Andric /// unreachable). For simplicity, we mark any instructions that are still
2017145449b1SDimitry Andric /// unknown as overdefined.
resolvedUndefsIn(Function & F)2018344a3780SDimitry Andric bool SCCPInstVisitor::resolvedUndefsIn(Function &F) {
2019344a3780SDimitry Andric   bool MadeChange = false;
2020344a3780SDimitry Andric   for (BasicBlock &BB : F) {
2021344a3780SDimitry Andric     if (!BBExecutable.count(&BB))
2022344a3780SDimitry Andric       continue;
2023344a3780SDimitry Andric 
20247fa27ce4SDimitry Andric     for (Instruction &I : BB)
20257fa27ce4SDimitry Andric       MadeChange |= resolvedUndef(I);
2026344a3780SDimitry Andric   }
2027344a3780SDimitry Andric 
2028e3b55780SDimitry Andric   LLVM_DEBUG(if (MadeChange) dbgs()
2029e3b55780SDimitry Andric              << "\nResolved undefs in " << F.getName() << '\n');
2030e3b55780SDimitry Andric 
2031344a3780SDimitry Andric   return MadeChange;
2032344a3780SDimitry Andric }
2033344a3780SDimitry Andric 
2034344a3780SDimitry Andric //===----------------------------------------------------------------------===//
2035344a3780SDimitry Andric //
2036344a3780SDimitry Andric // SCCPSolver implementations
2037344a3780SDimitry Andric //
SCCPSolver(const DataLayout & DL,std::function<const TargetLibraryInfo & (Function &)> GetTLI,LLVMContext & Ctx)2038344a3780SDimitry Andric SCCPSolver::SCCPSolver(
2039344a3780SDimitry Andric     const DataLayout &DL,
2040344a3780SDimitry Andric     std::function<const TargetLibraryInfo &(Function &)> GetTLI,
2041344a3780SDimitry Andric     LLVMContext &Ctx)
2042344a3780SDimitry Andric     : Visitor(new SCCPInstVisitor(DL, std::move(GetTLI), Ctx)) {}
2043344a3780SDimitry Andric 
2044145449b1SDimitry Andric SCCPSolver::~SCCPSolver() = default;
2045344a3780SDimitry Andric 
addPredicateInfo(Function & F,DominatorTree & DT,AssumptionCache & AC)20467fa27ce4SDimitry Andric void SCCPSolver::addPredicateInfo(Function &F, DominatorTree &DT,
20477fa27ce4SDimitry Andric                                   AssumptionCache &AC) {
20487fa27ce4SDimitry Andric   Visitor->addPredicateInfo(F, DT, AC);
2049344a3780SDimitry Andric }
2050344a3780SDimitry Andric 
markBlockExecutable(BasicBlock * BB)2051344a3780SDimitry Andric bool SCCPSolver::markBlockExecutable(BasicBlock *BB) {
2052344a3780SDimitry Andric   return Visitor->markBlockExecutable(BB);
2053344a3780SDimitry Andric }
2054344a3780SDimitry Andric 
getPredicateInfoFor(Instruction * I)2055344a3780SDimitry Andric const PredicateBase *SCCPSolver::getPredicateInfoFor(Instruction *I) {
2056344a3780SDimitry Andric   return Visitor->getPredicateInfoFor(I);
2057344a3780SDimitry Andric }
2058344a3780SDimitry Andric 
trackValueOfGlobalVariable(GlobalVariable * GV)2059344a3780SDimitry Andric void SCCPSolver::trackValueOfGlobalVariable(GlobalVariable *GV) {
2060344a3780SDimitry Andric   Visitor->trackValueOfGlobalVariable(GV);
2061344a3780SDimitry Andric }
2062344a3780SDimitry Andric 
addTrackedFunction(Function * F)2063344a3780SDimitry Andric void SCCPSolver::addTrackedFunction(Function *F) {
2064344a3780SDimitry Andric   Visitor->addTrackedFunction(F);
2065344a3780SDimitry Andric }
2066344a3780SDimitry Andric 
addToMustPreserveReturnsInFunctions(Function * F)2067344a3780SDimitry Andric void SCCPSolver::addToMustPreserveReturnsInFunctions(Function *F) {
2068344a3780SDimitry Andric   Visitor->addToMustPreserveReturnsInFunctions(F);
2069344a3780SDimitry Andric }
2070344a3780SDimitry Andric 
mustPreserveReturn(Function * F)2071344a3780SDimitry Andric bool SCCPSolver::mustPreserveReturn(Function *F) {
2072344a3780SDimitry Andric   return Visitor->mustPreserveReturn(F);
2073344a3780SDimitry Andric }
2074344a3780SDimitry Andric 
addArgumentTrackedFunction(Function * F)2075344a3780SDimitry Andric void SCCPSolver::addArgumentTrackedFunction(Function *F) {
2076344a3780SDimitry Andric   Visitor->addArgumentTrackedFunction(F);
2077344a3780SDimitry Andric }
2078344a3780SDimitry Andric 
isArgumentTrackedFunction(Function * F)2079344a3780SDimitry Andric bool SCCPSolver::isArgumentTrackedFunction(Function *F) {
2080344a3780SDimitry Andric   return Visitor->isArgumentTrackedFunction(F);
2081344a3780SDimitry Andric }
2082344a3780SDimitry Andric 
solve()2083344a3780SDimitry Andric void SCCPSolver::solve() { Visitor->solve(); }
2084344a3780SDimitry Andric 
resolvedUndefsIn(Function & F)2085344a3780SDimitry Andric bool SCCPSolver::resolvedUndefsIn(Function &F) {
2086344a3780SDimitry Andric   return Visitor->resolvedUndefsIn(F);
2087344a3780SDimitry Andric }
2088344a3780SDimitry Andric 
solveWhileResolvedUndefsIn(Module & M)2089e3b55780SDimitry Andric void SCCPSolver::solveWhileResolvedUndefsIn(Module &M) {
2090e3b55780SDimitry Andric   Visitor->solveWhileResolvedUndefsIn(M);
2091e3b55780SDimitry Andric }
2092e3b55780SDimitry Andric 
2093e3b55780SDimitry Andric void
solveWhileResolvedUndefsIn(SmallVectorImpl<Function * > & WorkList)2094e3b55780SDimitry Andric SCCPSolver::solveWhileResolvedUndefsIn(SmallVectorImpl<Function *> &WorkList) {
2095e3b55780SDimitry Andric   Visitor->solveWhileResolvedUndefsIn(WorkList);
2096e3b55780SDimitry Andric }
2097e3b55780SDimitry Andric 
solveWhileResolvedUndefs()20987fa27ce4SDimitry Andric void SCCPSolver::solveWhileResolvedUndefs() {
20997fa27ce4SDimitry Andric   Visitor->solveWhileResolvedUndefs();
21007fa27ce4SDimitry Andric }
21017fa27ce4SDimitry Andric 
isBlockExecutable(BasicBlock * BB) const2102344a3780SDimitry Andric bool SCCPSolver::isBlockExecutable(BasicBlock *BB) const {
2103344a3780SDimitry Andric   return Visitor->isBlockExecutable(BB);
2104344a3780SDimitry Andric }
2105344a3780SDimitry Andric 
isEdgeFeasible(BasicBlock * From,BasicBlock * To) const2106344a3780SDimitry Andric bool SCCPSolver::isEdgeFeasible(BasicBlock *From, BasicBlock *To) const {
2107344a3780SDimitry Andric   return Visitor->isEdgeFeasible(From, To);
2108344a3780SDimitry Andric }
2109344a3780SDimitry Andric 
2110344a3780SDimitry Andric std::vector<ValueLatticeElement>
getStructLatticeValueFor(Value * V) const2111344a3780SDimitry Andric SCCPSolver::getStructLatticeValueFor(Value *V) const {
2112344a3780SDimitry Andric   return Visitor->getStructLatticeValueFor(V);
2113344a3780SDimitry Andric }
2114344a3780SDimitry Andric 
removeLatticeValueFor(Value * V)2115344a3780SDimitry Andric void SCCPSolver::removeLatticeValueFor(Value *V) {
2116344a3780SDimitry Andric   return Visitor->removeLatticeValueFor(V);
2117344a3780SDimitry Andric }
2118344a3780SDimitry Andric 
resetLatticeValueFor(CallBase * Call)21197fa27ce4SDimitry Andric void SCCPSolver::resetLatticeValueFor(CallBase *Call) {
21207fa27ce4SDimitry Andric   Visitor->resetLatticeValueFor(Call);
21217fa27ce4SDimitry Andric }
21227fa27ce4SDimitry Andric 
getLatticeValueFor(Value * V) const2123344a3780SDimitry Andric const ValueLatticeElement &SCCPSolver::getLatticeValueFor(Value *V) const {
2124344a3780SDimitry Andric   return Visitor->getLatticeValueFor(V);
2125344a3780SDimitry Andric }
2126344a3780SDimitry Andric 
2127344a3780SDimitry Andric const MapVector<Function *, ValueLatticeElement> &
getTrackedRetVals()2128344a3780SDimitry Andric SCCPSolver::getTrackedRetVals() {
2129344a3780SDimitry Andric   return Visitor->getTrackedRetVals();
2130344a3780SDimitry Andric }
2131344a3780SDimitry Andric 
2132344a3780SDimitry Andric const DenseMap<GlobalVariable *, ValueLatticeElement> &
getTrackedGlobals()2133344a3780SDimitry Andric SCCPSolver::getTrackedGlobals() {
2134344a3780SDimitry Andric   return Visitor->getTrackedGlobals();
2135344a3780SDimitry Andric }
2136344a3780SDimitry Andric 
getMRVFunctionsTracked()2137344a3780SDimitry Andric const SmallPtrSet<Function *, 16> SCCPSolver::getMRVFunctionsTracked() {
2138344a3780SDimitry Andric   return Visitor->getMRVFunctionsTracked();
2139344a3780SDimitry Andric }
2140344a3780SDimitry Andric 
markOverdefined(Value * V)2141344a3780SDimitry Andric void SCCPSolver::markOverdefined(Value *V) { Visitor->markOverdefined(V); }
2142344a3780SDimitry Andric 
trackValueOfArgument(Argument * V)2143ac9a064cSDimitry Andric void SCCPSolver::trackValueOfArgument(Argument *V) {
2144ac9a064cSDimitry Andric   Visitor->trackValueOfArgument(V);
2145ac9a064cSDimitry Andric }
2146ac9a064cSDimitry Andric 
isStructLatticeConstant(Function * F,StructType * STy)2147344a3780SDimitry Andric bool SCCPSolver::isStructLatticeConstant(Function *F, StructType *STy) {
2148344a3780SDimitry Andric   return Visitor->isStructLatticeConstant(F, STy);
2149344a3780SDimitry Andric }
2150344a3780SDimitry Andric 
getConstant(const ValueLatticeElement & LV,Type * Ty) const21517fa27ce4SDimitry Andric Constant *SCCPSolver::getConstant(const ValueLatticeElement &LV,
21527fa27ce4SDimitry Andric                                   Type *Ty) const {
21537fa27ce4SDimitry Andric   return Visitor->getConstant(LV, Ty);
21547fa27ce4SDimitry Andric }
21557fa27ce4SDimitry Andric 
getConstantOrNull(Value * V) const21567fa27ce4SDimitry Andric Constant *SCCPSolver::getConstantOrNull(Value *V) const {
21577fa27ce4SDimitry Andric   return Visitor->getConstantOrNull(V);
2158344a3780SDimitry Andric }
2159344a3780SDimitry Andric 
getArgumentTrackedFunctions()2160344a3780SDimitry Andric SmallPtrSetImpl<Function *> &SCCPSolver::getArgumentTrackedFunctions() {
2161344a3780SDimitry Andric   return Visitor->getArgumentTrackedFunctions();
2162344a3780SDimitry Andric }
2163344a3780SDimitry Andric 
setLatticeValueForSpecializationArguments(Function * F,const SmallVectorImpl<ArgInfo> & Args)21647fa27ce4SDimitry Andric void SCCPSolver::setLatticeValueForSpecializationArguments(Function *F,
21657fa27ce4SDimitry Andric                                    const SmallVectorImpl<ArgInfo> &Args) {
21667fa27ce4SDimitry Andric   Visitor->setLatticeValueForSpecializationArguments(F, Args);
2167344a3780SDimitry Andric }
2168344a3780SDimitry Andric 
markFunctionUnreachable(Function * F)2169344a3780SDimitry Andric void SCCPSolver::markFunctionUnreachable(Function *F) {
2170344a3780SDimitry Andric   Visitor->markFunctionUnreachable(F);
2171344a3780SDimitry Andric }
2172344a3780SDimitry Andric 
visit(Instruction * I)2173344a3780SDimitry Andric void SCCPSolver::visit(Instruction *I) { Visitor->visit(I); }
2174344a3780SDimitry Andric 
visitCall(CallInst & I)2175344a3780SDimitry Andric void SCCPSolver::visitCall(CallInst &I) { Visitor->visitCall(I); }
2176