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

commit r16-7568-gd96b9b689fbf892a4b51d5115a494ee846b0bbd2
Author: Richard Biener <[email protected]>
Date:   Wed Feb 18 10:05:02 2026 +0100

    target/123137 - improve TLS call placement validity check
    
    When we search for a point in an inseration candidate block that has
    incoming live call clobbered regs we look for REG_DEAD notes of
    those and indication of FLAGS reg becoming live.  But we consider
    insns like
    
    (insn 807 805 6 2 (parallel [
                (set (subreg:SI (reg:HI 509) 0)
                    (lshiftrt:SI (reg:SI 514)
                        (const_int 16 [0x10])))
                (clobber (reg:CC 17 flags))
            ]) 
"/home/packages/tmp/onednn-3.9.1+ds/src/cpu/x64/brgemm/jit_brgemm_amx_uker.cpp":1891:25
 1213 {*lshrsi3_1}
         (expr_list:REG_UNUSED (reg:CC 17 flags)
            (expr_list:REG_DEAD (reg:SI 514)
                (nil))))
    
    making the FLAGS_REG live despite the REG_UNUSED note or the setter
    being a CLOBBER.  The following optimizes this by in turn honoring
    REG_UNUSED for FLAGS_REG, pruning it immediately again.
    
    This reduces required expensive iteration to other candidate BBs,
    reducing compile-time for the testcase in the PR from hours to 6s.
    
            PR target/123137
            * config/i386/i386-features.cc (ix86_emit_tls_call): Improve
            local FLAGS_REG liveness calculation.
    
            * g++.dg/torture/pr124137.C: New testcase.

Diff:
---
 gcc/config/i386/i386-features.cc        |  4 +++-
 gcc/testsuite/g++.dg/torture/pr124137.C | 41 +++++++++++++++++++++++++++++++++
 2 files changed, 44 insertions(+), 1 deletion(-)

diff --git a/gcc/config/i386/i386-features.cc b/gcc/config/i386/i386-features.cc
index 4e94b2f742ee..0e4fdcd28539 100644
--- a/gcc/config/i386/i386-features.cc
+++ b/gcc/config/i386/i386-features.cc
@@ -4083,7 +4083,9 @@ ix86_emit_tls_call (rtx tls_set, x86_cse_kind kind, 
basic_block bb,
 
          rtx link;
          for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
-           if (REG_NOTE_KIND (link) == REG_DEAD
+           if ((REG_NOTE_KIND (link) == REG_DEAD
+                || (REG_NOTE_KIND (link) == REG_UNUSED
+                    && REGNO (XEXP (link, 0)) == FLAGS_REG))
                && REG_P (XEXP (link, 0)))
              {
                /* Mark the live caller-saved register as dead.  */
diff --git a/gcc/testsuite/g++.dg/torture/pr124137.C 
b/gcc/testsuite/g++.dg/torture/pr124137.C
new file mode 100644
index 000000000000..538433e958b1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr124137.C
@@ -0,0 +1,41 @@
+// { dg-do compile }
+// { dg-require-effective-target fpic }
+// { dg-additional-options "-fPIC" }
+
+inline int &GetErrorRef() {
+  thread_local int err;
+  return err;
+}
+int SetError_err;
+bool isREG___trans_tmp_4;
+struct Operand {
+  int : 6;
+  int kind_ : 10;
+  int bit_ : 14;
+protected:
+  int : 11;
+public:
+  bool isREG(int bit) {
+    isREG___trans_tmp_4 = kind_ && bit_ & bit;
+    return isREG___trans_tmp_4;
+  }
+  int getBit() { return bit_; }
+};
+struct Reg : Operand {
+} index_, fp8_to_f16_upconvert_to_vnni_reg_data;
+enum { i32e = 4 };
+struct RegExp {
+  RegExp(Reg &r) {
+    if (r.isREG(i32e))
+      GetErrorRef() = SetError_err;
+    if (r.getBit())
+      index_ = r;
+  }
+};
+struct X {
+  void operator[](RegExp);
+} ptr;
+void jit_brgemm_amx_uker_base_tfp8_to_f16_upconvert_to_vnni(Reg reg_buf) {
+  RegExp __trans_tmp_3 = fp8_to_f16_upconvert_to_vnni_reg_data;
+  ptr[reg_buf];
+}

Reply via email to