Home | History | Annotate | Download | only in ScalarEvolution
      1 ; RUN: opt -S -indvars < %s | FileCheck %s
      2 
      3 ; Check that SCEV is able to recognize and use guards to prove
      4 ; conditions gaurding loop entries and backedges.  This isn't intended
      5 ; to be a comprehensive test of SCEV's simplification capabilities,
      6 ; tests directly testing e.g. if SCEV can elide a sext should go
      7 ; elsewhere.
      8 
      9 target datalayout = "n8:16:32:64"
     10 
     11 declare void @llvm.experimental.guard(i1, ...)
     12 
     13 declare void @use(i64 %x)
     14 
     15 define void @test_1(i1* %cond_buf, i32* %len_buf) {
     16 ; CHECK-LABEL: @test_1(
     17 entry:
     18   %len = load i32, i32* %len_buf, !range !{i32 1, i32 2147483648}
     19   br label %loop
     20 
     21 loop:
     22 ; CHECK: loop:
     23 ; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 true) [ "deopt"() ]
     24 ; CHECK:  %iv.inc.cmp = icmp ult i32 %iv.inc, %len
     25 ; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ]
     26 ; CHECK: leave:
     27 
     28   %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
     29   %iv.inc = add i32 %iv, 1
     30 
     31   %iv.cmp = icmp slt i32 %iv, %len
     32   call void(i1, ...) @llvm.experimental.guard(i1 %iv.cmp) [ "deopt"() ]
     33 
     34   %iv.inc.cmp = icmp slt i32 %iv.inc, %len
     35   call void(i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ]
     36 
     37   %becond = load volatile i1, i1* %cond_buf
     38   br i1 %becond, label %loop, label %leave
     39 
     40 leave:
     41   ret void
     42 }
     43 
     44 define void @test_2(i32 %n, i32* %len_buf) {
     45 ; CHECK-LABEL: @test_2(
     46 ; CHECK:  [[LEN_ZEXT:%[^ ]+]] = zext i32 %len to i64
     47 ; CHECK:  br label %loop
     48 
     49 entry:
     50   %len = load i32, i32* %len_buf, !range !{i32 0, i32 2147483648}
     51   br label %loop
     52 
     53 loop:
     54 ; CHECK: loop:
     55 ; CHECK:  %indvars.iv = phi i64 [ %indvars.iv.next, %loop ], [ 0, %entry ]
     56 ; CHECK:  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
     57 ; CHECK:  %iv.inc.cmp = icmp ult i64 %indvars.iv.next, [[LEN_ZEXT]]
     58 ; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ]
     59 ; CHECK: leave:
     60 
     61   %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
     62   %iv.inc = add i32 %iv, 1
     63 
     64   %iv.sext = sext i32 %iv to i64
     65   call void @use(i64 %iv.sext)
     66 
     67   %iv.inc.cmp = icmp slt i32 %iv.inc, %len
     68   call void(i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ]
     69 
     70   %becond = icmp ne i32 %iv, %n
     71   br i1 %becond, label %loop, label %leave
     72 
     73 leave:
     74   ret void
     75 }
     76 
     77 define void @test_3(i1* %cond_buf, i32* %len_buf) {
     78 ; CHECK-LABEL: @test_3(
     79 
     80 entry:
     81   %len = load i32, i32* %len_buf
     82   %entry.cond = icmp sgt i32 %len, 0
     83   call void(i1, ...) @llvm.experimental.guard(i1 %entry.cond) [ "deopt"() ]
     84   br label %loop
     85 
     86 loop:
     87 ; CHECK: loop:
     88 ; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 true) [ "deopt"() ]
     89 ; CHECK:  %iv.inc.cmp = icmp slt i32 %iv.inc, %len
     90 ; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ]
     91 ; CHECK: leave:
     92   %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
     93   %iv.inc = add i32 %iv, 1
     94 
     95   %iv.cmp = icmp slt i32 %iv, %len
     96   call void(i1, ...) @llvm.experimental.guard(i1 %iv.cmp) [ "deopt"() ]
     97 
     98   %iv.inc.cmp = icmp slt i32 %iv.inc, %len
     99   call void(i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ]
    100 
    101   %becond = load volatile i1, i1* %cond_buf
    102   br i1 %becond, label %loop, label %leave
    103 
    104 leave:
    105   ret void
    106 }
    107 
    108 define void @test_4(i1* %cond_buf, i32* %len_buf) {
    109 ; CHECK-LABEL: @test_4(
    110 
    111 entry:
    112   %len = load i32, i32* %len_buf
    113   %entry.cond = icmp sgt i32 %len, 0
    114   call void(i1, ...) @llvm.experimental.guard(i1 %entry.cond) [ "deopt"() ]
    115   br label %loop
    116 
    117 loop:
    118   %iv = phi i32 [ 0, %entry ], [ %iv.inc, %be ]
    119   %iv.inc = add i32 %iv, 1
    120 
    121   %cond = load volatile i1, i1* %cond_buf
    122   br i1 %cond, label %left, label %be
    123 
    124 left:
    125   ; Does not dominate the backedge, so cannot be used in the inductive proof
    126   %iv.inc.cmp = icmp slt i32 %iv.inc, %len
    127   call void(i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ]
    128   br label %be
    129 
    130 be:
    131 ; CHECK: be:
    132 ; CHECK-NEXT:  %iv.cmp = icmp slt i32 %iv, %len
    133 ; CHECK-NEXT:  call void (i1, ...) @llvm.experimental.guard(i1 %iv.cmp) [ "deopt"() ]
    134 ; CHECK: leave:
    135 
    136   %iv.cmp = icmp slt i32 %iv, %len
    137   call void(i1, ...) @llvm.experimental.guard(i1 %iv.cmp) [ "deopt"() ]
    138 
    139   %becond = load volatile i1, i1* %cond_buf
    140   br i1 %becond, label %loop, label %leave
    141 
    142 leave:
    143   ret void
    144 }
    145