1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4declare void @use(i1) 5declare void @usef64(double) 6 7; X == 42.0 ? X : 42.0 --> 42.0 8 9define double @oeq(double %x) { 10; CHECK-LABEL: @oeq( 11; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double [[X:%.*]], 4.200000e+01 12; CHECK-NEXT: call void @use(i1 [[CMP]]) 13; CHECK-NEXT: ret double 4.200000e+01 14; 15 %cmp = fcmp oeq double %x, 42.0 16 call void @use(i1 %cmp) ; extra use to thwart predicate canonicalization 17 %cond = select i1 %cmp, double %x, double 42.0 18 ret double %cond 19} 20 21; X == 42.0 ? 42.0 : X --> X 22 23define float @oeq_swapped(float %x) { 24; CHECK-LABEL: @oeq_swapped( 25; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[X:%.*]], 4.200000e+01 26; CHECK-NEXT: call void @use(i1 [[CMP]]) 27; CHECK-NEXT: ret float [[X]] 28; 29 %cmp = fcmp oeq float %x, 42.0 30 call void @use(i1 %cmp) ; extra use to thwart predicate canonicalization 31 %cond = select i1 %cmp, float 42.0, float %x 32 ret float %cond 33} 34 35; x != y ? x : y -> x if it's the right kind of != and at least 36; one of x and y is not negative zero. 37 38; X != 42.0 ? X : 42.0 --> X 39 40define double @une(double %x) { 41; CHECK-LABEL: @une( 42; CHECK-NEXT: [[CMP:%.*]] = fcmp une double [[X:%.*]], 4.200000e+01 43; CHECK-NEXT: call void @use(i1 [[CMP]]) 44; CHECK-NEXT: ret double [[X]] 45; 46 %cmp = fcmp une double %x, 42.0 47 call void @use(i1 %cmp) ; extra use to thwart predicate canonicalization 48 %cond = select i1 %cmp, double %x, double 42.0 49 ret double %cond 50} 51 52; X != 42.0 ? 42.0 : X --> 42.0 53 54define double @une_swapped(double %x) { 55; CHECK-LABEL: @une_swapped( 56; CHECK-NEXT: [[CMP:%.*]] = fcmp une double [[X:%.*]], 4.200000e+01 57; CHECK-NEXT: call void @use(i1 [[CMP]]) 58; CHECK-NEXT: ret double 4.200000e+01 59; 60 %cmp = fcmp une double %x, 42.0 61 call void @use(i1 %cmp) ; extra use to thwart predicate canonicalization 62 %cond = select i1 %cmp, double 42.0, double %x 63 ret double %cond 64} 65 66define double @une_could_be_negzero(double %x, double %y) { 67; CHECK-LABEL: @une_could_be_negzero( 68; CHECK-NEXT: [[CMP:%.*]] = fcmp une double [[X:%.*]], [[Y:%.*]] 69; CHECK-NEXT: call void @use(i1 [[CMP]]) 70; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], double [[X]], double [[Y]] 71; CHECK-NEXT: ret double [[COND]] 72; 73 %cmp = fcmp une double %x, %y 74 call void @use(i1 %cmp) ; extra use to thwart predicate canonicalization 75 %cond = select i1 %cmp, double %x, double %y 76 ret double %cond 77} 78 79define double @une_swapped_could_be_negzero(double %x, double %y) { 80; CHECK-LABEL: @une_swapped_could_be_negzero( 81; CHECK-NEXT: [[CMP:%.*]] = fcmp une double [[X:%.*]], [[Y:%.*]] 82; CHECK-NEXT: call void @use(i1 [[CMP]]) 83; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], double [[Y]], double [[X]] 84; CHECK-NEXT: ret double [[COND]] 85; 86 %cmp = fcmp une double %x, %y 87 call void @use(i1 %cmp) ; extra use to thwart predicate canonicalization 88 %cond = select i1 %cmp, double %y, double %x 89 ret double %cond 90} 91 92define double @one(double %x) { 93; CHECK-LABEL: @one( 94; CHECK-NEXT: [[CMP:%.*]] = fcmp one double [[X:%.*]], -1.000000e+00 95; CHECK-NEXT: call void @use(i1 [[CMP]]) 96; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], double [[X]], double -1.000000e+00 97; CHECK-NEXT: ret double [[COND]] 98; 99 %cmp = fcmp one double %x, -1.0 100 call void @use(i1 %cmp) ; extra use to thwart predicate canonicalization 101 %cond = select i1 %cmp, double %x, double -1.0 102 ret double %cond 103} 104 105define double @one_swapped(double %x) { 106; CHECK-LABEL: @one_swapped( 107; CHECK-NEXT: [[CMP:%.*]] = fcmp one double [[X:%.*]], -1.000000e+00 108; CHECK-NEXT: call void @use(i1 [[CMP]]) 109; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], double -1.000000e+00, double [[X]] 110; CHECK-NEXT: ret double [[COND]] 111; 112 %cmp = fcmp one double %x, -1.0 113 call void @use(i1 %cmp) ; extra use to thwart predicate canonicalization 114 %cond = select i1 %cmp, double -1.0, double %x 115 ret double %cond 116} 117 118define i1 @fcmp_oeq_select(i1 %cond, float %a, float %b) { 119; CHECK-LABEL: @fcmp_oeq_select( 120; CHECK-NEXT: [[RES:%.*]] = fcmp oeq float [[A:%.*]], [[B:%.*]] 121; CHECK-NEXT: ret i1 [[RES]] 122; 123 %lhs = select i1 %cond, float %a, float %b 124 %rhs = select i1 %cond, float %b, float %a 125 %res = fcmp oeq float %lhs, %rhs 126 ret i1 %res 127} 128 129define i1 @fcmp_uno_select(i1 %cond, float %a, float %b) { 130; CHECK-LABEL: @fcmp_uno_select( 131; CHECK-NEXT: [[RES:%.*]] = fcmp uno float [[A:%.*]], [[B:%.*]] 132; CHECK-NEXT: ret i1 [[RES]] 133; 134 %lhs = select i1 %cond, float %a, float %b 135 %rhs = select i1 %cond, float %b, float %a 136 %res = fcmp uno float %lhs, %rhs 137 ret i1 %res 138} 139 140define i1 @fcmp_ogt_select(i1 %cond, float %a, float %b) { 141; CHECK-LABEL: @fcmp_ogt_select( 142; CHECK-NEXT: [[LHS:%.*]] = select i1 [[COND:%.*]], float [[A:%.*]], float [[B:%.*]] 143; CHECK-NEXT: [[RHS:%.*]] = select i1 [[COND]], float [[B]], float [[A]] 144; CHECK-NEXT: [[RES:%.*]] = fcmp ogt float [[LHS]], [[RHS]] 145; CHECK-NEXT: ret i1 [[RES]] 146; 147 %lhs = select i1 %cond, float %a, float %b 148 %rhs = select i1 %cond, float %b, float %a 149 %res = fcmp ogt float %lhs, %rhs 150 ret i1 %res 151} 152 153define i1 @test_fcmp_select_const_const(double %x) { 154; CHECK-LABEL: @test_fcmp_select_const_const( 155; CHECK-NEXT: [[CMP1:%.*]] = fcmp uno double [[X:%.*]], 0.000000e+00 156; CHECK-NEXT: ret i1 [[CMP1]] 157; 158 %cmp1 = fcmp ord double %x, 0.000000e+00 159 %sel = select i1 %cmp1, double 0xFFFFFFFFFFFFFFFF, double 0.000000e+00 160 %cmp2 = fcmp oeq double %sel, 0.000000e+00 161 ret i1 %cmp2 162} 163 164define i1 @test_fcmp_select_var_const(double %x, double %y) { 165; CHECK-LABEL: @test_fcmp_select_var_const( 166; CHECK-NEXT: [[CMP1:%.*]] = fcmp ule double [[X:%.*]], 0x3E80000000000000 167; CHECK-NEXT: [[TMP1:%.*]] = fcmp olt double [[Y:%.*]], 0x3E80000000000000 168; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[TMP1]] 169; CHECK-NEXT: ret i1 [[CMP2]] 170; 171 %cmp1 = fcmp ogt double %x, 0x3E80000000000000 172 %sel = select i1 %cmp1, double %y, double 0.000000e+00 173 %cmp2 = fcmp olt double %sel, 0x3E80000000000000 174 ret i1 %cmp2 175} 176 177define i1 @test_fcmp_select_var_const_fmf(double %x, double %y) { 178; CHECK-LABEL: @test_fcmp_select_var_const_fmf( 179; CHECK-NEXT: [[CMP1:%.*]] = fcmp ule double [[X:%.*]], 0x3E80000000000000 180; CHECK-NEXT: [[TMP1:%.*]] = fcmp nnan olt double [[Y:%.*]], 0x3E80000000000000 181; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[TMP1]] 182; CHECK-NEXT: ret i1 [[CMP2]] 183; 184 %cmp1 = fcmp ogt double %x, 0x3E80000000000000 185 %sel = select i1 %cmp1, double %y, double 0.000000e+00 186 %cmp2 = fcmp nnan olt double %sel, 0x3E80000000000000 187 ret i1 %cmp2 188} 189 190define <2 x i1> @test_fcmp_select_const_const_vec(<2 x double> %x) { 191; CHECK-LABEL: @test_fcmp_select_const_const_vec( 192; CHECK-NEXT: [[CMP1:%.*]] = fcmp uno <2 x double> [[X:%.*]], zeroinitializer 193; CHECK-NEXT: ret <2 x i1> [[CMP1]] 194; 195 %cmp1 = fcmp ord <2 x double> %x, zeroinitializer 196 %sel = select <2 x i1> %cmp1, <2 x double> <double 0xFFFFFFFFFFFFFFFF, double 0xFFFFFFFFFFFFFFFF>, <2 x double> zeroinitializer 197 %cmp2 = fcmp oeq <2 x double> %sel, zeroinitializer 198 ret <2 x i1> %cmp2 199} 200 201; Don't break clamp idioms 202 203define double @test_fcmp_select_clamp(double %x) { 204; CHECK-LABEL: @test_fcmp_select_clamp( 205; CHECK-NEXT: [[CMP1:%.*]] = fcmp ogt double [[X:%.*]], 9.000000e-01 206; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[CMP1]], double 9.000000e-01, double [[X]] 207; CHECK-NEXT: [[CMP2:%.*]] = fcmp olt double [[SEL1]], 5.000000e-01 208; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[CMP2]], double 5.000000e-01, double [[SEL1]] 209; CHECK-NEXT: ret double [[SEL2]] 210; 211 %cmp1 = fcmp ogt double %x, 9.000000e-01 212 %sel1 = select i1 %cmp1, double 9.000000e-01, double %x 213 %cmp2 = fcmp olt double %sel1, 5.000000e-01 214 %sel2 = select i1 %cmp2, double 5.000000e-01, double %sel1 215 ret double %sel2 216} 217 218; Don't break fmin/fmax idioms 219 220define double @test_fcmp_select_maxnum(double %x) { 221; CHECK-LABEL: @test_fcmp_select_maxnum( 222; CHECK-NEXT: [[SEL1:%.*]] = call nsz double @llvm.maxnum.f64(double [[X:%.*]], double 1.000000e+00) 223; CHECK-NEXT: [[SEL2:%.*]] = call nsz double @llvm.minnum.f64(double [[SEL1]], double 2.550000e+02) 224; CHECK-NEXT: ret double [[SEL2]] 225; 226 %cmp1 = fcmp ogt double %x, 1.0 227 %sel1 = select nnan nsz i1 %cmp1, double %x, double 1.0 228 %cmp2 = fcmp olt double %sel1, 255.0 229 %sel2 = select nnan nsz i1 %cmp2, double %sel1, double 255.0 230 ret double %sel2 231} 232 233define i1 @test_fcmp_select_const_const_multiuse(double %x) { 234; CHECK-LABEL: @test_fcmp_select_const_const_multiuse( 235; CHECK-NEXT: [[CMP1:%.*]] = fcmp ord double [[X:%.*]], 0.000000e+00 236; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP1]], double 0xFFFFFFFFFFFFFFFF, double 0.000000e+00 237; CHECK-NEXT: call void @usef64(double [[SEL]]) 238; CHECK-NEXT: [[CMP2:%.*]] = fcmp oeq double [[SEL]], 0.000000e+00 239; CHECK-NEXT: ret i1 [[CMP2]] 240; 241 %cmp1 = fcmp ord double %x, 0.000000e+00 242 %sel = select i1 %cmp1, double 0xFFFFFFFFFFFFFFFF, double 0.000000e+00 243 call void @usef64(double %sel) 244 %cmp2 = fcmp oeq double %sel, 0.000000e+00 245 ret i1 %cmp2 246} 247 248define i1 @test_fcmp_select_const_const_unordered(double %x) { 249; CHECK-LABEL: @test_fcmp_select_const_const_unordered( 250; CHECK-NEXT: [[CMP1:%.*]] = fcmp ord double [[X:%.*]], 0.000000e+00 251; CHECK-NEXT: ret i1 [[CMP1]] 252; 253 %cmp1 = fcmp uno double %x, 0.000000e+00 254 %sel = select i1 %cmp1, double 0xFFFFFFFFFFFFFFFF, double 0.000000e+00 255 %cmp2 = fcmp oeq double %sel, 0.000000e+00 256 ret i1 %cmp2 257} 258 259define i1 @test_fcmp_select_var_const_unordered(double %x, double %y) { 260; CHECK-LABEL: @test_fcmp_select_var_const_unordered( 261; CHECK-NEXT: [[CMP1:%.*]] = fcmp ult double [[X:%.*]], 0x3E80000000000000 262; CHECK-NEXT: [[TMP1:%.*]] = fcmp ugt double [[Y:%.*]], 0x3E80000000000000 263; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[CMP1]], i1 [[TMP1]], i1 false 264; CHECK-NEXT: ret i1 [[CMP2]] 265; 266 %cmp1 = fcmp ult double %x, 0x3E80000000000000 267 %sel = select i1 %cmp1, double %y, double 0.000000e+00 268 %cmp2 = fcmp ugt double %sel, 0x3E80000000000000 269 ret i1 %cmp2 270} 271