]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
ext-dce: Don't refine live width with SUBREG mode if !TRULY_NOOP_TRUNCATION_MODES_P...
authorXi Ruoyao <xry111@xry111.site>
Sun, 11 May 2025 08:44:31 +0000 (16:44 +0800)
committerXi Ruoyao <xry111@xry111.site>
Wed, 4 Jun 2025 15:27:35 +0000 (23:27 +0800)
If we see a promoted subreg and TRULY_NOOP_TRUNCATION says the
truncation is not a noop, then all bits of the inner reg are live.  We
cannot reduce the live mask to that of the mode of the subreg.

gcc/ChangeLog:

PR rtl-optimization/120050
* ext-dce.cc (ext_dce_process_uses): Break early if a SUBREG in
rhs is promoted and the truncation from the inner mode to the
outer mode is not a noop when handling SETs.

gcc/ext-dce.cc

index a03439501419df9fccf712383040b2b2ea556c9f..aa80c0483d610cf76969cc5131a4e2051b4ab80f 100644 (file)
@@ -35,6 +35,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "print-rtl.h"
 #include "dbgcnt.h"
 #include "diagnostic-core.h"
+#include "target.h"
 
 /* These should probably move into a C++ class.  */
 static vec<bitmap_head> livein;
@@ -764,13 +765,25 @@ ext_dce_process_uses (rtx_insn *insn, rtx obj,
                         We don't want to mark those bits live unnecessarily
                         as that inhibits extension elimination in important
                         cases such as those in Coremark.  So we need that
-                        outer code.  */
+                        outer code.
+
+                        But if !TRULY_NOOP_TRUNCATION_MODES_P, the mode
+                        change performed by Y would normally need to be a
+                        TRUNCATE rather than a SUBREG.  It is probably the
+                        guarantee provided by SUBREG_PROMOTED_VAR_P that
+                        allows the SUBREG in Y as an exception.  We must
+                        therefore preserve that guarantee and treat the
+                        upper bits of the inner register as live
+                        regardless of the outer code.  See PR 120050.  */
                      if (!REG_P (SUBREG_REG (y))
                          || (SUBREG_PROMOTED_VAR_P (y)
                              && ((GET_CODE (SET_SRC (x)) == SIGN_EXTEND
                                   && SUBREG_PROMOTED_SIGNED_P (y))
                                  || (GET_CODE (SET_SRC (x)) == ZERO_EXTEND
-                                     && SUBREG_PROMOTED_UNSIGNED_P (y)))))
+                                     && SUBREG_PROMOTED_UNSIGNED_P (y))
+                                 || !TRULY_NOOP_TRUNCATION_MODES_P (
+                                       GET_MODE (y),
+                                       GET_MODE (SUBREG_REG (y))))))
                        break;
 
                      bit = subreg_lsb (y).to_constant ();