1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=riscv32 -mattr=+d,+zvfh,+v -target-abi=ilp32d \ 3; RUN: -verify-machineinstrs < %s | FileCheck %s 4; RUN: llc -mtriple=riscv64 -mattr=+d,+zvfh,+v -target-abi=lp64d \ 5; RUN: -verify-machineinstrs < %s | FileCheck %s 6 7; This tests a mix of vfnmacc and vfnmadd by using different operand orders to 8; trigger commuting in TwoAddressInstructionPass. 9 10declare <2 x half> @llvm.experimental.constrained.fma.v2f16(<2 x half>, <2 x half>, <2 x half>, metadata, metadata) 11 12define <2 x half> @vfnmsub_vv_v2f16(<2 x half> %va, <2 x half> %vb, <2 x half> %vc) strictfp { 13; CHECK-LABEL: vfnmsub_vv_v2f16: 14; CHECK: # %bb.0: 15; CHECK-NEXT: vsetivli zero, 2, e16, mf4, ta, ma 16; CHECK-NEXT: vfnmadd.vv v8, v10, v9 17; CHECK-NEXT: ret 18 %neg = fneg <2 x half> %va 19 %neg2 = fneg <2 x half> %vb 20 %vd = call <2 x half> @llvm.experimental.constrained.fma.v2f16(<2 x half> %neg, <2 x half> %vc, <2 x half> %neg2, metadata !"round.dynamic", metadata !"fpexcept.strict") 21 ret <2 x half> %vd 22} 23 24define <2 x half> @vfnmsub_vf_v2f16(<2 x half> %va, <2 x half> %vb, half %c) strictfp { 25; CHECK-LABEL: vfnmsub_vf_v2f16: 26; CHECK: # %bb.0: 27; CHECK-NEXT: vsetivli zero, 2, e16, mf4, ta, ma 28; CHECK-NEXT: vfnmadd.vf v8, fa0, v9 29; CHECK-NEXT: ret 30 %head = insertelement <2 x half> poison, half %c, i32 0 31 %splat = shufflevector <2 x half> %head, <2 x half> poison, <2 x i32> zeroinitializer 32 %neg = fneg <2 x half> %va 33 %neg2 = fneg <2 x half> %vb 34 %vd = call <2 x half> @llvm.experimental.constrained.fma.v2f16(<2 x half> %splat, <2 x half> %neg, <2 x half> %neg2, metadata !"round.dynamic", metadata !"fpexcept.strict") 35 ret <2 x half> %vd 36} 37 38declare <4 x half> @llvm.experimental.constrained.fma.v4f16(<4 x half>, <4 x half>, <4 x half>, metadata, metadata) 39 40define <4 x half> @vfnmsub_vv_v4f16(<4 x half> %va, <4 x half> %vb, <4 x half> %vc) strictfp { 41; CHECK-LABEL: vfnmsub_vv_v4f16: 42; CHECK: # %bb.0: 43; CHECK-NEXT: vsetivli zero, 4, e16, mf2, ta, ma 44; CHECK-NEXT: vfnmadd.vv v8, v9, v10 45; CHECK-NEXT: ret 46 %neg = fneg <4 x half> %vb 47 %neg2 = fneg <4 x half> %vc 48 %vd = call <4 x half> @llvm.experimental.constrained.fma.v4f16(<4 x half> %neg, <4 x half> %va, <4 x half> %neg2, metadata !"round.dynamic", metadata !"fpexcept.strict") 49 ret <4 x half> %vd 50} 51 52define <4 x half> @vfnmsub_vf_v4f16(<4 x half> %va, <4 x half> %vb, half %c) strictfp { 53; CHECK-LABEL: vfnmsub_vf_v4f16: 54; CHECK: # %bb.0: 55; CHECK-NEXT: vsetivli zero, 4, e16, mf2, ta, ma 56; CHECK-NEXT: vfnmadd.vf v8, fa0, v9 57; CHECK-NEXT: ret 58 %head = insertelement <4 x half> poison, half %c, i32 0 59 %splat = shufflevector <4 x half> %head, <4 x half> poison, <4 x i32> zeroinitializer 60 %neg = fneg <4 x half> %splat 61 %neg2 = fneg <4 x half> %vb 62 %vd = call <4 x half> @llvm.experimental.constrained.fma.v4f16(<4 x half> %va, <4 x half> %neg, <4 x half> %neg2, metadata !"round.dynamic", metadata !"fpexcept.strict") 63 ret <4 x half> %vd 64} 65 66declare <8 x half> @llvm.experimental.constrained.fma.v8f16(<8 x half>, <8 x half>, <8 x half>, metadata, metadata) 67 68define <8 x half> @vfnmsub_vv_v8f16(<8 x half> %va, <8 x half> %vb, <8 x half> %vc) strictfp { 69; CHECK-LABEL: vfnmsub_vv_v8f16: 70; CHECK: # %bb.0: 71; CHECK-NEXT: vsetivli zero, 8, e16, m1, ta, ma 72; CHECK-NEXT: vfnmacc.vv v8, v10, v9 73; CHECK-NEXT: ret 74 %neg = fneg <8 x half> %vb 75 %neg2 = fneg <8 x half> %va 76 %vd = call <8 x half> @llvm.experimental.constrained.fma.v8f16(<8 x half> %neg, <8 x half> %vc, <8 x half> %neg2, metadata !"round.dynamic", metadata !"fpexcept.strict") 77 ret <8 x half> %vd 78} 79 80define <8 x half> @vfnmsub_vf_v8f16(<8 x half> %va, <8 x half> %vb, half %c) strictfp { 81; CHECK-LABEL: vfnmsub_vf_v8f16: 82; CHECK: # %bb.0: 83; CHECK-NEXT: vsetivli zero, 8, e16, m1, ta, ma 84; CHECK-NEXT: vfnmacc.vf v8, fa0, v9 85; CHECK-NEXT: ret 86 %head = insertelement <8 x half> poison, half %c, i32 0 87 %splat = shufflevector <8 x half> %head, <8 x half> poison, <8 x i32> zeroinitializer 88 %neg = fneg <8 x half> %splat 89 %neg2 = fneg <8 x half> %va 90 %vd = call <8 x half> @llvm.experimental.constrained.fma.v8f16(<8 x half> %vb, <8 x half> %neg, <8 x half> %neg2, metadata !"round.dynamic", metadata !"fpexcept.strict") 91 ret <8 x half> %vd 92} 93 94declare <16 x half> @llvm.experimental.constrained.fma.v16f16(<16 x half>, <16 x half>, <16 x half>, metadata, metadata) 95 96define <16 x half> @vfnmsub_vv_v16f16(<16 x half> %va, <16 x half> %vb, <16 x half> %vc) strictfp { 97; CHECK-LABEL: vfnmsub_vv_v16f16: 98; CHECK: # %bb.0: 99; CHECK-NEXT: vsetivli zero, 16, e16, m2, ta, ma 100; CHECK-NEXT: vfnmadd.vv v8, v12, v10 101; CHECK-NEXT: ret 102 %neg = fneg <16 x half> %vc 103 %neg2 = fneg <16 x half> %vb 104 %vd = call <16 x half> @llvm.experimental.constrained.fma.v16f16(<16 x half> %neg, <16 x half> %va, <16 x half> %neg2, metadata !"round.dynamic", metadata !"fpexcept.strict") 105 ret <16 x half> %vd 106} 107 108define <16 x half> @vfnmsub_vf_v16f16(<16 x half> %va, <16 x half> %vb, half %c) strictfp { 109; CHECK-LABEL: vfnmsub_vf_v16f16: 110; CHECK: # %bb.0: 111; CHECK-NEXT: vsetivli zero, 16, e16, m2, ta, ma 112; CHECK-NEXT: vfnmadd.vf v8, fa0, v10 113; CHECK-NEXT: ret 114 %head = insertelement <16 x half> poison, half %c, i32 0 115 %splat = shufflevector <16 x half> %head, <16 x half> poison, <16 x i32> zeroinitializer 116 %neg = fneg <16 x half> %splat 117 %neg2 = fneg <16 x half> %vb 118 %vd = call <16 x half> @llvm.experimental.constrained.fma.v16f16(<16 x half> %neg, <16 x half> %va, <16 x half> %neg2, metadata !"round.dynamic", metadata !"fpexcept.strict") 119 ret <16 x half> %vd 120} 121 122declare <32 x half> @llvm.experimental.constrained.fma.v32f16(<32 x half>, <32 x half>, <32 x half>, metadata, metadata) 123 124define <32 x half> @vfnmsub_vv_v32f16(<32 x half> %va, <32 x half> %vb, <32 x half> %vc) strictfp { 125; CHECK-LABEL: vfnmsub_vv_v32f16: 126; CHECK: # %bb.0: 127; CHECK-NEXT: li a0, 32 128; CHECK-NEXT: vsetvli zero, a0, e16, m4, ta, ma 129; CHECK-NEXT: vfnmadd.vv v8, v16, v12 130; CHECK-NEXT: ret 131 %neg = fneg <32 x half> %vc 132 %neg2 = fneg <32 x half> %vb 133 %vd = call <32 x half> @llvm.experimental.constrained.fma.v32f16(<32 x half> %neg, <32 x half> %va, <32 x half> %neg2, metadata !"round.dynamic", metadata !"fpexcept.strict") 134 ret <32 x half> %vd 135} 136 137define <32 x half> @vfnmsub_vf_v32f16(<32 x half> %va, <32 x half> %vb, half %c) strictfp { 138; CHECK-LABEL: vfnmsub_vf_v32f16: 139; CHECK: # %bb.0: 140; CHECK-NEXT: li a0, 32 141; CHECK-NEXT: vsetvli zero, a0, e16, m4, ta, ma 142; CHECK-NEXT: vfnmacc.vf v8, fa0, v12 143; CHECK-NEXT: ret 144 %head = insertelement <32 x half> poison, half %c, i32 0 145 %splat = shufflevector <32 x half> %head, <32 x half> poison, <32 x i32> zeroinitializer 146 %neg = fneg <32 x half> %splat 147 %neg2 = fneg <32 x half> %va 148 %vd = call <32 x half> @llvm.experimental.constrained.fma.v32f16(<32 x half> %neg, <32 x half> %vb, <32 x half> %neg2, metadata !"round.dynamic", metadata !"fpexcept.strict") 149 ret <32 x half> %vd 150} 151 152declare <2 x float> @llvm.experimental.constrained.fma.v2f32(<2 x float>, <2 x float>, <2 x float>, metadata, metadata) 153 154define <2 x float> @vfnmsub_vv_v2f32(<2 x float> %va, <2 x float> %vb, <2 x float> %vc) strictfp { 155; CHECK-LABEL: vfnmsub_vv_v2f32: 156; CHECK: # %bb.0: 157; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma 158; CHECK-NEXT: vfnmadd.vv v8, v10, v9 159; CHECK-NEXT: ret 160 %neg = fneg <2 x float> %vc 161 %neg2 = fneg <2 x float> %vb 162 %vd = call <2 x float> @llvm.experimental.constrained.fma.v2f32(<2 x float> %va, <2 x float> %neg, <2 x float> %neg2, metadata !"round.dynamic", metadata !"fpexcept.strict") 163 ret <2 x float> %vd 164} 165 166define <2 x float> @vfnmsub_vf_v2f32(<2 x float> %va, <2 x float> %vb, float %c) strictfp { 167; CHECK-LABEL: vfnmsub_vf_v2f32: 168; CHECK: # %bb.0: 169; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma 170; CHECK-NEXT: vfnmadd.vf v8, fa0, v9 171; CHECK-NEXT: ret 172 %head = insertelement <2 x float> poison, float %c, i32 0 173 %splat = shufflevector <2 x float> %head, <2 x float> poison, <2 x i32> zeroinitializer 174 %neg = fneg <2 x float> %va 175 %neg2 = fneg <2 x float> %vb 176 %vd = call <2 x float> @llvm.experimental.constrained.fma.v2f32(<2 x float> %splat, <2 x float> %neg, <2 x float> %neg2, metadata !"round.dynamic", metadata !"fpexcept.strict") 177 ret <2 x float> %vd 178} 179 180declare <4 x float> @llvm.experimental.constrained.fma.v4f32(<4 x float>, <4 x float>, <4 x float>, metadata, metadata) 181 182define <4 x float> @vfnmsub_vv_v4f32(<4 x float> %va, <4 x float> %vb, <4 x float> %vc) strictfp { 183; CHECK-LABEL: vfnmsub_vv_v4f32: 184; CHECK: # %bb.0: 185; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma 186; CHECK-NEXT: vfnmadd.vv v8, v9, v10 187; CHECK-NEXT: ret 188 %neg = fneg <4 x float> %va 189 %neg2 = fneg <4 x float> %vc 190 %vd = call <4 x float> @llvm.experimental.constrained.fma.v4f32(<4 x float> %vb, <4 x float> %neg, <4 x float> %neg2, metadata !"round.dynamic", metadata !"fpexcept.strict") 191 ret <4 x float> %vd 192} 193 194define <4 x float> @vfnmsub_vf_v4f32(<4 x float> %va, <4 x float> %vb, float %c) strictfp { 195; CHECK-LABEL: vfnmsub_vf_v4f32: 196; CHECK: # %bb.0: 197; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma 198; CHECK-NEXT: vfnmadd.vf v8, fa0, v9 199; CHECK-NEXT: ret 200 %head = insertelement <4 x float> poison, float %c, i32 0 201 %splat = shufflevector <4 x float> %head, <4 x float> poison, <4 x i32> zeroinitializer 202 %neg = fneg <4 x float> %splat 203 %neg2 = fneg <4 x float> %vb 204 %vd = call <4 x float> @llvm.experimental.constrained.fma.v4f32(<4 x float> %va, <4 x float> %neg, <4 x float> %neg2, metadata !"round.dynamic", metadata !"fpexcept.strict") 205 ret <4 x float> %vd 206} 207 208declare <8 x float> @llvm.experimental.constrained.fma.v8f32(<8 x float>, <8 x float>, <8 x float>, metadata, metadata) 209 210define <8 x float> @vfnmsub_vv_v8f32(<8 x float> %va, <8 x float> %vb, <8 x float> %vc) strictfp { 211; CHECK-LABEL: vfnmsub_vv_v8f32: 212; CHECK: # %bb.0: 213; CHECK-NEXT: vsetivli zero, 8, e32, m2, ta, ma 214; CHECK-NEXT: vfnmacc.vv v8, v12, v10 215; CHECK-NEXT: ret 216 %neg = fneg <8 x float> %vc 217 %neg2 = fneg <8 x float> %va 218 %vd = call <8 x float> @llvm.experimental.constrained.fma.v8f32(<8 x float> %vb, <8 x float> %neg, <8 x float> %neg2, metadata !"round.dynamic", metadata !"fpexcept.strict") 219 ret <8 x float> %vd 220} 221 222define <8 x float> @vfnmsub_vf_v8f32(<8 x float> %va, <8 x float> %vb, float %c) strictfp { 223; CHECK-LABEL: vfnmsub_vf_v8f32: 224; CHECK: # %bb.0: 225; CHECK-NEXT: vsetivli zero, 8, e32, m2, ta, ma 226; CHECK-NEXT: vfnmacc.vf v8, fa0, v10 227; CHECK-NEXT: ret 228 %head = insertelement <8 x float> poison, float %c, i32 0 229 %splat = shufflevector <8 x float> %head, <8 x float> poison, <8 x i32> zeroinitializer 230 %neg = fneg <8 x float> %splat 231 %neg2 = fneg <8 x float> %va 232 %vd = call <8 x float> @llvm.experimental.constrained.fma.v8f32(<8 x float> %vb, <8 x float> %neg, <8 x float> %neg2, metadata !"round.dynamic", metadata !"fpexcept.strict") 233 ret <8 x float> %vd 234} 235 236declare <16 x float> @llvm.experimental.constrained.fma.v16f32(<16 x float>, <16 x float>, <16 x float>, metadata, metadata) 237 238define <16 x float> @vfnmsub_vv_v16f32(<16 x float> %va, <16 x float> %vb, <16 x float> %vc) strictfp { 239; CHECK-LABEL: vfnmsub_vv_v16f32: 240; CHECK: # %bb.0: 241; CHECK-NEXT: vsetivli zero, 16, e32, m4, ta, ma 242; CHECK-NEXT: vfnmadd.vv v8, v16, v12 243; CHECK-NEXT: ret 244 %neg = fneg <16 x float> %va 245 %neg2 = fneg <16 x float> %vb 246 %vd = call <16 x float> @llvm.experimental.constrained.fma.v16f32(<16 x float> %vc, <16 x float> %neg, <16 x float> %neg2, metadata !"round.dynamic", metadata !"fpexcept.strict") 247 ret <16 x float> %vd 248} 249 250define <16 x float> @vfnmsub_vf_v16f32(<16 x float> %va, <16 x float> %vb, float %c) strictfp { 251; CHECK-LABEL: vfnmsub_vf_v16f32: 252; CHECK: # %bb.0: 253; CHECK-NEXT: vsetivli zero, 16, e32, m4, ta, ma 254; CHECK-NEXT: vfnmadd.vf v8, fa0, v12 255; CHECK-NEXT: ret 256 %head = insertelement <16 x float> poison, float %c, i32 0 257 %splat = shufflevector <16 x float> %head, <16 x float> poison, <16 x i32> zeroinitializer 258 %neg = fneg <16 x float> %splat 259 %neg2 = fneg <16 x float> %vb 260 %vd = call <16 x float> @llvm.experimental.constrained.fma.v16f32(<16 x float> %neg, <16 x float> %va, <16 x float> %neg2, metadata !"round.dynamic", metadata !"fpexcept.strict") 261 ret <16 x float> %vd 262} 263 264declare <2 x double> @llvm.experimental.constrained.fma.v2f64(<2 x double>, <2 x double>, <2 x double>, metadata, metadata) 265 266define <2 x double> @vfnmsub_vv_v2f64(<2 x double> %va, <2 x double> %vb, <2 x double> %vc) strictfp { 267; CHECK-LABEL: vfnmsub_vv_v2f64: 268; CHECK: # %bb.0: 269; CHECK-NEXT: vsetivli zero, 2, e64, m1, ta, ma 270; CHECK-NEXT: vfnmadd.vv v8, v10, v9 271; CHECK-NEXT: ret 272 %neg = fneg <2 x double> %va 273 %neg2 = fneg <2 x double> %vb 274 %vd = call <2 x double> @llvm.experimental.constrained.fma.v2f64(<2 x double> %neg, <2 x double> %vc, <2 x double> %neg2, metadata !"round.dynamic", metadata !"fpexcept.strict") 275 ret <2 x double> %vd 276} 277 278define <2 x double> @vfnmsub_vf_v2f64(<2 x double> %va, <2 x double> %vb, double %c) strictfp { 279; CHECK-LABEL: vfnmsub_vf_v2f64: 280; CHECK: # %bb.0: 281; CHECK-NEXT: vsetivli zero, 2, e64, m1, ta, ma 282; CHECK-NEXT: vfnmadd.vf v8, fa0, v9 283; CHECK-NEXT: ret 284 %head = insertelement <2 x double> poison, double %c, i32 0 285 %splat = shufflevector <2 x double> %head, <2 x double> poison, <2 x i32> zeroinitializer 286 %neg = fneg <2 x double> %va 287 %neg2 = fneg <2 x double> %vb 288 %vd = call <2 x double> @llvm.experimental.constrained.fma.v2f64(<2 x double> %splat, <2 x double> %neg, <2 x double> %neg2, metadata !"round.dynamic", metadata !"fpexcept.strict") 289 ret <2 x double> %vd 290} 291 292declare <4 x double> @llvm.experimental.constrained.fma.v4f64(<4 x double>, <4 x double>, <4 x double>, metadata, metadata) 293 294define <4 x double> @vfnmsub_vv_v4f64(<4 x double> %va, <4 x double> %vb, <4 x double> %vc) strictfp { 295; CHECK-LABEL: vfnmsub_vv_v4f64: 296; CHECK: # %bb.0: 297; CHECK-NEXT: vsetivli zero, 4, e64, m2, ta, ma 298; CHECK-NEXT: vfnmadd.vv v8, v10, v12 299; CHECK-NEXT: ret 300 %neg = fneg <4 x double> %vb 301 %neg2 = fneg <4 x double> %vc 302 %vd = call <4 x double> @llvm.experimental.constrained.fma.v4f64(<4 x double> %neg, <4 x double> %va, <4 x double> %neg2, metadata !"round.dynamic", metadata !"fpexcept.strict") 303 ret <4 x double> %vd 304} 305 306define <4 x double> @vfnmsub_vf_v4f64(<4 x double> %va, <4 x double> %vb, double %c) strictfp { 307; CHECK-LABEL: vfnmsub_vf_v4f64: 308; CHECK: # %bb.0: 309; CHECK-NEXT: vsetivli zero, 4, e64, m2, ta, ma 310; CHECK-NEXT: vfnmadd.vf v8, fa0, v10 311; CHECK-NEXT: ret 312 %head = insertelement <4 x double> poison, double %c, i32 0 313 %splat = shufflevector <4 x double> %head, <4 x double> poison, <4 x i32> zeroinitializer 314 %neg = fneg <4 x double> %splat 315 %neg2 = fneg <4 x double> %vb 316 %vd = call <4 x double> @llvm.experimental.constrained.fma.v4f64(<4 x double> %va, <4 x double> %neg, <4 x double> %neg2, metadata !"round.dynamic", metadata !"fpexcept.strict") 317 ret <4 x double> %vd 318} 319 320declare <8 x double> @llvm.experimental.constrained.fma.v8f64(<8 x double>, <8 x double>, <8 x double>, metadata, metadata) 321 322define <8 x double> @vfnmsub_vv_v8f64(<8 x double> %va, <8 x double> %vb, <8 x double> %vc) strictfp { 323; CHECK-LABEL: vfnmsub_vv_v8f64: 324; CHECK: # %bb.0: 325; CHECK-NEXT: vsetivli zero, 8, e64, m4, ta, ma 326; CHECK-NEXT: vfnmacc.vv v8, v16, v12 327; CHECK-NEXT: ret 328 %neg = fneg <8 x double> %vb 329 %neg2 = fneg <8 x double> %va 330 %vd = call <8 x double> @llvm.experimental.constrained.fma.v8f64(<8 x double> %neg, <8 x double> %vc, <8 x double> %neg2, metadata !"round.dynamic", metadata !"fpexcept.strict") 331 ret <8 x double> %vd 332} 333 334define <8 x double> @vfnmsub_vf_v8f64(<8 x double> %va, <8 x double> %vb, double %c) strictfp { 335; CHECK-LABEL: vfnmsub_vf_v8f64: 336; CHECK: # %bb.0: 337; CHECK-NEXT: vsetivli zero, 8, e64, m4, ta, ma 338; CHECK-NEXT: vfnmacc.vf v8, fa0, v12 339; CHECK-NEXT: ret 340 %head = insertelement <8 x double> poison, double %c, i32 0 341 %splat = shufflevector <8 x double> %head, <8 x double> poison, <8 x i32> zeroinitializer 342 %neg = fneg <8 x double> %splat 343 %neg2 = fneg <8 x double> %va 344 %vd = call <8 x double> @llvm.experimental.constrained.fma.v8f64(<8 x double> %vb, <8 x double> %neg, <8 x double> %neg2, metadata !"round.dynamic", metadata !"fpexcept.strict") 345 ret <8 x double> %vd 346} 347