1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -instcombine < %s | FileCheck %s 3 4; This is the canonical form for a type-changing min/max. 5define double @t1(float %a) { 6; CHECK-LABEL: @t1( 7; CHECK-NEXT: [[DOTINV:%.*]] = fcmp oge float %a, 5.000000e+00 8; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[DOTINV]], float 5.000000e+00, float %a 9; CHECK-NEXT: [[TMP2:%.*]] = fpext float [[TMP1]] to double 10; CHECK-NEXT: ret double [[TMP2]] 11; 12 %1 = fcmp ult float %a, 5.0 13 %2 = select i1 %1, float %a, float 5.0 14 %3 = fpext float %2 to double 15 ret double %3 16} 17 18; Check this is converted into canonical form, as above. 19define double @t2(float %a) { 20; CHECK-LABEL: @t2( 21; CHECK-NEXT: [[DOTINV:%.*]] = fcmp oge float %a, 5.000000e+00 22; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[DOTINV]], float 5.000000e+00, float %a 23; CHECK-NEXT: [[TMP2:%.*]] = fpext float [[TMP1]] to double 24; CHECK-NEXT: ret double [[TMP2]] 25; 26 %1 = fcmp ult float %a, 5.0 27 %2 = fpext float %a to double 28 %3 = select i1 %1, double %2, double 5.0 29 ret double %3 30} 31 32; Same again, with trunc. 33define float @t4(double %a) { 34; CHECK-LABEL: @t4( 35; CHECK-NEXT: [[DOTINV:%.*]] = fcmp oge double %a, 5.000000e+00 36; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[DOTINV]], double 5.000000e+00, double %a 37; CHECK-NEXT: [[TMP2:%.*]] = fptrunc double [[TMP1]] to float 38; CHECK-NEXT: ret float [[TMP2]] 39; 40 %1 = fcmp ult double %a, 5.0 41 %2 = fptrunc double %a to float 42 %3 = select i1 %1, float %2, float 5.0 43 ret float %3 44} 45 46; different values, should not be converted. 47define double @t5(float %a) { 48; CHECK-LABEL: @t5( 49; CHECK-NEXT: [[TMP1:%.*]] = fcmp ult float %a, 5.000000e+00 50; CHECK-NEXT: [[TMP2:%.*]] = fpext float %a to double 51; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], double [[TMP2]], double 5.001000e+00 52; CHECK-NEXT: ret double [[TMP3]] 53; 54 %1 = fcmp ult float %a, 5.0 55 %2 = fpext float %a to double 56 %3 = select i1 %1, double %2, double 5.001 57 ret double %3 58} 59 60; Signed zero, should not be converted 61define double @t6(float %a) { 62; CHECK-LABEL: @t6( 63; CHECK-NEXT: [[TMP1:%.*]] = fcmp ult float %a, -0.000000e+00 64; CHECK-NEXT: [[TMP2:%.*]] = fpext float %a to double 65; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], double [[TMP2]], double 0.000000e+00 66; CHECK-NEXT: ret double [[TMP3]] 67; 68 %1 = fcmp ult float %a, -0.0 69 %2 = fpext float %a to double 70 %3 = select i1 %1, double %2, double 0.0 71 ret double %3 72} 73 74; Signed zero, should not be converted 75define double @t7(float %a) { 76; CHECK-LABEL: @t7( 77; CHECK-NEXT: [[TMP1:%.*]] = fcmp ult float %a, 0.000000e+00 78; CHECK-NEXT: [[TMP2:%.*]] = fpext float %a to double 79; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], double [[TMP2]], double -0.000000e+00 80; CHECK-NEXT: ret double [[TMP3]] 81; 82 %1 = fcmp ult float %a, 0.0 83 %2 = fpext float %a to double 84 %3 = select i1 %1, double %2, double -0.0 85 ret double %3 86} 87 88define i64 @t8(float %a) { 89; CHECK-LABEL: @t8( 90; CHECK-NEXT: [[DOTINV:%.*]] = fcmp oge float %a, 5.000000e+00 91; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[DOTINV]], float 5.000000e+00, float %a 92; CHECK-NEXT: [[TMP2:%.*]] = fptoui float [[TMP1]] to i64 93; CHECK-NEXT: ret i64 [[TMP2]] 94; 95 %1 = fcmp ult float %a, 5.0 96 %2 = fptoui float %a to i64 97 %3 = select i1 %1, i64 %2, i64 5 98 ret i64 %3 99} 100 101define i8 @t9(float %a) { 102; CHECK-LABEL: @t9( 103; CHECK-NEXT: [[DOTINV:%.*]] = fcmp oge float %a, 0.000000e+00 104; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[DOTINV]], float 0.000000e+00, float %a 105; CHECK-NEXT: [[TMP2:%.*]] = fptosi float [[TMP1]] to i8 106; CHECK-NEXT: ret i8 [[TMP2]] 107; 108 %1 = fcmp ult float %a, 0.0 109 %2 = fptosi float %a to i8 110 %3 = select i1 %1, i8 %2, i8 0 111 ret i8 %3 112} 113 114 ; Either operand could be NaN, but fast modifier applied. 115define i8 @t11(float %a, float %b) { 116; CHECK-LABEL: @t11( 117; CHECK-NEXT: [[DOTINV:%.*]] = fcmp fast oge float %b, %a 118; CHECK-NEXT: [[DOTV:%.*]] = select i1 [[DOTINV]], float %a, float %b 119; CHECK-NEXT: [[TMP1:%.*]] = fptosi float [[DOTV]] to i8 120; CHECK-NEXT: ret i8 [[TMP1]] 121; 122 %1 = fcmp fast ult float %b, %a 123 %2 = fptosi float %a to i8 124 %3 = fptosi float %b to i8 125 %4 = select i1 %1, i8 %3, i8 %2 126 ret i8 %4 127} 128 129; Either operand could be NaN, but nnan modifier applied. 130define i8 @t12(float %a, float %b) { 131; CHECK-LABEL: @t12( 132; CHECK-NEXT: [[DOTINV:%.*]] = fcmp nnan oge float %b, %a 133; CHECK-NEXT: [[DOTV:%.*]] = select i1 [[DOTINV]], float %a, float %b 134; CHECK-NEXT: [[TMP1:%.*]] = fptosi float [[DOTV]] to i8 135; CHECK-NEXT: ret i8 [[TMP1]] 136; 137 %1 = fcmp nnan ult float %b, %a 138 %2 = fptosi float %a to i8 139 %3 = fptosi float %b to i8 140 %4 = select i1 %1, i8 %3, i8 %2 141 ret i8 %4 142} 143 144; Float and int values do not match. 145define i8 @t13(float %a) { 146; CHECK-LABEL: @t13( 147; CHECK-NEXT: [[TMP1:%.*]] = fcmp ult float %a, 1.500000e+00 148; CHECK-NEXT: [[TMP2:%.*]] = fptosi float %a to i8 149; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i8 [[TMP2]], i8 1 150; CHECK-NEXT: ret i8 [[TMP3]] 151; 152 %1 = fcmp ult float %a, 1.5 153 %2 = fptosi float %a to i8 154 %3 = select i1 %1, i8 %2, i8 1 155 ret i8 %3 156} 157 158; %a could be -0.0, but it doesn't matter because the conversion to int is the same for 0.0 or -0.0. 159define i8 @t14(float %a) { 160; CHECK-LABEL: @t14( 161; CHECK-NEXT: [[DOTINV:%.*]] = fcmp oge float %a, 0.000000e+00 162; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[DOTINV]], float 0.000000e+00, float %a 163; CHECK-NEXT: [[TMP2:%.*]] = fptosi float [[TMP1]] to i8 164; CHECK-NEXT: ret i8 [[TMP2]] 165; 166 %1 = fcmp ule float %a, 0.0 167 %2 = fptosi float %a to i8 168 %3 = select i1 %1, i8 %2, i8 0 169 ret i8 %3 170} 171 172define i8 @t14_commute(float %a) { 173; CHECK-LABEL: @t14_commute( 174; CHECK-NEXT: [[TMP1:%.*]] = fcmp ogt float %a, 0.000000e+00 175; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], float %a, float 0.000000e+00 176; CHECK-NEXT: [[TMP3:%.*]] = fptosi float [[TMP2]] to i8 177; CHECK-NEXT: ret i8 [[TMP3]] 178; 179 %1 = fcmp ule float %a, 0.0 180 %2 = fptosi float %a to i8 181 %3 = select i1 %1, i8 0, i8 %2 182 ret i8 %3 183} 184 185define i8 @t15(float %a) { 186; CHECK-LABEL: @t15( 187; CHECK-NEXT: [[DOTINV:%.*]] = fcmp nsz oge float %a, 0.000000e+00 188; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[DOTINV]], float 0.000000e+00, float %a 189; CHECK-NEXT: [[TMP2:%.*]] = fptosi float [[TMP1]] to i8 190; CHECK-NEXT: ret i8 [[TMP2]] 191; 192 %1 = fcmp nsz ule float %a, 0.0 193 %2 = fptosi float %a to i8 194 %3 = select i1 %1, i8 %2, i8 0 195 ret i8 %3 196} 197 198define double @t16(i32 %x) { 199; CHECK-LABEL: @t16( 200; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 %x, 0 201; CHECK-NEXT: [[CST:%.*]] = sitofp i32 %x to double 202; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], double [[CST]], double 5.000000e-01 203; CHECK-NEXT: ret double [[SEL]] 204; 205 %cmp = icmp sgt i32 %x, 0 206 %cst = sitofp i32 %x to double 207 %sel = select i1 %cmp, double %cst, double 5.000000e-01 208 ret double %sel 209} 210 211define double @t17(i32 %x) { 212; CHECK-LABEL: @t17( 213; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 %x, 2 214; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[TMP1]], i32 %x, i32 2 215; CHECK-NEXT: [[TMP2:%.*]] = sitofp i32 [[SEL1]] to double 216; CHECK-NEXT: ret double [[TMP2]] 217; 218 %cmp = icmp sgt i32 %x, 2 219 %cst = sitofp i32 %x to double 220 %sel = select i1 %cmp, double %cst, double 2.0 221 ret double %sel 222} 223 224