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