llvm.org GIT mirror llvm / ca668e1
IR: Introduce inrange attribute on getelementptr indices. If the inrange keyword is present before any index, loading from or storing to any pointer derived from the getelementptr has undefined behavior if the load or store would access memory outside of the bounds of the element selected by the index marked as inrange. This can be used, e.g. for alias analysis or to split globals at element boundaries where beneficial. As previously proposed on llvm-dev: http://lists.llvm.org/pipermail/llvm-dev/2016-July/102472.html Differential Revision: https://reviews.llvm.org/D22793 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@286514 91177308-0d34-0410-b5e6-96231b3b80d8 Peter Collingbourne 3 years ago
18 changed file(s) with 219 addition(s) and 65 deletion(s). Raw diff Collapse all Expand all
74497449
74507450 ::
74517451
7452 = getelementptr , * {, }*
7453 = getelementptr inbounds , * {, }*
7454 = getelementptr , <ptr vector> ,
7452 = getelementptr , <ty>* {, [inrange] }*
7453 = getelementptr inbounds , * {, [inrange] }*
7454 = getelementptr , , [inrange]
74557455
74567456 Overview:
74577457 """""""""
75677567 though, even if it happens to point into allocated storage. See the
75687568 :ref:`Pointer Aliasing Rules ` section for more
75697569 information.
7570
7571 If the ``inrange`` keyword is present before any index, loading from or
7572 storing to any pointer derived from the ``getelementptr`` has undefined
7573 behavior if the load or store would access memory outside of the bounds of
7574 the element selected by the index marked as ``inrange``. The result of a
7575 pointer comparison or ``ptrtoint`` (including ``ptrtoint``-like operations
7576 involving memory) involving a pointer derived from a ``getelementptr`` with
7577 the ``inrange`` keyword is undefined, with the exception of comparisons
7578 in the case where both operands are in the range of the element selected
7579 by the ``inrange`` keyword, inclusive of the address one past the end of
7580 that element. Note that the ``inrange`` keyword is currently only allowed
7581 in constant ``getelementptr`` expressions.
75707582
75717583 The getelementptr instruction is often confusing. For some more insight
75727584 into how it works, see :doc:`the getelementptr FAQ `.
279279 CST_CODE_CE_INBOUNDS_GEP = 20, // INBOUNDS_GEP: [n x operands]
280280 CST_CODE_BLOCKADDRESS = 21, // CST_CODE_BLOCKADDRESS [fnty, fnval, bb#]
281281 CST_CODE_DATA = 22, // DATA: [n x elements]
282 CST_CODE_INLINEASM = 23 // INLINEASM: [sideeffect|alignstack|
282 CST_CODE_INLINEASM = 23, // INLINEASM: [sideeffect|alignstack|
283283 // asmdialect,asmstr,conststr]
284 CST_CODE_CE_GEP_WITH_INRANGE_INDEX = 24, // [opty, flags, n x operands]
284285 };
285286
286287 /// CastOpcodes - These are values used in the bitcode files to encode which
2323 #include "llvm/ADT/APFloat.h"
2424 #include "llvm/ADT/APInt.h"
2525 #include "llvm/ADT/ArrayRef.h"
26 #include "llvm/ADT/Optional.h"
2627 #include "llvm/IR/Constant.h"
2728 #include "llvm/IR/DerivedTypes.h"
2829 #include "llvm/IR/OperandTraits.h"
10701071 /// Getelementptr form. Value* is only accepted for convenience;
10711072 /// all elements must be Constants.
10721073 ///
1074 /// \param InRangeIndex the inrange index if present or None.
10731075 /// \param OnlyIfReducedTy see \a getWithOperands() docs.
10741076 static Constant *getGetElementPtr(Type *Ty, Constant *C,
10751077 ArrayRef IdxList,
10761078 bool InBounds = false,
1079 Optional InRangeIndex = None,
10771080 Type *OnlyIfReducedTy = nullptr) {
10781081 return getGetElementPtr(
10791082 Ty, C, makeArrayRef((Value * const *)IdxList.data(), IdxList.size()),
1080 InBounds, OnlyIfReducedTy);
1083 InBounds, InRangeIndex, OnlyIfReducedTy);
10811084 }
10821085 static Constant *getGetElementPtr(Type *Ty, Constant *C, Constant *Idx,
10831086 bool InBounds = false,
1087 Optional InRangeIndex = None,
10841088 Type *OnlyIfReducedTy = nullptr) {
10851089 // This form of the function only exists to avoid ambiguous overload
10861090 // warnings about whether to convert Idx to ArrayRef or
10871091 // ArrayRef.
1088 return getGetElementPtr(Ty, C, cast(Idx), InBounds, OnlyIfReducedTy);
1092 return getGetElementPtr(Ty, C, cast(Idx), InBounds, InRangeIndex,
1093 OnlyIfReducedTy);
10891094 }
10901095 static Constant *getGetElementPtr(Type *Ty, Constant *C,
10911096 ArrayRef IdxList,
10921097 bool InBounds = false,
1098 Optional InRangeIndex = None,
10931099 Type *OnlyIfReducedTy = nullptr);
10941100
10951101 /// Create an "inbounds" getelementptr. See the documentation for the
363363 class GEPOperator
364364 : public ConcreteOperator {
365365 enum {
366 IsInBounds = (1 << 0)
366 IsInBounds = (1 << 0),
367 // InRangeIndex: bits 1-6
367368 };
368369
369370 friend class GetElementPtrInst;
377378 /// Test whether this is an inbounds GEP, as defined by LangRef.html.
378379 bool isInBounds() const {
379380 return SubclassOptionalData & IsInBounds;
381 }
382 /// Returns the offset of the index with an inrange attachment, or None if
383 /// none.
384 Optional getInRangeIndex() const {
385 if (SubclassOptionalData >> 1 == 0) return None;
386 return (SubclassOptionalData >> 1) - 1;
380387 }
381388
382389 inline op_iterator idx_begin() { return op_begin()+1; }
717717 /// If array indices are not pointer-sized integers, explicitly cast them so
718718 /// that they aren't implicitly casted by the getelementptr.
719719 Constant *CastGEPIndices(Type *SrcElemTy, ArrayRef Ops,
720 Type *ResultTy, const DataLayout &DL,
721 const TargetLibraryInfo *TLI) {
720 Type *ResultTy, Optional InRangeIndex,
721 const DataLayout &DL, const TargetLibraryInfo *TLI) {
722722 Type *IntPtrTy = DL.getIntPtrType(ResultTy);
723723
724724 bool Any = false;
741741 if (!Any)
742742 return nullptr;
743743
744 Constant *C = ConstantExpr::getGetElementPtr(SrcElemTy, Ops[0], NewIdxs);
744 Constant *C = ConstantExpr::getGetElementPtr(
745 SrcElemTy, Ops[0], NewIdxs, /*InBounds=*/false, InRangeIndex);
745746 if (Constant *Folded = ConstantFoldConstant(C, DL, TLI))
746747 C = Folded;
747748
770771 ArrayRef Ops,
771772 const DataLayout &DL,
772773 const TargetLibraryInfo *TLI) {
774 const GEPOperator *InnermostGEP = GEP;
775
773776 Type *SrcElemTy = GEP->getSourceElementType();
774777 Type *ResElemTy = GEP->getResultElementType();
775778 Type *ResTy = GEP->getType();
776779 if (!SrcElemTy->isSized())
777780 return nullptr;
778781
779 if (Constant *C = CastGEPIndices(SrcElemTy, Ops, ResTy, DL, TLI))
782 if (Constant *C = CastGEPIndices(SrcElemTy, Ops, ResTy,
783 GEP->getInRangeIndex(), DL, TLI))
780784 return C;
781785
782786 Constant *Ptr = Ops[0];
819823
820824 // If this is a GEP of a GEP, fold it all into a single GEP.
821825 while (auto *GEP = dyn_cast(Ptr)) {
826 InnermostGEP = GEP;
827
822828 SmallVector NestedOps(GEP->op_begin() + 1, GEP->op_end());
823829
824830 // Do not try the incorporate the sub-GEP if some index is not a number.
924930 if (Offset != 0)
925931 return nullptr;
926932
933 // Preserve the inrange index from the innermost GEP if possible. We must
934 // have calculated the same indices up to and including the inrange index.
935 Optional InRangeIndex;
936 if (Optional LastIRIndex = InnermostGEP->getInRangeIndex())
937 if (SrcElemTy == InnermostGEP->getSourceElementType() &&
938 NewIdxs.size() > *LastIRIndex) {
939 InRangeIndex = LastIRIndex;
940 for (unsigned I = 0; I <= *LastIRIndex; ++I)
941 if (NewIdxs[I] != InnermostGEP->getOperand(I + 1)) {
942 InRangeIndex = None;
943 break;
944 }
945 }
946
927947 // Create a GEP.
928 Constant *C = ConstantExpr::getGetElementPtr(SrcElemTy, Ptr, NewIdxs);
948 Constant *C = ConstantExpr::getGetElementPtr(
949 SrcElemTy, Ptr, NewIdxs, /*InBounds=*/false, InRangeIndex);
929950 assert(C->getType()->getPointerElementType() == Ty &&
930951 "Computed GetElementPtr has unexpected type!");
931952
943964 /// attempting to fold instructions like loads and stores, which have no
944965 /// constant expression form.
945966 ///
946 /// TODO: This function neither utilizes nor preserves nsw/nuw/inbounds/etc
947 /// information, due to only being passed an opcode and operands. Constant
967 /// TODO: This function neither utilizes nor preserves nsw/nuw/inbounds/inrange
968 /// etc information, due to only being passed an opcode and operands. Constant
948969 /// folding using this function strips this information.
949970 ///
950971 Constant *ConstantFoldInstOperandsImpl(const Value *InstOrCE, unsigned Opcode,
964985 if (Constant *C = SymbolicallyEvaluateGEP(GEP, Ops, DL, TLI))
965986 return C;
966987
967 return ConstantExpr::getGetElementPtr(GEP->getSourceElementType(),
968 Ops[0], Ops.slice(1));
988 return ConstantExpr::getGetElementPtr(GEP->getSourceElementType(), Ops[0],
989 Ops.slice(1), GEP->isInBounds(),
990 GEP->getInRangeIndex());
969991 }
970992
971993 if (auto *CE = dyn_cast(InstOrCE))
550550 KEYWORD(nsw);
551551 KEYWORD(exact);
552552 KEYWORD(inbounds);
553 KEYWORD(inrange);
553554 KEYWORD(align);
554555 KEYWORD(addrspace);
555556 KEYWORD(section);
31743174 return true;
31753175 }
31763176
3177 if (ParseGlobalValueVector(Elts) ||
3177 Optional InRangeOp;
3178 if (ParseGlobalValueVector(
3179 Elts, Opc == Instruction::GetElementPtr ? &InRangeOp : nullptr) ||
31783180 ParseToken(lltok::rparen, "expected ')' in constantexpr"))
31793181 return true;
31803182
32133215
32143216 if (!GetElementPtrInst::getIndexedType(Ty, Indices))
32153217 return Error(ID.Loc, "invalid getelementptr indices");
3216 ID.ConstantVal =
3217 ConstantExpr::getGetElementPtr(Ty, Elts[0], Indices, InBounds);
3218
3219 if (InRangeOp) {
3220 if (*InRangeOp == 0)
3221 return Error(ID.Loc,
3222 "inrange keyword may not appear on pointer operand");
3223 --*InRangeOp;
3224 }
3225
3226 ID.ConstantVal = ConstantExpr::getGetElementPtr(Ty, Elts[0], Indices,
3227 InBounds, InRangeOp);
32183228 } else if (Opc == Instruction::Select) {
32193229 if (Elts.size() != 3)
32203230 return Error(ID.Loc, "expected three operands to select");
32973307
32983308 /// ParseGlobalValueVector
32993309 /// ::= /*empty*/
3300 /// ::= TypeAndValue (',' TypeAndValue)*
3301 bool LLParser::ParseGlobalValueVector(SmallVectorImpl &Elts) {
3310 /// ::= [inrange] TypeAndValue (',' [inrange] TypeAndValue)*
3311 bool LLParser::ParseGlobalValueVector(SmallVectorImpl &Elts,
3312 Optional *InRangeOp) {
33023313 // Empty list.
33033314 if (Lex.getKind() == lltok::rbrace ||
33043315 Lex.getKind() == lltok::rsquare ||
33063317 Lex.getKind() == lltok::rparen)
33073318 return false;
33083319
3309 Constant *C;
3310 if (ParseGlobalTypeAndValue(C)) return true;
3311 Elts.push_back(C);
3312
3313 while (EatIfPresent(lltok::comma)) {
3320 do {
3321 if (InRangeOp && !*InRangeOp && EatIfPresent(lltok::kw_inrange))
3322 *InRangeOp = Elts.size();
3323
3324 Constant *C;
33143325 if (ParseGlobalTypeAndValue(C)) return true;
33153326 Elts.push_back(C);
3316 }
3327 } while (EatIfPresent(lltok::comma));
33173328
33183329 return false;
33193330 }
410410 bool ParseValID(ValID &ID, PerFunctionState *PFS = nullptr);
411411 bool ParseGlobalValue(Type *Ty, Constant *&V);
412412 bool ParseGlobalTypeAndValue(Constant *&V);
413 bool ParseGlobalValueVector(SmallVectorImpl &Elts);
413 bool ParseGlobalValueVector(SmallVectorImpl &Elts,
414 Optional *InRangeOp = nullptr);
414415 bool parseOptionalComdat(StringRef GlobalName, Comdat *&C);
415416 bool ParseMetadataAsValue(Value *&V, PerFunctionState &PFS);
416417 bool ParseValueAsMetadata(Metadata *&MD, const Twine &TypeMsg,
102102 kw_nsw,
103103 kw_exact,
104104 kw_inbounds,
105 kw_inrange,
105106 kw_align,
106107 kw_addrspace,
107108 kw_section,
32673267 }
32683268 break;
32693269 }
3270 case bitc::CST_CODE_CE_INBOUNDS_GEP:
3271 case bitc::CST_CODE_CE_GEP: { // CE_GEP: [n x operands]
3270 case bitc::CST_CODE_CE_INBOUNDS_GEP: // [ty, n x operands]
3271 case bitc::CST_CODE_CE_GEP: // [ty, n x operands]
3272 case bitc::CST_CODE_CE_GEP_WITH_INRANGE_INDEX: { // [ty, flags, n x
3273 // operands]
32723274 unsigned OpNum = 0;
32733275 Type *PointeeType = nullptr;
3274 if (Record.size() % 2)
3276 if (BitCode == bitc::CST_CODE_CE_GEP_WITH_INRANGE_INDEX ||
3277 Record.size() % 2)
32753278 PointeeType = getTypeByID(Record[OpNum++]);
3279
3280 bool InBounds = false;
3281 Optional InRangeIndex;
3282 if (BitCode == bitc::CST_CODE_CE_GEP_WITH_INRANGE_INDEX) {
3283 uint64_t Op = Record[OpNum++];
3284 InBounds = Op & 1;
3285 InRangeIndex = Op >> 1;
3286 } else if (BitCode == bitc::CST_CODE_CE_INBOUNDS_GEP)
3287 InBounds = true;
3288
32763289 SmallVector Elts;
32773290 while (OpNum != Record.size()) {
32783291 Type *ElTy = getTypeByID(Record[OpNum++]);
32933306
32943307 ArrayRef Indices(Elts.begin() + 1, Elts.end());
32953308 V = ConstantExpr::getGetElementPtr(PointeeType, Elts[0], Indices,
3296 BitCode ==
3297 bitc::CST_CODE_CE_INBOUNDS_GEP);
3309 InBounds, InRangeIndex);
32983310 break;
32993311 }
33003312 case bitc::CST_CODE_CE_SELECT: { // CE_SELECT: [opval#, opval#, opval#]
22162216 case Instruction::GetElementPtr: {
22172217 Code = bitc::CST_CODE_CE_GEP;
22182218 const auto *GO = cast(C);
2219 if (GO->isInBounds())
2219 Record.push_back(VE.getTypeID(GO->getSourceElementType()));
2220 if (Optional Idx = GO->getInRangeIndex()) {
2221 Code = bitc::CST_CODE_CE_GEP_WITH_INRANGE_INDEX;
2222 Record.push_back((*Idx << 1) | GO->isInBounds());
2223 } else if (GO->isInBounds())
22202224 Code = bitc::CST_CODE_CE_INBOUNDS_GEP;
2221 Record.push_back(VE.getTypeID(GO->getSourceElementType()));
22222225 for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i) {
22232226 Record.push_back(VE.getTypeID(C->getOperand(i)->getType()));
22242227 Record.push_back(VE.getValueID(C->getOperand(i)));
13191319 static_cast(CE->getPredicate()));
13201320 Out << " (";
13211321
1322 Optional InRangeOp;
13221323 if (const GEPOperator *GEP = dyn_cast(CE)) {
13231324 TypePrinter.print(GEP->getSourceElementType(), Out);
13241325 Out << ", ";
1326 InRangeOp = GEP->getInRangeIndex();
1327 if (InRangeOp)
1328 ++*InRangeOp;
13251329 }
13261330
13271331 for (User::const_op_iterator OI=CE->op_begin(); OI != CE->op_end(); ++OI) {
1332 if (InRangeOp && (OI - CE->op_begin()) == *InRangeOp)
1333 Out << "inrange ";
13281334 TypePrinter.print((*OI)->getType(), Out);
13291335 Out << ' ';
13301336 WriteAsOperandInternal(Out, *OI, &TypePrinter, Machine, Context);
544544 } else if (CE->getOpcode() == Instruction::GetElementPtr &&
545545 // Do not fold addrspacecast (gep 0, .., 0). It might make the
546546 // addrspacecast uncanonicalized.
547 opc != Instruction::AddrSpaceCast) {
547 opc != Instruction::AddrSpaceCast &&
548 // Do not fold bitcast (gep) with inrange index, as this loses
549 // information.
550 !cast(CE)->getInRangeIndex().hasValue()) {
548551 // If all of the indexes in the GEP are null values, there is no pointer
549552 // adjustment going on. We might as well cast the source pointer.
550553 bool isAllNull = true;
20452048 return true;
20462049 }
20472050
2048 template
2049 static Constant *ConstantFoldGetElementPtrImpl(Type *PointeeTy, Constant *C,
2050 bool inBounds,
2051 ArrayRef Idxs) {
2051 Constant *llvm::ConstantFoldGetElementPtr(Type *PointeeTy, Constant *C,
2052 bool InBounds,
2053 Optional InRangeIndex,
2054 ArrayRef Idxs) {
20522055 if (Idxs.empty()) return C;
20532056 Constant *Idx0 = cast(Idxs[0]);
20542057 if ((Idxs.size() == 1 && Idx0->isNullValue()))
21452148
21462149 NewIndices.push_back(Combined);
21472150 NewIndices.append(Idxs.begin() + 1, Idxs.end());
2151
2152 // The combined GEP normally inherits its index inrange attribute from
2153 // the inner GEP, but if the inner GEP's last index was adjusted by the
2154 // outer GEP, any inbounds attribute on that index is invalidated.
2155 Optional IRIndex = cast(CE)->getInRangeIndex();
2156 if (IRIndex && *IRIndex == CE->getNumOperands() - 2 && !Idx0->isNullValue())
2157 IRIndex = None;
2158
21482159 return ConstantExpr::getGetElementPtr(
21492160 cast(CE)->getSourceElementType(), CE->getOperand(0),
2150 NewIndices, inBounds && cast(CE)->isInBounds());
2161 NewIndices, InBounds && cast(CE)->isInBounds(),
2162 IRIndex);
21512163 }
21522164 }
21532165
21722184 if (SrcArrayTy && DstArrayTy
21732185 && SrcArrayTy->getElementType() == DstArrayTy->getElementType()
21742186 && SrcPtrTy->getAddressSpace() == DstPtrTy->getAddressSpace())
2175 return ConstantExpr::getGetElementPtr(
2176 SrcArrayTy, (Constant *)CE->getOperand(0), Idxs, inBounds);
2187 return ConstantExpr::getGetElementPtr(SrcArrayTy,
2188 (Constant *)CE->getOperand(0),
2189 Idxs, InBounds, InRangeIndex);
21772190 }
21782191 }
21792192 }
21932206 Unknown = true;
21942207 continue;
21952208 }
2209 if (InRangeIndex && i == *InRangeIndex + 1) {
2210 // If an index is marked inrange, we cannot apply this canonicalization to
2211 // the following index, as that will cause the inrange index to point to
2212 // the wrong element.
2213 continue;
2214 }
21962215 if (isa(Ty)) {
21972216 // The verify makes sure that GEPs into a struct are in range.
21982217 continue;
22552274 if (!NewIdxs.empty()) {
22562275 for (unsigned i = 0, e = Idxs.size(); i != e; ++i)
22572276 if (!NewIdxs[i]) NewIdxs[i] = cast(Idxs[i]);
2258 return ConstantExpr::getGetElementPtr(PointeeTy, C, NewIdxs, inBounds);
2277 return ConstantExpr::getGetElementPtr(PointeeTy, C, NewIdxs, InBounds,
2278 InRangeIndex);
22592279 }
22602280
22612281 // If all indices are known integers and normalized, we can do a simple
22622282 // check for the "inbounds" property.
2263 if (!Unknown && !inBounds)
2283 if (!Unknown && !InBounds)
22642284 if (auto *GV = dyn_cast(C))
22652285 if (!GV->hasExternalWeakLinkage() && isInBoundsIndices(Idxs))
2266 return ConstantExpr::getInBoundsGetElementPtr(PointeeTy, C, Idxs);
2286 return ConstantExpr::getGetElementPtr(PointeeTy, C, Idxs,
2287 /*InBounds=*/true, InRangeIndex);
22672288
22682289 return nullptr;
22692290 }
2270
2271 Constant *llvm::ConstantFoldGetElementPtr(Type *Ty, Constant *C,
2272 bool inBounds,
2273 ArrayRef Idxs) {
2274 return ConstantFoldGetElementPtrImpl(Ty, C, inBounds, Idxs);
2275 }
2276
2277 Constant *llvm::ConstantFoldGetElementPtr(Type *Ty, Constant *C,
2278 bool inBounds,
2279 ArrayRef Idxs) {
2280 return ConstantFoldGetElementPtrImpl(Ty, C, inBounds, Idxs);
2281 }
1717
1818 #ifndef LLVM_LIB_IR_CONSTANTFOLD_H
1919 #define LLVM_LIB_IR_CONSTANTFOLD_H
20
21 #include "llvm/ADT/Optional.h"
2022
2123 namespace llvm {
2224 template class ArrayRef;
4547 Constant *V2);
4648 Constant *ConstantFoldCompareInstruction(unsigned short predicate,
4749 Constant *C1, Constant *C2);
48 Constant *ConstantFoldGetElementPtr(Type *Ty, Constant *C, bool inBounds,
49 ArrayRef Idxs);
50 Constant *ConstantFoldGetElementPtr(Type *Ty, Constant *C, bool inBounds,
50 Constant *ConstantFoldGetElementPtr(Type *Ty, Constant *C, bool InBounds,
51 Optional InRangeIndex,
5152 ArrayRef Idxs);
5253 } // End llvm namespace
5354
11661166 assert(SrcTy || (Ops[0]->getType() == getOperand(0)->getType()));
11671167 return ConstantExpr::getGetElementPtr(
11681168 SrcTy ? SrcTy : GEPO->getSourceElementType(), Ops[0], Ops.slice(1),
1169 GEPO->isInBounds(), OnlyIfReducedTy);
1169 GEPO->isInBounds(), GEPO->getInRangeIndex(), OnlyIfReducedTy);
11701170 }
11711171 case Instruction::ICmp:
11721172 case Instruction::FCmp:
18921892
18931893 Constant *ConstantExpr::getGetElementPtr(Type *Ty, Constant *C,
18941894 ArrayRef Idxs, bool InBounds,
1895 Optional InRangeIndex,
18951896 Type *OnlyIfReducedTy) {
18961897 if (!Ty)
18971898 Ty = cast(C->getType()->getScalarType())->getElementType();
19001901 Ty ==
19011902 cast(C->getType()->getScalarType())->getContainedType(0u));
19021903
1903 if (Constant *FC = ConstantFoldGetElementPtr(Ty, C, InBounds, Idxs))
1904 if (Constant *FC =
1905 ConstantFoldGetElementPtr(Ty, C, InBounds, InRangeIndex, Idxs))
19041906 return FC; // Fold a few common cases.
19051907
19061908 // Get the result type of the getelementptr!
19361938 Idx = ConstantVector::getSplat(NumVecElts, Idx);
19371939 ArgVec.push_back(Idx);
19381940 }
1941
1942 unsigned SubClassOptionalData = InBounds ? GEPOperator::IsInBounds : 0;
1943 if (InRangeIndex && *InRangeIndex < 63)
1944 SubClassOptionalData |= (*InRangeIndex + 1) << 1;
19391945 const ConstantExprKeyType Key(Instruction::GetElementPtr, ArgVec, 0,
1940 InBounds ? GEPOperator::IsInBounds : 0, None,
1941 Ty);
1946 SubClassOptionalData, None, Ty);
19421947
19431948 LLVMContextImpl *pImpl = C->getContext().pImpl;
19441949 return pImpl->ExprConstants.getOrCreate(ReqTy, Key);
0 ; RUN: opt -instcombine -S -o - %s | FileCheck %s
1 ; Tests that we preserve the inrange attribute on indices where possible.
2
3 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
4 target triple = "x86_64-unknown-linux-gnu"
5
6 %struct.A = type { i32 (...)** }
7
8 @vt = external global [3 x i8*]
9
10 ; CHECK: define i32 (...)* @f0()
11 define i32 (...)* @f0() {
12 ; CHECK-NEXT: load i32 (...)*, i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @vt, inrange i64 0, i64 2) to i32 (...)**)
13 %load = load i32 (...)*, i32 (...)** getelementptr (i32 (...)*, i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @vt, inrange i64 0, i64 1) to i32 (...)**), i64 1)
14 ret i32 (...)* %load
15 }
16
17 ; CHECK: define i32 (...)* @f1()
18 define i32 (...)* @f1() {
19 ; CHECK-NEXT: load i32 (...)*, i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @vt, i64 0, i64 2) to i32 (...)**)
20 %load = load i32 (...)*, i32 (...)** getelementptr (i32 (...)*, i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @vt, i64 0, inrange i64 1) to i32 (...)**), i64 1)
21 ret i32 (...)* %load
22 }
23
24 ; CHECK: define i32 (...)* @f2()
25 define i32 (...)* @f2() {
26 ; CHECK-NEXT: load i32 (...)*, i32 (...)** bitcast (i8** getelementptr ([3 x i8*], [3 x i8*]* @vt, i64 1, i64 1) to i32 (...)**)
27 %load = load i32 (...)*, i32 (...)** getelementptr (i32 (...)*, i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @vt, i64 0, inrange i64 1) to i32 (...)**), i64 3)
28 ret i32 (...)* %load
29 }
2121 @PR23753_a = external global i8
2222 @PR23753_b = global i8* getelementptr (i8, i8* @PR23753_a, i64 ptrtoint (i8* @PR23753_a to i64))
2323 ; CHECK: @PR23753_b = global i8* getelementptr (i8, i8* @PR23753_a, i64 ptrtoint (i8* @PR23753_a to i64))
24
25 ; Verify that inrange on an index inhibits over-indexed getelementptr folding.
26
27 @nestedarray = global [2 x [4 x i8*]] zeroinitializer
28
29 ; CHECK: @nestedarray.1 = alias i8*, getelementptr inbounds ([2 x [4 x i8*]], [2 x [4 x i8*]]* @nestedarray, inrange i32 0, i64 1, i32 0)
30 @nestedarray.1 = alias i8*, getelementptr inbounds ([2 x [4 x i8*]], [2 x [4 x i8*]]* @nestedarray, inrange i32 0, i32 0, i32 4)
31
32 ; CHECK: @nestedarray.2 = alias i8*, getelementptr inbounds ([2 x [4 x i8*]], [2 x [4 x i8*]]* @nestedarray, i32 0, inrange i32 0, i32 4)
33 @nestedarray.2 = alias i8*, getelementptr inbounds ([2 x [4 x i8*]], [2 x [4 x i8*]]* @nestedarray, i32 0, inrange i32 0, i32 4)
34
35 ; CHECK: @nestedarray.3 = alias i8*, getelementptr inbounds ([2 x [4 x i8*]], [2 x [4 x i8*]]* @nestedarray, i32 0, inrange i32 0, i32 0)
36 @nestedarray.3 = alias i8*, getelementptr inbounds ([4 x i8*], [4 x i8*]* getelementptr inbounds ([2 x [4 x i8*]], [2 x [4 x i8*]]* @nestedarray, i32 0, inrange i32 0), i32 0, i32 0)
37
38 ; CHECK: @nestedarray.4 = alias i8*, getelementptr inbounds ([2 x [4 x i8*]], [2 x [4 x i8*]]* @nestedarray, i32 0, i32 1, i32 0)
39 @nestedarray.4 = alias i8*, getelementptr inbounds ([4 x i8*], [4 x i8*]* getelementptr inbounds ([2 x [4 x i8*]], [2 x [4 x i8*]]* @nestedarray, i32 0, inrange i32 0), i32 1, i32 0)
40
41 ; CHECK: @nestedarray.5 = alias i8*, getelementptr inbounds ([2 x [4 x i8*]], [2 x [4 x i8*]]* @nestedarray, inrange i32 0, i32 1, i32 0)
42 @nestedarray.5 = alias i8*, getelementptr inbounds ([4 x i8*], [4 x i8*]* getelementptr inbounds ([2 x [4 x i8*]], [2 x [4 x i8*]]* @nestedarray, inrange i32 0, i32 0), i32 1, i32 0)
2443
2544 ; See if i92 indices work too.
2645 define i32 *@test({i32, i32}* %t, i92 %n) {
16101610 declare void @f.writeonly() writeonly
16111611 ; CHECK: declare void @f.writeonly() #39
16121612
1613 ;; Constant Expressions
1614
1615 define i8** @constexpr() {
1616 ; CHECK: ret i8** getelementptr inbounds ({ [4 x i8*], [4 x i8*] }, { [4 x i8*], [4 x i8*] }* null, i32 0, inrange i32 1, i32 2)
1617 ret i8** getelementptr inbounds ({ [4 x i8*], [4 x i8*] }, { [4 x i8*], [4 x i8*] }* null, i32 0, inrange i32 1, i32 2)
1618 }
1619
16131620 ; CHECK: attributes #0 = { alignstack=4 }
16141621 ; CHECK: attributes #1 = { alignstack=8 }
16151622 ; CHECK: attributes #2 = { alwaysinline }