UNSPEC_MMA_XVI8GER4SPP
UNSPEC_MMA_XXMFACC
UNSPEC_MMA_XXMTACC
+ UNSPEC_DMF_INSERT512
+ UNSPEC_DMF_INSERT1024
])
(define_c_enum "unspecv"
(match_operand:OO 1 "input_operand"))]
""
{
- if (TARGET_MMA)
+ if (TARGET_MMA || TARGET_DMF)
{
rs6000_emit_move (operands[0], operands[1], OOmode);
DONE;
(define_insn_and_split "*movoo"
[(set (match_operand:OO 0 "nonimmediate_operand" "=wa,ZwO,wa")
(match_operand:OO 1 "input_operand" "ZwO,wa,wa"))]
- "TARGET_MMA
+ "(TARGET_MMA || TARGET_DMF)
&& (gpc_reg_operand (operands[0], OOmode)
|| gpc_reg_operand (operands[1], OOmode))"
"@
[(match_operand:OO 0 "vsx_register_operand")
(match_operand:V16QI 1 "mma_assemble_input_operand")
(match_operand:V16QI 2 "mma_assemble_input_operand")]
- "TARGET_MMA"
+ "TARGET_MMA || TARGET_DMF"
{
rtx src = gen_rtx_UNSPEC (OOmode,
gen_rtvec (2, operands[1], operands[2]),
(unspec:OO [(match_operand:V16QI 1 "mma_assemble_input_operand" "mwa")
(match_operand:V16QI 2 "mma_assemble_input_operand" "mwa")]
UNSPEC_VSX_ASSEMBLE))]
- "TARGET_MMA"
+ "TARGET_MMA || TARGET_DMF"
"#"
"&& reload_completed"
[(const_int 0)]
[(match_operand:V16QI 0 "mma_disassemble_output_operand")
(match_operand:OO 1 "vsx_register_operand")
(match_operand 2 "const_0_to_1_operand")]
- "TARGET_MMA"
+ "TARGET_MMA || TARGET_DMF"
{
rtx src;
int regoff = INTVAL (operands[2]);
(unspec:V16QI [(match_operand:OO 1 "vsx_register_operand" "wa")
(match_operand 2 "const_0_to_1_operand")]
UNSPEC_MMA_EXTRACT))]
- "TARGET_MMA
+ "(TARGET_MMA || TARGET_DMF)
&& vsx_register_operand (operands[1], OOmode)"
"#"
"&& reload_completed"
DONE;
})
+(define_insn "dm_insert512"
+ [(set (match_operand:XO 0 "dmr_register_operand" "=wD")
+ (unspec:XO [(match_operand:OO 1 "vsx_register_operand" "wa")
+ (match_operand:OO 2 "vsx_register_operand" "wa")
+ (match_operand 3 "const_0_to_1_operand")]
+ UNSPEC_DMF_INSERT512))]
+ "TARGET_DMF"
+ "dmxxinstdmr512 %0,%x1,%x2,%3"
+ [(set_attr "type" "dmf")])
+
+;; Move from VSX registers to DMR registers via two insert 512 bit
+;; instructions.
+(define_insn "dm_insert1024"
+ [(set (match_operand:TDO 0 "dmr_register_operand" "=wD")
+ (unspec:TDO [(match_operand:OO 1 "vsx_register_operand" "wa")
+ (match_operand:OO 2 "vsx_register_operand" "wa")
+ (match_operand:OO 3 "vsx_register_operand" "wa")
+ (match_operand:OO 4 "vsx_register_operand" "wa")]
+ UNSPEC_DMF_INSERT1024))]
+ "TARGET_DMF"
+ "dmxxinstdmr512 %0,%x1,%x2,0\n\tdmxxinstdmr512 %0,%x3,%x4,1"
+ [(set_attr "type" "dmf")])
+
(define_expand "mma_assemble_acc"
- [(match_operand:XO 0 "fpr_reg_operand")
+ [(match_operand:XO 0 "accumulator_operand")
(match_operand:V16QI 1 "mma_assemble_input_operand")
(match_operand:V16QI 2 "mma_assemble_input_operand")
(match_operand:V16QI 3 "mma_assemble_input_operand")
(match_operand:V16QI 4 "mma_assemble_input_operand")]
- "TARGET_MMA"
+ "TARGET_MMA || TARGET_DMF"
{
- rtx src = gen_rtx_UNSPEC_VOLATILE (XOmode,
- gen_rtvec (4, operands[1], operands[2],
- operands[3], operands[4]),
- UNSPECV_MMA_ASSEMBLE);
- emit_move_insn (operands[0], src);
+ if (TARGET_DMF)
+ {
+ rtx vp0 = gen_reg_rtx (OOmode);
+ rtx vp1 = gen_reg_rtx (OOmode);
+ emit_insn (gen_vsx_assemble_pair (vp0, operands[1], operands[2]));
+ emit_insn (gen_vsx_assemble_pair (vp1, operands[3], operands[4]));
+ emit_insn (gen_dm_insert512 (operands[0], vp0, vp1, const0_rtx));
+ }
+ else
+ {
+ rtx src = gen_rtx_UNSPEC_VOLATILE (XOmode,
+ gen_rtvec (4, operands[1], operands[2],
+ operands[3], operands[4]),
+ UNSPECV_MMA_ASSEMBLE);
+ emit_move_insn (operands[0], src);
+ }
DONE;
})
;; as an early clobber so we don't accidentally clobber the input operands. */
(define_insn_and_split "*mma_assemble_acc"
- [(set (match_operand:XO 0 "fpr_reg_operand" "=&d")
+ [(set (match_operand:XO 0 "accumulator_operand" "=&wD")
(unspec_volatile:XO
[(match_operand:V16QI 1 "mma_assemble_input_operand" "mwa")
(match_operand:V16QI 2 "mma_assemble_input_operand" "mwa")
(match_operand:V16QI 4 "mma_assemble_input_operand" "mwa")]
UNSPECV_MMA_ASSEMBLE))]
"TARGET_MMA
- && fpr_reg_operand (operands[0], XOmode)"
+ && accumulator_operand (operands[0], XOmode)"
"#"
"&& reload_completed"
[(const_int 0)]
(define_expand "mma_disassemble_acc"
[(match_operand:V16QI 0 "mma_disassemble_output_operand")
- (match_operand:XO 1 "fpr_reg_operand")
+ (match_operand:XO 1 "accumulator_operand")
(match_operand 2 "const_0_to_3_operand")]
"TARGET_MMA"
{
DONE;
})
+;; xxmtacc/xxmfacc prime/deprime an accumulator that lives in 4 adjacent
+;; FPRs -- they reformat that shared FPR/accumulator storage in place. On
+;; TARGET_DMF, DMRs are a register file entirely separate from the FPRs,
+;; so there is no such format to convert and these are a nop. This expand
+;; only exists so __builtin_mma_xxmfacc/xxmtacc (which always resolve to
+;; this pattern) correctly do nothing on TARGET_DMF instead of failing
+;; to match any insn.
+(define_expand "mma_<acc>"
+ [(set (match_operand:XO 0 "accumulator_operand")
+ (unspec:XO [(match_operand:XO 1 "accumulator_operand")]
+ MMA_ACC))]
+ "TARGET_MMA || TARGET_DMF"
+{
+ if (TARGET_DMF)
+ {
+ emit_move_insn (operands[0], operands[1]);
+ DONE;
+ }
+})
+
+
;; MMA instructions that do not use their accumulators as an input, still
;; must not allow their vector operands to overlap the registers used by
;; the accumulator. We enforce this by marking the output as early clobber.
-(define_insn "mma_<acc>"
- [(set (match_operand:XO 0 "fpr_reg_operand" "=&d")
- (unspec:XO [(match_operand:XO 1 "fpr_reg_operand" "0")]
+(define_insn "*mma_<acc>"
+ [(set (match_operand:XO 0 "accumulator_operand" "=&wD")
+ (unspec:XO [(match_operand:XO 1 "accumulator_operand" "0")]
MMA_ACC))]
- "TARGET_MMA"
+ "TARGET_MMA && !TARGET_DMF"
"<acc> %A0"
[(set_attr "type" "mma")])
return VINT_REGNO_P (REGNO (op));
})
+;; Return 1 if op is a dense math register
+(define_predicate "dmr_register_operand"
+ (match_operand 0 "register_operand")
+{
+ if (!TARGET_DMF)
+ return 0;
+
+ if (!REG_P (op))
+ return 0;
+
+ if (!HARD_REGISTER_P (op))
+ return 1;
+
+ return DMR_REGNO_P (REGNO (op));
+})
+
;; Return 1 if op is an accumulator. On power10/11 systems, the accumulators
;; overlap with the FPRs. If TARGET_DMF is true, it will be Dense math register.
(define_predicate "accumulator_operand"
if (TARGET_VSX && VSX_REGNO_P (REGNO (op)))
return 1;
+ if (TARGET_DMF && DMR_REGNO_P (REGNO (op)))
+ return 1;
+
return INT_REGNO_P (REGNO (op)) || FP_REGNO_P (REGNO (op));
})
/* If we're disassembling an accumulator into a different type, we need
to emit a xxmfacc instruction now, since we cannot do it later. */
- if (fncode == RS6000_BIF_DISASSEMBLE_ACC)
+ if (fncode == RS6000_BIF_DISASSEMBLE_ACC && !TARGET_DMF)
{
new_decl = rs6000_builtin_decls[RS6000_BIF_XXMFACC_INTERNAL];
new_call = gimple_build_call (new_decl, 1, src);
unsigned size = GET_MODE_SIZE (reg_mode);
/* If we are reading an accumulator register, we have to
- deprime it before we can access it. */
- if (TARGET_MMA
+ deprime it before we can access it, unless we have dense math
+ registers, which do not need priming/depriming. */
+ if (TARGET_MMA && !TARGET_DMF
&& GET_MODE (src) == XOmode && FP_REGNO_P (REGNO (src)))
emit_insn (gen_mma_xxmfacc (src, src));
}
/* If we are writing an accumulator register, we have to
- prime it after we've written it. */
- if (TARGET_MMA
+ prime it after we've written it, unless we have dense math
+ registers, which do not need priming/depriming. */
+ if (TARGET_MMA && !TARGET_DMF
&& GET_MODE (dst) == XOmode && FP_REGNO_P (REGNO (dst)))
emit_insn (gen_mma_xxmtacc (dst, dst));
}
/* We are writing an accumulator register, so we have to
- prime it after we've written it. */
- if (GET_MODE (src) == XOmode)
+ prime it after we've written it, unless we have dense math
+ registers, which do not need priming/depriming. */
+ if (GET_MODE (src) == XOmode && !TARGET_DMF)
emit_insn (gen_mma_xxmtacc (dst, dst));
return;
if (REG_P (src) && REG_P (dst) && (REGNO (src) < REGNO (dst)))
{
/* If we are reading an accumulator register, we have to
- deprime it before we can access it. */
- if (TARGET_MMA
+ deprime it before we can access it, unless we have dense math
+ registers, which do not need priming/depriming. */
+ if (TARGET_MMA && !TARGET_DMF
&& GET_MODE (src) == XOmode && FP_REGNO_P (REGNO (src)))
emit_insn (gen_mma_xxmfacc (src, src));
}
/* If we are writing an accumulator register, we have to
- prime it after we've written it. */
- if (TARGET_MMA
+ prime it after we've written it, unless we have dense math
+ registers, which do not need priming/depriming. */
+ if (TARGET_MMA && !TARGET_DMF
&& GET_MODE (dst) == XOmode && FP_REGNO_P (REGNO (dst)))
emit_insn (gen_mma_xxmtacc (dst, dst));
}
}
/* If we are reading an accumulator register, we have to
- deprime it before we can access it. */
- if (TARGET_MMA && REG_P (src)
+ deprime it before we can access it, unless we have dense math
+ registers, which do not need priming/depriming. */
+ if (TARGET_MMA && !TARGET_DMF && REG_P (src)
&& GET_MODE (src) == XOmode && FP_REGNO_P (REGNO (src)))
emit_insn (gen_mma_xxmfacc (src, src));
}
/* If we are writing an accumulator register, we have to
- prime it after we've written it. */
- if (TARGET_MMA && REG_P (dst)
+ prime it after we've written it, unless we have dense math
+ registers, which do not need priming/depriming. */
+ if (TARGET_MMA && !TARGET_DMF && REG_P (dst)
&& GET_MODE (dst) == XOmode && FP_REGNO_P (REGNO (dst)))
emit_insn (gen_mma_xxmtacc (dst, dst));
vecsimple,veccomplex,vecdiv,veccmp,veccmpsimple,vecperm,
vecfloat,vecfdiv,vecdouble,mtvsr,mfvsr,crypto,
veclogical,veccmpfx,vecexts,vecmove,
- htm,htmsimple,dfp,mma,
+ htm,htmsimple,dfp,mma,dmf,
fused_arith_logical,
fused_cmp_isel,
fused_carry,
(const (symbol_ref "(enum attr_cpu) rs6000_tune")))
;; The ISA we implement.
-(define_attr "isa" "any,p5,p6,p7,p7v,p8,p8v,p9,p9v,p9kf,p9tf,p10,future"
+(define_attr "isa" "any,p5,p6,p7,p7v,p8,p8v,p9,p9v,p9kf,p9tf,p10,future,mma,dmf"
(const_string "any"))
;; Is this alternative enabled for the current CPU/ISA/etc.?
(and (eq_attr "isa" "future")
(match_test "TARGET_FUTURE"))
(const_int 1)
+
+ (and (eq_attr "isa" "mma")
+ (match_test "TARGET_MMA"))
+ (const_int 1)
+
+ (and (eq_attr "isa" "dmf")
+ (match_test "TARGET_DMF"))
+ (const_int 1)
] (const_int 0)))
;; If this instruction is microcoded on the CELL processor
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mdejagnu-cpu=future -O2" } */
+/* { dg-require-effective-target powerpc_future_compile_ok } */
+
+void
+foo (__vector_quad *acc)
+{
+ __builtin_mma_xxmtacc (acc);
+}
+
+void
+bar (__vector_quad *acc)
+{
+ __builtin_mma_xxmfacc (acc);
+}
+
+/* { dg-final { scan-assembler-not {\mxxmtacc\M} } } */
+/* { dg-final { scan-assembler-not {\mxxmfacc\M} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mdejagnu-cpu=future -O2 -mno-dense-math" } */
+/* { dg-require-effective-target powerpc_future_compile_ok } */
+
+void
+foo (__vector_quad *acc)
+{
+ __builtin_mma_xxmtacc (acc);
+}
+
+void
+bar (__vector_quad *acc)
+{
+ __builtin_mma_xxmfacc (acc);
+}
+
+/* { dg-final { scan-assembler {\mxxmtacc\M} } } */
+/* { dg-final { scan-assembler {\mxxmfacc\M} } } */