1 ; RUN: opt -S -basicaa -licm < %s | FileCheck %s 2 ; RUN: opt -aa-pipeline=basic-aa -passes='require<opt-remark-emit>,loop(licm)' -S %s | FileCheck %s 3 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 4 target triple = "x86_64-unknown-linux-gnu" 5 6 declare void @f() nounwind 7 8 ; constant fold on first ieration 9 define i32 @test1(i32* noalias nocapture readonly %a) nounwind uwtable { 10 ; CHECK-LABEL: @test1( 11 entry: 12 ; CHECK: %i1 = load i32, i32* %a, align 4 13 ; CHECK-NEXT: br label %for.body 14 br label %for.body 15 16 for.body: 17 %iv = phi i32 [ 0, %entry ], [ %inc, %continue ] 18 %acc = phi i32 [ 0, %entry ], [ %add, %continue ] 19 %r.chk = icmp ult i32 %iv, 2000 20 br i1 %r.chk, label %continue, label %fail 21 continue: 22 %i1 = load i32, i32* %a, align 4 23 %add = add nsw i32 %i1, %acc 24 %inc = add nuw nsw i32 %iv, 1 25 %exitcond = icmp eq i32 %inc, 1000 26 br i1 %exitcond, label %for.cond.cleanup, label %for.body 27 28 for.cond.cleanup: 29 ret i32 %add 30 31 fail: 32 call void @f() 33 ret i32 -1 34 } 35 36 ; Same as test1, but with a floating point IR and fcmp 37 define i32 @test_fcmp(i32* noalias nocapture readonly %a) nounwind uwtable { 38 ; CHECK-LABEL: @test_fcmp( 39 entry: 40 ; CHECK: %i1 = load i32, i32* %a, align 4 41 ; CHECK-NEXT: br label %for.body 42 br label %for.body 43 44 for.body: 45 %iv = phi float [ 0.0, %entry ], [ %inc, %continue ] 46 %acc = phi i32 [ 0, %entry ], [ %add, %continue ] 47 %r.chk = fcmp olt float %iv, 2000.0 48 br i1 %r.chk, label %continue, label %fail 49 continue: 50 %i1 = load i32, i32* %a, align 4 51 %add = add nsw i32 %i1, %acc 52 %inc = fadd float %iv, 1.0 53 %exitcond = fcmp ogt float %inc, 1000.0 54 br i1 %exitcond, label %for.cond.cleanup, label %for.body 55 56 for.cond.cleanup: 57 ret i32 %add 58 59 fail: 60 call void @f() 61 ret i32 -1 62 } 63 64 ; Count down from a.length w/entry guard 65 ; TODO: currently unable to prove the following: 66 ; ule i32 (add nsw i32 %len, -1), %len where len is [0, 512] 67 define i32 @test2(i32* noalias nocapture readonly %a) nounwind uwtable { 68 ; CHECK-LABEL: @test2( 69 entry: 70 %len = load i32, i32* %a, align 4, !range !{i32 0, i32 512} 71 %is.non.pos = icmp eq i32 %len, 0 72 br i1 %is.non.pos, label %fail, label %preheader 73 preheader: 74 %lenminusone = add nsw i32 %len, -1 75 br label %for.body 76 for.body: 77 %iv = phi i32 [ %lenminusone, %preheader ], [ %dec, %continue ] 78 %acc = phi i32 [ 0, %preheader ], [ %add, %continue ] 79 %r.chk = icmp ule i32 %iv, %len 80 br i1 %r.chk, label %continue, label %fail 81 continue: 82 ; CHECK-LABEL: continue 83 ; CHECK: %i1 = load i32, i32* %a, align 4 84 %i1 = load i32, i32* %a, align 4 85 %add = add nsw i32 %i1, %acc 86 %dec = add nsw i32 %iv, -1 87 %exitcond = icmp eq i32 %dec, 0 88 br i1 %exitcond, label %for.cond.cleanup, label %for.body 89 90 for.cond.cleanup: 91 ret i32 %add 92 93 fail: 94 call void @f() 95 ret i32 -1 96 } 97 98 ; trivially true for zero 99 define i32 @test3(i32* noalias nocapture readonly %a) nounwind uwtable { 100 ; CHECK-LABEL: @test3( 101 entry: 102 %len = load i32, i32* %a, align 4, !range !{i32 0, i32 512} 103 %is.zero = icmp eq i32 %len, 0 104 br i1 %is.zero, label %fail, label %preheader 105 preheader: 106 ; CHECK: %i1 = load i32, i32* %a, align 4 107 ; CHECK-NEXT: br label %for.body 108 br label %for.body 109 for.body: 110 %iv = phi i32 [ 0, %preheader ], [ %inc, %continue ] 111 %acc = phi i32 [ 0, %preheader ], [ %add, %continue ] 112 %r.chk = icmp ule i32 %iv, %len 113 br i1 %r.chk, label %continue, label %fail 114 continue: 115 %i1 = load i32, i32* %a, align 4 116 %add = add nsw i32 %i1, %acc 117 %inc = add nuw nsw i32 %iv, 1 118 %exitcond = icmp eq i32 %inc, 1000 119 br i1 %exitcond, label %for.cond.cleanup, label %for.body 120 121 for.cond.cleanup: 122 ret i32 %add 123 124 fail: 125 call void @f() 126 ret i32 -1 127 } 128 129 ; requires fact length is non-zero 130 ; TODO: IsKnownNonNullFromDominatingConditions is currently only be done for 131 ; pointers; should handle integers too 132 define i32 @test4(i32* noalias nocapture readonly %a) nounwind uwtable { 133 ; CHECK-LABEL: @test4( 134 entry: 135 %len = load i32, i32* %a, align 4, !range !{i32 0, i32 512} 136 %is.zero = icmp eq i32 %len, 0 137 br i1 %is.zero, label %fail, label %preheader 138 preheader: 139 br label %for.body 140 for.body: 141 %iv = phi i32 [ 0, %preheader ], [ %inc, %continue ] 142 %acc = phi i32 [ 0, %preheader ], [ %add, %continue ] 143 %r.chk = icmp ult i32 %iv, %len 144 br i1 %r.chk, label %continue, label %fail 145 continue: 146 ; CHECK-LABEL: continue 147 ; CHECK: %i1 = load i32, i32* %a, align 4 148 %i1 = load i32, i32* %a, align 4 149 %add = add nsw i32 %i1, %acc 150 %inc = add nuw nsw i32 %iv, 1 151 %exitcond = icmp eq i32 %inc, 1000 152 br i1 %exitcond, label %for.cond.cleanup, label %for.body 153 154 for.cond.cleanup: 155 ret i32 %add 156 157 fail: 158 call void @f() 159 ret i32 -1 160 } 161 162 ; variation on test1 with branch swapped 163 define i32 @test-brswap(i32* noalias nocapture readonly %a) nounwind uwtable { 164 ; CHECK-LABEL: @test-brswap( 165 entry: 166 ; CHECK: %i1 = load i32, i32* %a, align 4 167 ; CHECK-NEXT: br label %for.body 168 br label %for.body 169 170 for.body: 171 %iv = phi i32 [ 0, %entry ], [ %inc, %continue ] 172 %acc = phi i32 [ 0, %entry ], [ %add, %continue ] 173 %r.chk = icmp ugt i32 %iv, 2000 174 br i1 %r.chk, label %fail, label %continue 175 continue: 176 %i1 = load i32, i32* %a, align 4 177 %add = add nsw i32 %i1, %acc 178 %inc = add nuw nsw i32 %iv, 1 179 %exitcond = icmp eq i32 %inc, 1000 180 br i1 %exitcond, label %for.cond.cleanup, label %for.body 181 182 for.cond.cleanup: 183 ret i32 %add 184 185 fail: 186 call void @f() 187 ret i32 -1 188 } 189 190 define i32 @test-nonphi(i32* noalias nocapture readonly %a) nounwind uwtable { 191 ; CHECK-LABEL: @test-nonphi( 192 entry: 193 br label %for.body 194 195 for.body: 196 ; CHECK-LABEL: continue 197 ; CHECK: %i1 = load i32, i32* %a, align 4 198 %iv = phi i32 [ 0, %entry ], [ %inc, %continue ] 199 %acc = phi i32 [ 0, %entry ], [ %add, %continue ] 200 %xor = xor i32 %iv, 72 201 %r.chk = icmp ugt i32 %xor, 2000 202 br i1 %r.chk, label %fail, label %continue 203 continue: 204 %i1 = load i32, i32* %a, align 4 205 %add = add nsw i32 %i1, %acc 206 %inc = add nuw nsw i32 %iv, 1 207 %exitcond = icmp eq i32 %inc, 1000 208 br i1 %exitcond, label %for.cond.cleanup, label %for.body 209 210 for.cond.cleanup: 211 ret i32 %add 212 213 fail: 214 call void @f() 215 ret i32 -1 216 } 217 218 define i32 @test-wrongphi(i32* noalias nocapture readonly %a) nounwind uwtable { 219 ; CHECK-LABEL: @test-wrongphi( 220 entry: 221 br label %for.body 222 223 for.body: 224 %iv = phi i32 [ 0, %entry ], [ %inc, %continue ] 225 %acc = phi i32 [ 0, %entry ], [ %add, %continue ] 226 %cond = icmp ult i32 %iv, 500 227 br i1 %cond, label %dummy_block1, label %dummy_block2 228 229 dummy_block1: 230 br label %dummy_block2 231 232 dummy_block2: 233 %wrongphi = phi i32 [11, %for.body], [12, %dummy_block1] 234 %r.chk = icmp ugt i32 %wrongphi, 2000 235 br i1 %r.chk, label %fail, label %continue 236 continue: 237 ; CHECK-LABEL: continue 238 ; CHECK: %i1 = load i32, i32* %a, align 4 239 %i1 = load i32, i32* %a, align 4 240 %add = add nsw i32 %i1, %acc 241 %inc = add nuw nsw i32 %iv, 1 242 %exitcond = icmp eq i32 %inc, 1000 243 br i1 %exitcond, label %for.cond.cleanup, label %for.body 244 245 for.cond.cleanup: 246 ret i32 %add 247 248 fail: 249 call void @f() 250 ret i32 -1 251 } 252 253 ; This works because loop-simplify is run implicitly, but test for it anyways 254 define i32 @test-multiple-latch(i32* noalias nocapture readonly %a) nounwind uwtable { 255 ; CHECK-LABEL: @test-multiple-latch( 256 entry: 257 ; CHECK: %i1 = load i32, i32* %a, align 4 258 ; CHECK-NEXT: br label %for.body 259 br label %for.body 260 261 for.body: 262 %iv = phi i32 [ 0, %entry ], [ %inc, %continue1 ], [ %inc, %continue2 ] 263 %acc = phi i32 [ 0, %entry ], [ %add, %continue1 ], [ %add, %continue2 ] 264 %r.chk = icmp ult i32 %iv, 2000 265 br i1 %r.chk, label %continue1, label %fail 266 continue1: 267 %i1 = load i32, i32* %a, align 4 268 %add = add nsw i32 %i1, %acc 269 %inc = add nuw nsw i32 %iv, 1 270 %cmp = icmp eq i32 %add, 0 271 br i1 %cmp, label %continue2, label %for.body 272 continue2: 273 %exitcond = icmp eq i32 %inc, 1000 274 br i1 %exitcond, label %for.cond.cleanup, label %for.body 275 276 for.cond.cleanup: 277 ret i32 %add 278 279 fail: 280 call void @f() 281 ret i32 -1 282 } 283