Home | History | Annotate | Download | only in X86
      1 ; RUN: opt -codegenprepare -S < %s | FileCheck %s
      2 
      3 target triple = "x86_64-unknown-unknown"
      4 
      5 ; Nothing to sink and convert here.
      6 
      7 define i32 @no_sink(double %a, double* %b, i32 %x, i32 %y)  {
      8 entry:
      9   %load = load double, double* %b, align 8
     10   %cmp = fcmp olt double %load, %a
     11   %sel = select i1 %cmp, i32 %x, i32 %y
     12   ret i32 %sel
     13 
     14 ; CHECK-LABEL: @no_sink(
     15 ; CHECK:    %load = load double, double* %b, align 8
     16 ; CHECK:    %cmp = fcmp olt double %load, %a
     17 ; CHECK:    %sel = select i1 %cmp, i32 %x, i32 %y
     18 ; CHECK:    ret i32 %sel
     19 }
     20 
     21 
     22 ; An 'fdiv' is expensive, so sink it rather than speculatively execute it.
     23 
     24 define float @fdiv_true_sink(float %a, float %b) {
     25 entry:
     26   %div = fdiv float %a, %b
     27   %cmp = fcmp ogt float %a, 1.0
     28   %sel = select i1 %cmp, float %div, float 2.0
     29   ret float %sel
     30 
     31 ; CHECK-LABEL: @fdiv_true_sink(
     32 ; CHECK:    %cmp = fcmp ogt float %a, 1.0
     33 ; CHECK:    br i1 %cmp, label %select.true.sink, label %select.end
     34 ; CHECK:  select.true.sink:
     35 ; CHECK:    %div = fdiv float %a, %b
     36 ; CHECK:    br label %select.end
     37 ; CHECK:  select.end:
     38 ; CHECK:    %sel = phi float [ %div, %select.true.sink ], [ 2.000000e+00, %entry ]
     39 ; CHECK:    ret float %sel
     40 }
     41 
     42 define float @fdiv_false_sink(float %a, float %b) {
     43 entry:
     44   %div = fdiv float %a, %b
     45   %cmp = fcmp ogt float %a, 3.0
     46   %sel = select i1 %cmp, float 4.0, float %div
     47   ret float %sel
     48 
     49 ; CHECK-LABEL: @fdiv_false_sink(
     50 ; CHECK:    %cmp = fcmp ogt float %a, 3.0
     51 ; CHECK:    br i1 %cmp, label %select.end, label %select.false.sink
     52 ; CHECK:  select.false.sink:
     53 ; CHECK:    %div = fdiv float %a, %b
     54 ; CHECK:    br label %select.end
     55 ; CHECK:  select.end:
     56 ; CHECK:    %sel = phi float [ 4.000000e+00, %entry ], [ %div, %select.false.sink ]
     57 ; CHECK:    ret float %sel
     58 }
     59 
     60 define float @fdiv_both_sink(float %a, float %b) {
     61 entry:
     62   %div1 = fdiv float %a, %b
     63   %div2 = fdiv float %b, %a
     64   %cmp = fcmp ogt float %a, 5.0
     65   %sel = select i1 %cmp, float %div1, float %div2
     66   ret float %sel
     67 
     68 ; CHECK-LABEL: @fdiv_both_sink(
     69 ; CHECK:    %cmp = fcmp ogt float %a, 5.0
     70 ; CHECK:    br i1 %cmp, label %select.true.sink, label %select.false.sink
     71 ; CHECK:  select.true.sink:
     72 ; CHECK:    %div1 = fdiv float %a, %b
     73 ; CHECK:    br label %select.end
     74 ; CHECK:  select.false.sink:
     75 ; CHECK:    %div2 = fdiv float %b, %a
     76 ; CHECK:    br label %select.end
     77 ; CHECK:  select.end:
     78 ; CHECK:    %sel = phi float [ %div1, %select.true.sink ], [ %div2, %select.false.sink ]
     79 ; CHECK:    ret float %sel
     80 }
     81 
     82 ; But if the select is marked unpredictable, then don't turn it into a branch.
     83 
     84 define float @unpredictable_select(float %a, float %b) {
     85 ; CHECK-LABEL: @unpredictable_select(
     86 ; CHECK-NEXT:  entry:
     87 ; CHECK-NEXT:    [[DIV:%.*]] = fdiv float %a, %b
     88 ; CHECK-NEXT:    [[CMP:%.*]] = fcmp ogt float %a, 1.000000e+00
     89 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP]], float [[DIV]], float 2.000000e+00, !unpredictable !0
     90 ; CHECK-NEXT:    ret float [[SEL]]
     91 ;
     92 entry:
     93   %div = fdiv float %a, %b
     94   %cmp = fcmp ogt float %a, 1.0
     95   %sel = select i1 %cmp, float %div, float 2.0, !unpredictable !0
     96   ret float %sel
     97 }
     98 
     99 !0 = !{}
    100 
    101 ; An 'fadd' is not too expensive, so it's ok to speculate.
    102 
    103 define float @fadd_no_sink(float %a, float %b) {
    104   %add = fadd float %a, %b
    105   %cmp = fcmp ogt float 6.0, %a
    106   %sel = select i1 %cmp, float %add, float 7.0
    107   ret float %sel
    108 
    109 ; CHECK-LABEL: @fadd_no_sink(
    110 ; CHECK:  %sel = select i1 %cmp, float %add, float 7.0
    111 }
    112 
    113 ; Possible enhancement: sinkability is only calculated with the direct
    114 ; operand of the select, so we don't try to sink this. The fdiv cost is not
    115 ; taken into account.
    116 
    117 define float @fdiv_no_sink(float %a, float %b) {
    118 entry:
    119   %div = fdiv float %a, %b
    120   %add = fadd float %div, %b
    121   %cmp = fcmp ogt float %a, 1.0
    122   %sel = select i1 %cmp, float %add, float 8.0
    123   ret float %sel
    124 
    125 ; CHECK-LABEL: @fdiv_no_sink(
    126 ; CHECK:  %sel = select i1 %cmp, float %add, float 8.0
    127 }
    128 
    129 ; Do not transform the CFG if the select operands may have side effects.
    130 
    131 declare i64* @bar(i32, i32, i32)
    132 declare i64* @baz(i32, i32, i32)
    133 
    134 define i64* @calls_no_sink(i32 %in) {
    135   %call1 = call i64* @bar(i32 1, i32 2, i32 3)
    136   %call2 = call i64* @baz(i32 1, i32 2, i32 3)
    137   %tobool = icmp ne i32 %in, 0
    138   %sel = select i1 %tobool, i64* %call1, i64* %call2
    139   ret i64* %sel
    140 
    141 ; CHECK-LABEL: @calls_no_sink(
    142 ; CHECK:  %sel = select i1 %tobool, i64* %call1, i64* %call2
    143 }
    144 
    145 define i32 @sdiv_no_sink(i32 %a, i32 %b) {
    146   %div1 = sdiv i32 %a, %b
    147   %div2 = sdiv i32 %b, %a
    148   %cmp = icmp sgt i32 %a, 5
    149   %sel = select i1 %cmp, i32 %div1, i32 %div2
    150   ret i32 %sel
    151 
    152 ; CHECK-LABEL: @sdiv_no_sink(
    153 ; CHECK:  %sel = select i1 %cmp, i32 %div1, i32 %div2
    154 }
    155 
    156