return false;
}
+bool isVVPUnaryOp(unsigned VVPOpcode) {
+ switch (VVPOpcode) {
+#define ADD_UNARY_VVP_OP(VVPNAME, ...) \
+ case VEISD::VVPNAME: \
+ return true;
+#include "VVPNodes.def"
+ }
+ return false;
+}
+
bool isVVPBinaryOp(unsigned VVPOpcode) {
switch (VVPOpcode) {
#define ADD_BINARY_VVP_OP(VVPNAME, ...) \
Optional<unsigned> getVVPOpcode(unsigned Opcode);
+bool isVVPUnaryOp(unsigned Opcode);
bool isVVPBinaryOp(unsigned Opcode);
bool isVVPReductionOp(unsigned Opcode);
if (!Mask)
Mask = CDAG.getConstantMask(Packing, true);
- if (isVVPBinaryOp(VVPOpcode)) {
- assert(LegalVecVT.isSimple());
+ assert(LegalVecVT.isSimple());
+ if (isVVPUnaryOp(VVPOpcode))
+ return CDAG.getNode(VVPOpcode, LegalVecVT, {Op->getOperand(0), Mask, AVL});
+ if (isVVPBinaryOp(VVPOpcode))
return CDAG.getNode(VVPOpcode, LegalVecVT,
{Op->getOperand(0), Op->getOperand(1), Mask, AVL});
- }
if (isVVPReductionOp(VVPOpcode)) {
auto SrcHasStart = hasReductionStartParam(Op->getOpcode());
SDValue StartV = SrcHasStart ? Op->getOperand(0) : SDValue();
IsVLVT<4>
]>;
+// UnaryFPOp(x,mask,vl)
+def SDTFPUnaryOpVVP : SDTypeProfile<1, 3, [
+ SDTCisSameAs<0, 1>,
+ SDTCisFP<0>,
+ SDTCisInt<2>,
+ SDTCisSameNumEltsAs<0, 2>,
+ IsVLVT<3>
+]>;
+
// BinaryFPOp(x,y,mask,vl)
def SDTFPBinOpVVP : SDTypeProfile<1, 4, [ // vvp_fadd, etc.
SDTCisSameAs<0, 1>,
def vvp_sra : SDNode<"VEISD::VVP_SRA", SDTIntBinOpVVP>;
def vvp_shl : SDNode<"VEISD::VVP_SHL", SDTIntBinOpVVP>;
+def vvp_fneg : SDNode<"VEISD::VVP_FNEG", SDTFPUnaryOpVVP>;
+
def vvp_fadd : SDNode<"VEISD::VVP_FADD", SDTFPBinOpVVP>;
def c_vvp_fadd : vvp_commutative<vvp_fadd>;
def vvp_fsub : SDNode<"VEISD::VVP_FSUB", SDTFPBinOpVVP>;
defm : VectorScatter<v256i32, v256i64, v256i1, "VSCL">;
+/// FNEG {
+// Directly modify the sign bit to flip the sign.
+
+// Set sign bits in a pack of <2 x f32>.
+def packed_fneg_imm : OutPatFrag<(ins ),
+ (i64 (SLLri (i64 (ORim 1, (i32 32))), 31))>;
+
+
+multiclass FNeg<ValueType DataVT> {
+ // Masked with select.
+ def : Pat<(vvp_select (vvp_fneg DataVT:$vx, (v256i1 srcvalue), (i32 srcvalue)),
+ DataVT:$vfalse,
+ v256i1:$mask,
+ i32:$avl),
+ (VXORmvml_v (i32 1), $vx, $mask, $avl, $vfalse)>;
+
+ // Unmasked.
+ def : Pat<(vvp_fneg DataVT:$vx, (v256i1 true_mask), i32:$avl),
+ (VXORmvl (i32 1), $vx, $avl)>;
+
+ // Masked.
+ def : Pat<(vvp_fneg DataVT:$vx, v256i1:$mask, i32:$avl),
+ (VXORmvml (i32 1), $vx, $mask, $avl)>;
+}
+
+defm: FNeg<v256f32>;
+defm: FNeg<v256f64>;
+
+///// Packed FNeg /////
+
+// Masked with select.
+def : Pat<(vvp_select (vvp_fneg v512f32:$vx, (v512i1 srcvalue), (i32 srcvalue)),
+ v512f32:$vfalse,
+ v512i1:$mask,
+ i32:$avl),
+ (v512f32 (PVXORrvml_v (packed_fneg_imm ), $vx, $mask, $avl, $vfalse))>;
+
+// Unmasked.
+def : Pat<(vvp_fneg v512f32:$vx, (v512i1 true_mask), i32:$avl),
+ (v512f32 (PVXORrvl (packed_fneg_imm ), $vx, $avl))>;
+
+// Masked.
+def : Pat<(vvp_fneg v512f32:$vx, v512i1:$mask, i32:$avl),
+ (v512f32 (PVXORrvml (packed_fneg_imm ), $vx, $mask, $avl))>;
+
+/// } FNEG
+
multiclass Binary_rv<SDPatternOperator OpNode,
ValueType ScalarVT, ValueType DataVT,
ValueType MaskVT, string OpBaseName> {
#define ADD_VVP_OP(X, Y)
#endif
+/// ADD_UNARY_VVP_OP(VVPNAME,SDNAME)
+/// \p VVPName is a VVP Unary operator.
+/// \p SDNAME is the generic SD opcode corresponding to \p VVPName.
+#ifndef ADD_UNARY_VVP_OP
+#define ADD_UNARY_VVP_OP(VVPNAME,SDNAME) \
+ ADD_VVP_OP(VVPNAME,SDNAME)
+#endif
+
/// ADD_BINARY_VVP_OP(VVPNAME,SDNAME)
/// \p VVPName is a VVP Binary operator.
/// \p SDNAME is the generic SD opcode corresponding to \p VVPName.
ADD_BINARY_VVP_OP_COMPACT(XOR) REGISTER_PACKED(VVP_XOR)
// FP arithmetic.
+ADD_UNARY_VVP_OP(VVP_FNEG, FNEG) HANDLE_VP_TO_VVP(VP_FNEG, VVP_FNEG) REGISTER_PACKED(VVP_FNEG)
ADD_BINARY_VVP_OP_COMPACT(FADD) REGISTER_PACKED(VVP_FADD)
ADD_BINARY_VVP_OP_COMPACT(FSUB) REGISTER_PACKED(VVP_FSUB)
ADD_BINARY_VVP_OP_COMPACT(FMUL) REGISTER_PACKED(VVP_FMUL)
#undef ADD_BINARY_VVP_OP
#undef ADD_TERNARY_VVP_OP
+#undef ADD_UNARY_VVP_OP
#undef ADD_BINARY_VVP_OP_COMPACT
#undef ADD_REDUCE_VVP_OP
#undef ADD_VVP_OP
--- /dev/null
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -march=ve -mattr=+vpu | FileCheck %s
+
+define fastcc <512 x float> @test_vec_fneg_v512f32_v(<512 x float> %v) {
+; CHECK-LABEL: test_vec_fneg_v512f32_v:
+; CHECK: # %bb.0:
+; CHECK-NEXT: or %s0, 1, (32)1
+; CHECK-NEXT: sll %s0, %s0, 31
+; CHECK-NEXT: lea %s1, 512
+; CHECK-NEXT: lvl %s1
+; CHECK-NEXT: pvxor %v0, %s0, %v0
+; CHECK-NEXT: b.l.t (, %s10)
+ %neg = fneg <512 x float> %v
+ ret <512 x float> %neg
+}
--- /dev/null
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -march=ve -mattr=+vpu | FileCheck %s
+
+define fastcc <256 x float> @test_vec_fneg_v256f32_v(<256 x float> %v) {
+; CHECK-LABEL: test_vec_fneg_v256f32_v:
+; CHECK: # %bb.0:
+; CHECK-NEXT: lea %s0, 256
+; CHECK-NEXT: lvl %s0
+; CHECK-NEXT: vxor %v0, (1)1, %v0
+; CHECK-NEXT: b.l.t (, %s10)
+ %neg = fneg <256 x float> %v
+ ret <256 x float> %neg
+}
+
+define fastcc <256 x double> @test_vec_fneg_v256f64_v(<256 x double> %v) {
+; CHECK-LABEL: test_vec_fneg_v256f64_v:
+; CHECK: # %bb.0:
+; CHECK-NEXT: lea %s0, 256
+; CHECK-NEXT: lvl %s0
+; CHECK-NEXT: vxor %v0, (1)1, %v0
+; CHECK-NEXT: b.l.t (, %s10)
+ %neg = fneg <256 x double> %v
+ ret <256 x double> %neg
+}
+