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