1; RUN: opt -S -indvars %s | FileCheck %s 2target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 3target triple = "x86_64-unknown-linux-gnu" 4 5define void @test1(i64 %start) { 6; CHECK-LABEL: @test1 7entry: 8 br label %loop 9 10loop: 11 %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ] 12 %indvars.iv.next = add nsw i64 %indvars.iv, 1 13; CHECK: %cmp1 = icmp slt i64 %start, -1 14 %cmp1 = icmp slt i64 %indvars.iv, -1 15 br i1 %cmp1, label %for.end, label %loop 16 17for.end: ; preds = %if.end, %entry 18 ret void 19} 20 21define void @test2(i64 %start) { 22; CHECK-LABEL: @test2 23entry: 24 br label %loop 25 26loop: 27 %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ] 28 %indvars.iv.next = add nsw i64 %indvars.iv, 1 29; CHECK: %cmp1 = icmp sle i64 %start, -1 30 %cmp1 = icmp sle i64 %indvars.iv, -1 31 br i1 %cmp1, label %for.end, label %loop 32 33for.end: ; preds = %if.end, %entry 34 ret void 35} 36 37; As long as the test dominates the backedge, we're good 38define void @test3(i64 %start) { 39; CHECK-LABEL: @test3 40entry: 41 br label %loop 42 43loop: 44 %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ] 45 %indvars.iv.next = add nsw i64 %indvars.iv, 1 46 %cmp = icmp eq i64 %indvars.iv.next, 25 47 br i1 %cmp, label %backedge, label %for.end 48 49backedge: 50 ; prevent flattening, needed to make sure we're testing what we intend 51 call void @foo() 52; CHECK: %cmp1 = icmp slt i64 %start, -1 53 %cmp1 = icmp slt i64 %indvars.iv, -1 54 br i1 %cmp1, label %for.end, label %loop 55 56for.end: ; preds = %if.end, %entry 57 ret void 58} 59 60define void @test4(i64 %start) { 61; CHECK-LABEL: @test4 62entry: 63 br label %loop 64 65loop: 66 %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ] 67 %indvars.iv.next = add nsw i64 %indvars.iv, 1 68 %cmp = icmp eq i64 %indvars.iv.next, 25 69 br i1 %cmp, label %backedge, label %for.end 70 71backedge: 72 ; prevent flattening, needed to make sure we're testing what we intend 73 call void @foo() 74; CHECK: %cmp1 = icmp sgt i64 %start, -1 75 %cmp1 = icmp sgt i64 %indvars.iv, -1 76 br i1 %cmp1, label %loop, label %for.end 77 78for.end: ; preds = %if.end, %entry 79 ret void 80} 81 82define void @test5(i64 %start) { 83; CHECK-LABEL: @test5 84entry: 85 br label %loop 86 87loop: 88 %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ] 89 %indvars.iv.next = add nuw i64 %indvars.iv, 1 90 %cmp = icmp eq i64 %indvars.iv.next, 25 91 br i1 %cmp, label %backedge, label %for.end 92 93backedge: 94 ; prevent flattening, needed to make sure we're testing what we intend 95 call void @foo() 96; CHECK: %cmp1 = icmp ugt i64 %start, 100 97 %cmp1 = icmp ugt i64 %indvars.iv, 100 98 br i1 %cmp1, label %loop, label %for.end 99 100for.end: ; preds = %if.end, %entry 101 ret void 102} 103 104define void @test6(i64 %start) { 105; CHECK-LABEL: @test6 106entry: 107 br label %loop 108 109loop: 110 %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ] 111 %indvars.iv.next = add nuw i64 %indvars.iv, 1 112 %cmp = icmp eq i64 %indvars.iv.next, 25 113 br i1 %cmp, label %backedge, label %for.end 114 115backedge: 116 ; prevent flattening, needed to make sure we're testing what we intend 117 call void @foo() 118; CHECK: %cmp1 = icmp ult i64 %start, 100 119 %cmp1 = icmp ult i64 %indvars.iv, 100 120 br i1 %cmp1, label %for.end, label %loop 121 122for.end: ; preds = %if.end, %entry 123 ret void 124} 125 126define void @test7(i64 %start, i64* %inc_ptr) { 127; CHECK-LABEL: @test7 128entry: 129 %inc = load i64, i64* %inc_ptr, !range !0 130 %ok = icmp sge i64 %inc, 0 131 br i1 %ok, label %loop, label %for.end 132 133loop: 134 %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ] 135 %indvars.iv.next = add nsw i64 %indvars.iv, %inc 136; CHECK: %cmp1 = icmp slt i64 %start, -1 137 %cmp1 = icmp slt i64 %indvars.iv, -1 138 br i1 %cmp1, label %for.end, label %loop 139 140for.end: ; preds = %if.end, %entry 141 ret void 142} 143 144!0 = !{i64 0, i64 100} 145 146; Negative test - we can't show that the internal branch executes, so we can't 147; fold the test to a loop invariant one. 148define void @test1_neg(i64 %start) { 149; CHECK-LABEL: @test1_neg 150entry: 151 br label %loop 152 153loop: 154 %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ] 155 %indvars.iv.next = add nsw i64 %indvars.iv, 1 156 %cmp = icmp eq i64 %indvars.iv.next, 25 157 br i1 %cmp, label %backedge, label %skip 158skip: 159 ; prevent flattening, needed to make sure we're testing what we intend 160 call void @foo() 161; CHECK: %cmp1 = icmp slt i64 %indvars.iv, -1 162 %cmp1 = icmp slt i64 %indvars.iv, -1 163 br i1 %cmp1, label %for.end, label %backedge 164backedge: 165 ; prevent flattening, needed to make sure we're testing what we intend 166 call void @foo() 167 br label %loop 168 169for.end: ; preds = %if.end, %entry 170 ret void 171} 172 173; Slightly subtle version of @test4 where the icmp dominates the backedge, 174; but the exit branch doesn't. 175define void @test2_neg(i64 %start) { 176; CHECK-LABEL: @test2_neg 177entry: 178 br label %loop 179 180loop: 181 %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ] 182 %indvars.iv.next = add nsw i64 %indvars.iv, 1 183 %cmp = icmp eq i64 %indvars.iv.next, 25 184; CHECK: %cmp1 = icmp slt i64 %indvars.iv, -1 185 %cmp1 = icmp slt i64 %indvars.iv, -1 186 br i1 %cmp, label %backedge, label %skip 187skip: 188 ; prevent flattening, needed to make sure we're testing what we intend 189 call void @foo() 190 br i1 %cmp1, label %for.end, label %backedge 191backedge: 192 ; prevent flattening, needed to make sure we're testing what we intend 193 call void @foo() 194 br label %loop 195 196for.end: ; preds = %if.end, %entry 197 ret void 198} 199 200; The branch has to exit the loop if the condition is true 201define void @test3_neg(i64 %start) { 202; CHECK-LABEL: @test3_neg 203entry: 204 br label %loop 205 206loop: 207 %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ] 208 %indvars.iv.next = add nsw i64 %indvars.iv, 1 209; CHECK: %cmp1 = icmp slt i64 %indvars.iv, -1 210 %cmp1 = icmp slt i64 %indvars.iv, -1 211 br i1 %cmp1, label %loop, label %for.end 212 213for.end: ; preds = %if.end, %entry 214 ret void 215} 216 217define void @test4_neg(i64 %start) { 218; CHECK-LABEL: @test4_neg 219entry: 220 br label %loop 221 222loop: 223 %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ] 224 %indvars.iv.next = add nsw i64 %indvars.iv, 1 225 %cmp = icmp eq i64 %indvars.iv.next, 25 226 br i1 %cmp, label %backedge, label %for.end 227 228backedge: 229 ; prevent flattening, needed to make sure we're testing what we intend 230 call void @foo() 231; CHECK: %cmp1 = icmp sgt i64 %indvars.iv, -1 232 %cmp1 = icmp sgt i64 %indvars.iv, -1 233 234; %cmp1 can be made loop invariant only if the branch below goes to 235; %the header when %cmp1 is true. 236 br i1 %cmp1, label %for.end, label %loop 237 238for.end: ; preds = %if.end, %entry 239 ret void 240} 241 242define void @test5_neg(i64 %start, i64 %inc) { 243; CHECK-LABEL: @test5_neg 244entry: 245 br label %loop 246 247loop: 248 %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ] 249 %indvars.iv.next = add nsw i64 %indvars.iv, %inc 250; CHECK: %cmp1 = icmp slt i64 %indvars.iv, -1 251 %cmp1 = icmp slt i64 %indvars.iv, -1 252 br i1 %cmp1, label %for.end, label %loop 253 254for.end: ; preds = %if.end, %entry 255 ret void 256} 257 258define void @test8(i64 %start, i64* %inc_ptr) { 259; CHECK-LABEL: @test8 260entry: 261 %inc = load i64, i64* %inc_ptr, !range !1 262 %ok = icmp sge i64 %inc, 0 263 br i1 %ok, label %loop, label %for.end 264 265loop: 266 %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ] 267 %indvars.iv.next = add nsw i64 %indvars.iv, %inc 268; CHECK: %cmp1 = icmp slt i64 %indvars.iv, -1 269 %cmp1 = icmp slt i64 %indvars.iv, -1 270 br i1 %cmp1, label %for.end, label %loop 271 272for.end: ; preds = %if.end, %entry 273 ret void 274} 275 276!1 = !{i64 -1, i64 100} 277 278 279declare void @foo() 280