summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r--llvm/lib/Target/ARM/ARMISelLowering.cpp4
-rw-r--r--llvm/lib/Target/ARM/ARMInstrMVE.td212
2 files changed, 157 insertions, 59 deletions
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index db26feb5701..615a09e1601 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -3698,6 +3698,10 @@ ARMTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG,
case Intrinsic::arm_neon_vtbl2:
return DAG.getNode(ARMISD::VTBL2, SDLoc(Op), Op.getValueType(),
Op.getOperand(1), Op.getOperand(2), Op.getOperand(3));
+ case Intrinsic::arm_mve_pred_i2v:
+ case Intrinsic::arm_mve_pred_v2i:
+ return DAG.getNode(ARMISD::PREDICATE_CAST, SDLoc(Op), Op.getValueType(),
+ Op.getOperand(1));
}
}
diff --git a/llvm/lib/Target/ARM/ARMInstrMVE.td b/llvm/lib/Target/ARM/ARMInstrMVE.td
index 4f67cd6e47c..7d49df3d0c0 100644
--- a/llvm/lib/Target/ARM/ARMInstrMVE.td
+++ b/llvm/lib/Target/ARM/ARMInstrMVE.td
@@ -275,6 +275,62 @@ class mve_addr_q_shift<int shift> : MemOperand {
let MIOperandInfo = (ops MQPR:$base, i32imm:$imm);
}
+// A family of classes wrapping up information about the vector types
+// used by MVE.
+class MVEVectorVTInfo<ValueType vec, ValueType pred, bits<2> size,
+ string suffix, bit unsigned> {
+ // The LLVM ValueType representing the vector, so we can use it in
+ // ISel patterns.
+ ValueType Vec = vec;
+
+ // An LLVM ValueType representing a corresponding vector of
+ // predicate bits, for use in ISel patterns that handle an IR
+ // intrinsic describing the predicated form of the instruction.
+ //
+ // Usually, for a vector of N things, this will be vNi1. But for
+ // vectors of 2 values, we make an exception, and use v4i1 instead
+ // of v2i1. Rationale: MVE codegen doesn't support doing all the
+ // auxiliary operations on v2i1 (vector shuffles etc), and also,
+ // there's no MVE compare instruction that will _generate_ v2i1
+ // directly.
+ ValueType Pred = pred;
+
+ // The most common representation of the vector element size in MVE
+ // instruction encodings: a 2-bit value V representing an (8<<V)-bit
+ // vector element.
+ bits<2> Size = size;
+
+ // For vectors explicitly mentioning a signedness of integers: 0 for
+ // signed and 1 for unsigned. For anything else, undefined.
+ bit Unsigned = unsigned;
+
+ // The suffix used on the instruction in assembly language.
+ string Suffix = suffix;
+}
+
+// Integer vector types that don't treat signed and unsigned differently.
+def MVE_v16i8 : MVEVectorVTInfo<v16i8, v16i1, 0b00, "i8", ?>;
+def MVE_v8i16 : MVEVectorVTInfo<v8i16, v8i1, 0b01, "i16", ?>;
+def MVE_v4i32 : MVEVectorVTInfo<v4i32, v4i1, 0b10, "i32", ?>;
+def MVE_v2i64 : MVEVectorVTInfo<v2i64, v4i1, 0b11, "i64", ?>;
+
+// Explicitly signed and unsigned integer vectors. They map to the
+// same set of LLVM ValueTypes as above, but are represented
+// differently in assembly and instruction encodings.
+def MVE_v16s8 : MVEVectorVTInfo<v16i8, v16i1, 0b00, "s8", 0b0>;
+def MVE_v8s16 : MVEVectorVTInfo<v8i16, v8i1, 0b01, "s16", 0b0>;
+def MVE_v4s32 : MVEVectorVTInfo<v4i32, v4i1, 0b10, "s32", 0b0>;
+def MVE_v2s64 : MVEVectorVTInfo<v2i64, v4i1, 0b11, "s64", 0b0>;
+def MVE_v16u8 : MVEVectorVTInfo<v16i8, v16i1, 0b00, "u8", 0b1>;
+def MVE_v8u16 : MVEVectorVTInfo<v8i16, v8i1, 0b01, "u16", 0b1>;
+def MVE_v4u32 : MVEVectorVTInfo<v4i32, v4i1, 0b10, "u32", 0b1>;
+def MVE_v2u64 : MVEVectorVTInfo<v2i64, v4i1, 0b11, "u64", 0b1>;
+
+// FP vector types.
+def MVE_v8f16 : MVEVectorVTInfo<v8f16, v8i1, 0b01, "f16", ?>;
+def MVE_v4f32 : MVEVectorVTInfo<v4f32, v4i1, 0b10, "f32", ?>;
+def MVE_v2f64 : MVEVectorVTInfo<v2f64, v4i1, 0b11, "f64", ?>;
+
// --------- Start of base classes for the instructions themselves
class MVE_MI<dag oops, dag iops, InstrItinClass itin, string asm,
@@ -658,17 +714,31 @@ class MVE_VMINMAXV<string iname, string suffix, bit U, bits<2> size,
let Inst{0} = 0b0;
}
-multiclass MVE_VMINMAXV_ty<string iname, bit bit_7, list<dag> pattern=[]> {
- def s8 : MVE_VMINMAXV<iname, "s8", 0b0, 0b00, 0b1, bit_7>;
- def s16 : MVE_VMINMAXV<iname, "s16", 0b0, 0b01, 0b1, bit_7>;
- def s32 : MVE_VMINMAXV<iname, "s32", 0b0, 0b10, 0b1, bit_7>;
- def u8 : MVE_VMINMAXV<iname, "u8", 0b1, 0b00, 0b1, bit_7>;
- def u16 : MVE_VMINMAXV<iname, "u16", 0b1, 0b01, 0b1, bit_7>;
- def u32 : MVE_VMINMAXV<iname, "u32", 0b1, 0b10, 0b1, bit_7>;
+multiclass MVE_VMINMAXV_p<string iname, bit bit_17, bit bit_7,
+ MVEVectorVTInfo VTI, Intrinsic intr> {
+ def "": MVE_VMINMAXV<iname, VTI.Suffix, VTI.Unsigned, VTI.Size,
+ bit_17, bit_7>;
+
+ let Predicates = [HasMVEInt] in
+ def _pat : Pat<(i32 (intr (i32 rGPR:$prev), (VTI.Vec MQPR:$vec))),
+ (i32 (!cast<Instruction>(NAME)
+ (i32 rGPR:$prev), (VTI.Vec MQPR:$vec)))>;
}
-defm MVE_VMINV : MVE_VMINMAXV_ty<"vminv", 0b1>;
-defm MVE_VMAXV : MVE_VMINMAXV_ty<"vmaxv", 0b0>;
+multiclass MVE_VMINMAXV_ty<string iname, bit bit_7,
+ Intrinsic intr_s, Intrinsic intr_u> {
+ defm s8 : MVE_VMINMAXV_p<iname, 1, bit_7, MVE_v16s8, intr_s>;
+ defm s16: MVE_VMINMAXV_p<iname, 1, bit_7, MVE_v8s16, intr_s>;
+ defm s32: MVE_VMINMAXV_p<iname, 1, bit_7, MVE_v4s32, intr_s>;
+ defm u8 : MVE_VMINMAXV_p<iname, 1, bit_7, MVE_v16u8, intr_u>;
+ defm u16: MVE_VMINMAXV_p<iname, 1, bit_7, MVE_v8u16, intr_u>;
+ defm u32: MVE_VMINMAXV_p<iname, 1, bit_7, MVE_v4u32, intr_u>;
+}
+
+defm MVE_VMINV : MVE_VMINMAXV_ty<
+ "vminv", 0b1, int_arm_mve_minv_s, int_arm_mve_minv_u>;
+defm MVE_VMAXV : MVE_VMINMAXV_ty<
+ "vmaxv", 0b0, int_arm_mve_maxv_s, int_arm_mve_maxv_u>;
let Predicates = [HasMVEInt] in {
def : Pat<(i32 (vecreduce_smax (v16i8 MQPR:$src))),
@@ -1491,36 +1561,38 @@ class MVE_VADDSUB<string iname, string suffix, bits<2> size, bit subtract,
let validForTailPredication = 1;
}
-class MVE_VADD<string suffix, bits<2> size, list<dag> pattern=[]>
- : MVE_VADDSUB<"vadd", suffix, size, 0b0, pattern>;
-class MVE_VSUB<string suffix, bits<2> size, list<dag> pattern=[]>
- : MVE_VADDSUB<"vsub", suffix, size, 0b1, pattern>;
+multiclass MVE_VADDSUB_m<string iname, MVEVectorVTInfo VTI, bit subtract,
+ SDNode unpred_op, Intrinsic pred_int> {
+ def "" : MVE_VADDSUB<iname, VTI.Suffix, VTI.Size, subtract>;
-def MVE_VADDi8 : MVE_VADD<"i8", 0b00>;
-def MVE_VADDi16 : MVE_VADD<"i16", 0b01>;
-def MVE_VADDi32 : MVE_VADD<"i32", 0b10>;
+ let Predicates = [HasMVEInt] in {
+ // Unpredicated add/subtract
+ def : Pat<(VTI.Vec (unpred_op (VTI.Vec MQPR:$Qm), (VTI.Vec MQPR:$Qn))),
+ (VTI.Vec (!cast<Instruction>(NAME)
+ (VTI.Vec MQPR:$Qm), (VTI.Vec MQPR:$Qn)))>;
-let Predicates = [HasMVEInt] in {
- def : Pat<(v16i8 (add (v16i8 MQPR:$val1), (v16i8 MQPR:$val2))),
- (v16i8 (MVE_VADDi8 (v16i8 MQPR:$val1), (v16i8 MQPR:$val2)))>;
- def : Pat<(v8i16 (add (v8i16 MQPR:$val1), (v8i16 MQPR:$val2))),
- (v8i16 (MVE_VADDi16 (v8i16 MQPR:$val1), (v8i16 MQPR:$val2)))>;
- def : Pat<(v4i32 (add (v4i32 MQPR:$val1), (v4i32 MQPR:$val2))),
- (v4i32 (MVE_VADDi32 (v4i32 MQPR:$val1), (v4i32 MQPR:$val2)))>;
+ // Predicated add/subtract
+ def : Pat<(VTI.Vec (pred_int (VTI.Vec MQPR:$Qm), (VTI.Vec MQPR:$Qn),
+ (VTI.Pred VCCR:$mask), (VTI.Vec MQPR:$inactive))),
+ (VTI.Vec (!cast<Instruction>(NAME)
+ (VTI.Vec MQPR:$Qm), (VTI.Vec MQPR:$Qn),
+ (i32 1), (VTI.Pred VCCR:$mask),
+ (VTI.Vec MQPR:$inactive)))>;
+ }
}
-def MVE_VSUBi8 : MVE_VSUB<"i8", 0b00>;
-def MVE_VSUBi16 : MVE_VSUB<"i16", 0b01>;
-def MVE_VSUBi32 : MVE_VSUB<"i32", 0b10>;
+multiclass MVE_VADD<MVEVectorVTInfo VTI>
+ : MVE_VADDSUB_m<"vadd", VTI, 0b0, add, int_arm_mve_add_predicated>;
+multiclass MVE_VSUB<MVEVectorVTInfo VTI>
+ : MVE_VADDSUB_m<"vsub", VTI, 0b1, sub, int_arm_mve_sub_predicated>;
-let Predicates = [HasMVEInt] in {
- def : Pat<(v16i8 (sub (v16i8 MQPR:$val1), (v16i8 MQPR:$val2))),
- (v16i8 (MVE_VSUBi8 (v16i8 MQPR:$val1), (v16i8 MQPR:$val2)))>;
- def : Pat<(v8i16 (sub (v8i16 MQPR:$val1), (v8i16 MQPR:$val2))),
- (v8i16 (MVE_VSUBi16 (v8i16 MQPR:$val1), (v8i16 MQPR:$val2)))>;
- def : Pat<(v4i32 (sub (v4i32 MQPR:$val1), (v4i32 MQPR:$val2))),
- (v4i32 (MVE_VSUBi32 (v4i32 MQPR:$val1), (v4i32 MQPR:$val2)))>;
-}
+defm MVE_VADDi8 : MVE_VADD<MVE_v16i8>;
+defm MVE_VADDi16 : MVE_VADD<MVE_v8i16>;
+defm MVE_VADDi32 : MVE_VADD<MVE_v4i32>;
+
+defm MVE_VSUBi8 : MVE_VSUB<MVE_v16i8>;
+defm MVE_VSUBi16 : MVE_VSUB<MVE_v8i16>;
+defm MVE_VSUBi32 : MVE_VSUB<MVE_v4i32>;
class MVE_VQADDSUB<string iname, string suffix, bit U, bit subtract,
bits<2> size, ValueType vt>
@@ -2763,31 +2835,35 @@ let Predicates = [HasMVEFloat] in {
(v4f32 (MVE_VFMAf32 $src3, $src1, $src2))>;
}
+multiclass MVE_VADDSUB_fp_m<string iname, bit bit_21, MVEVectorVTInfo VTI,
+ SDNode unpred_op, Intrinsic pred_int> {
+ def "" : MVE_VADDSUBFMA_fp<iname, VTI.Suffix, VTI.Size{0}, 0, 1, bit_21> {
+ let validForTailPredication = 1;
+ }
-let validForTailPredication = 1 in {
- def MVE_VADDf32 : MVE_VADDSUBFMA_fp<"vadd", "f32", 0b0, 0b0, 0b1, 0b0>;
- def MVE_VADDf16 : MVE_VADDSUBFMA_fp<"vadd", "f16", 0b1, 0b0, 0b1, 0b0>;
-}
-
-let Predicates = [HasMVEFloat] in {
- def : Pat<(v4f32 (fadd (v4f32 MQPR:$val1), (v4f32 MQPR:$val2))),
- (v4f32 (MVE_VADDf32 (v4f32 MQPR:$val1), (v4f32 MQPR:$val2)))>;
- def : Pat<(v8f16 (fadd (v8f16 MQPR:$val1), (v8f16 MQPR:$val2))),
- (v8f16 (MVE_VADDf16 (v8f16 MQPR:$val1), (v8f16 MQPR:$val2)))>;
+ let Predicates = [HasMVEFloat] in {
+ def : Pat<(VTI.Vec (unpred_op (VTI.Vec MQPR:$Qm), (VTI.Vec MQPR:$Qn))),
+ (VTI.Vec (!cast<Instruction>(NAME)
+ (VTI.Vec MQPR:$Qm), (VTI.Vec MQPR:$Qn)))>;
+ def : Pat<(VTI.Vec (pred_int (VTI.Vec MQPR:$Qm), (VTI.Vec MQPR:$Qn),
+ (VTI.Pred VCCR:$mask), (VTI.Vec MQPR:$inactive))),
+ (VTI.Vec (!cast<Instruction>(NAME)
+ (VTI.Vec MQPR:$Qm), (VTI.Vec MQPR:$Qn),
+ (i32 1), (VTI.Pred VCCR:$mask),
+ (VTI.Vec MQPR:$inactive)))>;
+ }
}
+multiclass MVE_VADD_fp_m<MVEVectorVTInfo VTI>
+ : MVE_VADDSUB_fp_m<"vadd", 0, VTI, fadd, int_arm_mve_add_predicated>;
+multiclass MVE_VSUB_fp_m<MVEVectorVTInfo VTI>
+ : MVE_VADDSUB_fp_m<"vsub", 1, VTI, fsub, int_arm_mve_sub_predicated>;
-let validForTailPredication = 1 in {
- def MVE_VSUBf32 : MVE_VADDSUBFMA_fp<"vsub", "f32", 0b0, 0b0, 0b1, 0b1>;
- def MVE_VSUBf16 : MVE_VADDSUBFMA_fp<"vsub", "f16", 0b1, 0b0, 0b1, 0b1>;
-}
+defm MVE_VADDf32 : MVE_VADD_fp_m<MVE_v4f32>;
+defm MVE_VADDf16 : MVE_VADD_fp_m<MVE_v8f16>;
-let Predicates = [HasMVEFloat] in {
- def : Pat<(v4f32 (fsub (v4f32 MQPR:$val1), (v4f32 MQPR:$val2))),
- (v4f32 (MVE_VSUBf32 (v4f32 MQPR:$val1), (v4f32 MQPR:$val2)))>;
- def : Pat<(v8f16 (fsub (v8f16 MQPR:$val1), (v8f16 MQPR:$val2))),
- (v8f16 (MVE_VSUBf16 (v8f16 MQPR:$val1), (v8f16 MQPR:$val2)))>;
-}
+defm MVE_VSUBf32 : MVE_VSUB_fp_m<MVE_v4f32>;
+defm MVE_VSUBf16 : MVE_VSUB_fp_m<MVE_v8f16>;
class MVE_VCADD<string suffix, bit size, string cstr="", list<dag> pattern=[]>
: MVEFloatArithNeon<"vcadd", suffix, size, (outs MQPR:$Qd),
@@ -3551,13 +3627,31 @@ class MVE_VCVT_ff<string iname, string suffix, bit op, bit T,
let Predicates = [HasMVEFloat];
}
-multiclass MVE_VCVT_ff_halves<string suffix, bit op> {
- def bh : MVE_VCVT_ff<"vcvtb", suffix, op, 0b0>;
- def th : MVE_VCVT_ff<"vcvtt", suffix, op, 0b1>;
+multiclass MVE_VCVT_f2h_m<string iname, int half> {
+ def "": MVE_VCVT_ff<iname, "f16.f32", 0b0, half>;
+
+ let Predicates = [HasMVEFloat] in {
+ def : Pat<(v8f16 (int_arm_mve_vcvt_narrow
+ (v8f16 MQPR:$Qd_src), (v4f32 MQPR:$Qm), (i32 half))),
+ (v8f16 (!cast<Instruction>(NAME)
+ (v8f16 MQPR:$Qd_src), (v4f32 MQPR:$Qm)))>;
+ def : Pat<(v8f16 (int_arm_mve_vcvt_narrow_predicated
+ (v8f16 MQPR:$Qd_src), (v4f32 MQPR:$Qm), (i32 half),
+ (v4i1 VCCR:$mask))),
+ (v8f16 (!cast<Instruction>(NAME)
+ (v8f16 MQPR:$Qd_src), (v4f32 MQPR:$Qm),
+ (i32 1), (v4i1 VCCR:$mask)))>;
+ }
+}
+
+multiclass MVE_VCVT_h2f_m<string iname, int half> {
+ def "": MVE_VCVT_ff<iname, "f32.f16", 0b1, half>;
}
-defm MVE_VCVTf16f32 : MVE_VCVT_ff_halves<"f16.f32", 0b0>;
-defm MVE_VCVTf32f16 : MVE_VCVT_ff_halves<"f32.f16", 0b1>;
+defm MVE_VCVTf16f32bh : MVE_VCVT_f2h_m<"vcvtb", 0b0>;
+defm MVE_VCVTf16f32th : MVE_VCVT_f2h_m<"vcvtt", 0b1>;
+defm MVE_VCVTf32f16bh : MVE_VCVT_h2f_m<"vcvtb", 0b0>;
+defm MVE_VCVTf32f16th : MVE_VCVT_h2f_m<"vcvtt", 0b1>;
class MVE_VxCADD<string iname, string suffix, bits<2> size, bit halve,
string cstr="", list<dag> pattern=[]>
OpenPOWER on IntegriCloud