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