xtensa: Implement "-mforce-l32" target-specific option

In the previous patches, both the named address space "__force_l32" and
the target-specific attribute "force_l32" were introduced for reading
sub-words from the instruction memory area.

This patch introduces a new target-specific option "-mforce-l32", which
allows sub-word reading from the instruction memory area even in the
generic address spaces (ie., the default memory references) or without
the "force_l32" attribute.

     /* example */
     int test(unsigned int i) {
       static const char string[] __attribute__((section(".irom.text")))
         = "The quick brown fox jumps over the lazy dog.";
       return i < __builtin_strlen(string) ? string[i] : -1;
     }

     ;; result (-O2 -mforce-l32)
     	.literal_position
     	.literal .LC0, string$0
     test:
     	entry	sp, 32
     	movi.n	a8, 0x2b
     	bltu	a8, a2, .L3
     	l32r	a9, .LC0	;; If -mno-force-l32,
     	movi.n	a8, -4		;;
     	add.n	a9, a9, a2	;;	l32r	a8, .LC0
     	and	a8, a9, a8	;;	add.n	a8, a8, a2
     	l32i.n	a8, a8, 0	;;	l8ui	a2, a8, 0
     	ssa8l	a9		;;
     	srl	a8, a8		;;
     	extui	a2, a8, 0, 8	;;
     	retw.n
     .L3:
     	movi.n	a2, -1
     	retw.n
     	.section .irom.text,"a"
     string$0:
     	.string	"The quick brown fox jumps over the lazy dog."

gcc/ChangeLog:

	* config/xtensa/xtensa.cc (xtensa_expand_load_force_l32_2):
	New sub-function for inspecting pseudos that clearly point to the
	function's stack frame.
	(xtensa_expand_load_force_l32):
	Add handling for loading from the generic address space when the
	"-mforce-l32" option is enabled, however, obvious references to
	function stack frames are excluded.
	* config/xtensa/xtensa.opt (mforce-l32):
	New target-specific option definition.
This commit is contained in:
Takayuki 'January June' Suwa
2026-05-03 03:14:43 +09:00
committed by Max Filippov
parent 9eba97e412
commit 45f1fed76d
2 changed files with 36 additions and 4 deletions

View File

@@ -2628,7 +2628,7 @@ xtensa_emit_add_imm (rtx dst, rtx src, HOST_WIDE_INT imm, rtx scratch,
load with bit-extraction of the required bytes. */
static bool
xtensa_expand_load_force_l32_1 (rtx mem)
xtensa_expand_load_force_l32_1 (const_rtx mem)
{
tree expr = MEM_EXPR (mem), type;
@@ -2639,6 +2639,29 @@ xtensa_expand_load_force_l32_1 (rtx mem)
&& lookup_attribute ("force_l32", TYPE_ATTRIBUTES (type));
}
static bool
xtensa_expand_load_force_l32_2 (const_rtx reg)
{
unsigned int regno;
/* These pseudos are unlikely to be passed during the RTL generation,
but just in case. */
switch (regno = REGNO (reg))
{
case STACK_POINTER_REGNUM:
case FRAME_POINTER_REGNUM:
case ARG_POINTER_REGNUM:
return true;
}
/* gccint explicitly states that these pseudos indicate the location of
the stack frame. In addition, the static chain pointers also clearly
refer to the stack frame. */
return IN_RANGE (regno, FIRST_VIRTUAL_REGISTER, LAST_VIRTUAL_REGISTER)
|| (cfun && cfun->static_chain_decl
&& cfun->static_chain_decl == REG_EXPR (regno_reg_rtx[regno]));
}
bool
xtensa_expand_load_force_l32 (rtx *operands, machine_mode dest_mode,
machine_mode src_mode, int unsignedp)
@@ -2670,13 +2693,17 @@ xtensa_expand_load_force_l32 (rtx *operands, machine_mode dest_mode,
/* Exclude insns that do not perform memory loading with "force_l32". */
if (MEM_ADDR_SPACE (src) != ADDR_SPACE_FORCE_L32
&& ! xtensa_expand_load_force_l32_1 (src))
&& ! xtensa_expand_load_force_l32_1 (src)
&& (!TARGET_FORCE_L32 || MEM_ADDR_SPACE (src) != ADDR_SPACE_GENERIC))
return false;
/* As a preprocessing, handle cases where addr is (PLUS (REG, OFFSET))
form. */
if (REG_P (addr = XEXP (src, 0)))
;
{
if (xtensa_expand_load_force_l32_2 (addr))
return false;
}
else if (GET_CODE (addr) == PLUS)
{
rtx op0 = XEXP (addr, 0), op1 = XEXP (addr, 1);
@@ -2684,7 +2711,8 @@ xtensa_expand_load_force_l32 (rtx *operands, machine_mode dest_mode,
if (! CONST_INT_P (op1))
std::swap (op0, op1);
if (! REG_P (op0) || ! CONST_INT_P (op1))
if (! REG_P (op0) || ! CONST_INT_P (op1)
|| xtensa_expand_load_force_l32_2 (op0))
return false;
if ((v = INTVAL (op1)) == 0)
addr = op0;

View File

@@ -71,3 +71,7 @@ Use windowed registers ABI.
mstrict-align
Target Var(xtensa_strict_alignment) Init(XTENSA_STRICT_ALIGNMENT_UNDEFINED)
Do not use unaligned memory references.
mforce-l32
Target Mask(FORCE_L32)
Use L32I instruction to access 1- and 2-byte quantities in memory instead of L8UI/L16UI/L16SI.