[llvm] [X86] Coalesce redundant vector register clears in zero_call_used_regs (PR #212147)

Akshay K via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 14 15:51:35 PDT 2026


https://github.com/kumarak updated https://github.com/llvm/llvm-project/pull/212147

>From 7634e501270255f7e8d437faee64759ca9d73e93 Mon Sep 17 00:00:00 2001
From: AkshayK <iit.akshay at gmail.com>
Date: Sat, 25 Jul 2026 18:00:02 -0400
Subject: [PATCH 1/2] [X86] Coalesce redundant vector register clears in
 zero_call_used_regs

Map the aliasing XMM/YMM/ZMM views of each vector register to a single clear
per lane, mirroring the existing GPR handling. This removes the duplicate
XMM0-15 zeroing and the spurious VZEROUPPER emitted for -fzero-call-used-regs,
reducing both code size and latency.

Fixes #191911
---
 llvm/lib/Target/X86/X86FrameLowering.cpp      |  34 ++-
 .../CodeGen/X86/zero-call-used-regs-simd.ll   | 240 +++++++++++++++++-
 2 files changed, 270 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp
index 7251bdda1dd05..671b034d8b24f 100644
--- a/llvm/lib/Target/X86/X86FrameLowering.cpp
+++ b/llvm/lib/Target/X86/X86FrameLowering.cpp
@@ -670,7 +670,39 @@ void X86FrameLowering::emitZeroCallUsedRegs(BitVector RegsToZero,
   for (MCRegister Reg : GPRsToZero.set_bits())
     TII.buildClearRegister(Reg, MBB, MBBI, DL);
 
-  // Zero out the remaining registers.
+  // Coalesce the aliasing XMM/YMM/ZMM views of each vector register so a lane
+  // is cleared only once, mirroring the GPR handling above.
+  auto getVectorClearReg = [&](MCRegister Reg) -> MCRegister {
+    if (!X86::VR128RegClass.contains(Reg) &&
+        !X86::VR128XRegClass.contains(Reg) &&
+        !X86::VR256RegClass.contains(Reg) &&
+        !X86::VR256XRegClass.contains(Reg) && !X86::VR512RegClass.contains(Reg))
+      return MCRegister();
+
+    // Clearing the XMM zeroes the whole lane. XMM0-15 use the compact VEX form;
+    // XMM16-31 are EVEX-only, reachable only via the ZMM form.
+    MCRegister Xmm = TRI->getSubReg(Reg, X86::sub_xmm);
+    if (!Xmm)
+      Xmm = Reg;
+    if (X86::VR128RegClass.contains(Xmm))
+      return Xmm;
+    MCRegister Zmm =
+        TRI->getMatchingSuperReg(Xmm, X86::sub_xmm, &X86::VR512RegClass);
+    assert(Zmm && "XMM16-31 must have an enclosing ZMM to clear through");
+    return Zmm;
+  };
+
+  BitVector VecRegsToZero(TRI->getNumRegs());
+  for (MCRegister Reg : RegsToZero.set_bits())
+    if (MCRegister Clear = getVectorClearReg(Reg)) {
+      VecRegsToZero.set(Clear.id());
+      RegsToZero.reset(Reg);
+    }
+
+  for (MCRegister Reg : VecRegsToZero.set_bits())
+    TII.buildClearRegister(Reg, MBB, MBBI, DL);
+
+  // Zero out the remaining registers (e.g. mask registers).
   for (MCRegister Reg : RegsToZero.set_bits())
     TII.buildClearRegister(Reg, MBB, MBBI, DL);
 }
diff --git a/llvm/test/CodeGen/X86/zero-call-used-regs-simd.ll b/llvm/test/CodeGen/X86/zero-call-used-regs-simd.ll
index 9bb218781290b..15af5b333874d 100644
--- a/llvm/test/CodeGen/X86/zero-call-used-regs-simd.ll
+++ b/llvm/test/CodeGen/X86/zero-call-used-regs-simd.ll
@@ -177,8 +177,8 @@ define void @zero_k(<8 x i32> %arg, <8 x i1> %mask) #0 {
 ; AVX2-NEXT:    vpmovzxwd {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero
 ; AVX2-NEXT:    vpslld $31, %ymm1, %ymm1
 ; AVX2-NEXT:    vpmaskmovd %ymm0, %ymm1, 0
-; AVX2-NEXT:    vpxor %xmm1, %xmm1, %xmm1
 ; AVX2-NEXT:    vpxor %xmm0, %xmm0, %xmm0
+; AVX2-NEXT:    vpxor %xmm1, %xmm1, %xmm1
 ; AVX2-NEXT:    vzeroupper
 ; AVX2-NEXT:    retq
 ;
@@ -188,8 +188,8 @@ define void @zero_k(<8 x i32> %arg, <8 x i1> %mask) #0 {
 ; AVX512VL-NEXT:    vpslld $31, %ymm1, %ymm1
 ; AVX512VL-NEXT:    vptestmd %ymm1, %ymm1, %k1
 ; AVX512VL-NEXT:    vmovdqa32 %ymm0, 0 {%k1}
-; AVX512VL-NEXT:    vpxor %xmm1, %xmm1, %xmm1
 ; AVX512VL-NEXT:    vpxor %xmm0, %xmm0, %xmm0
+; AVX512VL-NEXT:    vpxor %xmm1, %xmm1, %xmm1
 ; AVX512VL-NEXT:    kxorw %k0, %k0, %k1
 ; AVX512VL-NEXT:    vzeroupper
 ; AVX512VL-NEXT:    retq
@@ -199,8 +199,8 @@ define void @zero_k(<8 x i32> %arg, <8 x i1> %mask) #0 {
 ; AVX512BW-NEXT:    vpsllw $15, %xmm1, %xmm1
 ; AVX512BW-NEXT:    vpmovw2m %xmm1, %k1
 ; AVX512BW-NEXT:    vmovdqa32 %ymm0, 0 {%k1}
-; AVX512BW-NEXT:    vpxor %xmm1, %xmm1, %xmm1
 ; AVX512BW-NEXT:    vpxor %xmm0, %xmm0, %xmm0
+; AVX512BW-NEXT:    vpxor %xmm1, %xmm1, %xmm1
 ; AVX512BW-NEXT:    kxorq %k0, %k0, %k1
 ; AVX512BW-NEXT:    vzeroupper
 ; AVX512BW-NEXT:    retq
@@ -208,4 +208,238 @@ define void @zero_k(<8 x i32> %arg, <8 x i1> %mask) #0 {
   ret void
 }
 
+; Under "all", each vector lane is cleared once (not once per XMM/YMM/ZMM view),
+; and no spurious VZEROUPPER is emitted.
+define void @all_no_live_vec() #1 {
+; SSE-LABEL: all_no_live_vec:
+; SSE:       # %bb.0:
+; SSE-NEXT:    fldz
+; SSE-NEXT:    fldz
+; SSE-NEXT:    fldz
+; SSE-NEXT:    fldz
+; SSE-NEXT:    fldz
+; SSE-NEXT:    fldz
+; SSE-NEXT:    fldz
+; SSE-NEXT:    fldz
+; SSE-NEXT:    fstp %st(0)
+; SSE-NEXT:    fstp %st(0)
+; SSE-NEXT:    fstp %st(0)
+; SSE-NEXT:    fstp %st(0)
+; SSE-NEXT:    fstp %st(0)
+; SSE-NEXT:    fstp %st(0)
+; SSE-NEXT:    fstp %st(0)
+; SSE-NEXT:    fstp %st(0)
+; SSE-NEXT:    xorl %eax, %eax
+; SSE-NEXT:    xorl %ecx, %ecx
+; SSE-NEXT:    xorl %edi, %edi
+; SSE-NEXT:    xorl %edx, %edx
+; SSE-NEXT:    xorl %esi, %esi
+; SSE-NEXT:    xorl %r8d, %r8d
+; SSE-NEXT:    xorl %r9d, %r9d
+; SSE-NEXT:    xorl %r10d, %r10d
+; SSE-NEXT:    xorl %r11d, %r11d
+; SSE-NEXT:    xorps %xmm0, %xmm0
+; SSE-NEXT:    xorps %xmm1, %xmm1
+; SSE-NEXT:    xorps %xmm2, %xmm2
+; SSE-NEXT:    xorps %xmm3, %xmm3
+; SSE-NEXT:    xorps %xmm4, %xmm4
+; SSE-NEXT:    xorps %xmm5, %xmm5
+; SSE-NEXT:    xorps %xmm6, %xmm6
+; SSE-NEXT:    xorps %xmm7, %xmm7
+; SSE-NEXT:    xorps %xmm8, %xmm8
+; SSE-NEXT:    xorps %xmm9, %xmm9
+; SSE-NEXT:    xorps %xmm10, %xmm10
+; SSE-NEXT:    xorps %xmm11, %xmm11
+; SSE-NEXT:    xorps %xmm12, %xmm12
+; SSE-NEXT:    xorps %xmm13, %xmm13
+; SSE-NEXT:    xorps %xmm14, %xmm14
+; SSE-NEXT:    xorps %xmm15, %xmm15
+; SSE-NEXT:    retq
+;
+; AVX-LABEL: all_no_live_vec:
+; AVX:       # %bb.0:
+; AVX-NEXT:    fldz
+; AVX-NEXT:    fldz
+; AVX-NEXT:    fldz
+; AVX-NEXT:    fldz
+; AVX-NEXT:    fldz
+; AVX-NEXT:    fldz
+; AVX-NEXT:    fldz
+; AVX-NEXT:    fldz
+; AVX-NEXT:    fstp %st(0)
+; AVX-NEXT:    fstp %st(0)
+; AVX-NEXT:    fstp %st(0)
+; AVX-NEXT:    fstp %st(0)
+; AVX-NEXT:    fstp %st(0)
+; AVX-NEXT:    fstp %st(0)
+; AVX-NEXT:    fstp %st(0)
+; AVX-NEXT:    fstp %st(0)
+; AVX-NEXT:    xorl %eax, %eax
+; AVX-NEXT:    xorl %ecx, %ecx
+; AVX-NEXT:    xorl %edi, %edi
+; AVX-NEXT:    xorl %edx, %edx
+; AVX-NEXT:    xorl %esi, %esi
+; AVX-NEXT:    xorl %r8d, %r8d
+; AVX-NEXT:    xorl %r9d, %r9d
+; AVX-NEXT:    xorl %r10d, %r10d
+; AVX-NEXT:    xorl %r11d, %r11d
+; AVX-NEXT:    vxorps %xmm0, %xmm0, %xmm0
+; AVX-NEXT:    vxorps %xmm1, %xmm1, %xmm1
+; AVX-NEXT:    vxorps %xmm2, %xmm2, %xmm2
+; AVX-NEXT:    vxorps %xmm3, %xmm3, %xmm3
+; AVX-NEXT:    vxorps %xmm4, %xmm4, %xmm4
+; AVX-NEXT:    vxorps %xmm5, %xmm5, %xmm5
+; AVX-NEXT:    vxorps %xmm6, %xmm6, %xmm6
+; AVX-NEXT:    vxorps %xmm7, %xmm7, %xmm7
+; AVX-NEXT:    vxorps %xmm8, %xmm8, %xmm8
+; AVX-NEXT:    vxorps %xmm9, %xmm9, %xmm9
+; AVX-NEXT:    vxorps %xmm10, %xmm10, %xmm10
+; AVX-NEXT:    vxorps %xmm11, %xmm11, %xmm11
+; AVX-NEXT:    vxorps %xmm12, %xmm12, %xmm12
+; AVX-NEXT:    vxorps %xmm13, %xmm13, %xmm13
+; AVX-NEXT:    vxorps %xmm14, %xmm14, %xmm14
+; AVX-NEXT:    vxorps %xmm15, %xmm15, %xmm15
+; AVX-NEXT:    retq
+;
+; AVX512VL-LABEL: all_no_live_vec:
+; AVX512VL:       # %bb.0:
+; AVX512VL-NEXT:    fldz
+; AVX512VL-NEXT:    fldz
+; AVX512VL-NEXT:    fldz
+; AVX512VL-NEXT:    fldz
+; AVX512VL-NEXT:    fldz
+; AVX512VL-NEXT:    fldz
+; AVX512VL-NEXT:    fldz
+; AVX512VL-NEXT:    fldz
+; AVX512VL-NEXT:    fstp %st(0)
+; AVX512VL-NEXT:    fstp %st(0)
+; AVX512VL-NEXT:    fstp %st(0)
+; AVX512VL-NEXT:    fstp %st(0)
+; AVX512VL-NEXT:    fstp %st(0)
+; AVX512VL-NEXT:    fstp %st(0)
+; AVX512VL-NEXT:    fstp %st(0)
+; AVX512VL-NEXT:    fstp %st(0)
+; AVX512VL-NEXT:    xorl %eax, %eax
+; AVX512VL-NEXT:    xorl %ecx, %ecx
+; AVX512VL-NEXT:    xorl %edi, %edi
+; AVX512VL-NEXT:    xorl %edx, %edx
+; AVX512VL-NEXT:    xorl %esi, %esi
+; AVX512VL-NEXT:    xorl %r8d, %r8d
+; AVX512VL-NEXT:    xorl %r9d, %r9d
+; AVX512VL-NEXT:    xorl %r10d, %r10d
+; AVX512VL-NEXT:    xorl %r11d, %r11d
+; AVX512VL-NEXT:    vxorps %xmm0, %xmm0, %xmm0
+; AVX512VL-NEXT:    vxorps %xmm1, %xmm1, %xmm1
+; AVX512VL-NEXT:    vxorps %xmm2, %xmm2, %xmm2
+; AVX512VL-NEXT:    vxorps %xmm3, %xmm3, %xmm3
+; AVX512VL-NEXT:    vxorps %xmm4, %xmm4, %xmm4
+; AVX512VL-NEXT:    vxorps %xmm5, %xmm5, %xmm5
+; AVX512VL-NEXT:    vxorps %xmm6, %xmm6, %xmm6
+; AVX512VL-NEXT:    vxorps %xmm7, %xmm7, %xmm7
+; AVX512VL-NEXT:    vxorps %xmm8, %xmm8, %xmm8
+; AVX512VL-NEXT:    vxorps %xmm9, %xmm9, %xmm9
+; AVX512VL-NEXT:    vxorps %xmm10, %xmm10, %xmm10
+; AVX512VL-NEXT:    vxorps %xmm11, %xmm11, %xmm11
+; AVX512VL-NEXT:    vxorps %xmm12, %xmm12, %xmm12
+; AVX512VL-NEXT:    vxorps %xmm13, %xmm13, %xmm13
+; AVX512VL-NEXT:    vxorps %xmm14, %xmm14, %xmm14
+; AVX512VL-NEXT:    vxorps %xmm15, %xmm15, %xmm15
+; AVX512VL-NEXT:    vpxord %xmm16, %xmm16, %xmm16
+; AVX512VL-NEXT:    vpxord %xmm17, %xmm17, %xmm17
+; AVX512VL-NEXT:    vpxord %xmm18, %xmm18, %xmm18
+; AVX512VL-NEXT:    vpxord %xmm19, %xmm19, %xmm19
+; AVX512VL-NEXT:    vpxord %xmm20, %xmm20, %xmm20
+; AVX512VL-NEXT:    vpxord %xmm21, %xmm21, %xmm21
+; AVX512VL-NEXT:    vpxord %xmm22, %xmm22, %xmm22
+; AVX512VL-NEXT:    vpxord %xmm23, %xmm23, %xmm23
+; AVX512VL-NEXT:    vpxord %xmm24, %xmm24, %xmm24
+; AVX512VL-NEXT:    vpxord %xmm25, %xmm25, %xmm25
+; AVX512VL-NEXT:    vpxord %xmm26, %xmm26, %xmm26
+; AVX512VL-NEXT:    vpxord %xmm27, %xmm27, %xmm27
+; AVX512VL-NEXT:    vpxord %xmm28, %xmm28, %xmm28
+; AVX512VL-NEXT:    vpxord %xmm29, %xmm29, %xmm29
+; AVX512VL-NEXT:    vpxord %xmm30, %xmm30, %xmm30
+; AVX512VL-NEXT:    vpxord %xmm31, %xmm31, %xmm31
+; AVX512VL-NEXT:    kxorw %k0, %k0, %k0
+; AVX512VL-NEXT:    kxorw %k0, %k0, %k1
+; AVX512VL-NEXT:    kxorw %k0, %k0, %k2
+; AVX512VL-NEXT:    kxorw %k0, %k0, %k3
+; AVX512VL-NEXT:    kxorw %k0, %k0, %k4
+; AVX512VL-NEXT:    kxorw %k0, %k0, %k5
+; AVX512VL-NEXT:    kxorw %k0, %k0, %k6
+; AVX512VL-NEXT:    kxorw %k0, %k0, %k7
+; AVX512VL-NEXT:    retq
+;
+; AVX512BW-LABEL: all_no_live_vec:
+; AVX512BW:       # %bb.0:
+; AVX512BW-NEXT:    fldz
+; AVX512BW-NEXT:    fldz
+; AVX512BW-NEXT:    fldz
+; AVX512BW-NEXT:    fldz
+; AVX512BW-NEXT:    fldz
+; AVX512BW-NEXT:    fldz
+; AVX512BW-NEXT:    fldz
+; AVX512BW-NEXT:    fldz
+; AVX512BW-NEXT:    fstp %st(0)
+; AVX512BW-NEXT:    fstp %st(0)
+; AVX512BW-NEXT:    fstp %st(0)
+; AVX512BW-NEXT:    fstp %st(0)
+; AVX512BW-NEXT:    fstp %st(0)
+; AVX512BW-NEXT:    fstp %st(0)
+; AVX512BW-NEXT:    fstp %st(0)
+; AVX512BW-NEXT:    fstp %st(0)
+; AVX512BW-NEXT:    xorl %eax, %eax
+; AVX512BW-NEXT:    xorl %ecx, %ecx
+; AVX512BW-NEXT:    xorl %edi, %edi
+; AVX512BW-NEXT:    xorl %edx, %edx
+; AVX512BW-NEXT:    xorl %esi, %esi
+; AVX512BW-NEXT:    xorl %r8d, %r8d
+; AVX512BW-NEXT:    xorl %r9d, %r9d
+; AVX512BW-NEXT:    xorl %r10d, %r10d
+; AVX512BW-NEXT:    xorl %r11d, %r11d
+; AVX512BW-NEXT:    vxorps %xmm0, %xmm0, %xmm0
+; AVX512BW-NEXT:    vxorps %xmm1, %xmm1, %xmm1
+; AVX512BW-NEXT:    vxorps %xmm2, %xmm2, %xmm2
+; AVX512BW-NEXT:    vxorps %xmm3, %xmm3, %xmm3
+; AVX512BW-NEXT:    vxorps %xmm4, %xmm4, %xmm4
+; AVX512BW-NEXT:    vxorps %xmm5, %xmm5, %xmm5
+; AVX512BW-NEXT:    vxorps %xmm6, %xmm6, %xmm6
+; AVX512BW-NEXT:    vxorps %xmm7, %xmm7, %xmm7
+; AVX512BW-NEXT:    vxorps %xmm8, %xmm8, %xmm8
+; AVX512BW-NEXT:    vxorps %xmm9, %xmm9, %xmm9
+; AVX512BW-NEXT:    vxorps %xmm10, %xmm10, %xmm10
+; AVX512BW-NEXT:    vxorps %xmm11, %xmm11, %xmm11
+; AVX512BW-NEXT:    vxorps %xmm12, %xmm12, %xmm12
+; AVX512BW-NEXT:    vxorps %xmm13, %xmm13, %xmm13
+; AVX512BW-NEXT:    vxorps %xmm14, %xmm14, %xmm14
+; AVX512BW-NEXT:    vxorps %xmm15, %xmm15, %xmm15
+; AVX512BW-NEXT:    vpxord %xmm16, %xmm16, %xmm16
+; AVX512BW-NEXT:    vpxord %xmm17, %xmm17, %xmm17
+; AVX512BW-NEXT:    vpxord %xmm18, %xmm18, %xmm18
+; AVX512BW-NEXT:    vpxord %xmm19, %xmm19, %xmm19
+; AVX512BW-NEXT:    vpxord %xmm20, %xmm20, %xmm20
+; AVX512BW-NEXT:    vpxord %xmm21, %xmm21, %xmm21
+; AVX512BW-NEXT:    vpxord %xmm22, %xmm22, %xmm22
+; AVX512BW-NEXT:    vpxord %xmm23, %xmm23, %xmm23
+; AVX512BW-NEXT:    vpxord %xmm24, %xmm24, %xmm24
+; AVX512BW-NEXT:    vpxord %xmm25, %xmm25, %xmm25
+; AVX512BW-NEXT:    vpxord %xmm26, %xmm26, %xmm26
+; AVX512BW-NEXT:    vpxord %xmm27, %xmm27, %xmm27
+; AVX512BW-NEXT:    vpxord %xmm28, %xmm28, %xmm28
+; AVX512BW-NEXT:    vpxord %xmm29, %xmm29, %xmm29
+; AVX512BW-NEXT:    vpxord %xmm30, %xmm30, %xmm30
+; AVX512BW-NEXT:    vpxord %xmm31, %xmm31, %xmm31
+; AVX512BW-NEXT:    kxorq %k0, %k0, %k0
+; AVX512BW-NEXT:    kxorq %k0, %k0, %k1
+; AVX512BW-NEXT:    kxorq %k0, %k0, %k2
+; AVX512BW-NEXT:    kxorq %k0, %k0, %k3
+; AVX512BW-NEXT:    kxorq %k0, %k0, %k4
+; AVX512BW-NEXT:    kxorq %k0, %k0, %k5
+; AVX512BW-NEXT:    kxorq %k0, %k0, %k6
+; AVX512BW-NEXT:    kxorq %k0, %k0, %k7
+; AVX512BW-NEXT:    retq
+  ret void
+}
+
 attributes #0 = { "zero-call-used-regs"="used" }
