Home | History | Annotate | Download | only in LoopPredication
      1 ; RUN: opt -S -loop-predication < %s 2>&1 | FileCheck %s
      2 ; RUN: opt -S -passes='require<scalar-evolution>,loop(loop-predication)' < %s 2>&1 | FileCheck %s
      3 
      4 declare void @llvm.experimental.guard(i1, ...)
      5 
      6 define i32 @signed_loop_0_to_n_nested_0_to_l_inner_index_check(i32* %array, i32 %length, i32 %n, i32 %l) {
      7 ; CHECK-LABEL: @signed_loop_0_to_n_nested_0_to_l_inner_index_check
      8 entry:
      9   %tmp5 = icmp sle i32 %n, 0
     10   br i1 %tmp5, label %exit, label %outer.loop.preheader
     11 
     12 outer.loop.preheader:
     13   br label %outer.loop
     14 
     15 outer.loop:
     16   %outer.loop.acc = phi i32 [ %outer.loop.acc.next, %outer.loop.inc ], [ 0, %outer.loop.preheader ]
     17   %i = phi i32 [ %i.next, %outer.loop.inc ], [ 0, %outer.loop.preheader ]
     18   %tmp6 = icmp sle i32 %l, 0
     19   br i1 %tmp6, label %outer.loop.inc, label %inner.loop.preheader
     20   
     21 inner.loop.preheader:
     22 ; CHECK: inner.loop.preheader:
     23 ; CHECK: [[limit_check:[^ ]+]] = icmp sle i32 %l, %length
     24 ; CHECK-NEXT: [[first_iteration_check:[^ ]+]] = icmp ult i32 0, %length
     25 ; CHECK-NEXT: [[wide_cond:[^ ]+]] = and i1 [[first_iteration_check]], [[limit_check]]
     26 ; CHECK-NEXT: br label %inner.loop
     27   br label %inner.loop
     28 
     29 inner.loop:
     30 ; CHECK: inner.loop:
     31 ; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ]
     32   %inner.loop.acc = phi i32 [ %inner.loop.acc.next, %inner.loop ], [ %outer.loop.acc, %inner.loop.preheader ]
     33   %j = phi i32 [ %j.next, %inner.loop ], [ 0, %inner.loop.preheader ]
     34 
     35   %within.bounds = icmp ult i32 %j, %length
     36   call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
     37   
     38   %j.i64 = zext i32 %j to i64
     39   %array.j.ptr = getelementptr inbounds i32, i32* %array, i64 %j.i64
     40   %array.j = load i32, i32* %array.j.ptr, align 4
     41   %inner.loop.acc.next = add i32 %inner.loop.acc, %array.j
     42 
     43   %j.next = add nsw i32 %j, 1
     44   %inner.continue = icmp slt i32 %j.next, %l
     45   br i1 %inner.continue, label %inner.loop, label %outer.loop.inc
     46 
     47 outer.loop.inc:
     48   %outer.loop.acc.next = phi i32 [ %inner.loop.acc.next, %inner.loop ], [ %outer.loop.acc, %outer.loop ]
     49   %i.next = add nsw i32 %i, 1
     50   %outer.continue = icmp slt i32 %i.next, %n
     51   br i1 %outer.continue, label %outer.loop, label %exit
     52 
     53 exit:
     54   %result = phi i32 [ 0, %entry ], [ %outer.loop.acc.next, %outer.loop.inc ]
     55   ret i32 %result
     56 }
     57 
     58 define i32 @signed_loop_0_to_n_nested_0_to_l_outer_index_check(i32* %array, i32 %length, i32 %n, i32 %l) {
     59 ; CHECK-LABEL: @signed_loop_0_to_n_nested_0_to_l_outer_index_check
     60 entry:
     61   %tmp5 = icmp sle i32 %n, 0
     62   br i1 %tmp5, label %exit, label %outer.loop.preheader
     63 
     64 outer.loop.preheader:
     65 ; CHECK: outer.loop.preheader:
     66 ; CHECK: [[limit_check:[^ ]+]] = icmp sle i32 %n, %length
     67 ; CHECK-NEXT: [[first_iteration_check:[^ ]+]] = icmp ult i32 0, %length
     68 ; CHECK-NEXT: [[wide_cond:[^ ]+]] = and i1 [[first_iteration_check]], [[limit_check]]
     69 ; CHECK-NEXT: br label %outer.loop
     70   br label %outer.loop
     71 
     72 outer.loop:
     73   %outer.loop.acc = phi i32 [ %outer.loop.acc.next, %outer.loop.inc ], [ 0, %outer.loop.preheader ]
     74   %i = phi i32 [ %i.next, %outer.loop.inc ], [ 0, %outer.loop.preheader ]
     75   %tmp6 = icmp sle i32 %l, 0
     76   br i1 %tmp6, label %outer.loop.inc, label %inner.loop.preheader
     77   
     78 inner.loop.preheader:
     79   br label %inner.loop
     80 
     81 inner.loop:
     82 ; CHECK: inner.loop:
     83 ; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ]
     84 
     85   %inner.loop.acc = phi i32 [ %inner.loop.acc.next, %inner.loop ], [ %outer.loop.acc, %inner.loop.preheader ]
     86   %j = phi i32 [ %j.next, %inner.loop ], [ 0, %inner.loop.preheader ]
     87 
     88   %within.bounds = icmp ult i32 %i, %length
     89   call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
     90   
     91   %i.i64 = zext i32 %i to i64
     92   %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
     93   %array.i = load i32, i32* %array.i.ptr, align 4
     94   %inner.loop.acc.next = add i32 %inner.loop.acc, %array.i
     95 
     96   %j.next = add nsw i32 %j, 1
     97   %inner.continue = icmp slt i32 %j.next, %l
     98   br i1 %inner.continue, label %inner.loop, label %outer.loop.inc
     99 
    100 outer.loop.inc:
    101   %outer.loop.acc.next = phi i32 [ %inner.loop.acc.next, %inner.loop ], [ %outer.loop.acc, %outer.loop ]
    102   %i.next = add nsw i32 %i, 1
    103   %outer.continue = icmp slt i32 %i.next, %n
    104   br i1 %outer.continue, label %outer.loop, label %exit
    105 
    106 exit:
    107   %result = phi i32 [ 0, %entry ], [ %outer.loop.acc.next, %outer.loop.inc ]
    108   ret i32 %result
    109 }
    110 
    111 define i32 @signed_loop_0_to_n_nested_i_to_l_inner_index_check(i32* %array, i32 %length, i32 %n, i32 %l) {
    112 ; CHECK-LABEL: @signed_loop_0_to_n_nested_i_to_l_inner_index_check
    113 entry:
    114   %tmp5 = icmp sle i32 %n, 0
    115   br i1 %tmp5, label %exit, label %outer.loop.preheader
    116 
    117 outer.loop.preheader:
    118 ; CHECK: outer.loop.preheader:
    119 ; CHECK-NEXT: [[limit_check_outer:[^ ]+]] = icmp sle i32 %n, %length
    120 ; CHECK-NEXT: [[first_iteration_check_outer:[^ ]+]] = icmp ult i32 0, %length
    121 ; CHECK-NEXT: [[wide_cond_outer:[^ ]+]] = and i1 [[first_iteration_check_outer]], [[limit_check_outer]]
    122 ; CHECK-NEXT: br label %outer.loop
    123   br label %outer.loop
    124 
    125 outer.loop:
    126 ; CHECK: outer.loop:
    127   %outer.loop.acc = phi i32 [ %outer.loop.acc.next, %outer.loop.inc ], [ 0, %outer.loop.preheader ]
    128   %i = phi i32 [ %i.next, %outer.loop.inc ], [ 0, %outer.loop.preheader ]
    129   %tmp6 = icmp sle i32 %l, 0
    130   br i1 %tmp6, label %outer.loop.inc, label %inner.loop.preheader
    131   
    132 inner.loop.preheader:
    133 ; CHECK: inner.loop.preheader:
    134 ; CHECK: [[limit_check_inner:[^ ]+]] = icmp sle i32 %l, %length
    135 ; CHECK: br label %inner.loop
    136   br label %inner.loop
    137 
    138 inner.loop:
    139 ; CHECK: inner.loop:
    140 ; CHECK: [[wide_cond:[^ ]+]] = and i1 [[limit_check_inner]], [[wide_cond_outer]]
    141 ; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ]
    142   %inner.loop.acc = phi i32 [ %inner.loop.acc.next, %inner.loop ], [ %outer.loop.acc, %inner.loop.preheader ]
    143   %j = phi i32 [ %j.next, %inner.loop ], [ %i, %inner.loop.preheader ]
    144 
    145   %within.bounds = icmp ult i32 %j, %length
    146   call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
    147   
    148   %j.i64 = zext i32 %j to i64
    149   %array.j.ptr = getelementptr inbounds i32, i32* %array, i64 %j.i64
    150   %array.j = load i32, i32* %array.j.ptr, align 4
    151   %inner.loop.acc.next = add i32 %inner.loop.acc, %array.j
    152 
    153   %j.next = add nsw i32 %j, 1
    154   %inner.continue = icmp slt i32 %j.next, %l
    155   br i1 %inner.continue, label %inner.loop, label %outer.loop.inc
    156 
    157 outer.loop.inc:
    158   %outer.loop.acc.next = phi i32 [ %inner.loop.acc.next, %inner.loop ], [ %outer.loop.acc, %outer.loop ]
    159   %i.next = add nsw i32 %i, 1
    160   %outer.continue = icmp slt i32 %i.next, %n
    161   br i1 %outer.continue, label %outer.loop, label %exit
    162 
    163 exit:
    164   %result = phi i32 [ 0, %entry ], [ %outer.loop.acc.next, %outer.loop.inc ]
    165   ret i32 %result
    166 }
    167 
    168 define i32 @cant_expand_guard_check_start(i32* %array, i32 %length, i32 %n, i32 %l, i32 %maybezero) {
    169 ; CHECK-LABEL: @cant_expand_guard_check_start
    170 entry:
    171   %tmp5 = icmp sle i32 %n, 0
    172   br i1 %tmp5, label %exit, label %outer.loop.preheader
    173 
    174 outer.loop.preheader:
    175   br label %outer.loop
    176 
    177 outer.loop:
    178   %outer.loop.acc = phi i32 [ %outer.loop.acc.next, %outer.loop.inc ], [ 0, %outer.loop.preheader ]
    179   %i = phi i32 [ %i.next, %outer.loop.inc ], [ 0, %outer.loop.preheader ]
    180   %tmp6 = icmp sle i32 %l, 0
    181   %div = udiv i32 %i, %maybezero
    182   br i1 %tmp6, label %outer.loop.inc, label %inner.loop.preheader
    183   
    184 inner.loop.preheader:
    185 ; CHECK: inner.loop.preheader:
    186 ; CHECK: br label %inner.loop
    187   br label %inner.loop
    188 
    189 inner.loop:
    190 ; CHECK: inner.loop:
    191 ; CHECK: %within.bounds = icmp ult i32 %j, %length
    192 ; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
    193   %inner.loop.acc = phi i32 [ %inner.loop.acc.next, %inner.loop ], [ %outer.loop.acc, %inner.loop.preheader ]
    194   %j = phi i32 [ %j.next, %inner.loop ], [ %div, %inner.loop.preheader ]
    195 
    196   %within.bounds = icmp ult i32 %j, %length
    197   call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
    198   
    199   %j.i64 = zext i32 %j to i64
    200   %array.j.ptr = getelementptr inbounds i32, i32* %array, i64 %j.i64
    201   %array.j = load i32, i32* %array.j.ptr, align 4
    202   %inner.loop.acc.next = add i32 %inner.loop.acc, %array.j
    203 
    204   %j.next = add nsw i32 %j, 1
    205   %inner.continue = icmp slt i32 %j.next, %l
    206   br i1 %inner.continue, label %inner.loop, label %outer.loop.inc
    207 
    208 outer.loop.inc:
    209   %outer.loop.acc.next = phi i32 [ %inner.loop.acc.next, %inner.loop ], [ %outer.loop.acc, %outer.loop ]
    210   %i.next = add nsw i32 %i, 1
    211   %outer.continue = icmp slt i32 %i.next, %n
    212   br i1 %outer.continue, label %outer.loop, label %exit
    213 
    214 exit:
    215   %result = phi i32 [ 0, %entry ], [ %outer.loop.acc.next, %outer.loop.inc ]
    216   ret i32 %result
    217 }