@@ -3176,6 +3176,216 @@ define internal i32 @recSimplify2() {
3176
3176
ret i32 %r
3177
3177
}
3178
3178
3179
+ ; TODO: Verify we do not return 10.
3180
+ define i32 @may_access_after_return (i32 noundef %N , i32 noundef %M ) {
3181
+ ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
3182
+ ; TUNIT-LABEL: define {{[^@]+}}@may_access_after_return
3183
+ ; TUNIT-SAME: (i32 noundef [[N:%.*]], i32 noundef [[M:%.*]]) #[[ATTR4]] {
3184
+ ; TUNIT-NEXT: entry:
3185
+ ; TUNIT-NEXT: [[A:%.*]] = alloca i32, align 4
3186
+ ; TUNIT-NEXT: [[B:%.*]] = alloca i32, align 4
3187
+ ; TUNIT-NEXT: call void @write_both(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[A]], ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[B]]) #[[ATTR18]]
3188
+ ; TUNIT-NEXT: ret i32 10
3189
+ ;
3190
+ ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
3191
+ ; CGSCC-LABEL: define {{[^@]+}}@may_access_after_return
3192
+ ; CGSCC-SAME: (i32 noundef [[N:%.*]], i32 noundef [[M:%.*]]) #[[ATTR16]] {
3193
+ ; CGSCC-NEXT: entry:
3194
+ ; CGSCC-NEXT: [[A:%.*]] = alloca i32, align 4
3195
+ ; CGSCC-NEXT: [[B:%.*]] = alloca i32, align 4
3196
+ ; CGSCC-NEXT: call void @write_both(ptr noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[A]], ptr noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[B]]) #[[ATTR21]]
3197
+ ; CGSCC-NEXT: [[TMP0:%.*]] = load i32, ptr [[A]], align 4
3198
+ ; CGSCC-NEXT: [[TMP1:%.*]] = load i32, ptr [[B]], align 4
3199
+ ; CGSCC-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP0]], [[TMP1]]
3200
+ ; CGSCC-NEXT: ret i32 [[ADD]]
3201
+ ;
3202
+ entry:
3203
+ %A = alloca i32 , align 4
3204
+ %B = alloca i32 , align 4
3205
+ %call = call ptr @passthrough (ptr noundef %A )
3206
+ %call1 = call ptr @passthrough (ptr noundef %B )
3207
+ call void @write_both (ptr noundef %call , ptr noundef %call1 )
3208
+ %0 = load i32 , ptr %A , align 4
3209
+ %1 = load i32 , ptr %B , align 4
3210
+ %add = add nsw i32 %0 , %1
3211
+ ret i32 %add
3212
+ }
3213
+
3214
+ define internal void @write_both (ptr noundef %Q , ptr noundef %R ) {
3215
+ ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
3216
+ ; CHECK-LABEL: define {{[^@]+}}@write_both
3217
+ ; CHECK-SAME: (ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[Q:%.*]], ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[R:%.*]]) #[[ATTR0]] {
3218
+ ; CHECK-NEXT: entry:
3219
+ ; CHECK-NEXT: store i32 3, ptr [[Q]], align 4
3220
+ ; CHECK-NEXT: store i32 5, ptr [[R]], align 4
3221
+ ; CHECK-NEXT: ret void
3222
+ ;
3223
+ entry:
3224
+ store i32 3 , ptr %Q , align 4
3225
+ store i32 5 , ptr %R , align 4
3226
+ ret void
3227
+ }
3228
+
3229
+ define internal ptr @passthrough (ptr noundef %P ) {
3230
+ ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
3231
+ ; CGSCC-LABEL: define {{[^@]+}}@passthrough
3232
+ ; CGSCC-SAME: (ptr noalias nofree noundef nonnull readnone returned align 4 dereferenceable(4) "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR4]] {
3233
+ ; CGSCC-NEXT: entry:
3234
+ ; CGSCC-NEXT: ret ptr [[P]]
3235
+ ;
3236
+ entry:
3237
+ ret ptr %P
3238
+ }
3239
+
3240
+ ; TODO: Verify we do not return 10.
3241
+ define i32 @may_access_after_return_choice (i32 noundef %N , i32 noundef %M , i1 %c ) {
3242
+ ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
3243
+ ; TUNIT-LABEL: define {{[^@]+}}@may_access_after_return_choice
3244
+ ; TUNIT-SAME: (i32 noundef [[N:%.*]], i32 noundef [[M:%.*]], i1 [[C:%.*]]) #[[ATTR4]] {
3245
+ ; TUNIT-NEXT: entry:
3246
+ ; TUNIT-NEXT: [[A:%.*]] = alloca i32, align 4
3247
+ ; TUNIT-NEXT: [[B:%.*]] = alloca i32, align 4
3248
+ ; TUNIT-NEXT: [[CALL:%.*]] = call nonnull align 4 dereferenceable(4) ptr @passthrough_choice(i1 [[C]], ptr noalias nofree noundef nonnull readnone align 4 dereferenceable(4) "no-capture-maybe-returned" [[A]], ptr noalias nofree noundef nonnull readnone align 4 dereferenceable(4) "no-capture-maybe-returned" [[B]]) #[[ATTR23:[0-9]+]]
3249
+ ; TUNIT-NEXT: [[CALL1:%.*]] = call nonnull align 4 dereferenceable(4) ptr @passthrough_choice(i1 [[C]], ptr noalias nofree noundef nonnull readnone align 4 dereferenceable(4) "no-capture-maybe-returned" [[B]], ptr noalias nofree noundef nonnull readnone align 4 dereferenceable(4) "no-capture-maybe-returned" [[A]]) #[[ATTR23]]
3250
+ ; TUNIT-NEXT: call void @write_both(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[CALL]], ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[CALL1]]) #[[ATTR18]]
3251
+ ; TUNIT-NEXT: ret i32 10
3252
+ ;
3253
+ ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn
3254
+ ; CGSCC-LABEL: define {{[^@]+}}@may_access_after_return_choice
3255
+ ; CGSCC-SAME: (i32 noundef [[N:%.*]], i32 noundef [[M:%.*]], i1 [[C:%.*]]) #[[ATTR3]] {
3256
+ ; CGSCC-NEXT: entry:
3257
+ ; CGSCC-NEXT: [[A:%.*]] = alloca i32, align 4
3258
+ ; CGSCC-NEXT: [[B:%.*]] = alloca i32, align 4
3259
+ ; CGSCC-NEXT: [[CALL:%.*]] = call nonnull align 4 dereferenceable(4) ptr @passthrough_choice(i1 [[C]], ptr noalias nofree noundef nonnull readnone align 4 dereferenceable(4) [[A]], ptr noalias nofree noundef nonnull readnone align 4 dereferenceable(4) [[B]]) #[[ATTR28:[0-9]+]]
3260
+ ; CGSCC-NEXT: [[CALL1:%.*]] = call nonnull align 4 dereferenceable(4) ptr @passthrough_choice(i1 [[C]], ptr noalias nofree noundef nonnull readnone align 4 dereferenceable(4) [[B]], ptr noalias nofree noundef nonnull readnone align 4 dereferenceable(4) [[A]]) #[[ATTR28]]
3261
+ ; CGSCC-NEXT: call void @write_both(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[CALL]], ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[CALL1]]) #[[ATTR21]]
3262
+ ; CGSCC-NEXT: [[TMP0:%.*]] = load i32, ptr [[A]], align 4
3263
+ ; CGSCC-NEXT: [[TMP1:%.*]] = load i32, ptr [[B]], align 4
3264
+ ; CGSCC-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP0]], [[TMP1]]
3265
+ ; CGSCC-NEXT: ret i32 [[ADD]]
3266
+ ;
3267
+ entry:
3268
+ %A = alloca i32 , align 4
3269
+ %B = alloca i32 , align 4
3270
+ %call = call ptr @passthrough_choice (i1 %c , ptr noundef %A , ptr noundef %B )
3271
+ %call1 = call ptr @passthrough_choice (i1 %c , ptr noundef %B , ptr noundef %A )
3272
+ call void @write_both (ptr noundef %call , ptr noundef %call1 )
3273
+ %0 = load i32 , ptr %A , align 4
3274
+ %1 = load i32 , ptr %B , align 4
3275
+ %add = add nsw i32 %0 , %1
3276
+ ret i32 %add
3277
+ }
3278
+
3279
+ define internal ptr @passthrough_choice (i1 %c , ptr noundef %P , ptr noundef %Q ) {
3280
+ ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
3281
+ ; CHECK-LABEL: define {{[^@]+}}@passthrough_choice
3282
+ ; CHECK-SAME: (i1 [[C:%.*]], ptr noalias nofree noundef nonnull readnone align 4 dereferenceable(4) "no-capture-maybe-returned" [[P:%.*]], ptr noalias nofree noundef nonnull readnone align 4 dereferenceable(4) "no-capture-maybe-returned" [[Q:%.*]]) #[[ATTR4]] {
3283
+ ; CHECK-NEXT: entry:
3284
+ ; CHECK-NEXT: [[R:%.*]] = select i1 [[C]], ptr [[P]], ptr [[Q]]
3285
+ ; CHECK-NEXT: ret ptr [[R]]
3286
+ ;
3287
+ entry:
3288
+ %R = select i1 %c , ptr %P , ptr %Q
3289
+ ret ptr %R
3290
+ }
3291
+
3292
+ ; TODO: Verify we do not return 10.
3293
+ define i32 @may_access_after_return_no_choice1 (i32 noundef %N , i32 noundef %M ) {
3294
+ ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
3295
+ ; TUNIT-LABEL: define {{[^@]+}}@may_access_after_return_no_choice1
3296
+ ; TUNIT-SAME: (i32 noundef [[N:%.*]], i32 noundef [[M:%.*]]) #[[ATTR4]] {
3297
+ ; TUNIT-NEXT: entry:
3298
+ ; TUNIT-NEXT: [[A:%.*]] = alloca i32, align 4
3299
+ ; TUNIT-NEXT: [[B:%.*]] = alloca i32, align 4
3300
+ ; TUNIT-NEXT: call void @write_both(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[A]], ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[B]]) #[[ATTR18]]
3301
+ ; TUNIT-NEXT: ret i32 10
3302
+ ;
3303
+ ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
3304
+ ; CGSCC-LABEL: define {{[^@]+}}@may_access_after_return_no_choice1
3305
+ ; CGSCC-SAME: (i32 noundef [[N:%.*]], i32 noundef [[M:%.*]]) #[[ATTR16]] {
3306
+ ; CGSCC-NEXT: entry:
3307
+ ; CGSCC-NEXT: [[A:%.*]] = alloca i32, align 4
3308
+ ; CGSCC-NEXT: [[B:%.*]] = alloca i32, align 4
3309
+ ; CGSCC-NEXT: call void @write_both(ptr noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[A]], ptr noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[B]]) #[[ATTR21]]
3310
+ ; CGSCC-NEXT: [[TMP0:%.*]] = load i32, ptr [[A]], align 4
3311
+ ; CGSCC-NEXT: [[TMP1:%.*]] = load i32, ptr [[B]], align 4
3312
+ ; CGSCC-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP0]], [[TMP1]]
3313
+ ; CGSCC-NEXT: ret i32 [[ADD]]
3314
+ ;
3315
+ entry:
3316
+ %A = alloca i32 , align 4
3317
+ %B = alloca i32 , align 4
3318
+ %call = call ptr @passthrough_no_choice_true (i1 true , ptr noundef %A , ptr noundef %B )
3319
+ %call1 = call ptr @passthrough_no_choice_true (i1 true , ptr noundef %B , ptr noundef %A )
3320
+ call void @write_both (ptr noundef %call , ptr noundef %call1 )
3321
+ %0 = load i32 , ptr %A , align 4
3322
+ %1 = load i32 , ptr %B , align 4
3323
+ %add = add nsw i32 %0 , %1
3324
+ ret i32 %add
3325
+ }
3326
+
3327
+ ; TODO: Verify we do not return 10.
3328
+ define i32 @may_access_after_return_no_choice2 (i32 noundef %N , i32 noundef %M ) {
3329
+ ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
3330
+ ; TUNIT-LABEL: define {{[^@]+}}@may_access_after_return_no_choice2
3331
+ ; TUNIT-SAME: (i32 noundef [[N:%.*]], i32 noundef [[M:%.*]]) #[[ATTR4]] {
3332
+ ; TUNIT-NEXT: entry:
3333
+ ; TUNIT-NEXT: [[A:%.*]] = alloca i32, align 4
3334
+ ; TUNIT-NEXT: [[B:%.*]] = alloca i32, align 4
3335
+ ; TUNIT-NEXT: call void @write_both(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[B]], ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[A]]) #[[ATTR18]]
3336
+ ; TUNIT-NEXT: ret i32 10
3337
+ ;
3338
+ ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
3339
+ ; CGSCC-LABEL: define {{[^@]+}}@may_access_after_return_no_choice2
3340
+ ; CGSCC-SAME: (i32 noundef [[N:%.*]], i32 noundef [[M:%.*]]) #[[ATTR16]] {
3341
+ ; CGSCC-NEXT: entry:
3342
+ ; CGSCC-NEXT: [[A:%.*]] = alloca i32, align 4
3343
+ ; CGSCC-NEXT: [[B:%.*]] = alloca i32, align 4
3344
+ ; CGSCC-NEXT: call void @write_both(ptr noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[B]], ptr noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[A]]) #[[ATTR21]]
3345
+ ; CGSCC-NEXT: [[TMP0:%.*]] = load i32, ptr [[A]], align 4
3346
+ ; CGSCC-NEXT: [[TMP1:%.*]] = load i32, ptr [[B]], align 4
3347
+ ; CGSCC-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP0]], [[TMP1]]
3348
+ ; CGSCC-NEXT: ret i32 [[ADD]]
3349
+ ;
3350
+ entry:
3351
+ %A = alloca i32 , align 4
3352
+ %B = alloca i32 , align 4
3353
+ %call = call ptr @passthrough_no_choice_false (i1 false , ptr noundef %A , ptr noundef %B )
3354
+ %call1 = call ptr @passthrough_no_choice_false (i1 false , ptr noundef %B , ptr noundef %A )
3355
+ call void @write_both (ptr noundef %call , ptr noundef %call1 )
3356
+ %0 = load i32 , ptr %A , align 4
3357
+ %1 = load i32 , ptr %B , align 4
3358
+ %add = add nsw i32 %0 , %1
3359
+ ret i32 %add
3360
+ }
3361
+
3362
+ define internal ptr @passthrough_no_choice_true (i1 %c , ptr noundef %P , ptr noundef %Q ) {
3363
+ ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
3364
+ ; CGSCC-LABEL: define {{[^@]+}}@passthrough_no_choice_true
3365
+ ; CGSCC-SAME: (ptr noalias nofree noundef nonnull readnone returned align 4 dereferenceable(4) "no-capture-maybe-returned" [[P:%.*]], i32 [[TMP0:%.*]]) #[[ATTR4]] {
3366
+ ; CGSCC-NEXT: entry:
3367
+ ; CGSCC-NEXT: [[Q_PRIV:%.*]] = alloca i32, align 4
3368
+ ; CGSCC-NEXT: store i32 [[TMP0]], ptr [[Q_PRIV]], align 4
3369
+ ; CGSCC-NEXT: ret ptr [[P]]
3370
+ ;
3371
+ entry:
3372
+ %R = select i1 %c , ptr %P , ptr %Q
3373
+ ret ptr %R
3374
+ }
3375
+ define internal ptr @passthrough_no_choice_false (i1 %c , ptr noundef %P , ptr noundef %Q ) {
3376
+ ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
3377
+ ; CGSCC-LABEL: define {{[^@]+}}@passthrough_no_choice_false
3378
+ ; CGSCC-SAME: (i32 [[TMP0:%.*]], ptr noalias nofree noundef nonnull readnone returned align 4 dereferenceable(4) "no-capture-maybe-returned" [[Q:%.*]]) #[[ATTR4]] {
3379
+ ; CGSCC-NEXT: entry:
3380
+ ; CGSCC-NEXT: [[P_PRIV:%.*]] = alloca i32, align 4
3381
+ ; CGSCC-NEXT: store i32 [[TMP0]], ptr [[P_PRIV]], align 4
3382
+ ; CGSCC-NEXT: ret ptr [[Q]]
3383
+ ;
3384
+ entry:
3385
+ %R = select i1 %c , ptr %P , ptr %Q
3386
+ ret ptr %R
3387
+ }
3388
+
3179
3389
declare void @llvm.assume (i1 noundef)
3180
3390
3181
3391
@@ -3238,6 +3448,7 @@ declare void @llvm.assume(i1 noundef)
3238
3448
; TUNIT: attributes #[[ATTR20]] = { norecurse }
3239
3449
; TUNIT: attributes #[[ATTR21]] = { nounwind }
3240
3450
; TUNIT: attributes #[[ATTR22]] = { nofree nosync nounwind willreturn }
3451
+ ; TUNIT: attributes #[[ATTR23]] = { nofree nosync nounwind willreturn memory(none) }
3241
3452
;.
3242
3453
; CGSCC: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) }
3243
3454
; CGSCC: attributes #[[ATTR1]] = { mustprogress nofree nosync nounwind willreturn memory(argmem: readwrite) }
@@ -3267,6 +3478,7 @@ declare void @llvm.assume(i1 noundef)
3267
3478
; CGSCC: attributes #[[ATTR25]] = { nofree nounwind }
3268
3479
; CGSCC: attributes #[[ATTR26]] = { nofree nounwind willreturn }
3269
3480
; CGSCC: attributes #[[ATTR27]] = { nofree }
3481
+ ; CGSCC: attributes #[[ATTR28]] = { nofree nosync willreturn }
3270
3482
;.
3271
3483
; TUNIT: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}
3272
3484
; TUNIT: [[META1:![0-9]+]] = !{i32 7, !"uwtable", i32 1}
0 commit comments