+attributes #1 = { "zero-call-used-regs"="all" }

>From 46926ad6e07157470f5d00d220022b2629221a15 Mon Sep 17 00:00:00 2001
From: AkshayK <iit.akshay at gmail.com>
Date: Fri, 14 Aug 2026 18:51:09 -0400
Subject: [PATCH 2/2] [X86][NFC] Drop vector clear coalescing, keep the test
 coverage

Revert the emitZeroCallUsedRegs change and regenerate
zero-call-used-regs-simd.ll so all_no_live_vec records the codegen
on trunk. On AVX512 targets each of xmm0-15 is still cleared twice,
once through the XMM/YMM views of a lane and once through the ZMM
view, which #191911 tracks.
---
 llvm/lib/Target/X86/X86FrameLowering.cpp      | 34 +--------
 .../CodeGen/X86/zero-call-used-regs-simd.ll   | 75 +++++++++++++------
 2 files changed, 55 insertions(+), 54 deletions(-)

diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp
index 671b034d8b24f..7251bdda1dd05 100644
--- a/llvm/lib/Target/X86/X86FrameLowering.cpp
+++ b/llvm/lib/Target/X86/X86FrameLowering.cpp
@@ -670,39 +670,7 @@ void X86FrameLowering::emitZeroCallUsedRegs(BitVector RegsToZero,
   for (MCRegister Reg : GPRsToZero.set_bits())
     TII.buildClearRegister(Reg, MBB, MBBI, DL);
 
-  // Coalesce the aliasing XMM/YMM/ZMM views of each vector register so a lane
-  // is cleared only once, mirroring the GPR handling above.
-  auto getVectorClearReg = [&](MCRegister Reg) -> MCRegister {
-    if (!X86::VR128RegClass.contains(Reg) &&
-        !X86::VR128XRegClass.contains(Reg) &&
-        !X86::VR256RegClass.contains(Reg) &&
-        !X86::VR256XRegClass.contains(Reg) && !X86::VR512RegClass.contains(Reg))
-      return MCRegister();
-
-    // Clearing the XMM zeroes the whole lane. XMM0-15 use the compact VEX form;
-    // XMM16-31 are EVEX-only, reachable only via the ZMM form.
-    MCRegister Xmm = TRI->getSubReg(Reg, X86::sub_xmm);
-    if (!Xmm)
-      Xmm = Reg;
-    if (X86::VR128RegClass.contains(Xmm))
-      return Xmm;
-    MCRegister Zmm =
-        TRI->getMatchingSuperReg(Xmm, X86::sub_xmm, &X86::VR512RegClass);
-    assert(Zmm && "XMM16-31 must have an enclosing ZMM to clear through");
-    return Zmm;
-  };
-
-  BitVector VecRegsToZero(TRI->getNumRegs());
-  for (MCRegister Reg : RegsToZero.set_bits())
-    if (MCRegister Clear = getVectorClearReg(Reg)) {
-      VecRegsToZero.set(Clear.id());
-      RegsToZero.reset(Reg);
-    }
-
-  for (MCRegister Reg : VecRegsToZero.set_bits())
-    TII.buildClearRegister(Reg, MBB, MBBI, DL);
-
-  // Zero out the remaining registers (e.g. mask registers).
+  // Zero out the remaining registers.
   for (MCRegister Reg : RegsToZero.set_bits())
     TII.buildClearRegister(Reg, MBB, MBBI, DL);
 }
