197 using namespace llvm;
201 "disable-separate-const-offset-from-gep",
cl::init(
false),
202 cl::desc(
"Do not separate the constant offset from a GEP instruction"),
210 cl::desc(
"Verify this pass produces no dead code"),
228 class ConstantOffsetExtractor {
248 : IP(InsertionPt), DL(InsertionPt->getModule()->getDataLayout()), DT(DT) {
265 APInt find(
Value *V,
bool SignExtended,
bool ZeroExtended,
bool NonNegative);
286 Value *rebuildWithoutConstOffset();
303 Value *distributeExtsAndCloneChain(
unsigned ChainIndex);
306 Value *removeConstOffset(
unsigned ChainIndex);
320 bool CanTraceInto(
bool SignExtended,
bool ZeroExtended,
BinaryOperator *BO,
345 class SeparateConstOffsetFromGEP :
public FunctionPass {
349 SeparateConstOffsetFromGEP(
bool LowerGEP =
false)
363 bool doInitialization(
Module &M)
override {
383 int64_t AccumulativeByteOffset);
393 int64_t AccumulativeByteOffset);
439 bool hasMoreThanOneUseInLoop(
Value *v,
Loop *L);
467 SeparateConstOffsetFromGEP,
"separate-const-offset-from-gep",
468 "Split GEPs to a variadic base and a constant offset for better CSE",
false,
476 SeparateConstOffsetFromGEP, "separate-
const-offset-from-
gep",
477 "
Split GEPs to a variadic base and a constant offset
for better
CSE",
false,
481 return new SeparateConstOffsetFromGEP(LowerGEP);
484 bool ConstantOffsetExtractor::CanTraceInto(
bool SignExtended,
502 if (BO->
getOpcode() == Instruction::Or &&
526 if (
ConstantInt *ConstLHS = dyn_cast<ConstantInt>(LHS)) {
527 if (!ConstLHS->isNegative())
530 if (
ConstantInt *ConstRHS = dyn_cast<ConstantInt>(RHS)) {
531 if (!ConstRHS->isNegative())
561 if (ConstantOffset != 0)
return ConstantOffset;
562 ConstantOffset =
find(BO->
getOperand(1), SignExtended, ZeroExtended,
567 ConstantOffset = -ConstantOffset;
568 return ConstantOffset;
572 bool ZeroExtended,
bool NonNegative) {
580 if (U ==
nullptr)
return APInt(BitWidth, 0);
582 APInt ConstantOffset(BitWidth, 0);
585 ConstantOffset = CI->getValue();
588 if (CanTraceInto(SignExtended, ZeroExtended, BO, NonNegative))
589 ConstantOffset = findInEitherOperand(BO, SignExtended, ZeroExtended);
590 }
else if (isa<TruncInst>(V)) {
594 }
else if (isa<SExtInst>(V)) {
596 ZeroExtended, NonNegative).sext(BitWidth);
597 }
else if (isa<ZExtInst>(V)) {
604 true,
false).zext(BitWidth);
610 if (ConstantOffset != 0)
611 UserChain.push_back(U);
612 return ConstantOffset;
615 Value *ConstantOffsetExtractor::applyExts(
Value *V) {
619 for (
auto I = ExtInsts.rbegin(),
E = ExtInsts.rend();
I !=
E; ++
I) {
620 if (
Constant *
C = dyn_cast<Constant>(Current)) {
634 Value *ConstantOffsetExtractor::rebuildWithoutConstOffset() {
635 distributeExtsAndCloneChain(UserChain.size() - 1);
637 unsigned NewSize = 0;
638 for (
User *
I : UserChain) {
640 UserChain[NewSize] =
I;
644 UserChain.resize(NewSize);
645 return removeConstOffset(UserChain.size() - 1);
649 ConstantOffsetExtractor::distributeExtsAndCloneChain(
unsigned ChainIndex) {
650 User *U = UserChain[ChainIndex];
651 if (ChainIndex == 0) {
652 assert(isa<ConstantInt>(U));
654 return UserChain[ChainIndex] = cast<ConstantInt>(applyExts(U));
657 if (
CastInst *Cast = dyn_cast<CastInst>(U)) {
659 (isa<SExtInst>(Cast) || isa<ZExtInst>(Cast) || isa<TruncInst>(Cast)) &&
660 "Only following instructions can be traced: sext, zext & trunc");
661 ExtInsts.push_back(Cast);
662 UserChain[ChainIndex] =
nullptr;
663 return distributeExtsAndCloneChain(ChainIndex - 1);
669 unsigned OpNo = (BO->
getOperand(0) == UserChain[ChainIndex - 1] ? 0 : 1);
671 Value *NextInChain = distributeExtsAndCloneChain(ChainIndex - 1);
681 return UserChain[ChainIndex] = NewBO;
684 Value *ConstantOffsetExtractor::removeConstOffset(
unsigned ChainIndex) {
685 if (ChainIndex == 0) {
686 assert(isa<ConstantInt>(UserChain[ChainIndex]));
692 "distributeExtsAndCloneChain clones each BinaryOperator in " 693 "UserChain, so no one should be used more than " 696 unsigned OpNo = (BO->
getOperand(0) == UserChain[ChainIndex - 1] ? 0 : 1);
698 Value *NextInChain = removeConstOffset(ChainIndex - 1);
703 if (
ConstantInt *CI = dyn_cast<ConstantInt>(NextInChain)) {
704 if (CI->isZero() && !(BO->
getOpcode() == Instruction::Sub && OpNo == 0))
709 if (BO->
getOpcode() == Instruction::Or) {
737 User *&UserChainTail,
739 ConstantOffsetExtractor Extractor(GEP, DT);
741 APInt ConstantOffset =
742 Extractor.find(Idx,
false,
false,
744 if (ConstantOffset == 0) {
745 UserChainTail =
nullptr;
749 Value *IdxWithoutConstOffset = Extractor.rebuildWithoutConstOffset();
750 UserChainTail = Extractor.UserChain.back();
751 return IdxWithoutConstOffset;
757 return ConstantOffsetExtractor(GEP, DT)
758 .find(Idx,
false,
false,
763 bool SeparateConstOffsetFromGEP::canonicalizeArrayIndicesToPointerSize(
765 bool Changed =
false;
766 Type *IntPtrTy = DL->getIntPtrType(GEP->
getType());
769 I !=
E; ++
I, ++GTI) {
772 if ((*I)->getType() != IntPtrTy) {
783 bool &NeedsExtraction) {
784 NeedsExtraction =
false;
785 int64_t AccumulativeByteOffset = 0;
790 int64_t ConstantOffset =
792 if (ConstantOffset != 0) {
793 NeedsExtraction =
true;
797 AccumulativeByteOffset +=
800 }
else if (LowerGEP) {
805 NeedsExtraction =
true;
806 AccumulativeByteOffset +=
807 DL->getStructLayout(StTy)->getElementOffset(Field);
811 return AccumulativeByteOffset;
814 void SeparateConstOffsetFromGEP::lowerToSingleIndexGEPs(
817 Type *IntPtrTy = DL->getIntPtrType(Variadic->
getType());
824 bool isSwapCandidate =
826 !hasMoreThanOneUseInLoop(ResultPtr, L);
827 Value *FirstResult =
nullptr;
829 if (ResultPtr->
getType() != I8PtrTy)
846 if (ElementSize != 1) {
857 if (FirstResult ==
nullptr)
858 FirstResult = ResultPtr;
863 if (AccumulativeByteOffset != 0) {
868 isSwapCandidate =
false;
875 if (isSwapCandidate && isLegalToSwapOperand(FirstGEP, SecondGEP, L))
876 swapGEPOperand(FirstGEP, SecondGEP);
887 int64_t AccumulativeByteOffset) {
889 Type *IntPtrTy = DL->getIntPtrType(Variadic->
getType());
907 if (ElementSize != 1) {
916 ResultPtr = Builder.
CreateAdd(ResultPtr, Idx);
921 if (AccumulativeByteOffset != 0) {
941 bool Changed = canonicalizeArrayIndicesToPointerSize(GEP);
943 bool NeedsExtraction;
944 int64_t AccumulativeByteOffset = accumulateByteOffset(GEP, NeedsExtraction);
946 if (!NeedsExtraction)
950 getAnalysis<TargetTransformInfoWrapperPass>().getTTI(*GEP->
getFunction());
962 nullptr, AccumulativeByteOffset,
984 ConstantOffsetExtractor::Extract(OldIdx, GEP, UserChainTail, DT);
985 if (NewIdx !=
nullptr) {
1023 lowerToSingleIndexGEPs(GEP, AccumulativeByteOffset);
1025 lowerToArithmetics(GEP, AccumulativeByteOffset);
1030 if (AccumulativeByteOffset == 0)
1067 int64_t ElementTypeSizeOfGEP =
static_cast<int64_t
>(
1069 Type *IntPtrTy = DL->getIntPtrType(GEP->
getType());
1070 if (AccumulativeByteOffset % ElementTypeSizeOfGEP == 0) {
1073 int64_t
Index = AccumulativeByteOffset / ElementTypeSizeOfGEP;
1079 cast<GetElementPtrInst>(NewGEP)->setIsInBounds(GEPWasInBounds);
1097 NewGEP =
new BitCastInst(NewGEP, I8PtrTy,
"", GEP);
1104 cast<GetElementPtrInst>(NewGEP)->setIsInBounds(GEPWasInBounds);
1105 if (GEP->
getType() != I8PtrTy)
1116 if (skipFunction(F))
1122 DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
1123 SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
1124 LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
1125 TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
1126 bool Changed =
false;
1130 Changed |= splitGEP(GEP);
1135 Changed |= reuniteExts(F);
1138 verifyNoDeadCode(F);
1143 Instruction *SeparateConstOffsetFromGEP::findClosestMatchingDominator(
1145 auto Pos = DominatingExprs.find(Key);
1146 if (Pos == DominatingExprs.end())
1149 auto &Candidates = Pos->second;
1154 while (!Candidates.empty()) {
1156 if (DT->
dominates(Candidate, Dominatee))
1158 Candidates.pop_back();
1163 bool SeparateConstOffsetFromGEP::reuniteExts(
Instruction *
I) {
1164 if (!SE->isSCEVable(I->
getType()))
1171 Value *LHS =
nullptr, *RHS =
nullptr;
1174 if (LHS->
getType() == RHS->getType()) {
1176 SE->getAddExpr(SE->getUnknown(LHS), SE->getUnknown(RHS));
1177 if (
auto *Dom = findClosestMatchingDominator(Key, I)) {
1192 SE->getAddExpr(SE->getUnknown(LHS), SE->getUnknown(RHS));
1193 DominatingExprs[
Key].push_back(I);
1199 bool SeparateConstOffsetFromGEP::reuniteExts(
Function &F) {
1200 bool Changed =
false;
1201 DominatingExprs.clear();
1204 for (
auto I = BB->
begin(); I != BB->
end(); ) {
1206 Changed |= reuniteExts(Cur);
1212 void SeparateConstOffsetFromGEP::verifyNoDeadCode(
Function &F) {
1216 std::string ErrMessage;
1218 RSO <<
"Dead instruction detected!\n" << I <<
"\n";
1225 bool SeparateConstOffsetFromGEP::isLegalToSwapOperand(
1227 if (!FirstGEP || !FirstGEP->
hasOneUse())
1233 if (FirstGEP == SecondGEP)
1239 if (FirstNum != SecondNum || FirstNum != 2)
1264 if (FirstOffsetDef && FirstOffsetDef->
isShift() &&
1265 isa<ConstantInt>(FirstOffsetDef->
getOperand(1)))
1271 if (
BinaryOperator *BO = dyn_cast<BinaryOperator>(FirstOffsetDef)) {
1281 bool SeparateConstOffsetFromGEP::hasMoreThanOneUseInLoop(
Value *V,
Loop *L) {
1286 if (++UsesInLoop > 1)
1302 cast<PointerType>(First->
getType())->getAddressSpace()),
1306 uint64_t ObjectSize;
1308 Offset.
ugt(ObjectSize)) {
static unsigned getBitWidth(Type *Ty, const DataLayout &DL)
Returns the bitwidth of the given scalar or pointer type.
bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout &DL, const TargetLibraryInfo *TLI, ObjectSizeOpts Opts={})
Compute the size of the object pointed by Ptr.
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
OverflowingBinaryOp_match< LHS, RHS, Instruction::Sub, OverflowingBinaryOperator::NoSignedWrap > m_NSWSub(const LHS &L, const RHS &R)
A parsed version of the target data layout string in and methods for querying it. ...
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
unsigned getIndexSizeInBits(unsigned AS) const
Size in bits of index used for address calculation in getelementptr.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
BinaryOp_match< LHS, RHS, Instruction::Sub > m_Sub(const LHS &L, const RHS &R)
This class represents lattice values for constants.
BinaryOps getOpcode() const
INITIALIZE_PASS_BEGIN(SeparateConstOffsetFromGEP, "separate-const-offset-from-gep", "Split GEPs to a variadic base and a constant offset for better CSE", false, false) INITIALIZE_PASS_END(SeparateConstOffsetFromGEP
A Module instance is used to store all the information related to an LLVM module. ...
The main scalar evolution driver.
static GetElementPtrInst * Create(Type *PointeeType, Value *Ptr, ArrayRef< Value *> IdxList, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
static cl::opt< bool > VerifyNoDeadCode("reassociate-geps-verify-no-dead-code", cl::init(false), cl::desc("Verify this pass produces no dead code"), cl::Hidden)
StructType * getStructType() const
LLVMContext & getContext() const
All values hold a context through their type.
This class represents a sign extension of integer types.
unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
bool isVectorTy() const
True if this is an instance of VectorType.
bool hasNoSignedWrap() const
Determine whether the no signed wrap flag is set.
static Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
iterator begin()
Instruction iterator methods.
bool match(Val *V, const Pattern &P)
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
This is the base class for all instructions that perform data casts.
Class to represent struct types.
A Use represents the edge between a Value definition and its users.
void setIsInBounds(bool b=true)
Set or clear the inbounds flag on this GEP instruction.
separate const offset from Split GEPs to a variadic base and a constant offset for better CSE
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
This file implements a class to represent arbitrary precision integral constant values and operations...
BinaryOp_match< LHS, RHS, Instruction::Add > m_Add(const LHS &L, const RHS &R)
bool programUndefinedIfFullPoison(const Instruction *PoisonI)
Return true if this function can prove that if PoisonI is executed and yields a full-poison value (al...
Value * CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name="")
Instruction * clone() const
Create a copy of 'this' instruction that is identical in all ways except the following: ...
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
Type * getType() const
All values are typed, get the type of this value.
bool isInBounds() const
Determine whether the GEP has the inbounds flag.
This class represents a no-op cast from one type to another.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
void takeName(Value *V)
Transfer the name from V to this value.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree...
void initializeSeparateConstOffsetFromGEPPass(PassRegistry &)
Value * getOperand(unsigned i) const
an instruction for type-safe pointer arithmetic to access elements of arrays and structs ...
static bool runOnFunction(Function &F, bool PostInlining)
initializer< Ty > init(const Ty &Val)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
void insertBefore(Instruction *InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified instruction...
LLVM Basic Block Representation.
The instances of the Type class are immutable: once they are created, they are never changed...
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This is an important base class in LLVM.
static const SubtargetFeatureKV * Find(StringRef S, ArrayRef< SubtargetFeatureKV > A)
Find KV in array using binary search.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
Represent the analysis usage information of a pass.
static cl::opt< bool > DisableSeparateConstOffsetFromGEP("disable-separate-const-offset-from-gep", cl::init(false), cl::desc("Do not separate the constant offset from a GEP instruction"), cl::Hidden)
FunctionPass class - This class is used to implement most global optimizations.
const Function * getFunction() const
Return the function this instruction belongs to.
bool RecursivelyDeleteTriviallyDeadInstructions(Value *V, const TargetLibraryInfo *TLI=nullptr, MemorySSAUpdater *MSSAU=nullptr)
If the specified value is a trivially dead instruction, delete it.
Type * getIndexedType() const
static wasm::ValType getType(const TargetRegisterClass *RC)
auto find(R &&Range, const T &Val) -> decltype(adl_begin(Range))
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly...
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
PointerType * getInt8PtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer to an 8-bit integer value.
std::string & str()
Flushes the stream contents to the target string and returns the string's reference.
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE, "Assign register bank of generic virtual registers", false, false) RegBankSelect
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Value * CreateMul(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
bool isLoopInvariant(const Value *V) const
Return true if the specified value is loop invariant.
CastClass_match< OpTy, Instruction::SExt > m_SExt(const OpTy &Op)
Matches SExt.
Value * CreateGEP(Value *Ptr, ArrayRef< Value *> IdxList, const Twine &Name="")
bool contains(const LoopT *L) const
Return true if the specified loop is contained within in this loop.
static CastInst * CreateIntegerCast(Value *S, Type *Ty, bool isSigned, const Twine &Name="", Instruction *InsertBefore=nullptr)
Create a ZExt, BitCast, or Trunc for int -> int casts.
Iterator for intrusive lists based on ilist_node.
unsigned getNumOperands() const
This is the shared class of boolean and integer constants.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
bool dominates(const Instruction *Def, const Use &U) const
Return true if Def dominates a use in User.
Module.h This file contains the declarations for the Module class.
Provides information about what library functions are available for the current target.
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:
OverflowingBinaryOp_match< LHS, RHS, Instruction::Add, OverflowingBinaryOperator::NoSignedWrap > m_NSWAdd(const LHS &L, const RHS &R)
void setOperand(unsigned i, Value *Val)
unsigned logBase2() const
const Value * stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL, APInt &Offset) const
Accumulate offsets from stripInBoundsConstantOffsets().
FunctionPass * createSeparateConstOffsetFromGEPPass(bool LowerGEP=false)
const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
Class for arbitrary precision integers.
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
static BinaryOperator * Create(BinaryOps Op, Value *S1, Value *S2, const Twine &Name=Twine(), Instruction *InsertBefore=nullptr)
Construct a binary instruction, given the opcode and the two operands.
iterator_range< user_iterator > users()
IntegerType * getInt8Ty()
Fetch the type representing an 8-bit integer.
static Constant * getCast(unsigned ops, Constant *C, Type *Ty, bool OnlyIfReduced=false)
Convenience function for getting a Cast operation.
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
bool isSequential() const
bool ugt(const APInt &RHS) const
Unsigned greather than comparison.
unsigned getNumUses() const
This method computes the number of uses of this Value.
This class represents an analyzed expression in the program.
unsigned getIntegerBitWidth() const
Represents a single loop in the control flow graph.
StringRef getName() const
Return a constant reference to the value's name.
bool haveNoCommonBitsSet(const Value *LHS, const Value *RHS, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true)
Return true if LHS and RHS have no common bits set.
Type * getResultElementType() const
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
bool hasNoUnsignedWrap() const
Determine whether the no unsigned wrap flag is set.
Value * CreatePtrToInt(Value *V, Type *DestTy, const Twine &Name="")
iterator_range< df_iterator< T > > depth_first(const T &G)
separate const offset from gep
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A raw_ostream that writes to an std::string.
bool isInstructionTriviallyDead(Instruction *I, const TargetLibraryInfo *TLI=nullptr)
Return true if the result produced by the instruction is not used, and the instruction has no side ef...
LLVM Value Representation.
void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
The legacy pass manager's analysis pass to compute loop information.
bool hasOneUse() const
Return true if there is exactly one user of this value.
Legacy analysis pass which computes a DominatorTree.
static void Split(std::vector< std::string > &V, StringRef S)
Splits a string of comma separated items in to a vector of strings.
for(unsigned i=Desc.getNumOperands(), e=OldMI.getNumOperands();i !=e;++i)
static IntegerType * getInt8Ty(LLVMContext &C)
bool hasAllConstantIndices() const
Return true if all of the indices of this GEP are constant integers.
const BasicBlock * getParent() const
gep_type_iterator gep_type_begin(const User *GEP)