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 ; A more complicated case: the condition is a select based on a comparison.
     95 
     96 ; CHECK-LABEL: @test_switch_cmp(
     97 ; CHECK-NEXT: entry:
     98 ; CHECK-NEXT: br i1 %cond, label %L0, label %[[THREADED:[A-Za-z.0-9]+]]
     99 ; CHECK: [[THREADED]]:
    100 ; CHECK-NEXT: call void @quux
    101 ; CHECK-NEXT: br label %L1
    102 define void @test_switch_cmp(i1 %cond, i32 %val, i8 %value) nounwind {
    103 entry:
    104   br i1 %cond, label %L0, label %L4
    105 L0:
    106   %val.phi = phi i32 [%val, %entry], [-1, %L4]
    107   %cmp = icmp slt i32 %val.phi, 0
    108   %expr = select i1 %cmp, i8 1, i8 %value
    109   switch i8 %expr, label %L3 [i8 1, label %L1 i8 2, label %L2]
    110 
    111 L1:
    112   call void @foo()
    113   ret void
    114 L2:
    115   call void @bar()
    116   ret void
    117 L3:
    118   call void @baz()
    119   ret void
    120 L4:
    121   call void @quux()
    122   br label %L0
    123 }
    124 
    125 ; Make sure the edge value of %0 from entry to L2 includes 0 and L3 is
    126 ; reachable.
    127 ; CHECK: test_switch_default
    128 ; CHECK: entry:
    129 ; CHECK: load
    130 ; CHECK: icmp
    131 ; CHECK: [[THREADED:[A-Za-z.0-9]+]]:
    132 ; CHECK: store
    133 ; CHECK: br
    134 ; CHECK: L2:
    135 ; CHECK: icmp
    136 define void @test_switch_default(i32* nocapture %status) nounwind {
    137 entry:
    138   %0 = load i32* %status, align 4
    139   switch i32 %0, label %L2 [
    140     i32 5061, label %L1
    141     i32 0, label %L2
    142   ]
    143 
    144 L1:
    145   store i32 10025, i32* %status, align 4
    146   br label %L2
    147 
    148 L2:
    149   %1 = load i32* %status, align 4
    150   %cmp57.i = icmp eq i32 %1, 0
    151   br i1 %cmp57.i, label %L3, label %L4
    152 
    153 L3:
    154   store i32 10000, i32* %status, align 4
    155   br label %L4
    156 
    157 L4:
    158   ret void
    159 }
    160 
    161 define void @unfold1(double %x, double %y) nounwind {
    162 entry:
    163   %sub = fsub double %x, %y
    164   %cmp = fcmp ogt double %sub, 1.000000e+01
    165   br i1 %cmp, label %cond.end4, label %cond.false
    166 
    167 cond.false:                                       ; preds = %entry
    168   %add = fadd double %x, %y
    169   %cmp1 = fcmp ogt double %add, 1.000000e+01
    170   %add. = select i1 %cmp1, double %add, double 0.000000e+00
    171   br label %cond.end4
    172 
    173 cond.end4:                                        ; preds = %entry, %cond.false
    174   %cond5 = phi double [ %add., %cond.false ], [ %sub, %entry ]
    175   %cmp6 = fcmp oeq double %cond5, 0.000000e+00
    176   br i1 %cmp6, label %if.then, label %if.end
    177 
    178 if.then:                                          ; preds = %cond.end4
    179   call void @foo()
    180   br label %if.end
    181 
    182 if.end:                                           ; preds = %if.then, %cond.end4
    183   ret void
    184 
    185 ; CHECK-LABEL: @unfold1
    186 ; CHECK: br i1 %cmp, label %cond.end4, label %cond.false
    187 ; CHECK: br i1 %cmp1, label %cond.end4, label %if.then
    188 ; CHECK: br i1 %cmp6, label %if.then, label %if.end
    189 ; CHECK: br label %if.end
    190 }
    191 
    192 
    193 define void @unfold2(i32 %x, i32 %y) nounwind {
    194 entry:
    195   %sub = sub nsw i32 %x, %y
    196   %cmp = icmp sgt i32 %sub, 10
    197   br i1 %cmp, label %cond.end4, label %cond.false
    198 
    199 cond.false:                                       ; preds = %entry
    200   %add = add nsw i32 %x, %y
    201   %cmp1 = icmp sgt i32 %add, 10
    202   %add. = select i1 %cmp1, i32 0, i32 %add
    203   br label %cond.end4
    204 
    205 cond.end4:                                        ; preds = %entry, %cond.false
    206   %cond5 = phi i32 [ %add., %cond.false ], [ %sub, %entry ]
    207   %cmp6 = icmp eq i32 %cond5, 0
    208   br i1 %cmp6, label %if.then, label %if.end
    209 
    210 if.then:                                          ; preds = %cond.end4
    211   call void @foo()
    212   br label %if.end
    213 
    214 if.end:                                           ; preds = %if.then, %cond.end4
    215   ret void
    216 
    217 ; CHECK-LABEL: @unfold2
    218 ; CHECK: br i1 %cmp, label %if.end, label %cond.false
    219 ; CHECK: br i1 %cmp1, label %if.then, label %cond.end4
    220 ; CHECK: br i1 %cmp6, label %if.then, label %if.end
    221 ; CHECK: br label %if.end
    222 }
    223