19 #define AA_NAME "alignment-from-assumptions"
20 #define DEBUG_TYPE AA_NAME
41 "Number of loads changed by alignment assumptions");
43 "Number of stores changed by alignment assumptions");
45 "Number of memory intrinsics changed by alignment assumptions");
74 static const char aip_name[] =
"Alignment from assumptions";
84 return new AlignmentFromAssumptions();
94 const SCEV *AlignSCEV,
101 DEBUG(
dbgs() <<
"\talignment relative to " << *AlignSCEV <<
" is " <<
102 *DiffUnitsSCEV <<
" (diff: " << *DiffSCEV <<
")\n");
105 dyn_cast<SCEVConstant>(DiffUnitsSCEV)) {
106 int64_t DiffUnits = ConstDUSCEV->getValue()->getSExtValue();
113 cast<SCEVConstant>(AlignSCEV)->getValue()->getSExtValue();
117 uint64_t DiffUnitsAbs =
std::abs(DiffUnits);
119 return (
unsigned) DiffUnitsAbs;
142 DEBUG(
dbgs() <<
"AFI: alignment of " << *Ptr <<
" relative to " <<
143 *AlignSCEV <<
" and offset " << *OffSCEV <<
144 " using diff " << *DiffSCEV <<
"\n");
147 DEBUG(
dbgs() <<
"\tnew alignment: " << NewAlignment <<
"\n");
152 dyn_cast<SCEVAddRecExpr>(DiffSCEV)) {
160 const SCEV *DiffStartSCEV = DiffARSCEV->getStart();
161 const SCEV *DiffIncSCEV = DiffARSCEV->getStepRecurrence(*SE);
163 DEBUG(
dbgs() <<
"\ttrying start/inc alignment using start " <<
164 *DiffStartSCEV <<
" and inc " << *DiffIncSCEV <<
"\n");
173 DEBUG(
dbgs() <<
"\tnew start alignment: " << NewAlignment <<
"\n");
174 DEBUG(
dbgs() <<
"\tnew inc alignment: " << NewIncAlignment <<
"\n");
176 if (!NewAlignment || !NewIncAlignment) {
178 }
else if (NewAlignment > NewIncAlignment) {
179 if (NewAlignment % NewIncAlignment == 0) {
180 DEBUG(
dbgs() <<
"\tnew start/inc alignment: " <<
181 NewIncAlignment <<
"\n");
182 return NewIncAlignment;
184 }
else if (NewIncAlignment > NewAlignment) {
185 if (NewIncAlignment % NewAlignment == 0) {
186 DEBUG(
dbgs() <<
"\tnew start/inc alignment: " <<
187 NewAlignment <<
"\n");
190 }
else if (NewIncAlignment == NewAlignment) {
191 DEBUG(
dbgs() <<
"\tnew start/inc alignment: " <<
192 NewAlignment <<
"\n");
202 const SCEV *&AlignSCEV,
203 const SCEV *&OffSCEV) {
221 else if (!CmpRHSSCEV->
isZero())
234 if (isa<SCEVConstant>(AndLHSSCEV)) {
252 TrailingOnes =
std::min(TrailingOnes,
253 unsigned(
sizeof(
unsigned) * CHAR_BIT - 1));
263 if (
PtrToIntInst *PToI = dyn_cast<PtrToIntInst>(AndLHS)) {
264 AAPtr = PToI->getPointerOperand();
267 dyn_cast<SCEVAddExpr>(AndLHSSCEV)) {
270 JE = AndLHSAddSCEV->op_end(); J != JE; ++J)
271 if (
const SCEVUnknown *OpUnk = dyn_cast<SCEVUnknown>(*J))
272 if (
PtrToIntInst *PToI = dyn_cast<PtrToIntInst>(OpUnk->getValue())) {
273 AAPtr = PToI->getPointerOperand();
285 if (OffSCEVBits < 64)
287 else if (OffSCEVBits > 64)
296 const SCEV *AlignSCEV, *OffSCEV;
302 if (isa<ConstantData>(AAPtr))
319 while (!WorkList.
empty()) {
322 if (
LoadInst *LI = dyn_cast<LoadInst>(J)) {
324 LI->getPointerOperand(),
SE);
326 if (NewAlignment > LI->getAlignment()) {
327 LI->setAlignment(NewAlignment);
328 ++NumLoadAlignChanged;
330 }
else if (
StoreInst *
SI = dyn_cast<StoreInst>(J)) {
332 SI->getPointerOperand(),
SE);
334 if (NewAlignment >
SI->getAlignment()) {
335 SI->setAlignment(NewAlignment);
336 ++NumStoreAlignChanged;
339 unsigned NewDestAlignment =
getNewAlignment(AASCEV, AlignSCEV, OffSCEV,
349 MTI->getSource(),
SE);
361 DEBUG(
dbgs() <<
"\tmem trans: " << NewDestAlignment <<
" " <<
362 AltDestAlignment <<
" " << NewSrcAlignment <<
363 " " << AltSrcAlignment <<
"\n");
366 unsigned NewAlignment = 0;
367 if (NewDestAlignment <= std::max(NewSrcAlignment, AltSrcAlignment))
368 NewAlignment = std::max(NewAlignment, NewDestAlignment);
369 if (AltDestAlignment <= std::max(NewSrcAlignment, AltSrcAlignment))
370 NewAlignment = std::max(NewAlignment, AltDestAlignment);
371 if (NewSrcAlignment <= std::max(NewDestAlignment, AltDestAlignment))
372 NewAlignment = std::max(NewAlignment, NewSrcAlignment);
373 if (AltSrcAlignment <= std::max(NewDestAlignment, AltDestAlignment))
374 NewAlignment = std::max(NewAlignment, AltSrcAlignment);
376 if (NewAlignment >
MI->getAlignment()) {
378 MI->getParent()->getContext()), NewAlignment));
379 ++NumMemIntAlignChanged;
384 }
else if (NewDestAlignment >
MI->getAlignment()) {
385 assert((!isa<MemIntrinsic>(
MI) || isa<MemSetInst>(
MI)) &&
386 "Unknown memory intrinsic");
389 MI->getParent()->getContext()), NewDestAlignment));
390 ++NumMemIntAlignChanged;
407 bool AlignmentFromAssumptions::runOnFunction(
Function &
F) {
411 auto &AC = getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
412 ScalarEvolution *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
413 DominatorTree *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
415 return Impl.runImpl(F, AC, SE, DT);
427 bool Changed =
false;
441 bool Changed =
runImpl(F, AC, &SE, &DT);
Legacy wrapper pass to provide the GlobalsAAResult object.
void push_back(const T &Elt)
INITIALIZE_PASS_BEGIN(AlignmentFromAssumptions, AA_NAME, aip_name, false, false) INITIALIZE_PASS_END(AlignmentFromAssumptions
DenseMap< MemTransferInst *, unsigned > NewSrcAlignments
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
const SCEV * getConstant(ConstantInt *V)
STATISTIC(NumFunctions,"Total number of functions")
This is the interface for a simple mod/ref and alias analysis over globals.
static unsigned getNewAlignment(const SCEV *AASCEV, const SCEV *AlignSCEV, const SCEV *OffSCEV, Value *Ptr, ScalarEvolution *SE)
bool isZero() const
Return true if the expression is a constant zero.
The main scalar evolution driver.
This class represents a function call, abstracting a target machine's calling convention.
size_type count(PtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
An immutable pass that tracks lazily created AssumptionCache objects.
A cache of .assume calls within a function.
const Function * getParent() const
Return the enclosing method, or null if none.
bool isValidAssumeForContext(const Instruction *I, const Instruction *CxtI, const DominatorTree *DT=nullptr)
Return true if it is valid to use the assumptions provided by an assume intrinsic, I, at the point in the control-flow identified by the context instruction, CxtI.
Analysis pass which computes a DominatorTree.
An instruction for reading from memory.
static IntegerType * getInt64Ty(LLVMContext &C)
DenseMap< MemTransferInst *, unsigned > NewDestAlignments
FunctionPass * createAlignmentFromAssumptionsPass()
const SCEV * getZero(Type *Ty)
Return a SCEV for the constant 0 of a specific type.
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
const SCEV *const * op_iterator
Analysis pass that exposes the LoopInfo for a function.
static const unsigned MaximumAlignment
This class represents a cast from a pointer to an integer.
LLVM_NODISCARD bool empty() const
This node represents a polynomial recurrence on the trip count of the specified loop.
An instruction for storing to memory.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree...
Maximum length of the test input libFuzzer tries to guess a good value based on the corpus and reports it always prefer smaller inputs during the corpus shuffle When libFuzzer itself reports a bug this exit code will be used If indicates the maximal total time in seconds to run the fuzzer minimizes the provided crash input Use with etc Experimental Use value profile to guide fuzzing Number of simultaneous worker processes to run the jobs If min(jobs, NumberOfCpuCores()/2)\" is used.") FUZZER_FLAG_INT(reload
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
This means that we are dealing with an entirely unknown SCEV value, and only represent it as its LLVM...
A set of analyses that are preserved following a run of a transformation pass.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs...ExtraArgs)
Get the result of an analysis pass for a given IR unit.
The instances of the Type class are immutable: once they are created, they are never changed...
Type * getType() const
Return the LLVM type of this SCEV expression.
static const char aip_name[]
A manager for alias analyses.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
Represent the analysis usage information of a pass.
constexpr bool isPowerOf2_64(uint64_t Value)
isPowerOf2_64 - This function returns true if the argument is a power of two 0 (64 bit edition...
This instruction compares its operands according to the predicate given to the constructor.
Analysis pass providing a never-invalidated alias analysis result.
const SCEV * getMinusSCEV(const SCEV *LHS, const SCEV *RHS, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap)
Return LHS-RHS. Minus is represented in SCEV as A+B*-1.
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE,"Assign register bank of generic virtual registers", false, false) RegBankSelect
FunctionPass class - This class is used to implement most global optimizations.
Value * getOperand(unsigned i) const
Predicate getPredicate() const
Return the predicate for this instruction.
MutableArrayRef< WeakVH > assumptions()
Access the list of assumption handles currently tracked for this function.
const APInt & getAPInt() const
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
A function analysis which provides an AssumptionCache.
BinaryOps getOpcode() const
This is the common base class for memset/memcpy/memmove.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
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.
const SCEV * getNoopOrSignExtend(const SCEV *V, Type *Ty)
Return a SCEV corresponding to a conversion of the input value to the specified type.
LLVM_NODISCARD T pop_back_val()
void invalidate(IRUnitT &IR)
Invalidate a specific analysis pass for an IR module.
Value * stripPointerCasts()
Strip off pointer casts, all-zero GEPs, and aliases.
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:
bool extractAlignmentInfo(CallInst *I, Value *&AAPtr, const SCEV *&AlignSCEV, const SCEV *&OffSCEV)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Value * getArgOperand(unsigned i) const
getArgOperand/setArgOperand - Return/set the i-th call argument.
This node represents an addition of some number of SCEVs.
const SCEV * getSignExtendExpr(const SCEV *Op, Type *Ty)
bool processAssumption(CallInst *I)
iterator_range< user_iterator > users()
APInt And(const APInt &LHS, const APInt &RHS)
Bitwise AND function for APInt.
Analysis pass that exposes the ScalarEvolution for a function.
This class wraps the llvm.memcpy/memmove intrinsics.
This class represents an analyzed expression in the program.
static unsigned getNewAlignmentDiff(const SCEV *DiffSCEV, const SCEV *AlignSCEV, ScalarEvolution *SE)
static IntegerType * getInt32Ty(LLVMContext &C)
void initializeAlignmentFromAssumptionsPass(PassRegistry &)
APFloat abs(APFloat X)
Returns the absolute value of the argument.
unsigned countTrailingOnes() const
Count the number of trailing one bits.
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
void preserve()
Mark an analysis as preserved.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
unsigned getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
LLVM Value Representation.
const SCEV * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
const SCEV * getUDivExpr(const SCEV *LHS, const SCEV *RHS)
Get a canonical unsigned division expression, or something simpler if possible.
The legacy pass manager's analysis pass to compute loop information.
bool runImpl(Function &F, AssumptionCache &AC, ScalarEvolution *SE_, DominatorTree *DT_)
A container for analyses that lazily runs them and caches their results.
Legacy analysis pass which computes a DominatorTree.
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object...
const SCEV * getMulExpr(SmallVectorImpl< const SCEV * > &Ops, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap)
Get a canonical multiply expression, or something simpler if possible.
const BasicBlock * getParent() const
This class represents a constant integer value.