]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
xtensa: Implement "-mforce-l32" target-specific option
authorTakayuki 'January June' Suwa <jjsuwa_sys3175@yahoo.co.jp>
Sat, 2 May 2026 18:14:43 +0000 (03:14 +0900)
committerMax Filippov <jcmvbkbc@gmail.com>
Mon, 4 May 2026 07:28:39 +0000 (00:28 -0700)
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.

gcc/config/xtensa/xtensa.cc
gcc/config/xtensa/xtensa.opt

index 1b4aa8934ff65b1f53b923bebb678a6e7450d28b..5a9b18de1cef5eae6a0f9b509d969a1beb8349cd 100644 (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;
index aee776f124e1fe4338286dfe0d77b89a2057f8d0..90665ba180c679b43676e28aee8e14d7b8673b34 100644 (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.