[llvm] [X86] Remove zero extends made redundant by the byte/word fixup (PR #217923)

via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 21 11:19:31 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-globalisel

@llvm/pr-subscribers-backend-x86

Author: Jan Ječmen (JanJecmen)

<details>
<summary>Changes</summary>

Widening an 8 or 16 bit load to MOVZX32rm* leaves any later zero extend of the loaded value doing nothing. Remove such an extend, or rewrite it as MOV32rr when it moves the value to a different register. The redundancy only appears once the load has been widened, which is why this runs here.

A forward walk over each block records how many low bits each 32 bit register is known to be zero extended from; an extend is redundant when that is no more than the number of bits it reads. Sources that are not the low part of their super register (e.g., %ah) are excluded.

Assisted-by: Claude Opus 5 <noreply@<!-- -->anthropic.com>

---

Patch is 55.73 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/217923.diff


15 Files Affected:

- (modified) llvm/lib/Target/X86/X86FixupBWInsts.cpp (+111-1) 
- (modified) llvm/test/CodeGen/X86/2007-08-09-IllegalX86-64Asm.ll (+1-1) 
- (modified) llvm/test/CodeGen/X86/GlobalISel/callingconv.ll (+2-2) 
- (modified) llvm/test/CodeGen/X86/atomic-load-store.ll (-1) 
- (added) llvm/test/CodeGen/X86/fixup-bw-eliminate-redundant-zext.mir (+157) 
- (modified) llvm/test/CodeGen/X86/isel-select-cmov.ll (-6) 
- (modified) llvm/test/CodeGen/X86/isel-udiv.ll (-1) 
- (modified) llvm/test/CodeGen/X86/isel-urem.ll (-1) 
- (modified) llvm/test/CodeGen/X86/load-local-v4i5.ll (+1-1) 
- (modified) llvm/test/CodeGen/X86/popcnt.ll (-1) 
- (modified) llvm/test/CodeGen/X86/pr15267.ll (+1-1) 
- (modified) llvm/test/CodeGen/X86/pr38539.ll (-1) 
- (modified) llvm/test/CodeGen/X86/promote-assert-zext.ll (+6-1) 
- (modified) llvm/test/CodeGen/X86/vector-compress.ll (+6-116) 
- (modified) llvm/test/CodeGen/X86/vector-sext.ll (+14-14) 


``````````diff
diff --git a/llvm/lib/Target/X86/X86FixupBWInsts.cpp b/llvm/lib/Target/X86/X86FixupBWInsts.cpp
index 18819efd35e27..d07b7c64693f5 100644
--- a/llvm/lib/Target/X86/X86FixupBWInsts.cpp
+++ b/llvm/lib/Target/X86/X86FixupBWInsts.cpp
@@ -42,11 +42,15 @@
 /// wouldn't be created, or when your know a newer processor is being
 /// targeted, or when optimizing for minimum code size.
 ///
+/// Widening the loads in this pass can leave behind zero extends of values
+/// that are already zero extended, so as a second step these are removed.
+///
 //===----------------------------------------------------------------------===//
 
 #include "X86.h"
 #include "X86InstrInfo.h"
 #include "X86Subtarget.h"
+#include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/Analysis/ProfileSummaryInfo.h"
 #include "llvm/CodeGen/LazyMachineBlockFrequencyInfo.h"
@@ -60,6 +64,7 @@
 #include "llvm/CodeGen/TargetInstrInfo.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/raw_ostream.h"
+#include <optional>
 using namespace llvm;
 
 #define FIXUPBW_DESC "X86 Byte/Word Instruction Fixup"
@@ -73,6 +78,11 @@ static cl::opt<bool>
                  cl::desc("Change byte and word instructions to larger sizes"),
                  cl::init(true), cl::Hidden);
 
