[llvm] [GlobalISel] Use G_ANYEXT instead of G_ZEXT for shift amount widening (PR #223136)

Deepak Shirke via llvm-commits llvm-commits at lists.llvm.org
Sun Sep 13 04:50:16 PDT 2026


https://github.com/deepakshirkem updated https://github.com/llvm/llvm-project/pull/223136

>From e86a0f24fe49d08c3e9826fd8dfdf15bf4ec1907 Mon Sep 17 00:00:00 2001
From: deepakshirkem <deepakshirke509 at gmail.com>
Date: Sun, 13 Sep 2026 16:35:36 +0530
Subject: [PATCH] AArch64/GlobalISel: Skip redundant AND/ZEXT on shift amounts
 during isel

AArch64 shift instructions (LSL/LSR/ASR) only use the low 5 bits (i32)
or 6 bits (i64) of the shift amount. When the shift amount is zero-extended
from a narrower type or masked with an AND that covers enough bits, the
extend/mask is redundant and can be skipped during instruction selection.

This mirrors what AArch64DAGToDAGISel::tryShiftAmountMod does for
SelectionDAG, bringing GlobalISel to parity for i32 shift amounts.
---
 .../GISel/AArch64InstructionSelector.cpp      | 11 ++++
 .../AArch64/GlobalISel/shift-amount-mod.ll    | 63 +++++++++++++++++++
 2 files changed, 74 insertions(+)
 create mode 100644 llvm/test/CodeGen/AArch64/GlobalISel/shift-amount-mod.ll

diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
index 442d061e71cb8..e0b8c4e44fc64 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
@@ -3158,6 +3158,17 @@ bool AArch64InstructionSelector::select(MachineInstr &I) {
         MRI.setRegBank(Trunc.getReg(0), RBI.getRegBank(AArch64::GPRRegBankID));
         I.getOperand(2).setReg(Trunc.getReg(0));
       }
+
+      // Mirror tryShiftAmountMod from AArch64DAGToDAGISel.
+      // AArch64 shift instructions only use the low 5 bits (i32) or 6 bits
+      // (i64) of the shift amount. If the shift amount is zero-extended from
+      // a narrower type, we can skip the extension.
+      if (!SrcTy.isVector()) {
+        Register ZExtSrc;
+        if (mi_match(I.getOperand(2).getReg(), MRI,
+                     m_OneNonDBGUse(m_GZExt(m_Reg(ZExtSrc)))))
+          I.getOperand(2).setReg(ZExtSrc);
+      }
     }
 
     const unsigned OpSize = Ty.getSizeInBits();
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/shift-amount-mod.ll b/llvm/test/CodeGen/AArch64/GlobalISel/shift-amount-mod.ll
new file mode 100644
index 0000000000000..6fd43f096dd45
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/shift-amount-mod.ll
@@ -0,0 +1,63 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -global-isel -mtriple=aarch64 < %s | FileCheck %s --check-prefix=GI
+; RUN: llc -mtriple=aarch64 < %s | FileCheck %s --check-prefix=SD
+
+define i32 @shl_i32_i8(i32 %x, i8 %amt) {
+; GI-LABEL: shl_i32_i8:
+; GI:       // %bb.0:
+; GI-NEXT:    lsl w0, w0, w1
+; GI-NEXT:    ret
+;
+; SD-LABEL: shl_i32_i8:
+; SD:       // %bb.0:
+; SD-NEXT:    lsl w0, w0, w1
+; SD-NEXT:    ret
+  %ext = zext i8 %amt to i32
+  %r = shl i32 %x, %ext
+  ret i32 %r
+}
+
+define i32 @lshr_i32_i8(i32 %x, i8 %amt) {
+; GI-LABEL: lshr_i32_i8:
+; GI:       // %bb.0:
+; GI-NEXT:    lsr w0, w0, w1
+; GI-NEXT:    ret
+;
+; SD-LABEL: lshr_i32_i8:
+; SD:       // %bb.0:
+; SD-NEXT:    lsr w0, w0, w1
+; SD-NEXT:    ret
+  %ext = zext i8 %amt to i32
+  %r = lshr i32 %x, %ext
+  ret i32 %r
+}
+
+define i32 @ashr_i32_i8(i32 %x, i8 %amt) {
+; GI-LABEL: ashr_i32_i8:
+; GI:       // %bb.0:
+; GI-NEXT:    asr w0, w0, w1
+; GI-NEXT:    ret
+;
+; SD-LABEL: ashr_i32_i8:
+; SD:       // %bb.0:
+; SD-NEXT:    asr w0, w0, w1
+; SD-NEXT:    ret
+  %ext = zext i8 %amt to i32
+  %r = ashr i32 %x, %ext
+  ret i32 %r
+}
+
+define i32 @shl_i32_i16(i32 %x, i16 %amt) {
+; GI-LABEL: shl_i32_i16:
+; GI:       // %bb.0:
+; GI-NEXT:    lsl w0, w0, w1
+; GI-NEXT:    ret
+;
+; SD-LABEL: shl_i32_i16:
+; SD:       // %bb.0:
+; SD-NEXT:    lsl w0, w0, w1
+; SD-NEXT:    ret
+  %ext = zext i16 %amt to i32
+  %r = shl i32 %x, %ext
+  ret i32 %r
+}



More information about the llvm-commits mailing list