Skip to content

Commit fd81bd8

Browse files
authored
[ConstantFolding] Avoid use of isNonIntegralPointerType()
Avoiding any new inttoptr is unnecessarily restrictive for "plain" non-integral pointers, but it is important for unstable pointers and pointers with external state. Fixes another test codegen regression from #105735. Reviewed By: nikic Pull Request: #159959
1 parent cf7a97e commit fd81bd8

File tree

3 files changed

+152
-23
lines changed

3 files changed

+152
-23
lines changed

llvm/lib/Analysis/ConstantFolding.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -951,21 +951,21 @@ Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP,
951951

952952
// If the base value for this address is a literal integer value, fold the
953953
// getelementptr to the resulting integer value casted to the pointer type.
954-
APInt BasePtr(DL.getPointerTypeSizeInBits(Ptr->getType()), 0);
954+
APInt BaseIntVal(DL.getPointerTypeSizeInBits(Ptr->getType()), 0);
955955
if (auto *CE = dyn_cast<ConstantExpr>(Ptr)) {
956956
if (CE->getOpcode() == Instruction::IntToPtr) {
957957
if (auto *Base = dyn_cast<ConstantInt>(CE->getOperand(0)))
958-
BasePtr = Base->getValue().zextOrTrunc(BasePtr.getBitWidth());
958+
BaseIntVal = Base->getValue().zextOrTrunc(BaseIntVal.getBitWidth());
959959
}
960960
}
961961

