40 #define DEBUG_TYPE "bdce"
42 STATISTIC(NumRemoved,
"Number of instructions removed (unused)");
43 STATISTIC(NumSimplified,
"Number of instructions trivialized (dead bits)");
60 void determineLiveOperandBits(
const Instruction *UserI,
80 return isa<TerminatorInst>(
I) || isa<DbgInfoIntrinsic>(I) ||
81 isa<LandingPadInst>(
I) || I->mayHaveSideEffects();
84 void BDCE::determineLiveOperandBits(
const Instruction *UserI,
97 auto ComputeKnownBits =
98 [&](
unsigned BitWidth,
const Value *V1,
const Value *
V2) {
100 KnownZero =
APInt(BitWidth, 0);
101 KnownOne =
APInt(BitWidth, 0);
106 KnownZero2 =
APInt(BitWidth, 0);
107 KnownOne2 =
APInt(BitWidth, 0);
116 case Instruction::Invoke:
117 if (
const IntrinsicInst *II = dyn_cast<IntrinsicInst>(UserI))
118 switch (II->getIntrinsicID()) {
120 case Intrinsic::bswap:
125 case Intrinsic::ctlz:
126 if (OperandNo == 0) {
130 ComputeKnownBits(BitWidth, I,
nullptr);
135 case Intrinsic::cttz:
136 if (OperandNo == 0) {
140 ComputeKnownBits(BitWidth, I,
nullptr);
147 case Instruction::Add:
148 case Instruction::Sub:
154 case Instruction::Shl:
157 dyn_cast<ConstantInt>(UserI->
getOperand(1))) {
159 AB = AOut.
lshr(ShiftAmt);
170 case Instruction::LShr:
173 dyn_cast<ConstantInt>(UserI->
getOperand(1))) {
175 AB = AOut.
shl(ShiftAmt);
179 if (cast<LShrOperator>(UserI)->isExact())
183 case Instruction::AShr:
186 dyn_cast<ConstantInt>(UserI->
getOperand(1))) {
187 uint64_t ShiftAmt = CI->getLimitedValue(BitWidth-1);
188 AB = AOut.
shl(ShiftAmt);
198 if (cast<AShrOperator>(UserI)->isExact())
209 if (OperandNo == 0) {
210 ComputeKnownBits(BitWidth, I, UserI->
getOperand(1));
214 ComputeKnownBits(BitWidth, UserI->
getOperand(0),
I);
215 AB &= ~(KnownZero & ~KnownZero2);
225 if (OperandNo == 0) {
226 ComputeKnownBits(BitWidth, I, UserI->
getOperand(1));
230 ComputeKnownBits(BitWidth, UserI->
getOperand(0),
I);
231 AB &= ~(KnownOne & ~KnownOne2);
238 case Instruction::Trunc:
239 AB = AOut.
zext(BitWidth);
241 case Instruction::ZExt:
242 AB = AOut.
trunc(BitWidth);
244 case Instruction::SExt:
245 AB = AOut.
trunc(BitWidth);
262 if (skipOptnoneFunction(F))
265 AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
266 DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
279 DEBUG(
dbgs() <<
"BDCE: Root: " << I <<
"\n");
285 if (!AliveBits.
count(&I)) {
286 AliveBits[&
I] =
APInt(
IT->getBitWidth(), 0);
308 while (!Worklist.
empty()) {
311 DEBUG(
dbgs() <<
"BDCE: Visiting: " << *UserI);
314 AOut = AliveBits[UserI];
322 APInt KnownZero, KnownOne, KnownZero2, KnownOne2;
329 unsigned BitWidth =
IT->getBitWidth();
333 AB =
APInt(BitWidth, 0);
338 determineLiveOperandBits(UserI, I, OI.getOperandNo(), AOut, AB,
340 KnownZero2, KnownOne2);
346 APInt ABPrev(BitWidth, 0);
347 auto ABI = AliveBits.
find(I);
348 if (ABI != AliveBits.
end())
349 ABPrev = ABI->second;
351 APInt ABNew = AB | ABPrev;
352 if (ABNew != ABPrev || ABI == AliveBits.
end()) {
353 AliveBits[
I] = std::move(ABNew);
356 }
else if (!Visited.
count(I)) {
363 bool Changed =
false;
373 auto ABI = AliveBits.
find(&I);
374 if (ABI != AliveBits.
end()) {
375 if (ABI->second.getBoolValue())
378 DEBUG(
dbgs() <<
"BDCE: Trivializing: " << I <<
" (all bits dead)\n");
387 }
else if (Visited.
count(&I)) {
iplist< Instruction >::iterator eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing basic block and deletes it...
void push_back(const T &Elt)
A parsed version of the target data layout string in and methods for querying it. ...
APInt LLVM_ATTRIBUTE_UNUSED_RESULT byteSwap() const
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
static APInt getAllOnesValue(unsigned numBits)
Get the all-ones value.
void dropAllReferences()
Drop all references to operands.
INITIALIZE_PASS_BEGIN(BDCE,"bdce","Bit-Tracking Dead Code Elimination", false, false) INITIALIZE_PASS_END(BDCE
STATISTIC(NumFunctions,"Total number of functions")
void setBit(unsigned bitPosition)
Set a given bit to 1.
bool hasNoSignedWrap() const
Test whether this operation is known to never undergo signed overflow, aka the nsw property...
size_type count(PtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Get a value with low bits set.
An immutable pass that tracks lazily created AssumptionCache objects.
void computeKnownBits(Value *V, APInt &KnownZero, APInt &KnownOne, const DataLayout &DL, unsigned Depth=0, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr)
Determine which bits of V are known to be either zero or one and return them in the KnownZero/KnownOn...
A cache of .assume calls within a function.
uint64_t getLimitedValue(uint64_t Limit=~0ULL) const
If this value is smaller than the specified limit, return it, otherwise return the limit value...
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::ZeroOrMore, cl::values(clEnumValN(DefaultIT,"arm-default-it","Generate IT block based on arch"), clEnumValN(RestrictedIT,"arm-restrict-it","Disallow deprecated IT based on ARMv8"), clEnumValN(NoRestrictedIT,"arm-no-restrict-it","Allow IT blocks based on ARMv7"), clEnumValEnd))
T LLVM_ATTRIBUTE_UNUSED_RESULT pop_back_val()
A Use represents the edge between a Value definition and its users.
APInt LLVM_ATTRIBUTE_UNUSED_RESULT lshr(unsigned shiftAmt) const
Logical right-shift function.
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Number of individual test Apply this number of consecutive mutations to each input exit after the first new interesting input is found the minimized corpus is saved into the first input directory Number of jobs to run If min(jobs, NumberOfCpuCores()/2)\" is used.") FUZZER_FLAG_INT(reload
bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const
unsigned getActiveBits() const
Compute the number of active bits in the value.
APInt LLVM_ATTRIBUTE_UNUSED_RESULT shl(unsigned shiftAmt) const
Left-shift function.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree...
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Get a value with high bits set.
Bit Tracking Dead Code false
* if(!EatIfPresent(lltok::kw_thread_local)) return false
ParseOptionalThreadLocal := /*empty.
APInt LLVM_ATTRIBUTE_UNUSED_RESULT trunc(unsigned width) const
Truncate to new width.
void initializeBDCEPass(PassRegistry &)
APInt Or(const APInt &LHS, const APInt &RHS)
Bitwise OR function for APInt.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
APInt Xor(const APInt &LHS, const APInt &RHS)
Bitwise XOR function for APInt.
Represent the analysis usage information of a pass.
unsigned getBitWidth() const
Return the number of bits in the APInt.
FunctionPass class - This class is used to implement most global optimizations.
FunctionPass * createBitTrackingDCEPass()
Value * getOperand(unsigned i) const
Class to represent integer types.
Bit Tracking Dead Code Elimination
unsigned countTrailingZeros() const
Count the number of trailing zero bits.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
This is the shared class of boolean and integer constants.
const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Module.h This file contains the declarations for the Module class.
Type * getType() const
All values are typed, get the type of this value.
static Constant * get(Type *Ty, uint64_t V, bool isSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
size_type count(const KeyT &Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Class for arbitrary precision integers.
bool isIntegerTy() const
isIntegerTy - True if this is an instance of IntegerType.
APInt And(const APInt &LHS, const APInt &RHS)
Bitwise AND function for APInt.
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
iterator_range< inst_iterator > inst_range(Function *F)
iterator find(const KeyT &Val)
Bit Tracking Dead Code static false bool isAlwaysLive(Instruction *I)
LLVM Value Representation.
unsigned getOpcode() const
getOpcode() returns a member of one of the enums like Instruction::Add.
unsigned countLeadingZeros() const
The APInt version of the countLeadingZeros functions in MathExtras.h.
APInt LLVM_ATTRIBUTE_UNUSED_RESULT zext(unsigned width) const
Zero extend to a new width.
Legacy analysis pass which computes a DominatorTree.
bool hasNoUnsignedWrap() const
Test whether this operation is known to never undergo unsigned overflow, aka the nuw property...
IntrinsicInst - A useful wrapper class for inspecting calls to intrinsic functions.