1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -mtriple=x86_64-linux -codegenprepare -S | FileCheck %s 3 4; No overflow flags, same type width. 5define i32 @test_01(ptr %p, i64 %len, i32 %x) { 6; CHECK-LABEL: @test_01( 7; CHECK-NEXT: entry: 8; CHECK-NEXT: br label [[LOOP:%.*]] 9; CHECK: loop: 10; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[ENTRY:%.*]] ] 11; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 12; CHECK-NEXT: [[COND_1:%.*]] = icmp eq i64 [[IV]], [[LEN:%.*]] 13; CHECK-NEXT: br i1 [[COND_1]], label [[EXIT:%.*]], label [[BACKEDGE]] 14; CHECK: backedge: 15; CHECK-NEXT: [[SUNKADDR:%.*]] = mul i64 [[IV_NEXT]], 4 16; CHECK-NEXT: [[SUNKADDR1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[SUNKADDR]] 17; CHECK-NEXT: [[SUNKADDR2:%.*]] = getelementptr i8, ptr [[SUNKADDR1]], i64 -8 18; CHECK-NEXT: [[LOADED:%.*]] = load atomic i32, ptr [[SUNKADDR2]] unordered, align 4 19; CHECK-NEXT: [[COND_2:%.*]] = icmp eq i32 [[LOADED]], [[X:%.*]] 20; CHECK-NEXT: br i1 [[COND_2]], label [[FAILURE:%.*]], label [[LOOP]] 21; CHECK: exit: 22; CHECK-NEXT: ret i32 -1 23; CHECK: failure: 24; CHECK-NEXT: unreachable 25; 26entry: 27 %scevgep = getelementptr i32, ptr %p, i64 -1 28 br label %loop 29 30loop: ; preds = %backedge, %entry 31 %iv = phi i64 [ %iv.next, %backedge ], [ 0, %entry ] 32 %iv.next = add i64 %iv, 1 33 %cond_1 = icmp eq i64 %iv, %len 34 br i1 %cond_1, label %exit, label %backedge 35 36backedge: ; preds = %loop 37 %scevgep1 = getelementptr i32, ptr %scevgep, i64 %iv 38 %loaded = load atomic i32, ptr %scevgep1 unordered, align 4 39 %cond_2 = icmp eq i32 %loaded, %x 40 br i1 %cond_2, label %failure, label %loop 41 42exit: ; preds = %loop 43 ret i32 -1 44 45failure: ; preds = %backedge 46 unreachable 47} 48 49; nsw flag, same type width. 50define i32 @test_02(ptr %p, i64 %len, i32 %x) { 51; CHECK-LABEL: @test_02( 52; CHECK-NEXT: entry: 53; CHECK-NEXT: br label [[LOOP:%.*]] 54; CHECK: loop: 55; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[ENTRY:%.*]] ] 56; CHECK-NEXT: [[IV_NEXT]] = add nsw i64 [[IV]], 1 57; CHECK-NEXT: [[COND_1:%.*]] = icmp eq i64 [[IV]], [[LEN:%.*]] 58; CHECK-NEXT: br i1 [[COND_1]], label [[EXIT:%.*]], label [[BACKEDGE]] 59; CHECK: backedge: 60; CHECK-NEXT: [[SUNKADDR:%.*]] = mul i64 [[IV]], 4 61; CHECK-NEXT: [[SUNKADDR1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[SUNKADDR]] 62; CHECK-NEXT: [[SUNKADDR2:%.*]] = getelementptr i8, ptr [[SUNKADDR1]], i64 -4 63; CHECK-NEXT: [[LOADED:%.*]] = load atomic i32, ptr [[SUNKADDR2]] unordered, align 4 64; 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 -1 68; CHECK: failure: 69; CHECK-NEXT: unreachable 70; 71entry: 72 %scevgep = getelementptr i32, ptr %p, i64 -1 73 br label %loop 74 75loop: ; preds = %backedge, %entry 76 %iv = phi i64 [ %iv.next, %backedge ], [ 0, %entry ] 77 %iv.next = add nsw i64 %iv, 1 78 %cond_1 = icmp eq i64 %iv, %len 79 br i1 %cond_1, label %exit, label %backedge 80 81backedge: ; preds = %loop 82 %scevgep1 = getelementptr i32, ptr %scevgep, i64 %iv 83 %loaded = load atomic i32, ptr %scevgep1 unordered, align 4 84 %cond_2 = icmp eq i32 %loaded, %x 85 br i1 %cond_2, label %failure, label %loop 86 87exit: ; preds = %loop 88 ret i32 -1 89 90failure: ; preds = %backedge 91 unreachable 92} 93 94; nsw flag, optimization is possible because memory instruction is dominated by loop-exiting check against iv.next. 95define i32 @test_02_nopoison(ptr %p, i64 %len, i32 %x) { 96; CHECK-LABEL: @test_02_nopoison( 97; CHECK-NEXT: entry: 98; CHECK-NEXT: [[LEN_PLUS_1:%.*]] = add i64 [[LEN:%.*]], 1 99; CHECK-NEXT: br label [[LOOP:%.*]] 100; CHECK: loop: 101; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[ENTRY:%.*]] ] 102; CHECK-NEXT: [[IV_NEXT]] = add nsw i64 [[IV]], 1 103; CHECK-NEXT: [[COND_1:%.*]] = icmp eq i64 [[IV_NEXT]], [[LEN_PLUS_1]] 104; CHECK-NEXT: br i1 [[COND_1]], label [[EXIT:%.*]], label [[BACKEDGE]] 105; CHECK: backedge: 106; CHECK-NEXT: [[SUNKADDR:%.*]] = mul i64 [[IV]], 4 107; CHECK-NEXT: [[SUNKADDR1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[SUNKADDR]] 108; CHECK-NEXT: [[SUNKADDR2:%.*]] = getelementptr i8, ptr [[SUNKADDR1]], i64 -4 109; CHECK-NEXT: [[LOADED:%.*]] = load atomic i32, ptr [[SUNKADDR2]] unordered, align 4 110; CHECK-NEXT: [[COND_2:%.*]] = icmp eq i32 [[LOADED]], [[X:%.*]] 111; CHECK-NEXT: br i1 [[COND_2]], label [[FAILURE:%.*]], label [[LOOP]] 112; CHECK: exit: 113; CHECK-NEXT: ret i32 -1 114; CHECK: failure: 115; CHECK-NEXT: unreachable 116; 117entry: 118 %len.plus.1 = add i64 %len, 1 119 %scevgep = getelementptr i32, ptr %p, i64 -1 120 br label %loop 121 122loop: ; preds = %backedge, %entry 123 %iv = phi i64 [ %iv.next, %backedge ], [ 0, %entry ] 124 %iv.next = add nsw i64 %iv, 1 125 %cond_1 = icmp eq i64 %iv.next, %len.plus.1 126 br i1 %cond_1, label %exit, label %backedge 127 128backedge: ; preds = %loop 129 %scevgep1 = getelementptr i32, ptr %scevgep, i64 %iv 130 %loaded = load atomic i32, ptr %scevgep1 unordered, align 4 131 %cond_2 = icmp eq i32 %loaded, %x 132 br i1 %cond_2, label %failure, label %loop 133 134exit: ; preds = %loop 135 ret i32 -1 136 137failure: ; preds = %backedge 138 unreachable 139} 140 141 142; nuw flag, same type width. 143define i32 @test_03(ptr %p, i64 %len, i32 %x) { 144; CHECK-LABEL: @test_03( 145; CHECK-NEXT: entry: 146; CHECK-NEXT: br label [[LOOP:%.*]] 147; CHECK: loop: 148; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[ENTRY:%.*]] ] 149; CHECK-NEXT: [[IV_NEXT]] = add nuw i64 [[IV]], 1 150; CHECK-NEXT: [[COND_1:%.*]] = icmp eq i64 [[IV]], [[LEN:%.*]] 151; CHECK-NEXT: br i1 [[COND_1]], label [[EXIT:%.*]], label [[BACKEDGE]] 152; CHECK: backedge: 153; CHECK-NEXT: [[SUNKADDR:%.*]] = mul i64 [[IV]], 4 154; CHECK-NEXT: [[SUNKADDR1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[SUNKADDR]] 155; CHECK-NEXT: [[SUNKADDR2:%.*]] = getelementptr i8, ptr [[SUNKADDR1]], i64 -4 156; CHECK-NEXT: [[LOADED:%.*]] = load atomic i32, ptr [[SUNKADDR2]] unordered, align 4 157; CHECK-NEXT: [[COND_2:%.*]] = icmp eq i32 [[LOADED]], [[X:%.*]] 158; CHECK-NEXT: br i1 [[COND_2]], label [[FAILURE:%.*]], label [[LOOP]] 159; CHECK: exit: 160; CHECK-NEXT: ret i32 -1 161; CHECK: failure: 162; CHECK-NEXT: unreachable 163; 164entry: 165 %scevgep = getelementptr i32, ptr %p, i64 -1 166 br label %loop 167 168loop: ; preds = %backedge, %entry 169 %iv = phi i64 [ %iv.next, %backedge ], [ 0, %entry ] 170 %iv.next = add nuw i64 %iv, 1 171 %cond_1 = icmp eq i64 %iv, %len 172 br i1 %cond_1, label %exit, label %backedge 173 174backedge: ; preds = %loop 175 %scevgep1 = getelementptr i32, ptr %scevgep, i64 %iv 176 %loaded = load atomic i32, ptr %scevgep1 unordered, align 4 177 %cond_2 = icmp eq i32 %loaded, %x 178 br i1 %cond_2, label %failure, label %loop 179 180exit: ; preds = %loop 181 ret i32 -1 182 183failure: ; preds = %backedge 184 unreachable 185} 186 187; nuw flag, optimization is possible because memory instruction is dominated by loop-exiting check against iv.next. 188define i32 @test_03_nopoison(ptr %p, i64 %len, i32 %x) { 189; CHECK-LABEL: @test_03_nopoison( 190; CHECK-NEXT: entry: 191; CHECK-NEXT: [[LEN_PLUS_1:%.*]] = add i64 [[LEN:%.*]], 1 192; CHECK-NEXT: br label [[LOOP:%.*]] 193; CHECK: loop: 194; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ 0, [[ENTRY:%.*]] ] 195; CHECK-NEXT: [[IV_NEXT]] = add nuw i64 [[IV]], 1 196; CHECK-NEXT: [[COND_1:%.*]] = icmp eq i64 [[IV_NEXT]], [[LEN_PLUS_1]] 197; CHECK-NEXT: br i1 [[COND_1]], label [[EXIT:%.*]], label [[BACKEDGE]] 198; CHECK: backedge: 199; CHECK-NEXT: [[SUNKADDR:%.*]] = mul i64 [[IV]], 4 200; CHECK-NEXT: [[SUNKADDR1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[SUNKADDR]] 201; CHECK-NEXT: [[SUNKADDR2:%.*]] = getelementptr i8, ptr [[SUNKADDR1]], i64 -4 202; CHECK-NEXT: [[LOADED:%.*]] = load atomic i32, ptr [[SUNKADDR2]] unordered, align 4 203; CHECK-NEXT: [[COND_2:%.*]] = icmp eq i32 [[LOADED]], [[X:%.*]] 204; CHECK-NEXT: br i1 [[COND_2]], label [[FAILURE:%.*]], label [[LOOP]] 205; CHECK: exit: 206; CHECK-NEXT: ret i32 -1 207; CHECK: failure: 208; CHECK-NEXT: unreachable 209; 210entry: 211 %len.plus.1 = add i64 %len, 1 212 %scevgep = getelementptr i32, ptr %p, i64 -1 213 br label %loop 214 215loop: ; preds = %backedge, %entry 216 %iv = phi i64 [ %iv.next, %backedge ], [ 0, %entry ] 217 %iv.next = add nuw i64 %iv, 1 218 %cond_1 = icmp eq i64 %iv.next, %len.plus.1 219 br i1 %cond_1, label %exit, label %backedge 220 221backedge: ; preds = %loop 222 %scevgep1 = getelementptr i32, ptr %scevgep, i64 %iv 223 %loaded = load atomic i32, ptr %scevgep1 unordered, align 4 224 %cond_2 = icmp eq i32 %loaded, %x 225 br i1 %cond_2, label %failure, label %loop 226 227exit: ; preds = %loop 228 ret i32 -1 229 230failure: ; preds = %backedge 231 unreachable 232} 233