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