1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -instcombine -S | FileCheck %s 3 4; (X < C1) ? C1 : MIN(X, C2) 5define float @clamp_float_fast_ordered_strict_maxmin(float %x) { 6; CHECK-LABEL: define {{[^@]+}}@clamp_float_fast_ordered_strict_maxmin( 7; CHECK-NEXT: [[CMP2:%.*]] = fcmp fast olt float [[X:%.*]], 2.550000e+02 8; CHECK-NEXT: [[MIN:%.*]] = select i1 [[CMP2]], float [[X]], float 2.550000e+02 9; CHECK-NEXT: [[TMP1:%.*]] = call fast float @llvm.maxnum.f32(float [[MIN]], float 1.000000e+00) 10; CHECK-NEXT: ret float [[TMP1]] 11; 12 %cmp2 = fcmp fast olt float %x, 255.0 13 %min = select i1 %cmp2, float %x, float 255.0 14 %cmp1 = fcmp fast olt float %x, 1.0 15 %r = select i1 %cmp1, float 1.0, float %min 16 ret float %r 17} 18 19; (X <= C1) ? C1 : MIN(X, C2) 20define float @clamp_float_fast_ordered_nonstrict_maxmin(float %x) { 21; CHECK-LABEL: define {{[^@]+}}@clamp_float_fast_ordered_nonstrict_maxmin( 22; CHECK-NEXT: [[CMP2:%.*]] = fcmp fast olt float [[X:%.*]], 2.550000e+02 23; CHECK-NEXT: [[MIN:%.*]] = select i1 [[CMP2]], float [[X]], float 2.550000e+02 24; CHECK-NEXT: [[TMP1:%.*]] = call fast float @llvm.maxnum.f32(float [[MIN]], float 1.000000e+00) 25; CHECK-NEXT: ret float [[TMP1]] 26; 27 %cmp2 = fcmp fast olt float %x, 255.0 28 %min = select i1 %cmp2, float %x, float 255.0 29 %cmp1 = fcmp fast ole float %x, 1.0 30 %r = select i1 %cmp1, float 1.0, float %min 31 ret float %r 32} 33 34; (X > C1) ? C1 : MAX(X, C2) 35define float @clamp_float_fast_ordered_strict_minmax(float %x) { 36; CHECK-LABEL: define {{[^@]+}}@clamp_float_fast_ordered_strict_minmax( 37; CHECK-NEXT: [[CMP2:%.*]] = fcmp fast ogt float [[X:%.*]], 1.000000e+00 38; CHECK-NEXT: [[MAX:%.*]] = select i1 [[CMP2]], float [[X]], float 1.000000e+00 39; CHECK-NEXT: [[TMP1:%.*]] = call fast float @llvm.minnum.f32(float [[MAX]], float 2.550000e+02) 40; CHECK-NEXT: ret float [[TMP1]] 41; 42 %cmp2 = fcmp fast ogt float %x, 1.0 43 %max = select i1 %cmp2, float %x, float 1.0 44 %cmp1 = fcmp fast ogt float %x, 255.0 45 %r = select i1 %cmp1, float 255.0, float %max 46 ret float %r 47} 48 49; (X >= C1) ? C1 : MAX(X, C2) 50define float @clamp_float_fast_ordered_nonstrict_minmax(float %x) { 51; CHECK-LABEL: define {{[^@]+}}@clamp_float_fast_ordered_nonstrict_minmax( 52; CHECK-NEXT: [[CMP2:%.*]] = fcmp fast ogt float [[X:%.*]], 1.000000e+00 53; CHECK-NEXT: [[MAX:%.*]] = select i1 [[CMP2]], float [[X]], float 1.000000e+00 54; CHECK-NEXT: [[TMP1:%.*]] = call fast float @llvm.minnum.f32(float [[MAX]], float 2.550000e+02) 55; CHECK-NEXT: ret float [[TMP1]] 56; 57 %cmp2 = fcmp fast ogt float %x, 1.0 58 %max = select i1 %cmp2, float %x, float 1.0 59 %cmp1 = fcmp fast oge float %x, 255.0 60 %r = select i1 %cmp1, float 255.0, float %max 61 ret float %r 62} 63 64 65; The same for unordered 66 67; (X < C1) ? C1 : MIN(X, C2) 68define float @clamp_float_fast_unordered_strict_maxmin(float %x) { 69; CHECK-LABEL: define {{[^@]+}}@clamp_float_fast_unordered_strict_maxmin( 70; CHECK-NEXT: [[CMP2_INV:%.*]] = fcmp fast oge float [[X:%.*]], 2.550000e+02 71; CHECK-NEXT: [[TMP1:%.*]] = select fast i1 [[CMP2_INV]], float 2.550000e+02, float [[X]] 72; CHECK-NEXT: [[TMP2:%.*]] = call fast float @llvm.maxnum.f32(float [[TMP1]], float 1.000000e+00) 73; CHECK-NEXT: ret float [[TMP2]] 74; 75 %cmp2 = fcmp fast ult float %x, 255.0 76 %min = select i1 %cmp2, float %x, float 255.0 77 %cmp1 = fcmp fast ult float %x, 1.0 78 %r = select i1 %cmp1, float 1.0, float %min 79 ret float %r 80} 81 82; (X <= C1) ? C1 : MIN(X, C2) 83define float @clamp_float_fast_unordered_nonstrict_maxmin(float %x) { 84; CHECK-LABEL: define {{[^@]+}}@clamp_float_fast_unordered_nonstrict_maxmin( 85; CHECK-NEXT: [[CMP2_INV:%.*]] = fcmp fast oge float [[X:%.*]], 2.550000e+02 86; CHECK-NEXT: [[TMP1:%.*]] = select fast i1 [[CMP2_INV]], float 2.550000e+02, float [[X]] 87; CHECK-NEXT: [[TMP2:%.*]] = call fast float @llvm.maxnum.f32(float [[TMP1]], float 1.000000e+00) 88; CHECK-NEXT: ret float [[TMP2]] 89; 90 %cmp2 = fcmp fast ult float %x, 255.0 91 %min = select i1 %cmp2, float %x, float 255.0 92 %cmp1 = fcmp fast ule float %x, 1.0 93 %r = select i1 %cmp1, float 1.0, float %min 94 ret float %r 95} 96 97; (X > C1) ? C1 : MAX(X, C2) 98define float @clamp_float_fast_unordered_strict_minmax(float %x) { 99; CHECK-LABEL: define {{[^@]+}}@clamp_float_fast_unordered_strict_minmax( 100; CHECK-NEXT: [[CMP2_INV:%.*]] = fcmp fast ole float [[X:%.*]], 1.000000e+00 101; CHECK-NEXT: [[TMP1:%.*]] = select fast i1 [[CMP2_INV]], float 1.000000e+00, float [[X]] 102; CHECK-NEXT: [[TMP2:%.*]] = call fast float @llvm.minnum.f32(float [[TMP1]], float 2.550000e+02) 103; CHECK-NEXT: ret float [[TMP2]] 104; 105 %cmp2 = fcmp fast ugt float %x, 1.0 106 %max = select i1 %cmp2, float %x, float 1.0 107 %cmp1 = fcmp fast ugt float %x, 255.0 108 %r = select i1 %cmp1, float 255.0, float %max 109 ret float %r 110} 111 112; (X >= C1) ? C1 : MAX(X, C2) 113define float @clamp_float_fast_unordered_nonstrict_minmax(float %x) { 114; CHECK-LABEL: define {{[^@]+}}@clamp_float_fast_unordered_nonstrict_minmax( 115; CHECK-NEXT: [[CMP2_INV:%.*]] = fcmp fast ole float [[X:%.*]], 1.000000e+00 116; CHECK-NEXT: [[TMP1:%.*]] = select fast i1 [[CMP2_INV]], float 1.000000e+00, float [[X]] 117; CHECK-NEXT: [[TMP2:%.*]] = call fast float @llvm.minnum.f32(float [[TMP1]], float 2.550000e+02) 118; CHECK-NEXT: ret float [[TMP2]] 119; 120 %cmp2 = fcmp fast ugt float %x, 1.0 121 %max = select i1 %cmp2, float %x, float 1.0 122 %cmp1 = fcmp fast uge float %x, 255.0 123 %r = select i1 %cmp1, float 255.0, float %max 124 ret float %r 125} 126 127; Some more checks with fast 128 129; (X > 1.0) ? min(x, 255.0) : 1.0 130; That did not match because select was in inverse order. 131define float @clamp_test_1(float %x) { 132; CHECK-LABEL: define {{[^@]+}}@clamp_test_1( 133; CHECK-NEXT: [[INNER_CMP_INV:%.*]] = fcmp fast oge float [[X:%.*]], 2.550000e+02 134; CHECK-NEXT: [[TMP1:%.*]] = select fast i1 [[INNER_CMP_INV]], float 2.550000e+02, float [[X]] 135; CHECK-NEXT: [[TMP2:%.*]] = call fast float @llvm.maxnum.f32(float [[TMP1]], float 1.000000e+00) 136; CHECK-NEXT: ret float [[TMP2]] 137; 138 %inner_cmp = fcmp fast ult float %x, 255.0 139 %inner_sel = select i1 %inner_cmp, float %x, float 255.0 140 %outer_cmp = fcmp fast ugt float %x, 1.0 141 %r = select i1 %outer_cmp, float %inner_sel, float 1.0 142 ret float %r 143} 144 145; And something negative 146 147; Like @clamp_test_1 but HighConst < LowConst 148define float @clamp_negative_wrong_const(float %x) { 149; CHECK-LABEL: define {{[^@]+}}@clamp_negative_wrong_const( 150; CHECK-NEXT: [[INNER_CMP_INV:%.*]] = fcmp fast oge float [[X:%.*]], 2.550000e+02 151; CHECK-NEXT: [[TMP1:%.*]] = select fast i1 [[INNER_CMP_INV]], float 2.550000e+02, float [[X]] 152; CHECK-NEXT: [[OUTER_CMP:%.*]] = fcmp fast ugt float [[X]], 5.120000e+02 153; CHECK-NEXT: [[R:%.*]] = select i1 [[OUTER_CMP]], float [[TMP1]], float 5.120000e+02 154; CHECK-NEXT: ret float [[R]] 155; 156 %inner_cmp = fcmp fast ult float %x, 255.0 157 %inner_sel = select i1 %inner_cmp, float %x, float 255.0 158 %outer_cmp = fcmp fast ugt float %x, 512.0 159 %r = select i1 %outer_cmp, float %inner_sel, float 512.0 160 ret float %r 161} 162 163; Like @clamp_test_1 but both are min 164define float @clamp_negative_same_op(float %x) { 165; CHECK-LABEL: define {{[^@]+}}@clamp_negative_same_op( 166; CHECK-NEXT: [[INNER_CMP_INV:%.*]] = fcmp fast oge float [[X:%.*]], 2.550000e+02 167; CHECK-NEXT: [[TMP1:%.*]] = select fast i1 [[INNER_CMP_INV]], float 2.550000e+02, float [[X]] 168; CHECK-NEXT: [[OUTER_CMP:%.*]] = fcmp fast ult float [[X]], 1.000000e+00 169; CHECK-NEXT: [[R:%.*]] = select i1 [[OUTER_CMP]], float [[TMP1]], float 1.000000e+00 170; CHECK-NEXT: ret float [[R]] 171; 172 %inner_cmp = fcmp fast ult float %x, 255.0 173 %inner_sel = select i1 %inner_cmp, float %x, float 255.0 174 %outer_cmp = fcmp fast ult float %x, 1.0 175 %r = select i1 %outer_cmp, float %inner_sel, float 1.0 176 ret float %r 177} 178 179 180; And now without fast. 181 182; First, check that we don't do bad things in the presence of signed zeros 183define float @clamp_float_with_zero1(float %x) { 184; CHECK-LABEL: define {{[^@]+}}@clamp_float_with_zero1( 185; CHECK-NEXT: [[CMP2:%.*]] = fcmp fast olt float [[X:%.*]], 2.550000e+02 186; CHECK-NEXT: [[MIN:%.*]] = select i1 [[CMP2]], float [[X]], float 2.550000e+02 187; CHECK-NEXT: [[CMP1:%.*]] = fcmp ole float [[X]], 0.000000e+00 188; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP1]], float 0.000000e+00, float [[MIN]] 189; CHECK-NEXT: ret float [[R]] 190; 191 %cmp2 = fcmp fast olt float %x, 255.0 192 %min = select i1 %cmp2, float %x, float 255.0 193 %cmp1 = fcmp ole float %x, 0.0 194 %r = select i1 %cmp1, float 0.0, float %min 195 ret float %r 196} 197 198define float @clamp_float_with_zero2(float %x) { 199; CHECK-LABEL: define {{[^@]+}}@clamp_float_with_zero2( 200; CHECK-NEXT: [[CMP2:%.*]] = fcmp fast olt float [[X:%.*]], 2.550000e+02 201; CHECK-NEXT: [[MIN:%.*]] = select i1 [[CMP2]], float [[X]], float 2.550000e+02 202; CHECK-NEXT: [[CMP1:%.*]] = fcmp olt float [[X]], 0.000000e+00 203; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP1]], float 0.000000e+00, float [[MIN]] 204; CHECK-NEXT: ret float [[R]] 205; 206 %cmp2 = fcmp fast olt float %x, 255.0 207 %min = select i1 %cmp2, float %x, float 255.0 208 %cmp1 = fcmp olt float %x, 0.0 209 %r = select i1 %cmp1, float 0.0, float %min 210 ret float %r 211} 212 213; Also, here we care more about the ordering of the inner min/max, so 214; two times more cases. 215; TODO: that is not implemented yet, so these checks are for the 216; future. This means that checks below can just check that 217; "fcmp.*%x" happens twice for each label. 218 219; (X < C1) ? C1 : MIN(X, C2) 220define float @clamp_float_ordered_strict_maxmin1(float %x) { 221; CHECK-LABEL: define {{[^@]+}}@clamp_float_ordered_strict_maxmin1( 222; CHECK-NEXT: [[CMP2:%.*]] = fcmp olt float [[X:%.*]], 2.550000e+02 223; CHECK-NEXT: [[MIN:%.*]] = select i1 [[CMP2]], float [[X]], float 2.550000e+02 224; CHECK-NEXT: [[CMP1:%.*]] = fcmp olt float [[X]], 1.000000e+00 225; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP1]], float 1.000000e+00, float [[MIN]] 226; CHECK-NEXT: ret float [[R]] 227; 228 %cmp2 = fcmp olt float %x, 255.0 ; X is NaN => false 229 %min = select i1 %cmp2, float %x, float 255.0 ; 255.0 230 %cmp1 = fcmp olt float %x, 1.0 ; false 231 %r = select i1 %cmp1, float 1.0, float %min ; min (255.0) 232 ret float %r 233} 234 235define float @clamp_float_ordered_strict_maxmin2(float %x) { 236; CHECK-LABEL: define {{[^@]+}}@clamp_float_ordered_strict_maxmin2( 237; CHECK-NEXT: [[CMP2_INV:%.*]] = fcmp oge float [[X:%.*]], 2.550000e+02 238; CHECK-NEXT: [[MIN:%.*]] = select i1 [[CMP2_INV]], float 2.550000e+02, float [[X]] 239; CHECK-NEXT: [[CMP1:%.*]] = fcmp olt float [[X]], 1.000000e+00 240; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP1]], float 1.000000e+00, float [[MIN]] 241; CHECK-NEXT: ret float [[R]] 242; 243 %cmp2 = fcmp ult float %x, 255.0 ; X is NaN => true 244 %min = select i1 %cmp2, float %x, float 255.0 ; NaN 245 %cmp1 = fcmp olt float %x, 1.0 ; false 246 %r = select i1 %cmp1, float 1.0, float %min ; min (NaN) 247 ret float %r 248} 249 250; (X <= C1) ? C1 : MIN(X, C2) 251define float @clamp_float_ordered_nonstrict_maxmin1(float %x) { 252; CHECK-LABEL: define {{[^@]+}}@clamp_float_ordered_nonstrict_maxmin1( 253; CHECK-NEXT: [[CMP2:%.*]] = fcmp olt float [[X:%.*]], 2.550000e+02 254; CHECK-NEXT: [[MIN:%.*]] = select i1 [[CMP2]], float [[X]], float 2.550000e+02 255; CHECK-NEXT: [[CMP1:%.*]] = fcmp ole float [[X]], 1.000000e+00 256; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP1]], float 1.000000e+00, float [[MIN]] 257; CHECK-NEXT: ret float [[R]] 258; 259 %cmp2 = fcmp olt float %x, 255.0 ; X is NaN => false 260 %min = select i1 %cmp2, float %x, float 255.0 ; 255.0 261 %cmp1 = fcmp ole float %x, 1.0 ; false 262 %r = select i1 %cmp1, float 1.0, float %min ; min (255.0) 263 ret float %r 264} 265 266define float @clamp_float_ordered_nonstrict_maxmin2(float %x) { 267; CHECK-LABEL: define {{[^@]+}}@clamp_float_ordered_nonstrict_maxmin2( 268; CHECK-NEXT: [[CMP2_INV:%.*]] = fcmp oge float [[X:%.*]], 2.550000e+02 269; CHECK-NEXT: [[MIN:%.*]] = select i1 [[CMP2_INV]], float 2.550000e+02, float [[X]] 270; CHECK-NEXT: [[CMP1:%.*]] = fcmp ole float [[X]], 1.000000e+00 271; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP1]], float 1.000000e+00, float [[MIN]] 272; CHECK-NEXT: ret float [[R]] 273; 274 %cmp2 = fcmp ult float %x, 255.0 ; x is NaN => true 275 %min = select i1 %cmp2, float %x, float 255.0 ; NaN 276 %cmp1 = fcmp ole float %x, 1.0 ; false 277 %r = select i1 %cmp1, float 1.0, float %min ; min (NaN) 278 ret float %r 279} 280 281; (X > C1) ? C1 : MAX(X, C2) 282define float @clamp_float_ordered_strict_minmax1(float %x) { 283; CHECK-LABEL: define {{[^@]+}}@clamp_float_ordered_strict_minmax1( 284; CHECK-NEXT: [[CMP2:%.*]] = fcmp ogt float [[X:%.*]], 1.000000e+00 285; CHECK-NEXT: [[MAX:%.*]] = select i1 [[CMP2]], float [[X]], float 1.000000e+00 286; CHECK-NEXT: [[CMP1:%.*]] = fcmp ogt float [[X]], 2.550000e+02 287; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP1]], float 2.550000e+02, float [[MAX]] 288; CHECK-NEXT: ret float [[R]] 289; 290 %cmp2 = fcmp ogt float %x, 1.0 ; x is NaN => false 291 %max = select i1 %cmp2, float %x, float 1.0 ; 1.0 292 %cmp1 = fcmp ogt float %x, 255.0 ; false 293 %r = select i1 %cmp1, float 255.0, float %max ; max (1.0) 294 ret float %r 295} 296 297define float @clamp_float_ordered_strict_minmax2(float %x) { 298; CHECK-LABEL: define {{[^@]+}}@clamp_float_ordered_strict_minmax2( 299; CHECK-NEXT: [[CMP2_INV:%.*]] = fcmp ole float [[X:%.*]], 1.000000e+00 300; CHECK-NEXT: [[MAX:%.*]] = select i1 [[CMP2_INV]], float 1.000000e+00, float [[X]] 301; CHECK-NEXT: [[CMP1:%.*]] = fcmp ogt float [[X]], 2.550000e+02 302; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP1]], float 2.550000e+02, float [[MAX]] 303; CHECK-NEXT: ret float [[R]] 304; 305 %cmp2 = fcmp ugt float %x, 1.0 ; x is NaN => true 306 %max = select i1 %cmp2, float %x, float 1.0 ; NaN 307 %cmp1 = fcmp ogt float %x, 255.0 ; false 308 %r = select i1 %cmp1, float 255.0, float %max ; max (NaN) 309 ret float %r 310} 311 312; (X >= C1) ? C1 : MAX(X, C2) 313define float @clamp_float_ordered_nonstrict_minmax1(float %x) { 314; CHECK-LABEL: define {{[^@]+}}@clamp_float_ordered_nonstrict_minmax1( 315; CHECK-NEXT: [[CMP2:%.*]] = fcmp ogt float [[X:%.*]], 1.000000e+00 316; CHECK-NEXT: [[MAX:%.*]] = select i1 [[CMP2]], float [[X]], float 1.000000e+00 317; CHECK-NEXT: [[CMP1:%.*]] = fcmp oge float [[X]], 2.550000e+02 318; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP1]], float 2.550000e+02, float [[MAX]] 319; CHECK-NEXT: ret float [[R]] 320; 321 %cmp2 = fcmp ogt float %x, 1.0 ; x is NaN => false 322 %max = select i1 %cmp2, float %x, float 1.0 ; 1.0 323 %cmp1 = fcmp oge float %x, 255.0 ; false 324 %r = select i1 %cmp1, float 255.0, float %max ; max (1.0) 325 ret float %r 326} 327 328define float @clamp_float_ordered_nonstrict_minmax2(float %x) { 329; CHECK-LABEL: define {{[^@]+}}@clamp_float_ordered_nonstrict_minmax2( 330; CHECK-NEXT: [[CMP2_INV:%.*]] = fcmp ole float [[X:%.*]], 1.000000e+00 331; CHECK-NEXT: [[MAX:%.*]] = select i1 [[CMP2_INV]], float 1.000000e+00, float [[X]] 332; CHECK-NEXT: [[CMP1:%.*]] = fcmp oge float [[X]], 2.550000e+02 333; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP1]], float 2.550000e+02, float [[MAX]] 334; CHECK-NEXT: ret float [[R]] 335; 336 %cmp2 = fcmp ugt float %x, 1.0 ; x is NaN => true 337 %max = select i1 %cmp2, float %x, float 1.0 ; NaN 338 %cmp1 = fcmp oge float %x, 255.0 ; false 339 %r = select i1 %cmp1, float 255.0, float %max ; max (NaN) 340 ret float %r 341} 342 343 344; The same for unordered 345 346; (X < C1) ? C1 : MIN(X, C2) 347define float @clamp_float_unordered_strict_maxmin1(float %x) { 348; CHECK-LABEL: define {{[^@]+}}@clamp_float_unordered_strict_maxmin1( 349; CHECK-NEXT: [[CMP2:%.*]] = fcmp olt float [[X:%.*]], 2.550000e+02 350; CHECK-NEXT: [[MIN:%.*]] = select i1 [[CMP2]], float [[X]], float 2.550000e+02 351; CHECK-NEXT: [[CMP1:%.*]] = fcmp ult float [[X]], 1.000000e+00 352; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP1]], float 1.000000e+00, float [[MIN]] 353; CHECK-NEXT: ret float [[R]] 354; 355 %cmp2 = fcmp olt float %x, 255.0 ; x is NaN => false 356 %min = select i1 %cmp2, float %x, float 255.0 ; 255.0 357 %cmp1 = fcmp ult float %x, 1.0 ; true 358 %r = select i1 %cmp1, float 1.0, float %min ; 1.0 359 ret float %r 360} 361 362define float @clamp_float_unordered_strict_maxmin2(float %x) { 363; CHECK-LABEL: define {{[^@]+}}@clamp_float_unordered_strict_maxmin2( 364; CHECK-NEXT: [[CMP2_INV:%.*]] = fcmp oge float [[X:%.*]], 2.550000e+02 365; CHECK-NEXT: [[MIN:%.*]] = select i1 [[CMP2_INV]], float 2.550000e+02, float [[X]] 366; CHECK-NEXT: [[CMP1:%.*]] = fcmp ult float [[X]], 1.000000e+00 367; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP1]], float 1.000000e+00, float [[MIN]] 368; CHECK-NEXT: ret float [[R]] 369; 370 %cmp2 = fcmp ult float %x, 255.0 ; x is NaN => true 371 %min = select i1 %cmp2, float %x, float 255.0 ; NaN 372 %cmp1 = fcmp ult float %x, 1.0 ; true 373 %r = select i1 %cmp1, float 1.0, float %min ; 1.0 374 ret float %r 375} 376 377; (X <= C1) ? C1 : MIN(X, C2) 378define float @clamp_float_unordered_nonstrict_maxmin1(float %x) { 379; CHECK-LABEL: define {{[^@]+}}@clamp_float_unordered_nonstrict_maxmin1( 380; CHECK-NEXT: [[CMP2:%.*]] = fcmp olt float [[X:%.*]], 2.550000e+02 381; CHECK-NEXT: [[MIN:%.*]] = select i1 [[CMP2]], float [[X]], float 2.550000e+02 382; CHECK-NEXT: [[CMP1:%.*]] = fcmp ule float [[X]], 1.000000e+00 383; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP1]], float 1.000000e+00, float [[MIN]] 384; CHECK-NEXT: ret float [[R]] 385; 386 %cmp2 = fcmp olt float %x, 255.0 ; x is NaN => false 387 %min = select i1 %cmp2, float %x, float 255.0 ; 255.0 388 %cmp1 = fcmp ule float %x, 1.0 ; true 389 %r = select i1 %cmp1, float 1.0, float %min ; 1.0 390 ret float %r 391} 392 393define float @clamp_float_unordered_nonstrict_maxmin2(float %x) { 394; CHECK-LABEL: define {{[^@]+}}@clamp_float_unordered_nonstrict_maxmin2( 395; CHECK-NEXT: [[CMP2_INV:%.*]] = fcmp oge float [[X:%.*]], 2.550000e+02 396; CHECK-NEXT: [[MIN:%.*]] = select i1 [[CMP2_INV]], float 2.550000e+02, float [[X]] 397; CHECK-NEXT: [[CMP1:%.*]] = fcmp ule float [[X]], 1.000000e+00 398; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP1]], float 1.000000e+00, float [[MIN]] 399; CHECK-NEXT: ret float [[R]] 400; 401 %cmp2 = fcmp ult float %x, 255.0 ; x is NaN => true 402 %min = select i1 %cmp2, float %x, float 255.0 ; NaN 403 %cmp1 = fcmp ule float %x, 1.0 ; true 404 %r = select i1 %cmp1, float 1.0, float %min ; 1.0 405 ret float %r 406} 407 408; (X > C1) ? C1 : MAX(X, C2) 409define float @clamp_float_unordered_strict_minmax1(float %x) { 410; CHECK-LABEL: define {{[^@]+}}@clamp_float_unordered_strict_minmax1( 411; CHECK-NEXT: [[CMP2:%.*]] = fcmp ogt float [[X:%.*]], 1.000000e+00 412; CHECK-NEXT: [[MAX:%.*]] = select i1 [[CMP2]], float [[X]], float 1.000000e+00 413; CHECK-NEXT: [[CMP1:%.*]] = fcmp ugt float [[X]], 2.550000e+02 414; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP1]], float 2.550000e+02, float [[MAX]] 415; CHECK-NEXT: ret float [[R]] 416; 417 %cmp2 = fcmp ogt float %x, 1.0 ; x is NaN => false 418 %max = select i1 %cmp2, float %x, float 1.0 ; 1.0 419 %cmp1 = fcmp ugt float %x, 255.0 ; true 420 %r = select i1 %cmp1, float 255.0, float %max ; 255.0 421 ret float %r 422} 423 424define float @clamp_float_unordered_strict_minmax2(float %x) { 425; CHECK-LABEL: define {{[^@]+}}@clamp_float_unordered_strict_minmax2( 426; CHECK-NEXT: [[CMP2_INV:%.*]] = fcmp ole float [[X:%.*]], 1.000000e+00 427; CHECK-NEXT: [[MAX:%.*]] = select i1 [[CMP2_INV]], float 1.000000e+00, float [[X]] 428; CHECK-NEXT: [[CMP1:%.*]] = fcmp ugt float [[X]], 2.550000e+02 429; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP1]], float 2.550000e+02, float [[MAX]] 430; CHECK-NEXT: ret float [[R]] 431; 432 %cmp2 = fcmp ugt float %x, 1.0 ; x is NaN => true 433 %max = select i1 %cmp2, float %x, float 1.0 ; NaN 434 %cmp1 = fcmp ugt float %x, 255.0 ; true 435 %r = select i1 %cmp1, float 255.0, float %max ; 255.0 436 ret float %r 437} 438 439; (X >= C1) ? C1 : MAX(X, C2) 440define float @clamp_float_unordered_nonstrict_minmax1(float %x) { 441; CHECK-LABEL: define {{[^@]+}}@clamp_float_unordered_nonstrict_minmax1( 442; CHECK-NEXT: [[CMP2:%.*]] = fcmp ogt float [[X:%.*]], 1.000000e+00 443; CHECK-NEXT: [[MAX:%.*]] = select i1 [[CMP2]], float [[X]], float 1.000000e+00 444; CHECK-NEXT: [[CMP1:%.*]] = fcmp uge float [[X]], 2.550000e+02 445; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP1]], float 2.550000e+02, float [[MAX]] 446; CHECK-NEXT: ret float [[R]] 447; 448 %cmp2 = fcmp ogt float %x, 1.0 ; x is NaN => false 449 %max = select i1 %cmp2, float %x, float 1.0 ; 1.0 450 %cmp1 = fcmp uge float %x, 255.0 ; true 451 %r = select i1 %cmp1, float 255.0, float %max ; 255.0 452 ret float %r 453} 454 455define float @clamp_float_unordered_nonstrict_minmax2(float %x) { 456; CHECK-LABEL: define {{[^@]+}}@clamp_float_unordered_nonstrict_minmax2( 457; CHECK-NEXT: [[CMP2_INV:%.*]] = fcmp ole float [[X:%.*]], 1.000000e+00 458; CHECK-NEXT: [[MAX:%.*]] = select i1 [[CMP2_INV]], float 1.000000e+00, float [[X]] 459; CHECK-NEXT: [[CMP1:%.*]] = fcmp uge float [[X]], 2.550000e+02 460; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP1]], float 2.550000e+02, float [[MAX]] 461; CHECK-NEXT: ret float [[R]] 462; 463 %cmp2 = fcmp ugt float %x, 1.0 ; x is NaN => true 464 %max = select i1 %cmp2, float %x, float 1.0 ; NaN 465 %cmp1 = fcmp uge float %x, 255.0 ; true 466 %r = select i1 %cmp1, float 255.0, float %max ; 255.0 467 ret float %r 468} 469 470;; Check casts behavior 471define float @ui32_clamp_and_cast_to_float(i32 %x) { 472; CHECK-LABEL: define {{[^@]+}}@ui32_clamp_and_cast_to_float( 473; CHECK-NEXT: [[LO_CMP:%.*]] = icmp eq i32 [[X:%.*]], 0 474; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[X]], 255 475; CHECK-NEXT: [[MIN1:%.*]] = select i1 [[TMP1]], i32 [[X]], i32 255 476; CHECK-NEXT: [[TMP2:%.*]] = uitofp i32 [[MIN1]] to float 477; CHECK-NEXT: [[R:%.*]] = select i1 [[LO_CMP]], float 1.000000e+00, float [[TMP2]] 478; CHECK-NEXT: ret float [[R]] 479; 480 %f_x = uitofp i32 %x to float 481 %up_cmp = icmp ugt i32 %x, 255 482 %lo_cmp = icmp ult i32 %x, 1 483 %min = select i1 %up_cmp, float 255.0, float %f_x 484 %r = select i1 %lo_cmp, float 1.0, float %min 485 ret float %r 486} 487 488define float @ui64_clamp_and_cast_to_float(i64 %x) { 489; CHECK-LABEL: define {{[^@]+}}@ui64_clamp_and_cast_to_float( 490; CHECK-NEXT: [[LO_CMP:%.*]] = icmp eq i64 [[X:%.*]], 0 491; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i64 [[X]], 255 492; CHECK-NEXT: [[MIN1:%.*]] = select i1 [[TMP1]], i64 [[X]], i64 255 493; CHECK-NEXT: [[TMP2:%.*]] = uitofp i64 [[MIN1]] to float 494; CHECK-NEXT: [[R:%.*]] = select i1 [[LO_CMP]], float 1.000000e+00, float [[TMP2]] 495; CHECK-NEXT: ret float [[R]] 496; 497 %f_x = uitofp i64 %x to float 498 %up_cmp = icmp ugt i64 %x, 255 499 %lo_cmp = icmp ult i64 %x, 1 500 %min = select i1 %up_cmp, float 255.0, float %f_x 501 %r = select i1 %lo_cmp, float 1.0, float %min 502 ret float %r 503} 504 505define float @mixed_clamp_to_float_1(i32 %x) { 506; CHECK-LABEL: define {{[^@]+}}@mixed_clamp_to_float_1( 507; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 255 508; CHECK-NEXT: [[SI_MIN:%.*]] = select i1 [[TMP1]], i32 [[X]], i32 255 509; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[SI_MIN]], 1 510; CHECK-NEXT: [[R1:%.*]] = select i1 [[TMP2]], i32 [[SI_MIN]], i32 1 511; CHECK-NEXT: [[TMP3:%.*]] = sitofp i32 [[R1]] to float 512; CHECK-NEXT: ret float [[TMP3]] 513; 514 %si_min_cmp = icmp sgt i32 %x, 255 515 %si_min = select i1 %si_min_cmp, i32 255, i32 %x 516 %f_min = sitofp i32 %si_min to float 517 %f_x = sitofp i32 %x to float 518 %lo_cmp = fcmp ult float %f_x, 1.0 519 %r = select i1 %lo_cmp, float 1.0, float %f_min 520 ret float %r 521} 522 523define i32 @mixed_clamp_to_i32_1(float %x) { 524; CHECK-LABEL: define {{[^@]+}}@mixed_clamp_to_i32_1( 525; CHECK-NEXT: [[FLOAT_MIN_CMP:%.*]] = fcmp ogt float [[X:%.*]], 2.550000e+02 526; CHECK-NEXT: [[FLOAT_MIN:%.*]] = select i1 [[FLOAT_MIN_CMP]], float 2.550000e+02, float [[X]] 527; CHECK-NEXT: [[I32_MIN:%.*]] = fptosi float [[FLOAT_MIN]] to i32 528; CHECK-NEXT: [[I32_X:%.*]] = fptosi float [[X]] to i32 529; CHECK-NEXT: [[LO_CMP:%.*]] = icmp eq i32 [[I32_X]], 0 530; CHECK-NEXT: [[R:%.*]] = select i1 [[LO_CMP]], i32 1, i32 [[I32_MIN]] 531; CHECK-NEXT: ret i32 [[R]] 532; 533 %float_min_cmp = fcmp ogt float %x, 255.0 534 %float_min = select i1 %float_min_cmp, float 255.0, float %x 535 %i32_min = fptosi float %float_min to i32 536 %i32_x = fptosi float %x to i32 537 %lo_cmp = icmp ult i32 %i32_x, 1 538 %r = select i1 %lo_cmp, i32 1, i32 %i32_min 539 ret i32 %r 540} 541 542define float @mixed_clamp_to_float_2(i32 %x) { 543; CHECK-LABEL: define {{[^@]+}}@mixed_clamp_to_float_2( 544; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 255 545; CHECK-NEXT: [[SI_MIN:%.*]] = select i1 [[TMP1]], i32 [[X]], i32 255 546; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[SI_MIN]], 1 547; CHECK-NEXT: [[R1:%.*]] = select i1 [[TMP2]], i32 [[SI_MIN]], i32 1 548; CHECK-NEXT: [[TMP3:%.*]] = sitofp i32 [[R1]] to float 549; CHECK-NEXT: ret float [[TMP3]] 550; 551 %si_min_cmp = icmp sgt i32 %x, 255 552 %si_min = select i1 %si_min_cmp, i32 255, i32 %x 553 %f_min = sitofp i32 %si_min to float 554 %lo_cmp = icmp slt i32 %x, 1 555 %r = select i1 %lo_cmp, float 1.0, float %f_min 556 ret float %r 557} 558 559define i32 @mixed_clamp_to_i32_2(float %x) { 560; CHECK-LABEL: define {{[^@]+}}@mixed_clamp_to_i32_2( 561; CHECK-NEXT: [[FLOAT_MIN_CMP:%.*]] = fcmp ogt float [[X:%.*]], 2.550000e+02 562; CHECK-NEXT: [[FLOAT_MIN:%.*]] = select i1 [[FLOAT_MIN_CMP]], float 2.550000e+02, float [[X]] 563; CHECK-NEXT: [[I32_MIN:%.*]] = fptosi float [[FLOAT_MIN]] to i32 564; CHECK-NEXT: [[LO_CMP:%.*]] = fcmp olt float [[X]], 1.000000e+00 565; CHECK-NEXT: [[R:%.*]] = select i1 [[LO_CMP]], i32 1, i32 [[I32_MIN]] 566; CHECK-NEXT: ret i32 [[R]] 567; 568 %float_min_cmp = fcmp ogt float %x, 255.0 569 %float_min = select i1 %float_min_cmp, float 255.0, float %x 570 %i32_min = fptosi float %float_min to i32 571 %lo_cmp = fcmp olt float %x, 1.0 572 %r = select i1 %lo_cmp, i32 1, i32 %i32_min 573 ret i32 %r 574} 575