[llvm] [X86] Widen zero-extended narrow lshr before isel (PR #207919)
Jaeuk Lee via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 7 01:11:27 PDT 2026
https://github.com/skku970412 updated https://github.com/llvm/llvm-project/pull/207919
>From 775cc41cf41dd3c5e649e4cd8f09fd2186d259ff Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=9D=B4=EC=9E=AC=EC=9A=B1?=
<126692701+skku970412 at users.noreply.github.com>
Date: Tue, 7 Jul 2026 16:44:05 +0900
Subject: [PATCH 1/2] [X86] Widen zero-extended narrow lshr before isel
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 32 +++++++++++++++++++++++++
llvm/test/CodeGen/X86/pr205898.ll | 31 ++++++++++++++++++++++++
2 files changed, 63 insertions(+)
create mode 100644 llvm/test/CodeGen/X86/pr205898.ll
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 9209134a055c6..407f15688da30 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -57647,6 +57647,38 @@ static SDValue combineZext(SDNode *N, SelectionDAG &DAG,
DAG, DCI, Subtarget))
return V;
+ // If an AssertZext-backed wide source is known to have zeros above the
+ // truncated type, prefer shifting the wide value directly. This avoids an
+ // 8/16-bit shift followed by a zero-extend when the result is used in a
+ // wider register, for example as an address index.
+ if (N->getOpcode() == ISD::ZERO_EXTEND &&
+ (VT == MVT::i32 || VT == MVT::i64) && N0.getOpcode() == ISD::SRL &&
+ N0.hasOneUse()) {
+ SDValue Trunc = N0.getOperand(0);
+ EVT NarrowVT = Trunc.getValueType();
+
+ if (Trunc.getOpcode() == ISD::TRUNCATE && Trunc.hasOneUse() &&
+ NarrowVT.isScalarInteger()) {
+ SDValue Wide = Trunc.getOperand(0);
+ EVT WideVT = Wide.getValueType();
+ unsigned NarrowBits = NarrowVT.getSizeInBits();
+ unsigned WideBits = WideVT.getSizeInBits();
+ std::optional<unsigned> ShiftAmt = DAG.getValidShiftAmount(N0);
+
+ if (WideVT == VT && Wide.getOpcode() == ISD::AssertZext && ShiftAmt &&
+ *ShiftAmt < NarrowBits) {
+ APInt HighBits =
+ APInt::getHighBitsSet(WideBits, WideBits - NarrowBits);
+ if (DAG.MaskedValueIsZero(Wide, HighBits)) {
+ SDValue WideShiftAmt =
+ DAG.getShiftAmountConstant(*ShiftAmt, VT, SDLoc(N0));
+ return DAG.getNode(ISD::SRL, SDLoc(N0), VT, Wide, WideShiftAmt,
+ N0->getFlags());
+ }
+ }
+ }
+ }
+
if (VT.isVector())
if (SDValue R = PromoteMaskArithmetic(SDValue(N, 0), dl, DAG, Subtarget))
return R;
diff --git a/llvm/test/CodeGen/X86/pr205898.ll b/llvm/test/CodeGen/X86/pr205898.ll
new file mode 100644
index 0000000000000..e51743cc30036
--- /dev/null
+++ b/llvm/test/CodeGen/X86/pr205898.ll
@@ -0,0 +1,31 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu | FileCheck %s
+
+define i64 @known_zero_trunc_lshr_index(i8 zeroext %b, ptr %p) {
+; CHECK-LABEL: known_zero_trunc_lshr_index:
+; CHECK: # %bb.0:
+; CHECK-NEXT: # kill: def $edi killed $edi def $rdi
+; CHECK-NEXT: shrl $6, %edi
+; CHECK-NEXT: movq (%rsi,%rdi,8), %rax
+; CHECK-NEXT: retq
+ %shr = lshr i8 %b, 6
+ %idx = zext i8 %shr to i64
+ %gep = getelementptr i64, ptr %p, i64 %idx
+ %load = load i64, ptr %gep, align 8
+ ret i64 %load
+}
+
+define i64 @do_not_widen_trunc_lshr_without_known_high_zero(i32 %x, ptr %p) {
+; CHECK-LABEL: do_not_widen_trunc_lshr_without_known_high_zero:
+; CHECK: # %bb.0:
+; CHECK-NEXT: shrb $6, %dil
+; CHECK-NEXT: movzbl %dil, %eax
+; CHECK-NEXT: movq (%rsi,%rax,8), %rax
+; CHECK-NEXT: retq
+ %tr = trunc i32 %x to i8
+ %shr = lshr i8 %tr, 6
+ %idx = zext i8 %shr to i64
+ %gep = getelementptr i64, ptr %p, i64 %idx
+ %load = load i64, ptr %gep, align 8
+ ret i64 %load
+}
>From 1a384b92a7487ebeae495dd721a14d960a2f2b53 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=9D=B4=EC=9E=AC=EC=9A=B1?=
<126692701+skku970412 at users.noreply.github.com>
Date: Tue, 7 Jul 2026 17:10:55 +0900
Subject: [PATCH 2/2] [X86] Format narrow shift combine
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 407f15688da30..fe0d34b93e1f5 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -57667,8 +57667,7 @@ static SDValue combineZext(SDNode *N, SelectionDAG &DAG,
if (WideVT == VT && Wide.getOpcode() == ISD::AssertZext && ShiftAmt &&
*ShiftAmt < NarrowBits) {
- APInt HighBits =
- APInt::getHighBitsSet(WideBits, WideBits - NarrowBits);
+ APInt HighBits = APInt::getHighBitsSet(WideBits, WideBits - NarrowBits);
if (DAG.MaskedValueIsZero(Wide, HighBits)) {
SDValue WideShiftAmt =
DAG.getShiftAmountConstant(*ShiftAmt, VT, SDLoc(N0));
More information about the llvm-commits
mailing list