diff mbox series

[07/13,APX,EGPR] Add backend hook for base_reg_class/index_reg_class.

Message ID 20230831082024.314097-8-hongyu.wang@intel.com
State New
Headers show
Series Support Intel APX EGPR | expand

Commit Message

Hongyu Wang Aug. 31, 2023, 8:20 a.m. UTC
From: Kong Lingling <lingling.kong@intel.com>

Add backend helper functions to verify if a rtx_insn can adopt EGPR to
its base/index reg of memory operand. The verification rule goes like
  1. For asm insn, enable/disable EGPR by ix86_apx_inline_asm_use_gpr32.
  2. Disable EGPR for unrecognized insn.
  3. If which_alternative is not decided, loop through enabled alternatives
  and check its attr_gpr32. Only enable EGPR when all enabled
  alternatives has attr_gpr32 = 1.
  4. If which_alternative is decided, enable/disable EGPR by its corresponding
  attr_gpr32.

gcc/ChangeLog:

	* config/i386/i386-protos.h (ix86_mode_code_base_reg_class): New
	prototype.
	(ix86_regno_mode_code_ok_for_base_p): Likewise.
	(ix86_insn_index_reg_class): Likewise.
	* config/i386/i386.cc (ix86_memory_address_use_extended_reg_class_p):
	New helper function to scan the insn.
	(ix86_mode_code_base_reg_class): New function to choose BASE_REG_CLASS.
	(ix86_regno_mode_code_ok_for_base_p): Likewise for base regno.
	(ix86_insn_index_reg_class): Likewise for INDEX_REG_CLASS.
	* config/i386/i386.h (MODE_CODE_BASE_REG_CLASS): Define.
	(REGNO_MODE_CODE_OK_FOR_BASE_P): Likewise.
	(INSN_INDEX_REG_CLASS): Likewise.
	(enum reg_class): Add INDEX_GPR16.
	(GENERAL_GPR16_REGNO_P): Define.
	* config/i386/i386.md (gpr32): New attribute.

gcc/testsuite/ChangeLog:

	* gcc.target/i386/apx-inline-gpr-norex2.c: Adjust.
---
 gcc/config/i386/i386-protos.h                 |  7 ++
 gcc/config/i386/i386.cc                       | 98 +++++++++++++++++++
 gcc/config/i386/i386.h                        | 16 ++-
 gcc/config/i386/i386.md                       |  3 +
 .../gcc.target/i386/apx-inline-gpr-norex2.c   |  7 +-
 5 files changed, 127 insertions(+), 4 deletions(-)
diff mbox series

Patch

diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index bd4782800c4..78eb3e0f584 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -79,6 +79,13 @@  extern bool ix86_expand_set_or_cpymem (rtx, rtx, rtx, rtx, rtx, rtx,
 				       rtx, rtx, rtx, rtx, bool);
 extern bool ix86_expand_cmpstrn_or_cmpmem (rtx, rtx, rtx, rtx, rtx, bool);
 
+extern enum reg_class ix86_mode_code_base_reg_class (machine_mode, addr_space_t,
+						     RTX_CODE, RTX_CODE,
+						     rtx_insn *);
+extern bool ix86_regno_mode_code_ok_for_base_p (int, machine_mode, addr_space_t,
+						RTX_CODE, RTX_CODE,
+						rtx_insn *);
+extern enum reg_class ix86_insn_index_reg_class (rtx_insn *);
 extern bool constant_address_p (rtx);
 extern bool legitimate_pic_operand_p (rtx);
 extern bool legitimate_pic_address_disp_p (rtx);
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 9460ebbfda4..412f3aefc43 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -11054,6 +11054,104 @@  ix86_validate_address_register (rtx op)
   return NULL_RTX;
 }
 
