diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h b/llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h --- a/llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h @@ -594,6 +594,30 @@ return UnaryOp_match(Src); } +template struct SextInRegOp_match { + SrcTy L; + int64_t &R; + + SextInRegOp_match(const SrcTy &LHS, int64_t &RHS) : L(LHS), R(RHS) {} + template + bool match(const MachineRegisterInfo &MRI, OpTy &&Op) { + MachineInstr *TmpMI; + if (mi_match(Op, MRI, m_MInstr(TmpMI))) { + if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 3) { + R = TmpMI->getOperand(2).getImm(); + return L.match(MRI, TmpMI->getOperand(1).getReg()); + } + } + return false; + } +}; + +template +inline SextInRegOp_match +m_GSExtInReg(const SrcTy &Src, int64_t &BitPos) { + return SextInRegOp_match(Src, BitPos); +} + // General helper for generic MI compares, i.e. G_ICMP and G_FCMP // TODO: Allow checking a specific predicate. template diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp --- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp @@ -4351,13 +4351,18 @@ Register ShlSrc; int64_t ShrAmt; int64_t ShlAmt; - const unsigned Size = Ty.getScalarSizeInBits(); + int64_t Size = Ty.getScalarSizeInBits(); // Try to match shr (shl x, c1), c2 - if (!mi_match(Dst, MRI, - m_BinOp(Opcode, - m_OneNonDBGUse(m_GShl(m_Reg(ShlSrc), m_ICst(ShlAmt))), - m_ICst(ShrAmt)))) + if (!mi_match( + Dst, MRI, + m_BinOp( + Opcode, + m_any_of(m_GSExtInReg(m_OneNonDBGUse( + m_GShl(m_Reg(ShlSrc), m_ICst(ShlAmt))), + Size), + m_OneNonDBGUse(m_GShl(m_Reg(ShlSrc), m_ICst(ShlAmt)))), + m_ICst(ShrAmt)))) return false; // Make sure that the shift sizes can fit a bitfield extract diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/form-bitfield-extract-from-shr.mir b/llvm/test/CodeGen/AArch64/GlobalISel/form-bitfield-extract-from-shr.mir --- a/llvm/test/CodeGen/AArch64/GlobalISel/form-bitfield-extract-from-shr.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/form-bitfield-extract-from-shr.mir @@ -176,3 +176,47 @@ %5:_(s32) = G_MUL %3, %4 $w0 = COPY %5(s32) ... + +--- +name: test_ashr_sextinreg_shl_to_sbfx +legalized: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_ashr_sextinreg_shl_to_sbfx + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 4 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 + ; CHECK-NEXT: [[SBFX:%[0-9]+]]:_(s32) = G_SBFX [[COPY]], [[C1]](s32), [[C]] + ; CHECK-NEXT: $w0 = COPY [[SBFX]](s32) + %0:_(s32) = COPY $w0 + %1:_(s32) = G_CONSTANT i32 3 + %2:_(s32) = G_CONSTANT i32 4 + %3:_(s32) = COPY %1:_(s32) + %4:_(s32) = G_SHL %0:_, %3:_(s32) + %5:_(s32) = COPY %2:_(s32) + %6:_(s32) = G_SEXT_INREG %4:_, 8 + %7:_(s32) = G_ASHR %6:_, %5:_(s32) + $w0 = COPY %7:_(s32) +... + +--- +name: test_lshr_sextinreg_shl_to_sbfx +legalized: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_lshr_sextinreg_shl_to_sbfx + ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 4 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 + ; CHECK-NEXT: [[UBFX:%[0-9]+]]:_(s32) = G_UBFX [[COPY]], [[C1]](s32), [[C]] + ; CHECK-NEXT: $w0 = COPY [[UBFX]](s32) + %0:_(s32) = COPY $w0 + %1:_(s32) = G_CONSTANT i32 3 + %2:_(s32) = G_CONSTANT i32 4 + %3:_(s32) = COPY %1:_(s32) + %4:_(s32) = G_SHL %0:_, %3:_(s32) + %5:_(s32) = COPY %2:_(s32) + %6:_(s32) = G_SEXT_INREG %4:_, 8 + %7:_(s32) = G_LSHR %6:_, %5:_(s32) + $w0 = COPY %7:_(s32) +...