1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S < %s -indvars | FileCheck %s 3; RUN: opt -S < %s -passes=indvars | FileCheck %s 4 5declare i1 @cond() 6declare void @exit(i32 %code) 7 8; FIXME: We can remove 2nd check here because it is implied by check 9; against the shifted value. 10define void @test_01(i32* %p, i32 %shift) { 11; CHECK-LABEL: @test_01( 12; CHECK-NEXT: entry: 13; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4, !range [[RNG0:![0-9]+]] 14; CHECK-NEXT: [[X_SHIFTED:%.*]] = lshr i32 [[X]], [[SHIFT:%.*]] 15; CHECK-NEXT: br label [[LOOP:%.*]] 16; CHECK: loop: 17; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 18; CHECK-NEXT: [[LESS_THAN_SHIFTED:%.*]] = icmp slt i32 [[IV]], [[X_SHIFTED]] 19; CHECK-NEXT: br i1 [[LESS_THAN_SHIFTED]], label [[GUARDED:%.*]], label [[FAILURE:%.*]] 20; CHECK: guarded: 21; CHECK-NEXT: [[LESS_THAN_X:%.*]] = icmp ult i32 [[IV]], [[X]] 22; CHECK-NEXT: br i1 [[LESS_THAN_X]], label [[BACKEDGE]], label [[NEVER_HAPPENS:%.*]] 23; CHECK: backedge: 24; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 25; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @cond() 26; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[DONE:%.*]] 27; CHECK: done: 28; CHECK-NEXT: ret void 29; CHECK: failure: 30; CHECK-NEXT: call void @exit(i32 1) 31; CHECK-NEXT: unreachable 32; CHECK: never_happens: 33; CHECK-NEXT: call void @exit(i32 0) 34; CHECK-NEXT: unreachable 35; 36entry: 37 %x = load i32, i32* %p, !range !0 38 %x.shifted = lshr i32 %x, %shift 39 br label %loop 40 41loop: 42 %iv = phi i32 [0, %entry], [%iv.next, %backedge] 43 %less.than.shifted = icmp slt i32 %iv, %x.shifted 44 br i1 %less.than.shifted, label %guarded, label %failure 45 46guarded: 47 %less.than.x = icmp slt i32 %iv, %x 48 br i1 %less.than.x, label %backedge, label %never_happens 49 50backedge: 51 %iv.next = add nuw nsw i32 %iv, 1 52 %loop.cond = call i1 @cond() 53 br i1 %loop.cond, label %loop, label %done 54 55done: 56 ret void 57 58failure: 59 call void @exit(i32 1) 60 unreachable 61 62never_happens: 63 call void @exit(i32 0) 64 unreachable 65} 66 67; FIXME: We can remove 2nd check here because it is implied by check 68; against the shifted value. 69define void @test_02(i32* %p, i32 %shift) { 70; CHECK-LABEL: @test_02( 71; CHECK-NEXT: entry: 72; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4, !range [[RNG0]] 73; CHECK-NEXT: [[X_SHIFTED:%.*]] = lshr i32 [[X]], [[SHIFT:%.*]] 74; CHECK-NEXT: br label [[LOOP:%.*]] 75; CHECK: loop: 76; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 77; CHECK-NEXT: [[LESS_THAN_SHIFTED:%.*]] = icmp sgt i32 [[X_SHIFTED]], [[IV]] 78; CHECK-NEXT: br i1 [[LESS_THAN_SHIFTED]], label [[GUARDED:%.*]], label [[FAILURE:%.*]] 79; CHECK: guarded: 80; CHECK-NEXT: [[LESS_THAN_X:%.*]] = icmp ugt i32 [[X]], [[IV]] 81; CHECK-NEXT: br i1 [[LESS_THAN_X]], label [[BACKEDGE]], label [[NEVER_HAPPENS:%.*]] 82; CHECK: backedge: 83; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 84; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @cond() 85; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[DONE:%.*]] 86; CHECK: done: 87; CHECK-NEXT: ret void 88; CHECK: failure: 89; CHECK-NEXT: call void @exit(i32 1) 90; CHECK-NEXT: unreachable 91; CHECK: never_happens: 92; CHECK-NEXT: call void @exit(i32 0) 93; CHECK-NEXT: unreachable 94; 95entry: 96 %x = load i32, i32* %p, !range !0 97 %x.shifted = lshr i32 %x, %shift 98 br label %loop 99 100loop: 101 %iv = phi i32 [0, %entry], [%iv.next, %backedge] 102 %less.than.shifted = icmp sgt i32 %x.shifted, %iv 103 br i1 %less.than.shifted, label %guarded, label %failure 104 105guarded: 106 %less.than.x = icmp sgt i32 %x, %iv 107 br i1 %less.than.x, label %backedge, label %never_happens 108 109backedge: 110 %iv.next = add nuw nsw i32 %iv, 1 111 %loop.cond = call i1 @cond() 112 br i1 %loop.cond, label %loop, label %done 113 114done: 115 ret void 116 117failure: 118 call void @exit(i32 1) 119 unreachable 120 121never_happens: 122 call void @exit(i32 0) 123 unreachable 124} 125 126; FIXME: We can remove 2nd check here because it is implied by check 127; against the shifted value. 128define void @test_03(i32* %p, i32 %shift) { 129; CHECK-LABEL: @test_03( 130; CHECK-NEXT: entry: 131; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4, !range [[RNG0]] 132; CHECK-NEXT: [[X_SHIFTED:%.*]] = lshr i32 [[X]], [[SHIFT:%.*]] 133; CHECK-NEXT: br label [[LOOP:%.*]] 134; CHECK: loop: 135; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 136; CHECK-NEXT: [[LESS_THAN_SHIFTED:%.*]] = icmp ult i32 [[IV]], [[X_SHIFTED]] 137; CHECK-NEXT: br i1 [[LESS_THAN_SHIFTED]], label [[GUARDED:%.*]], label [[FAILURE:%.*]] 138; CHECK: guarded: 139; CHECK-NEXT: [[LESS_THAN_X:%.*]] = icmp ult i32 [[IV]], [[X]] 140; CHECK-NEXT: br i1 [[LESS_THAN_X]], label [[BACKEDGE]], label [[NEVER_HAPPENS:%.*]] 141; CHECK: backedge: 142; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 143; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @cond() 144; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[DONE:%.*]] 145; CHECK: done: 146; CHECK-NEXT: ret void 147; CHECK: failure: 148; CHECK-NEXT: call void @exit(i32 1) 149; CHECK-NEXT: unreachable 150; CHECK: never_happens: 151; CHECK-NEXT: call void @exit(i32 0) 152; CHECK-NEXT: unreachable 153; 154entry: 155 %x = load i32, i32* %p, !range !0 156 %x.shifted = lshr i32 %x, %shift 157 br label %loop 158 159loop: 160 %iv = phi i32 [0, %entry], [%iv.next, %backedge] 161 %less.than.shifted = icmp ult i32 %iv, %x.shifted 162 br i1 %less.than.shifted, label %guarded, label %failure 163 164guarded: 165 %less.than.x = icmp ult i32 %iv, %x 166 br i1 %less.than.x, label %backedge, label %never_happens 167 168backedge: 169 %iv.next = add nuw nsw i32 %iv, 1 170 %loop.cond = call i1 @cond() 171 br i1 %loop.cond, label %loop, label %done 172 173done: 174 ret void 175 176failure: 177 call void @exit(i32 1) 178 unreachable 179 180never_happens: 181 call void @exit(i32 0) 182 unreachable 183} 184 185; FIXME: We can remove 2nd check here because it is implied by check 186; against the shifted value. 187define void @test_04(i32* %p, i32 %shift) { 188; CHECK-LABEL: @test_04( 189; CHECK-NEXT: entry: 190; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P:%.*]], align 4, !range [[RNG0]] 191; CHECK-NEXT: [[X_SHIFTED:%.*]] = lshr i32 [[X]], [[SHIFT:%.*]] 192; CHECK-NEXT: br label [[LOOP:%.*]] 193; CHECK: loop: 194; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 195; CHECK-NEXT: [[LESS_THAN_SHIFTED:%.*]] = icmp ugt i32 [[X_SHIFTED]], [[IV]] 196; CHECK-NEXT: br i1 [[LESS_THAN_SHIFTED]], label [[GUARDED:%.*]], label [[FAILURE:%.*]] 197; CHECK: guarded: 198; CHECK-NEXT: [[LESS_THAN_X:%.*]] = icmp ugt i32 [[X]], [[IV]] 199; CHECK-NEXT: br i1 [[LESS_THAN_X]], label [[BACKEDGE]], label [[NEVER_HAPPENS:%.*]] 200; CHECK: backedge: 201; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 202; CHECK-NEXT: [[LOOP_COND:%.*]] = call i1 @cond() 203; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[DONE:%.*]] 204; CHECK: done: 205; CHECK-NEXT: ret void 206; CHECK: failure: 207; CHECK-NEXT: call void @exit(i32 1) 208; CHECK-NEXT: unreachable 209; CHECK: never_happens: 210; CHECK-NEXT: call void @exit(i32 0) 211; CHECK-NEXT: unreachable 212; 213entry: 214 %x = load i32, i32* %p, !range !0 215 %x.shifted = lshr i32 %x, %shift 216 br label %loop 217 218loop: 219 %iv = phi i32 [0, %entry], [%iv.next, %backedge] 220 %less.than.shifted = icmp ugt i32 %x.shifted, %iv 221 br i1 %less.than.shifted, label %guarded, label %failure 222 223guarded: 224 %less.than.x = icmp ugt i32 %x, %iv 225 br i1 %less.than.x, label %backedge, label %never_happens 226 227backedge: 228 %iv.next = add nuw nsw i32 %iv, 1 229 %loop.cond = call i1 @cond() 230 br i1 %loop.cond, label %loop, label %done 231 232done: 233 ret void 234 235failure: 236 call void @exit(i32 1) 237 unreachable 238 239never_happens: 240 call void @exit(i32 0) 241 unreachable 242} 243 244!0 = !{i32 0, i32 2147483647} 245