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