Home | History | Annotate | Download | only in LoopUnswitch
      1 ; RUN: opt -S -loop-unswitch < %s | FileCheck %s
      2 
      3 declare void @llvm.experimental.guard(i1, ...)
      4 
      5 define void @f_0(i32 %n, i32* %ptr, i1 %c) {
      6 ; CHECK-LABEL: @f_0(
      7 ; CHECK: loop.us:
      8 ; CHECK-NOT: guard
      9 ; CHECK: loop:
     10 ; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ]
     11 entry:
     12   br label %loop
     13 
     14 loop:
     15   %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
     16   %iv.inc = add i32 %iv, 1
     17   call void(i1, ...) @llvm.experimental.guard(i1 %c) [ "deopt"() ]
     18   store volatile i32 0, i32* %ptr
     19   %becond = icmp ult i32 %iv.inc, %n
     20   br i1 %becond, label %leave, label %loop
     21 
     22 leave:
     23   ret void
     24 }
     25 
     26 define void @f_1(i32 %n, i32* %ptr, i1 %c_0, i1 %c_1) {
     27 ; CHECK-LABEL: @f_1(
     28 ; CHECK: loop.us.us:
     29 ; CHECK-NOT: guard
     30 ; CHECK: loop.us:
     31 ; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"(i32 2) ]
     32 ; CHECK-NOT: guard
     33 ; CHECK: loop.us1:
     34 ; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"(i32 1) ]
     35 ; CHECK-NOT: guard
     36 ; CHECK: loop:
     37 ; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"(i32 1) ]
     38 ; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"(i32 2) ]
     39 entry:
     40   br label %loop
     41 
     42 loop:
     43   %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
     44   %iv.inc = add i32 %iv, 1
     45   call void(i1, ...) @llvm.experimental.guard(i1 %c_0) [ "deopt"(i32 1) ]
     46   store volatile i32 0, i32* %ptr
     47   call void(i1, ...) @llvm.experimental.guard(i1 %c_1) [ "deopt"(i32 2) ]
     48   %becond = icmp ult i32 %iv.inc, %n
     49   br i1 %becond, label %leave, label %loop
     50 
     51 leave:
     52   ret void
     53 }
     54 
     55 ; Basic negative test
     56 
     57 define void @f_3(i32 %n, i32* %ptr, i1* %c_ptr) {
     58 ; CHECK-LABEL: @f_3(
     59 ; CHECK-NOT: loop.us:
     60 entry:
     61   br label %loop
     62 
     63 loop:
     64   %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
     65   %iv.inc = add i32 %iv, 1
     66   %c = load volatile i1, i1* %c_ptr
     67   call void(i1, ...) @llvm.experimental.guard(i1 %c) [ "deopt"() ]
     68   store volatile i32 0, i32* %ptr
     69   %becond = icmp ult i32 %iv.inc, %n
     70   br i1 %becond, label %leave, label %loop
     71 
     72 leave:
     73   ret void
     74 }
     75 
     76 define void @f_4(i32 %n, i32* %ptr, i1 %c) {
     77 ; CHECK-LABEL: @f_4(
     78 ;
     79 ; Demonstrate that unswitching on one guard can cause another guard to
     80 ; be erased (this has implications on what guards we can keep raw
     81 ; pointers to).
     82 entry:
     83   br label %loop
     84 
     85 loop:
     86   %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
     87   %iv.inc = add i32 %iv, 1
     88   call void(i1, ...) @llvm.experimental.guard(i1 %c) [ "deopt"(i32 1) ]
     89   store volatile i32 0, i32* %ptr
     90   %neg = xor i1 %c, 1
     91   call void(i1, ...) @llvm.experimental.guard(i1 %neg) [ "deopt"(i32 2) ]
     92   %becond = icmp ult i32 %iv.inc, %n
     93   br i1 %becond, label %leave, label %loop
     94 
     95 leave:
     96   ret void
     97 }
     98