Home | History | Annotate | Download | only in IndVarSimplify
      1 ; RUN: opt < %s -indvars -indvars-post-increment-ranges -S | FileCheck %s
      2 
      3 target datalayout = "p:64:64:64-n32:64"
      4 
      5 ; When the IV in this loop is widened we want to widen this use as well:
      6 ; icmp slt i32 %i.inc, %limit
      7 ; In order to do this indvars need to prove that the narrow IV def (%i.inc)
      8 ; is not-negative from the range check inside of the loop.
      9 define void @test(i32* %base, i32 %limit, i32 %start) {
     10 ; CHECK-LABEL: @test(
     11 ; CHECK-NOT: trunc
     12 
     13 for.body.lr.ph:
     14   br label %for.body
     15 
     16 for.body:
     17   %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ]
     18   %within_limits = icmp ult i32 %i, 64
     19   br i1 %within_limits, label %continue, label %for.end
     20 
     21 continue:
     22   %i.i64 = zext i32 %i to i64
     23   %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64
     24   %val = load i32, i32* %arrayidx, align 4
     25   br label %for.inc
     26 
     27 for.inc:
     28   %i.inc = add nsw nuw i32 %i, 1
     29   %cmp = icmp slt i32 %i.inc, %limit
     30   br i1 %cmp, label %for.body, label %for.end
     31 
     32 for.end:
     33   br label %exit
     34 
     35 exit:
     36   ret void
     37 }
     38 
     39 define void @test_false_edge(i32* %base, i32 %limit, i32 %start) {
     40 ; CHECK-LABEL: @test_false_edge(
     41 ; CHECK-NOT: trunc
     42 
     43 for.body.lr.ph:
     44   br label %for.body
     45 
     46 for.body:
     47   %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ]
     48   %out_of_bounds = icmp ugt i32 %i, 64
     49   br i1 %out_of_bounds, label %for.end, label %continue
     50 
     51 continue:
     52   %i.i64 = zext i32 %i to i64
     53   %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64
     54   %val = load i32, i32* %arrayidx, align 4
     55   br label %for.inc
     56 
     57 for.inc:
     58   %i.inc = add nsw nuw i32 %i, 1
     59   %cmp = icmp slt i32 %i.inc, %limit
     60   br i1 %cmp, label %for.body, label %for.end
     61 
     62 for.end:
     63   br label %exit
     64 
     65 exit:
     66   ret void
     67 }
     68 
     69 define void @test_range_metadata(i32* %array_length_ptr, i32* %base,
     70                                  i32 %limit, i32 %start) {
     71 ; CHECK-LABEL: @test_range_metadata(
     72 ; CHECK-NOT: trunc
     73 
     74 for.body.lr.ph:
     75   br label %for.body
     76 
     77 for.body:
     78   %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ]
     79   %array_length = load i32, i32* %array_length_ptr, !range !{i32 0, i32 64 }
     80   %within_limits = icmp ult i32 %i, %array_length
     81   br i1 %within_limits, label %continue, label %for.end
     82 
     83 continue:
     84   %i.i64 = zext i32 %i to i64
     85   %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64
     86   %val = load i32, i32* %arrayidx, align 4
     87   br label %for.inc
     88 
     89 for.inc:
     90   %i.inc = add nsw nuw i32 %i, 1
     91   %cmp = icmp slt i32 %i.inc, %limit
     92   br i1 %cmp, label %for.body, label %for.end
     93 
     94 for.end:
     95   br label %exit
     96 
     97 exit:
     98   ret void
     99 }
    100 
    101 ; Negative version of the test above, we don't know anything about
    102 ; array_length_ptr range.
    103 define void @test_neg(i32* %array_length_ptr, i32* %base,
    104                       i32 %limit, i32 %start) {
    105 ; CHECK-LABEL: @test_neg(
    106 ; CHECK: trunc i64
    107 
    108 for.body.lr.ph:
    109   br label %for.body
    110 
    111 for.body:
    112   %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ]
    113   %array_length = load i32, i32* %array_length_ptr
    114   %within_limits = icmp ult i32 %i, %array_length
    115   br i1 %within_limits, label %continue, label %for.end
    116 
    117 continue:
    118   %i.i64 = zext i32 %i to i64
    119   %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64
    120   %val = load i32, i32* %arrayidx, align 4
    121   br label %for.inc
    122 
    123 for.inc:
    124   %i.inc = add nsw nuw i32 %i, 1
    125   %cmp = icmp slt i32 %i.inc, %limit
    126   br i1 %cmp, label %for.body, label %for.end
    127 
    128 for.end:
    129   br label %exit
    130 
    131 exit:
    132   ret void
    133 }
    134 
    135 define void @test_transitive_use(i32* %base, i32 %limit, i32 %start) {
    136 ; CHECK-LABEL: @test_transitive_use(
    137 ; CHECK-NOT: trunc
    138 ; CHECK: %result = icmp slt i64
    139 
    140 for.body.lr.ph:
    141   br label %for.body
    142 
    143 for.body:
    144   %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ]
    145   %within_limits = icmp ult i32 %i, 64
    146   br i1 %within_limits, label %continue, label %for.end
    147 
    148 continue:
    149   %i.mul.3 = mul nsw nuw i32 %i, 3
    150   %mul_within = icmp ult i32 %i.mul.3, 64
    151   br i1 %mul_within, label %guarded, label %continue.2
    152   
    153 guarded:
    154   %i.mul.3.inc = add nsw nuw i32 %i.mul.3, 1
    155   %result = icmp slt i32 %i.mul.3.inc, %limit
    156   br i1 %result, label %continue.2, label %for.end
    157 
    158 continue.2:
    159   %i.i64 = zext i32 %i to i64
    160   %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64
    161   %val = load i32, i32* %arrayidx, align 4
    162   br label %for.inc
    163 
    164 for.inc:
    165   %i.inc = add nsw nuw i32 %i, 1
    166   %cmp = icmp slt i32 %i.inc, %limit
    167   br i1 %cmp, label %for.body, label %for.end
    168 
    169 
    170 for.end:
    171   br label %exit
    172 
    173 exit:
    174   ret void
    175 }
    176 
    177 declare void @llvm.experimental.guard(i1, ...)
    178 
    179 define void @test_guard_one_bb(i32* %base, i32 %limit, i32 %start) {
    180 ; CHECK-LABEL: @test_guard_one_bb(
    181 ; CHECK-NOT: trunc
    182 ; CHECK-NOT: icmp slt i32
    183 
    184 for.body.lr.ph:
    185   br label %for.body
    186 
    187 for.body:
    188   %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.body ]
    189   %within_limits = icmp ult i32 %i, 64
    190   %i.i64 = zext i32 %i to i64
    191   %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64
    192   %val = load i32, i32* %arrayidx, align 4
    193   call void(i1, ...) @llvm.experimental.guard(i1 %within_limits) [ "deopt"() ]
    194   %i.inc = add nsw nuw i32 %i, 1
    195   %cmp = icmp slt i32 %i.inc, %limit
    196   br i1 %cmp, label %for.body, label %for.end
    197 
    198 for.end:
    199   br label %exit
    200 
    201 exit:
    202   ret void
    203 }
    204 
    205 define void @test_guard_in_the_same_bb(i32* %base, i32 %limit, i32 %start) {
    206 ; CHECK-LABEL: @test_guard_in_the_same_bb(
    207 ; CHECK-NOT: trunc
    208 ; CHECK-NOT: icmp slt i32
    209 
    210 for.body.lr.ph:
    211   br label %for.body
    212 
    213 for.body:
    214   %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ]
    215   %within_limits = icmp ult i32 %i, 64
    216   %i.i64 = zext i32 %i to i64
    217   %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64
    218   %val = load i32, i32* %arrayidx, align 4
    219   br label %for.inc
    220 
    221 for.inc:
    222   call void(i1, ...) @llvm.experimental.guard(i1 %within_limits) [ "deopt"() ]
    223   %i.inc = add nsw nuw i32 %i, 1
    224   %cmp = icmp slt i32 %i.inc, %limit
    225   br i1 %cmp, label %for.body, label %for.end
    226 
    227 for.end:
    228   br label %exit
    229 
    230 exit:
    231   ret void
    232 }
    233 
    234 define void @test_guard_in_idom(i32* %base, i32 %limit, i32 %start) {
    235 ; CHECK-LABEL: @test_guard_in_idom(
    236 ; CHECK-NOT: trunc
    237 ; CHECK-NOT: icmp slt i32
    238 
    239 for.body.lr.ph:
    240   br label %for.body
    241 
    242 for.body:
    243   %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ]
    244   %within_limits = icmp ult i32 %i, 64
    245   call void(i1, ...) @llvm.experimental.guard(i1 %within_limits) [ "deopt"() ]
    246   %i.i64 = zext i32 %i to i64
    247   %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64
    248   %val = load i32, i32* %arrayidx, align 4
    249   br label %for.inc
    250 
    251 for.inc:
    252   %i.inc = add nsw nuw i32 %i, 1
    253   %cmp = icmp slt i32 %i.inc, %limit
    254   br i1 %cmp, label %for.body, label %for.end
    255 
    256 for.end:
    257   br label %exit
    258 
    259 exit:
    260   ret void
    261 }
    262 
    263 define void @test_guard_merge_ranges(i32* %base, i32 %limit, i32 %start) {
    264 ; CHECK-LABEL: @test_guard_merge_ranges(
    265 ; CHECK-NOT: trunc
    266 ; CHECK-NOT: icmp slt i32
    267 
    268 for.body.lr.ph:
    269   br label %for.body
    270 
    271 for.body:
    272   %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.body ]
    273   %within_limits.1 = icmp ult i32 %i, 64
    274   call void(i1, ...) @llvm.experimental.guard(i1 %within_limits.1) [ "deopt"() ]
    275   %within_limits.2 = icmp ult i32 %i, 2147483647
    276   call void(i1, ...) @llvm.experimental.guard(i1 %within_limits.2) [ "deopt"() ]
    277   %i.i64 = zext i32 %i to i64
    278   %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64
    279   %val = load i32, i32* %arrayidx, align 4
    280   %i.inc = add nsw nuw i32 %i, 1
    281   %cmp = icmp slt i32 %i.inc, %limit
    282   br i1 %cmp, label %for.body, label %for.end
    283 
    284 for.end:
    285   br label %exit
    286 
    287 exit:
    288   ret void
    289 }
    290