[gcc r14-6433] Treat "p" in asms as addressing VOIDmode

Richard Sandiford rsandifo@gcc.gnu.org
Mon Dec 11 19:43:47 GMT 2023


https://gcc.gnu.org/g:a14d247f339454ef9068d24e64eeaeef282fec95

commit r14-6433-ga14d247f339454ef9068d24e64eeaeef282fec95
Author: Richard Sandiford <richard.sandiford@arm.com>
Date:   Mon Dec 11 19:43:38 2023 +0000

    Treat "p" in asms as addressing VOIDmode
    
    check_asm_operands was inconsistent about how it handled "p"
    after RA compared to before RA.  Before RA it tested the address
    with a void (unknown) memory mode:
    
                case CT_ADDRESS:
                  /* Every address operand can be reloaded to fit.  */
                  result = result || address_operand (op, VOIDmode);
                  break;
    
    After RA it deferred to constrain_operands, which used the mode
    of the operand:
    
                    if ((GET_MODE (op) == VOIDmode
                         || SCALAR_INT_MODE_P (GET_MODE (op)))
                        && (strict <= 0
                            || (strict_memory_address_p
                                 (recog_data.operand_mode[opno], op))))
                      win = true;
    
    Using the mode of the operand is necessary for special predicates,
    where it is used to give the memory mode.  But for asms, the operand
    mode is simply the mode of the address itself (so DImode on 64-bit
    targets), which doesn't say anything about the addressed memory.
    
    This patch uses VOIDmode for asms but continues to use the operand
    mode for .md insns.  It's needed to avoid a regression in the
    testcase with the late-combine pass.
    
    Fixing this made me realise that recog_level2 was doing duplicate
    work for asms after RA.
    
    gcc/
            * recog.cc (constrain_operands): Pass VOIDmode to
            strict_memory_address_p for 'p' constraints in asms.
            * rtl-ssa/changes.cc (recog_level2): Skip redundant constrain_operands
            for asms.
    
    gcc/testsuite/
            * gcc.target/aarch64/prfm_imm_offset_2.c: New test.

Diff:
---
 gcc/recog.cc                                         | 18 +++++++++++-------
 gcc/rtl-ssa/changes.cc                               |  4 +++-
 gcc/testsuite/gcc.target/aarch64/prfm_imm_offset_2.c |  1 +
 3 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/gcc/recog.cc b/gcc/recog.cc
index ed084fa8808..1138a7934bd 100644
--- a/gcc/recog.cc
+++ b/gcc/recog.cc
@@ -3199,13 +3199,17 @@ constrain_operands (int strict, alternative_mask alternatives)
 		   strictly valid, i.e., that all pseudos requiring hard regs
 		   have gotten them.  We also want to make sure we have a
 		   valid mode.  */
-		if ((GET_MODE (op) == VOIDmode
-		     || SCALAR_INT_MODE_P (GET_MODE (op)))
-		    && (strict <= 0
-			|| (strict_memory_address_p
-			     (recog_data.operand_mode[opno], op))))
-		  win = true;
-		break;
+		{
+		  auto mem_mode = (recog_data.is_asm
+				   ? VOIDmode
+				   : recog_data.operand_mode[opno]);
+		  if ((GET_MODE (op) == VOIDmode
+		       || SCALAR_INT_MODE_P (GET_MODE (op)))
+		      && (strict <= 0
+			  || strict_memory_address_p (mem_mode, op)))
+		    win = true;
+		  break;
+		}
 
 		/* No need to check general_operand again;
 		   it was done in insn-recog.cc.  Well, except that reload
diff --git a/gcc/rtl-ssa/changes.cc b/gcc/rtl-ssa/changes.cc
index 2f2d12d5f30..443d0575df5 100644
--- a/gcc/rtl-ssa/changes.cc
+++ b/gcc/rtl-ssa/changes.cc
@@ -986,8 +986,10 @@ recog_level2 (insn_change &change, add_regno_clobber_fn add_regno_clobber)
       pat = newpat;
     }
 
+  // check_asm_operands checks the constraints after RA, so we don't
+  // need to do it again.
   INSN_CODE (rtl) = icode;
-  if (reload_completed)
+  if (reload_completed && !asm_p)
     {
       extract_insn (rtl);
       if (!constrain_operands (1, get_preferred_alternatives (rtl)))
diff --git a/gcc/testsuite/gcc.target/aarch64/prfm_imm_offset_2.c b/gcc/testsuite/gcc.target/aarch64/prfm_imm_offset_2.c
new file mode 100644
index 00000000000..2dd695157f2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/prfm_imm_offset_2.c
@@ -0,0 +1 @@
+void f(char *p) { asm("prfm pldl1keep, %a0\n" :: "p" (p + 6)); }


More information about the Gcc-cvs mailing list