[PATCH] tcg/x86_64: Use the mulx insn from the bmi2 isa

Richard Henderson posted 1 patch 1 week, 2 days ago
tcg/x86_64/tcg-target-con-set.h |  2 ++
tcg/x86_64/tcg-target.c.inc     | 36 ++++++++++++++++++++++++++++++---
2 files changed, 35 insertions(+), 3 deletions(-)
[PATCH] tcg/x86_64: Use the mulx insn from the bmi2 isa
Posted by Richard Henderson 1 week, 2 days ago
This vex encoded instruction can be used or either mulu2 or muluh.
This replaces the highly constrained mul insn from the base x86 isa.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 tcg/x86_64/tcg-target-con-set.h |  2 ++
 tcg/x86_64/tcg-target.c.inc     | 36 ++++++++++++++++++++++++++++++---
 2 files changed, 35 insertions(+), 3 deletions(-)

diff --git a/tcg/x86_64/tcg-target-con-set.h b/tcg/x86_64/tcg-target-con-set.h
index 458d69c3c07..7df9bf49177 100644
--- a/tcg/x86_64/tcg-target-con-set.h
+++ b/tcg/x86_64/tcg-target-con-set.h
@@ -42,6 +42,7 @@ C_O1_I2(r, 0, reZ)
 C_O1_I2(r, 0, ri)
 C_O1_I2(r, 0, rI)
 C_O1_I2(r, L, L)
+C_O1_I2(r, r, d)
 C_O1_I2(r, r, r)
 C_O1_I2(r, r, re)
 C_O1_I2(r, r, ri)
@@ -56,5 +57,6 @@ C_O1_I4(r, r, reT, r, 0)
 C_O1_I4(r, r, r, ri, ri)
 C_O2_I1(r, r, L)
 C_O2_I2(a, d, a, r)
+C_O2_I2(r, r, r, d)
 C_O2_I2(r, r, L, L)
 C_O2_I3(a, d, 0, 1, r)
diff --git a/tcg/x86_64/tcg-target.c.inc b/tcg/x86_64/tcg-target.c.inc
index 2c8f1f3e580..8e0d8e08146 100644
--- a/tcg/x86_64/tcg-target.c.inc
+++ b/tcg/x86_64/tcg-target.c.inc
@@ -274,6 +274,7 @@ static bool tcg_target_const_match(int64_t val, int ct,
 #define OPC_MOVSLQ	(0x63 | P_REXW)
 #define OPC_MOVZBL	(0xb6 | P_EXT)
 #define OPC_MOVZWL	(0xb7 | P_EXT)
+#define OPC_MULX        (0xf6 | P_SIMDF2 | P_EXT38)
 #define OPC_PABSB       (0x1c | P_EXT38 | P_DATA16)
 #define OPC_PABSW       (0x1d | P_EXT38 | P_DATA16)
 #define OPC_PABSD       (0x1e | P_EXT38 | P_DATA16)
@@ -2732,19 +2733,48 @@ static const TCGOutOpBinary outop_mulsh = {
     .base.static_constraint = C_NotImplemented,
 };
 
+static void tgen_muluh(TCGContext *s, TCGType type,
+                       TCGReg a0, TCGReg a1, TCGReg a2)
+{
+    /*
+     * Note from the architecture manual:
+     * If the first and second operand are identical,
+     * it will contain the high half of the multiplication result.
+     */
+    int rexw = type == TCG_TYPE_I32 ? 0 : P_REXW;
+    tcg_out_vex_modrm(s, OPC_MULX + rexw, a0, a0, a1);
+}
+
+static TCGConstraintSetIndex cset_muluh(TCGType type, unsigned flags)
+{
+    return have_bmi2 ? C_O1_I2(r, r, d) : C_NotImplemented;
+}
+
 static const TCGOutOpBinary outop_muluh = {
-    .base.static_constraint = C_NotImplemented,
+    .base.static_constraint = C_Dynamic,
+    .base.dynamic_constraint = cset_muluh,
+    .out_rrr = tgen_muluh,
 };
 
 static void tgen_mulu2(TCGContext *s, TCGType type,
                        TCGReg a0, TCGReg a1, TCGReg a2, TCGReg a3)
 {
     int rexw = type == TCG_TYPE_I32 ? 0 : P_REXW;
-    tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_MUL, a3);
+    if (have_bmi2) {
+        tcg_out_vex_modrm(s, OPC_MULX + rexw, a0, a1, a2);
+    } else {
+        tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_MUL, a3);
+    }
+}
+
+static TCGConstraintSetIndex cset_mulu2(TCGType type, unsigned flags)
+{
+    return have_bmi2 ? C_O2_I2(r, r, r, d) : C_O2_I2(a, d, a, r);
 }
 
 static const TCGOutOpMul2 outop_mulu2 = {
-    .base.static_constraint = C_O2_I2(a, d, a, r),
+    .base.static_constraint = C_Dynamic,
+    .base.dynamic_constraint = cset_mulu2,
     .out_rrrr = tgen_mulu2,
 };
 
-- 
2.53.0