diff --git a/llvm/test/CodeGen/X86/zero-call-used-regs-simd.ll b/llvm/test/CodeGen/X86/zero-call-used-regs-simd.ll
index 15af5b333874d..4110f457b5195 100644
--- a/llvm/test/CodeGen/X86/zero-call-used-regs-simd.ll
+++ b/llvm/test/CodeGen/X86/zero-call-used-regs-simd.ll
@@ -177,8 +177,8 @@ define void @zero_k(<8 x i32> %arg, <8 x i1> %mask) #0 {
 ; AVX2-NEXT:    vpmovzxwd {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero
 ; AVX2-NEXT:    vpslld $31, %ymm1, %ymm1
 ; AVX2-NEXT:    vpmaskmovd %ymm0, %ymm1, 0
-; AVX2-NEXT:    vpxor %xmm0, %xmm0, %xmm0
 ; AVX2-NEXT:    vpxor %xmm1, %xmm1, %xmm1
+; AVX2-NEXT:    vpxor %xmm0, %xmm0, %xmm0
 ; AVX2-NEXT:    vzeroupper
 ; AVX2-NEXT:    retq
 ;
@@ -188,8 +188,8 @@ define void @zero_k(<8 x i32> %arg, <8 x i1> %mask) #0 {
 ; AVX512VL-NEXT:    vpslld $31, %ymm1, %ymm1
 ; AVX512VL-NEXT:    vptestmd %ymm1, %ymm1, %k1
 ; AVX512VL-NEXT:    vmovdqa32 %ymm0, 0 {%k1}
-; AVX512VL-NEXT:    vpxor %xmm0, %xmm0, %xmm0
 ; AVX512VL-NEXT:    vpxor %xmm1, %xmm1, %xmm1
+; AVX512VL-NEXT:    vpxor %xmm0, %xmm0, %xmm0
 ; AVX512VL-NEXT:    kxorw %k0, %k0, %k1
 ; AVX512VL-NEXT:    vzeroupper
 ; AVX512VL-NEXT:    retq
@@ -199,8 +199,8 @@ define void @zero_k(<8 x i32> %arg, <8 x i1> %mask) #0 {
 ; AVX512BW-NEXT:    vpsllw $15, %xmm1, %xmm1
 ; AVX512BW-NEXT:    vpmovw2m %xmm1, %k1
 ; AVX512BW-NEXT:    vmovdqa32 %ymm0, 0 {%k1}
-; AVX512BW-NEXT:    vpxor %xmm0, %xmm0, %xmm0
 ; AVX512BW-NEXT:    vpxor %xmm1, %xmm1, %xmm1
+; AVX512BW-NEXT:    vpxor %xmm0, %xmm0, %xmm0
 ; AVX512BW-NEXT:    kxorq %k0, %k0, %k1
 ; AVX512BW-NEXT:    vzeroupper
 ; AVX512BW-NEXT:    retq
@@ -208,8 +208,9 @@ define void @zero_k(<8 x i32> %arg, <8 x i1> %mask) #0 {
   ret void
 }
 
