1 ; RUN: opt -S -indvars %s | FileCheck %s 2 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 3 target triple = "x86_64-unknown-linux-gnu" 4 5 define void @test1(i64 %start) { 6 ; CHECK-LABEL: @test1 7 entry: 8 br label %loop 9 10 loop: 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 17 for.end: ; preds = %if.end, %entry 18 ret void 19 } 20 21 define void @test2(i64 %start) { 22 ; CHECK-LABEL: @test2 23 entry: 24 br label %loop 25 26 loop: 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 33 for.end: ; preds = %if.end, %entry 34 ret void 35 } 36 37 ; As long as the test dominates the backedge, we're good 38 define void @test3(i64 %start) { 39 ; CHECK-LABEL: @test3 40 entry: 41 br label %loop 42 43 loop: 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 49 backedge: 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 56 for.end: ; preds = %if.end, %entry 57 ret void 58 } 59 60 define void @test4(i64 %start) { 61 ; CHECK-LABEL: @test4 62 entry: 63 br label %loop 64 65 loop: 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 71 backedge: 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 78 for.end: ; preds = %if.end, %entry 79 ret void 80 } 81 82 define void @test5(i64 %start) { 83 ; CHECK-LABEL: @test5 84 entry: 85 br label %loop 86 87 loop: 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 93 backedge: 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 100 for.end: ; preds = %if.end, %entry 101 ret void 102 } 103 104 define void @test6(i64 %start) { 105 ; CHECK-LABEL: @test6 106 entry: 107 br label %loop 108 109 loop: 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 115 backedge: 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 122 for.end: ; preds = %if.end, %entry 123 ret void 124 } 125 126 define void @test7(i64 %start, i64* %inc_ptr) { 127 ; CHECK-LABEL: @test7 128 entry: 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 133 loop: 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 140 for.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. 148 define void @test1_neg(i64 %start) { 149 ; CHECK-LABEL: @test1_neg 150 entry: 151 br label %loop 152 153 loop: 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 158 skip: 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 164 backedge: 165 ; prevent flattening, needed to make sure we're testing what we intend 166 call void @foo() 167 br label %loop 168 169 for.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. 175 define void @test2_neg(i64 %start) { 176 ; CHECK-LABEL: @test2_neg 177 entry: 178 br label %loop 179 180 loop: 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 187 skip: 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 191 backedge: 192 ; prevent flattening, needed to make sure we're testing what we intend 193 call void @foo() 194 br label %loop 195 196 for.end: ; preds = %if.end, %entry 197 ret void 198 } 199 200 ; The branch has to exit the loop if the condition is true 201 define void @test3_neg(i64 %start) { 202 ; CHECK-LABEL: @test3_neg 203 entry: 204 br label %loop 205 206 loop: 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 213 for.end: ; preds = %if.end, %entry 214 ret void 215 } 216 217 define void @test4_neg(i64 %start) { 218 ; CHECK-LABEL: @test4_neg 219 entry: 220 br label %loop 221 222 loop: 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 228 backedge: 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 238 for.end: ; preds = %if.end, %entry 239 ret void 240 } 241 242 define void @test5_neg(i64 %start, i64 %inc) { 243 ; CHECK-LABEL: @test5_neg 244 entry: 245 br label %loop 246 247 loop: 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 254 for.end: ; preds = %if.end, %entry 255 ret void 256 } 257 258 define void @test8(i64 %start, i64* %inc_ptr) { 259 ; CHECK-LABEL: @test8 260 entry: 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 265 loop: 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 272 for.end: ; preds = %if.end, %entry 273 ret void 274 } 275 276 !1 = !{i64 -1, i64 100} 277 278 279 declare void @foo() 280