llvm.org GIT mirror llvm / 80f495a
Teach ConstantFolding about pointer address spaces git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@188831 91177308-0d34-0410-b5e6-96231b3b80d8 Matt Arsenault 6 years ago
5 changed file(s) with 585 addition(s) and 37 deletion(s). Raw diff Collapse all Expand all
366366
367367 if (ConstantExpr *CE = dyn_cast(C)) {
368368 if (CE->getOpcode() == Instruction::IntToPtr &&
369 CE->getOperand(0)->getType() == TD.getIntPtrType(CE->getContext())) {
369 CE->getOperand(0)->getType() == TD.getIntPtrType(CE->getType())) {
370370 return ReadDataFromGlobal(CE->getOperand(0), ByteOffset, CurPtr,
371371 BytesLeft, TD);
372372 }
378378
379379 static Constant *FoldReinterpretLoadFromConstPtr(Constant *C,
380380 const DataLayout &TD) {
381 Type *LoadTy = cast(C->getType())->getElementType();
381 PointerType *PTy = cast(C->getType());
382 Type *LoadTy = PTy->getElementType();
382383 IntegerType *IntType = dyn_cast(LoadTy);
383384
384385 // If this isn't an integer load we can't fold it directly.
385386 if (!IntType) {
387 unsigned AS = PTy->getAddressSpace();
388
386389 // If this is a float/double load, we can try folding it as an int32/64 load
387390 // and then bitcast the result. This can be useful for union cases. Note
388391 // that address spaces don't matter here since we're not going to result in
389392 // an actual new load.
390393 Type *MapTy;
391394 if (LoadTy->isHalfTy())
392 MapTy = Type::getInt16PtrTy(C->getContext());
395 MapTy = Type::getInt16PtrTy(C->getContext(), AS);
393396 else if (LoadTy->isFloatTy())
394 MapTy = Type::getInt32PtrTy(C->getContext());
397 MapTy = Type::getInt32PtrTy(C->getContext(), AS);
395398 else if (LoadTy->isDoubleTy())
396 MapTy = Type::getInt64PtrTy(C->getContext());
399 MapTy = Type::getInt64PtrTy(C->getContext(), AS);
397400 else if (LoadTy->isVectorTy()) {
398 MapTy = IntegerType::get(C->getContext(),
399 TD.getTypeAllocSizeInBits(LoadTy));
400 MapTy = PointerType::getUnqual(MapTy);
401 MapTy = PointerType::getIntNPtrTy(C->getContext(),
402 TD.getTypeAllocSizeInBits(LoadTy),
403 AS);
401404 } else
402405 return 0;
403406
412415 return 0;
413416
414417 GlobalValue *GVal;
415 APInt Offset(TD.getPointerSizeInBits(), 0);
418 APInt Offset(TD.getPointerTypeSizeInBits(PTy), 0);
416419 if (!IsConstantOffsetFromGlobal(C, GVal, Offset, TD))
417420 return 0;
418421
605608 static Constant *CastGEPIndices(ArrayRef Ops,
606609 Type *ResultTy, const DataLayout *TD,
607610 const TargetLibraryInfo *TLI) {
608 if (!TD) return 0;
609 Type *IntPtrTy = TD->getIntPtrType(ResultTy->getContext());
611 if (!TD)
612 return 0;
613
614 Type *IntPtrTy = TD->getIntPtrType(ResultTy);
610615
611616 bool Any = false;
612617 SmallVector NewIdxs;
664669 !Ptr->getType()->isPointerTy())
665670 return 0;
666671
667 Type *IntPtrTy = TD->getIntPtrType(Ptr->getContext());
672 Type *IntPtrTy = TD->getIntPtrType(Ptr->getType());
668673 Type *ResultElementTy = ResultTy->getPointerElementType();
669674
670675 // If this is a constant expr gep that is effectively computing an
740745 // Also, this helps GlobalOpt do SROA on GlobalVariables.
741746 Type *Ty = Ptr->getType();
742747 assert(Ty->isPointerTy() && "Forming regular GEP of non-pointer type");
743 SmallVector*, 32> NewIdxs;
748 SmallVector *, 32> NewIdxs;
749
744750 do {
745751 if (SequentialType *ATy = dyn_cast(Ty)) {
746752 if (ATy->isPointerTy()) {
755761
756762 // Determine which element of the array the offset points into.
757763 APInt ElemSize(BitWidth, TD->getTypeAllocSize(ATy->getElementType()));
758 IntegerType *IntPtrTy = TD->getIntPtrType(Ty->getContext());
759764 if (ElemSize == 0)
760765 // The element size is 0. This may be [0 x Ty]*, so just use a zero
761766 // index for this level and proceed to the next level to see if it can
967972 if (TD && CE->getOpcode() == Instruction::IntToPtr) {
968973 Constant *Input = CE->getOperand(0);
969974 unsigned InWidth = Input->getType()->getScalarSizeInBits();
970 if (TD->getPointerSizeInBits() < InWidth) {
975 if (TD->getPointerTypeSizeInBits(CE->getType()) < InWidth) {
971976 Constant *Mask =
972977 ConstantInt::get(CE->getContext(), APInt::getLowBitsSet(InWidth,
973978 TD->getPointerSizeInBits()));
982987 // If the input is a ptrtoint, turn the pair into a ptr to ptr bitcast if
983988 // the int size is >= the ptr size. This requires knowing the width of a
984989 // pointer, so it can't be done in ConstantExpr::getCast.
985 if (ConstantExpr *CE = dyn_cast(Ops[0]))
986 if (TD &&
987 TD->getPointerSizeInBits() <= CE->getType()->getScalarSizeInBits() &&
988 CE->getOpcode() == Instruction::PtrToInt)
989 return FoldBitCast(CE->getOperand(0), DestTy, *TD);
990 if (ConstantExpr *CE = dyn_cast(Ops[0])) {
991 if (TD && CE->getOpcode() == Instruction::PtrToInt) {
992 Constant *SrcPtr = CE->getOperand(0);
993 unsigned SrcPtrSize = TD->getPointerTypeSizeInBits(SrcPtr->getType());
994 unsigned MidIntSize = CE->getType()->getScalarSizeInBits();
995
996 if (MidIntSize >= SrcPtrSize) {
997 unsigned DestPtrSize = TD->getPointerTypeSizeInBits(DestTy);
998 if (SrcPtrSize == DestPtrSize)
999 return FoldBitCast(CE->getOperand(0), DestTy, *TD);
1000 }
1001 }
1002 }
9901003
9911004 return ConstantExpr::getCast(Opcode, Ops[0], DestTy);
9921005 case Instruction::Trunc:
10381051 // around to know if bit truncation is happening.
10391052 if (ConstantExpr *CE0 = dyn_cast(Ops0)) {
10401053 if (TD && Ops1->isNullValue()) {
1041 Type *IntPtrTy = TD->getIntPtrType(CE0->getContext());
10421054 if (CE0->getOpcode() == Instruction::IntToPtr) {
1055 Type *IntPtrTy = TD->getIntPtrType(CE0->getType());
10431056 // Convert the integer value to the right size to ensure we get the
10441057 // proper extension or truncation.
10451058 Constant *C = ConstantExpr::getIntegerCast(CE0->getOperand(0),
10501063
10511064 // Only do this transformation if the int is intptrty in size, otherwise
10521065 // there is a truncation or extension that we aren't modeling.
1053 if (CE0->getOpcode() == Instruction::PtrToInt &&
1054 CE0->getType() == IntPtrTy) {
1055 Constant *C = CE0->getOperand(0);
1056 Constant *Null = Constant::getNullValue(C->getType());
1057 return ConstantFoldCompareInstOperands(Predicate, C, Null, TD, TLI);
1066 if (CE0->getOpcode() == Instruction::PtrToInt) {
1067 Type *IntPtrTy = TD->getIntPtrType(CE0->getOperand(0)->getType());
1068 if (CE0->getType() == IntPtrTy) {
1069 Constant *C = CE0->getOperand(0);
1070 Constant *Null = Constant::getNullValue(C->getType());
1071 return ConstantFoldCompareInstOperands(Predicate, C, Null, TD, TLI);
1072 }
10581073 }
10591074 }
10601075
10611076 if (ConstantExpr *CE1 = dyn_cast(Ops1)) {
10621077 if (TD && CE0->getOpcode() == CE1->getOpcode()) {
1063 Type *IntPtrTy = TD->getIntPtrType(CE0->getContext());
1064
10651078 if (CE0->getOpcode() == Instruction::IntToPtr) {
1079 Type *IntPtrTy = TD->getIntPtrType(CE0->getType());
1080
10661081 // Convert the integer value to the right size to ensure we get the
10671082 // proper extension or truncation.
10681083 Constant *C0 = ConstantExpr::getIntegerCast(CE0->getOperand(0),
10741089
10751090 // Only do this transformation if the int is intptrty in size, otherwise
10761091 // there is a truncation or extension that we aren't modeling.
1077 if ((CE0->getOpcode() == Instruction::PtrToInt &&
1078 CE0->getType() == IntPtrTy &&
1079 CE0->getOperand(0)->getType() == CE1->getOperand(0)->getType()))
1080 return ConstantFoldCompareInstOperands(Predicate, CE0->getOperand(0),
1081 CE1->getOperand(0), TD, TLI);
1092 if (CE0->getOpcode() == Instruction::PtrToInt) {
1093 Type *IntPtrTy = TD->getIntPtrType(CE0->getOperand(0)->getType());
1094 if (CE0->getType() == IntPtrTy &&
1095 CE0->getOperand(0)->getType() == CE1->getOperand(0)->getType()) {
1096 return ConstantFoldCompareInstOperands(Predicate,
1097 CE0->getOperand(0),
1098 CE1->getOperand(0),
1099 TD,
1100 TLI);
1101 }
1102 }
10821103 }
10831104 }
10841105
0 ; "PLAIN" - No optimizations. This tests the target-independent
1 ; constant folder.
2 ; RUN: opt -S -o - %s | FileCheck --check-prefix=PLAIN %s
3
4 target datalayout = "e-p:128:128:128-p1:32:32:32-p2:8:8:8-p3:16:16:16-p4:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:32"
5
6 ; The automatic constant folder in opt does not have targetdata access, so
7 ; it can't fold gep arithmetic, in general. However, the constant folder run
8 ; from instcombine and global opt can use targetdata.
9 ; PLAIN: @G8 = global i8 addrspace(1)* getelementptr (i8 addrspace(1)* inttoptr (i32 1 to i8 addrspace(1)*), i32 -1)
10 @G8 = global i8 addrspace(1)* getelementptr (i8 addrspace(1)* inttoptr (i32 1 to i8 addrspace(1)*), i32 -1)
11 ; PLAIN: @G1 = global i1 addrspace(2)* getelementptr (i1 addrspace(2)* inttoptr (i8 1 to i1 addrspace(2)*), i8 -1)
12 @G1 = global i1 addrspace(2)* getelementptr (i1 addrspace(2)* inttoptr (i8 1 to i1 addrspace(2)*), i8 -1)
13 ; PLAIN: @F8 = global i8 addrspace(1)* getelementptr (i8 addrspace(1)* inttoptr (i32 1 to i8 addrspace(1)*), i32 -2)
14 @F8 = global i8 addrspace(1)* getelementptr (i8 addrspace(1)* inttoptr (i32 1 to i8 addrspace(1)*), i32 -2)
15 ; PLAIN: @F1 = global i1 addrspace(2)* getelementptr (i1 addrspace(2)* inttoptr (i8 1 to i1 addrspace(2)*), i8 -2)
16 @F1 = global i1 addrspace(2)* getelementptr (i1 addrspace(2)* inttoptr (i8 1 to i1 addrspace(2)*), i8 -2)
17 ; PLAIN: @H8 = global i8 addrspace(1)* getelementptr (i8 addrspace(1)* null, i32 -1)
18 @H8 = global i8 addrspace(1)* getelementptr (i8 addrspace(1)* inttoptr (i32 0 to i8 addrspace(1)*), i32 -1)
19 ; PLAIN: @H1 = global i1 addrspace(2)* getelementptr (i1 addrspace(2)* null, i8 -1)
20 @H1 = global i1 addrspace(2)* getelementptr (i1 addrspace(2)* inttoptr (i8 0 to i1 addrspace(2)*), i8 -1)
21
22
23 ; The target-independent folder should be able to do some clever
24 ; simplifications on sizeof, alignof, and offsetof expressions. The
25 ; target-dependent folder should fold these down to constants.
26 ; PLAIN-X: @a = constant i64 mul (i64 ptrtoint (double addrspace(4)* getelementptr (double addrspace(4)* null, i32 1) to i64), i64 2310)
27 @a = constant i64 mul (i64 3, i64 mul (i64 ptrtoint ({[7 x double], [7 x double]} addrspace(4)* getelementptr ({[7 x double], [7 x double]} addrspace(4)* null, i64 11) to i64), i64 5))
28
29 ; PLAIN-X: @b = constant i64 ptrtoint (double addrspace(4)* getelementptr ({ i1, double }* null, i64 0, i32 1) to i64)
30 @b = constant i64 ptrtoint ([13 x double] addrspace(4)* getelementptr ({i1, [13 x double]} addrspace(4)* null, i64 0, i32 1) to i64)
31
32 ; PLAIN-X: @c = constant i64 mul nuw (i64 ptrtoint (double addrspace(4)* getelementptr (double addrspace(4)* null, i32 1) to i64), i64 2)
33 @c = constant i64 ptrtoint (double addrspace(4)* getelementptr ({double, double, double, double} addrspace(4)* null, i64 0, i32 2) to i64)
34
35 ; PLAIN-X: @d = constant i64 mul nuw (i64 ptrtoint (double addrspace(4)* getelementptr (double addrspace(4)* null, i32 1) to i64), i64 11)
36 @d = constant i64 ptrtoint (double addrspace(4)* getelementptr ([13 x double] addrspace(4)* null, i64 0, i32 11) to i64)
37
38 ; PLAIN-X: @e = constant i64 ptrtoint (double addrspace(4)* getelementptr ({ double, float, double, double }* null, i64 0, i32 2) to i64)
39 @e = constant i64 ptrtoint (double addrspace(4)* getelementptr ({double, float, double, double} addrspace(4)* null, i64 0, i32 2) to i64)
40
41 ; PLAIN-X: @f = constant i64 1
42 @f = constant i64 ptrtoint (<{ i16, i128 }> addrspace(4)* getelementptr ({i1, <{ i16, i128 }>} addrspace(4)* null, i64 0, i32 1) to i64)
43
44 ; PLAIN-X: @g = constant i64 ptrtoint (double addrspace(4)* getelementptr ({ i1, double }* null, i64 0, i32 1) to i64)
45 @g = constant i64 ptrtoint ({double, double} addrspace(4)* getelementptr ({i1, {double, double}} addrspace(4)* null, i64 0, i32 1) to i64)
46
47 ; PLAIN-X: @h = constant i64 ptrtoint (i1 addrspace(2)* getelementptr (i1 addrspace(2)* null, i32 1) to i64)
48 @h = constant i64 ptrtoint (double addrspace(4)* getelementptr (double addrspace(4)* null, i64 1) to i64)
49
50 ; PLAIN-X: @i = constant i64 ptrtoint (i1 addrspace(2)* getelementptr ({ i1, i1 addrspace(2)* }* null, i64 0, i32 1) to i64)
51 @i = constant i64 ptrtoint (double addrspace(4)* getelementptr ({i1, double} addrspace(4)* null, i64 0, i32 1) to i64)
52
53 ; The target-dependent folder should cast GEP indices to integer-sized pointers.
54
55 ; PLAIN: @M = constant i64 addrspace(4)* getelementptr (i64 addrspace(4)* null, i32 1)
56 ; PLAIN: @N = constant i64 addrspace(4)* getelementptr ({ i64, i64 } addrspace(4)* null, i32 0, i32 1)
57 ; PLAIN: @O = constant i64 addrspace(4)* getelementptr ([2 x i64] addrspace(4)* null, i32 0, i32 1)
58
59 @M = constant i64 addrspace(4)* getelementptr (i64 addrspace(4)* null, i32 1)
60 @N = constant i64 addrspace(4)* getelementptr ({ i64, i64 } addrspace(4)* null, i32 0, i32 1)
61 @O = constant i64 addrspace(4)* getelementptr ([2 x i64] addrspace(4)* null, i32 0, i32 1)
62
63 ; Fold GEP of a GEP. Very simple cases are folded.
64
65 ; PLAIN-X: @Y = global [3 x { i32, i32 }]addrspace(3)* getelementptr inbounds ([3 x { i32, i32 }]addrspace(3)* @ext, i64 2)
66 @ext = external addrspace(3) global [3 x { i32, i32 }]
67 @Y = global [3 x { i32, i32 }]addrspace(3)* getelementptr inbounds ([3 x { i32, i32 }]addrspace(3)* getelementptr inbounds ([3 x { i32, i32 }]addrspace(3)* @ext, i64 1), i64 1)
68
69 ; PLAIN-X: @Z = global i32addrspace(3)* getelementptr inbounds (i32addrspace(3)* getelementptr inbounds ([3 x { i32, i32 }]addrspace(3)* @ext, i64 0, i64 1, i32 0), i64 1)
70 @Z = global i32addrspace(3)* getelementptr inbounds (i32addrspace(3)* getelementptr inbounds ([3 x { i32, i32 }]addrspace(3)* @ext, i64 0, i64 1, i32 0), i64 1)
71
72
73 ; Duplicate all of the above as function return values rather than
74 ; global initializers.
75
76 ; PLAIN: define i8 addrspace(1)* @goo8() #0 {
77 ; PLAIN: %t = bitcast i8 addrspace(1)* getelementptr (i8 addrspace(1)* inttoptr (i32 1 to i8 addrspace(1)*), i32 -1) to i8 addrspace(1)*
78 ; PLAIN: ret i8 addrspace(1)* %t
79 ; PLAIN: }
80 ; PLAIN: define i1 addrspace(2)* @goo1() #0 {
81 ; PLAIN: %t = bitcast i1 addrspace(2)* getelementptr (i1 addrspace(2)* inttoptr (i32 1 to i1 addrspace(2)*), i32 -1) to i1 addrspace(2)*
82 ; PLAIN: ret i1 addrspace(2)* %t
83 ; PLAIN: }
84 ; PLAIN: define i8 addrspace(1)* @foo8() #0 {
85 ; PLAIN: %t = bitcast i8 addrspace(1)* getelementptr (i8 addrspace(1)* inttoptr (i32 1 to i8 addrspace(1)*), i32 -2) to i8 addrspace(1)*
86 ; PLAIN: ret i8 addrspace(1)* %t
87 ; PLAIN: }
88 ; PLAIN: define i1 addrspace(2)* @foo1() #0 {
89 ; PLAIN: %t = bitcast i1 addrspace(2)* getelementptr (i1 addrspace(2)* inttoptr (i32 1 to i1 addrspace(2)*), i32 -2) to i1 addrspace(2)*
90 ; PLAIN: ret i1 addrspace(2)* %t
91 ; PLAIN: }
92 ; PLAIN: define i8 addrspace(1)* @hoo8() #0 {
93 ; PLAIN: %t = bitcast i8 addrspace(1)* getelementptr (i8 addrspace(1)* null, i32 -1) to i8 addrspace(1)*
94 ; PLAIN: ret i8 addrspace(1)* %t
95 ; PLAIN: }
96 ; PLAIN: define i1 addrspace(2)* @hoo1() #0 {
97 ; PLAIN: %t = bitcast i1 addrspace(2)* getelementptr (i1 addrspace(2)* null, i32 -1) to i1 addrspace(2)*
98 ; PLAIN: ret i1 addrspace(2)* %t
99 ; PLAIN: }
100 define i8 addrspace(1)* @goo8() #0 {
101 %t = bitcast i8 addrspace(1)* getelementptr (i8 addrspace(1)* inttoptr (i32 1 to i8 addrspace(1)*), i32 -1) to i8 addrspace(1)*
102 ret i8 addrspace(1)* %t
103 }
104 define i1 addrspace(2)* @goo1() #0 {
105 %t = bitcast i1 addrspace(2)* getelementptr (i1 addrspace(2)* inttoptr (i32 1 to i1 addrspace(2)*), i32 -1) to i1 addrspace(2)*
106 ret i1 addrspace(2)* %t
107 }
108 define i8 addrspace(1)* @foo8() #0 {
109 %t = bitcast i8 addrspace(1)* getelementptr (i8 addrspace(1)* inttoptr (i32 1 to i8 addrspace(1)*), i32 -2) to i8 addrspace(1)*
110 ret i8 addrspace(1)* %t
111 }
112 define i1 addrspace(2)* @foo1() #0 {
113 %t = bitcast i1 addrspace(2)* getelementptr (i1 addrspace(2)* inttoptr (i32 1 to i1 addrspace(2)*), i32 -2) to i1 addrspace(2)*
114 ret i1 addrspace(2)* %t
115 }
116 define i8 addrspace(1)* @hoo8() #0 {
117 %t = bitcast i8 addrspace(1)* getelementptr (i8 addrspace(1)* inttoptr (i32 0 to i8 addrspace(1)*), i32 -1) to i8 addrspace(1)*
118 ret i8 addrspace(1)* %t
119 }
120 define i1 addrspace(2)* @hoo1() #0 {
121 %t = bitcast i1 addrspace(2)* getelementptr (i1 addrspace(2)* inttoptr (i32 0 to i1 addrspace(2)*), i32 -1) to i1 addrspace(2)*
122 ret i1 addrspace(2)* %t
123 }
124
125 ; PLAIN-X: define i64 @fa() #0 {
126 ; PLAIN-X: %t = bitcast i64 mul (i64 ptrtoint (double addrspace(4)* getelementptr (double addrspace(4)* null, i32 1) to i64), i64 2310) to i64
127 ; PLAIN-X: ret i64 %t
128 ; PLAIN-X: }
129 ; PLAIN-X: define i64 @fb() #0 {
130 ; PLAIN-X: %t = bitcast i64 ptrtoint (double addrspace(4)* getelementptr ({ i1, double }* null, i64 0, i32 1) to i64) to i64
131 ; PLAIN-X: ret i64 %t
132 ; PLAIN-X: }
133 ; PLAIN-X: define i64 @fc() #0 {
134 ; PLAIN-X: %t = bitcast i64 mul nuw (i64 ptrtoint (double addrspace(4)* getelementptr (double addrspace(4)* null, i32 1) to i64), i64 2) to i64
135 ; PLAIN-X: ret i64 %t
136 ; PLAIN-X: }
137 ; PLAIN-X: define i64 @fd() #0 {
138 ; PLAIN-X: %t = bitcast i64 mul nuw (i64 ptrtoint (double addrspace(4)* getelementptr (double addrspace(4)* null, i32 1) to i64), i64 11) to i64
139 ; PLAIN-X: ret i64 %t
140 ; PLAIN-X: }
141 ; PLAIN-X: define i64 @fe() #0 {
142 ; PLAIN-X: %t = bitcast i64 ptrtoint (double addrspace(4)* getelementptr ({ double, float, double, double }* null, i64 0, i32 2) to i64) to i64
143 ; PLAIN-X: ret i64 %t
144 ; PLAIN-X: }
145 ; PLAIN-X: define i64 @ff() #0 {
146 ; PLAIN-X: %t = bitcast i64 1 to i64
147 ; PLAIN-X: ret i64 %t
148 ; PLAIN-X: }
149 ; PLAIN-X: define i64 @fg() #0 {
150 ; PLAIN-X: %t = bitcast i64 ptrtoint (double addrspace(4)* getelementptr ({ i1, double }* null, i64 0, i32 1) to i64) to i64
151 ; PLAIN-X: ret i64 %t
152 ; PLAIN-X: }
153 ; PLAIN-X: define i64 @fh() #0 {
154 ; PLAIN-X: %t = bitcast i64 ptrtoint (i1 addrspace(2)* getelementptr (i1 addrspace(2)* null, i32 1) to i64) to i64
155 ; PLAIN-X: ret i64 %t
156 ; PLAIN-X: }
157 ; PLAIN-X: define i64 @fi() #0 {
158 ; PLAIN-X: %t = bitcast i64 ptrtoint (i1 addrspace(2)* getelementptr ({ i1, i1 addrspace(2)* }* null, i64 0, i32 1) to i64) to i64
159 ; PLAIN-X: ret i64 %t
160 ; PLAIN-X: }
161 define i64 @fa() #0 {
162 %t = bitcast i64 mul (i64 3, i64 mul (i64 ptrtoint ({[7 x double], [7 x double]}* getelementptr ({[7 x double], [7 x double]}* null, i64 11) to i64), i64 5)) to i64
163 ret i64 %t
164 }
165 define i64 @fb() #0 {
166 %t = bitcast i64 ptrtoint ([13 x double] addrspace(4)* getelementptr ({i1, [13 x double]} addrspace(4)* null, i64 0, i32 1) to i64) to i64
167 ret i64 %t
168 }
169 define i64 @fc() #0 {
170 %t = bitcast i64 ptrtoint (double addrspace(4)* getelementptr ({double, double, double, double} addrspace(4)* null, i64 0, i32 2) to i64) to i64
171 ret i64 %t
172 }
173 define i64 @fd() #0 {
174 %t = bitcast i64 ptrtoint (double addrspace(4)* getelementptr ([13 x double] addrspace(4)* null, i64 0, i32 11) to i64) to i64
175 ret i64 %t
176 }
177 define i64 @fe() #0 {
178 %t = bitcast i64 ptrtoint (double addrspace(4)* getelementptr ({double, float, double, double} addrspace(4)* null, i64 0, i32 2) to i64) to i64
179 ret i64 %t
180 }
181 define i64 @ff() #0 {
182 %t = bitcast i64 ptrtoint (<{ i16, i128 }> addrspace(4)* getelementptr ({i1, <{ i16, i128 }>} addrspace(4)* null, i64 0, i32 1) to i64) to i64
183 ret i64 %t
184 }
185 define i64 @fg() #0 {
186 %t = bitcast i64 ptrtoint ({double, double} addrspace(4)* getelementptr ({i1, {double, double}} addrspace(4)* null, i64 0, i32 1) to i64) to i64
187 ret i64 %t
188 }
189 define i64 @fh() #0 {
190 %t = bitcast i64 ptrtoint (double addrspace(4)* getelementptr (double addrspace(4)* null, i32 1) to i64) to i64
191 ret i64 %t
192 }
193 define i64 @fi() #0 {
194 %t = bitcast i64 ptrtoint (double addrspace(4)* getelementptr ({i1, double}addrspace(4)* null, i64 0, i32 1) to i64) to i64
195 ret i64 %t
196 }
197
198 ; PLAIN: define i64* @fM() #0 {
199 ; PLAIN: %t = bitcast i64* getelementptr (i64* null, i32 1) to i64*
200 ; PLAIN: ret i64* %t
201 ; PLAIN: }
202 ; PLAIN: define i64* @fN() #0 {
203 ; PLAIN: %t = bitcast i64* getelementptr ({ i64, i64 }* null, i32 0, i32 1) to i64*
204 ; PLAIN: ret i64* %t
205 ; PLAIN: }
206 ; PLAIN: define i64* @fO() #0 {
207 ; PLAIN: %t = bitcast i64* getelementptr ([2 x i64]* null, i32 0, i32 1) to i64*
208 ; PLAIN: ret i64* %t
209 ; PLAIN: }
210
211 define i64* @fM() #0 {
212 %t = bitcast i64* getelementptr (i64* null, i32 1) to i64*
213 ret i64* %t
214 }
215 define i64* @fN() #0 {
216 %t = bitcast i64* getelementptr ({ i64, i64 }* null, i32 0, i32 1) to i64*
217 ret i64* %t
218 }
219 define i64* @fO() #0 {
220 %t = bitcast i64* getelementptr ([2 x i64]* null, i32 0, i32 1) to i64*
221 ret i64* %t
222 }
223
224 ; PLAIN: define i32 addrspace(1)* @fZ() #0 {
225 ; PLAIN: %t = bitcast i32 addrspace(1)* getelementptr inbounds (i32 addrspace(1)* getelementptr inbounds ([3 x { i32, i32 }] addrspace(1)* @ext2, i64 0, i64 1, i32 0), i64 1) to i32 addrspace(1)*
226 ; PLAIN: ret i32 addrspace(1)* %t
227 ; PLAIN: }
228 @ext2 = external addrspace(1) global [3 x { i32, i32 }]
229 define i32 addrspace(1)* @fZ() #0 {
230 %t = bitcast i32 addrspace(1)* getelementptr inbounds (i32 addrspace(1)* getelementptr inbounds ([3 x { i32, i32 }] addrspace(1)* @ext2, i64 0, i64 1, i32 0), i64 1) to i32 addrspace(1)*
231 ret i32 addrspace(1)* %t
232 }
233
234 attributes #0 = { nounwind }
None ; RUN: opt < %s -default-data-layout="e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64" -instcombine -S | FileCheck %s --check-prefix=LE
1 ; RUN: opt < %s -default-data-layout="E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64" -instcombine -S | FileCheck %s --check-prefix=BE
0 ; RUN: opt < %s -default-data-layout="e-p:64:64:64-p1:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64" -instcombine -S | FileCheck %s --check-prefix=LE
1 ; RUN: opt < %s -default-data-layout="E-p:64:64:64-p1:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64" -instcombine -S | FileCheck %s --check-prefix=BE
22
33 ; {{ 0xDEADBEEF, 0xBA }, 0xCAFEBABE}
44 @g1 = constant {{i32,i8},i32} {{i32,i8} { i32 -559038737, i8 186 }, i32 -889275714 }
154154 @test12g = private constant [6 x i8] c"a\00b\00\00\00"
155155
156156 define i16 @test12() {
157 %a = load i16* getelementptr inbounds ([3 x i16]* bitcast ([6 x i8]* @test12g to [3 x i16]*), i32 0, i64 1)
157 %a = load i16* getelementptr inbounds ([3 x i16]* bitcast ([6 x i8]* @test12g to [3 x i16]*), i32 0, i64 1)
158158 ret i16 %a
159159
160160 ; 0x0062
193193 ; BE: ret i64 1
194194 }
195195
196 ; Check with address space pointers
197 @g6_as1 = constant [2 x i8 addrspace(1)*] [i8 addrspace(1)* inttoptr (i16 1 to i8 addrspace(1)*), i8 addrspace(1)* inttoptr (i16 2 to i8 addrspace(1)*)]
198 define i16 @test14_as1() nounwind {
199 entry:
200 %tmp = load i16* bitcast ([2 x i8 addrspace(1)*]* @g6_as1 to i16*)
201 ret i16 %tmp
202
203 ; LE: @test14_as1
204 ; LE: ret i16 1
205
206 ; BE: @test14_as1
207 ; BE: ret i16 1
208 }
209
196210 define i64 @test15() nounwind {
197211 entry:
198212 %tmp = load i64* bitcast (i8** getelementptr inbounds ([2 x i8*]* @g6, i32 0, i64 1) to i64*)
0 ; RUN: opt -S -instcombine %s -o - | FileCheck %s
1 target datalayout = "e-p:32:32:32-p1:64:64:64-p2:8:8:8-p3:16:16:16-p4:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:32"
2
3 @g = addrspace(3) global i32 89
4
5 @const_zero_i8_as1 = addrspace(1) constant i8 0
6 @const_zero_i32_as1 = addrspace(1) constant i32 0
7
8 @const_zero_i8_as2 = addrspace(2) constant i8 0
9 @const_zero_i32_as2 = addrspace(2) constant i32 0
10
11 @const_zero_i8_as3 = addrspace(3) constant i8 0
12 @const_zero_i32_as3 = addrspace(3) constant i32 0
13
14 ; Test constant folding of inttoptr (ptrtoint constantexpr)
15 ; The intermediate integer size is the same as the pointer size
16 define i32 addrspace(3)* @test_constant_fold_inttoptr_as_pointer_same_size() {
17 ; CHECK-LABEL: @test_constant_fold_inttoptr_as_pointer_same_size(
18 ; CHECK-NEXT: ret i32 addrspace(3)* @const_zero_i32_as3
19 %x = ptrtoint i32 addrspace(3)* @const_zero_i32_as3 to i32
20 %y = inttoptr i32 %x to i32 addrspace(3)*
21 ret i32 addrspace(3)* %y
22 }
23
24 ; The intermediate integer size is larger than the pointer size
25 define i32 addrspace(2)* @test_constant_fold_inttoptr_as_pointer_smaller() {
26 ; CHECK-LABEL: @test_constant_fold_inttoptr_as_pointer_smaller(
27 ; CHECK-NEXT: ret i32 addrspace(2)* @const_zero_i32_as2
28 %x = ptrtoint i32 addrspace(2)* @const_zero_i32_as2 to i16
29 %y = inttoptr i16 %x to i32 addrspace(2)*
30 ret i32 addrspace(2)* %y
31 }
32
33 ; Different address spaces that are the same size, but they are
34 ; different so there should be a bitcast.
35 define i32 addrspace(4)* @test_constant_fold_inttoptr_as_pointer_smaller_different_as() {
36 ; CHECK-LABEL: @test_constant_fold_inttoptr_as_pointer_smaller_different_as(
37 ; CHECK-NEXT: ret i32 addrspace(4)* bitcast (i32 addrspace(3)* @const_zero_i32_as3 to i32 addrspace(4)*)
38 %x = ptrtoint i32 addrspace(3)* @const_zero_i32_as3 to i16
39 %y = inttoptr i16 %x to i32 addrspace(4)*
40 ret i32 addrspace(4)* %y
41 }
42
43 ; Make sure we don't introduce a bitcast between different sized
44 ; address spaces when folding this
45 define i32 addrspace(2)* @test_constant_fold_inttoptr_as_pointer_smaller_different_size_as() {
46 ; CHECK-LABEL: @test_constant_fold_inttoptr_as_pointer_smaller_different_size_as(
47 ; CHECK-NEXT: ret i32 addrspace(2)* inttoptr (i32 ptrtoint (i32 addrspace(3)* @const_zero_i32_as3 to i32) to i32 addrspace(2)*)
48 %x = ptrtoint i32 addrspace(3)* @const_zero_i32_as3 to i32
49 %y = inttoptr i32 %x to i32 addrspace(2)*
50 ret i32 addrspace(2)* %y
51 }
52
53 ; The intermediate integer size is too small, nothing should happen
54 define i32 addrspace(3)* @test_constant_fold_inttoptr_as_pointer_larger() {
55 ; CHECK-LABEL: @test_constant_fold_inttoptr_as_pointer_larger(
56 ; CHECK-NEXT: ret i32 addrspace(3)* inttoptr (i8 ptrtoint (i32 addrspace(3)* @const_zero_i32_as3 to i8) to i32 addrspace(3)*)
57 %x = ptrtoint i32 addrspace(3)* @const_zero_i32_as3 to i8
58 %y = inttoptr i8 %x to i32 addrspace(3)*
59 ret i32 addrspace(3)* %y
60 }
61
62 define i8 @const_fold_ptrtoint() {
63 ; CHECK-LABEL: @const_fold_ptrtoint(
64 ; CHECK-NEXT: ret i8 4
65 ret i8 ptrtoint (i32 addrspace(2)* inttoptr (i4 4 to i32 addrspace(2)*) to i8)
66 }
67
68 ; Test that mask happens when the destination pointer is smaller than
69 ; the original
70 define i8 @const_fold_ptrtoint_mask() {
71 ; CHECK-LABEL: @const_fold_ptrtoint_mask(
72 ; CHECK-NEXT: ret i8 1
73 ret i8 ptrtoint (i32 addrspace(3)* inttoptr (i32 257 to i32 addrspace(3)*) to i8)
74 }
75
76 define i32 addrspace(3)* @const_inttoptr() {
77 ; CHECK-LABEL: @const_inttoptr(
78 ; CHECK-NEXT: ret i32 addrspace(3)* inttoptr (i16 4 to i32 addrspace(3)*)
79 %p = inttoptr i16 4 to i32 addrspace(3)*
80 ret i32 addrspace(3)* %p
81 }
82
83 define i16 @const_ptrtoint() {
84 ; CHECK-LABEL: @const_ptrtoint(
85 ; CHECK-NEXT: ret i16 ptrtoint (i32 addrspace(3)* @g to i16)
86 %i = ptrtoint i32 addrspace(3)* @g to i16
87 ret i16 %i
88 }
89
90 define i16 @const_inttoptr_ptrtoint() {
91 ; CHECK-LABEL: @const_inttoptr_ptrtoint(
92 ; CHECK-NEXT: ret i16 9
93 ret i16 ptrtoint (i32 addrspace(3)* inttoptr (i16 9 to i32 addrspace(3)*) to i16)
94 }
95
96 define i1 @constant_fold_cmp_constantexpr_inttoptr() {
97 ; CHECK-LABEL: @constant_fold_cmp_constantexpr_inttoptr(
98 ; CHECK-NEXT: ret i1 true
99 %x = icmp eq i32 addrspace(3)* inttoptr (i16 0 to i32 addrspace(3)*), null
100 ret i1 %x
101 }
102
103 define i1 @constant_fold_inttoptr_null(i16 %i) {
104 ; CHECK-LABEL: @constant_fold_inttoptr_null(
105 ; CHECK-NEXT: ret i1 false
106 %x = icmp eq i32 addrspace(3)* inttoptr (i16 99 to i32 addrspace(3)*), inttoptr (i16 0 to i32 addrspace(3)*)
107 ret i1 %x
108 }
109
110 define i1 @constant_fold_ptrtoint_null() {
111 ; CHECK-LABEL: @constant_fold_ptrtoint_null(
112 ; CHECK-NEXT: ret i1 false
113 %x = icmp eq i16 ptrtoint (i32 addrspace(3)* @g to i16), ptrtoint (i32 addrspace(3)* null to i16)
114 ret i1 %x
115 }
116
117 define i1 @constant_fold_ptrtoint_null_2() {
118 ; CHECK-LABEL: @constant_fold_ptrtoint_null_2(
119 ; CHECK-NEXT: ret i1 false
120 %x = icmp eq i16 ptrtoint (i32 addrspace(3)* null to i16), ptrtoint (i32 addrspace(3)* @g to i16)
121 ret i1 %x
122 }
123
124 define i1 @constant_fold_ptrtoint() {
125 ; CHECK-LABEL: @constant_fold_ptrtoint(
126 ; CHECK-NEXT: ret i1 true
127 %x = icmp eq i16 ptrtoint (i32 addrspace(3)* @g to i16), ptrtoint (i32 addrspace(3)* @g to i16)
128 ret i1 %x
129 }
130
131 define i1 @constant_fold_inttoptr() {
132 ; CHECK-LABEL: @constant_fold_inttoptr(
133 ; CHECK-NEXT: ret i1 false
134 %x = icmp eq i32 addrspace(3)* inttoptr (i16 99 to i32 addrspace(3)*), inttoptr (i16 27 to i32 addrspace(3)*)
135 ret i1 %x
136 }
137
138 @g_float_as3 = addrspace(3) global float zeroinitializer
139 @g_v4f_as3 = addrspace(3) global <4 x float> zeroinitializer
140
141 define float @constant_fold_bitcast_ftoi_load() {
142 ; CHECK-LABEL: @constant_fold_bitcast_ftoi_load(
143 ; CHECK: load float addrspace(3)* bitcast (i32 addrspace(3)* @g to float addrspace(3)*), align 4
144 %a = load float addrspace(3)* bitcast (i32 addrspace(3)* @g to float addrspace(3)*), align 4
145 ret float %a
146 }
147
148 define i32 @constant_fold_bitcast_itof_load() {
149 ; CHECK-LABEL: @constant_fold_bitcast_itof_load(
150 ; CHECK: load i32 addrspace(3)* bitcast (float addrspace(3)* @g_float_as3 to i32 addrspace(3)*), align 4
151 %a = load i32 addrspace(3)* bitcast (float addrspace(3)* @g_float_as3 to i32 addrspace(3)*), align 4
152 ret i32 %a
153 }
154
155 define <4 x i32> @constant_fold_bitcast_vector_as() {
156 ; CHECK-LABEL: @constant_fold_bitcast_vector_as(
157 ; CHECK: load <4 x float> addrspace(3)* @g_v4f_as3, align 16
158 ; CHECK: bitcast <4 x float> %1 to <4 x i32>
159 %a = load <4 x i32> addrspace(3)* bitcast (<4 x float> addrspace(3)* @g_v4f_as3 to <4 x i32> addrspace(3)*), align 4
160 ret <4 x i32> %a
161 }
162
163 @i32_array_as3 = addrspace(3) global [10 x i32] zeroinitializer
164
165 define i32 @test_cast_gep_small_indices_as() {
166 ; CHECK-LABEL: @test_cast_gep_small_indices_as(
167 ; CHECK: load i32 addrspace(3)* getelementptr inbounds ([10 x i32] addrspace(3)* @i32_array_as3, i16 0, i16 0), align 16
168 %p = getelementptr [10 x i32] addrspace(3)* @i32_array_as3, i7 0, i7 0
169 %x = load i32 addrspace(3)* %p, align 4
170 ret i32 %x
171 }
172
173 %struct.foo = type { float, float, [4 x i32], i32 addrspace(3)* }
174
175 @constant_fold_global_ptr = addrspace(3) global %struct.foo {
176 float 0.0,
177 float 0.0,
178 [4 x i32] zeroinitializer,
179 i32 addrspace(3)* getelementptr ([10 x i32] addrspace(3)* @i32_array_as3, i64 0, i64 0)
180 }
181
182 define i32 @test_cast_gep_large_indices_as() {
183 ; CHECK-LABEL: @test_cast_gep_large_indices_as(
184 ; CHECK: load i32 addrspace(3)* getelementptr inbounds ([10 x i32] addrspace(3)* @i32_array_as3, i16 0, i16 0), align 16
185 %p = getelementptr [10 x i32] addrspace(3)* @i32_array_as3, i64 0, i64 0
186 %x = load i32 addrspace(3)* %p, align 4
187 ret i32 %x
188 }
189
190 define i32 @test_constant_cast_gep_struct_indices_as() {
191 ; CHECK-LABEL: @test_constant_cast_gep_struct_indices_as(
192 ; CHECK: load i32 addrspace(3)* getelementptr inbounds (%struct.foo addrspace(3)* @constant_fold_global_ptr, i16 0, i32 2, i16 2), align 8
193 %x = getelementptr %struct.foo addrspace(3)* @constant_fold_global_ptr, i18 0, i32 2, i12 2
194 %y = load i32 addrspace(3)* %x, align 4
195 ret i32 %y
196 }
197
198 @constant_data_as3 = addrspace(3) constant [5 x i32] [i32 1, i32 2, i32 3, i32 4, i32 5]
199
200 define i32 @test_read_data_from_global_as3() {
201 ; CHECK-LABEL: @test_read_data_from_global_as3(
202 ; CHECK-NEXT: ret i32 2
203 %x = getelementptr [5 x i32] addrspace(3)* @constant_data_as3, i32 0, i32 1
204 %y = load i32 addrspace(3)* %x, align 4
205 ret i32 %y
206 }
207
208 @a = addrspace(1) constant i32 9
209 @b = addrspace(1) constant i32 23
210 @c = addrspace(1) constant i32 34
211 @d = addrspace(1) constant i32 99
212
213 @ptr_array = addrspace(2) constant [4 x i32 addrspace(1)*] [ i32 addrspace(1)* @a, i32 addrspace(1)* @b, i32 addrspace(1)* @c, i32 addrspace(1)* @d]
214 @indirect = addrspace(0) constant i32 addrspace(1)* addrspace(2)* getelementptr inbounds ([4 x i32 addrspace(1)*] addrspace(2)* @ptr_array, i1 0, i32 2)
215
216 define i32 @constant_through_array_as_ptrs() {
217 ; CHECK-LABEL: @constant_through_array_as_ptrs(
218 ; CHECK-NEXT: ret i32 34
219 %p = load i32 addrspace(1)* addrspace(2)* addrspace(0)* @indirect, align 4
220 %a = load i32 addrspace(1)* addrspace(2)* %p, align 4
221 %b = load i32 addrspace(1)* %a, align 4
222 ret i32 %b
223 }
0 ; RUN: opt < %s -instcombine -S | FileCheck %s
11
2 target datalayout = "e-p:64:64"
2 target datalayout = "e-p:64:64-p1:16:16-p2:32:32:32"
3
34 %intstruct = type { i32 }
45 %pair = type { i32, i32 }
56 %struct.B = type { double }
78
89
910 @Global = constant [10 x i8] c"helloworld"
11 @Global_as1 = addrspace(1) constant [10 x i8] c"helloworld"
1012
1113 ; Test noop elimination
1214 define i32* @test1(i32* %I) {
1416 ret i32* %A
1517 ; CHECK-LABEL: @test1(
1618 ; CHECK: ret i32* %I
19 }
20
21 define i32 addrspace(1)* @test1_as1(i32 addrspace(1)* %I) {
22 %A = getelementptr i32 addrspace(1)* %I, i64 0
23 ret i32 addrspace(1)* %A
24 ; CHECK-LABEL: @test1_as1(
25 ; CHECK: ret i32 addrspace(1)* %I
1726 }
1827
1928 ; Test noop elimination
5160 ; CHECK: store i8 %B, i8* getelementptr inbounds ([10 x i8]* @Global, i64 0, i64 4)
5261 }
5362
63 define void @test5_as1(i8 %B) {
64 ; This should be turned into a constexpr instead of being an instruction
65 %A = getelementptr [10 x i8] addrspace(1)* @Global_as1, i16 0, i16 4
66 store i8 %B, i8 addrspace(1)* %A
67 ret void
68 ; CHECK-LABEL: @test5_as1(
69 ; CHECK: store i8 %B, i8 addrspace(1)* getelementptr inbounds ([10 x i8] addrspace(1)* @Global_as1, i16 0, i16 4)
70 }
71
72 %as1_ptr_struct = type { i32 addrspace(1)* }
73 %as2_ptr_struct = type { i32 addrspace(2)* }
74
75 @global_as2 = addrspace(2) global i32 zeroinitializer
76 @global_as1_as2_ptr = addrspace(1) global %as2_ptr_struct { i32 addrspace(2)* @global_as2 }
77
78 ; This should be turned into a constexpr instead of being an instruction
79 define void @test_evaluate_gep_nested_as_ptrs(i32 addrspace(2)* %B) {
80 ; CHECK-LABEL: @test_evaluate_gep_nested_as_ptrs(
81 ; CHECK-NEXT: store i32 addrspace(2)* %B, i32 addrspace(2)* addrspace(1)* getelementptr inbounds (%as2_ptr_struct addrspace(1)* @global_as1_as2_ptr, i16 0, i32 0), align 8
82 ; CHECK-NEXT: ret void
83 %A = getelementptr %as2_ptr_struct addrspace(1)* @global_as1_as2_ptr, i16 0, i32 0
84 store i32 addrspace(2)* %B, i32 addrspace(2)* addrspace(1)* %A
85 ret void
86 }
87
88 @arst = addrspace(1) global [4 x i8 addrspace(2)*] zeroinitializer
89
90 define void @test_evaluate_gep_as_ptrs_array(i8 addrspace(2)* %B) {
91 ; CHECK-LABEL: @test_evaluate_gep_as_ptrs_array(
92 ; CHECK-NEXT: store i8 addrspace(2)* %B, i8 addrspace(2)* addrspace(1)* getelementptr inbounds ([4 x i8 addrspace(2)*] addrspace(1)* @arst, i16 0, i16 2), align 4
93
94 ; CHECK-NEXT: ret void
95 %A = getelementptr [4 x i8 addrspace(2)*] addrspace(1)* @arst, i16 0, i16 2
96 store i8 addrspace(2)* %B, i8 addrspace(2)* addrspace(1)* %A
97 ret void
98 }
5499
55100 define i32* @test7(i32* %I, i64 %C, i64 %D) {
56101 %A = getelementptr i32* %I, i64 %C
256301 ret i32 %tmp.7
257302 ; CHECK-LABEL: @test20(
258303 ; CHECK: icmp eq i32 %A, 0
304 }
305
306 define i32 @test20_as1(i32 addrspace(1)* %P, i32 %A, i32 %B) {
307 %tmp.4 = getelementptr inbounds i32 addrspace(1)* %P, i32 %A
308 %tmp.6 = icmp eq i32 addrspace(1)* %tmp.4, %P
309 %tmp.7 = zext i1 %tmp.6 to i32
310 ret i32 %tmp.7
311 ; CHECK-LABEL: @test20_as1(
312 ; CHECK: icmp eq i16 %1, 0
259313 }
260314
261315