+/* Return true if insn memory address can use any available reg
+   in BASE_REG_CLASS or INDEX_REG_CLASS, otherwise false.
+   For APX, some instruction can't be encoded with gpr32
+   which is BASE_REG_CLASS or INDEX_REG_CLASS, for that case
+   returns false.  */
+static bool
+ix86_memory_address_use_extended_reg_class_p (rtx_insn* insn)
+{
+  /* LRA will do some initialization with insn == NULL,
+     return the maximum reg class for that.
+     For other cases, real insn will be passed and checked.  */
+  bool ret = true;
+  if (TARGET_APX_EGPR && insn)
+    {
+      if (asm_noperands (PATTERN (insn)) >= 0
+	  || GET_CODE (PATTERN (insn)) == ASM_INPUT)
+	return ix86_apx_inline_asm_use_gpr32;
+
+      if (INSN_CODE (insn) < 0)
+	return false;
+
+      /* Try recog the insn before calling get_attr_gpr32. Save
+	 the current recog_data first.  */
+      /* Also save which_alternative for current recog.  */
+
+      struct recog_data_d recog_data_save = recog_data;
+      int which_alternative_saved = which_alternative;
+
+      /* Update the recog_data for alternative check. */
+      if (recog_data.insn != insn)
+	extract_insn_cached (insn);
+
+      /* If alternative is not set, loop throught each alternative
+	 of insn and get gpr32 attr for all enabled alternatives.
+	 If any enabled alternatives has 0 value for gpr32, disallow
+	 gpr32 for addressing.  */
+      if (which_alternative_saved == -1)
+	{
+	  alternative_mask enabled = get_enabled_alternatives (insn);
+	  bool curr_insn_gpr32 = false;
+	  for (int i = 0; i < recog_data.n_alternatives; i++)
+	    {
+	      if (!TEST_BIT (enabled, i))
+		continue;
+	      which_alternative = i;
+	      curr_insn_gpr32 = get_attr_gpr32 (insn);
+	      if (!curr_insn_gpr32)
+		ret = false;
+	    }
+	}
+      else
+	{
+	  which_alternative = which_alternative_saved;
+	  ret = get_attr_gpr32 (insn);
+	}
+
+      recog_data = recog_data_save;
+      which_alternative = which_alternative_saved;
+    }
+
+  return ret;
+}
+
+/* For APX, some instructions can't be encoded with gpr32.  */
+enum reg_class
+ix86_mode_code_base_reg_class (machine_mode mode ATTRIBUTE_UNUSED,
+			       addr_space_t as ATTRIBUTE_UNUSED,
+			       enum rtx_code outer_code ATTRIBUTE_UNUSED,
+			       enum rtx_code index_code ATTRIBUTE_UNUSED,
+			       rtx_insn* insn)
+{
+  if (ix86_memory_address_use_extended_reg_class_p (insn))
+    return BASE_REG_CLASS;
+  return GENERAL_GPR16;
+}
+
+bool
+ix86_regno_mode_code_ok_for_base_p (int regno,
+				    machine_mode mode ATTRIBUTE_UNUSED,
+				    addr_space_t as ATTRIBUTE_UNUSED,
+				    enum rtx_code outer_code ATTRIBUTE_UNUSED,
+				    enum rtx_code index_code ATTRIBUTE_UNUSED,
+				    rtx_insn* insn)
+{
+
+  if (ix86_memory_address_use_extended_reg_class_p (insn))
+    return GENERAL_REGNO_P (regno);
+  return GENERAL_GPR16_REGNO_P (regno);
+}
+
+enum reg_class
+ix86_insn_index_reg_class (rtx_insn* insn)
+{
+  if (ix86_memory_address_use_extended_reg_class_p (insn))
+    return INDEX_REG_CLASS;
+  return INDEX_GPR16;
+}
+
 /* Recognizes RTL expressions that are valid memory addresses for an
    instruction.  The MODE argument is the machine mode for the MEM
    expression that wants to use this address.
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 7ec3086641c..c8362ef451c 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -1018,6 +1018,13 @@  extern const char *host_detect_local_cpu (int argc, const char **argv);
 
 #define ADJUST_REG_ALLOC_ORDER x86_order_regs_for_local_alloc ()
 
+#define MODE_CODE_BASE_REG_CLASS(MODE, AS, OUTER, INDEX, INSN) \
+  ix86_mode_code_base_reg_class (MODE, AS, OUTER, INDEX, INSN)
+#define REGNO_MODE_CODE_OK_FOR_BASE_P(NUM, MODE, AS, OUTER, INDEX, INSN) \
+  ix86_regno_mode_code_ok_for_base_p (NUM, MODE, AS, OUTER, INDEX, INSN)
+
+#define INSN_INDEX_REG_CLASS(INSN) \
+  ix86_insn_index_reg_class (INSN)
 
 #define OVERRIDE_ABI_FORMAT(FNDECL) ix86_call_abi_override (FNDECL)
 
@@ -1297,6 +1304,8 @@  enum reg_class
 				   %r24 %r25 %r26 %r27 %r28 %r29 %r30 %r31 */
   GENERAL_GPR16,		/* %eax %ebx %ecx %edx %esi %edi %ebp %esp
 				   %r8 %r9 %r10 %r11 %r12 %r13 %r14 %r15 */
+  INDEX_GPR16,			/* %eax %ebx %ecx %edx %esi %edi %ebp
+				   %r8 %r9 %r10 %r11 %r12 %r13 %r14 %r15 */
   FP_TOP_REG, FP_SECOND_REG,	/* %st(0) %st(1) */
   FLOAT_REGS,
   SSE_FIRST_REG,
