https://gcc.gnu.org/g:16065b6239aab2eecfd7a50f58d38324ee6478ba

commit r15-8281-g16065b6239aab2eecfd7a50f58d38324ee6478ba
Author: Georg-Johann Lay <a...@gjlay.de>
Date:   Tue Mar 18 21:22:22 2025 +0100

    AVR: target/119355 - Fix ICE in pass avr-fuse-move / -mfuse-move.
    
    This ICE only occurred when the compiler is built with, say
    CXXFLAGS='-Wp,-D_GLIBCXX_ASSERTIONS'.  The problem was that
    a value from an illegal REGNO was read.  The value was not
    used in these cases, but the access triggered an assertion
    due to reading past std::array.
    
    gcc/
            PR target/119355
            * config/avr/avr-passes.cc (memento_t::apply): Only
            read values[p.arg] when it is actually used.

Diff:
---
 gcc/config/avr/avr-passes.cc | 54 ++++++++++++++++++++++++++------------------
 1 file changed, 32 insertions(+), 22 deletions(-)

diff --git a/gcc/config/avr/avr-passes.cc b/gcc/config/avr/avr-passes.cc
index e32c46738d81..184619af6cb4 100644
--- a/gcc/config/avr/avr-passes.cc
+++ b/gcc/config/avr/avr-passes.cc
@@ -2205,9 +2205,6 @@ memento_t::apply (const ply_t &p)
     }
   else if (p.size == 1)
     {
-      int x = values[p.regno];
-      int y = values[p.arg];
-
       switch (p.code)
        {
        default:
@@ -2234,29 +2231,42 @@ memento_t::apply (const ply_t &p)
            gcc_unreachable ();
          break;
 
-#define DO_ARITH(n_args, code, expr)                                   \
+#define DO_ARITH1(code, expr)                                          \
+         case code:                                                    \
+           gcc_assert (knows (p.regno));                               \
+           {                                                           \
+             const int x = values[p.regno];                            \
+             set_value (p.regno, expr);                                \
+           }                                                           \
+           break
+
+#define DO_ARITH2(code, expr)                                          \
          case code:                                                    \
            gcc_assert (knows (p.regno));                               \
-           if (n_args == 2)                                            \
-             gcc_assert (knows (p.arg));                               \
-           set_value (p.regno, expr);                                  \
+           gcc_assert (knows (p.arg));                                 \
+           {                                                           \
+             const int x = values[p.regno];                            \
+             const int y = values[p.arg];                              \
+             set_value (p.regno, expr);                                \
+           }                                                           \
            break
 
-         DO_ARITH (1, NEG, -x);
-         DO_ARITH (1, NOT, ~x);
-         DO_ARITH (1, PRE_INC, x + 1);
-         DO_ARITH (1, PRE_DEC, x - 1);
-         DO_ARITH (1, ROTATE, (x << 4) | (x >> 4));
-         DO_ARITH (1, ASHIFT, x << 1);
-         DO_ARITH (1, LSHIFTRT, x >> 1);
-         DO_ARITH (1, ASHIFTRT, (x >> 1) | (x & 0x80));
-
-         DO_ARITH (2, AND, x & y);
-         DO_ARITH (2, IOR, x | y);
-         DO_ARITH (2, XOR, x ^ y);
-         DO_ARITH (2, PLUS, x + y);
-         DO_ARITH (2, MINUS, x - y);
-#undef DO_ARITH
+         DO_ARITH1 (NEG, -x);
+         DO_ARITH1 (NOT, ~x);
+         DO_ARITH1 (PRE_INC, x + 1);
+         DO_ARITH1 (PRE_DEC, x - 1);
+         DO_ARITH1 (ROTATE, (x << 4) | (x >> 4));
+         DO_ARITH1 (ASHIFT, x << 1);
+         DO_ARITH1 (LSHIFTRT, x >> 1);
+         DO_ARITH1 (ASHIFTRT, (x >> 1) | (x & 0x80));
+
+         DO_ARITH2 (AND, x & y);
+         DO_ARITH2 (IOR, x | y);
+         DO_ARITH2 (XOR, x ^ y);
+         DO_ARITH2 (PLUS, x + y);
+         DO_ARITH2 (MINUS, x - y);
+#undef DO_ARITH1
+#undef DO_ARITH2
        }
     } // size == 1
   else

Reply via email to