From e2574d3215c412a15763d26aee9aa5d856764c2c Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 11 Aug 2009 17:57:01 +0000 Subject: [PATCH] Add convenience functions for creating inbounds GEPs. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78695 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Constants.h | 11 +++- include/llvm/Instructions.h | 38 ++++++++++++++ include/llvm/Support/ConstantFolder.h | 9 ++++ include/llvm/Support/IRBuilder.h | 74 +++++++++++++++++++++++++-- include/llvm/Support/NoFolder.h | 9 ++++ include/llvm/Support/TargetFolder.h | 9 ++++ lib/VMCore/Constants.cpp | 20 ++++++++ 7 files changed, 164 insertions(+), 6 deletions(-) diff --git a/include/llvm/Constants.h b/include/llvm/Constants.h index 3b674cda574..78b3ca83ea7 100644 --- a/include/llvm/Constants.h +++ b/include/llvm/Constants.h @@ -723,7 +723,16 @@ public: Constant* const *IdxList, unsigned NumIdx); static Constant *getGetElementPtr(Constant *C, Value* const *IdxList, unsigned NumIdx); - + + /// Create an "inbounds" getelementptr. See the documentation for the + /// "inbounds" flag in LangRef.html for details. + static Constant *getInBoundsGetElementPtr(Constant *C, + Constant* const *IdxList, + unsigned NumIdx); + static Constant *getInBoundsGetElementPtr(Constant *C, + Value* const *IdxList, + unsigned NumIdx); + static Constant *getExtractElement(Constant *Vec, Constant *Idx); static Constant *getInsertElement(Constant *Vec, Constant *Elt,Constant *Idx); static Constant *getShuffleVector(Constant *V1, Constant *V2, Constant *Mask); diff --git a/include/llvm/Instructions.h b/include/llvm/Instructions.h index ecfddf2cf9a..9bee045878b 100644 --- a/include/llvm/Instructions.h +++ b/include/llvm/Instructions.h @@ -493,6 +493,44 @@ public: return new(2) GetElementPtrInst(Ptr, Idx, NameStr, InsertAtEnd); } + /// Create an "inbounds" getelementptr. See the documentation for the + /// "inbounds" flag in LangRef.html for details. + template + static GetElementPtrInst *CreateInBounds(Value *Ptr, InputIterator IdxBegin, + InputIterator IdxEnd, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + GetElementPtrInst *GEP = Create(Ptr, IdxBegin, IdxEnd, + NameStr, InsertBefore); + cast(GEP)->setIsInBounds(true); + return GEP; + } + template + static GetElementPtrInst *CreateInBounds(Value *Ptr, + InputIterator IdxBegin, + InputIterator IdxEnd, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + GetElementPtrInst *GEP = Create(Ptr, IdxBegin, IdxEnd, + NameStr, InsertAtEnd); + cast(GEP)->setIsInBounds(true); + return GEP; + } + static GetElementPtrInst *CreateInBounds(Value *Ptr, Value *Idx, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + GetElementPtrInst *GEP = Create(Ptr, Idx, NameStr, InsertBefore); + cast(GEP)->setIsInBounds(true); + return GEP; + } + static GetElementPtrInst *CreateInBounds(Value *Ptr, Value *Idx, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + GetElementPtrInst *GEP = Create(Ptr, Idx, NameStr, InsertAtEnd); + cast(GEP)->setIsInBounds(true); + return GEP; + } + virtual GetElementPtrInst *clone(LLVMContext &Context) const; /// Transparently provide more efficient getOperand methods. diff --git a/include/llvm/Support/ConstantFolder.h b/include/llvm/Support/ConstantFolder.h index 422d1ad00d2..1b5b2b77459 100644 --- a/include/llvm/Support/ConstantFolder.h +++ b/include/llvm/Support/ConstantFolder.h @@ -122,6 +122,15 @@ public: return ConstantExpr::getGetElementPtr(C, IdxList, NumIdx); } + Constant *CreateInBoundsGetElementPtr(Constant *C, Constant* const *IdxList, + unsigned NumIdx) const { + return ConstantExpr::getInBoundsGetElementPtr(C, IdxList, NumIdx); + } + Constant *CreateInBoundsGetElementPtr(Constant *C, Value* const *IdxList, + unsigned NumIdx) const { + return ConstantExpr::getInBoundsGetElementPtr(C, IdxList, NumIdx); + } + //===--------------------------------------------------------------------===// // Cast/Conversion Operators //===--------------------------------------------------------------------===// diff --git a/include/llvm/Support/IRBuilder.h b/include/llvm/Support/IRBuilder.h index 33ceb69feb5..89dd2953daa 100644 --- a/include/llvm/Support/IRBuilder.h +++ b/include/llvm/Support/IRBuilder.h @@ -362,21 +362,43 @@ public: if (Constant *PC = dyn_cast(Ptr)) { // Every index must be constant. InputIterator i; - for (i = IdxBegin; i < IdxEnd; ++i) { + for (i = IdxBegin; i < IdxEnd; ++i) if (!isa(*i)) break; - } if (i == IdxEnd) return Folder.CreateGetElementPtr(PC, &IdxBegin[0], IdxEnd - IdxBegin); } return Insert(GetElementPtrInst::Create(Ptr, IdxBegin, IdxEnd), Name); } + template + Value *CreateInBoundsGEP(Value *Ptr, InputIterator IdxBegin, InputIterator IdxEnd, + const char *Name = "") { + if (Constant *PC = dyn_cast(Ptr)) { + // Every index must be constant. + InputIterator i; + for (i = IdxBegin; i < IdxEnd; ++i) + if (!isa(*i)) + break; + if (i == IdxEnd) + return Folder.CreateInBoundsGetElementPtr(PC, + &IdxBegin[0], + IdxEnd - IdxBegin); + } + return Insert(GetElementPtrInst::CreateInBounds(Ptr, IdxBegin, IdxEnd), + Name); + } Value *CreateGEP(Value *Ptr, Value *Idx, const char *Name = "") { if (Constant *PC = dyn_cast(Ptr)) if (Constant *IC = dyn_cast(Idx)) return Folder.CreateGetElementPtr(PC, &IC, 1); return Insert(GetElementPtrInst::Create(Ptr, Idx), Name); } + Value *CreateInBoundsGEP(Value *Ptr, Value *Idx, const char *Name = "") { + if (Constant *PC = dyn_cast(Ptr)) + if (Constant *IC = dyn_cast(Idx)) + return Folder.CreateInBoundsGetElementPtr(PC, &IC, 1); + return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idx), Name); + } Value *CreateConstGEP1_32(Value *Ptr, unsigned Idx0, const char *Name = "") { Value *Idx = ConstantInt::get(Type::Int32Ty, Idx0); @@ -385,6 +407,15 @@ public: return Insert(GetElementPtrInst::Create(Ptr, &Idx, &Idx+1), Name); } + Value *CreateConstInBoundsGEP1_32(Value *Ptr, unsigned Idx0, + const char *Name = "") { + Value *Idx = ConstantInt::get(Type::Int32Ty, Idx0); + + if (Constant *PC = dyn_cast(Ptr)) + return Folder.CreateInBoundsGetElementPtr(PC, &Idx, 1); + + return Insert(GetElementPtrInst::CreateInBounds(Ptr, &Idx, &Idx+1), Name); + } Value *CreateConstGEP2_32(Value *Ptr, unsigned Idx0, unsigned Idx1, const char *Name = "") { Value *Idxs[] = { @@ -397,6 +428,18 @@ public: return Insert(GetElementPtrInst::Create(Ptr, Idxs, Idxs+2), Name); } + Value *CreateConstInBoundsGEP2_32(Value *Ptr, unsigned Idx0, unsigned Idx1, + const char *Name = "") { + Value *Idxs[] = { + ConstantInt::get(Type::Int32Ty, Idx0), + ConstantInt::get(Type::Int32Ty, Idx1) + }; + + if (Constant *PC = dyn_cast(Ptr)) + return Folder.CreateInBoundsGetElementPtr(PC, Idxs, 2); + + return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idxs, Idxs+2), Name); + } Value *CreateConstGEP1_64(Value *Ptr, uint64_t Idx0, const char *Name = "") { Value *Idx = ConstantInt::get(Type::Int64Ty, Idx0); @@ -405,7 +448,16 @@ public: return Insert(GetElementPtrInst::Create(Ptr, &Idx, &Idx+1), Name); } - Value *CreateConstGEP2_64(Value *Ptr, uint64_t Idx0, uint64_t Idx1, + Value *CreateConstInBoundsGEP1_64(Value *Ptr, uint64_t Idx0, + const char *Name = "") { + Value *Idx = ConstantInt::get(Type::Int64Ty, Idx0); + + if (Constant *PC = dyn_cast(Ptr)) + return Folder.CreateInBoundsGetElementPtr(PC, &Idx, 1); + + return Insert(GetElementPtrInst::CreateInBounds(Ptr, &Idx, &Idx+1), Name); + } + Value *CreateConstGEP2_64(Value *Ptr, uint64_t Idx0, uint64_t Idx1, const char *Name = "") { Value *Idxs[] = { ConstantInt::get(Type::Int64Ty, Idx0), @@ -417,8 +469,20 @@ public: return Insert(GetElementPtrInst::Create(Ptr, Idxs, Idxs+2), Name); } + Value *CreateConstInBoundsGEP2_64(Value *Ptr, uint64_t Idx0, uint64_t Idx1, + const char *Name = "") { + Value *Idxs[] = { + ConstantInt::get(Type::Int64Ty, Idx0), + ConstantInt::get(Type::Int64Ty, Idx1) + }; + + if (Constant *PC = dyn_cast(Ptr)) + return Folder.CreateInBoundsGetElementPtr(PC, Idxs, 2); + + return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idxs, Idxs+2), Name); + } Value *CreateStructGEP(Value *Ptr, unsigned Idx, const char *Name = "") { - return CreateConstGEP2_32(Ptr, 0, Idx, Name); + return CreateConstInBoundsGEP2_32(Ptr, 0, Idx, Name); } Value *CreateGlobalString(const char *Str = "", const char *Name = "") { Constant *StrConstant = ConstantArray::get(Str, true); @@ -438,7 +502,7 @@ public: Value *gv = CreateGlobalString(Str, Name); Value *zero = ConstantInt::get(Type::Int32Ty, 0); Value *Args[] = { zero, zero }; - return CreateGEP(gv, Args, Args+2, Name); + return CreateInBoundsGEP(gv, Args, Args+2, Name); } //===--------------------------------------------------------------------===// // Instruction creation methods: Cast/Conversion Operators diff --git a/include/llvm/Support/NoFolder.h b/include/llvm/Support/NoFolder.h index b89c084b586..5333b87efd1 100644 --- a/include/llvm/Support/NoFolder.h +++ b/include/llvm/Support/NoFolder.h @@ -126,6 +126,15 @@ public: return GetElementPtrInst::Create(C, IdxList, IdxList+NumIdx); } + Constant *CreateInBoundsGetElementPtr(Constant *C, Constant* const *IdxList, + unsigned NumIdx) const { + return ConstantExpr::getInBoundsGetElementPtr(C, IdxList, NumIdx); + } + Value *CreateInBoundsGetElementPtr(Constant *C, Value* const *IdxList, + unsigned NumIdx) const { + return GetElementPtrInst::CreateInBounds(C, IdxList, IdxList+NumIdx); + } + //===--------------------------------------------------------------------===// // Cast/Conversion Operators //===--------------------------------------------------------------------===// diff --git a/include/llvm/Support/TargetFolder.h b/include/llvm/Support/TargetFolder.h index 473b0ab03c9..2569cb90197 100644 --- a/include/llvm/Support/TargetFolder.h +++ b/include/llvm/Support/TargetFolder.h @@ -138,6 +138,15 @@ public: return Fold(ConstantExpr::getGetElementPtr(C, IdxList, NumIdx)); } + Constant *CreateInBoundsGetElementPtr(Constant *C, Constant* const *IdxList, + unsigned NumIdx) const { + return Fold(ConstantExpr::getInBoundsGetElementPtr(C, IdxList, NumIdx)); + } + Constant *CreateInBoundsGetElementPtr(Constant *C, Value* const *IdxList, + unsigned NumIdx) const { + return Fold(ConstantExpr::getInBoundsGetElementPtr(C, IdxList, NumIdx)); + } + //===--------------------------------------------------------------------===// // Cast/Conversion Operators //===--------------------------------------------------------------------===// diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp index 2670965f734..89578fb8972 100644 --- a/lib/VMCore/Constants.cpp +++ b/lib/VMCore/Constants.cpp @@ -1363,6 +1363,7 @@ Constant* ConstantExpr::getSizeOf(const Type* Ty) { Constant* ConstantExpr::getAlignOf(const Type* Ty) { // alignof is implemented as: (i64) gep ({i8,Ty}*)null, 0, 1 + // Note that a non-inbounds gep is used, as null isn't within any object. const Type *AligningTy = StructType::get(Ty->getContext(), Type::Int8Ty, Ty, NULL); Constant *NullPtr = Constant::getNullValue(AligningTy->getPointerTo()); @@ -1438,11 +1439,30 @@ Constant *ConstantExpr::getGetElementPtr(Constant *C, Value* const *Idxs, return getGetElementPtrTy(PointerType::get(Ty, As), C, Idxs, NumIdx); } +Constant *ConstantExpr::getInBoundsGetElementPtr(Constant *C, + Value* const *Idxs, + unsigned NumIdx) { + // Get the result type of the getelementptr! + const Type *Ty = + GetElementPtrInst::getIndexedType(C->getType(), Idxs, Idxs+NumIdx); + assert(Ty && "GEP indices invalid!"); + unsigned As = cast(C->getType())->getAddressSpace(); + Constant *Result = getGetElementPtrTy(PointerType::get(Ty, As), C, + Idxs, NumIdx); + cast(Result)->setIsInBounds(true); + return Result; +} + Constant *ConstantExpr::getGetElementPtr(Constant *C, Constant* const *Idxs, unsigned NumIdx) { return getGetElementPtr(C, (Value* const *)Idxs, NumIdx); } +Constant *ConstantExpr::getInBoundsGetElementPtr(Constant *C, + Constant* const *Idxs, + unsigned NumIdx) { + return getInBoundsGetElementPtr(C, (Value* const *)Idxs, NumIdx); +} Constant * ConstantExpr::getICmp(unsigned short pred, Constant* LHS, Constant* RHS) {