Home | History | Annotate | Download | only in JumpThreading
      1 ; RUN: opt -S -jump-threading < %s | FileCheck %s
      2 
      3 declare void @foo()
      4 declare void @bar()
      5 declare void @baz()
      6 declare void @quux()
      7 
      8 
      9 ; Jump threading of branch with select as condition.
     10 ; Mostly theoretical since instruction combining simplifies all selects of
     11 ; booleans where at least one operand is true/false/undef.
     12 
     13 ; CHECK-LABEL: @test_br(
     14 ; CHECK-NEXT: entry:
     15 ; CHECK-NEXT: br i1 %cond, label %L1,
     16 define void @test_br(i1 %cond, i1 %value) nounwind {
     17 entry:
     18   br i1 %cond, label %L0, label %L3
     19 L0:
     20   %expr = select i1 %cond, i1 true, i1 %value
     21   br i1 %expr, label %L1, label %L2
     22 
     23 L1:
     24   call void @foo()
     25   ret void
     26 L2:
     27   call void @bar()
     28   ret void
     29 L3:
     30   call void @baz()
     31   br label %L0
     32 }
     33 
     34 
     35 ; Jump threading of switch with select as condition.
     36 
     37 ; CHECK-LABEL: @test_switch(
     38 ; CHECK-NEXT: entry:
     39 ; CHECK-NEXT: br i1 %cond, label %L1,
     40 define void @test_switch(i1 %cond, i8 %value) nounwind {
     41 entry:
     42   br i1 %cond, label %L0, label %L4
     43 L0:
     44   %expr = select i1 %cond, i8 1, i8 %value
     45   switch i8 %expr, label %L3 [i8 1, label %L1 i8 2, label %L2]
     46 
     47 L1:
     48   call void @foo()
     49   ret void
     50 L2:
     51   call void @bar()
     52   ret void
     53 L3:
     54   call void @baz()
     55   ret void
     56 L4:
     57   call void @quux()
     58   br label %L0
     59 }
     60 
     61 ; Make sure the blocks in the indirectbr test aren't trivially removable as
     62 ; successors by taking their addresses.
     63 @anchor = constant [3 x i8*] [
     64   i8* blockaddress(@test_indirectbr, %L1),
     65   i8* blockaddress(@test_indirectbr, %L2),
     66   i8* blockaddress(@test_indirectbr, %L3)
     67 ]
     68 
     69 
     70 ; Jump threading of indirectbr with select as address.
     71 
     72 ; CHECK-LABEL: @test_indirectbr(
     73 ; CHECK-NEXT: entry:
     74 ; CHECK-NEXT: br i1 %cond, label %L1, label %L3
     75 define void @test_indirectbr(i1 %cond, i8* %address) nounwind {
     76 entry:
     77   br i1 %cond, label %L0, label %L3
     78 L0:
     79   %indirect.goto.dest = select i1 %cond, i8* blockaddress(@test_indirectbr, %L1), i8* %address
     80   indirectbr i8* %indirect.goto.dest, [label %L1, label %L2, label %L3]
     81 
     82 L1:
     83   call void @foo()
     84   ret void
     85 L2:
     86   call void @bar()
     87   ret void
     88 L3:
     89   call void @baz()
     90   ret void
     91 }
     92 
     93 
     94 ; Jump threading of indirectbr with select as address.  Test increased
     95 ; duplication threshold for cases where indirectbr is being threaded
     96 ; through.
     97 
     98 ; CHECK-LABEL: @test_indirectbr_thresh(
     99 ; CHECK-NEXT: entry:
    100 ; CHECK-NEXT: br i1 %cond, label %L1, label %L3
    101 ; CHECK-NOT: indirectbr
    102 define void @test_indirectbr_thresh(i1 %cond, i8* %address) nounwind {
    103 entry:
    104   br i1 %cond, label %L0, label %L3
    105 L0:
    106   %indirect.goto.dest = select i1 %cond, i8* blockaddress(@test_indirectbr_thresh, %L1), i8* %address
    107   call void @quux()
    108   call void @quux()
    109   call void @quux()
    110   indirectbr i8* %indirect.goto.dest, [label %L1, label %L2, label %L3]
    111 
    112 L1:
    113   call void @foo()
    114   ret void
    115 L2:
    116   call void @bar()
    117   ret void
    118 L3:
    119   call void @baz()
    120   ret void
    121 }
    122 
    123 
    124 ; A more complicated case: the condition is a select based on a comparison.
    125 
    126 ; CHECK-LABEL: @test_switch_cmp(
    127 ; CHECK-NEXT: entry:
    128 ; CHECK-NEXT: br i1 %cond, label %L0, label %[[THREADED:[A-Za-z.0-9]+]]
    129 ; CHECK: [[THREADED]]:
    130 ; CHECK-NEXT: call void @quux
    131 ; CHECK-NEXT: br label %L1
    132 define void @test_switch_cmp(i1 %cond, i32 %val, i8 %value) nounwind {
    133 entry:
    134   br i1 %cond, label %L0, label %L4
    135 L0:
    136   %val.phi = phi i32 [%val, %entry], [-1, %L4]
    137   %cmp = icmp slt i32 %val.phi, 0
    138   %expr = select i1 %cmp, i8 1, i8 %value
    139   switch i8 %expr, label %L3 [i8 1, label %L1 i8 2, label %L2]
    140 
    141 L1:
    142   call void @foo()
    143   ret void
    144 L2:
    145   call void @bar()
    146   ret void
    147 L3:
    148   call void @baz()
    149   ret void
    150 L4:
    151   call void @quux()
    152   br label %L0
    153 }
    154 
    155 ; Make sure the edge value of %0 from entry to L2 includes 0 and L3 is
    156 ; reachable.
    157 ; CHECK: test_switch_default
    158 ; CHECK: entry:
    159 ; CHECK: load
    160 ; CHECK: icmp
    161 ; CHECK: [[THREADED:[A-Za-z.0-9]+]]:
    162 ; CHECK: store
    163 ; CHECK: br
    164 ; CHECK: L2:
    165 ; CHECK: icmp
    166 define void @test_switch_default(i32* nocapture %status) nounwind {
    167 entry:
    168   %0 = load i32, i32* %status, align 4
    169   switch i32 %0, label %L2 [
    170     i32 5061, label %L1
    171     i32 0, label %L2
    172   ]
    173 
    174 L1:
    175   store i32 10025, i32* %status, align 4
    176   br label %L2
    177 
    178 L2:
    179   %1 = load i32, i32* %status, align 4
    180   %cmp57.i = icmp eq i32 %1, 0
    181   br i1 %cmp57.i, label %L3, label %L4
    182 
    183 L3:
    184   store i32 10000, i32* %status, align 4
    185   br label %L4
    186 
    187 L4:
    188   ret void
    189 }
    190 
    191 define void @unfold1(double %x, double %y) nounwind {
    192 entry:
    193   %sub = fsub double %x, %y
    194   %cmp = fcmp ogt double %sub, 1.000000e+01
    195   br i1 %cmp, label %cond.end4, label %cond.false
    196 
    197 cond.false:                                       ; preds = %entry
    198   %add = fadd double %x, %y
    199   %cmp1 = fcmp ogt double %add, 1.000000e+01
    200   %add. = select i1 %cmp1, double %add, double 0.000000e+00
    201   br label %cond.end4
    202 
    203 cond.end4:                                        ; preds = %entry, %cond.false
    204   %cond5 = phi double [ %add., %cond.false ], [ %sub, %entry ]
    205   %cmp6 = fcmp oeq double %cond5, 0.000000e+00
    206   br i1 %cmp6, label %if.then, label %if.end
    207 
    208 if.then:                                          ; preds = %cond.end4
    209   call void @foo()
    210   br label %if.end
    211 
    212 if.end:                                           ; preds = %if.then, %cond.end4
    213   ret void
    214 
    215 ; CHECK-LABEL: @unfold1
    216 ; CHECK: br i1 %cmp, label %cond.end4, label %cond.false
    217 ; CHECK: br i1 %cmp1, label %cond.end4, label %if.then
    218 ; CHECK: br i1 %cmp6, label %if.then, label %if.end
    219 ; CHECK: br label %if.end
    220 }
    221 
    222 
    223 define void @unfold2(i32 %x, i32 %y) nounwind {
    224 entry:
    225   %sub = sub nsw i32 %x, %y
    226   %cmp = icmp sgt i32 %sub, 10
    227   br i1 %cmp, label %cond.end4, label %cond.false
    228 
    229 cond.false:                                       ; preds = %entry
    230   %add = add nsw i32 %x, %y
    231   %cmp1 = icmp sgt i32 %add, 10
    232   %add. = select i1 %cmp1, i32 0, i32 %add
    233   br label %cond.end4
    234 
    235 cond.end4:                                        ; preds = %entry, %cond.false
    236   %cond5 = phi i32 [ %add., %cond.false ], [ %sub, %entry ]
    237   %cmp6 = icmp eq i32 %cond5, 0
    238   br i1 %cmp6, label %if.then, label %if.end
    239 
    240 if.then:                                          ; preds = %cond.end4
    241   call void @foo()
    242   br label %if.end
    243 
    244 if.end:                                           ; preds = %if.then, %cond.end4
    245   ret void
    246 
    247 ; CHECK-LABEL: @unfold2
    248 ; CHECK: br i1 %cmp, label %if.end, label %cond.false
    249 ; CHECK: br i1 %cmp1, label %if.then, label %cond.end4
    250 ; CHECK: br i1 %cmp6, label %if.then, label %if.end
    251 ; CHECK: br label %if.end
    252 }
    253 
    254 
    255 define i32 @unfold3(i32 %u, i32 %v, i32 %w, i32 %x, i32 %y, i32 %z, i32 %j) nounwind {
    256 entry:
    257   %add3 = add nsw i32 %j, 2
    258   %cmp.i = icmp slt i32 %u, %v
    259   br i1 %cmp.i, label %.exit, label %cond.false.i
    260 
    261 cond.false.i:                                     ; preds = %entry
    262   %cmp4.i = icmp sgt i32 %u, %v
    263   br i1 %cmp4.i, label %.exit, label %cond.false.6.i
    264 
    265 cond.false.6.i:                                   ; preds = %cond.false.i
    266   %cmp8.i = icmp slt i32 %w, %x
    267   br i1 %cmp8.i, label %.exit, label %cond.false.10.i
    268 
    269 cond.false.10.i:                                  ; preds = %cond.false.6.i
    270   %cmp13.i = icmp sgt i32 %w, %x
    271   br i1 %cmp13.i, label %.exit, label %cond.false.15.i
    272 
    273 cond.false.15.i:                                  ; preds = %cond.false.10.i
    274   %phitmp = icmp sge i32 %y, %z
    275   br label %.exit
    276 
    277 .exit:                                  ; preds = %entry, %cond.false.i, %cond.false.6.i, %cond.false.10.i, %cond.false.15.i
    278   %cond23.i = phi i1 [ false, %entry ], [ true, %cond.false.i ], [ false, %cond.false.6.i ], [ %phitmp, %cond.false.15.i ], [ true, %cond.false.10.i ]
    279   %j.add3 = select i1 %cond23.i, i32 %j, i32 %add3
    280   ret i32 %j.add3
    281 
    282 ; CHECK-LABEL: @unfold3
    283 ; CHECK: br i1 %cmp.i, label %.exit.thread2, label %cond.false.i 
    284 ; CHECK: br i1 %cmp4.i, label %.exit.thread, label %cond.false.6.i
    285 ; CHECK: br i1 %cmp8.i, label %.exit.thread2, label %cond.false.10.i
    286 ; CHECK: br i1 %cmp13.i, label %.exit.thread, label %.exit
    287 ; CHECK: br i1 %phitmp, label %.exit.thread, label %.exit.thread2
    288 ; CHECK: br label %.exit.thread2
    289 }
    290