-; Under "all", each vector lane is cleared once (not once per XMM/YMM/ZMM view),
-; and no spurious VZEROUPPER is emitted.
+; Coverage for the vector clears emitted under "all". On AVX512 targets xmm0-15
+; are cleared twice, once for the XMM/YMM views of a lane and once for the ZMM
+; view, see llvm/llvm-project#191911.
 define void @all_no_live_vec() #1 {
 ; SSE-LABEL: all_no_live_vec:
 ; SSE:       # %bb.0:
@@ -344,6 +345,30 @@ define void @all_no_live_vec() #1 {
 ; AVX512VL-NEXT:    vxorps %xmm13, %xmm13, %xmm13
 ; AVX512VL-NEXT:    vxorps %xmm14, %xmm14, %xmm14
 ; AVX512VL-NEXT:    vxorps %xmm15, %xmm15, %xmm15
+; AVX512VL-NEXT:    kxorw %k0, %k0, %k0
+; AVX512VL-NEXT:    kxorw %k0, %k0, %k1
+; AVX512VL-NEXT:    kxorw %k0, %k0, %k2
+; AVX512VL-NEXT:    kxorw %k0, %k0, %k3
+; AVX512VL-NEXT:    kxorw %k0, %k0, %k4
+; AVX512VL-NEXT:    kxorw %k0, %k0, %k5
+; AVX512VL-NEXT:    kxorw %k0, %k0, %k6
+; AVX512VL-NEXT:    kxorw %k0, %k0, %k7
+; AVX512VL-NEXT:    vxorps %xmm0, %xmm0, %xmm0
+; AVX512VL-NEXT:    vxorps %xmm1, %xmm1, %xmm1
+; AVX512VL-NEXT:    vxorps %xmm2, %xmm2, %xmm2
+; AVX512VL-NEXT:    vxorps %xmm3, %xmm3, %xmm3
+; AVX512VL-NEXT:    vxorps %xmm4, %xmm4, %xmm4
+; AVX512VL-NEXT:    vxorps %xmm5, %xmm5, %xmm5
+; AVX512VL-NEXT:    vxorps %xmm6, %xmm6, %xmm6
+; AVX512VL-NEXT:    vxorps %xmm7, %xmm7, %xmm7
+; AVX512VL-NEXT:    vxorps %xmm8, %xmm8, %xmm8
+; AVX512VL-NEXT:    vxorps %xmm9, %xmm9, %xmm9
+; AVX512VL-NEXT:    vxorps %xmm10, %xmm10, %xmm10
+; AVX512VL-NEXT:    vxorps %xmm11, %xmm11, %xmm11
+; AVX512VL-NEXT:    vxorps %xmm12, %xmm12, %xmm12
+; AVX512VL-NEXT:    vxorps %xmm13, %xmm13, %xmm13
+; AVX512VL-NEXT:    vxorps %xmm14, %xmm14, %xmm14
+; AVX512VL-NEXT:    vxorps %xmm15, %xmm15, %xmm15
 ; AVX512VL-NEXT:    vpxord %xmm16, %xmm16, %xmm16
 ; AVX512VL-NEXT:    vpxord %xmm17, %xmm17, %xmm17
 ; AVX512VL-NEXT:    vpxord %xmm18, %xmm18, %xmm18
