mirror of
https://github.com/gcc-mirror/gcc.git
synced 2026-05-06 14:59:39 +02:00
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:
committed by
Max Filippov
parent
9eba97e412
commit
45f1fed76d
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user