@@ -17,25 +17,123 @@ entry:
17
17
ret ptr %arrayidx
18
18
}
19
19
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 ) {
22
22
; CHECK-LABEL: @must_be_inbounds(
23
23
; CHECK-NEXT: entry:
24
24
; 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]]
32
28
;
33
29
entry:
34
30
%i.prom = zext i32 %i to i64
35
31
%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
41
139
}
0 commit comments