1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instsimplify -S | FileCheck %s 3 4; 5; constrained fsub 6; 7 8; 9; fsub X, +0 ==> X 10; 11 12define float @fsub_x_p0_defaultenv(float %a) #0 { 13; CHECK-LABEL: @fsub_x_p0_defaultenv( 14; CHECK-NEXT: ret float [[A:%.*]] 15; 16 %ret = call float @llvm.experimental.constrained.fsub.f32(float %a, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") 17 ret float %ret 18} 19 20; Missing nnan: must not fire. 21define float @fsub_x_p0_ebmaytrap(float %a) #0 { 22; CHECK-LABEL: @fsub_x_p0_ebmaytrap( 23; CHECK-NEXT: [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[A:%.*]], float 0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.maytrap") 24; CHECK-NEXT: ret float [[RET]] 25; 26 %ret = call float @llvm.experimental.constrained.fsub.f32(float %a, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.maytrap") 27 ret float %ret 28} 29 30define float @fsub_nnan_x_p0_ebmaytrap(float %a) #0 { 31; CHECK-LABEL: @fsub_nnan_x_p0_ebmaytrap( 32; CHECK-NEXT: ret float [[A:%.*]] 33; 34 %ret = call nnan float @llvm.experimental.constrained.fsub.f32(float %a, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.maytrap") 35 ret float %ret 36} 37 38; Missing nnan: must not fire. 39define float @fsub_x_p0_ebstrict(float %a) #0 { 40; CHECK-LABEL: @fsub_x_p0_ebstrict( 41; CHECK-NEXT: [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[A:%.*]], float 0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.strict") 42; CHECK-NEXT: ret float [[RET]] 43; 44 %ret = call float @llvm.experimental.constrained.fsub.f32(float %a, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.strict") 45 ret float %ret 46} 47 48; The instruction is expected to remain, but the result isn't used. 49define float @fsub_nnan_x_p0_ebstrict(float %a) #0 { 50; CHECK-LABEL: @fsub_nnan_x_p0_ebstrict( 51; CHECK-NEXT: [[RET:%.*]] = call nnan float @llvm.experimental.constrained.fsub.f32(float [[A:%.*]], float 0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.strict") 52; CHECK-NEXT: ret float [[A]] 53; 54 %ret = call nnan float @llvm.experimental.constrained.fsub.f32(float %a, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.strict") 55 ret float %ret 56} 57 58; Test with a fast math flag set but that flag is not "nnan". 59define float @fsub_ninf_x_p0_ebstrict(float %a) #0 { 60; CHECK-LABEL: @fsub_ninf_x_p0_ebstrict( 61; CHECK-NEXT: [[RET:%.*]] = call ninf float @llvm.experimental.constrained.fsub.f32(float [[A:%.*]], float 0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.strict") 62; CHECK-NEXT: ret float [[RET]] 63; 64 %ret = call ninf float @llvm.experimental.constrained.fsub.f32(float %a, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.strict") 65 ret float %ret 66} 67 68; Round to -inf and if x is zero then the result is -0.0: must not fire 69define float @fsub_x_p0_neginf(float %a) #0 { 70; CHECK-LABEL: @fsub_x_p0_neginf( 71; CHECK-NEXT: [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[A:%.*]], float 0.000000e+00, metadata !"round.downward", metadata !"fpexcept.ignore") 72; CHECK-NEXT: ret float [[RET]] 73; 74 %ret = call float @llvm.experimental.constrained.fsub.f32(float %a, float 0.0, metadata !"round.downward", metadata !"fpexcept.ignore") 75 ret float %ret 76} 77 78; Dynamic rounding means the rounding mode might be to -inf: 79; Round to -inf and if x is zero then the result is -0.0: must not fire 80define float @fsub_x_p0_dynamic(float %a) #0 { 81; CHECK-LABEL: @fsub_x_p0_dynamic( 82; CHECK-NEXT: [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[A:%.*]], float 0.000000e+00, metadata !"round.dynamic", metadata !"fpexcept.ignore") 83; CHECK-NEXT: ret float [[RET]] 84; 85 %ret = call float @llvm.experimental.constrained.fsub.f32(float %a, float 0.0, metadata !"round.dynamic", metadata !"fpexcept.ignore") 86 ret float %ret 87} 88 89; With nsz we don't have to worry about -0.0 so the transform is valid. 90define float @fsub_nsz_x_p0_neginf(float %a) #0 { 91; CHECK-LABEL: @fsub_nsz_x_p0_neginf( 92; CHECK-NEXT: ret float [[A:%.*]] 93; 94 %ret = call nsz float @llvm.experimental.constrained.fsub.f32(float %a, float 0.0, metadata !"round.downward", metadata !"fpexcept.ignore") 95 ret float %ret 96} 97 98; With nsz we don't have to worry about -0.0 so the transform is valid. 99define float @fsub_nsz_x_p0_dynamic(float %a) #0 { 100; CHECK-LABEL: @fsub_nsz_x_p0_dynamic( 101; CHECK-NEXT: ret float [[A:%.*]] 102; 103 %ret = call nsz float @llvm.experimental.constrained.fsub.f32(float %a, float 0.0, metadata !"round.dynamic", metadata !"fpexcept.ignore") 104 ret float %ret 105} 106 107; 108; fsub X, -0 ==> X, when we know X is not -0 109; (fast math flag: nsz) 110; 111 112define float @fold_fsub_nsz_x_n0_defaultenv(float %a) #0 { 113; CHECK-LABEL: @fold_fsub_nsz_x_n0_defaultenv( 114; CHECK-NEXT: ret float [[A:%.*]] 115; 116 %sub = call nsz float @llvm.experimental.constrained.fsub.f32(float %a, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") 117 ret float %sub 118} 119 120; Missing nnan: must not fire. 121define float @fold_fsub_nsz_x_n0_ebmaytrap(float %a) #0 { 122; CHECK-LABEL: @fold_fsub_nsz_x_n0_ebmaytrap( 123; CHECK-NEXT: [[SUB:%.*]] = call nsz float @llvm.experimental.constrained.fsub.f32(float [[A:%.*]], float -0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.maytrap") 124; CHECK-NEXT: ret float [[SUB]] 125; 126 %sub = call nsz float @llvm.experimental.constrained.fsub.f32(float %a, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.maytrap") 127 ret float %sub 128} 129 130define float @fold_fsub_nnan_nsz_x_n0_ebmaytrap(float %a) #0 { 131; CHECK-LABEL: @fold_fsub_nnan_nsz_x_n0_ebmaytrap( 132; CHECK-NEXT: ret float [[A:%.*]] 133; 134 %sub = call nnan nsz float @llvm.experimental.constrained.fsub.f32(float %a, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.maytrap") 135 ret float %sub 136} 137 138; Missing nnan: must not fire. 139define float @fold_fsub_nsz_x_n0_ebstrict(float %a) #0 { 140; CHECK-LABEL: @fold_fsub_nsz_x_n0_ebstrict( 141; CHECK-NEXT: [[SUB:%.*]] = call nsz float @llvm.experimental.constrained.fsub.f32(float [[A:%.*]], float -0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.strict") 142; CHECK-NEXT: ret float [[SUB]] 143; 144 %sub = call nsz float @llvm.experimental.constrained.fsub.f32(float %a, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.strict") 145 ret float %sub 146} 147 148; The instruction is expected to remain, but the result isn't used. 149define float @fold_fsub_nsz_nnan_x_n0_ebstrict(float %a) #0 { 150; CHECK-LABEL: @fold_fsub_nsz_nnan_x_n0_ebstrict( 151; CHECK-NEXT: [[SUB:%.*]] = call nnan nsz float @llvm.experimental.constrained.fsub.f32(float [[A:%.*]], float -0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.strict") 152; CHECK-NEXT: ret float [[A]] 153; 154 %sub = call nsz nnan float @llvm.experimental.constrained.fsub.f32(float %a, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.strict") 155 ret float %sub 156} 157 158; 159; fsub X, -0 ==> X, when we know X is not -0 160; (No "nsz" flags) 161; 162 163define float @fold_fsub_fabs_x_n0_defaultenv(float %a) #0 { 164; CHECK-LABEL: @fold_fsub_fabs_x_n0_defaultenv( 165; CHECK-NEXT: [[ABSA:%.*]] = call float @llvm.fabs.f32(float [[A:%.*]]) #[[ATTR0:[0-9]+]] 166; CHECK-NEXT: ret float [[ABSA]] 167; 168 %absa = call float @llvm.fabs.f32(float %a) #0 169 %sub = call float @llvm.experimental.constrained.fsub.f32(float %absa, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") 170 ret float %sub 171} 172 173; Missing nnan: must not fire. 174define float @fold_fsub_fabs_x_n0_ebmaytrap(float %a) #0 { 175; CHECK-LABEL: @fold_fsub_fabs_x_n0_ebmaytrap( 176; CHECK-NEXT: [[ABSA:%.*]] = call float @llvm.fabs.f32(float [[A:%.*]]) #[[ATTR0]] 177; CHECK-NEXT: [[SUB:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[ABSA]], float -0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.maytrap") 178; CHECK-NEXT: ret float [[SUB]] 179; 180 %absa = call float @llvm.fabs.f32(float %a) #0 181 %sub = call float @llvm.experimental.constrained.fsub.f32(float %absa, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.maytrap") 182 ret float %sub 183} 184 185define float @fold_fsub_fabs_nnan_x_n0_ebmaytrap(float %a) #0 { 186; CHECK-LABEL: @fold_fsub_fabs_nnan_x_n0_ebmaytrap( 187; CHECK-NEXT: [[ABSA:%.*]] = call float @llvm.fabs.f32(float [[A:%.*]]) #[[ATTR0]] 188; CHECK-NEXT: ret float [[ABSA]] 189; 190 %absa = call float @llvm.fabs.f32(float %a) #0 191 %sub = call nnan float @llvm.experimental.constrained.fsub.f32(float %absa, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.maytrap") 192 ret float %sub 193} 194 195; Missing nnan: must not fire. 196define float @fold_fsub_fabs_x_n0_ebstrict(float %a) #0 { 197; CHECK-LABEL: @fold_fsub_fabs_x_n0_ebstrict( 198; CHECK-NEXT: [[ABSA:%.*]] = call float @llvm.fabs.f32(float [[A:%.*]]) #[[ATTR0]] 199; CHECK-NEXT: [[SUB:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[ABSA]], float -0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.strict") 200; CHECK-NEXT: ret float [[SUB]] 201; 202 %absa = call float @llvm.fabs.f32(float %a) #0 203 %sub = call float @llvm.experimental.constrained.fsub.f32(float %absa, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.strict") 204 ret float %sub 205} 206 207; The instruction is expected to remain, but the result isn't used. 208define float @fold_fsub_fabs_nnan_x_n0_ebstrict(float %a) #0 { 209; CHECK-LABEL: @fold_fsub_fabs_nnan_x_n0_ebstrict( 210; CHECK-NEXT: [[ABSA:%.*]] = call float @llvm.fabs.f32(float [[A:%.*]]) #[[ATTR0]] 211; CHECK-NEXT: [[SUB:%.*]] = call nnan float @llvm.experimental.constrained.fsub.f32(float [[ABSA]], float -0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.strict") 212; CHECK-NEXT: ret float [[ABSA]] 213; 214 %absa = call float @llvm.fabs.f32(float %a) #0 215 %sub = call nnan float @llvm.experimental.constrained.fsub.f32(float %absa, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.strict") 216 ret float %sub 217} 218 219define float @fold_fsub_sitofp_x_n0_defaultenv(i32 %a) #0 { 220; CHECK-LABEL: @fold_fsub_sitofp_x_n0_defaultenv( 221; CHECK-NEXT: [[FPA:%.*]] = call float @llvm.experimental.constrained.sitofp.f32.i32(i32 [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") 222; CHECK-NEXT: ret float [[FPA]] 223; 224 %fpa = call float @llvm.experimental.constrained.sitofp.f32.i32(i32 %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") 225 %sub = call float @llvm.experimental.constrained.fsub.f32(float %fpa, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") 226 ret float %sub 227} 228 229; 230; fsub -0.0, (fneg X) ==> X 231; 232 233define float @fsub_fneg_n0_fnX_defaultenv(float %a) #0 { 234; CHECK-LABEL: @fsub_fneg_n0_fnX_defaultenv( 235; CHECK-NEXT: ret float [[A:%.*]] 236; 237 %nega = fneg float %a 238 %ret = call float @llvm.experimental.constrained.fsub.f32(float -0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.ignore") 239 ret float %ret 240} 241 242; Missing nnan: must not fire. 243define float @fsub_fneg_n0_fnX_ebmaytrap(float %a) #0 { 244; CHECK-LABEL: @fsub_fneg_n0_fnX_ebmaytrap( 245; CHECK-NEXT: [[NEGA:%.*]] = fneg float [[A:%.*]] 246; CHECK-NEXT: [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[NEGA]], metadata !"round.tonearest", metadata !"fpexcept.maytrap") 247; CHECK-NEXT: ret float [[RET]] 248; 249 %nega = fneg float %a 250 %ret = call float @llvm.experimental.constrained.fsub.f32(float -0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.maytrap") 251 ret float %ret 252} 253 254define float @fsub_fneg_nnan_n0_fnX_ebmaytrap(float %a) #0 { 255; CHECK-LABEL: @fsub_fneg_nnan_n0_fnX_ebmaytrap( 256; CHECK-NEXT: ret float [[A:%.*]] 257; 258 %nega = fneg float %a 259 %ret = call nnan float @llvm.experimental.constrained.fsub.f32(float -0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.maytrap") 260 ret float %ret 261} 262 263; Missing nnan: must not fire. 264define float @fsub_fneg_n0_fnX_ebstrict(float %a) #0 { 265; CHECK-LABEL: @fsub_fneg_n0_fnX_ebstrict( 266; CHECK-NEXT: [[NEGA:%.*]] = fneg float [[A:%.*]] 267; CHECK-NEXT: [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[NEGA]], metadata !"round.tonearest", metadata !"fpexcept.strict") 268; CHECK-NEXT: ret float [[RET]] 269; 270 %nega = fneg float %a 271 %ret = call float @llvm.experimental.constrained.fsub.f32(float -0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.strict") 272 ret float %ret 273} 274 275; The instruction is expected to remain, but the result isn't used. 276define float @fsub_fneg_nnan_n0_fnX_ebstrict(float %a) #0 { 277; CHECK-LABEL: @fsub_fneg_nnan_n0_fnX_ebstrict( 278; CHECK-NEXT: [[NEGA:%.*]] = fneg float [[A:%.*]] 279; CHECK-NEXT: [[RET:%.*]] = call nnan float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[NEGA]], metadata !"round.tonearest", metadata !"fpexcept.strict") 280; CHECK-NEXT: ret float [[A]] 281; 282 %nega = fneg float %a 283 %ret = call nnan float @llvm.experimental.constrained.fsub.f32(float -0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.strict") 284 ret float %ret 285} 286 287; 288; fsub -0.0, (fsub -0.0, X) ==> X 289; 290 291; TODO: This won't fire without m_FNeg() knowing the constrained intrinsics. 292define float @fsub_fsub_n0_fnX_defaultenv(float %a) #0 { 293; CHECK-LABEL: @fsub_fsub_n0_fnX_defaultenv( 294; CHECK-NEXT: [[NEGA:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") 295; CHECK-NEXT: [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[NEGA]], metadata !"round.tonearest", metadata !"fpexcept.ignore") 296; CHECK-NEXT: ret float [[RET]] 297; 298 %nega = call float @llvm.experimental.constrained.fsub.f32(float -0.0, float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") 299 %ret = call float @llvm.experimental.constrained.fsub.f32(float -0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.ignore") 300 ret float %ret 301} 302 303; Missing nnan: must not fire. 304define float @fsub_fsub_n0_fnX_ebmaytrap(float %a) #0 { 305; CHECK-LABEL: @fsub_fsub_n0_fnX_ebmaytrap( 306; CHECK-NEXT: [[NEGA:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.maytrap") 307; CHECK-NEXT: [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[NEGA]], metadata !"round.tonearest", metadata !"fpexcept.maytrap") 308; CHECK-NEXT: ret float [[RET]] 309; 310 %nega = call float @llvm.experimental.constrained.fsub.f32(float -0.0, float %a, metadata !"round.tonearest", metadata !"fpexcept.maytrap") 311 %ret = call float @llvm.experimental.constrained.fsub.f32(float -0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.maytrap") 312 ret float %ret 313} 314 315; TODO: This won't fire without m_FNeg() knowing the constrained intrinsics. 316define float @fsub_fsub_nnan_n0_fnX_ebmaytrap(float %a) #0 { 317; CHECK-LABEL: @fsub_fsub_nnan_n0_fnX_ebmaytrap( 318; CHECK-NEXT: [[NEGA:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.maytrap") 319; CHECK-NEXT: [[RET:%.*]] = call nnan float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[NEGA]], metadata !"round.tonearest", metadata !"fpexcept.maytrap") 320; CHECK-NEXT: ret float [[RET]] 321; 322 %nega = call float @llvm.experimental.constrained.fsub.f32(float -0.0, float %a, metadata !"round.tonearest", metadata !"fpexcept.maytrap") 323 %ret = call nnan float @llvm.experimental.constrained.fsub.f32(float -0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.maytrap") 324 ret float %ret 325} 326 327; Missing nnan: must not fire. 328define float @fsub_fsub_n0_fnX_ebstrict(float %a) #0 { 329; CHECK-LABEL: @fsub_fsub_n0_fnX_ebstrict( 330; CHECK-NEXT: [[NEGA:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.strict") 331; CHECK-NEXT: [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[NEGA]], metadata !"round.tonearest", metadata !"fpexcept.strict") 332; CHECK-NEXT: ret float [[RET]] 333; 334 %nega = call float @llvm.experimental.constrained.fsub.f32(float -0.0, float %a, metadata !"round.tonearest", metadata !"fpexcept.strict") 335 %ret = call float @llvm.experimental.constrained.fsub.f32(float -0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.strict") 336 ret float %ret 337} 338 339; TODO: This won't fire without m_FNeg() knowing the constrained intrinsics. 340define float @fsub_fsub_nnan_n0_fnX_ebstrict(float %a) #0 { 341; CHECK-LABEL: @fsub_fsub_nnan_n0_fnX_ebstrict( 342; CHECK-NEXT: [[NEGA:%.*]] = call nnan float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.strict") 343; CHECK-NEXT: [[RET:%.*]] = call nnan float @llvm.experimental.constrained.fsub.f32(float -0.000000e+00, float [[NEGA]], metadata !"round.tonearest", metadata !"fpexcept.strict") 344; CHECK-NEXT: ret float [[RET]] 345; 346 %nega = call nnan float @llvm.experimental.constrained.fsub.f32(float -0.0, float %a, metadata !"round.tonearest", metadata !"fpexcept.strict") 347 %ret = call nnan float @llvm.experimental.constrained.fsub.f32(float -0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.strict") 348 ret float %ret 349} 350 351; 352; fsub 0.0, (fneg X) ==> X if signed zeros are ignored. 353; 354 355define float @fsub_fneg_nsz_p0_fnX_defaultenv(float %a) #0 { 356; CHECK-LABEL: @fsub_fneg_nsz_p0_fnX_defaultenv( 357; CHECK-NEXT: ret float [[A:%.*]] 358; 359 %nega = fneg float %a 360 %ret = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.ignore") 361 ret float %ret 362} 363 364; Missing nnan: must not fire. 365define float @fsub_fneg_nsz_p0_fnX_ebmaytrap(float %a) #0 { 366; CHECK-LABEL: @fsub_fneg_nsz_p0_fnX_ebmaytrap( 367; CHECK-NEXT: [[NEGA:%.*]] = fneg float [[A:%.*]] 368; CHECK-NEXT: [[RET:%.*]] = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[NEGA]], metadata !"round.tonearest", metadata !"fpexcept.maytrap") 369; CHECK-NEXT: ret float [[RET]] 370; 371 %nega = fneg float %a 372 %ret = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.maytrap") 373 ret float %ret 374} 375 376define float @fsub_fneg_nsz_nnan_p0_fnX_ebmaytrap(float %a) #0 { 377; CHECK-LABEL: @fsub_fneg_nsz_nnan_p0_fnX_ebmaytrap( 378; CHECK-NEXT: ret float [[A:%.*]] 379; 380 %nega = fneg float %a 381 %ret = call nnan nsz float @llvm.experimental.constrained.fsub.f32(float 0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.maytrap") 382 ret float %ret 383} 384 385; Missing nnan: must not fire. 386define float @fsub_fneg_nsz_p0_fnX_ebstrict(float %a) #0 { 387; CHECK-LABEL: @fsub_fneg_nsz_p0_fnX_ebstrict( 388; CHECK-NEXT: [[NEGA:%.*]] = fneg float [[A:%.*]] 389; CHECK-NEXT: [[RET:%.*]] = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[NEGA]], metadata !"round.tonearest", metadata !"fpexcept.strict") 390; CHECK-NEXT: ret float [[RET]] 391; 392 %nega = fneg float %a 393 %ret = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.strict") 394 ret float %ret 395} 396 397; The instruction is expected to remain, but the result isn't used. 398define float @fsub_fneg_nnan_nsz_p0_fnX_ebstrict(float %a) #0 { 399; CHECK-LABEL: @fsub_fneg_nnan_nsz_p0_fnX_ebstrict( 400; CHECK-NEXT: [[NEGA:%.*]] = fneg float [[A:%.*]] 401; CHECK-NEXT: [[RET:%.*]] = call nnan nsz float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[NEGA]], metadata !"round.tonearest", metadata !"fpexcept.strict") 402; CHECK-NEXT: ret float [[A]] 403; 404 %nega = fneg float %a 405 %ret = call nnan nsz float @llvm.experimental.constrained.fsub.f32(float 0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.strict") 406 ret float %ret 407} 408 409; 410; fsub 0.0, (fsub 0.0, X) ==> X if signed zeros are ignored. 411; 412 413; TODO: Need constrained intrinsic support in m_FNeg() and m_FSub to fire. 414define float @fsub_fsub_p0_nsz_fnX_defaultenv(float %a) #0 { 415; CHECK-LABEL: @fsub_fsub_p0_nsz_fnX_defaultenv( 416; CHECK-NEXT: [[NEGA:%.*]] = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") 417; CHECK-NEXT: [[RET:%.*]] = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[NEGA]], metadata !"round.tonearest", metadata !"fpexcept.ignore") 418; CHECK-NEXT: ret float [[RET]] 419; 420 %nega = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.0, float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") 421 %ret = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.ignore") 422 ret float %ret 423} 424 425; Missing nnan: must not fire. 426define float @fsub_fsub_nsz_p0_fnX_ebmaytrap(float %a) #0 { 427; CHECK-LABEL: @fsub_fsub_nsz_p0_fnX_ebmaytrap( 428; CHECK-NEXT: [[NEGA:%.*]] = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.maytrap") 429; CHECK-NEXT: [[RET:%.*]] = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[NEGA]], metadata !"round.tonearest", metadata !"fpexcept.maytrap") 430; CHECK-NEXT: ret float [[RET]] 431; 432 %nega = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.0, float %a, metadata !"round.tonearest", metadata !"fpexcept.maytrap") 433 %ret = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.maytrap") 434 ret float %ret 435} 436 437; TODO: Need constrained intrinsic support in m_FNeg() and m_FSub to fire. 438define float @fsub_fsub_nnan_nsz_p0_fnX_ebmaytrap(float %a) #0 { 439; CHECK-LABEL: @fsub_fsub_nnan_nsz_p0_fnX_ebmaytrap( 440; CHECK-NEXT: [[NEGA:%.*]] = call nnan nsz float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.maytrap") 441; CHECK-NEXT: [[RET:%.*]] = call nnan nsz float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[NEGA]], metadata !"round.tonearest", metadata !"fpexcept.maytrap") 442; CHECK-NEXT: ret float [[RET]] 443; 444 %nega = call nnan nsz float @llvm.experimental.constrained.fsub.f32(float 0.0, float %a, metadata !"round.tonearest", metadata !"fpexcept.maytrap") 445 %ret = call nnan nsz float @llvm.experimental.constrained.fsub.f32(float 0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.maytrap") 446 ret float %ret 447} 448 449; Missing nnan: must not fire. 450define float @fsub_fsub_nsz_p0_fnX_ebstrict(float %a) #0 { 451; CHECK-LABEL: @fsub_fsub_nsz_p0_fnX_ebstrict( 452; CHECK-NEXT: [[NEGA:%.*]] = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.strict") 453; CHECK-NEXT: [[RET:%.*]] = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[NEGA]], metadata !"round.tonearest", metadata !"fpexcept.strict") 454; CHECK-NEXT: ret float [[RET]] 455; 456 %nega = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.0, float %a, metadata !"round.tonearest", metadata !"fpexcept.strict") 457 %ret = call nsz float @llvm.experimental.constrained.fsub.f32(float 0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.strict") 458 ret float %ret 459} 460 461; TODO: Need constrained intrinsic support in m_FNeg() and m_FSub to fire. 462define float @fsub_fsub_nnan_nsz_p0_fnX_ebstrict(float %a) #0 { 463; CHECK-LABEL: @fsub_fsub_nnan_nsz_p0_fnX_ebstrict( 464; CHECK-NEXT: [[NEGA:%.*]] = call nnan nsz float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[A:%.*]], metadata !"round.tonearest", metadata !"fpexcept.strict") 465; CHECK-NEXT: [[RET:%.*]] = call nnan nsz float @llvm.experimental.constrained.fsub.f32(float 0.000000e+00, float [[NEGA]], metadata !"round.tonearest", metadata !"fpexcept.strict") 466; CHECK-NEXT: ret float [[RET]] 467; 468 %nega = call nnan nsz float @llvm.experimental.constrained.fsub.f32(float 0.0, float %a, metadata !"round.tonearest", metadata !"fpexcept.strict") 469 %ret = call nnan nsz float @llvm.experimental.constrained.fsub.f32(float 0.0, float %nega, metadata !"round.tonearest", metadata !"fpexcept.strict") 470 ret float %ret 471} 472 473; 474; fsub nnan x, x ==> 0.0 475; 476 477; Missing nnan: must not fire. 478define float @fsub_x_x_defaultenv(float %a) #0 { 479; CHECK-LABEL: @fsub_x_x_defaultenv( 480; CHECK-NEXT: [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[A:%.*]], float [[A]], metadata !"round.tonearest", metadata !"fpexcept.ignore") 481; CHECK-NEXT: ret float [[RET]] 482; 483 %ret = call float @llvm.experimental.constrained.fsub.f32(float %a, float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") 484 ret float %ret 485} 486 487define float @fsub_nnan_x_x_defaultenv(float %a) #0 { 488; CHECK-LABEL: @fsub_nnan_x_x_defaultenv( 489; CHECK-NEXT: ret float 0.000000e+00 490; 491 %ret = call nnan float @llvm.experimental.constrained.fsub.f32(float %a, float %a, metadata !"round.tonearest", metadata !"fpexcept.ignore") 492 ret float %ret 493} 494 495; Missing nnan: must not fire. 496define float @fsub_x_x_ebmaytrap(float %a) #0 { 497; CHECK-LABEL: @fsub_x_x_ebmaytrap( 498; CHECK-NEXT: [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[A:%.*]], float [[A]], metadata !"round.tonearest", metadata !"fpexcept.maytrap") 499; CHECK-NEXT: ret float [[RET]] 500; 501 %ret = call float @llvm.experimental.constrained.fsub.f32(float %a, float %a, metadata !"round.tonearest", metadata !"fpexcept.maytrap") 502 ret float %ret 503} 504 505; TODO: This will fold if we allow non-default floating point environments. 506define float @fsub_nnan_x_x_ebmaytrap(float %a) #0 { 507; CHECK-LABEL: @fsub_nnan_x_x_ebmaytrap( 508; CHECK-NEXT: [[RET:%.*]] = call nnan float @llvm.experimental.constrained.fsub.f32(float [[A:%.*]], float [[A]], metadata !"round.tonearest", metadata !"fpexcept.maytrap") 509; CHECK-NEXT: ret float [[RET]] 510; 511 %ret = call nnan float @llvm.experimental.constrained.fsub.f32(float %a, float %a, metadata !"round.tonearest", metadata !"fpexcept.maytrap") 512 ret float %ret 513} 514 515; Missing nnan: must not fire. 516define float @fsub_x_x_ebstrict(float %a) #0 { 517; CHECK-LABEL: @fsub_x_x_ebstrict( 518; CHECK-NEXT: [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[A:%.*]], float [[A]], metadata !"round.tonearest", metadata !"fpexcept.strict") 519; CHECK-NEXT: ret float [[RET]] 520; 521 %ret = call float @llvm.experimental.constrained.fsub.f32(float %a, float %a, metadata !"round.tonearest", metadata !"fpexcept.strict") 522 ret float %ret 523} 524 525; TODO: This will fold if we allow non-default floating point environments. 526; The instruction is expected to remain, but the result isn't used. 527define float @fsub_nnan_x_x_ebstrict(float %a) #0 { 528; CHECK-LABEL: @fsub_nnan_x_x_ebstrict( 529; CHECK-NEXT: [[RET:%.*]] = call nnan float @llvm.experimental.constrained.fsub.f32(float [[A:%.*]], float [[A]], metadata !"round.tonearest", metadata !"fpexcept.strict") 530; CHECK-NEXT: ret float [[RET]] 531; 532 %ret = call nnan float @llvm.experimental.constrained.fsub.f32(float %a, float %a, metadata !"round.tonearest", metadata !"fpexcept.strict") 533 ret float %ret 534} 535 536; 537; Y - (Y - X) --> X 538; 539 540; Missing nsz and reassoc: must not fire 541define float @fsub_fsub_y_x_x_defaultenv(float %x, float %y) #0 { 542; CHECK-LABEL: @fsub_fsub_y_x_x_defaultenv( 543; CHECK-NEXT: [[INNER:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[Y:%.*]], float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") 544; CHECK-NEXT: [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[Y]], float [[INNER]], metadata !"round.tonearest", metadata !"fpexcept.ignore") 545; CHECK-NEXT: ret float [[RET]] 546; 547 %inner = call float @llvm.experimental.constrained.fsub.f32(float %y, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") 548 %ret = call float @llvm.experimental.constrained.fsub.f32(float %y, float %inner, metadata !"round.tonearest", metadata !"fpexcept.ignore") 549 ret float %ret 550} 551 552; TODO: Need constrained intrinsic support in m_c_FAdd() and m_FSub to fire. 553define float @fsub_fsub_fmf_y_x_x_defaultenv(float %x, float %y) #0 { 554; CHECK-LABEL: @fsub_fsub_fmf_y_x_x_defaultenv( 555; CHECK-NEXT: [[INNER:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[Y:%.*]], float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") 556; CHECK-NEXT: [[RET:%.*]] = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float [[Y]], float [[INNER]], metadata !"round.tonearest", metadata !"fpexcept.ignore") 557; CHECK-NEXT: ret float [[RET]] 558; 559 %inner = call float @llvm.experimental.constrained.fsub.f32(float %y, float %x, metadata !"round.tonearest", metadata !"fpexcept.ignore") 560 %ret = call nsz reassoc float @llvm.experimental.constrained.fsub.f32(float %y, float %inner, metadata !"round.tonearest", metadata !"fpexcept.ignore") 561 ret float %ret 562} 563 564; TODO: Consider how alternate rounding modes can break these transforms. 565 566; The "fpexcept.maytrap" instruction must _not_ be folded into the 567; "fpexcept.ignore" instruction. This must not fire. 568define float @fsub_fsub_fmf_y_x_x_ebmaytrap_defaultenv(float %x, float %y) #0 { 569; CHECK-LABEL: @fsub_fsub_fmf_y_x_x_ebmaytrap_defaultenv( 570; CHECK-NEXT: [[INNER:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[Y:%.*]], float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.maytrap") 571; CHECK-NEXT: [[RET:%.*]] = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float [[Y]], float [[INNER]], metadata !"round.tonearest", metadata !"fpexcept.ignore") 572; CHECK-NEXT: ret float [[RET]] 573; 574 %inner = call float @llvm.experimental.constrained.fsub.f32(float %y, float %x, metadata !"round.tonearest", metadata !"fpexcept.maytrap") 575 %ret = call nsz reassoc float @llvm.experimental.constrained.fsub.f32(float %y, float %inner, metadata !"round.tonearest", metadata !"fpexcept.ignore") 576 ret float %ret 577} 578 579; Missing nsz and reassoc: must not fire 580define float @fsub_fsub_y_x_x_ebmaytrap(float %x, float %y) #0 { 581; CHECK-LABEL: @fsub_fsub_y_x_x_ebmaytrap( 582; CHECK-NEXT: [[INNER:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[Y:%.*]], float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.maytrap") 583; CHECK-NEXT: [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[Y]], float [[INNER]], metadata !"round.tonearest", metadata !"fpexcept.maytrap") 584; CHECK-NEXT: ret float [[RET]] 585; 586 %inner = call float @llvm.experimental.constrained.fsub.f32(float %y, float %x, metadata !"round.tonearest", metadata !"fpexcept.maytrap") 587 %ret = call float @llvm.experimental.constrained.fsub.f32(float %y, float %inner, metadata !"round.tonearest", metadata !"fpexcept.maytrap") 588 ret float %ret 589} 590 591; TODO: Need constrained intrinsic support in m_c_FAdd() and m_FSub to fire. 592define float @fsub_fsub_fmf_y_x_x_ebmaytrap(float %x, float %y) #0 { 593; CHECK-LABEL: @fsub_fsub_fmf_y_x_x_ebmaytrap( 594; CHECK-NEXT: [[INNER:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[Y:%.*]], float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.maytrap") 595; CHECK-NEXT: [[RET:%.*]] = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float [[Y]], float [[INNER]], metadata !"round.tonearest", metadata !"fpexcept.maytrap") 596; CHECK-NEXT: ret float [[RET]] 597; 598 %inner = call float @llvm.experimental.constrained.fsub.f32(float %y, float %x, metadata !"round.tonearest", metadata !"fpexcept.maytrap") 599 %ret = call nsz reassoc float @llvm.experimental.constrained.fsub.f32(float %y, float %inner, metadata !"round.tonearest", metadata !"fpexcept.maytrap") 600 ret float %ret 601} 602 603; Missing nsz and reassoc: must not fire 604define float @fsub_fsub_y_x_x_ebstrict(float %x, float %y) #0 { 605; CHECK-LABEL: @fsub_fsub_y_x_x_ebstrict( 606; CHECK-NEXT: [[INNER:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[Y:%.*]], float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.strict") 607; CHECK-NEXT: [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[Y]], float [[INNER]], metadata !"round.tonearest", metadata !"fpexcept.strict") 608; CHECK-NEXT: ret float [[RET]] 609; 610 %inner = call float @llvm.experimental.constrained.fsub.f32(float %y, float %x, metadata !"round.tonearest", metadata !"fpexcept.strict") 611 %ret = call float @llvm.experimental.constrained.fsub.f32(float %y, float %inner, metadata !"round.tonearest", metadata !"fpexcept.strict") 612 ret float %ret 613} 614 615; TODO: Need constrained intrinsic support in m_c_FAdd() and m_FSub to fire. 616define float @fsub_fsub_fmf_y_x_x_ebstrict(float %x, float %y) #0 { 617; CHECK-LABEL: @fsub_fsub_fmf_y_x_x_ebstrict( 618; CHECK-NEXT: [[INNER:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[Y:%.*]], float [[X:%.*]], metadata !"round.tonearest", metadata !"fpexcept.strict") 619; CHECK-NEXT: [[RET:%.*]] = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float [[Y]], float [[INNER]], metadata !"round.tonearest", metadata !"fpexcept.strict") 620; CHECK-NEXT: ret float [[RET]] 621; 622 %inner = call float @llvm.experimental.constrained.fsub.f32(float %y, float %x, metadata !"round.tonearest", metadata !"fpexcept.strict") 623 %ret = call nsz reassoc float @llvm.experimental.constrained.fsub.f32(float %y, float %inner, metadata !"round.tonearest", metadata !"fpexcept.strict") 624 ret float %ret 625} 626 627; 628; (X + Y) - Y --> X 629; TODO: Missing IR matcher support means these won't fire. 630; 631 632; Missing nsz and reassoc: must not fire 633define float @fadd_fsub_x_y_y_defaultenv(float %x, float %y) #0 { 634; CHECK-LABEL: @fadd_fsub_x_y_y_defaultenv( 635; CHECK-NEXT: [[INNER:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[X:%.*]], float [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") 636; CHECK-NEXT: [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[INNER]], float [[Y]], metadata !"round.tonearest", metadata !"fpexcept.ignore") 637; CHECK-NEXT: ret float [[RET]] 638; 639 %inner = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") 640 %ret = call float @llvm.experimental.constrained.fsub.f32(float %inner, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") 641 ret float %ret 642} 643 644; TODO: Need constrained intrinsic support in m_c_FAdd() and m_FSub to fire. 645define float @fadd_fsub_fmf_x_y_y_defaultenv(float %x, float %y) #0 { 646; CHECK-LABEL: @fadd_fsub_fmf_x_y_y_defaultenv( 647; CHECK-NEXT: [[INNER:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[X:%.*]], float [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.ignore") 648; CHECK-NEXT: [[RET:%.*]] = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float [[INNER]], float [[Y]], metadata !"round.tonearest", metadata !"fpexcept.ignore") 649; CHECK-NEXT: ret float [[RET]] 650; 651 %inner = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") 652 %ret = call nsz reassoc float @llvm.experimental.constrained.fsub.f32(float %inner, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") 653 ret float %ret 654} 655 656; The "fpexcept.maytrap" instruction must _not_ be folded into the 657; "fpexcept.ignore" instruction. This must not fire. 658define float @fadd_fsub_fmf_x_y_y_ebmaytrap_defaultenv(float %x, float %y) #0 { 659; CHECK-LABEL: @fadd_fsub_fmf_x_y_y_ebmaytrap_defaultenv( 660; CHECK-NEXT: [[INNER:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[X:%.*]], float [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.maytrap") 661; CHECK-NEXT: [[RET:%.*]] = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float [[INNER]], float [[Y]], metadata !"round.tonearest", metadata !"fpexcept.ignore") 662; CHECK-NEXT: ret float [[RET]] 663; 664 %inner = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.maytrap") 665 %ret = call nsz reassoc float @llvm.experimental.constrained.fsub.f32(float %inner, float %y, metadata !"round.tonearest", metadata !"fpexcept.ignore") 666 ret float %ret 667} 668 669; Missing nsz and reassoc: must not fire 670define float @fadd_fsub_x_y_y_ebmaytrap(float %x, float %y) #0 { 671; CHECK-LABEL: @fadd_fsub_x_y_y_ebmaytrap( 672; CHECK-NEXT: [[INNER:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[X:%.*]], float [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.maytrap") 673; CHECK-NEXT: [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[INNER]], float [[Y]], metadata !"round.tonearest", metadata !"fpexcept.maytrap") 674; CHECK-NEXT: ret float [[RET]] 675; 676 %inner = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.maytrap") 677 %ret = call float @llvm.experimental.constrained.fsub.f32(float %inner, float %y, metadata !"round.tonearest", metadata !"fpexcept.maytrap") 678 ret float %ret 679} 680 681; TODO: Need constrained intrinsic support in m_c_FAdd() and m_FSub to fire. 682define float @fadd_fsub_fmf_x_y_y_ebmaytrap(float %x, float %y) #0 { 683; CHECK-LABEL: @fadd_fsub_fmf_x_y_y_ebmaytrap( 684; CHECK-NEXT: [[INNER:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[X:%.*]], float [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.maytrap") 685; CHECK-NEXT: [[RET:%.*]] = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float [[INNER]], float [[Y]], metadata !"round.tonearest", metadata !"fpexcept.maytrap") 686; CHECK-NEXT: ret float [[RET]] 687; 688 %inner = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.maytrap") 689 %ret = call nsz reassoc float @llvm.experimental.constrained.fsub.f32(float %inner, float %y, metadata !"round.tonearest", metadata !"fpexcept.maytrap") 690 ret float %ret 691} 692 693; Missing nsz and reassoc: must not fire 694define float @fadd_fsub_x_y_y_ebstrict(float %x, float %y) #0 { 695; CHECK-LABEL: @fadd_fsub_x_y_y_ebstrict( 696; CHECK-NEXT: [[INNER:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[X:%.*]], float [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.strict") 697; CHECK-NEXT: [[RET:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[INNER]], float [[Y]], metadata !"round.tonearest", metadata !"fpexcept.strict") 698; CHECK-NEXT: ret float [[RET]] 699; 700 %inner = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.strict") 701 %ret = call float @llvm.experimental.constrained.fsub.f32(float %inner, float %y, metadata !"round.tonearest", metadata !"fpexcept.strict") 702 ret float %ret 703} 704 705; TODO: Need constrained intrinsic support in m_c_FAdd() and m_FSub to fire. 706define float @fadd_fsub_fmf_x_y_y_ebstrict(float %x, float %y) #0 { 707; CHECK-LABEL: @fadd_fsub_fmf_x_y_y_ebstrict( 708; CHECK-NEXT: [[INNER:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[X:%.*]], float [[Y:%.*]], metadata !"round.tonearest", metadata !"fpexcept.strict") 709; CHECK-NEXT: [[RET:%.*]] = call reassoc nsz float @llvm.experimental.constrained.fsub.f32(float [[INNER]], float [[Y]], metadata !"round.tonearest", metadata !"fpexcept.strict") 710; CHECK-NEXT: ret float [[RET]] 711; 712 %inner = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.strict") 713 %ret = call nsz reassoc float @llvm.experimental.constrained.fsub.f32(float %inner, float %y, metadata !"round.tonearest", metadata !"fpexcept.strict") 714 ret float %ret 715} 716 717declare float @llvm.fabs.f32(float) 718declare <2 x float> @llvm.fabs.v2f32(<2 x float>) 719 720declare float @llvm.experimental.constrained.fadd.f32(float, float, metadata, metadata) 721declare float @llvm.experimental.constrained.fsub.f32(float, float, metadata, metadata) 722 723declare float @llvm.experimental.constrained.sitofp.f32.i32(i32, metadata, metadata) 724 725attributes #0 = { strictfp } 726