392 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -mtriple=x86_64-linux -codegenprepare -S < %s | FileCheck %s3 4define i32 @test_01(ptr %p, i64 %len, i32 %x) {5; CHECK-LABEL: @test_01(6; CHECK-NEXT: entry:7; CHECK-NEXT: br label [[LOOP:%.*]]8; CHECK: loop:9; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[MATH:%.*]], [[BACKEDGE:%.*]] ], [ [[LEN:%.*]], [[ENTRY:%.*]] ]10; CHECK-NEXT: [[TMP0:%.*]] = call { i64, i1 } @llvm.usub.with.overflow.i64(i64 [[IV]], i64 1)11; CHECK-NEXT: [[MATH]] = extractvalue { i64, i1 } [[TMP0]], 012; CHECK-NEXT: [[OV:%.*]] = extractvalue { i64, i1 } [[TMP0]], 113; CHECK-NEXT: br i1 [[OV]], label [[EXIT:%.*]], label [[BACKEDGE]]14; CHECK: backedge:15; CHECK-NEXT: [[SUNKADDR:%.*]] = mul i64 [[MATH]], 416; CHECK-NEXT: [[SUNKADDR1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[SUNKADDR]]17; CHECK-NEXT: [[LOADED:%.*]] = load atomic i32, ptr [[SUNKADDR1]] unordered, align 418; CHECK-NEXT: [[COND_2:%.*]] = icmp eq i32 [[LOADED]], [[X:%.*]]19; CHECK-NEXT: br i1 [[COND_2]], label [[FAILURE:%.*]], label [[LOOP]]20; CHECK: exit:21; CHECK-NEXT: ret i32 -122; CHECK: failure:23; CHECK-NEXT: unreachable24;25entry:26 %scevgep = getelementptr i32, ptr %p, i64 -127 br label %loop28 29loop: ; preds = %backedge, %entry30 %iv = phi i64 [ %iv.next, %backedge ], [ %len, %entry ]31 %iv.next = add i64 %iv, -132 %cond_1 = icmp eq i64 %iv, 033 br i1 %cond_1, label %exit, label %backedge34 35backedge: ; preds = %loop36 %scevgep1 = getelementptr i32, ptr %scevgep, i64 %iv37 %loaded = load atomic i32, ptr %scevgep1 unordered, align 438 %cond_2 = icmp eq i32 %loaded, %x39 br i1 %cond_2, label %failure, label %loop40 41exit: ; preds = %loop42 ret i32 -143 44failure: ; preds = %backedge45 unreachable46}47 48; Similar to test_01, but with different offset.49define i32 @test_01a(ptr %p, i64 %len, i32 %x) {50; CHECK-LABEL: @test_01a(51; CHECK-NEXT: entry:52; CHECK-NEXT: br label [[LOOP:%.*]]53; CHECK: loop:54; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[MATH:%.*]], [[BACKEDGE:%.*]] ], [ [[LEN:%.*]], [[ENTRY:%.*]] ]55; CHECK-NEXT: [[TMP0:%.*]] = call { i64, i1 } @llvm.usub.with.overflow.i64(i64 [[IV]], i64 1)56; CHECK-NEXT: [[MATH]] = extractvalue { i64, i1 } [[TMP0]], 057; CHECK-NEXT: [[OV:%.*]] = extractvalue { i64, i1 } [[TMP0]], 158; CHECK-NEXT: br i1 [[OV]], label [[EXIT:%.*]], label [[BACKEDGE]]59; CHECK: backedge:60; CHECK-NEXT: [[SUNKADDR:%.*]] = mul i64 [[MATH]], 461; CHECK-NEXT: [[SUNKADDR1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[SUNKADDR]]62; CHECK-NEXT: [[SUNKADDR2:%.*]] = getelementptr i8, ptr [[SUNKADDR1]], i64 -2463; CHECK-NEXT: [[LOADED:%.*]] = load atomic i32, ptr [[SUNKADDR2]] unordered, align 464; CHECK-NEXT: [[COND_2:%.*]] = icmp eq i32 [[LOADED]], [[X:%.*]]65; CHECK-NEXT: br i1 [[COND_2]], label [[FAILURE:%.*]], label [[LOOP]]66; CHECK: exit:67; CHECK-NEXT: ret i32 -168; CHECK: failure:69; CHECK-NEXT: unreachable70;71entry:72 %scevgep = getelementptr i32, ptr %p, i64 -773 br label %loop74 75loop: ; preds = %backedge, %entry76 %iv = phi i64 [ %iv.next, %backedge ], [ %len, %entry ]77 %iv.next = add i64 %iv, -178 %cond_1 = icmp eq i64 %iv, 079 br i1 %cond_1, label %exit, label %backedge80 81backedge: ; preds = %loop82 %scevgep1 = getelementptr i32, ptr %scevgep, i64 %iv83 %loaded = load atomic i32, ptr %scevgep1 unordered, align 484 %cond_2 = icmp eq i32 %loaded, %x85 br i1 %cond_2, label %failure, label %loop86 87exit: ; preds = %loop88 ret i32 -189 90failure: ; preds = %backedge91 unreachable92}93 94; TODO: We can use trick with usub here.95define i32 @test_02(ptr %p, i64 %len, i32 %x) {96; CHECK-LABEL: @test_02(97; CHECK-NEXT: entry:98; CHECK-NEXT: br label [[LOOP:%.*]]99; CHECK: loop:100; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[MATH:%.*]], [[BACKEDGE:%.*]] ], [ [[LEN:%.*]], [[ENTRY:%.*]] ]101; CHECK-NEXT: [[TMP0:%.*]] = call { i64, i1 } @llvm.usub.with.overflow.i64(i64 [[IV]], i64 1)102; CHECK-NEXT: [[MATH]] = extractvalue { i64, i1 } [[TMP0]], 0103; CHECK-NEXT: [[OV:%.*]] = extractvalue { i64, i1 } [[TMP0]], 1104; CHECK-NEXT: br i1 [[OV]], label [[EXIT:%.*]], label [[BACKEDGE]]105; CHECK: backedge:106; CHECK-NEXT: [[SUNKADDR:%.*]] = mul i64 [[MATH]], 4107; CHECK-NEXT: [[SUNKADDR1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[SUNKADDR]]108; CHECK-NEXT: [[LOADED:%.*]] = load atomic i32, ptr [[SUNKADDR1]] unordered, align 4109; CHECK-NEXT: [[COND_2:%.*]] = icmp eq i32 [[LOADED]], [[X:%.*]]110; CHECK-NEXT: br i1 [[COND_2]], label [[FAILURE:%.*]], label [[LOOP]]111; CHECK: exit:112; CHECK-NEXT: ret i32 -1113; CHECK: failure:114; CHECK-NEXT: unreachable115;116entry:117 %scevgep = getelementptr i32, ptr %p, i64 -1118 br label %loop119 120loop: ; preds = %backedge, %entry121 %iv = phi i64 [ %iv.next, %backedge ], [ %len, %entry ]122 %cond_1 = icmp eq i64 %iv, 0123 br i1 %cond_1, label %exit, label %backedge124 125backedge: ; preds = %loop126 %scevgep1 = getelementptr i32, ptr %scevgep, i64 %iv127 %loaded = load atomic i32, ptr %scevgep1 unordered, align 4128 %cond_2 = icmp eq i32 %loaded, %x129 %iv.next = add i64 %iv, -1130 br i1 %cond_2, label %failure, label %loop131 132exit: ; preds = %loop133 ret i32 -1134 135failure: ; preds = %backedge136 unreachable137}138 139declare i1 @use(i64 %x)140declare i1 @some_cond()141 142; Make sure we do not move the increment below the point where it is used.143define i32 @test_03_neg(ptr %p, i64 %len, i32 %x) {144; CHECK-LABEL: @test_03_neg(145; CHECK-NEXT: entry:146; CHECK-NEXT: br label [[LOOP:%.*]]147; CHECK: loop:148; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[LEN:%.*]], [[ENTRY:%.*]] ]149; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], -1150; CHECK-NEXT: [[COND_0:%.*]] = call i1 @use(i64 [[IV_NEXT]])151; CHECK-NEXT: br i1 [[COND_0]], label [[MIDDLE:%.*]], label [[FAILURE:%.*]]152; CHECK: middle:153; CHECK-NEXT: [[COND_1:%.*]] = icmp eq i64 [[IV]], 0154; CHECK-NEXT: br i1 [[COND_1]], label [[EXIT:%.*]], label [[BACKEDGE]]155; CHECK: backedge:156; CHECK-NEXT: [[SUNKADDR:%.*]] = mul i64 [[IV_NEXT]], 4157; CHECK-NEXT: [[SUNKADDR1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[SUNKADDR]]158; CHECK-NEXT: [[LOADED:%.*]] = load atomic i32, ptr [[SUNKADDR1]] unordered, align 4159; CHECK-NEXT: [[COND_2:%.*]] = icmp eq i32 [[LOADED]], [[X:%.*]]160; CHECK-NEXT: br i1 [[COND_2]], label [[FAILURE]], label [[LOOP]]161; CHECK: exit:162; CHECK-NEXT: ret i32 -1163; CHECK: failure:164; CHECK-NEXT: unreachable165;166entry:167 %scevgep = getelementptr i32, ptr %p, i64 -1168 br label %loop169 170loop: ; preds = %backedge, %entry171 %iv = phi i64 [ %iv.next, %backedge ], [ %len, %entry ]172 %iv.next = add i64 %iv, -1173 %cond_0 = call i1 @use(i64 %iv.next)174 br i1 %cond_0, label %middle, label %failure175 176middle:177 %cond_1 = icmp eq i64 %iv, 0178 br i1 %cond_1, label %exit, label %backedge179 180backedge: ; preds = %loop181 %scevgep1 = getelementptr i32, ptr %scevgep, i64 %iv182 %loaded = load atomic i32, ptr %scevgep1 unordered, align 4183 %cond_2 = icmp eq i32 %loaded, %x184 br i1 %cond_2, label %failure, label %loop185 186exit: ; preds = %loop187 ret i32 -1188 189failure: ; preds = %backedge190 unreachable191}192 193define i32 @test_04_neg(ptr %p, i64 %len, i32 %x) {194; CHECK-LABEL: @test_04_neg(195; CHECK-NEXT: entry:196; CHECK-NEXT: br label [[LOOP:%.*]]197; CHECK: loop:198; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[LEN:%.*]], [[ENTRY:%.*]] ]199; CHECK-NEXT: br label [[INNER:%.*]]200; CHECK: inner:201; CHECK-NEXT: [[COND_1:%.*]] = icmp eq i64 [[IV]], 0202; CHECK-NEXT: br i1 [[COND_1]], label [[INNER_BACKEDGE:%.*]], label [[EXIT:%.*]]203; CHECK: inner_backedge:204; CHECK-NEXT: [[COND_INNER:%.*]] = call i1 @some_cond()205; CHECK-NEXT: br i1 [[COND_INNER]], label [[INNER]], label [[BACKEDGE]]206; CHECK: backedge:207; CHECK-NEXT: [[SUNKADDR:%.*]] = mul i64 [[IV]], 4208; CHECK-NEXT: [[SUNKADDR1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[SUNKADDR]]209; CHECK-NEXT: [[SUNKADDR2:%.*]] = getelementptr i8, ptr [[SUNKADDR1]], i64 -4210; CHECK-NEXT: [[LOADED:%.*]] = load atomic i32, ptr [[SUNKADDR2]] unordered, align 4211; CHECK-NEXT: [[COND_2:%.*]] = icmp eq i32 [[LOADED]], [[X:%.*]]212; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], -1213; CHECK-NEXT: br i1 [[COND_2]], label [[FAILURE:%.*]], label [[LOOP]]214; CHECK: exit:215; CHECK-NEXT: ret i32 -1216; CHECK: failure:217; CHECK-NEXT: unreachable218;219entry:220 %scevgep = getelementptr i32, ptr %p, i64 -1221 br label %loop222 223loop:224 %iv = phi i64 [ %iv.next, %backedge ], [ %len, %entry ]225 br label %inner226 227inner:228 %cond_1 = icmp eq i64 %iv, 0229 br i1 %cond_1, label %inner_backedge, label %exit230 231inner_backedge:232 %cond_inner = call i1 @some_cond()233 br i1 %cond_inner, label %inner, label %backedge234 235backedge:236 %scevgep1 = getelementptr i32, ptr %scevgep, i64 %iv237 %loaded = load atomic i32, ptr %scevgep1 unordered, align 4238 %cond_2 = icmp eq i32 %loaded, %x239 %iv.next = add i64 %iv, -1240 br i1 %cond_2, label %failure, label %loop241 242exit:243 ret i32 -1244 245failure:246 unreachable247}248 249; Here Cmp does not dominate latch.250define i32 @test_05_neg(ptr %p, i64 %len, i32 %x, i1 %cond) {251; CHECK-LABEL: @test_05_neg(252; CHECK-NEXT: entry:253; CHECK-NEXT: br label [[LOOP:%.*]]254; CHECK: loop:255; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[LEN:%.*]], [[ENTRY:%.*]] ]256; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], -1257; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_TRUE:%.*]], label [[BACKEDGE]]258; CHECK: if.true:259; CHECK-NEXT: [[COND_1:%.*]] = icmp eq i64 [[IV]], 0260; CHECK-NEXT: br i1 [[COND_1]], label [[EXIT:%.*]], label [[BACKEDGE]]261; CHECK: backedge:262; CHECK-NEXT: [[SUNKADDR:%.*]] = mul i64 [[IV_NEXT]], 4263; CHECK-NEXT: [[SUNKADDR1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[SUNKADDR]]264; CHECK-NEXT: [[LOADED:%.*]] = load atomic i32, ptr [[SUNKADDR1]] unordered, align 4265; CHECK-NEXT: [[COND_2:%.*]] = icmp eq i32 [[LOADED]], [[X:%.*]]266; CHECK-NEXT: br i1 [[COND_2]], label [[FAILURE:%.*]], label [[LOOP]]267; CHECK: exit:268; CHECK-NEXT: ret i32 -1269; CHECK: failure:270; CHECK-NEXT: unreachable271;272entry:273 %scevgep = getelementptr i32, ptr %p, i64 -1274 br label %loop275 276loop: ; preds = %backedge, %entry277 %iv = phi i64 [ %iv.next, %backedge ], [ %len, %entry ]278 %iv.next = add i64 %iv, -1279 br i1 %cond, label %if.true, label %backedge280 281if.true:282 %cond_1 = icmp eq i64 %iv, 0283 br i1 %cond_1, label %exit, label %backedge284 285backedge: ; preds = %loop286 %scevgep1 = getelementptr i32, ptr %scevgep, i64 %iv287 %loaded = load atomic i32, ptr %scevgep1 unordered, align 4288 %cond_2 = icmp eq i32 %loaded, %x289 br i1 %cond_2, label %failure, label %loop290 291exit: ; preds = %loop292 ret i32 -1293 294failure: ; preds = %backedge295 unreachable296}297 298 299; test_01, but with an additional use of %iv.next outside the loop300define i32 @test_06(ptr %p, i64 %len, i32 %x) {301; CHECK-LABEL: @test_06(302; CHECK-NEXT: entry:303; CHECK-NEXT: br label [[LOOP:%.*]]304; CHECK: loop:305; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[MATH:%.*]], [[BACKEDGE:%.*]] ], [ [[LEN:%.*]], [[ENTRY:%.*]] ]306; CHECK-NEXT: [[OV:%.*]] = icmp eq i64 [[IV]], 0307; CHECK-NEXT: br i1 [[OV]], label [[EXIT:%.*]], label [[BACKEDGE]]308; CHECK: backedge:309; CHECK-NEXT: [[SUNKADDR:%.*]] = mul i64 [[IV]], 4310; CHECK-NEXT: [[SUNKADDR1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[SUNKADDR]]311; CHECK-NEXT: [[SUNKADDR2:%.*]] = getelementptr i8, ptr [[SUNKADDR1]], i64 -4312; CHECK-NEXT: [[LOADED:%.*]] = load atomic i32, ptr [[SUNKADDR2]] unordered, align 4313; CHECK-NEXT: [[MATH]] = add i64 [[IV]], -1314; CHECK-NEXT: [[COND_2:%.*]] = icmp eq i32 [[LOADED]], [[X:%.*]]315; CHECK-NEXT: br i1 [[COND_2]], label [[FAILURE:%.*]], label [[LOOP]]316; CHECK: exit:317; CHECK-NEXT: ret i32 -1318; CHECK: failure:319; CHECK-NEXT: [[TRUNC:%.*]] = trunc i64 [[MATH]] to i32320; CHECK-NEXT: ret i32 [[TRUNC]]321;322entry:323 %scevgep = getelementptr i32, ptr %p, i64 -1324 br label %loop325 326loop: ; preds = %backedge, %entry327 %iv = phi i64 [ %iv.next, %backedge ], [ %len, %entry ]328 %cond_1 = icmp eq i64 %iv, 0329 br i1 %cond_1, label %exit, label %backedge330 331backedge: ; preds = %loop332 %scevgep1 = getelementptr i32, ptr %scevgep, i64 %iv333 %loaded = load atomic i32, ptr %scevgep1 unordered, align 4334 %iv.next = add i64 %iv, -1335 %cond_2 = icmp eq i32 %loaded, %x336 br i1 %cond_2, label %failure, label %loop337 338exit:339 ret i32 -1340 341failure:342 %trunc = trunc i64 %iv.next to i32343 ret i32 %trunc344}345 346 347; Extra use outside loop which prevents us moving the increment to the cmp348define i32 @test_07_neg(ptr %p, i64 %len, i32 %x) {349; CHECK-LABEL: @test_07_neg(350; CHECK-NEXT: entry:351; CHECK-NEXT: br label [[LOOP:%.*]]352; CHECK: loop:353; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[LEN:%.*]], [[ENTRY:%.*]] ]354; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], -1355; CHECK-NEXT: [[SUNKADDR:%.*]] = mul i64 [[IV_NEXT]], 4356; CHECK-NEXT: [[SUNKADDR1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[SUNKADDR]]357; CHECK-NEXT: [[LOADED:%.*]] = load atomic i32, ptr [[SUNKADDR1]] unordered, align 4358; CHECK-NEXT: [[COND_2:%.*]] = icmp eq i32 [[LOADED]], [[X:%.*]]359; CHECK-NEXT: br i1 [[COND_2]], label [[FAILURE:%.*]], label [[BACKEDGE]]360; CHECK: backedge:361; CHECK-NEXT: [[COND_1:%.*]] = icmp eq i64 [[IV]], 0362; CHECK-NEXT: br i1 [[COND_1]], label [[EXIT:%.*]], label [[LOOP]]363; CHECK: exit:364; CHECK-NEXT: ret i32 -1365; CHECK: failure:366; CHECK-NEXT: [[TRUNC:%.*]] = trunc i64 [[IV_NEXT]] to i32367; CHECK-NEXT: ret i32 [[TRUNC]]368;369entry:370 %scevgep = getelementptr i32, ptr %p, i64 -1371 br label %loop372 373loop:374 %iv = phi i64 [ %iv.next, %backedge ], [ %len, %entry ]375 %iv.next = add i64 %iv, -1376 %scevgep1 = getelementptr i32, ptr %scevgep, i64 %iv377 %loaded = load atomic i32, ptr %scevgep1 unordered, align 4378 %cond_2 = icmp eq i32 %loaded, %x379 br i1 %cond_2, label %failure, label %backedge380 381backedge:382 %cond_1 = icmp eq i64 %iv, 0383 br i1 %cond_1, label %exit, label %loop384 385exit:386 ret i32 -1387 388failure:389 %trunc = trunc i64 %iv.next to i32390 ret i32 %trunc391}392