]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
xtensa: Fix inaccuracy in xtensa_rtx_costs()
authorTakayuki 'January June' Suwa <jjsuwa_sys3175@yahoo.co.jp>
Wed, 16 Jul 2025 08:12:03 +0000 (17:12 +0900)
committerMax Filippov <jcmvbkbc@gmail.com>
Tue, 22 Jul 2025 16:53:52 +0000 (09:53 -0700)
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.

gcc/config/xtensa/xtensa.cc
gcc/config/xtensa/xtensa.md

index b75cec13b28ad1ce3ebd75f80ab1c53a321b70d4..02554c55687da0f73acaf44b5844886f670fd2c7 100644 (file)
@@ -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.  */
index 5d3bc3baaac6646a6ec1810c87508c603adc9acb..629dfdde33cb09ca7fc8842f7cddcf5602916cf6 100644 (file)
       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")
       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