LLVM 22.0.0git
DropUnnecessaryAssumes.cpp
Go to the documentation of this file.
1//===------------------------------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10#include "llvm/ADT/SetVector.h"
16
17using namespace llvm;
18using namespace llvm::PatternMatch;
19
21 // Check whether all the uses are ephemeral, i.e. recursively only used
22 // by assumes. In that case, the assume does not provide useful information.
23 // Note that additional users may appear as a result of inlining and CSE,
24 // so we should only make this assumption late in the optimization pipeline.
26 auto AddUsers = [&](Value *V) {
27 for (User *U : V->users()) {
28 // Bail out if we need to inspect too many users.
29 if (Worklist.size() >= 32)
30 return false;
31 Worklist.insert(cast<Instruction>(U));
32 }
33 return true;
34 };
35
36 for (Value *V : Affected) {
37 // Do not handle assumes on globals for now. The use list for them may
38 // contain uses in other functions.
40 return false;
41
42 if (!AddUsers(V))
43 return false;
44 }
45
46 for (unsigned Idx = 0; Idx < Worklist.size(); ++Idx) {
47 Instruction *I = Worklist[Idx];
48
49 // Use in assume is ephemeral.
50 if (isa<AssumeInst>(I))
51 continue;
52
53 // Use in side-effecting instruction is non-ephemeral.
54 if (I->mayHaveSideEffects() || I->isTerminator())
55 return false;
56
57 // Otherwise, recursively look at the users.
58 if (!AddUsers(I))
59 return false;
60 }
61
62 return true;
63}
64
67 AssumptionCache &AC = FAM.getResult<AssumptionAnalysis>(F);
68 bool Changed = false;
69
70 for (const WeakVH &Elem : AC.assumptions()) {
71 auto *Assume = cast_or_null<AssumeInst>(Elem);
72 if (!Assume)
73 continue;
74
75 if (Assume->hasOperandBundles()) {
76 // Handle operand bundle assumptions.
77 SmallVector<WeakTrackingVH> DeadBundleArgs;
79 unsigned NumBundles = Assume->getNumOperandBundles();
80 for (unsigned I = 0; I != NumBundles; ++I) {
81 auto IsDead = [](OperandBundleUse Bundle) {
82 // "ignore" operand bundles are always dead.
83 if (Bundle.getTagName() == "ignore")
84 return true;
85
86 // Bundles without arguments do not affect any specific values.
87 // Always keep them for now.
88 if (Bundle.Inputs.empty())
89 return false;
90
91 SmallVector<Value *> Affected;
93 Bundle, [&](Value *A) { Affected.push_back(A); });
94
95 return affectedValuesAreEphemeral(Affected);
96 };
97
98 OperandBundleUse Bundle = Assume->getOperandBundleAt(I);
99 if (IsDead(Bundle))
100 append_range(DeadBundleArgs, Bundle.Inputs);
101 else
102 KeptBundles.emplace_back(Bundle);
103 }
104
105 if (KeptBundles.size() != NumBundles) {
106 if (KeptBundles.empty()) {
107 // All operand bundles are dead, remove the whole assume.
108 Assume->eraseFromParent();
109 } else {
110 // Otherwise only drop the dead operand bundles.
111 CallBase *NewAssume =
112 CallBase::Create(Assume, KeptBundles, Assume->getIterator());
114 Assume->eraseFromParent();
115 }
116
118 Changed = true;
119 }
120 continue;
121 }
122
123 Value *Cond = Assume->getArgOperand(0);
124 // Don't drop type tests, which have special semantics.
126 continue;
127
128 SmallVector<Value *> Affected;
129 findValuesAffectedByCondition(Cond, /*IsAssume=*/true,
130 [&](Value *A) { Affected.push_back(A); });
131
132 if (!affectedValuesAreEphemeral(Affected))
133 continue;
134
135 Assume->eraseFromParent();
137 Changed = true;
138 }
139
140 if (Changed) {
143 return PA;
144 }
145 return PreservedAnalyses::all();
146}
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static bool affectedValuesAreEphemeral(ArrayRef< Value * > Affected)
#define F(x, y, z)
Definition MD5.cpp:55
#define I(x, y, z)
Definition MD5.cpp:58
FunctionAnalysisManager FAM
const SmallVectorImpl< MachineOperand > & Cond
bool IsDead
This file implements a set that has insertion order iteration characteristics.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:41
A function analysis which provides an AssumptionCache.
A cache of @llvm.assume calls within a function.
static void findValuesAffectedByOperandBundle(OperandBundleUse Bundle, function_ref< void(Value *)> InsertAffected)
Determine which values are affected by this assume operand bundle.
LLVM_ABI void registerAssumption(AssumeInst *CI)
Add an @llvm.assume intrinsic to this function's cache.
MutableArrayRef< WeakVH > assumptions()
Access the list of assumption handles currently tracked for this function.
Represents analyses that only rely on functions' control flow.
Definition Analysis.h:73
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
static LLVM_ABI CallBase * Create(CallBase *CB, ArrayRef< OperandBundleDef > Bundles, InsertPosition InsertPt=nullptr)
Create a clone of CB with a different set of operand bundles and insert it before InsertPt.
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Definition Analysis.h:151
size_type size() const
Determine the number of elements in the SetVector.
Definition SetVector.h:102
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition SetVector.h:150
A SetVector that performs no allocations if smaller than a certain size.
Definition SetVector.h:338
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
LLVM Value Representation.
Definition Value.h:75
iterator_range< user_iterator > users()
Definition Value.h:426
A nullable Value handle that is nullable.
Changed
bool match(Val *V, const Pattern &P)
IntrinsicID_match m_Intrinsic()
Match intrinsic calls like this: m_Intrinsic<Intrinsic::fabs>(m_Value(X))
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI bool RecursivelyDeleteTriviallyDeadInstructions(Value *V, const TargetLibraryInfo *TLI=nullptr, MemorySSAUpdater *MSSAU=nullptr, std::function< void(Value *)> AboutToDeleteCallback=std::function< void(Value *)>())
If the specified value is a trivially dead instruction, delete it.
Definition Local.cpp:533
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2116
auto cast_or_null(const Y &Val)
Definition Casting.h:715
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:548
LLVM_ABI bool RecursivelyDeleteTriviallyDeadInstructionsPermissive(SmallVectorImpl< WeakTrackingVH > &DeadInsts, const TargetLibraryInfo *TLI=nullptr, MemorySSAUpdater *MSSAU=nullptr, std::function< void(Value *)> AboutToDeleteCallback=std::function< void(Value *)>())
Same functionality as RecursivelyDeleteTriviallyDeadInstructions, but allow instructions that are not...
Definition Local.cpp:548
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:560
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI void findValuesAffectedByCondition(Value *Cond, bool IsAssume, function_ref< void(Value *)> InsertAffected)
Call InsertAffected on all Values whose known bits / value may be affected by the condition Cond.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
A lightweight accessor for an operand bundle meant to be passed around by value.
ArrayRef< Use > Inputs