@@ -360,14 +385,6 @@ define void @all_no_live_vec() #1 {
 ; AVX512VL-NEXT:    vpxord %xmm29, %xmm29, %xmm29
 ; AVX512VL-NEXT:    vpxord %xmm30, %xmm30, %xmm30
 ; AVX512VL-NEXT:    vpxord %xmm31, %xmm31, %xmm31
-; AVX512VL-NEXT:    kxorw %k0, %k0, %k0
-; AVX512VL-NEXT:    kxorw %k0, %k0, %k1
-; AVX512VL-NEXT:    kxorw %k0, %k0, %k2
-; AVX512VL-NEXT:    kxorw %k0, %k0, %k3
-; AVX512VL-NEXT:    kxorw %k0, %k0, %k4
-; AVX512VL-NEXT:    kxorw %k0, %k0, %k5
-; AVX512VL-NEXT:    kxorw %k0, %k0, %k6
-; AVX512VL-NEXT:    kxorw %k0, %k0, %k7
 ; AVX512VL-NEXT:    retq
 ;
 ; AVX512BW-LABEL: all_no_live_vec:
@@ -413,6 +430,30 @@ define void @all_no_live_vec() #1 {
 ; AVX512BW-NEXT:    vxorps %xmm13, %xmm13, %xmm13
 ; AVX512BW-NEXT:    vxorps %xmm14, %xmm14, %xmm14
 ; AVX512BW-NEXT:    vxorps %xmm15, %xmm15, %xmm15
