brintos

brintos / llvm-project-archived public Read only

0
0
Text · 14.5 KiB · fe4f037 Raw
402 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -S -passes=licm -use-dereferenceable-at-point-semantics=false < %s | FileCheck %s3; RUN: opt -S -passes=licm -use-dereferenceable-at-point-semantics < %s | FileCheck %s4 5target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"6target triple = "x86_64-unknown-linux-gnu"7 8declare void @unknown()9declare void @init(ptr nocapture)10declare void @use(i8)11 12define i8 @test_sink_alloca() {13; CHECK-LABEL: @test_sink_alloca(14; CHECK-NEXT:  entry:15; CHECK-NEXT:    [[A:%.*]] = alloca [32 x i8], align 116; CHECK-NEXT:    call void @init(ptr [[A]])17; CHECK-NEXT:    br label [[FOR_BODY:%.*]]18; CHECK:       for.body:19; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]20; CHECK-NEXT:    call void @unknown()21; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 122; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i64 [[IV_NEXT]], 20023; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]24; CHECK:       for.end:25; CHECK-NEXT:    [[ADDR_LE:%.*]] = getelementptr i8, ptr [[A]], i32 3126; CHECK-NEXT:    [[RES_LE:%.*]] = load i8, ptr [[ADDR_LE]], align 127; CHECK-NEXT:    ret i8 [[RES_LE]]28;29entry:30  %a = alloca [32 x i8]31  call void @init(ptr %a)32  br label %for.body33 34for.body:35  %iv = phi i64 [ %iv.next, %for.body ], [ 0, %entry ]36  call void @unknown() ;; may throw37  %addr = getelementptr i8, ptr %a, i32 3138  %res = load i8, ptr %addr39  %iv.next = add nuw nsw i64 %iv, 140  %exitcond = icmp eq i64 %iv.next, 20041  br i1 %exitcond, label %for.end, label %for.body42 43for.end:44  ret i8 %res45}46 47define i8 @test_hoist_alloca() {48; CHECK-LABEL: @test_hoist_alloca(49; CHECK-NEXT:  entry:50; CHECK-NEXT:    [[A:%.*]] = alloca [32 x i8], align 151; CHECK-NEXT:    call void @init(ptr [[A]])52; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i8, ptr [[A]], i32 3153; CHECK-NEXT:    [[RES:%.*]] = load i8, ptr [[ADDR]], align 154; CHECK-NEXT:    br label [[FOR_BODY:%.*]]55; CHECK:       for.body:56; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]57; CHECK-NEXT:    call void @unknown()58; CHECK-NEXT:    call void @use(i8 [[RES]])59; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 160; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i64 [[IV_NEXT]], 20061; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]62; CHECK:       for.end:63; CHECK-NEXT:    [[RES_LCSSA:%.*]] = phi i8 [ [[RES]], [[FOR_BODY]] ]64; CHECK-NEXT:    ret i8 [[RES_LCSSA]]65;66entry:67  %a = alloca [32 x i8]68  call void @init(ptr %a)69  br label %for.body70 71for.body:72  %iv = phi i64 [ %iv.next, %for.body ], [ 0, %entry ]73  call void @unknown() ;; may throw74  %addr = getelementptr i8, ptr %a, i32 3175  %res = load i8, ptr %addr76  call void @use(i8 %res)77  %iv.next = add nuw nsw i64 %iv, 178  %exitcond = icmp eq i64 %iv.next, 20079  br i1 %exitcond, label %for.end, label %for.body80 81for.end:82  ret i8 %res83}84 85; The attributes listed here are a) inferred by -O3 from the names86; and b) required for a standalone test.  We're very inconsistent about87; which decisions we drive from TLI vs assume attributes have been infered.88declare void @free(ptr nocapture)89declare noalias ptr @malloc(i64)90 91define i8 @test_sink_malloc() {92; CHECK-LABEL: @test_sink_malloc(93; CHECK-NEXT:  entry:94; CHECK-NEXT:    [[A_RAW:%.*]] = call nonnull ptr @malloc(i64 32)95; CHECK-NEXT:    call void @init(ptr [[A_RAW]])96; CHECK-NEXT:    br label [[FOR_BODY:%.*]]97; CHECK:       for.body:98; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]99; CHECK-NEXT:    call void @unknown()100; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1101; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i64 [[IV_NEXT]], 200102; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]103; CHECK:       for.end:104; CHECK-NEXT:    [[ADDR_LE:%.*]] = getelementptr i8, ptr [[A_RAW]], i32 31105; CHECK-NEXT:    [[RES_LE:%.*]] = load i8, ptr [[ADDR_LE]], align 1106; CHECK-NEXT:    call void @free(ptr [[A_RAW]])107; CHECK-NEXT:    ret i8 [[RES_LE]]108;109entry:110  ; Mark as nonnull to simplify test111  %a.raw = call nonnull ptr @malloc(i64 32)112  call void @init(ptr %a.raw)113  br label %for.body114 115for.body:116  %iv = phi i64 [ %iv.next, %for.body ], [ 0, %entry ]117  call void @unknown() ;; may throw118  %addr = getelementptr i8, ptr %a.raw, i32 31119  %res = load i8, ptr %addr120  %iv.next = add nuw nsw i64 %iv, 1121  %exitcond = icmp eq i64 %iv.next, 200122  br i1 %exitcond, label %for.end, label %for.body123 124for.end:125  call void @free(ptr %a.raw)126  ret i8 %res127}128 129; TODO: We can hoist the load in this case, but only once we have130; some form of context sensitive free analysis.131define i8 @test_hoist_malloc() {132; CHECK-LABEL: @test_hoist_malloc(133; CHECK-NEXT:  entry:134; CHECK-NEXT:    [[A_RAW:%.*]] = call nonnull ptr @malloc(i64 32)135; CHECK-NEXT:    call void @init(ptr [[A_RAW]])136; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i8, ptr [[A_RAW]], i32 31137; CHECK-NEXT:    br label [[FOR_BODY:%.*]]138; CHECK:       for.body:139; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]140; CHECK-NEXT:    call void @unknown()141; CHECK-NEXT:    [[RES:%.*]] = load i8, ptr [[ADDR]], align 1142; CHECK-NEXT:    call void @use(i8 [[RES]])143; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1144; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i64 [[IV_NEXT]], 200145; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]146; CHECK:       for.end:147; CHECK-NEXT:    [[RES_LCSSA:%.*]] = phi i8 [ [[RES]], [[FOR_BODY]] ]148; CHECK-NEXT:    call void @free(ptr [[A_RAW]])149; CHECK-NEXT:    ret i8 [[RES_LCSSA]]150;151entry:152  %a.raw = call nonnull ptr @malloc(i64 32)153  call void @init(ptr %a.raw)154  br label %for.body155 156for.body:157  %iv = phi i64 [ %iv.next, %for.body ], [ 0, %entry ]158  call void @unknown() ;; may throw159  %addr = getelementptr i8, ptr %a.raw, i32 31160  %res = load i8, ptr %addr161  call void @use(i8 %res)162  %iv.next = add nuw nsw i64 %iv, 1163  %exitcond = icmp eq i64 %iv.next, 200164  br i1 %exitcond, label %for.end, label %for.body165 166for.end:167  call void @free(ptr %a.raw)168  ret i8 %res169}170 171define i8 @test_hoist_malloc_leak() nofree nosync {172; CHECK-LABEL: @test_hoist_malloc_leak(173; CHECK-NEXT:  entry:174; CHECK-NEXT:    [[A_RAW:%.*]] = call nonnull ptr @malloc(i64 32)175; CHECK-NEXT:    call void @init(ptr [[A_RAW]])176; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i8, ptr [[A_RAW]], i32 31177; CHECK-NEXT:    br label [[FOR_BODY:%.*]]178; CHECK:       for.body:179; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]180; CHECK-NEXT:    call void @unknown()181; CHECK-NEXT:    [[RES:%.*]] = load i8, ptr [[ADDR]], align 1182; CHECK-NEXT:    call void @use(i8 [[RES]])183; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1184; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i64 [[IV_NEXT]], 200185; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]186; CHECK:       for.end:187; CHECK-NEXT:    [[RES_LCSSA:%.*]] = phi i8 [ [[RES]], [[FOR_BODY]] ]188; CHECK-NEXT:    ret i8 [[RES_LCSSA]]189;190entry:191  %a.raw = call nonnull ptr @malloc(i64 32)192  call void @init(ptr %a.raw)193  br label %for.body194 195for.body:196  %iv = phi i64 [ %iv.next, %for.body ], [ 0, %entry ]197  call void @unknown() ;; may throw198  %addr = getelementptr i8, ptr %a.raw, i32 31199  %res = load i8, ptr %addr200  call void @use(i8 %res)201  %iv.next = add nuw nsw i64 %iv, 1202  %exitcond = icmp eq i64 %iv.next, 200203  br i1 %exitcond, label %for.end, label %for.body204 205for.end:206  ret i8 %res207}208 209; In this case, we can't hoist the load out of the loop as the memory it210; accesses may have been conditionally freed in a manner correlated with211; whether the load is reached in the loop.212define void @test_hoist_malloc_cond_free(i1 %c) {213; CHECK-LABEL: @test_hoist_malloc_cond_free(214; CHECK-NEXT:  entry:215; CHECK-NEXT:    [[A_RAW:%.*]] = call nonnull ptr @malloc(i64 32)216; CHECK-NEXT:    call void @init(ptr [[A_RAW]])217; CHECK-NEXT:    br i1 [[C:%.*]], label [[COND_FREE:%.*]], label [[PREHEADER:%.*]]218; CHECK:       cond.free:219; CHECK-NEXT:    call void @free(ptr [[A_RAW]])220; CHECK-NEXT:    br label [[PREHEADER]]221; CHECK:       preheader:222; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i8, ptr [[A_RAW]], i32 31223; CHECK-NEXT:    br label [[FOR_BODY:%.*]]224; CHECK:       for.body:225; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ], [ 0, [[PREHEADER]] ]226; CHECK-NEXT:    br i1 [[C]], label [[FOR_END:%.*]], label [[LOOP_LATCH]]227; CHECK:       loop.latch:228; CHECK-NEXT:    call void @unknown()229; CHECK-NEXT:    [[RES:%.*]] = load i8, ptr [[ADDR]], align 1230; CHECK-NEXT:    call void @use(i8 [[RES]])231; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1232; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i64 [[IV_NEXT]], 200233; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_END]], label [[FOR_BODY]]234; CHECK:       for.end:235; CHECK-NEXT:    ret void236;237entry:238  %a.raw = call nonnull ptr @malloc(i64 32)239  call void @init(ptr %a.raw)240  br i1 %c, label %cond.free, label %preheader241cond.free:242  call void @free(ptr %a.raw)243  br label %preheader244preheader:245  br label %for.body246 247for.body:248  %iv = phi i64 [ %iv.next, %loop.latch ], [ 0, %preheader ]249  br i1 %c, label %for.end, label %loop.latch250 251loop.latch:252  call void @unknown() ;; may throw253  %addr = getelementptr i8, ptr %a.raw, i32 31254  %res = load i8, ptr %addr255  call void @use(i8 %res)256  %iv.next = add nuw nsw i64 %iv, 1257  %exitcond = icmp eq i64 %iv.next, 200258  br i1 %exitcond, label %for.end, label %for.body259 260for.end:261  ret void262}263 264define i8 @test_sink_malloc_cond_free(i1 %c) {265; CHECK-LABEL: @test_sink_malloc_cond_free(266; CHECK-NEXT:  entry:267; CHECK-NEXT:    [[A_RAW:%.*]] = call nonnull ptr @malloc(i64 32)268; CHECK-NEXT:    call void @init(ptr [[A_RAW]])269; CHECK-NEXT:    br i1 [[C:%.*]], label [[COND_FREE:%.*]], label [[PREHEADER:%.*]]270; CHECK:       cond.free:271; CHECK-NEXT:    call void @free(ptr [[A_RAW]])272; CHECK-NEXT:    br label [[PREHEADER]]273; CHECK:       preheader:274; CHECK-NEXT:    br label [[FOR_BODY:%.*]]275; CHECK:       for.body:276; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ], [ 0, [[PREHEADER]] ]277; CHECK-NEXT:    br i1 [[C]], label [[FOR_END_SPLIT_LOOP_EXIT1:%.*]], label [[LOOP_LATCH]]278; CHECK:       loop.latch:279; CHECK-NEXT:    call void @unknown()280; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1281; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i64 [[IV_NEXT]], 200282; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_END_SPLIT_LOOP_EXIT:%.*]], label [[FOR_BODY]]283; CHECK:       for.end.split.loop.exit:284; CHECK-NEXT:    [[ADDR_LE:%.*]] = getelementptr i8, ptr [[A_RAW]], i32 31285; CHECK-NEXT:    [[RES_LE:%.*]] = load i8, ptr [[ADDR_LE]], align 1286; CHECK-NEXT:    br label [[FOR_END:%.*]]287; CHECK:       for.end.split.loop.exit1:288; CHECK-NEXT:    [[PHI_PH2:%.*]] = phi i8 [ 0, [[FOR_BODY]] ]289; CHECK-NEXT:    br label [[FOR_END]]290; CHECK:       for.end:291; CHECK-NEXT:    [[PHI:%.*]] = phi i8 [ [[RES_LE]], [[FOR_END_SPLIT_LOOP_EXIT]] ], [ [[PHI_PH2]], [[FOR_END_SPLIT_LOOP_EXIT1]] ]292; CHECK-NEXT:    ret i8 [[PHI]]293;294entry:295  %a.raw = call nonnull ptr @malloc(i64 32)296  call void @init(ptr %a.raw)297  br i1 %c, label %cond.free, label %preheader298cond.free:299  call void @free(ptr %a.raw)300  br label %preheader301preheader:302  br label %for.body303 304for.body:305  %iv = phi i64 [ %iv.next, %loop.latch ], [ 0, %preheader ]306  br i1 %c, label %for.end, label %loop.latch307 308loop.latch:309  call void @unknown() ;; may throw310  %addr = getelementptr i8, ptr %a.raw, i32 31311  %res = load i8, ptr %addr312  %iv.next = add nuw nsw i64 %iv, 1313  %exitcond = icmp eq i64 %iv.next, 200314  br i1 %exitcond, label %for.end, label %for.body315 316for.end:317  %phi = phi i8 [%res, %loop.latch], [0, %for.body]318  ret i8 %phi319}320 321declare noalias ptr @my_alloc(i64) allocsize(0)322 323; We would need context sensitive reasoning about frees (which we don't324; don't currently have) to hoist the load in this example.325define i8 @test_hoist_allocsize() {326; CHECK-LABEL: @test_hoist_allocsize(327; CHECK-NEXT:  entry:328; CHECK-NEXT:    [[A_RAW:%.*]] = call nonnull ptr @my_alloc(i64 32)329; CHECK-NEXT:    call void @init(ptr [[A_RAW]])330; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i8, ptr [[A_RAW]], i32 31331; CHECK-NEXT:    br label [[FOR_BODY:%.*]]332; CHECK:       for.body:333; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]334; CHECK-NEXT:    call void @unknown()335; CHECK-NEXT:    [[RES:%.*]] = load i8, ptr [[ADDR]], align 1336; CHECK-NEXT:    call void @use(i8 [[RES]])337; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1338; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i64 [[IV_NEXT]], 200339; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]340; CHECK:       for.end:341; CHECK-NEXT:    [[RES_LCSSA:%.*]] = phi i8 [ [[RES]], [[FOR_BODY]] ]342; CHECK-NEXT:    call void @free(ptr [[A_RAW]])343; CHECK-NEXT:    ret i8 [[RES_LCSSA]]344;345entry:346  %a.raw = call nonnull ptr @my_alloc(i64 32)347  call void @init(ptr %a.raw)348  br label %for.body349 350for.body:351  %iv = phi i64 [ %iv.next, %for.body ], [ 0, %entry ]352  call void @unknown() ;; may throw353  %addr = getelementptr i8, ptr %a.raw, i32 31354  %res = load i8, ptr %addr355  call void @use(i8 %res)356  %iv.next = add nuw nsw i64 %iv, 1357  %exitcond = icmp eq i64 %iv.next, 200358  br i1 %exitcond, label %for.end, label %for.body359 360for.end:361  call void @free(ptr %a.raw)362  ret i8 %res363}364 365define i8 @test_hoist_allocsize_leak() nofree nosync {366; CHECK-LABEL: @test_hoist_allocsize_leak(367; CHECK-NEXT:  entry:368; CHECK-NEXT:    [[A_RAW:%.*]] = call nonnull ptr @my_alloc(i64 32)369; CHECK-NEXT:    call void @init(ptr [[A_RAW]])370; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i8, ptr [[A_RAW]], i32 31371; CHECK-NEXT:    br label [[FOR_BODY:%.*]]372; CHECK:       for.body:373; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]374; CHECK-NEXT:    call void @unknown()375; CHECK-NEXT:    [[RES:%.*]] = load i8, ptr [[ADDR]], align 1376; CHECK-NEXT:    call void @use(i8 [[RES]])377; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1378; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i64 [[IV_NEXT]], 200379; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]380; CHECK:       for.end:381; CHECK-NEXT:    [[RES_LCSSA:%.*]] = phi i8 [ [[RES]], [[FOR_BODY]] ]382; CHECK-NEXT:    ret i8 [[RES_LCSSA]]383;384entry:385  %a.raw = call nonnull ptr @my_alloc(i64 32)386  call void @init(ptr %a.raw)387  br label %for.body388 389for.body:390  %iv = phi i64 [ %iv.next, %for.body ], [ 0, %entry ]391  call void @unknown() ;; may throw392  %addr = getelementptr i8, ptr %a.raw, i32 31393  %res = load i8, ptr %addr394  call void @use(i8 %res)395  %iv.next = add nuw nsw i64 %iv, 1396  %exitcond = icmp eq i64 %iv.next, 200397  br i1 %exitcond, label %for.end, label %for.body398 399for.end:400  ret i8 %res401}402