1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2 ; RUN: opt < %s -instsimplify -S | FileCheck %s 3 4 define <2 x float> @fsub_negzero_vec_undef_elts(<2 x float> %x) { 5 ; CHECK-LABEL: @fsub_negzero_vec_undef_elts( 6 ; CHECK-NEXT: ret <2 x float> [[X:%.*]] 7 ; 8 %r = fsub nsz <2 x float> %x, <float undef, float -0.0> 9 ret <2 x float> %r 10 } 11 12 ; fsub -0.0, (fsub -0.0, X) ==> X 13 define float @fsub_-0_-0_x(float %a) { 14 ; CHECK-LABEL: @fsub_-0_-0_x( 15 ; CHECK-NEXT: ret float [[A:%.*]] 16 ; 17 %t1 = fsub float -0.0, %a 18 %ret = fsub float -0.0, %t1 19 ret float %ret 20 } 21 22 define <2 x float> @fsub_-0_-0_x_vec(<2 x float> %a) { 23 ; CHECK-LABEL: @fsub_-0_-0_x_vec( 24 ; CHECK-NEXT: ret <2 x float> [[A:%.*]] 25 ; 26 %t1 = fsub <2 x float> <float -0.0, float -0.0>, %a 27 %ret = fsub <2 x float> <float -0.0, float -0.0>, %t1 28 ret <2 x float> %ret 29 } 30 31 define <2 x float> @fsub_-0_-0_x_vec_undef_elts(<2 x float> %a) { 32 ; CHECK-LABEL: @fsub_-0_-0_x_vec_undef_elts( 33 ; CHECK-NEXT: ret <2 x float> [[A:%.*]] 34 ; 35 %t1 = fsub <2 x float> <float undef, float -0.0>, %a 36 %ret = fsub <2 x float> <float -0.0, float undef>, %t1 37 ret <2 x float> %ret 38 } 39 40 ; fsub 0.0, (fsub -0.0, X) != X 41 define float @fsub_0_-0_x(float %a) { 42 ; CHECK-LABEL: @fsub_0_-0_x( 43 ; CHECK-NEXT: [[T1:%.*]] = fsub float 0.000000e+00, [[A:%.*]] 44 ; CHECK-NEXT: [[RET:%.*]] = fsub float -0.000000e+00, [[T1]] 45 ; CHECK-NEXT: ret float [[RET]] 46 ; 47 %t1 = fsub float 0.0, %a 48 %ret = fsub float -0.0, %t1 49 ret float %ret 50 } 51 52 ; fsub -0.0, (fsub 0.0, X) != X 53 define float @fsub_-0_0_x(float %a) { 54 ; CHECK-LABEL: @fsub_-0_0_x( 55 ; CHECK-NEXT: [[T1:%.*]] = fsub float -0.000000e+00, [[A:%.*]] 56 ; CHECK-NEXT: [[RET:%.*]] = fsub float 0.000000e+00, [[T1]] 57 ; CHECK-NEXT: ret float [[RET]] 58 ; 59 %t1 = fsub float -0.0, %a 60 %ret = fsub float 0.0, %t1 61 ret float %ret 62 } 63 64 ; fsub X, 0 ==> X 65 define float @fsub_x_0(float %x) { 66 ; CHECK-LABEL: @fsub_x_0( 67 ; CHECK-NEXT: ret float [[X:%.*]] 68 ; 69 %r = fsub float %x, 0.0 70 ret float %r 71 } 72 73 define <2 x float> @fsub_x_0_vec_undef(<2 x float> %x) { 74 ; CHECK-LABEL: @fsub_x_0_vec_undef( 75 ; CHECK-NEXT: ret <2 x float> [[X:%.*]] 76 ; 77 %r = fsub <2 x float> %x, <float undef, float 0.0> 78 ret <2 x float> %r 79 } 80 81 ; fadd X, -0 ==> X 82 define float @fadd_x_n0(float %a) { 83 ; CHECK-LABEL: @fadd_x_n0( 84 ; CHECK-NEXT: ret float [[A:%.*]] 85 ; 86 %ret = fadd float %a, -0.0 87 ret float %ret 88 } 89 90 define <2 x float> @fadd_x_n0_vec_undef_elt(<2 x float> %a) { 91 ; CHECK-LABEL: @fadd_x_n0_vec_undef_elt( 92 ; CHECK-NEXT: ret <2 x float> [[A:%.*]] 93 ; 94 %ret = fadd <2 x float> %a, <float -0.0, float undef> 95 ret <2 x float> %ret 96 } 97 98 ; fmul X, 1.0 ==> X 99 define double @fmul_X_1(double %a) { 100 ; CHECK-LABEL: @fmul_X_1( 101 ; CHECK-NEXT: ret double [[A:%.*]] 102 ; 103 %b = fmul double 1.0, %a 104 ret double %b 105 } 106 107 ; PR2642 108 define <4 x float> @fmul_X_1_vec(<4 x float> %x) { 109 ; CHECK-LABEL: @fmul_X_1_vec( 110 ; CHECK-NEXT: ret <4 x float> [[X:%.*]] 111 ; 112 %m = fmul <4 x float> %x, <float 1.0, float 1.0, float 1.0, float 1.0> 113 ret <4 x float> %m 114 } 115 116 ; fdiv X, 1.0 ==> X 117 define float @fdiv_x_1(float %a) { 118 ; CHECK-LABEL: @fdiv_x_1( 119 ; CHECK-NEXT: ret float [[A:%.*]] 120 ; 121 %ret = fdiv float %a, 1.0 122 ret float %ret 123 } 124 125 ; We can't optimize away the fadd in this test because the input 126 ; value to the function and subsequently to the fadd may be -0.0. 127 ; In that one special case, the result of the fadd should be +0.0 128 ; rather than the first parameter of the fadd. 129 130 ; Fragile test warning: We need 6 sqrt calls to trigger the bug 131 ; because the internal logic has a magic recursion limit of 6. 132 ; This is presented without any explanation or ability to customize. 133 134 declare float @sqrtf(float) 135 136 define float @PR22688(float %x) { 137 ; CHECK-LABEL: @PR22688( 138 ; CHECK-NEXT: [[TMP1:%.*]] = call float @sqrtf(float [[X:%.*]]) 139 ; CHECK-NEXT: [[TMP2:%.*]] = call float @sqrtf(float [[TMP1]]) 140 ; CHECK-NEXT: [[TMP3:%.*]] = call float @sqrtf(float [[TMP2]]) 141 ; CHECK-NEXT: [[TMP4:%.*]] = call float @sqrtf(float [[TMP3]]) 142 ; CHECK-NEXT: [[TMP5:%.*]] = call float @sqrtf(float [[TMP4]]) 143 ; CHECK-NEXT: [[TMP6:%.*]] = call float @sqrtf(float [[TMP5]]) 144 ; CHECK-NEXT: [[TMP7:%.*]] = fadd float [[TMP6]], 0.000000e+00 145 ; CHECK-NEXT: ret float [[TMP7]] 146 ; 147 %1 = call float @sqrtf(float %x) 148 %2 = call float @sqrtf(float %1) 149 %3 = call float @sqrtf(float %2) 150 %4 = call float @sqrtf(float %3) 151 %5 = call float @sqrtf(float %4) 152 %6 = call float @sqrtf(float %5) 153 %7 = fadd float %6, 0.0 154 ret float %7 155 } 156 157 declare float @llvm.fabs.f32(float) 158 declare <2 x float> @llvm.fabs.v2f32(<2 x float>) 159 declare float @llvm.sqrt.f32(float) 160 161 define float @fabs_select_positive_constants(i32 %c) { 162 ; CHECK-LABEL: @fabs_select_positive_constants( 163 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 164 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 1.000000e+00, float 2.000000e+00 165 ; CHECK-NEXT: ret float [[SELECT]] 166 ; 167 %cmp = icmp eq i32 %c, 0 168 %select = select i1 %cmp, float 1.0, float 2.0 169 %fabs = call float @llvm.fabs.f32(float %select) 170 ret float %fabs 171 } 172 173 define <2 x float> @fabs_select_positive_constants_vector(i32 %c) { 174 ; CHECK-LABEL: @fabs_select_positive_constants_vector( 175 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 176 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 1.000000e+00, float 1.000000e+00>, <2 x float> <float 2.000000e+00, float 2.000000e+00> 177 ; CHECK-NEXT: ret <2 x float> [[SELECT]] 178 ; 179 %cmp = icmp eq i32 %c, 0 180 %select = select i1 %cmp, <2 x float> <float 1.0, float 1.0>, <2 x float> <float 2.0, float 2.0> 181 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 182 ret <2 x float> %fabs 183 } 184 185 define float @fabs_select_constant_variable(i32 %c, float %x) { 186 ; CHECK-LABEL: @fabs_select_constant_variable( 187 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 188 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 1.000000e+00, float [[X:%.*]] 189 ; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) 190 ; CHECK-NEXT: ret float [[FABS]] 191 ; 192 %cmp = icmp eq i32 %c, 0 193 %select = select i1 %cmp, float 1.0, float %x 194 %fabs = call float @llvm.fabs.f32(float %select) 195 ret float %fabs 196 } 197 198 define <2 x float> @fabs_select_constant_variable_vector(i32 %c, <2 x float> %x) { 199 ; CHECK-LABEL: @fabs_select_constant_variable_vector( 200 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 201 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 1.000000e+00, float 1.000000e+00>, <2 x float> [[X:%.*]] 202 ; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]]) 203 ; CHECK-NEXT: ret <2 x float> [[FABS]] 204 ; 205 %cmp = icmp eq i32 %c, 0 206 %select = select i1 %cmp, <2 x float> <float 1.0, float 1.0>, <2 x float> %x 207 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 208 ret <2 x float> %fabs 209 } 210 211 define float @fabs_select_neg0_pos0(i32 %c) { 212 ; CHECK-LABEL: @fabs_select_neg0_pos0( 213 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 214 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float -0.000000e+00, float 0.000000e+00 215 ; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) 216 ; CHECK-NEXT: ret float [[FABS]] 217 ; 218 %cmp = icmp eq i32 %c, 0 219 %select = select i1 %cmp, float -0.0, float 0.0 220 %fabs = call float @llvm.fabs.f32(float %select) 221 ret float %fabs 222 } 223 224 define <2 x float> @fabs_select_neg0_pos0_vector(i32 %c) { 225 ; CHECK-LABEL: @fabs_select_neg0_pos0_vector( 226 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 227 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float -0.000000e+00, float -0.000000e+00>, <2 x float> zeroinitializer 228 ; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]]) 229 ; CHECK-NEXT: ret <2 x float> [[FABS]] 230 ; 231 %cmp = icmp eq i32 %c, 0 232 %select = select i1 %cmp, <2 x float> <float -0.0, float -0.0>, <2 x float> <float 0.0, float 0.0> 233 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 234 ret <2 x float> %fabs 235 } 236 237 define float @fabs_select_neg0_neg1(i32 %c) { 238 ; CHECK-LABEL: @fabs_select_neg0_neg1( 239 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 240 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float -0.000000e+00, float -1.000000e+00 241 ; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) 242 ; CHECK-NEXT: ret float [[FABS]] 243 ; 244 %cmp = icmp eq i32 %c, 0 245 %select = select i1 %cmp, float -0.0, float -1.0 246 %fabs = call float @llvm.fabs.f32(float %select) 247 ret float %fabs 248 } 249 250 define <2 x float> @fabs_select_neg0_neg1_vector(i32 %c) { 251 ; CHECK-LABEL: @fabs_select_neg0_neg1_vector( 252 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 253 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float -0.000000e+00, float -0.000000e+00>, <2 x float> <float -1.000000e+00, float -1.000000e+00> 254 ; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]]) 255 ; CHECK-NEXT: ret <2 x float> [[FABS]] 256 ; 257 %cmp = icmp eq i32 %c, 0 258 %select = select i1 %cmp, <2 x float> <float -0.0, float -0.0>, <2 x float> <float -1.0, float -1.0> 259 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 260 ret <2 x float> %fabs 261 } 262 263 define float @fabs_select_nan_nan(i32 %c) { 264 ; CHECK-LABEL: @fabs_select_nan_nan( 265 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 266 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 0x7FF8000000000000, float 0x7FF8000100000000 267 ; CHECK-NEXT: ret float [[SELECT]] 268 ; 269 %cmp = icmp eq i32 %c, 0 270 %select = select i1 %cmp, float 0x7FF8000000000000, float 0x7FF8000100000000 271 %fabs = call float @llvm.fabs.f32(float %select) 272 ret float %fabs 273 } 274 275 define <2 x float> @fabs_select_nan_nan_vector(i32 %c) { 276 ; CHECK-LABEL: @fabs_select_nan_nan_vector( 277 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 278 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000> 279 ; CHECK-NEXT: ret <2 x float> [[SELECT]] 280 ; 281 %cmp = icmp eq i32 %c, 0 282 %select = select i1 %cmp, <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000> 283 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 284 ret <2 x float> %fabs 285 } 286 287 define float @fabs_select_negnan_nan(i32 %c) { 288 ; CHECK-LABEL: @fabs_select_negnan_nan( 289 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 290 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float 0x7FF8000000000000 291 ; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) 292 ; CHECK-NEXT: ret float [[FABS]] 293 ; 294 %cmp = icmp eq i32 %c, 0 295 %select = select i1 %cmp, float 0xFFF8000000000000, float 0x7FF8000000000000 296 %fabs = call float @llvm.fabs.f32(float %select) 297 ret float %fabs 298 } 299 300 define <2 x float> @fabs_select_negnan_nan_vector(i32 %c) { 301 ; CHECK-LABEL: @fabs_select_negnan_nan_vector( 302 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 303 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000> 304 ; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]]) 305 ; CHECK-NEXT: ret <2 x float> [[FABS]] 306 ; 307 %cmp = icmp eq i32 %c, 0 308 %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000> 309 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 310 ret <2 x float> %fabs 311 } 312 313 define float @fabs_select_negnan_negnan(i32 %c) { 314 ; CHECK-LABEL: @fabs_select_negnan_negnan( 315 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 316 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float 0x7FF8000100000000 317 ; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) 318 ; CHECK-NEXT: ret float [[FABS]] 319 ; 320 %cmp = icmp eq i32 %c, 0 321 %select = select i1 %cmp, float 0xFFF8000000000000, float 0x7FF8000100000000 322 %fabs = call float @llvm.fabs.f32(float %select) 323 ret float %fabs 324 } 325 326 define <2 x float> @fabs_select_negnan_negnan_vector(i32 %c) { 327 ; CHECK-LABEL: @fabs_select_negnan_negnan_vector( 328 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 329 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000> 330 ; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]]) 331 ; CHECK-NEXT: ret <2 x float> [[FABS]] 332 ; 333 %cmp = icmp eq i32 %c, 0 334 %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000> 335 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 336 ret <2 x float> %fabs 337 } 338 339 define float @fabs_select_negnan_negzero(i32 %c) { 340 ; CHECK-LABEL: @fabs_select_negnan_negzero( 341 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 342 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float -0.000000e+00 343 ; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) 344 ; CHECK-NEXT: ret float [[FABS]] 345 ; 346 %cmp = icmp eq i32 %c, 0 347 %select = select i1 %cmp, float 0xFFF8000000000000, float -0.0 348 %fabs = call float @llvm.fabs.f32(float %select) 349 ret float %fabs 350 } 351 352 define <2 x float> @fabs_select_negnan_negzero_vector(i32 %c) { 353 ; CHECK-LABEL: @fabs_select_negnan_negzero_vector( 354 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 355 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float -0.000000e+00, float -0.000000e+00> 356 ; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]]) 357 ; CHECK-NEXT: ret <2 x float> [[FABS]] 358 ; 359 %cmp = icmp eq i32 %c, 0 360 %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float -0.0, float -0.0> 361 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 362 ret <2 x float> %fabs 363 } 364 365 define float @fabs_select_negnan_zero(i32 %c) { 366 ; CHECK-LABEL: @fabs_select_negnan_zero( 367 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 368 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float 0.000000e+00 369 ; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]]) 370 ; CHECK-NEXT: ret float [[FABS]] 371 ; 372 %cmp = icmp eq i32 %c, 0 373 %select = select i1 %cmp, float 0xFFF8000000000000, float 0.0 374 %fabs = call float @llvm.fabs.f32(float %select) 375 ret float %fabs 376 } 377 378 define <2 x float> @fabs_select_negnan_zero_vector(i32 %c) { 379 ; CHECK-LABEL: @fabs_select_negnan_zero_vector( 380 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 381 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> zeroinitializer 382 ; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]]) 383 ; CHECK-NEXT: ret <2 x float> [[FABS]] 384 ; 385 %cmp = icmp eq i32 %c, 0 386 %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0.0, float 0.0> 387 %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select) 388 ret <2 x float> %fabs 389 } 390 391 ; The fabs can't be eliminated because llvm.sqrt.f32 may return -0 or NaN with 392 ; an arbitrary sign bit. 393 define float @fabs_sqrt(float %a) { 394 ; CHECK-LABEL: @fabs_sqrt( 395 ; CHECK-NEXT: [[SQRT:%.*]] = call float @llvm.sqrt.f32(float [[A:%.*]]) 396 ; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]]) 397 ; CHECK-NEXT: ret float [[FABS]] 398 ; 399 %sqrt = call float @llvm.sqrt.f32(float %a) 400 %fabs = call float @llvm.fabs.f32(float %sqrt) 401 ret float %fabs 402 } 403 404 ; The fabs can't be eliminated because the nnan sqrt may still return -0. 405 define float @fabs_sqrt_nnan(float %a) { 406 ; CHECK-LABEL: @fabs_sqrt_nnan( 407 ; CHECK-NEXT: [[SQRT:%.*]] = call nnan float @llvm.sqrt.f32(float [[A:%.*]]) 408 ; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]]) 409 ; CHECK-NEXT: ret float [[FABS]] 410 ; 411 %sqrt = call nnan float @llvm.sqrt.f32(float %a) 412 %fabs = call float @llvm.fabs.f32(float %sqrt) 413 ret float %fabs 414 } 415 416 ; The fabs can't be eliminated because the nsz sqrt may still return NaN. 417 define float @fabs_sqrt_nsz(float %a) { 418 ; CHECK-LABEL: @fabs_sqrt_nsz( 419 ; CHECK-NEXT: [[SQRT:%.*]] = call nsz float @llvm.sqrt.f32(float [[A:%.*]]) 420 ; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]]) 421 ; CHECK-NEXT: ret float [[FABS]] 422 ; 423 %sqrt = call nsz float @llvm.sqrt.f32(float %a) 424 %fabs = call float @llvm.fabs.f32(float %sqrt) 425 ret float %fabs 426 } 427 428 ; The fabs can be eliminated because we're nsz and nnan. 429 define float @fabs_sqrt_nnan_nsz(float %a) { 430 ; CHECK-LABEL: @fabs_sqrt_nnan_nsz( 431 ; CHECK-NEXT: [[SQRT:%.*]] = call nnan nsz float @llvm.sqrt.f32(float [[A:%.*]]) 432 ; CHECK-NEXT: ret float [[SQRT]] 433 ; 434 %sqrt = call nnan nsz float @llvm.sqrt.f32(float %a) 435 %fabs = call float @llvm.fabs.f32(float %sqrt) 436 ret float %fabs 437 } 438 439 ; The second fabs can be eliminated because the operand to sqrt cannot be -0. 440 define float @fabs_sqrt_nnan_fabs(float %a) { 441 ; CHECK-LABEL: @fabs_sqrt_nnan_fabs( 442 ; CHECK-NEXT: [[B:%.*]] = call float @llvm.fabs.f32(float [[A:%.*]]) 443 ; CHECK-NEXT: [[SQRT:%.*]] = call nnan float @llvm.sqrt.f32(float [[B]]) 444 ; CHECK-NEXT: ret float [[SQRT]] 445 ; 446 %b = call float @llvm.fabs.f32(float %a) 447 %sqrt = call nnan float @llvm.sqrt.f32(float %b) 448 %fabs = call float @llvm.fabs.f32(float %sqrt) 449 ret float %fabs 450 } 451 452 define float @fabs_select_positive_constants_vector_extract(i32 %c) { 453 ; CHECK-LABEL: @fabs_select_positive_constants_vector_extract( 454 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0 455 ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 1.000000e+00, float 1.000000e+00>, <2 x float> <float 2.000000e+00, float 2.000000e+00> 456 ; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement <2 x float> [[SELECT]], i32 0 457 ; CHECK-NEXT: ret float [[EXTRACT]] 458 ; 459 %cmp = icmp eq i32 %c, 0 460 %select = select i1 %cmp, <2 x float> <float 1.0, float 1.0>, <2 x float> <float 2.0, float 2.0> 461 %extract = extractelement <2 x float> %select, i32 0 462 %fabs = call float @llvm.fabs.f32(float %extract) 463 ret float %fabs 464 } 465 466 declare double @llvm.minnum.f64(double, double) 467 declare double @llvm.maxnum.f64(double, double) 468 declare <2 x double> @llvm.minnum.v2f64(<2 x double>, <2 x double>) 469 declare <2 x double> @llvm.maxnum.v2f64(<2 x double>, <2 x double>) 470 471 ; From the LangRef for minnum/maxnum: 472 ; "follows the IEEE-754 semantics for maxNum, which also match for libms fmax. 473 ; If either operand is a NaN, returns the other non-NaN operand." 474 475 define double @maxnum_nan_op0(double %x) { 476 ; CHECK-LABEL: @maxnum_nan_op0( 477 ; CHECK-NEXT: ret double [[X:%.*]] 478 ; 479 %r = call double @llvm.maxnum.f64(double 0x7ff8000000000000, double %x) 480 ret double %r 481 } 482 483 define double @maxnum_nan_op1(double %x) { 484 ; CHECK-LABEL: @maxnum_nan_op1( 485 ; CHECK-NEXT: ret double [[X:%.*]] 486 ; 487 %r = call double @llvm.maxnum.f64(double %x, double 0x7ff800000000dead) 488 ret double %r 489 } 490 491 define double @minnum_nan_op0(double %x) { 492 ; CHECK-LABEL: @minnum_nan_op0( 493 ; CHECK-NEXT: ret double [[X:%.*]] 494 ; 495 %r = call double @llvm.minnum.f64(double 0x7ff8000dead00000, double %x) 496 ret double %r 497 } 498 499 define double @minnum_nan_op1(double %x) { 500 ; CHECK-LABEL: @minnum_nan_op1( 501 ; CHECK-NEXT: ret double [[X:%.*]] 502 ; 503 %r = call double @llvm.minnum.f64(double %x, double 0x7ff800dead00dead) 504 ret double %r 505 } 506 507 define <2 x double> @maxnum_nan_op0_vec(<2 x double> %x) { 508 ; CHECK-LABEL: @maxnum_nan_op0_vec( 509 ; CHECK-NEXT: ret <2 x double> [[X:%.*]] 510 ; 511 %r = call <2 x double> @llvm.maxnum.v2f64(<2 x double> <double 0x7ff8000000000000, double undef>, <2 x double> %x) 512 ret <2 x double> %r 513 } 514 515 define <2 x double> @maxnum_nan_op1_vec(<2 x double> %x) { 516 ; CHECK-LABEL: @maxnum_nan_op1_vec( 517 ; CHECK-NEXT: ret <2 x double> [[X:%.*]] 518 ; 519 %r = call <2 x double> @llvm.maxnum.v2f64(<2 x double> %x, <2 x double> <double 0x7ff800000000dead, double 0x7ff8ffffffffffff>) 520 ret <2 x double> %r 521 } 522 523 define <2 x double> @minnum_nan_op0_vec(<2 x double> %x) { 524 ; CHECK-LABEL: @minnum_nan_op0_vec( 525 ; CHECK-NEXT: ret <2 x double> [[X:%.*]] 526 ; 527 %r = call <2 x double> @llvm.minnum.v2f64(<2 x double> <double undef, double 0x7ff8000dead00000>, <2 x double> %x) 528 ret <2 x double> %r 529 } 530 531 define <2 x double> @minnum_nan_op1_vec(<2 x double> %x) { 532 ; CHECK-LABEL: @minnum_nan_op1_vec( 533 ; CHECK-NEXT: ret <2 x double> [[X:%.*]] 534 ; 535 %r = call <2 x double> @llvm.minnum.v2f64(<2 x double> %x, <2 x double> <double 0x7ff800dead00dead, double 0x7ff800dead00dead>) 536 ret <2 x double> %r 537 } 538 539