1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -passes=instcombine < %s | FileCheck %s 3 4declare float @llvm.fma.f32(float, float, float) 5declare <2 x float> @llvm.fma.v2f32(<2 x float>, <2 x float>, <2 x float>) 6declare <3 x float> @llvm.fma.v3f32(<3 x float>, <3 x float>, <3 x float>) 7declare <8 x half> @llvm.fma.v8f16(<8 x half>, <8 x half>, <8 x half>) 8declare <2 x double> @llvm.fma.v2f64(<2 x double>, <2 x double>, <2 x double>) 9 10declare float @llvm.fmuladd.f32(float, float, float) 11declare <2 x double> @llvm.fmuladd.v2f64(<2 x double>, <2 x double>, <2 x double>) 12declare float @llvm.fabs.f32(float) 13declare <2 x double> @llvm.sqrt.v2f64(<2 x double>) 14declare void @use_vec(<2 x float>) 15declare void @use_vec3(<3 x float>) 16 17@external = external global i32 18 19define float @fma_fneg_x_fneg_y(float %x, float %y, float %z) { 20; CHECK-LABEL: @fma_fneg_x_fneg_y( 21; CHECK-NEXT: [[FMA:%.*]] = call float @llvm.fma.f32(float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) 22; CHECK-NEXT: ret float [[FMA]] 23; 24 %x.fneg = fsub float -0.0, %x 25 %y.fneg = fsub float -0.0, %y 26 %fma = call float @llvm.fma.f32(float %x.fneg, float %y.fneg, float %z) 27 ret float %fma 28} 29 30define float @fma_unary_fneg_x_unary_fneg_y(float %x, float %y, float %z) { 31; CHECK-LABEL: @fma_unary_fneg_x_unary_fneg_y( 32; CHECK-NEXT: [[FMA:%.*]] = call float @llvm.fma.f32(float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) 33; CHECK-NEXT: ret float [[FMA]] 34; 35 %x.fneg = fneg float %x 36 %y.fneg = fneg float %y 37 %fma = call float @llvm.fma.f32(float %x.fneg, float %y.fneg, float %z) 38 ret float %fma 39} 40 41define <2 x float> @fma_fneg_x_fneg_y_vec(<2 x float> %x, <2 x float> %y, <2 x float> %z) { 42; CHECK-LABEL: @fma_fneg_x_fneg_y_vec( 43; CHECK-NEXT: [[FMA:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> [[X:%.*]], <2 x float> [[Y:%.*]], <2 x float> [[Z:%.*]]) 44; CHECK-NEXT: ret <2 x float> [[FMA]] 45; 46 %xn = fsub <2 x float> <float -0.0, float -0.0>, %x 47 %yn = fsub <2 x float> <float -0.0, float -0.0>, %y 48 %fma = call <2 x float> @llvm.fma.v2f32(<2 x float> %xn, <2 x float> %yn, <2 x float> %z) 49 ret <2 x float> %fma 50} 51 52define <2 x float> @fma_unary_fneg_x_unary_fneg_y_vec(<2 x float> %x, <2 x float> %y, <2 x float> %z) { 53; CHECK-LABEL: @fma_unary_fneg_x_unary_fneg_y_vec( 54; CHECK-NEXT: [[FMA:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> [[X:%.*]], <2 x float> [[Y:%.*]], <2 x float> [[Z:%.*]]) 55; CHECK-NEXT: ret <2 x float> [[FMA]] 56; 57 %xn = fneg <2 x float> %x 58 %yn = fneg <2 x float> %y 59 %fma = call <2 x float> @llvm.fma.v2f32(<2 x float> %xn, <2 x float> %yn, <2 x float> %z) 60 ret <2 x float> %fma 61} 62 63define <2 x float> @fma_fneg_x_fneg_y_vec_poison(<2 x float> %x, <2 x float> %y, <2 x float> %z) { 64; CHECK-LABEL: @fma_fneg_x_fneg_y_vec_poison( 65; CHECK-NEXT: [[FMA:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> [[X:%.*]], <2 x float> [[Y:%.*]], <2 x float> [[Z:%.*]]) 66; CHECK-NEXT: ret <2 x float> [[FMA]] 67; 68 %xn = fsub <2 x float> <float -0.0, float poison>, %x 69 %yn = fsub <2 x float> <float poison, float -0.0>, %y 70 %fma = call <2 x float> @llvm.fma.v2f32(<2 x float> %xn, <2 x float> %yn, <2 x float> %z) 71 ret <2 x float> %fma 72} 73 74define float @fma_fneg_x_fneg_y_fast(float %x, float %y, float %z) { 75; CHECK-LABEL: @fma_fneg_x_fneg_y_fast( 76; CHECK-NEXT: [[FMA:%.*]] = call fast float @llvm.fma.f32(float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) 77; CHECK-NEXT: ret float [[FMA]] 78; 79 %x.fneg = fsub float -0.0, %x 80 %y.fneg = fsub float -0.0, %y 81 %fma = call fast float @llvm.fma.f32(float %x.fneg, float %y.fneg, float %z) 82 ret float %fma 83} 84 85define float @fma_unary_fneg_x_unary_fneg_y_fast(float %x, float %y, float %z) { 86; CHECK-LABEL: @fma_unary_fneg_x_unary_fneg_y_fast( 87; CHECK-NEXT: [[FMA:%.*]] = call fast float @llvm.fma.f32(float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) 88; CHECK-NEXT: ret float [[FMA]] 89; 90 %x.fneg = fneg float %x 91 %y.fneg = fneg float %y 92 %fma = call fast float @llvm.fma.f32(float %x.fneg, float %y.fneg, float %z) 93 ret float %fma 94} 95 96define float @fma_fneg_const_fneg_y(float %y, float %z) { 97; CHECK-LABEL: @fma_fneg_const_fneg_y( 98; CHECK-NEXT: [[FMA:%.*]] = call float @llvm.fma.f32(float [[Y:%.*]], float bitcast (i32 ptrtoint (ptr @external to i32) to float), float [[Z:%.*]]) 99; CHECK-NEXT: ret float [[FMA]] 100; 101 %y.fneg = fsub float -0.0, %y 102 %fsub = fsub float -0.0, bitcast (i32 ptrtoint (ptr @external to i32) to float) 103 %fma = call float @llvm.fma.f32(float %fsub, float %y.fneg, float %z) 104 ret float %fma 105} 106 107define float @fma_unary_fneg_const_unary_fneg_y(float %y, float %z) { 108; CHECK-LABEL: @fma_unary_fneg_const_unary_fneg_y( 109; CHECK-NEXT: [[FMA:%.*]] = call float @llvm.fma.f32(float [[Y:%.*]], float bitcast (i32 ptrtoint (ptr @external to i32) to float), float [[Z:%.*]]) 110; CHECK-NEXT: ret float [[FMA]] 111; 112 %y.fneg = fneg float %y 113 %external.fneg = fneg float bitcast (i32 ptrtoint (ptr @external to i32) to float) 114 %fma = call float @llvm.fma.f32(float %external.fneg, float %y.fneg, float %z) 115 ret float %fma 116} 117 118define float @fma_fneg_x_fneg_const(float %x, float %z) { 119; CHECK-LABEL: @fma_fneg_x_fneg_const( 120; CHECK-NEXT: [[FMA:%.*]] = call float @llvm.fma.f32(float [[X:%.*]], float bitcast (i32 ptrtoint (ptr @external to i32) to float), float [[Z:%.*]]) 121; CHECK-NEXT: ret float [[FMA]] 122; 123 %x.fneg = fsub float -0.0, %x 124 %fsub = fsub float -0.0, bitcast (i32 ptrtoint (ptr @external to i32) to float) 125 %fma = call float @llvm.fma.f32(float %x.fneg, float %fsub, float %z) 126 ret float %fma 127} 128 129define float @fma_unary_fneg_x_unary_fneg_const(float %x, float %z) { 130; CHECK-LABEL: @fma_unary_fneg_x_unary_fneg_const( 131; CHECK-NEXT: [[FMA:%.*]] = call float @llvm.fma.f32(float [[X:%.*]], float bitcast (i32 ptrtoint (ptr @external to i32) to float), float [[Z:%.*]]) 132; CHECK-NEXT: ret float [[FMA]] 133; 134 %x.fneg = fneg float %x 135 %external.fneg = fneg float bitcast (i32 ptrtoint (ptr @external to i32) to float) 136 %fma = call float @llvm.fma.f32(float %x.fneg, float %external.fneg, float %z) 137 ret float %fma 138} 139 140define float @fma_fabs_x_fabs_y(float %x, float %y, float %z) { 141; CHECK-LABEL: @fma_fabs_x_fabs_y( 142; CHECK-NEXT: [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]]) 143; CHECK-NEXT: [[Y_FABS:%.*]] = call float @llvm.fabs.f32(float [[Y:%.*]]) 144; CHECK-NEXT: [[FMA:%.*]] = call float @llvm.fma.f32(float [[X_FABS]], float [[Y_FABS]], float [[Z:%.*]]) 145; CHECK-NEXT: ret float [[FMA]] 146; 147 %x.fabs = call float @llvm.fabs.f32(float %x) 148 %y.fabs = call float @llvm.fabs.f32(float %y) 149 %fma = call float @llvm.fma.f32(float %x.fabs, float %y.fabs, float %z) 150 ret float %fma 151} 152 153define float @fma_fabs_x_fabs_x(float %x, float %z) { 154; CHECK-LABEL: @fma_fabs_x_fabs_x( 155; CHECK-NEXT: [[FMA:%.*]] = call float @llvm.fma.f32(float [[X:%.*]], float [[X]], float [[Z:%.*]]) 156; CHECK-NEXT: ret float [[FMA]] 157; 158 %x.fabs = call float @llvm.fabs.f32(float %x) 159 %fma = call float @llvm.fma.f32(float %x.fabs, float %x.fabs, float %z) 160 ret float %fma 161} 162 163define float @fma_fabs_x_fabs_x_fast(float %x, float %z) { 164; CHECK-LABEL: @fma_fabs_x_fabs_x_fast( 165; CHECK-NEXT: [[FMA:%.*]] = call fast float @llvm.fma.f32(float [[X:%.*]], float [[X]], float [[Z:%.*]]) 166; CHECK-NEXT: ret float [[FMA]] 167; 168 %x.fabs = call float @llvm.fabs.f32(float %x) 169 %fma = call fast float @llvm.fma.f32(float %x.fabs, float %x.fabs, float %z) 170 ret float %fma 171} 172 173define float @fmuladd_fneg_x_fneg_y(float %x, float %y, float %z) { 174; CHECK-LABEL: @fmuladd_fneg_x_fneg_y( 175; CHECK-NEXT: [[FMULADD:%.*]] = call float @llvm.fmuladd.f32(float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) 176; CHECK-NEXT: ret float [[FMULADD]] 177; 178 %x.fneg = fsub float -0.0, %x 179 %y.fneg = fsub float -0.0, %y 180 %fmuladd = call float @llvm.fmuladd.f32(float %x.fneg, float %y.fneg, float %z) 181 ret float %fmuladd 182} 183 184define float @fmuladd_unary_fneg_x_unary_fneg_y(float %x, float %y, float %z) { 185; CHECK-LABEL: @fmuladd_unary_fneg_x_unary_fneg_y( 186; CHECK-NEXT: [[FMULADD:%.*]] = call float @llvm.fmuladd.f32(float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) 187; CHECK-NEXT: ret float [[FMULADD]] 188; 189 %x.fneg = fneg float %x 190 %y.fneg = fneg float %y 191 %fmuladd = call float @llvm.fmuladd.f32(float %x.fneg, float %y.fneg, float %z) 192 ret float %fmuladd 193} 194 195define float @fmuladd_fneg_x_fneg_y_fast(float %x, float %y, float %z) { 196; CHECK-LABEL: @fmuladd_fneg_x_fneg_y_fast( 197; CHECK-NEXT: [[FMULADD:%.*]] = call fast float @llvm.fmuladd.f32(float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) 198; CHECK-NEXT: ret float [[FMULADD]] 199; 200 %x.fneg = fsub float -0.0, %x 201 %y.fneg = fsub float -0.0, %y 202 %fmuladd = call fast float @llvm.fmuladd.f32(float %x.fneg, float %y.fneg, float %z) 203 ret float %fmuladd 204} 205 206define float @fmuladd_unfold(float %x, float %y, float %z) { 207; CHECK-LABEL: @fmuladd_unfold( 208; CHECK-NEXT: [[FMULADD:%.*]] = call reassoc contract float @llvm.fmuladd.f32(float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) 209; CHECK-NEXT: ret float [[FMULADD]] 210; 211 %fmuladd = call reassoc contract float @llvm.fmuladd.f32(float %x, float %y, float %z) 212 ret float %fmuladd 213} 214 215define <8 x half> @fmuladd_unfold_vec(<8 x half> %x, <8 x half> %y, <8 x half> %z) { 216; CHECK-LABEL: @fmuladd_unfold_vec( 217; CHECK-NEXT: [[FMULADD:%.*]] = call reassoc contract <8 x half> @llvm.fmuladd.v8f16(<8 x half> [[X:%.*]], <8 x half> [[Y:%.*]], <8 x half> [[Z:%.*]]) 218; CHECK-NEXT: ret <8 x half> [[FMULADD]] 219; 220 %fmuladd = call reassoc contract <8 x half> @llvm.fmuladd.v8f16(<8 x half> %x, <8 x half> %y, <8 x half> %z) 221 ret <8 x half> %fmuladd 222} 223 224define float @fmuladd_unary_fneg_x_unary_fneg_y_fast(float %x, float %y, float %z) { 225; CHECK-LABEL: @fmuladd_unary_fneg_x_unary_fneg_y_fast( 226; CHECK-NEXT: [[FMULADD:%.*]] = call fast float @llvm.fmuladd.f32(float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) 227; CHECK-NEXT: ret float [[FMULADD]] 228; 229 %x.fneg = fneg float %x 230 %y.fneg = fneg float %y 231 %fmuladd = call fast float @llvm.fmuladd.f32(float %x.fneg, float %y.fneg, float %z) 232 ret float %fmuladd 233} 234 235define float @fmuladd_fneg_const_fneg_y(float %y, float %z) { 236; CHECK-LABEL: @fmuladd_fneg_const_fneg_y( 237; CHECK-NEXT: [[FMULADD:%.*]] = call float @llvm.fmuladd.f32(float [[Y:%.*]], float bitcast (i32 ptrtoint (ptr @external to i32) to float), float [[Z:%.*]]) 238; CHECK-NEXT: ret float [[FMULADD]] 239; 240 %y.fneg = fsub float -0.0, %y 241 %fsub = fsub float -0.0, bitcast (i32 ptrtoint (ptr @external to i32) to float) 242 %fmuladd = call float @llvm.fmuladd.f32(float %fsub, float %y.fneg, float %z) 243 ret float %fmuladd 244} 245 246define float @fmuladd_unary_fneg_const_unary_fneg_y(float %y, float %z) { 247; CHECK-LABEL: @fmuladd_unary_fneg_const_unary_fneg_y( 248; CHECK-NEXT: [[FMULADD:%.*]] = call float @llvm.fmuladd.f32(float [[Y:%.*]], float bitcast (i32 ptrtoint (ptr @external to i32) to float), float [[Z:%.*]]) 249; CHECK-NEXT: ret float [[FMULADD]] 250; 251 %y.fneg = fneg float %y 252 %external.fneg = fneg float bitcast (i32 ptrtoint (ptr @external to i32) to float) 253 %fmuladd = call float @llvm.fmuladd.f32(float %external.fneg, float %y.fneg, float %z) 254 ret float %fmuladd 255} 256 257define float @fmuladd_fneg_x_fneg_const(float %x, float %z) { 258; CHECK-LABEL: @fmuladd_fneg_x_fneg_const( 259; CHECK-NEXT: [[FMULADD:%.*]] = call float @llvm.fmuladd.f32(float [[X:%.*]], float bitcast (i32 ptrtoint (ptr @external to i32) to float), float [[Z:%.*]]) 260; CHECK-NEXT: ret float [[FMULADD]] 261; 262 %x.fneg = fsub float -0.0, %x 263 %fsub = fsub float -0.0, bitcast (i32 ptrtoint (ptr @external to i32) to float) 264 %fmuladd = call float @llvm.fmuladd.f32(float %x.fneg, float %fsub, float %z) 265 ret float %fmuladd 266} 267 268define float @fmuladd_unary_fneg_x_unary_fneg_const(float %x, float %z) { 269; CHECK-LABEL: @fmuladd_unary_fneg_x_unary_fneg_const( 270; CHECK-NEXT: [[FMULADD:%.*]] = call float @llvm.fmuladd.f32(float [[X:%.*]], float bitcast (i32 ptrtoint (ptr @external to i32) to float), float [[Z:%.*]]) 271; CHECK-NEXT: ret float [[FMULADD]] 272; 273 %x.fneg = fneg float %x 274 %external.fneg = fneg float bitcast (i32 ptrtoint (ptr @external to i32) to float) 275 %fmuladd = call float @llvm.fmuladd.f32(float %x.fneg, float %external.fneg, float %z) 276 ret float %fmuladd 277} 278 279define float @fmuladd_fabs_x_fabs_y(float %x, float %y, float %z) { 280; CHECK-LABEL: @fmuladd_fabs_x_fabs_y( 281; CHECK-NEXT: [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]]) 282; CHECK-NEXT: [[Y_FABS:%.*]] = call float @llvm.fabs.f32(float [[Y:%.*]]) 283; CHECK-NEXT: [[FMULADD:%.*]] = call float @llvm.fmuladd.f32(float [[X_FABS]], float [[Y_FABS]], float [[Z:%.*]]) 284; CHECK-NEXT: ret float [[FMULADD]] 285; 286 %x.fabs = call float @llvm.fabs.f32(float %x) 287 %y.fabs = call float @llvm.fabs.f32(float %y) 288 %fmuladd = call float @llvm.fmuladd.f32(float %x.fabs, float %y.fabs, float %z) 289 ret float %fmuladd 290} 291 292define float @fmuladd_fabs_x_fabs_x(float %x, float %z) { 293; CHECK-LABEL: @fmuladd_fabs_x_fabs_x( 294; CHECK-NEXT: [[FMULADD:%.*]] = call float @llvm.fmuladd.f32(float [[X:%.*]], float [[X]], float [[Z:%.*]]) 295; CHECK-NEXT: ret float [[FMULADD]] 296; 297 %x.fabs = call float @llvm.fabs.f32(float %x) 298 %fmuladd = call float @llvm.fmuladd.f32(float %x.fabs, float %x.fabs, float %z) 299 ret float %fmuladd 300} 301 302define float @fmuladd_fabs_x_fabs_x_fast(float %x, float %z) { 303; CHECK-LABEL: @fmuladd_fabs_x_fabs_x_fast( 304; CHECK-NEXT: [[FMULADD:%.*]] = call fast float @llvm.fmuladd.f32(float [[X:%.*]], float [[X]], float [[Z:%.*]]) 305; CHECK-NEXT: ret float [[FMULADD]] 306; 307 %x.fabs = call float @llvm.fabs.f32(float %x) 308 %fmuladd = call fast float @llvm.fmuladd.f32(float %x.fabs, float %x.fabs, float %z) 309 ret float %fmuladd 310} 311 312define float @fma_k_y_z(float %y, float %z) { 313; CHECK-LABEL: @fma_k_y_z( 314; CHECK-NEXT: [[FMA:%.*]] = call float @llvm.fma.f32(float [[Y:%.*]], float 4.000000e+00, float [[Z:%.*]]) 315; CHECK-NEXT: ret float [[FMA]] 316; 317 %fma = call float @llvm.fma.f32(float 4.0, float %y, float %z) 318 ret float %fma 319} 320 321define float @fma_k_y_z_fast(float %y, float %z) { 322; CHECK-LABEL: @fma_k_y_z_fast( 323; CHECK-NEXT: [[FMA:%.*]] = call fast float @llvm.fma.f32(float [[Y:%.*]], float 4.000000e+00, float [[Z:%.*]]) 324; CHECK-NEXT: ret float [[FMA]] 325; 326 %fma = call fast float @llvm.fma.f32(float 4.0, float %y, float %z) 327 ret float %fma 328} 329 330; Treat fmuladd like an fma intrinsic 331define float @fmuladd_k_y_z_fast(float %y, float %z) { 332; CHECK-LABEL: @fmuladd_k_y_z_fast( 333; CHECK-NEXT: [[FMULADD:%.*]] = call fast float @llvm.fmuladd.f32(float [[Y:%.*]], float 4.000000e+00, float [[Z:%.*]]) 334; CHECK-NEXT: ret float [[FMULADD]] 335; 336 %fmuladd = call fast float @llvm.fmuladd.f32(float 4.0, float %y, float %z) 337 ret float %fmuladd 338} 339 340define float @fma_1_y_z(float %y, float %z) { 341; CHECK-LABEL: @fma_1_y_z( 342; CHECK-NEXT: [[FMA:%.*]] = fadd float [[Y:%.*]], [[Z:%.*]] 343; CHECK-NEXT: ret float [[FMA]] 344; 345 %fma = call float @llvm.fma.f32(float 1.0, float %y, float %z) 346 ret float %fma 347} 348 349define float @fma_x_1_z(float %x, float %z) { 350; CHECK-LABEL: @fma_x_1_z( 351; CHECK-NEXT: [[FMA:%.*]] = fadd float [[X:%.*]], [[Z:%.*]] 352; CHECK-NEXT: ret float [[FMA]] 353; 354 %fma = call float @llvm.fma.f32(float %x, float 1.0, float %z) 355 ret float %fma 356} 357 358define <2 x float> @fma_x_1_z_v2f32(<2 x float> %x, <2 x float> %z) { 359; CHECK-LABEL: @fma_x_1_z_v2f32( 360; CHECK-NEXT: [[FMA:%.*]] = fadd <2 x float> [[X:%.*]], [[Z:%.*]] 361; CHECK-NEXT: ret <2 x float> [[FMA]] 362; 363 %fma = call <2 x float> @llvm.fma.v2f32(<2 x float> %x, <2 x float> <float 1.0, float 1.0>, <2 x float> %z) 364 ret <2 x float> %fma 365} 366 367define <2 x float> @fma_x_1_2_z_v2f32(<2 x float> %x, <2 x float> %z) { 368; CHECK-LABEL: @fma_x_1_2_z_v2f32( 369; CHECK-NEXT: [[FMA:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> [[X:%.*]], <2 x float> <float 1.000000e+00, float 2.000000e+00>, <2 x float> [[Z:%.*]]) 370; CHECK-NEXT: ret <2 x float> [[FMA]] 371; 372 %fma = call <2 x float> @llvm.fma.v2f32(<2 x float> %x, <2 x float> <float 1.0, float 2.0>, <2 x float> %z) 373 ret <2 x float> %fma 374} 375 376define float @fma_x_1_z_fast(float %x, float %z) { 377; CHECK-LABEL: @fma_x_1_z_fast( 378; CHECK-NEXT: [[FMA:%.*]] = fadd fast float [[X:%.*]], [[Z:%.*]] 379; CHECK-NEXT: ret float [[FMA]] 380; 381 %fma = call fast float @llvm.fma.f32(float %x, float 1.0, float %z) 382 ret float %fma 383} 384 385define float @fma_1_1_z(float %z) { 386; CHECK-LABEL: @fma_1_1_z( 387; CHECK-NEXT: [[FMA:%.*]] = fadd float [[Z:%.*]], 1.000000e+00 388; CHECK-NEXT: ret float [[FMA]] 389; 390 %fma = call float @llvm.fma.f32(float 1.0, float 1.0, float %z) 391 ret float %fma 392} 393 394define float @fma_x_y_0(float %x, float %y) { 395; CHECK-LABEL: @fma_x_y_0( 396; CHECK-NEXT: [[FMA:%.*]] = call float @llvm.fma.f32(float [[X:%.*]], float [[Y:%.*]], float 0.000000e+00) 397; CHECK-NEXT: ret float [[FMA]] 398; 399 %fma = call float @llvm.fma.f32(float %x, float %y, float 0.0) 400 ret float %fma 401} 402 403define float @fma_x_y_0_nsz(float %x, float %y) { 404; CHECK-LABEL: @fma_x_y_0_nsz( 405; CHECK-NEXT: [[FMA:%.*]] = fmul nsz float [[X:%.*]], [[Y:%.*]] 406; CHECK-NEXT: ret float [[FMA]] 407; 408 %fma = call nsz float @llvm.fma.f32(float %x, float %y, float 0.0) 409 ret float %fma 410} 411 412define <8 x half> @fma_x_y_0_v(<8 x half> %x, <8 x half> %y) { 413; CHECK-LABEL: @fma_x_y_0_v( 414; CHECK-NEXT: [[FMA:%.*]] = call <8 x half> @llvm.fma.v8f16(<8 x half> [[X:%.*]], <8 x half> [[Y:%.*]], <8 x half> zeroinitializer) 415; CHECK-NEXT: ret <8 x half> [[FMA]] 416; 417 %fma = call <8 x half> @llvm.fma.v8f16(<8 x half> %x, <8 x half> %y, <8 x half> zeroinitializer) 418 ret <8 x half> %fma 419} 420 421define <8 x half> @fma_x_y_0_nsz_v(<8 x half> %x, <8 x half> %y) { 422; CHECK-LABEL: @fma_x_y_0_nsz_v( 423; CHECK-NEXT: [[FMA:%.*]] = fmul nsz <8 x half> [[X:%.*]], [[Y:%.*]] 424; CHECK-NEXT: ret <8 x half> [[FMA]] 425; 426 %fma = call nsz <8 x half> @llvm.fma.v8f16(<8 x half> %x, <8 x half> %y, <8 x half> zeroinitializer) 427 ret <8 x half> %fma 428} 429 430define float @fmuladd_x_y_0(float %x, float %y) { 431; CHECK-LABEL: @fmuladd_x_y_0( 432; CHECK-NEXT: [[FMA:%.*]] = call float @llvm.fmuladd.f32(float [[X:%.*]], float [[Y:%.*]], float 0.000000e+00) 433; CHECK-NEXT: ret float [[FMA]] 434; 435 %fma = call float @llvm.fmuladd.f32(float %x, float %y, float 0.0) 436 ret float %fma 437} 438 439define float @fmuladd_x_y_0_nsz(float %x, float %y) { 440; CHECK-LABEL: @fmuladd_x_y_0_nsz( 441; CHECK-NEXT: [[FMA:%.*]] = fmul nsz float [[X:%.*]], [[Y:%.*]] 442; CHECK-NEXT: ret float [[FMA]] 443; 444 %fma = call nsz float @llvm.fmuladd.f32(float %x, float %y, float 0.0) 445 ret float %fma 446} 447 448define float @fma_x_y_m0(float %x, float %y) { 449; CHECK-LABEL: @fma_x_y_m0( 450; CHECK-NEXT: [[FMA:%.*]] = fmul float [[X:%.*]], [[Y:%.*]] 451; CHECK-NEXT: ret float [[FMA]] 452; 453 %fma = call float @llvm.fma.f32(float %x, float %y, float -0.0) 454 ret float %fma 455} 456 457define <8 x half> @fma_x_y_m0_v(<8 x half> %x, <8 x half> %y) { 458; CHECK-LABEL: @fma_x_y_m0_v( 459; CHECK-NEXT: [[FMA:%.*]] = fmul <8 x half> [[X:%.*]], [[Y:%.*]] 460; CHECK-NEXT: ret <8 x half> [[FMA]] 461; 462 %fma = call <8 x half> @llvm.fma.v8f16(<8 x half> %x, <8 x half> %y, <8 x half> <half -0.0, half -0.0, half -0.0, half -0.0, half -0.0, half -0.0, half -0.0, half -0.0>) 463 ret <8 x half> %fma 464} 465 466define float @fmuladd_x_y_m0(float %x, float %y) { 467; CHECK-LABEL: @fmuladd_x_y_m0( 468; CHECK-NEXT: [[FMA:%.*]] = fmul float [[X:%.*]], [[Y:%.*]] 469; CHECK-NEXT: ret float [[FMA]] 470; 471 %fma = call float @llvm.fmuladd.f32(float %x, float %y, float -0.0) 472 ret float %fma 473} 474 475define float @fmuladd_x_1_z_fast(float %x, float %z) { 476; CHECK-LABEL: @fmuladd_x_1_z_fast( 477; CHECK-NEXT: [[FMULADD:%.*]] = fadd fast float [[X:%.*]], [[Z:%.*]] 478; CHECK-NEXT: ret float [[FMULADD]] 479; 480 %fmuladd = call fast float @llvm.fmuladd.f32(float %x, float 1.0, float %z) 481 ret float %fmuladd 482} 483 484define <2 x double> @fmuladd_a_0_b(<2 x double> %a, <2 x double> %b) { 485; CHECK-LABEL: @fmuladd_a_0_b( 486; CHECK-NEXT: ret <2 x double> [[B:%.*]] 487; 488 %res = call nnan nsz <2 x double> @llvm.fmuladd.v2f64(<2 x double> %a, <2 x double> zeroinitializer, <2 x double> %b) 489 ret <2 x double> %res 490} 491 492define <2 x double> @fmuladd_0_a_b(<2 x double> %a, <2 x double> %b) { 493; CHECK-LABEL: @fmuladd_0_a_b( 494; CHECK-NEXT: ret <2 x double> [[B:%.*]] 495; 496 %res = call nnan nsz <2 x double> @llvm.fmuladd.v2f64(<2 x double> zeroinitializer, <2 x double> %a, <2 x double> %b) 497 ret <2 x double> %res 498} 499 500define <2 x double> @fmuladd_a_0_b_missing_flags(<2 x double> %a, <2 x double> %b) { 501; CHECK-LABEL: @fmuladd_a_0_b_missing_flags( 502; CHECK-NEXT: [[RES:%.*]] = call nnan <2 x double> @llvm.fmuladd.v2f64(<2 x double> [[A:%.*]], <2 x double> zeroinitializer, <2 x double> [[B:%.*]]) 503; CHECK-NEXT: ret <2 x double> [[RES]] 504; 505 %res = call nnan <2 x double> @llvm.fmuladd.v2f64(<2 x double> %a, <2 x double> zeroinitializer, <2 x double> %b) 506 ret <2 x double> %res 507} 508 509define <2 x double> @fma_a_0_b(<2 x double> %a, <2 x double> %b) { 510; CHECK-LABEL: @fma_a_0_b( 511; CHECK-NEXT: ret <2 x double> [[B:%.*]] 512; 513 %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> %a, <2 x double> zeroinitializer, <2 x double> %b) 514 ret <2 x double> %res 515} 516 517define <2 x double> @fma_0_a_b(<2 x double> %a, <2 x double> %b) { 518; CHECK-LABEL: @fma_0_a_b( 519; CHECK-NEXT: ret <2 x double> [[B:%.*]] 520; 521 %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> zeroinitializer, <2 x double> %a, <2 x double> %b) 522 ret <2 x double> %res 523} 524 525define <2 x double> @fma_0_a_b_missing_flags(<2 x double> %a, <2 x double> %b) { 526; CHECK-LABEL: @fma_0_a_b_missing_flags( 527; CHECK-NEXT: [[RES:%.*]] = call nsz <2 x double> @llvm.fma.v2f64(<2 x double> [[A:%.*]], <2 x double> zeroinitializer, <2 x double> [[B:%.*]]) 528; CHECK-NEXT: ret <2 x double> [[RES]] 529; 530 %res = call nsz <2 x double> @llvm.fma.v2f64(<2 x double> zeroinitializer, <2 x double> %a, <2 x double> %b) 531 ret <2 x double> %res 532} 533 534define <2 x double> @fma_sqrt(<2 x double> %a, <2 x double> %b) { 535; CHECK-LABEL: @fma_sqrt( 536; CHECK-NEXT: [[RES:%.*]] = fadd fast <2 x double> [[A:%.*]], [[B:%.*]] 537; CHECK-NEXT: ret <2 x double> [[RES]] 538; 539 %sqrt = call fast <2 x double> @llvm.sqrt.v2f64(<2 x double> %a) 540 %res = call fast <2 x double> @llvm.fma.v2f64(<2 x double> %sqrt, <2 x double> %sqrt, <2 x double> %b) 541 ret <2 x double> %res 542} 543 544; We do not fold constant multiplies in FMAs, as they could require rounding, unless either constant is 0.0 or 1.0. 545define <2 x double> @fma_const_fmul(<2 x double> %b) { 546; CHECK-LABEL: @fma_const_fmul( 547; CHECK-NEXT: [[RES:%.*]] = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> <double 0x4131233302898702, double 0x40C387800000D6C0>, <2 x double> <double 1.291820e-08, double 9.123000e-06>, <2 x double> [[B:%.*]]) 548; CHECK-NEXT: ret <2 x double> [[RES]] 549; 550 %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> <double 1123123.0099110012314, double 9999.0000001>, <2 x double> <double 0.0000000129182, double 0.000009123>, <2 x double> %b) 551 ret <2 x double> %res 552} 553 554define <2 x double> @fma_const_fmul_zero(<2 x double> %b) { 555; CHECK-LABEL: @fma_const_fmul_zero( 556; CHECK-NEXT: ret <2 x double> [[B:%.*]] 557; 558 %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> <double 0.0, double 0.0>, <2 x double> <double 1123123.0099110012314, double 9999.0000001>, <2 x double> %b) 559 ret <2 x double> %res 560} 561 562define <2 x double> @fma_const_fmul_zero2(<2 x double> %b) { 563; CHECK-LABEL: @fma_const_fmul_zero2( 564; CHECK-NEXT: ret <2 x double> [[B:%.*]] 565; 566 %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> <double 1123123.0099110012314, double 9999.0000001>, <2 x double> <double 0.0, double 0.0>, <2 x double> %b) 567 ret <2 x double> %res 568} 569 570define <2 x double> @fma_const_fmul_one(<2 x double> %b) { 571; CHECK-LABEL: @fma_const_fmul_one( 572; CHECK-NEXT: [[RES:%.*]] = fadd nnan nsz <2 x double> [[B:%.*]], <double 0x4131233302898702, double 0x40C387800000D6C0> 573; CHECK-NEXT: ret <2 x double> [[RES]] 574; 575 %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> <double 1.0, double 1.0>, <2 x double> <double 1123123.0099110012314, double 9999.0000001>, <2 x double> %b) 576 ret <2 x double> %res 577} 578 579define <2 x double> @fma_const_fmul_one2(<2 x double> %b) { 580; CHECK-LABEL: @fma_const_fmul_one2( 581; CHECK-NEXT: [[RES:%.*]] = fadd nnan nsz <2 x double> [[B:%.*]], <double 0x4131233302898702, double 0x40C387800000D6C0> 582; CHECK-NEXT: ret <2 x double> [[RES]] 583; 584 %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> <double 1123123.0099110012314, double 9999.0000001>, <2 x double> <double 1.0, double 1.0>, <2 x double> %b) 585 ret <2 x double> %res 586} 587 588define <2 x double> @fma_nan_and_const_0(<2 x double> %b) { 589; CHECK-LABEL: @fma_nan_and_const_0( 590; CHECK-NEXT: ret <2 x double> splat (double 0x7FF8000000000000) 591; 592 %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> <double 0x7FF8000000000000, double 0x7FF8000000000000>, <2 x double> <double 0.0000000129182, double 0.000009123>, <2 x double> %b) 593 ret <2 x double> %res 594} 595 596define <2 x double> @fma_nan_and_const_1(<2 x double> %b) { 597; CHECK-LABEL: @fma_nan_and_const_1( 598; CHECK-NEXT: ret <2 x double> splat (double 0x7FF8000000000000) 599; 600 %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> <double 0.0000000129182, double 0.000009123>, <2 x double> <double 0x7FF8000000000000, double 0x7FF8000000000000>, <2 x double> %b) 601 ret <2 x double> %res 602} 603 604define <2 x double> @fma_nan_and_const_2(<2 x double> %b) { 605; CHECK-LABEL: @fma_nan_and_const_2( 606; CHECK-NEXT: ret <2 x double> splat (double 0x7FF8000000000000) 607; 608 %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> <double 0.0000000129182, double 0.000009123>, <2 x double> %b, <2 x double> <double 0x7FF8000000000000, double 0x7FF8000000000000>) 609 ret <2 x double> %res 610} 611 612define <2 x double> @fma_undef_0(<2 x double> %b, <2 x double> %c) { 613; CHECK-LABEL: @fma_undef_0( 614; CHECK-NEXT: ret <2 x double> splat (double 0x7FF8000000000000) 615; 616 %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> <double undef, double undef>, <2 x double> %b, <2 x double> %c) 617 ret <2 x double> %res 618} 619 620define <2 x double> @fma_undef_1(<2 x double> %b, <2 x double> %c) { 621; CHECK-LABEL: @fma_undef_1( 622; CHECK-NEXT: ret <2 x double> splat (double 0x7FF8000000000000) 623; 624 %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> %b, <2 x double> <double undef, double undef>, <2 x double> %c) 625 ret <2 x double> %res 626} 627 628define <2 x double> @fma_undef_2(<2 x double> %b, <2 x double> %c) { 629; CHECK-LABEL: @fma_undef_2( 630; CHECK-NEXT: ret <2 x double> splat (double 0x7FF8000000000000) 631; 632 %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> %b, <2 x double> %c, <2 x double> <double undef, double undef>) 633 ret <2 x double> %res 634} 635 636define <2 x double> @fma_partial_undef_0(<2 x double> %b, <2 x double> %c) { 637; CHECK-LABEL: @fma_partial_undef_0( 638; CHECK-NEXT: [[RES:%.*]] = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> [[B:%.*]], <2 x double> <double undef, double 0x4068E00A137F38C5>, <2 x double> [[C:%.*]]) 639; CHECK-NEXT: ret <2 x double> [[RES]] 640; 641 %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> <double undef, double 199.00123>, <2 x double> %b, <2 x double> %c) 642 ret <2 x double> %res 643} 644 645define <2 x double> @fma_partial_undef_1(<2 x double> %b, <2 x double> %c) { 646; CHECK-LABEL: @fma_partial_undef_1( 647; CHECK-NEXT: [[RES:%.*]] = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> [[B:%.*]], <2 x double> <double 0x4068E00A137F38C5, double undef>, <2 x double> [[C:%.*]]) 648; CHECK-NEXT: ret <2 x double> [[RES]] 649; 650 %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> %b, <2 x double> <double 199.00123, double undef>, <2 x double> %c) 651 ret <2 x double> %res 652} 653 654define <2 x double> @fma_partial_undef_2(<2 x double> %b, <2 x double> %c) { 655; CHECK-LABEL: @fma_partial_undef_2( 656; CHECK-NEXT: [[RES:%.*]] = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> [[B:%.*]], <2 x double> [[C:%.*]], <2 x double> <double 0x4068E00A137F38C5, double undef>) 657; CHECK-NEXT: ret <2 x double> [[RES]] 658; 659 %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> %b, <2 x double> %c, <2 x double> <double 199.00123, double undef>) 660 ret <2 x double> %res 661} 662 663 664define <2 x double> @fma_nan_0(<2 x double> %b, <2 x double> %c) { 665; CHECK-LABEL: @fma_nan_0( 666; CHECK-NEXT: ret <2 x double> splat (double 0x7FF8000000000000) 667; 668 %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> <double 0x7FF8000000000000, double 0x7FF8000000000000>, <2 x double> %b, <2 x double> %c) 669 ret <2 x double> %res 670} 671define <2 x double> @fma_nan_1(<2 x double> %b, <2 x double> %c) { 672; CHECK-LABEL: @fma_nan_1( 673; CHECK-NEXT: ret <2 x double> splat (double 0x7FF8000000000000) 674; 675 %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> %b, <2 x double> <double 0x7FF8000000000000, double 0x7FF8000000000000>, <2 x double> %c) 676 ret <2 x double> %res 677} 678 679define <2 x double> @fma_nan_2(<2 x double> %b, <2 x double> %c) { 680; CHECK-LABEL: @fma_nan_2( 681; CHECK-NEXT: ret <2 x double> splat (double 0x7FF8000000000000) 682; 683 %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> %b, <2 x double> %c, <2 x double> <double 0x7FF8000000000000, double 0x7FF8000000000000>) 684 ret <2 x double> %res 685} 686 687define <2 x double> @fmuladd_const_fmul(<2 x double> %b) { 688; CHECK-LABEL: @fmuladd_const_fmul( 689; CHECK-NEXT: [[RES:%.*]] = fadd nnan nsz <2 x double> [[B:%.*]], <double 0x3F8DB6C076AD949B, double 0x3FB75A405B6E6D69> 690; CHECK-NEXT: ret <2 x double> [[RES]] 691; 692 %res = call nnan nsz <2 x double> @llvm.fmuladd.v2f64(<2 x double> <double 1123123.0099110012314, double 9999.0000001>, <2 x double> <double 0.0000000129182, double 0.000009123>, <2 x double> %b) 693 ret <2 x double> %res 694} 695 696define <2 x double> @fmuladd_nan_and_const_0(<2 x double> %b) { 697; CHECK-LABEL: @fmuladd_nan_and_const_0( 698; CHECK-NEXT: ret <2 x double> splat (double 0x7FF8000000000000) 699; 700 %res = call nnan nsz <2 x double> @llvm.fmuladd.v2f64(<2 x double> <double 0x7FF8000000000000, double 0x7FF8000000000000>, <2 x double> <double 0.0000000129182, double 0.000009123>, <2 x double> %b) 701 ret <2 x double> %res 702} 703 704define <2 x double> @fmuladd_nan_and_const_1(<2 x double> %b) { 705; CHECK-LABEL: @fmuladd_nan_and_const_1( 706; CHECK-NEXT: ret <2 x double> splat (double 0x7FF8000000000000) 707; 708 %res = call nnan nsz <2 x double> @llvm.fmuladd.v2f64(<2 x double> <double 0.0000000129182, double 0.000009123>, <2 x double> <double 0x7FF8000000000000, double 0x7FF8000000000000>, <2 x double> %b) 709 ret <2 x double> %res 710} 711 712define <2 x double> @fmuladd_nan_and_const_2(<2 x double> %b) { 713; CHECK-LABEL: @fmuladd_nan_and_const_2( 714; CHECK-NEXT: ret <2 x double> splat (double 0x7FF8000000000000) 715; 716 %res = call nnan nsz <2 x double> @llvm.fmuladd.v2f64(<2 x double> <double 0.0000000129182, double 0.000009123>, <2 x double> %b, <2 x double> <double 0x7FF8000000000000, double 0x7FF8000000000000>) 717 ret <2 x double> %res 718} 719 720define <2 x double> @fmuladd_nan_0(<2 x double> %b, <2 x double> %c) { 721; CHECK-LABEL: @fmuladd_nan_0( 722; CHECK-NEXT: ret <2 x double> splat (double 0x7FF8000000000000) 723; 724 %res = call nnan nsz <2 x double> @llvm.fmuladd.v2f64(<2 x double> <double 0x7FF8000000000000, double 0x7FF8000000000000>, <2 x double> %b, <2 x double> %c) 725 ret <2 x double> %res 726} 727 728define <2 x double> @fmuladd_nan_1(<2 x double> %b, <2 x double> %c) { 729; CHECK-LABEL: @fmuladd_nan_1( 730; CHECK-NEXT: ret <2 x double> splat (double 0x7FF8000000000000) 731; 732 %res = call nnan nsz <2 x double> @llvm.fmuladd.v2f64(<2 x double> %b, <2 x double> <double 0x7FF8000000000000, double 0x7FF8000000000000>, <2 x double> %c) 733 ret <2 x double> %res 734} 735 736define <2 x double> @fmuladd_undef_0(<2 x double> %b, <2 x double> %c) { 737; CHECK-LABEL: @fmuladd_undef_0( 738; CHECK-NEXT: ret <2 x double> splat (double 0x7FF8000000000000) 739; 740 %res = call nnan nsz <2 x double> @llvm.fmuladd.v2f64(<2 x double> <double undef, double undef>, <2 x double> %b, <2 x double> %c) 741 ret <2 x double> %res 742} 743 744define <2 x double> @fmuladd_undef_1(<2 x double> %b, <2 x double> %c) { 745; CHECK-LABEL: @fmuladd_undef_1( 746; CHECK-NEXT: ret <2 x double> splat (double 0x7FF8000000000000) 747; 748 %res = call nnan nsz <2 x double> @llvm.fmuladd.v2f64(<2 x double> %b, <2 x double> <double undef, double undef>, <2 x double> %c) 749 ret <2 x double> %res 750} 751 752define <2 x double> @fmuladd_undef_2(<2 x double> %b, <2 x double> %c) { 753; CHECK-LABEL: @fmuladd_undef_2( 754; CHECK-NEXT: ret <2 x double> splat (double 0x7FF8000000000000) 755; 756 %res = call nnan nsz <2 x double> @llvm.fmuladd.v2f64(<2 x double> %b, <2 x double> %c, <2 x double> <double 0x7FF8000000000000, double 0x7FF8000000000000>) 757 ret <2 x double> %res 758} 759 760define <2 x float> @fma_unary_shuffle_ops(<2 x float> %x, <2 x float> %y, <2 x float> %z) { 761; CHECK-LABEL: @fma_unary_shuffle_ops( 762; CHECK-NEXT: [[TMP1:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> [[X:%.*]], <2 x float> [[Y:%.*]], <2 x float> [[Z:%.*]]) 763; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> poison, <2 x i32> <i32 1, i32 0> 764; CHECK-NEXT: ret <2 x float> [[R]] 765; 766 %a = shufflevector <2 x float> %x, <2 x float> poison, <2 x i32> <i32 1, i32 0> 767 %b = shufflevector <2 x float> %y, <2 x float> poison, <2 x i32> <i32 1, i32 0> 768 %c = shufflevector <2 x float> %z, <2 x float> poison, <2 x i32> <i32 1, i32 0> 769 %r = call <2 x float> @llvm.fma.v2f32(<2 x float> %a, <2 x float> %b, <2 x float> %c) 770 ret <2 x float> %r 771} 772 773define <3 x float> @fma_unary_shuffle_ops_widening(<2 x float> %x, <2 x float> %y, <2 x float> %z) { 774; CHECK-LABEL: @fma_unary_shuffle_ops_widening( 775; CHECK-NEXT: [[A:%.*]] = shufflevector <2 x float> [[X:%.*]], <2 x float> poison, <3 x i32> <i32 1, i32 0, i32 1> 776; CHECK-NEXT: call void @use_vec3(<3 x float> [[A]]) 777; CHECK-NEXT: [[TMP1:%.*]] = call fast <2 x float> @llvm.fma.v2f32(<2 x float> [[X]], <2 x float> [[Y:%.*]], <2 x float> [[Z:%.*]]) 778; CHECK-NEXT: [[R:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> poison, <3 x i32> <i32 1, i32 0, i32 1> 779; CHECK-NEXT: ret <3 x float> [[R]] 780; 781 %a = shufflevector <2 x float> %x, <2 x float> poison, <3 x i32> <i32 1, i32 0, i32 1> 782 call void @use_vec3(<3 x float> %a) 783 %b = shufflevector <2 x float> %y, <2 x float> poison, <3 x i32> <i32 1, i32 0, i32 1> 784 %c = shufflevector <2 x float> %z, <2 x float> poison, <3 x i32> <i32 1, i32 0, i32 1> 785 %r = call fast <3 x float> @llvm.fma.v3f32(<3 x float> %a, <3 x float> %b, <3 x float> %c) 786 ret <3 x float> %r 787} 788 789define <2 x float> @fma_unary_shuffle_ops_narrowing(<3 x float> %x, <3 x float> %y, <3 x float> %z) { 790; CHECK-LABEL: @fma_unary_shuffle_ops_narrowing( 791; CHECK-NEXT: [[B:%.*]] = shufflevector <3 x float> [[Y:%.*]], <3 x float> poison, <2 x i32> <i32 1, i32 0> 792; CHECK-NEXT: call void @use_vec(<2 x float> [[B]]) 793; CHECK-NEXT: [[TMP1:%.*]] = call nnan nsz <3 x float> @llvm.fma.v3f32(<3 x float> [[X:%.*]], <3 x float> [[Y]], <3 x float> [[Z:%.*]]) 794; CHECK-NEXT: [[R:%.*]] = shufflevector <3 x float> [[TMP1]], <3 x float> poison, <2 x i32> <i32 1, i32 0> 795; CHECK-NEXT: ret <2 x float> [[R]] 796; 797 %a = shufflevector <3 x float> %x, <3 x float> poison, <2 x i32> <i32 1, i32 0> 798 %b = shufflevector <3 x float> %y, <3 x float> poison, <2 x i32> <i32 1, i32 0> 799 call void @use_vec(<2 x float> %b) 800 %c = shufflevector <3 x float> %z, <3 x float> poison, <2 x i32> <i32 1, i32 0> 801 %r = call nnan nsz <2 x float> @llvm.fma.v2f32(<2 x float> %a, <2 x float> %b, <2 x float> %c) 802 ret <2 x float> %r 803} 804 805; negative test - must have 3 shuffles 806 807define <2 x float> @fma_unary_shuffle_ops_unshuffled(<2 x float> %x, <2 x float> %y, <2 x float> %z) { 808; CHECK-LABEL: @fma_unary_shuffle_ops_unshuffled( 809; CHECK-NEXT: [[A:%.*]] = shufflevector <2 x float> [[X:%.*]], <2 x float> poison, <2 x i32> <i32 1, i32 0> 810; CHECK-NEXT: [[B:%.*]] = shufflevector <2 x float> [[Y:%.*]], <2 x float> poison, <2 x i32> <i32 1, i32 0> 811; CHECK-NEXT: [[R:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> [[A]], <2 x float> [[B]], <2 x float> [[Z:%.*]]) 812; CHECK-NEXT: ret <2 x float> [[R]] 813; 814 %a = shufflevector <2 x float> %x, <2 x float> poison, <2 x i32> <i32 1, i32 0> 815 %b = shufflevector <2 x float> %y, <2 x float> poison, <2 x i32> <i32 1, i32 0> 816 %r = call <2 x float> @llvm.fma.v2f32(<2 x float> %a, <2 x float> %b, <2 x float> %z) 817 ret <2 x float> %r 818} 819 820; negative test - must have identical masks 821 822define <2 x float> @fma_unary_shuffle_ops_wrong_mask(<2 x float> %x, <2 x float> %y, <2 x float> %z) { 823; CHECK-LABEL: @fma_unary_shuffle_ops_wrong_mask( 824; CHECK-NEXT: [[A:%.*]] = shufflevector <2 x float> [[X:%.*]], <2 x float> poison, <2 x i32> <i32 1, i32 0> 825; CHECK-NEXT: [[B:%.*]] = shufflevector <2 x float> [[Y:%.*]], <2 x float> poison, <2 x i32> zeroinitializer 826; CHECK-NEXT: [[C:%.*]] = shufflevector <2 x float> [[Z:%.*]], <2 x float> poison, <2 x i32> <i32 1, i32 0> 827; CHECK-NEXT: [[R:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> [[A]], <2 x float> [[B]], <2 x float> [[C]]) 828; CHECK-NEXT: ret <2 x float> [[R]] 829; 830 %a = shufflevector <2 x float> %x, <2 x float> poison, <2 x i32> <i32 1, i32 0> 831 %b = shufflevector <2 x float> %y, <2 x float> poison, <2 x i32> <i32 0, i32 0> 832 %c = shufflevector <2 x float> %z, <2 x float> poison, <2 x i32> <i32 1, i32 0> 833 %r = call <2 x float> @llvm.fma.v2f32(<2 x float> %a, <2 x float> %b, <2 x float> %c) 834 ret <2 x float> %r 835} 836 837; negative test - too many uses 838 839define <2 x float> @fma_unary_shuffle_ops_uses(<2 x float> %x, <2 x float> %y, <2 x float> %z) { 840; CHECK-LABEL: @fma_unary_shuffle_ops_uses( 841; CHECK-NEXT: [[A:%.*]] = shufflevector <2 x float> [[X:%.*]], <2 x float> poison, <2 x i32> <i32 1, i32 0> 842; CHECK-NEXT: call void @use_vec(<2 x float> [[A]]) 843; CHECK-NEXT: [[B:%.*]] = shufflevector <2 x float> [[Y:%.*]], <2 x float> poison, <2 x i32> <i32 1, i32 0> 844; CHECK-NEXT: call void @use_vec(<2 x float> [[B]]) 845; CHECK-NEXT: [[C:%.*]] = shufflevector <2 x float> [[Z:%.*]], <2 x float> poison, <2 x i32> <i32 1, i32 0> 846; CHECK-NEXT: call void @use_vec(<2 x float> [[C]]) 847; CHECK-NEXT: [[R:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> [[A]], <2 x float> [[B]], <2 x float> [[C]]) 848; CHECK-NEXT: ret <2 x float> [[R]] 849; 850 %a = shufflevector <2 x float> %x, <2 x float> poison, <2 x i32> <i32 1, i32 0> 851 call void @use_vec(<2 x float> %a) 852 %b = shufflevector <2 x float> %y, <2 x float> poison, <2 x i32> <i32 1, i32 0> 853 call void @use_vec(<2 x float> %b) 854 %c = shufflevector <2 x float> %z, <2 x float> poison, <2 x i32> <i32 1, i32 0> 855 call void @use_vec(<2 x float> %c) 856 %r = call <2 x float> @llvm.fma.v2f32(<2 x float> %a, <2 x float> %b, <2 x float> %c) 857 ret <2 x float> %r 858} 859 860define half @fma_negone(half %x, half %y) { 861; CHECK-LABEL: @fma_negone( 862; CHECK-NEXT: [[SUB:%.*]] = fsub half [[Y:%.*]], [[X:%.*]] 863; CHECK-NEXT: ret half [[SUB]] 864; 865 %sub = call half @llvm.fma.f16(half %x, half -1.0, half %y) 866 ret half %sub 867} 868 869define half @fmuladd_negone(half %x, half %y) { 870; CHECK-LABEL: @fmuladd_negone( 871; CHECK-NEXT: [[SUB:%.*]] = fsub half [[Y:%.*]], [[X:%.*]] 872; CHECK-NEXT: ret half [[SUB]] 873; 874 %sub = call half @llvm.fmuladd.f16(half %x, half -1.0, half %y) 875 ret half %sub 876} 877 878define half @fma_negone_fmf(half %x, half %y) { 879; CHECK-LABEL: @fma_negone_fmf( 880; CHECK-NEXT: [[SUB:%.*]] = fsub nnan ninf nsz half [[Y:%.*]], [[X:%.*]] 881; CHECK-NEXT: ret half [[SUB]] 882; 883 %sub = call nnan ninf nsz half @llvm.fma.f16(half %x, half -1.0, half %y) 884 ret half %sub 885} 886 887define half @fmuladd_negone_fmf(half %x, half %y) { 888; CHECK-LABEL: @fmuladd_negone_fmf( 889; CHECK-NEXT: [[SUB:%.*]] = fsub nnan ninf nsz half [[Y:%.*]], [[X:%.*]] 890; CHECK-NEXT: ret half [[SUB]] 891; 892 %sub = call nnan ninf nsz half @llvm.fmuladd.f16(half %x, half -1.0, half %y) 893 ret half %sub 894} 895 896define <2 x half> @fma_negone_vec(<2 x half> %x, <2 x half> %y) { 897; CHECK-LABEL: @fma_negone_vec( 898; CHECK-NEXT: [[SUB:%.*]] = fsub <2 x half> [[Y:%.*]], [[X:%.*]] 899; CHECK-NEXT: ret <2 x half> [[SUB]] 900; 901 %sub = call <2 x half> @llvm.fma.v2f16(<2 x half> %x, <2 x half> splat(half -1.0), <2 x half> %y) 902 ret <2 x half> %sub 903} 904 905define <2 x half> @fma_negone_vec_partial_undef(<2 x half> %x, <2 x half> %y) { 906; CHECK-LABEL: @fma_negone_vec_partial_undef( 907; CHECK-NEXT: [[SUB:%.*]] = call <2 x half> @llvm.fma.v2f16(<2 x half> [[X:%.*]], <2 x half> <half undef, half 0xHBC00>, <2 x half> [[Y:%.*]]) 908; CHECK-NEXT: ret <2 x half> [[SUB]] 909; 910 %sub = call <2 x half> @llvm.fma.v2f16(<2 x half> %x, <2 x half> <half undef, half -1.0>, <2 x half> %y) 911 ret <2 x half> %sub 912} 913 914; negative tests 915 916define half @fma_non_negone(half %x, half %y) { 917; CHECK-LABEL: @fma_non_negone( 918; CHECK-NEXT: [[SUB:%.*]] = call half @llvm.fma.f16(half [[X:%.*]], half 0xHBE00, half [[Y:%.*]]) 919; CHECK-NEXT: ret half [[SUB]] 920; 921 %sub = call half @llvm.fma.f16(half %x, half -1.5, half %y) 922 ret half %sub 923} 924