@@ -117,3 +117,179 @@ if.end:
117117 %size = call i64 @llvm.objectsize.i64.p0 (ptr %p , i1 true , i1 true , i1 false )
118118 ret i64 %size
119119}
120+
121+ define i64 @pick_negative_offset (i32 %n ) {
122+ ; CHECK-LABEL: @pick_negative_offset(
123+ ; CHECK-NEXT: entry:
124+ ; CHECK-NEXT: [[BUFFER0:%.*]] = alloca i8, i64 20, align 1
125+ ; CHECK-NEXT: [[OFFSETED0:%.*]] = getelementptr i8, ptr [[BUFFER0]], i64 20
126+ ; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[N:%.*]], 0
127+ ; CHECK-NEXT: br i1 [[COND]], label [[IF_ELSE:%.*]], label [[IF_END:%.*]]
128+ ; CHECK: if.else:
129+ ; CHECK-NEXT: [[BUFFER1:%.*]] = alloca i8, i64 20, align 1
130+ ; CHECK-NEXT: [[OFFSETED1:%.*]] = getelementptr i8, ptr [[BUFFER1]], i64 20
131+ ; CHECK-NEXT: br label [[IF_END]]
132+ ; CHECK: if.end:
133+ ; CHECK-NEXT: [[P:%.*]] = phi ptr [ [[OFFSETED1]], [[IF_ELSE]] ], [ [[OFFSETED0]], [[ENTRY:%.*]] ]
134+ ; CHECK-NEXT: [[POFFSETED:%.*]] = getelementptr i8, ptr [[P]], i64 -4
135+ ; CHECK-NEXT: ret i64 4
136+ ;
137+ entry:
138+ %buffer0 = alloca i8 , i64 20
139+ %offseted0 = getelementptr i8 , ptr %buffer0 , i64 20
140+ %cond = icmp eq i32 %n , 0
141+ br i1 %cond , label %if.else , label %if.end
142+
143+ if.else:
144+ %buffer1 = alloca i8 , i64 20
145+ %offseted1 = getelementptr i8 , ptr %buffer1 , i64 20
146+ br label %if.end
147+
148+ if.end:
149+ %p = phi ptr [ %offseted1 , %if.else ], [ %offseted0 , %entry ]
150+ %poffseted = getelementptr i8 , ptr %p , i64 -4
151+ %size = call i64 @llvm.objectsize.i64.p0 (ptr %poffseted , i1 false , i1 false , i1 false )
152+ ret i64 %size
153+ }
154+
155+ define i64 @pick_negative_offset_with_nullptr (i32 %n ) {
156+ ; CHECK-LABEL: @pick_negative_offset_with_nullptr(
157+ ; CHECK-NEXT: entry:
158+ ; CHECK-NEXT: [[BUFFER0:%.*]] = alloca i8, i64 20, align 1
159+ ; CHECK-NEXT: [[OFFSETED0:%.*]] = getelementptr i8, ptr [[BUFFER0]], i64 20
160+ ; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[N:%.*]], 0
161+ ; CHECK-NEXT: br i1 [[COND]], label [[IF_ELSE:%.*]], label [[IF_END:%.*]]
162+ ; CHECK: if.else:
163+ ; CHECK-NEXT: br label [[IF_END]]
164+ ; CHECK: if.end:
165+ ; CHECK-NEXT: [[P0:%.*]] = phi ptr [ [[OFFSETED0]], [[ENTRY:%.*]] ], [ null, [[IF_ELSE]] ]
166+ ; CHECK-NEXT: [[P1:%.*]] = phi ptr [ null, [[IF_ELSE]] ], [ [[OFFSETED0]], [[ENTRY]] ]
167+ ; CHECK-NEXT: [[P0OFFSETED:%.*]] = getelementptr i8, ptr [[P0]], i64 -4
168+ ; CHECK-NEXT: [[P1OFFSETED:%.*]] = getelementptr i8, ptr [[P1]], i64 -4
169+ ; CHECK-NEXT: ret i64 4
170+ ;
171+ entry:
172+ %buffer0 = alloca i8 , i64 20
173+ %offseted0 = getelementptr i8 , ptr %buffer0 , i64 20
174+ %cond = icmp eq i32 %n , 0
175+ br i1 %cond , label %if.else , label %if.end
176+
177+ if.else:
178+ br label %if.end
179+
180+ if.end:
181+ %p0 = phi ptr [ %offseted0 , %entry ], [ null , %if.else ]
182+ %p1 = phi ptr [ null , %if.else ], [ %offseted0 , %entry ]
183+ %p0offseted = getelementptr i8 , ptr %p0 , i64 -4
184+ %p1offseted = getelementptr i8 , ptr %p1 , i64 -4
185+ %size0 = call i64 @llvm.objectsize.i64.p0 (ptr %p0offseted , i1 false , i1 false , i1 false )
186+ %size1 = call i64 @llvm.objectsize.i64.p0 (ptr %p1offseted , i1 false , i1 false , i1 false )
187+ %size = select i1 %cond , i64 %size0 , i64 %size1
188+ ret i64 %size
189+ }
190+
191+ define i64 @pick_negative_offset_with_unsized_nullptr (i32 %n ) {
192+ ; CHECK-LABEL: @pick_negative_offset_with_unsized_nullptr(
193+ ; CHECK-NEXT: entry:
194+ ; CHECK-NEXT: [[BUFFER0:%.*]] = alloca i8, i64 20, align 1
195+ ; CHECK-NEXT: [[OFFSETED0:%.*]] = getelementptr i8, ptr [[BUFFER0]], i64 20
196+ ; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[N:%.*]], 0
197+ ; CHECK-NEXT: br i1 [[COND]], label [[IF_ELSE:%.*]], label [[IF_END:%.*]]
198+ ; CHECK: if.else:
199+ ; CHECK-NEXT: br label [[IF_END]]
200+ ; CHECK: if.end:
201+ ; CHECK-NEXT: [[P0:%.*]] = phi ptr [ [[OFFSETED0]], [[ENTRY:%.*]] ], [ null, [[IF_ELSE]] ]
202+ ; CHECK-NEXT: [[P1:%.*]] = phi ptr [ null, [[IF_ELSE]] ], [ [[OFFSETED0]], [[ENTRY]] ]
203+ ; CHECK-NEXT: [[P0OFFSETED:%.*]] = getelementptr i8, ptr [[P0]], i64 -4
204+ ; CHECK-NEXT: [[P1OFFSETED:%.*]] = getelementptr i8, ptr [[P1]], i64 -4
205+ ; CHECK-NEXT: ret i64 -1
206+ ;
207+ entry:
208+ %buffer0 = alloca i8 , i64 20
209+ %offseted0 = getelementptr i8 , ptr %buffer0 , i64 20
210+ %cond = icmp eq i32 %n , 0
211+ br i1 %cond , label %if.else , label %if.end
212+
213+ if.else:
214+ br label %if.end
215+
216+ if.end:
217+ %p0 = phi ptr [ %offseted0 , %entry ], [ null , %if.else ]
218+ %p1 = phi ptr [ null , %if.else ], [ %offseted0 , %entry ]
219+ %p0offseted = getelementptr i8 , ptr %p0 , i64 -4
220+ %p1offseted = getelementptr i8 , ptr %p1 , i64 -4
221+ %size0 = call i64 @llvm.objectsize.i64.p0 (ptr %p0offseted , i1 false , i1 true , i1 false )
222+ %size1 = call i64 @llvm.objectsize.i64.p0 (ptr %p1offseted , i1 false , i1 true , i1 false )
223+ %size = select i1 %cond , i64 %size0 , i64 %size1
224+ ret i64 %size
225+ }
226+
227+ define i64 @chain_pick_negative_offset_with_nullptr (i32 %x ) {
228+ ; CHECK-LABEL: @chain_pick_negative_offset_with_nullptr(
229+ ; CHECK-NEXT: entry:
230+ ; CHECK-NEXT: [[ARRAY:%.*]] = alloca [4 x i32], align 4
231+ ; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X:%.*]], 0
232+ ; CHECK-NEXT: [[P:%.*]] = getelementptr i8, ptr [[ARRAY]], i64 8
233+ ; CHECK-NEXT: [[COND:%.*]] = select i1 [[C]], ptr [[P]], ptr null
234+ ; CHECK-NEXT: [[P4:%.*]] = getelementptr i8, ptr [[COND]], i64 8
235+ ; CHECK-NEXT: [[COND6:%.*]] = select i1 [[C]], ptr [[P4]], ptr null
236+ ; CHECK-NEXT: [[P7:%.*]] = getelementptr i8, ptr [[COND6]], i64 -4
237+ ; CHECK-NEXT: ret i64 4
238+ ;
239+ entry:
240+ %array = alloca [4 x i32 ]
241+ %c = icmp eq i32 %x , 0
242+ %p = getelementptr i8 , ptr %array , i64 8
243+ %cond = select i1 %c , ptr %p , ptr null
244+ %p4 = getelementptr i8 , ptr %cond , i64 8
245+ %cond6 = select i1 %c , ptr %p4 , ptr null
246+ %p7 = getelementptr i8 , ptr %cond6 , i64 -4
247+ %size = call i64 @llvm.objectsize.i64.p0 (ptr %p7 , i1 false , i1 false , i1 false )
248+ ret i64 %size
249+ }
250+
251+
252+ define i64 @negative_offset_dynamic_eval (i32 %x , i64 %i ) {
253+ ; CHECK-LABEL: @negative_offset_dynamic_eval(
254+ ; CHECK-NEXT: entry:
255+ ; CHECK-NEXT: [[ARRAY1:%.*]] = alloca [4 x i32], align 16
256+ ; CHECK-NEXT: [[ARRAY2:%.*]] = alloca [8 x i32], align 16
257+ ; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[X:%.*]], 0
258+ ; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]
259+ ; CHECK: if.then:
260+ ; CHECK-NEXT: br label [[IF_END:%.*]]
261+ ; CHECK: if.else:
262+ ; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[ARRAY2]], i64 16
263+ ; CHECK-NEXT: br label [[IF_END]]
264+ ; CHECK: if.end:
265+ ; CHECK-NEXT: [[PTR:%.*]] = phi ptr [ [[ARRAY1]], [[IF_THEN]] ], [ [[ADD_PTR]], [[IF_ELSE]] ]
266+ ; CHECK-NEXT: [[ADD_PTR2_IDX:%.*]] = mul i64 [[I:%.*]], 4
267+ ; CHECK-NEXT: [[TMP0:%.*]] = add i64 16, [[ADD_PTR2_IDX]]
268+ ; CHECK-NEXT: [[ADD_PTR2:%.*]] = getelementptr inbounds i32, ptr [[PTR]], i64 [[I]]
269+ ; CHECK-NEXT: [[TMP1:%.*]] = sub i64 32, [[TMP0]]
270+ ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i64 32, [[TMP0]]
271+ ; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i64 0, i64 [[TMP1]]
272+ ; CHECK-NEXT: [[TMP4:%.*]] = icmp ne i64 [[TMP3]], -1
273+ ; CHECK-NEXT: call void @llvm.assume(i1 [[TMP4]])
274+ ; CHECK-NEXT: ret i64 [[TMP3]]
275+ ;
276+ entry:
277+ %array1 = alloca [4 x i32 ], align 16
278+ %array2 = alloca [8 x i32 ], align 16
279+ %tobool.not = icmp eq i32 %x , 0
280+ br i1 %tobool.not , label %if.else , label %if.then
281+
282+ if.then:
283+ br label %if.end
284+
285+ if.else:
286+ %add.ptr = getelementptr inbounds i8 , ptr %array2 , i64 16
287+ br label %if.end
288+
289+ if.end:
290+ %ptr = phi ptr [ %array1 , %if.then ], [ %add.ptr , %if.else ]
291+ %add.ptr2 = getelementptr inbounds i32 , ptr %ptr , i64 %i
292+ %objsize = call i64 @llvm.objectsize.i64.p0 (ptr %add.ptr2 , i1 false , i1 true , i1 true )
293+ ret i64 %objsize
294+ }
295+
0 commit comments