https://gcc.gnu.org/g:bb561b45e490377046b7ce14e8934cc8a81ec6a7

commit r16-2428-gbb561b45e490377046b7ce14e8934cc8a81ec6a7
Author: Takayuki 'January June' Suwa <jjsuwa_sys3...@yahoo.co.jp>
Date:   Wed Jul 16 17:12:03 2025 +0900

    xtensa: Fix inaccuracy in xtensa_rtx_costs()
    
    This patch fixes the following defects in the function:
    
       - The cost of move instructions larger than the natural word width,
         specifically "movd[if]_internal", cannot be estimated correctly
       - Floating-point or symbolic constant assignment insns cannot be
         identified as L32R instructions
    
    gcc/ChangeLog:
    
            * config/xtensa/xtensa.cc (xtensa_is_insn_L32R_p):
            Rewrite to capture insns that could be L32R machine instructions
            wherever possible.
            (xtensa_rtx_costs): Fix to consider that moves larger than a
            natural word can take multiple L32R machine instructions.
            (constantpool_address_p): Cosmetics.
            * config/xtensa/xtensa.md (movdi_internal, movdf_internal):
            Add missing insn attributes.

Diff:
---
 gcc/config/xtensa/xtensa.cc | 44 ++++++++++++++++++++++++--------------------
 gcc/config/xtensa/xtensa.md | 10 ++++++++--
 2 files changed, 32 insertions(+), 22 deletions(-)

diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc
index b75cec13b28a..02554c55687d 100644
--- a/gcc/config/xtensa/xtensa.cc
+++ b/gcc/config/xtensa/xtensa.cc
@@ -601,8 +601,8 @@ constantpool_address_p (const_rtx addr)
 
       /* Make sure the address is word aligned.  */
       offset = XEXP (addr, 1);
-      if ((!CONST_INT_P (offset))
-         || ((INTVAL (offset) & 3) != 0))
+      if (! CONST_INT_P (offset)
+         || (INTVAL (offset) & 3) != 0)
        return false;
 
       sym = XEXP (addr, 0);
@@ -611,6 +611,7 @@ constantpool_address_p (const_rtx addr)
   if (SYMBOL_REF_P (sym)
       && CONSTANT_POOL_ADDRESS_P (sym))
     return true;
+
   return false;
 }
 
@@ -4694,29 +4695,32 @@ xtensa_rtx_costs (rtx x, machine_mode mode, int 
outer_code,
     }
 }
 
+/* Return TRUE if the specified insn corresponds to one or more L32R machine
+   instructions.  */
+
 static bool
 xtensa_is_insn_L32R_p (const rtx_insn *insn)
 {
-  rtx x = PATTERN (insn);
+  rtx pat, dest, src;
 
-  if (GET_CODE (x) != SET)
+  /* "PATTERN (insn)" can be used without checking, see insn_cost()
+     in gcc/rtlanal.cc.  */
+  if (GET_CODE (pat = PATTERN (insn)) != SET
+      || ! register_operand (dest = SET_DEST (pat), VOIDmode))
     return false;
 
-  x = XEXP (x, 1);
-  if (MEM_P (x))
-    {
-      x = XEXP (x, 0);
-      return (SYMBOL_REF_P (x) || CONST_INT_P (x))
-            && CONSTANT_POOL_ADDRESS_P (x);
-    }
-
-  /* relaxed MOVI instructions, that will be converted to L32R by the
-     assembler.  */
-  if (CONST_INT_P (x)
-      && ! xtensa_simm12b (INTVAL (x)))
+  if (constantpool_mem_p (src = SET_SRC (pat)))
     return true;
 
-  return false;
+  /* Return true if:
+     - CONST16 instruction is not configured, and
+     - the source is some constant, and also
+     - negation of "the source is integer and fits into the immediate
+       field".  */
+  return (!TARGET_CONST16
+         && CONSTANT_P (src)
+         && ! ((GET_MODE (dest) == SImode || GET_MODE (dest) == HImode)
+               && CONST_INT_P (src) && xtensa_simm12b (INTVAL (src))));
 }
 
 /* Compute a relative costs of RTL insns.  This is necessary in order to
@@ -4725,7 +4729,7 @@ xtensa_is_insn_L32R_p (const rtx_insn *insn)
 static int
 xtensa_insn_cost (rtx_insn *insn, bool speed)
 {
-  if (!(recog_memoized (insn) < 0))
+  if (! (recog_memoized (insn) < 0))
     {
       int len = get_attr_length (insn);
 
@@ -4738,7 +4742,7 @@ xtensa_insn_cost (rtx_insn *insn, bool speed)
 
          /* "L32R" may be particular slow (implementation-dependent).  */
          if (xtensa_is_insn_L32R_p (insn))
-           return COSTS_N_INSNS (1 + xtensa_extra_l32r_costs);
+           return COSTS_N_INSNS ((1 + xtensa_extra_l32r_costs) * n);
 
          /* Cost based on the pipeline model.  */
          switch (get_attr_type (insn))
@@ -4783,7 +4787,7 @@ xtensa_insn_cost (rtx_insn *insn, bool speed)
            {
              /* "L32R" itself plus constant in litpool.  */
              if (xtensa_is_insn_L32R_p (insn))
-               len = 3 + 4;
+               len += (len / 3) * 4;
 
              /* Consider fractional instruction length (for example, ".n"
                 short instructions or "L32R" litpool constants.  */
diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md
index 5d3bc3baaac6..629dfdde33cb 100644
--- a/gcc/config/xtensa/xtensa.md
+++ b/gcc/config/xtensa/xtensa.md
@@ -1297,7 +1297,10 @@
       std::swap (operands[0], operands[1]);
       std::swap (operands[2], operands[3]);
     }
-})
+}
+  [(set_attr "type"    "move,move,load,load,store")
+   (set_attr "mode"    "DI")
+   (set_attr "length"  "6,12,6,6,6")])
 
 (define_split
   [(set (match_operand:DI 0 "register_operand")
@@ -1643,7 +1646,10 @@
       std::swap (operands[0], operands[1]);
       std::swap (operands[2], operands[3]);
     }
-})
+}
+  [(set_attr "type"    "move,load,move,load,load,store")
+   (set_attr "mode"    "DF")
+   (set_attr "length"  "6,6,12,6,6,6")])
 
 ;; Block moves

Reply via email to