@@ -17,25 +17,123 @@ entry:
1717 ret ptr %arrayidx
1818}
1919
20- ; All offsets must be positive , so inbounds can be preserved.
21- define void @must_be_inbounds (ptr %dst , ptr %src , i32 %i ) {
20+ ; All indices must be non-negative , so inbounds can be preserved.
21+ define ptr @must_be_inbounds (ptr %p , i32 %i ) {
2222; CHECK-LABEL: @must_be_inbounds(
2323; CHECK-NEXT: entry:
2424; CHECK-NEXT: [[I_PROM:%.*]] = zext i32 [[I:%.*]] to i64
25- ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds float, ptr [[SRC:%.*]], i64 [[I_PROM]]
26- ; CHECK-NEXT: [[ARRAYIDX_SRC2:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 4
27- ; CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[ARRAYIDX_SRC2]], align 4
28- ; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds float, ptr [[DST:%.*]], i64 [[I_PROM]]
29- ; CHECK-NEXT: [[ARRAYIDX_DST4:%.*]] = getelementptr inbounds i8, ptr [[TMP2]], i64 4
30- ; CHECK-NEXT: store float [[TMP1]], ptr [[ARRAYIDX_DST4]], align 4
31- ; CHECK-NEXT: ret void
25+ ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[I_PROM]]
26+ ; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 4
27+ ; CHECK-NEXT: ret ptr [[ARRAYIDX2]]
3228;
3329entry:
3430 %i.prom = zext i32 %i to i64
3531 %idx = add nsw i64 %i.prom , 1
36- %arrayidx.src = getelementptr inbounds float , ptr %src , i64 %idx
37- %3 = load float , ptr %arrayidx.src , align 4
38- %arrayidx.dst = getelementptr inbounds float , ptr %dst , i64 %idx
39- store float %3 , ptr %arrayidx.dst , align 4
40- ret void
32+ %arrayidx = getelementptr inbounds i32 , ptr %p , i64 %idx
33+ ret ptr %arrayidx
34+ }
35+
36+ ; idx must be non-negative -> preserve inbounds
37+ define ptr @sign_bit_clear (ptr %p , i64 %i ) {
38+ ; CHECK-LABEL: @sign_bit_clear(
39+ ; CHECK-NEXT: entry:
40+ ; CHECK-NEXT: [[IDX:%.*]] = and i64 [[I:%.*]], 9223372036854775807
41+ ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[IDX]]
42+ ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 4
43+ ; CHECK-NEXT: ret ptr [[ARRAYIDX]]
44+ ;
45+ entry:
46+ %idx = and i64 %i , u0x7fffffffffffffff
47+ %idx.add = add i64 %idx , 1
48+ %arrayidx = getelementptr inbounds i32 , ptr %p , i64 %idx.add
49+ ret ptr %arrayidx
50+ }
51+
52+ ; idx may be negative -> don't preserve inbounds
53+ define ptr @sign_bit_not_clear (ptr %p , i64 %i ) {
54+ ; CHECK-LABEL: @sign_bit_not_clear(
55+ ; CHECK-NEXT: entry:
56+ ; CHECK-NEXT: [[IDX:%.*]] = and i64 [[I:%.*]], -256
57+ ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[IDX]]
58+ ; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr i8, ptr [[TMP0]], i64 4
59+ ; CHECK-NEXT: ret ptr [[ARRAYIDX2]]
60+ ;
61+ entry:
62+ %idx = and i64 %i , u0xffffffffffffff00
63+ %idx.add = add i64 %idx , 1
64+ %arrayidx = getelementptr inbounds i32 , ptr %p , i64 %idx.add
65+ ret ptr %arrayidx
66+ }
67+
68+ ; idx may be 0 or very negative -> don't preserve inbounds
69+ define ptr @only_sign_bit_not_clear (ptr %p , i64 %i ) {
70+ ; CHECK-LABEL: @only_sign_bit_not_clear(
71+ ; CHECK-NEXT: entry:
72+ ; CHECK-NEXT: [[IDX:%.*]] = and i64 [[I:%.*]], -9223372036854775808
73+ ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[IDX]]
74+ ; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr i8, ptr [[TMP0]], i64 4
75+ ; CHECK-NEXT: ret ptr [[ARRAYIDX2]]
76+ ;
77+ entry:
78+ %idx = and i64 %i , u0x8000000000000000
79+ %idx.add = add i64 %idx , 1
80+ %arrayidx = getelementptr inbounds i32 , ptr %p , i64 %idx.add
81+ ret ptr %arrayidx
82+ }
83+
84+ ; all indices non-negative -> preserve inbounds
85+ define ptr @multi_level_nonnegative (ptr %p , i64 %idx1 , i64 %idx2 ) {
86+ ; CHECK-LABEL: @multi_level_nonnegative(
87+ ; CHECK-NEXT: entry:
88+ ; CHECK-NEXT: [[MASKED_IDX1:%.*]] = and i64 [[IDX1:%.*]], 255
89+ ; CHECK-NEXT: [[MASKED_IDX2:%.*]] = and i64 [[IDX2:%.*]], 65535
90+ ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds [10 x [20 x i32]], ptr [[P:%.*]], i64 0, i64 [[MASKED_IDX1]], i64 [[MASKED_IDX2]]
91+ ; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 180
92+ ; CHECK-NEXT: ret ptr [[ARRAYIDX3]]
93+ ;
94+ entry:
95+ %masked.idx1 = and i64 %idx1 , u0xff
96+ %masked.idx2 = and i64 %idx2 , u0xffff
97+ %idx1.add = add i64 %masked.idx1 , 2
98+ %idx2.add = add i64 %masked.idx2 , 5
99+ %arrayidx = getelementptr inbounds [10 x [20 x i32 ]], ptr %p , i64 0 , i64 %idx1.add , i64 %idx2.add
100+ ret ptr %arrayidx
101+ }
102+
103+ ; It doesn't matter that %idx2.add might be negative, the indices in the resulting GEPs are all non-negative -> preserve inbounds
104+ define ptr @multi_level_mixed_okay (ptr %p , i64 %idx1 , i64 %idx2 ) {
105+ ; CHECK-LABEL: @multi_level_mixed_okay(
106+ ; CHECK-NEXT: entry:
107+ ; CHECK-NEXT: [[MASKED_IDX1:%.*]] = and i64 [[IDX1:%.*]], 255
108+ ; CHECK-NEXT: [[MASKED_IDX2:%.*]] = and i64 [[IDX2:%.*]], 65535
109+ ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds [10 x [20 x i32]], ptr [[P:%.*]], i64 0, i64 [[MASKED_IDX1]], i64 [[MASKED_IDX2]]
110+ ; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 156
111+ ; CHECK-NEXT: ret ptr [[ARRAYIDX3]]
112+ ;
113+ entry:
114+ %masked.idx1 = and i64 %idx1 , u0xff
115+ %masked.idx2 = and i64 %idx2 , u0xffff
116+ %idx1.add = add i64 %masked.idx1 , 2
117+ %idx2.add = add i64 %masked.idx2 , -1
118+ %arrayidx = getelementptr inbounds [10 x [20 x i32 ]], ptr %p , i64 0 , i64 %idx1.add , i64 %idx2.add
119+ ret ptr %arrayidx
120+ }
121+
122+ ; One index may be negative -> don't preserve inbounds
123+ define ptr @multi_level_mixed_not_okay (ptr %p , i64 %idx1 , i64 %idx2 ) {
124+ ; CHECK-LABEL: @multi_level_mixed_not_okay(
125+ ; CHECK-NEXT: entry:
126+ ; CHECK-NEXT: [[MASKED_IDX1:%.*]] = and i64 [[IDX1:%.*]], -256
127+ ; CHECK-NEXT: [[MASKED_IDX2:%.*]] = and i64 [[IDX2:%.*]], 65535
128+ ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr [10 x [20 x i32]], ptr [[P:%.*]], i64 0, i64 [[MASKED_IDX1]], i64 [[MASKED_IDX2]]
129+ ; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr i8, ptr [[TMP0]], i64 156
130+ ; CHECK-NEXT: ret ptr [[ARRAYIDX3]]
131+ ;
132+ entry:
133+ %masked.idx1 = and i64 %idx1 , u0xffffffffffffff00
134+ %masked.idx2 = and i64 %idx2 , u0xffff
135+ %idx1.add = add i64 %masked.idx1 , 2
136+ %idx2.add = add i64 %masked.idx2 , -1
137+ %arrayidx = getelementptr inbounds [10 x [20 x i32 ]], ptr %p , i64 0 , i64 %idx1.add , i64 %idx2.add
138+ ret ptr %arrayidx
41139}
0 commit comments