962-
auto *PTy = cast<PointerType>(Ptr->getType());
963-
if ((Ptr->isNullValue() || BasePtr != 0) &&
964-
!DL.isNonIntegralPointerType(PTy)) {
962+
if ((Ptr->isNullValue() || BaseIntVal != 0) &&
963+
!DL.mustNotIntroduceIntToPtr(Ptr->getType())) {
964+
965965
// If the index size is smaller than the pointer size, add to the low
966966
// bits only.
967-
BasePtr.insertBits(BasePtr.trunc(BitWidth) + Offset, 0);
968-
Constant *C = ConstantInt::get(Ptr->getContext(), BasePtr);
967+
BaseIntVal.insertBits(BaseIntVal.trunc(BitWidth) + Offset, 0);
968+
Constant *C = ConstantInt::get(Ptr->getContext(), BaseIntVal);
969969
return ConstantExpr::getIntToPtr(C, ResTy);
970970
}
971971

llvm/test/Transforms/InstSimplify/ConstProp/inttoptr-gep-index-width.ll

Lines changed: 0 additions & 16 deletions
This file was deleted.
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt -S -passes=instsimplify < %s | FileCheck %s
3+
;; Check that we do not create new inttoptr instructions for unstable pointers
4+
;; or pointers with external state (even if the values are all constants).
5+
;; NOTE: for all but the zero address space, the GEP should only modify the
6+
;; low 8 bits of the pointer.
7+
target datalayout = "p:16:16:16:16-p1:16:16:16:8-pu2:16:16:16:8-pe3:16:16:16:8"
8+
9+
define ptr @test_null_base_normal() {
10+
; CHECK-LABEL: define ptr @test_null_base_normal() {
11+
; CHECK-NEXT: ret ptr inttoptr (i16 -2 to ptr)
12+
;
13+
%gep = getelementptr i8, ptr null, i8 -2
14+
ret ptr %gep
15+
}
16+
define ptr @test_inttoptr_base_normal() {
17+
; CHECK-LABEL: define ptr @test_inttoptr_base_normal() {
18+
; CHECK-NEXT: ret ptr null
19+
;
20+
%base = inttoptr i16 -1 to ptr
21+
%gep = getelementptr i8, ptr %base, i8 1
22+
ret ptr %gep
23+
}
24+
25+
;; Transformation is fine for non-integral address space, but we can only change
26+
;; the index bits: (i8 -2 == i16 254)
27+
define ptr addrspace(1) @test_null_base_nonintegral() {
28+
; CHECK-LABEL: define ptr addrspace(1) @test_null_base_nonintegral() {
29+
; CHECK-NEXT: ret ptr addrspace(1) inttoptr (i16 254 to ptr addrspace(1))
30+
;
31+
%gep = getelementptr i8, ptr addrspace(1) null, i8 -2
32+
ret ptr addrspace(1) %gep
33+
}
34+
define ptr addrspace(1) @test_inttoptr_base_nonintegral() {
35+
; CHECK-LABEL: define ptr addrspace(1) @test_inttoptr_base_nonintegral() {
36+
; CHECK-NEXT: ret ptr addrspace(1) inttoptr (i16 -256 to ptr addrspace(1))
37+
;
38+
%base = inttoptr i16 -1 to ptr addrspace(1)
39+
%gep = getelementptr i8, ptr addrspace(1) %base, i8 1
40+
ret ptr addrspace(1) %gep
41+
}
42+
43+
;; For unstable pointers we should avoid any introduction of inttoptr
44+
define ptr addrspace(2) @test_null_base_unstable() {
45+
; CHECK-LABEL: define ptr addrspace(2) @test_null_base_unstable() {
46+
; CHECK-NEXT: ret ptr addrspace(2) getelementptr (i8, ptr addrspace(2) null, i8 -2)
47+
;
48+
%gep = getelementptr i8, ptr addrspace(2) null, i8 -2
49+
ret ptr addrspace(2) %gep
50+
}
51+
define ptr addrspace(2) @test_inttoptr_base_unstable() {
52+
; CHECK-LABEL: define ptr addrspace(2) @test_inttoptr_base_unstable() {
53+
; CHECK-NEXT: ret ptr addrspace(2) getelementptr (i8, ptr addrspace(2) inttoptr (i16 -1 to ptr addrspace(2)), i8 1)
54+
;
55+
%base = inttoptr i16 -1 to ptr addrspace(2)
56+
%gep = getelementptr i8, ptr addrspace(2) %base, i8 1
57+
ret ptr addrspace(2) %gep
58+
}
59+
60+
;; The same is true for pointers with external state: no new inttoptr
61+
define ptr addrspace(3) @test_null_base_external() {
62+
; CHECK-LABEL: define ptr addrspace(3) @test_null_base_external() {
63+
; CHECK-NEXT: ret ptr addrspace(3) getelementptr (i8, ptr addrspace(3) null, i8 -2)
64+
;
65+
%gep = getelementptr i8, ptr addrspace(3) null, i8 -2
66+
ret ptr addrspace(3) %gep
67+
}
68+
69+
define ptr addrspace(3) @test_inttoptr_base_external() {
70+
; CHECK-LABEL: define ptr addrspace(3) @test_inttoptr_base_external() {
71+
; CHECK-NEXT: ret ptr addrspace(3) getelementptr (i8, ptr addrspace(3) inttoptr (i16 -1 to ptr addrspace(3)), i8 1)
72+
;
73+
%base = inttoptr i16 -1 to ptr addrspace(3)
74+
%gep = getelementptr i8, ptr addrspace(3) %base, i8 1
75+
ret ptr addrspace(3) %gep
76+
}
77+
78+
define <2 x ptr> @test_vec_null_base_normal() {
79+
; CHECK-LABEL: define <2 x ptr> @test_vec_null_base_normal() {
80+
; CHECK-NEXT: ret <2 x ptr> getelementptr (i8, <2 x ptr> zeroinitializer, <2 x i16> <i16 -2, i16 -3>)
81+
;
82+
%gep = getelementptr i8, <2 x ptr> <ptr null, ptr null>, <2 x i8> <i8 -2, i8 -3>
83+
ret <2 x ptr> %gep
84+
}
85+
define <2 x ptr> @test_vec_inttoptr_base_normal() {
86+
; CHECK-LABEL: define <2 x ptr> @test_vec_inttoptr_base_normal() {
87+
; CHECK-NEXT: ret <2 x ptr> getelementptr (i8, <2 x ptr> <ptr inttoptr (i16 -1 to ptr), ptr inttoptr (i16 -2 to ptr)>, <2 x i16> <i16 1, i16 2>)
88+
;
89+
%base = inttoptr <2 x i16> <i16 -1, i16 -2> to <2 x ptr>
90+
%gep = getelementptr i8, <2 x ptr> %base, <2 x i8> <i8 1, i8 2>
91+
ret <2 x ptr> %gep
92+
}
93+
94+
;; Transformation is fine for non-integral address space, but we can only change
95+
;; the index bits: (i8 -2 == i16 254)
96+
define <2 x ptr addrspace(1)> @test_vec_null_base_nonintegral() {
97+
; CHECK-LABEL: define <2 x ptr addrspace(1)> @test_vec_null_base_nonintegral() {
98+
; CHECK-NEXT: ret <2 x ptr addrspace(1)> getelementptr (i8, <2 x ptr addrspace(1)> zeroinitializer, <2 x i8> <i8 -2, i8 -3>)
99+
;
100+
%gep = getelementptr i8, <2 x ptr addrspace(1)> <ptr addrspace(1) null, ptr addrspace(1) null>, <2 x i8> <i8 -2, i8 -3>
101+
ret <2 x ptr addrspace(1)> %gep
102+
}
103+
define <2 x ptr addrspace(1)> @test_vec_inttoptr_base_nonintegral() {
104+
; CHECK-LABEL: define <2 x ptr addrspace(1)> @test_vec_inttoptr_base_nonintegral() {
105+
; CHECK-NEXT: ret <2 x ptr addrspace(1)> getelementptr (i8, <2 x ptr addrspace(1)> <ptr addrspace(1) inttoptr (i16 -1 to ptr addrspace(1)), ptr addrspace(1) inttoptr (i16 -2 to ptr addrspace(1))>, <2 x i8> <i8 1, i8 2>)
106+
;
107+
%base = inttoptr <2 x i16> <i16 -1, i16 -2> to <2 x ptr addrspace(1)>
108+
%gep = getelementptr i8, <2 x ptr addrspace(1)> %base, <2 x i8> <i8 1, i8 2>
109+
ret <2 x ptr addrspace(1)> %gep
110+
}
111+
112+
;; For unstable pointers we should avoid any introduction of inttoptr
113+
define <2 x ptr addrspace(2)> @test_vec_null_base_unstable() {
114+
; CHECK-LABEL: define <2 x ptr addrspace(2)> @test_vec_null_base_unstable() {
115+
; CHECK-NEXT: ret <2 x ptr addrspace(2)> getelementptr (i8, <2 x ptr addrspace(2)> zeroinitializer, <2 x i8> <i8 -2, i8 -3>)
116+
;
117+
%gep = getelementptr i8, <2 x ptr addrspace(2)> <ptr addrspace(2) null, ptr addrspace(2) null>, <2 x i8> <i8 -2, i8 -3>
118+
ret <2 x ptr addrspace(2)> %gep
119+
}
120+
define <2 x ptr addrspace(2)> @test_vec_inttoptr_base_unstable() {
121+
; CHECK-LABEL: define <2 x ptr addrspace(2)> @test_vec_inttoptr_base_unstable() {
122+
; CHECK-NEXT: ret <2 x ptr addrspace(2)> getelementptr (i8, <2 x ptr addrspace(2)> <ptr addrspace(2) inttoptr (i16 -1 to ptr addrspace(2)), ptr addrspace(2) inttoptr (i16 -2 to ptr addrspace(2))>, <2 x i8> <i8 1, i8 2>)
123+
;
124+
%base = inttoptr <2 x i16> <i16 -1, i16 -2> to <2 x ptr addrspace(2)>
125+
%gep = getelementptr i8, <2 x ptr addrspace(2)> %base, <2 x i8> <i8 1, i8 2>
126+
ret <2 x ptr addrspace(2)> %gep
127+
}
128+
129+
;; The same is true for pointers with external state: no new inttoptr
130+
define <2 x ptr addrspace(3)> @test_vec_null_base_external() {
131+
; CHECK-LABEL: define <2 x ptr addrspace(3)> @test_vec_null_base_external() {
132+
; CHECK-NEXT: ret <2 x ptr addrspace(3)> getelementptr (i8, <2 x ptr addrspace(3)> zeroinitializer, <2 x i8> <i8 -2, i8 -3>)
133+
;
134+
%gep = getelementptr i8, <2 x ptr addrspace(3)> <ptr addrspace(3) null, ptr addrspace(3) null>, <2 x i8> <i8 -2, i8 -3>
135+
ret <2 x ptr addrspace(3)> %gep
136+
}
137+
138+
define <2 x ptr addrspace(3)> @test_vec_inttoptr_base_external() {
139+
; CHECK-LABEL: define <2 x ptr addrspace(3)> @test_vec_inttoptr_base_external() {
140+
; CHECK-NEXT: ret <2 x ptr addrspace(3)> getelementptr (i8, <2 x ptr addrspace(3)> <ptr addrspace(3) inttoptr (i16 -1 to ptr addrspace(3)), ptr addrspace(3) inttoptr (i16 -2 to ptr addrspace(3))>, <2 x i8> <i8 1, i8 2>)
141+
;
142+
%base = inttoptr <2 x i16> <i16 -1, i16 -2> to <2 x ptr addrspace(3)>
143+
%gep = getelementptr i8, <2 x ptr addrspace(3)> %base, <2 x i8> <i8 1, i8 2>
144+
ret <2 x ptr addrspace(3)> %gep
145+
}

0 commit comments

Comments
 (0)