+; AVX512BW-NEXT:    kxorq %k0, %k0, %k0
+; AVX512BW-NEXT:    kxorq %k0, %k0, %k1
+; AVX512BW-NEXT:    kxorq %k0, %k0, %k2
+; AVX512BW-NEXT:    kxorq %k0, %k0, %k3
+; AVX512BW-NEXT:    kxorq %k0, %k0, %k4
+; AVX512BW-NEXT:    kxorq %k0, %k0, %k5
+; AVX512BW-NEXT:    kxorq %k0, %k0, %k6
+; AVX512BW-NEXT:    kxorq %k0, %k0, %k7
+; AVX512BW-NEXT:    vxorps %xmm0, %xmm0, %xmm0
+; AVX512BW-NEXT:    vxorps %xmm1, %xmm1, %xmm1
+; AVX512BW-NEXT:    vxorps %xmm2, %xmm2, %xmm2
+; AVX512BW-NEXT:    vxorps %xmm3, %xmm3, %xmm3
+; AVX512BW-NEXT:    vxorps %xmm4, %xmm4, %xmm4
+; AVX512BW-NEXT:    vxorps %xmm5, %xmm5, %xmm5
+; AVX512BW-NEXT:    vxorps %xmm6, %xmm6, %xmm6
+; AVX512BW-NEXT:    vxorps %xmm7, %xmm7, %xmm7
+; AVX512BW-NEXT:    vxorps %xmm8, %xmm8, %xmm8
+; AVX512BW-NEXT:    vxorps %xmm9, %xmm9, %xmm9
+; AVX512BW-NEXT:    vxorps %xmm10, %xmm10, %xmm10
+; AVX512BW-NEXT:    vxorps %xmm11, %xmm11, %xmm11
+; AVX512BW-NEXT:    vxorps %xmm12, %xmm12, %xmm12
+; AVX512BW-NEXT:    vxorps %xmm13, %xmm13, %xmm13
+; AVX512BW-NEXT:    vxorps %xmm14, %xmm14, %xmm14
+; AVX512BW-NEXT:    vxorps %xmm15, %xmm15, %xmm15
 ; AVX512BW-NEXT:    vpxord %xmm16, %xmm16, %xmm16
 ; AVX512BW-NEXT:    vpxord %xmm17, %xmm17, %xmm17
 ; AVX512BW-NEXT:    vpxord %xmm18, %xmm18, %xmm18
@@ -429,14 +470,6 @@ define void @all_no_live_vec() #1 {
 ; AVX512BW-NEXT:    vpxord %xmm29, %xmm29, %xmm29
 ; AVX512BW-NEXT:    vpxord %xmm30, %xmm30, %xmm30
 ; AVX512BW-NEXT:    vpxord %xmm31, %xmm31, %xmm31
-; AVX512BW-NEXT:    kxorq %k0, %k0, %k0
-; AVX512BW-NEXT:    kxorq %k0, %k0, %k1
-; AVX512BW-NEXT:    kxorq %k0, %k0, %k2
-; AVX512BW-NEXT:    kxorq %k0, %k0, %k3
-; AVX512BW-NEXT:    kxorq %k0, %k0, %k4
-; AVX512BW-NEXT:    kxorq %k0, %k0, %k5
-; AVX512BW-NEXT:    kxorq %k0, %k0, %k6
-; AVX512BW-NEXT:    kxorq %k0, %k0, %k7
 ; AVX512BW-NEXT:    retq
   ret void
 }



More information about the llvm-commits mailing list