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"
