LLVM 24.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"
17
18using namespace llvm;
19using namespace llvm::PatternMatch;
20
22 // Check whether all the uses are ephemeral, i.e. recursively only used
23 // by assumes. In that case, the assume does not provide useful information.
24 // Note that additional users may appear as a result of inlining and CSE,
25 // so we should only make this assumption late in the optimization pipeline.
27 auto AddUsers = [&](Value *V) {
28 for (User *U : V->users()) {
29 // Bail out if we need to inspect too many users.
30 if (Worklist.size() >= 32)
31 return false;
32 Worklist.insert(cast<Instruction>(U));
33 }
34 return true;
35 };
36
37 for (Value *V : Affected) {
38 // Do not handle assumes on globals for now. The use list for them may
39 // contain uses in other functions.
41 return false;
42
43 if (!AddUsers(V))
44 return false;
45 }
46
47 for (unsigned Idx = 0; Idx < Worklist.size(); ++Idx) {
48 Instruction *I = Worklist[Idx];
49
50 // Use in assume is ephemeral.
51 if (isa<AssumeInst>(I))
52 continue;
53
54 // Use in side-effecting instruction is non-ephemeral.
55 if (I->mayHaveSideEffects() || I->isTerminator())
56 return false;
57
58 // Otherwise, recursively look at the users.
59 if (!AddUsers(I))
60 return false;
61 }
62
63 return true;
64}
65
68 AssumptionCache &AC = FAM.getResult<AssumptionAnalysis>(F);
69 bool Changed = false;
70
71 for (WeakVH &Elem : AC.assumptions()) {
72 auto *Assume = cast_or_null<AssumeInst>(Elem);
73 if (!Assume)
74 continue;
75
76 if (Assume->hasOperandBundles()) {
77 // Handle operand bundle assumptions.
78 SmallVector<WeakTrackingVH> DeadBundleArgs;
80 unsigned NumBundles = Assume->getNumOperandBundles();
81 for (unsigned I = 0; I != NumBundles; ++I) {
82 auto IsDead = [&](OperandBundleUse Bundle) {
83 switch (getBundleAttrFromOBU(Bundle)) {
84 // "ignore" operand bundles are always dead.
85 case BundleAttr::Ignore:
86 return true;
87
88 // "dereferenceable" operand bundles are only dropped if requested
89 // (e.g., after loop vectorization has run).
90 case BundleAttr::Dereferenceable:
91 return DropDereferenceable;
92
93 default:
94 break;
95 }
96
97 // Bundles without arguments do not affect any specific values.
98 // Always keep them for now.
99 if (Bundle.Inputs.empty())
100 return false;
101
102 SmallVector<Value *> Affected;
104 Bundle, [&](Value *A) { Affected.push_back(A); });
105
106 return affectedValuesAreEphemeral(Affected);
107 };
108
109 OperandBundleUse Bundle = Assume->getOperandBundleAt(I);
110 if (IsDead(Bundle))
111 append_range(DeadBundleArgs, Bundle.Inputs);
112 else
113 KeptBundles.emplace_back(Bundle);
114 }
115
116 if (KeptBundles.size() != NumBundles) {
117 if (KeptBundles.empty()) {
118 // All operand bundles are dead, remove the whole assume.
119 Assume->eraseFromParent();
120 } else {
121 // Otherwise only drop the dead operand bundles. Replace the existing
122 // assumption in place so the cache's assumption vector is not grown
123 // while we iterate over it.
124 CallBase *NewAssume =
125 CallBase::Create(Assume, KeptBundles, Assume->getIterator());
126 AC.replaceAssumption(Elem, cast<AssumeInst>(NewAssume));
127 Assume->eraseFromParent();
128 }
129
131 Changed = true;
132 }
133 continue;
134 }
135
136 Value *Cond = Assume->getArgOperand(0);
137 // Don't drop type tests, which have special semantics.
140 continue;
141
142 SmallVector<Value *> Affected;
143 findValuesAffectedByCondition(Cond, /*IsAssume=*/true,
144 [&](Value *A) { Affected.push_back(A); });
145
146 if (!affectedValuesAreEphemeral(Affected))
147 continue;
148
149 Assume->eraseFromParent();
151 Changed = true;
152 }
153
154 if (Changed) {
157 return PA;
158 }
159 return PreservedAnalyses::all();
160}
161
163 raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {
164 static_cast<PassInfoMixin<DropUnnecessaryAssumesPass> *>(this)->printPipeline(
165 OS, MapClassName2PassName);
166 if (DropDereferenceable)
167 OS << "<drop-deref>";
168}
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static bool affectedValuesAreEphemeral(ArrayRef< Value * > Affected)
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
FunctionAnalysisManager FAM
SmallVector< MachineOperand, 4 > Cond
bool IsDead
This file implements a set that has insertion order iteration characteristics.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
A function analysis which provides an AssumptionCache.
A cache of @llvm.assume calls within a function.
static LLVM_ABI void findValuesAffectedByOperandBundle(OperandBundleUse Bundle, function_ref< void(Value *)> InsertAffected)
Determine which values are affected by this assume operand bundle.
LLVM_ABI void replaceAssumption(WeakVH &Handle, AssumeInst *New)
Replace the assumption referenced by Handle (must be a valid handle for a registered assumption) with...
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:103
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition SetVector.h:157
A SetVector that performs no allocations if smaller than a certain size.
Definition SetVector.h:345
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.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
LLVM Value Representation.
Definition Value.h:75
iterator_range< user_iterator > users()
Definition Value.h:428
A nullable Value handle that is nullable.
An efficient, type-erasing, non-owning reference to a callable.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
bool match(Val *V, const Pattern &P)
auto m_Intrinsic(const Ts &...Ops)
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:522
BundleAttr getBundleAttrFromOBU(OperandBundleUse OBU)
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2224
auto cast_or_null(const Y &Val)
Definition Casting.h:714
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:547
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:537
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
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.
LLVM_ABI void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
A lightweight accessor for an operand bundle meant to be passed around by value.
ArrayRef< Use > Inputs