[llvm] [GlobalISel] [AArch64] Skip redundant shift amount masking during isel (PR #223136)

David Green via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 30 00:49:39 PDT 2026


================
@@ -7305,6 +7303,45 @@ AArch64InstructionSelector::selectShiftB_64(const MachineOperand &Root) const {
   return {{[=](MachineInstrBuilder &MIB) { MIB.addImm(Enc); }}};
 }
 
+template <unsigned ShiftWidth>
+InstructionSelector::ComplexRendererFns
+AArch64InstructionSelector::selectShiftMask(MachineOperand &Root) const {
+  if (!Root.isReg())
+    return std::nullopt;
+
+  MachineRegisterInfo &MRI =
+      Root.getParent()->getParent()->getParent()->getRegInfo();
+
+  Register ShAmtReg = Root.getReg();
+
+  // Peek through zext for i32 shifts only. For i64 shifts the zext case
+  // is already handled by existing patterns in the Shift multiclass.
+  if (ShiftWidth == 32) {
+    Register ZExtSrcReg;
+    if (mi_match(ShAmtReg, MRI, m_GZExt(m_Reg(ZExtSrcReg))))
+      ShAmtReg = ZExtSrcReg;
+  }
+
+  // Remove redundant AND mask that exactly covers a narrow type (byte,
+  // halfword, word) and whose result type matches the shift width. This
+  // avoids removing intentional masks used in fshl/fshr computations.
+  APInt AndMask;
+  Register AndSrcReg;
+  if (mi_match(ShAmtReg, MRI, m_GAnd(m_Reg(AndSrcReg), m_ICst(AndMask))) &&
+      MRI.getType(ShAmtReg).getSizeInBits() == ShiftWidth) {
+    uint64_t UMask = AndMask.getZExtValue();
+    if (UMask == 0xff || UMask == 0xffff || UMask == 0xffffffff)
----------------
davemgreen wrote:

Mask.countr_one() > ShiftWidth

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


More information about the llvm-commits mailing list