19 #define AA_NAME "alignment-from-assumptions"
20 #define DEBUG_TYPE AA_NAME
40 "Number of loads changed by alignment assumptions");
42 "Number of stores changed by alignment assumptions");
44 "Number of memory intrinsics changed by alignment assumptions");
76 const SCEV *&OffSCEV);
82 static const char aip_name[] =
"Alignment from assumptions";
92 return new AlignmentFromAssumptions();
102 const SCEV *AlignSCEV,
109 DEBUG(
dbgs() <<
"\talignment relative to " << *AlignSCEV <<
" is " <<
110 *DiffUnitsSCEV <<
" (diff: " << *DiffSCEV <<
")\n");
113 dyn_cast<SCEVConstant>(DiffUnitsSCEV)) {
114 int64_t DiffUnits = ConstDUSCEV->getValue()->getSExtValue();
121 cast<SCEVConstant>(AlignSCEV)->getValue()->getSExtValue();
125 uint64_t DiffUnitsAbs =
std::abs(DiffUnits);
127 return (
unsigned) DiffUnitsAbs;
150 DEBUG(
dbgs() <<
"AFI: alignment of " << *Ptr <<
" relative to " <<
151 *AlignSCEV <<
" and offset " << *OffSCEV <<
152 " using diff " << *DiffSCEV <<
"\n");
155 DEBUG(
dbgs() <<
"\tnew alignment: " << NewAlignment <<
"\n");
160 dyn_cast<SCEVAddRecExpr>(DiffSCEV)) {
168 const SCEV *DiffStartSCEV = DiffARSCEV->getStart();
169 const SCEV *DiffIncSCEV = DiffARSCEV->getStepRecurrence(*SE);
171 DEBUG(
dbgs() <<
"\ttrying start/inc alignment using start " <<
172 *DiffStartSCEV <<
" and inc " << *DiffIncSCEV <<
"\n");
181 DEBUG(
dbgs() <<
"\tnew start alignment: " << NewAlignment <<
"\n");
182 DEBUG(
dbgs() <<
"\tnew inc alignment: " << NewIncAlignment <<
"\n");
184 if (!NewAlignment || !NewIncAlignment) {
186 }
else if (NewAlignment > NewIncAlignment) {
187 if (NewAlignment % NewIncAlignment == 0) {
188 DEBUG(
dbgs() <<
"\tnew start/inc alignment: " <<
189 NewIncAlignment <<
"\n");
190 return NewIncAlignment;
192 }
else if (NewIncAlignment > NewAlignment) {
193 if (NewIncAlignment % NewAlignment == 0) {
194 DEBUG(
dbgs() <<
"\tnew start/inc alignment: " <<
195 NewAlignment <<
"\n");
198 }
else if (NewIncAlignment == NewAlignment) {
199 DEBUG(
dbgs() <<
"\tnew start/inc alignment: " <<
200 NewAlignment <<
"\n");
208 bool AlignmentFromAssumptions::extractAlignmentInfo(
CallInst *
I,
210 const SCEV *&OffSCEV) {
224 const SCEV *CmpLHSSCEV = SE->getSCEV(CmpLHS);
225 const SCEV *CmpRHSSCEV = SE->getSCEV(CmpRHS);
228 else if (!CmpRHSSCEV->
isZero())
239 const SCEV *AndLHSSCEV = SE->getSCEV(AndLHS);
240 const SCEV *AndRHSSCEV = SE->getSCEV(AndRHS);
241 if (isa<SCEVConstant>(AndLHSSCEV)) {
252 unsigned TrailingOnes =
260 TrailingOnes =
std::min(TrailingOnes,
261 unsigned(
sizeof(
unsigned) * CHAR_BIT - 1));
265 AlignSCEV = SE->getConstant(Int64Ty, Alignment);
271 if (
PtrToIntInst *PToI = dyn_cast<PtrToIntInst>(AndLHS)) {
272 AAPtr = PToI->getPointerOperand();
273 OffSCEV = SE->getConstant(Int64Ty, 0);
275 dyn_cast<SCEVAddExpr>(AndLHSSCEV)) {
278 JE = AndLHSAddSCEV->op_end(); J != JE; ++J)
279 if (
const SCEVUnknown *OpUnk = dyn_cast<SCEVUnknown>(*J))
280 if (
PtrToIntInst *PToI = dyn_cast<PtrToIntInst>(OpUnk->getValue())) {
281 AAPtr = PToI->getPointerOperand();
282 OffSCEV = SE->getMinusSCEV(AndLHSAddSCEV, *J);
293 if (OffSCEVBits < 64)
294 OffSCEV = SE->getSignExtendExpr(OffSCEV, Int64Ty);
295 else if (OffSCEVBits > 64)
302 bool AlignmentFromAssumptions::processAssumption(
CallInst *ACall) {
304 const SCEV *AlignSCEV, *OffSCEV;
305 if (!extractAlignmentInfo(ACall, AAPtr, AlignSCEV, OffSCEV))
308 const SCEV *AASCEV = SE->getSCEV(AAPtr);
322 while (!WorkList.
empty()) {
325 if (
LoadInst *LI = dyn_cast<LoadInst>(J)) {
327 LI->getPointerOperand(), SE);
329 if (NewAlignment > LI->getAlignment()) {
330 LI->setAlignment(NewAlignment);
331 ++NumLoadAlignChanged;
333 }
else if (
StoreInst *SI = dyn_cast<StoreInst>(J)) {
335 SI->getPointerOperand(), SE);
337 if (NewAlignment >
SI->getAlignment()) {
338 SI->setAlignment(NewAlignment);
339 ++NumStoreAlignChanged;
342 unsigned NewDestAlignment =
getNewAlignment(AASCEV, AlignSCEV, OffSCEV,
352 MTI->getSource(), SE);
355 NewDestAlignments.find(MTI);
356 unsigned AltDestAlignment = (DI == NewDestAlignments.end()) ?
360 NewSrcAlignments.
find(MTI);
361 unsigned AltSrcAlignment = (
SI == NewSrcAlignments.end()) ?
364 DEBUG(
dbgs() <<
"\tmem trans: " << NewDestAlignment <<
" " <<
365 AltDestAlignment <<
" " << NewSrcAlignment <<
366 " " << AltSrcAlignment <<
"\n");
369 unsigned NewAlignment = 0;
370 if (NewDestAlignment <= std::max(NewSrcAlignment, AltSrcAlignment))
371 NewAlignment = std::max(NewAlignment, NewDestAlignment);
372 if (AltDestAlignment <= std::max(NewSrcAlignment, AltSrcAlignment))
373 NewAlignment = std::max(NewAlignment, AltDestAlignment);
374 if (NewSrcAlignment <= std::max(NewDestAlignment, AltDestAlignment))
375 NewAlignment = std::max(NewAlignment, NewSrcAlignment);
376 if (AltSrcAlignment <= std::max(NewDestAlignment, AltDestAlignment))
377 NewAlignment = std::max(NewAlignment, AltSrcAlignment);
379 if (NewAlignment >
MI->getAlignment()) {
381 MI->getParent()->getContext()), NewAlignment));
382 ++NumMemIntAlignChanged;
385 NewDestAlignments.insert(std::make_pair(MTI, NewDestAlignment));
386 NewSrcAlignments.insert(std::make_pair(MTI, NewSrcAlignment));
387 }
else if (NewDestAlignment >
MI->getAlignment()) {
388 assert((!isa<MemIntrinsic>(
MI) || isa<MemSetInst>(
MI)) &&
389 "Unknown memory intrinsic");
392 MI->getParent()->getContext()), NewDestAlignment));
393 ++NumMemIntAlignChanged;
410 bool AlignmentFromAssumptions::runOnFunction(
Function &
F) {
411 bool Changed =
false;
412 auto &AC = getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
413 SE = &getAnalysis<ScalarEvolution>();
414 DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
416 NewDestAlignments.clear();
417 NewSrcAlignments.clear();
419 for (
auto &AssumeVH : AC.assumptions())
421 Changed |= processAssumption(cast<CallInst>(AssumeVH));
void push_back(const T &Elt)
INITIALIZE_PASS_BEGIN(AlignmentFromAssumptions, AA_NAME, aip_name, false, false) INITIALIZE_PASS_END(AlignmentFromAssumptions
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. ...
STATISTIC(NumFunctions,"Total number of functions")
static unsigned getNewAlignment(const SCEV *AASCEV, const SCEV *AlignSCEV, const SCEV *OffSCEV, Value *Ptr, ScalarEvolution *SE)
bool isZero() const
isZero - Return true if the expression is a constant zero.
ScalarEvolution - This class is the main scalar evolution driver.
CallInst - 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.
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.
LoadInst - an instruction for reading from memory.
static IntegerType * getInt64Ty(LLVMContext &C)
FunctionPass * createAlignmentFromAssumptionsPass()
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
const APInt & getValue() const
Return the constant as an APInt value reference.
T LLVM_ATTRIBUTE_UNUSED_RESULT pop_back_val()
const SCEV *const * op_iterator
#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
static const unsigned MaximumAlignment
This class represents a cast from a pointer to an integer.
SCEVAddRecExpr - This node represents a polynomial recurrence on the trip count of the specified loop...
bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const
StoreInst - an instruction for storing to memory.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree...
SCEVUnknown - This means that we are dealing with an entirely unknown SCEV value, and only represent ...
The instances of the Type class are immutable: once they are created, they are never changed...
Type * getType() const
getType - Return the LLVM type of this SCEV expression.
static const char aip_name[]
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.
This instruction compares its operands according to the predicate given to the constructor.
const SCEV * getMinusSCEV(const SCEV *LHS, const SCEV *RHS, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap)
getMinusSCEV - Return LHS-RHS. Minus is represented in SCEV as A+B*-1.
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.
BinaryOps getOpcode() const
MemIntrinsic - 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)
getNoopOrSignExtend - Return a SCEV corresponding to a conversion of the input value to the specified...
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.
ConstantInt * getValue() const
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.
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.
SCEVAddExpr - This node represents an addition of some number of SCEVs.
iterator_range< user_iterator > users()
bool isPowerOf2_64(uint64_t Value)
isPowerOf2_64 - This function returns true if the argument is a power of two 0 (64 bit edition...
LLVM_ATTRIBUTE_UNUSED_RESULT std::enable_if< !is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
APInt And(const APInt &LHS, const APInt &RHS)
Bitwise AND function for APInt.
MemTransferInst - This class wraps the llvm.memcpy/memmove intrinsics.
SCEV - 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.
iterator find(const KeyT &Val)
unsigned countTrailingOnes() const
Count the number of trailing one bits.
unsigned getPrimitiveSizeInBits() const LLVM_READONLY
getPrimitiveSizeInBits - Return the basic size of this type if it is a primitive type.
LLVM Value Representation.
const SCEV * getSCEV(Value *V)
getSCEV - Return a SCEV expression for the full generality of the specified expression.
const SCEV * getUDivExpr(const SCEV *LHS, const SCEV *RHS)
getUDivExpr - Get a canonical unsigned division expression, or something simpler if possible...
The legacy pass manager's analysis pass to compute loop information.
Legacy analysis pass which computes a DominatorTree.
const SCEV * getMulExpr(SmallVectorImpl< const SCEV * > &Ops, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap)
getMulExpr - Get a canonical multiply expression, or something simpler if possible.
const BasicBlock * getParent() const
SCEVConstant - This class represents a constant integer value.