https://gcc.gnu.org/g:2ce24fb6d9e4275b03b205f22c2629bd371008c1

commit r16-4320-g2ce24fb6d9e4275b03b205f22c2629bd371008c1
Author: Takayuki 'January June' Suwa <[email protected]>
Date:   Fri Sep 19 21:23:51 2025 +0900

    xtensa: Implement TARGET_MD_ASM_ADJUST
    
    The behavior of the 'g'-constraint on asm statement operands does not
    strictly match that described in the GCC User Manual:
    
       "'g'  Any register, memory, or immediate integer operand is allowed,
        except for registers that are not general registers."
    
       -- 6.12.3.1 Simple Constraints, Using the GCC (the latest)
    
    Contrary to the quote above, the following example will produce different
    results depending on whether TARGET_CONST16 or TARGET_AUTO_LITPOOLS is
    enabled:
    
         /* example */
         void test(void) {
           asm volatile ("# %0"::"g"(65536));
         }
    
         ;; TARGET_CONST16 || TARGET_AUTO_LITPOOLS
         test:
            entry   sp, 32
            # 65536
            retw.n
    
         ;; !TARGET_CONST16 && !TARGET_AUTO_LITPOOLS
            .literal_position
            .literal .LC0, 65536
         test:
            entry   sp, 32
            # .LC0
            retw.n
    
    Indeed, both of the above results satisfy the constraint, but the latter
    is not an "any" constant as stated in the manual, and is therefore incon-
    sistent with the former.
    
    This is because the behavior of the 'g'-constraint on constants depends
    on the general_operand() predicate, and essentially on
    TARGET_LEGITIMATE_CONSTANT_P().
    
    This patch resolves that inconsistency by adding an 'n'-constraint imme-
    diately before every occurrence of 'g' in each constraint string during
    the RTL generation pass, to prioritize being an integer constant for the
    alternative to which 'g' belongs.
    
    gcc/ChangeLog:
    
            * config/xtensa/xtensa.cc
            (TARGET_MD_ASM_ADJUST): New macro definition.
            (xtensa_md_asm_adjust): New function prototype and definition, that
            prepends all 'g'-constraints in the "constraints" vector with 'n',
            if neither TARGET_CONST16 nor TARGET_AUTO_LITPOOLS is enabled.

Diff:
---
 gcc/config/xtensa/xtensa.cc | 66 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 66 insertions(+)

diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc
index bcb26df2e22b..00c36915795a 100644
--- a/gcc/config/xtensa/xtensa.cc
+++ b/gcc/config/xtensa/xtensa.cc
@@ -204,6 +204,10 @@ static rtx xtensa_delegitimize_address (rtx);
 static reg_class_t xtensa_ira_change_pseudo_allocno_class (int, reg_class_t,
                                                           reg_class_t);
 static HARD_REG_SET xtensa_zero_call_used_regs (HARD_REG_SET);
+static rtx_insn *xtensa_md_asm_adjust (vec<rtx> &, vec<rtx> &,
+                                      vec<machine_mode> &, vec<const char *> &,
+                                      vec<rtx> &, vec<rtx> &, HARD_REG_SET &,
+                                      location_t);
 
 
 
@@ -377,6 +381,9 @@ static HARD_REG_SET xtensa_zero_call_used_regs 
(HARD_REG_SET);
 #undef TARGET_ZERO_CALL_USED_REGS
 #define TARGET_ZERO_CALL_USED_REGS xtensa_zero_call_used_regs
 
+#undef TARGET_MD_ASM_ADJUST
+#define TARGET_MD_ASM_ADJUST xtensa_md_asm_adjust
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 
@@ -5648,4 +5655,63 @@ xtensa_zero_call_used_regs (HARD_REG_SET selected_regs)
   return selected_regs;
 }
 
+/* Implement TARGET_MD_ASM_ADJUST.
+
+   If either TARGET_CONST16 or TARGET_AUTO_LITPOOLS is enabled, the 'g'-
+   constraint (based on general_operand()) accepts any integer constant,
+   but if neither it limits within signed 12 bit by
+   TARGET_LEGITIMATE_CONSTANT_P().
+   This behavior is not reasonable and can be addressed by prepending an
+   'n'-constraint to the 'g' during the RTL generation, if necessary.  */
+
+static rtx_insn *
+xtensa_md_asm_adjust (vec<rtx> &outputs ATTRIBUTE_UNUSED,
+                     vec<rtx> &inputs ATTRIBUTE_UNUSED,
+                     vec<machine_mode> &input_modes ATTRIBUTE_UNUSED,
+                     vec<const char *> &constraints,
+                     vec<rtx> &uses ATTRIBUTE_UNUSED,
+                     vec<rtx> &clobbers ATTRIBUTE_UNUSED,
+                     HARD_REG_SET &clobbered_regs ATTRIBUTE_UNUSED,
+                     location_t loc ATTRIBUTE_UNUSED)
+{
+  size_t n, l;
+  const char *p;
+  int c;
+  char *modified, *q;
+
+  if (!TARGET_CONST16 && !TARGET_AUTO_LITPOOLS)
+    for (auto &constraint : constraints)
+      {
+       /* Count the number of 'g'-constraints in each constraint string.  */
+       for (n = 0, p = constraint; (c = *p); p += CONSTRAINT_LEN (c, p))
+         if (c == 'g')
+           ++n;
+       if (n == 0)
+         continue;
+
+       /* If the constraint string contains 'g'-constraints, then each
+          'g' is prefixed with an 'n'-constraint to form a new constraint
+          string.  */
+       n += strlen (constraint);
+       modified = (char *)ggc_alloc_atomic (n + 1);
+       for (p = constraint, q = modified; (c = *p); )
+         if (c == 'g')
+           q[0] = 'n', q[1] = 'g', ++p, q += 2;
+         else
+           if ((l = CONSTRAINT_LEN (c, p)) > 1)
+             memcpy (q, p, l), p += l, q += l;
+           else
+             *q++ = *p++;
+       *q = '\0';
+       if (dump_file)
+         fprintf (dump_file,
+                  "xtensa_md_asm_adjust: "
+                  "The constraint \"%s\" contains 'g's, so modify it to "
+                  "\"%s\".\n", constraint, modified);
+       constraint = modified;
+      }
+
+  return NULL;
+}
+
 #include "gt-xtensa.h"

Reply via email to