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) 5 define 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) 22 define 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) 39 define 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) 56 define 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) 76 define 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) 93 define 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) 110 define 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) 127 define 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. 147 define 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 165 define 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 181 define 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 200 define 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 215 define 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) 237 define 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 253 define 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) 270 define 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 286 define 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) 303 define 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 319 define 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) 336 define 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 352 define 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) 372 define 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 388 define 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) 405 define 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 421 define 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) 438 define 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 454 define 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) 471 define 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 487 define 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 504 define 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 521 define 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 538 define 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 556 define 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 575 define 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 592 define 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