@@ -1360,6 +1369,7 @@  enum reg_class
    "LEGACY_REGS",			\
    "GENERAL_REGS",			\
    "GENERAL_GPR16",			\
+   "INDEX_GPR16",			\
    "FP_TOP_REG", "FP_SECOND_REG",	\
    "FLOAT_REGS",			\
    "SSE_FIRST_REG",			\
@@ -1395,10 +1405,11 @@  enum reg_class
       { 0x0f,        0x0,   0x0 },	/* Q_REGS */			\
    { 0x900f0,        0x0,   0x0 },	/* NON_Q_REGS */		\
       { 0x7e,      0xff0,   0x0 },	/* TLS_GOTBASE_REGS */		\
-      { 0x7f,      0xff0,   0x0 },	/* INDEX_REGS */		\
+      { 0x7f,      0xff0,   0xffff000 },	/* INDEX_REGS */		\
    { 0x900ff,        0x0,   0x0 },	/* LEGACY_REGS */		\
    { 0x900ff,      0xff0,   0xffff000 },	/* GENERAL_REGS */		\
    { 0x900ff,      0xff0,   0x0 },	/* GENERAL_GPR16 */		\
+   { 0x0007f,      0xff0,   0x0 },	/* INDEX_GPR16 */		\
      { 0x100,        0x0,   0x0 },	/* FP_TOP_REG */		\
      { 0x200,        0x0,   0x0 },	/* FP_SECOND_REG */		\
     { 0xff00,        0x0,   0x0 },	/* FLOAT_REGS */		\
@@ -1456,6 +1467,9 @@  enum reg_class
 #define INDEX_REGNO_P(N) \
   (LEGACY_INDEX_REGNO_P (N) || REX_INT_REGNO_P (N) || REX2_INT_REGNO_P (N))
 
+#define GENERAL_GPR16_REGNO_P(N) \
+  (LEGACY_INT_REGNO_P (N) || REX_INT_REGNO_P (N))
+
 #define ANY_QI_REG_P(X) (REG_P (X) && ANY_QI_REGNO_P (REGNO (X)))
 #define ANY_QI_REGNO_P(N) \
   (TARGET_64BIT ? GENERAL_REGNO_P (N) : QI_REGNO_P (N))
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index e3270658cb7..b9eaea78f00 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -873,6 +873,9 @@  (define_attr "use_carry" "0,1" (const_string "0"))
 ;; Define attribute to indicate unaligned ssemov insns
 (define_attr "movu" "0,1" (const_string "0"))
 
+;; Define attribute to indicate gpr32 insns.
+(define_attr "gpr32" "0, 1" (const_string "1"))
+
 ;; Define instruction set of MMX instructions
 (define_attr "mmx_isa" "base,native,sse,sse_noavx,avx"
   (const_string "base"))
diff --git a/gcc/testsuite/gcc.target/i386/apx-inline-gpr-norex2.c b/gcc/testsuite/gcc.target/i386/apx-inline-gpr-norex2.c
index 21534450045..6dfc6714c2f 100644
--- a/gcc/testsuite/gcc.target/i386/apx-inline-gpr-norex2.c
+++ b/gcc/testsuite/gcc.target/i386/apx-inline-gpr-norex2.c
@@ -98,9 +98,10 @@  void foo (DTYPE in[16], DTYPE out[8], const DTYPE C[16])
 /* { dg-final { scan-assembler-not "kor" } } */
 /* { dg-final { scan-assembler-not "kandn" } } */
 /* { dg-final { scan-assembler-times "test_asm_xmm %xmm5, %rax" 1 } } */
-/* { dg-final { scan-assembler-times "test_asm_Brr %r15d, %rax" 1 } } */
-/* { dg-final { scan-assembler-times "test_asm_rBr %r14d, %rax" 1 } } */
-/* { dg-final { scan-assembler-times "test_asm_r %r13d, %rax" 1 } } */
+/* { dg-final { scan-assembler-times "test_asm_Brr %r12d, %rax" 1 } } */
+/* { dg-final { scan-assembler-times "test_asm_rBr %eax, %rax" 1 } } */
+/* { dg-final { scan-assembler-times "test_asm_r %eax, %rax" 1 } } */
+/* { dg-final { scan-assembler-times "test_asm_m \\(%rax\\), %rax" 1 } } */
 /* { dg-final { scan-assembler-not "test_asm_rBr %r31d, %rax" } } */
 /* { dg-final { scan-assembler-not "test_asm_r %r30d, %rax" } } */
 /* { dg-final { scan-assembler-not "test_asm_m \\(%r29d\\), %rax" } } */