+static cl::opt<bool> EliminateRedundantZExts(
+    "fixup-bw-eliminate-redundant-zext",
+    cl::desc("Remove zero extends of already zero extended values"),
+    cl::init(true), cl::Hidden);
+
 namespace {
 class X86FixupBWInstImpl {
 public:
@@ -111,6 +121,10 @@ class X86FixupBWInstImpl {
   // otherwise.
   MachineInstr *tryReplaceInstr(MachineInstr *MI, MachineBasicBlock &MBB) const;
 
+  /// Remove the zero extends in \p MBB of values that an earlier instruction
+  /// in the same block (widened by this pass) has already zero extended. 
+  void eliminateRedundantZeroExtends(MachineBasicBlock &MBB);
+
   MachineFunction *MF = nullptr;
 
   /// Machine instruction info used throughout the class.
@@ -174,8 +188,11 @@ bool X86FixupBWInstImpl::runOnMachineFunction(MachineFunction &MF) {
   LLVM_DEBUG(dbgs() << "Start X86FixupBWInsts\n";);
 
   // Process all basic blocks.
-  for (auto &MBB : MF)
+  for (auto &MBB : MF) {
     processBasicBlock(MF, MBB);
+    if (EliminateRedundantZExts)
+      eliminateRedundantZeroExtends(MBB);
+  }
 
   LLVM_DEBUG(dbgs() << "End X86FixupBWInsts\n";);
 
@@ -431,6 +448,99 @@ X86FixupBWInstImpl::tryReplaceInstr(MachineInstr *MI,
   return nullptr;
 }
 
+void X86FixupBWInstImpl::eliminateRedundantZeroExtends(MachineBasicBlock &MBB) {
+  // Return the number of source bits in the zero extending mov.
+  auto DefinedZeroExtendedValueBits =
+      [](const MachineInstr &MI) -> std::optional<unsigned> {
+    switch (MI.getOpcode()) {
+    case X86::MOVZX32rm8:
+    case X86::MOVZX32rr8:
+      return 8;
+    case X86::MOVZX32rm16:
+    case X86::MOVZX32rr16:
+      return 16;
+    default:
+      return std::nullopt;
+    }
+  };
+
+  // Maps what is currently known about each 32 bit register to the number
+  // of low bits its value is known to be zero extended from: 8 for a value
+  // in [0, 0xFF] and 16 for one in [0, 0xFFFF]. Only tracks registers within
+  // a single block.
+  SmallDenseMap<MCRegister, unsigned, 8> Known;
+
+  for (MachineInstr &MI : llvm::make_early_inc_range(MBB)) {
+    if (MI.isDebugInstr())
+      continue;
+
+    // Only match 8 and 16 bit register to register extends. Loads can't be
+    // eliminated. The 64 bit target versions are handled by the 32 bit
+    // versions.
+    unsigned Opc = MI.getOpcode();
+    if (Opc == X86::MOVZX32rr8 || Opc == X86::MOVZX32rr16) {
+      // The extend is redundant if the value is already zero extended from no
+      // more bits than it reads.
+      unsigned ReadBits = Opc == X86::MOVZX32rr8 ? 8 : 16;
+      MCRegister Dst = MI.getOperand(0).getReg().asMCReg();
+      MCRegister Src = MI.getOperand(1).getReg().asMCReg();
+      MCRegister SrcSuper = getX86SubSuperRegister(Src, 32);
+      auto It = Known.find(SrcSuper);
+      // Reading %ah and friends does not read the part of the super register
+      // that is known to hold the whole value, so insist on the low bits.
+      if (getX86SubSuperRegister(SrcSuper, ReadBits) == Src &&
+          It != Known.end() && It->second <= ReadBits) {
+
+        if (Dst == SrcSuper) {
+          // The extend writes back the value that is already in the register.
+          LLVM_DEBUG(dbgs() << "Removing redundant zero extend: " << MI);
+          MI.eraseFromParent();
+          continue;
+        }
+
+        // The extend is redundant but the move is not. A 32 bit copy is a
+        // byte shorter and can be eliminated at rename.
+        LLVM_DEBUG(dbgs() << "Turning zero extend into a copy: " << MI);
+        MachineInstrBuilder MIB =
+            BuildMI(MBB, MI, MIMetadata(MI), TII->get(X86::MOV32rr), Dst)
+                .addReg(SrcSuper);
+        if (unsigned OldInstrNum = MI.peekDebugInstrNum()) {
+          unsigned NewInstrNum = MIB->getDebugInstrNum(*MF);
+          MF->makeDebugValueSubstitution({OldInstrNum, 0}, {NewInstrNum, 0}, 0);
+        }
+        MI.eraseFromParent();
+
+        // The copy leaves the destination holding the value the source had,
+        // so it inherits what was known about it.
+        unsigned SrcBits = It->second;
+        Known[Dst] = SrcBits;
+        continue;
+      }
+    }
+
+    // Clear what this instruction overwrites. Two 32 bit registers never
+    // overlap, so a definition can only invalidate the one it is a sub or
+    // super register of.
+    for (const MachineOperand &MO : MI.operands()) {
+      if (MO.isRegMask()) {
+        SmallVector<MCRegister, 4> Clobbered;
+        for (auto &KnownReg : Known)
+          if (MO.clobbersPhysReg(KnownReg.first))
+            Clobbered.push_back(KnownReg.first);
+        for (MCRegister Reg : Clobbered)
+          Known.erase(Reg);
+      } else if (MO.isReg() && MO.isDef()) {
+        Known.erase(getX86SubSuperRegister(MO.getReg().asMCReg(), 32));
+      }
+    }
+
+    if (auto Bits = DefinedZeroExtendedValueBits(MI)) {
+      MCRegister Dst = MI.getOperand(0).getReg().asMCReg();
+      Known[getX86SubSuperRegister(Dst, 32)] = *Bits;
+    }
+  }
+}
+
 void X86FixupBWInstImpl::processBasicBlock(MachineFunction &MF,
                                            MachineBasicBlock &MBB) {
 
diff --git a/llvm/test/CodeGen/X86/2007-08-09-IllegalX86-64Asm.ll b/llvm/test/CodeGen/X86/2007-08-09-IllegalX86-64Asm.ll
index 7bdc4e19a1cf6..ba0eaa3013a79 100644
--- a/llvm/test/CodeGen/X86/2007-08-09-IllegalX86-64Asm.ll
+++ b/llvm/test/CodeGen/X86/2007-08-09-IllegalX86-64Asm.ll
@@ -77,7 +77,7 @@ define ptr @ubyte_divmod(ptr %a, ptr %b) {
 ; CHECK-NEXT:    je LBB0_11
 ; CHECK-NEXT:  ## %bb.7: ## %cond_false.i
 ; CHECK-NEXT:    movzbl {{[0-9]+}}(%rsp), %esi
-; CHECK-NEXT:    movzbl %sil, %ecx
+; CHECK-NEXT:    movl %esi, %ecx
 ; CHECK-NEXT:    movl %ecx, %eax
 ; CHECK-NEXT:    divb %dl
 ; CHECK-NEXT:    movl %eax, %r15d
diff --git a/llvm/test/CodeGen/X86/GlobalISel/callingconv.ll b/llvm/test/CodeGen/X86/GlobalISel/callingconv.ll
index ab8880734afe0..ca70f10b18b41 100644
--- a/llvm/test/CodeGen/X86/GlobalISel/callingconv.ll
+++ b/llvm/test/CodeGen/X86/GlobalISel/callingconv.ll
@@ -324,7 +324,7 @@ define void @test_abi_exts_call(ptr %addr) {
 ; X32-NEXT:    .cfi_offset %ebx, -8
 ; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax
 ; X32-NEXT:    movzbl (%eax), %ebx
-; X32-NEXT:    movzbl %bl, %esi
+; X32-NEXT:    movl %ebx, %esi
 ; X32-NEXT:    movl %esi, (%esp)
 ; X32-NEXT:    calll take_char
 ; X32-NEXT:    movsbl %bl, %eax
@@ -346,7 +346,7 @@ define void @test_abi_exts_call(ptr %addr) {
 ; X64-NEXT:    .cfi_def_cfa_offset 16
 ; X64-NEXT:    .cfi_offset %rbx, -16
 ; X64-NEXT:    movzbl (%rdi), %eax
-; X64-NEXT:    movzbl %al, %ebx
+; X64-NEXT:    movl %eax, %ebx
 ; X64-NEXT:    movl %ebx, %edi
 ; X64-NEXT:    callq take_char
 ; X64-NEXT:    movsbl %bl, %edi
diff --git a/llvm/test/CodeGen/X86/atomic-load-store.ll b/llvm/test/CodeGen/X86/atomic-load-store.ll
index 7cfe7af47748a..fca0ba894016f 100644
--- a/llvm/test/CodeGen/X86/atomic-load-store.ll
+++ b/llvm/test/CodeGen/X86/atomic-load-store.ll
@@ -76,7 +76,6 @@ define <1 x i32> @atomic_vec1_i8_zext(ptr %x) {
 ; CHECK-O3-LABEL: atomic_vec1_i8_zext:
 ; CHECK-O3:       # %bb.0:
 ; CHECK-O3-NEXT:    movzbl (%rdi), %eax
-; CHECK-O3-NEXT:    movzbl %al, %eax
 ; CHECK-O3-NEXT:    retq
 ;
 ; CHECK-O0-LABEL: atomic_vec1_i8_zext:
diff --git a/llvm/test/CodeGen/X86/fixup-bw-eliminate-redundant-zext.mir b/llvm/test/CodeGen/X86/fixup-bw-eliminate-redundant-zext.mir
new file mode 100644
index 0000000000000..f1f64b38a15bb
--- /dev/null
+++ b/llvm/test/CodeGen/X86/fixup-bw-eliminate-redundant-zext.mir
@@ -0,0 +1,157 @@
+# RUN: llc -mtriple=x86_64-- -run-pass x86-fixup-bw-insts -verify-machineinstrs %s -o - | FileCheck %s
+# RUN: llc -mtriple=x86_64-- -run-pass x86-fixup-bw-insts -verify-machineinstrs -fixup-bw-eliminate-redundant-zext=0 %s -o - | FileCheck %s --check-prefix=DISABLED
+
+--- |
+  define i32 @same_block(ptr %p) { ret i32 0 }
+  define i32 @across_blocks(ptr %p) { ret i32 0 }
+  define i32 @into_copy(ptr %p) { ret i32 0 }
+  define i32 @clobbered_super_reg(ptr %p) { ret i32 0 }
+  define i32 @high_byte_source(ptr %p) { ret i32 0 }
+  define i32 @word_from_byte(ptr %p) { ret i32 0 }
+  define i32 @byte_from_word(ptr %p) { ret i32 0 }
+...
+
+---
+# The load already zero extends $r12d, so the extend below it is a no-op.
+# CHECK-LABEL: name: same_block
+# CHECK:      $r12d = MOVZX32rm8
+# CHECK-NEXT: CMP32ri renamable $r12d, 13
+#
+# DISABLED-LABEL: name: same_block
+# DISABLED:      $r12d = MOVZX32rm8
+# DISABLED-NEXT: renamable $r12d = MOVZX32rr8 killed renamable $r12b
+name:            same_block
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $rdi
+
+    $r12d = MOVZX32rm8 killed renamable $rdi, 1, $noreg, 0, $noreg
+    renamable $r12d = MOVZX32rr8 killed renamable $r12b
+    CMP32ri renamable $r12d, 13, implicit-def $eflags
+    RET64 $r12d
+...
+
+---
+# The analysis is block local, so an extend in a successor is left alone even
+# though the only predecessor zero extends the value.  Removing it would mean
+# making $r9d live in to bb.1, which so far only needed $r9b.
+# CHECK-LABEL: name: across_blocks
+# CHECK:     $r9d = MOVZX32rm8
+# CHECK:   bb.1:
+# CHECK:     liveins: $r9b{{$}}
+# CHECK:     renamable $r9d = MOVZX32rr8 killed renamable $r9b
+name:            across_blocks
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    successors: %bb.1, %bb.2
+    liveins: $rdi
+
+    $r9d = MOVZX32rm8 killed renamable $rdi, 1, $noreg, 0, $noreg
+    CMP8ri renamable $r9b, 10, implicit-def $eflags
+    JCC_1 %bb.2, 4, implicit killed $eflags
+
+  bb.1:
+    successors: %bb.2
+    liveins: $r9b
+
+    renamable $r9d = MOVZX32rr8 killed renamable $r9b
+    CMP32ri renamable $r9d, 13, implicit-def $eflags
+
+  bb.2:
+    liveins: $r9d
+
+    RET64 $r9d
+...
+
+---
+# When the extend moves the value to a different register the move is still
+# needed, but it can be done 32 bits at a time.
+# CHECK-LABEL: name: into_copy
+# CHECK:      $eax = MOVZX32rm8
+# CHECK-NEXT: $ecx = MOV32rr $eax
+#
+# DISABLED-LABEL: name: into_copy
+# DISABLED:      $eax = MOVZX32rm8
+# DISABLED-NEXT: renamable $ecx = MOVZX32rr8 renamable $al
+name:            into_copy
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $rdi
+
+    $eax = MOVZX32rm8 killed renamable $rdi, 1, $noreg, 0, $noreg
+    renamable $ecx = MOVZX32rr8 renamable $al
+    RET64 $eax, $ecx
+...
+
+---
+# The add writes bits that the load had zeroed, so the extend is needed.
+# CHECK-LABEL: name: clobbered_super_reg
+# CHECK: renamable $r12d = MOVZX32rr8 killed renamable $r12b
+name:            clobbered_super_reg
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $rdi
+
+    $r12d = MOVZX32rm8 killed renamable $rdi, 1, $noreg, 0, $noreg
+    renamable $r12d = ADD32ri killed renamable $r12d, 65536, implicit-def $eflags
+    renamable $r12d = MOVZX32rr8 killed renamable $r12b
+    RET64 $r12d
+...
+
+---
+# Knowing that $eax is in [0, 0xFF] says that $ah is zero, not that the extend
+# leaves $eax alone, so this one has to stay.
+# CHECK-LABEL: name: high_byte_source
+# CHECK: renamable $eax = MOVZX32rr8 killed renamable $ah
+name:            high_byte_source
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $rdi
+
+    $eax = MOVZX32rm8 killed renamable $rdi, 1, $noreg, 0, $noreg
+    renamable $eax = MOVZX32rr8 killed renamable $ah
+    RET64 $eax
+...
+
+---
+# A value in [0, 0xFF] is also in [0, 0xFFFF], so extending it from its low
+# word does nothing either.
+# CHECK-LABEL: name: word_from_byte
+# CHECK:      $eax = MOVZX32rm8
+# CHECK-NEXT: CMP32ri renamable $eax, 13
+#
+# DISABLED-LABEL: name: word_from_byte
+# DISABLED:      $eax = MOVZX32rm8
+# DISABLED-NEXT: renamable $eax = MOVZX32rr16 killed renamable $ax
+name:            word_from_byte
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $rdi
+
+    $eax = MOVZX32rm8 killed renamable $rdi, 1, $noreg, 0, $noreg
+    renamable $eax = MOVZX32rr16 killed renamable $ax
+    CMP32ri renamable $eax, 13, implicit-def $eflags
+    RET64 $eax
+...
+
+---
+# The other way round does not hold: 0x1234 is in [0, 0xFFFF] but extending
+# it from its low byte gives 0x34, so this extend has to stay.
+# CHECK-LABEL: name: byte_from_word
+# CHECK: renamable $eax = MOVZX32rr8 killed renamable $al
+name:            byte_from_word
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $rdi
+
+    $eax = MOVZX32rm16 killed renamable $rdi, 1, $noreg, 0, $noreg
+    renamable $eax = MOVZX32rr8 killed renamable $al
+    RET64 $eax
+...
diff --git a/llvm/test/CodeGen/X86/isel-select-cmov.ll b/llvm/test/CodeGen/X86/isel-select-cmov.ll
index 6ced7f45b6233..a9a43a1663bc1 100644
--- a/llvm/test/CodeGen/X86/isel-select-cmov.ll
+++ b/llvm/test/CodeGen/X86/isel-select-cmov.ll
@@ -73,11 +73,9 @@ define zeroext i8 @select_cmov_i8(i1 zeroext %cond, i8 zeroext %a, i8 zeroext %b
 ; FAST-X86-NEXT:    jne LBB0_1
 ; FAST-X86-NEXT:  ## %bb.2:
 ; FAST-X86-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
-; FAST-X86-NEXT:    movzbl %al, %eax
 ; FAST-X86-NEXT:    retl
 ; FAST-X86-NEXT:  LBB0_1:
 ; FAST-X86-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
-; FAST-X86-NEXT:    movzbl %al, %eax
 ; FAST-X86-NEXT:    retl
 ;
 ; FAST-X86-CMOV-LABEL: select_cmov_i8:
@@ -86,11 +84,9 @@ define zeroext i8 @select_cmov_i8(i1 zeroext %cond, i8 zeroext %a, i8 zeroext %b
 ; FAST-X86-CMOV-NEXT:    jne LBB0_1
 ; FAST-X86-CMOV-NEXT:  ## %bb.2:
 ; FAST-X86-CMOV-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
-; FAST-X86-CMOV-NEXT:    movzbl %al, %eax
 ; FAST-X86-CMOV-NEXT:    retl
 ; FAST-X86-CMOV-NEXT:  LBB0_1:
 ; FAST-X86-CMOV-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
-; FAST-X86-CMOV-NEXT:    movzbl %al, %eax
 ; FAST-X86-CMOV-NEXT:    retl
 ;
 ; GISEL-X86-LABEL: select_cmov_i8:
@@ -181,11 +177,9 @@ define zeroext i16 @select_cmov_i16(i1 zeroext %cond, i16 zeroext %a, i16 zeroex
 ; FAST-X86-NEXT:    jne LBB1_1
 ; FAST-X86-NEXT:  ## %bb.2:
 ; FAST-X86-NEXT:    movzwl {{[0-9]+}}(%esp), %eax
-; FAST-X86-NEXT:    movzwl %ax, %eax
 ; FAST-X86-NEXT:    retl
 ; FAST-X86-NEXT:  LBB1_1:
 ; FAST-X86-NEXT:    movzwl {{[0-9]+}}(%esp), %eax
-; FAST-X86-NEXT:    movzwl %ax, %eax
 ; FAST-X86-NEXT:    retl
 ;
 ; FAST-X86-CMOV-LABEL: select_cmov_i16:
diff --git a/llvm/test/CodeGen/X86/isel-udiv.ll b/llvm/test/CodeGen/X86/isel-udiv.ll
index b123b3c7780fa..f96a12c2fafd0 100644
--- a/llvm/test/CodeGen/X86/isel-udiv.ll
+++ b/llvm/test/CodeGen/X86/isel-udiv.ll
@@ -22,7 +22,6 @@ define i8 @test_udiv_i8(i8 %arg1, i8 %arg2) nounwind {
 ; GISEL-X86-LABEL: test_udiv_i8:
 ; GISEL-X86:       # %bb.0:
 ; GISEL-X86-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
-; GISEL-X86-NEXT:    movzbl %al, %eax
 ; GISEL-X86-NEXT:    movzbl {{[0-9]+}}(%esp), %ecx
 ; GISEL-X86-NEXT:    divb %cl
 ; GISEL-X86-NEXT:    retl
diff --git a/llvm/test/CodeGen/X86/isel-urem.ll b/llvm/test/CodeGen/X86/isel-urem.ll
index 386f08151ad9c..5dd901fe8daa6 100644
--- a/llvm/test/CodeGen/X86/isel-urem.ll
+++ b/llvm/test/CodeGen/X86/isel-urem.ll
@@ -49,7 +49,6 @@ define i8 @test_urem_i8(i8 %arg1, i8 %arg2) nounwind {
 ; GISEL-X86-LABEL: test_urem_i8:
 ; GISEL-X86:       # %bb.0:
 ; GISEL-X86-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
-; GISEL-X86-NEXT:    movzbl %al, %eax
 ; GISEL-X86-NEXT:    movzbl {{[0-9]+}}(%esp), %ecx
 ; GISEL-X86-NEXT:    divb %cl
 ; GISEL-X86-NEXT:    movb %ah, %al
diff --git a/llvm/test/CodeGen/X86/load-local-v4i5.ll b/llvm/test/CodeGen/X86/load-local-v4i5.ll
index 1d119b1dfefc2..d470c590a1ac7 100644
--- a/llvm/test/CodeGen/X86/load-local-v4i5.ll
+++ b/llvm/test/CodeGen/X86/load-local-v4i5.ll
@@ -11,7 +11,7 @@ define void @_start() {
 ; CHECK-NEXT:    movzbl -9(%rsp), %ecx
 ; CHECK-NEXT:    movzbl -10(%rsp), %edx
 ; CHECK-NEXT:    movzbl -11(%rsp), %esi
-; CHECK-NEXT:    movzbl %cl, %edi
+; CHECK-NEXT:    movl %ecx, %edi
 ; CHECK-NEXT:    shrb %cl
 ; CHECK-NEXT:    movb %cl, -2(%rsp)
 ; CHECK-NEXT:    andl $31, %eax
diff --git a/llvm/test/CodeGen/X86/popcnt.ll b/llvm/test/CodeGen/X86/popcnt.ll
index 3004b8b72fcc5..0e3f907e8d5be 100644
--- a/llvm/test/CodeGen/X86/popcnt.ll
+++ b/llvm/test/CodeGen/X86/popcnt.ll
@@ -1890,7 +1890,6 @@ define i32 @popcount_i16_zext(i16 zeroext %x) {
 ; X64-NDD-NEXT:    movzbl %ah, %ecx
 ; X64-NDD-NEXT:    addw %cx, %ax
 ; X64-NDD-NEXT:    movzbl %al, %eax
-; X64-NDD-NEXT:    movzwl %ax, %eax
 ; X64-NDD-NEXT:    retq
   %cnt = tail call i16 @llvm.ctpop.i16(i16 %x)
   %z = zext i16 %cnt to i32
diff --git a/llvm/test/CodeGen/X86/pr15267.ll b/llvm/test/CodeGen/X86/pr15267.ll
index 5083eac71dce0..a8c4b9eb6370d 100644
--- a/llvm/test/CodeGen/X86/pr15267.ll
+++ b/llvm/test/CodeGen/X86/pr15267.ll
@@ -50,7 +50,7 @@ define <4 x i64> @test3(ptr %in) nounwind {
 ; CHECK-LABEL: test3:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    movzbl (%rdi), %eax
-; CHECK-NEXT:    movzbl %al, %ecx
+; CHECK-NEXT:    movl %eax, %ecx
 ; CHECK-NEXT:    shrb %al
 ; CHECK-NEXT:    movzbl %al, %eax
 ; CHECK-NEXT:    andl $1, %eax
diff --git a/llvm/test/CodeGen/X86/pr38539.ll b/llvm/test/CodeGen/X86/pr38539.ll
index eecd15dd2afe9..6cd27afe75842 100644
--- a/llvm/test/CodeGen/X86/pr38539.ll
+++ b/llvm/test/CodeGen/X86/pr38539.ll
@@ -28,7 +28,6 @@ define void @f() nounwind {
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %ebx
 ; X86-NEXT:    movzbl (%eax), %eax
 ; X86-NEXT:    movzbl (%eax), %ecx
-; X86-NEXT:    movzbl %al, %eax
 ; X86-NEXT:    movb %cl, {{[-0-9]+}}(%e{{[sb]}}p) # 1-byte Spill
 ; X86-NEXT:    divb %cl
 ; X86-NEXT:    movl %edi, %eax
diff --git a/llvm/test/CodeGen/X86/promote-assert-zext.ll b/llvm/test/CodeGen/X86/promote-assert-zext.ll
index d9e2585262ab7..feec7de48bd19 100644
--- a/llvm/test/CodeGen/X86/promote-assert-zext.ll
+++ b/llvm/test/CodeGen/X86/promote-assert-zext.ll
@@ -1,6 +1,11 @@
-; RUN: llc < %s | FileCheck %s
+; RUN: llc < %s -fixup-bw-eliminate-redundant-zext=0 | FileCheck %s
 ; rdar://8051990
 
+; The zero-extend below is removed later on, by X86FixupBWInsts, which can
+; prove from the widened load that it is a no-op. That is disabled here so
+; that this keeps testing what it was written to test, that ISel does not
+; remove it: without the extra instruction the two outcomes are the same.
+
 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
 target triple = "x86_64-apple-darwin11"
 
diff --git a/llvm/test/CodeGen/X86/vector-compress.ll b/llvm/test/CodeGen/X86/vector-compress.ll
index 018c3d36ee60d..a055319f346ef 100644
--- a/llvm/test/CodeGen/X86/vector-compress.ll
+++ b/llvm/test/CodeGen/X86/vector-compress.ll
@@ -2236,7 +2236,7 @@ define <64 x i8> @test_compress_v64i8(<64 x i8> %vec, <64 x i1> %mask, <64 x i8>
 ; AVX2-NEXT:    vpextrb $5, %xmm0, (%rsp,%rax)
 ; AVX2-NEXT:    andl $1, %r9d
 ; AVX2-NEXT:    addq %r8, %r9
-; AVX2-NEXT:    movzbl %r10b, %eax
+; AVX2-NEXT:    movl %r10d, %eax
 ; AVX2-NEXT:    andl $1, %eax
 ; AVX2-NEXT:    addq %r9, %rax
 ; AVX2-NEXT:    # kill: def $r9d killed $r9d killed $r9 def $r9
@@ -2245,10 +2245,10 @@ define <64 x i8> @test_compress_v64i8(<64 x i8> %vec, <64 x i1> %mask, <64 x i8>
 ; AVX2-NEXT:    movl %eax, %ecx
 ; AVX2-NEXT:    andl $63, %ecx
 ; AVX2-NEXT:    vpextrb $7, %xmm0, (%rsp,%rcx)
-; AVX2-NEXT:    movzbl %r11b, %ecx
+; AVX2-NEX...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/217923


More information about the llvm-commits mailing list