Skip to content

[AArch64][GlobalISel] Add a constant funnel shift post-legalizer combine. #151912

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -627,7 +627,8 @@ class CombinerHelper {
/// This variant does not erase \p MI after calling the build function.
void applyBuildFnNoErase(MachineInstr &MI, BuildFnTy &MatchInfo) const;

bool matchOrShiftToFunnelShift(MachineInstr &MI, BuildFnTy &MatchInfo) const;
bool matchOrShiftToFunnelShift(MachineInstr &MI, bool ScalarConstantsAreLegal,
BuildFnTy &MatchInfo) const;
bool matchFunnelShiftToRotate(MachineInstr &MI) const;
void applyFunnelShiftToRotate(MachineInstr &MI) const;
bool matchRotateOutOfRange(MachineInstr &MI) const;
Expand Down
10 changes: 9 additions & 1 deletion llvm/include/llvm/Target/GlobalISel/Combine.td
Original file line number Diff line number Diff line change
Expand Up @@ -1000,10 +1000,18 @@ def extract_vec_elt_combines : GICombineGroup<[
def funnel_shift_from_or_shift : GICombineRule<
(defs root:$root, build_fn_matchinfo:$info),
(match (wip_match_opcode G_OR):$root,
[{ return Helper.matchOrShiftToFunnelShift(*${root}, ${info}); }]),
[{ return Helper.matchOrShiftToFunnelShift(*${root}, false, ${info}); }]),
(apply [{ Helper.applyBuildFn(*${root}, ${info}); }])
>;

def funnel_shift_from_or_shift_constants_are_legal : GICombineRule<
(defs root:$root, build_fn_matchinfo:$info),
(match (wip_match_opcode G_OR):$root,
[{ return Helper.matchOrShiftToFunnelShift(*${root}, true, ${info}); }]),
(apply [{ Helper.applyBuildFn(*${root}, ${info}); }])
>;


def funnel_shift_to_rotate : GICombineRule<
(defs root:$root),
(match (wip_match_opcode G_FSHL, G_FSHR):$root,
Expand Down
9 changes: 4 additions & 5 deletions llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4390,6 +4390,7 @@ void CombinerHelper::applyBuildFnNoErase(
}

bool CombinerHelper::matchOrShiftToFunnelShift(MachineInstr &MI,
bool ScalarConstantsAreLegal,
BuildFnTy &MatchInfo) const {
assert(MI.getOpcode() == TargetOpcode::G_OR);

Expand All @@ -4409,31 +4410,29 @@ bool CombinerHelper::matchOrShiftToFunnelShift(MachineInstr &MI,

// Given constants C0 and C1 such that C0 + C1 is bit-width:
// (or (shl x, C0), (lshr y, C1)) -> (fshl x, y, C0) or (fshr x, y, C1)
int64_t CstShlAmt, CstLShrAmt;
int64_t CstShlAmt = 0, CstLShrAmt;
if (mi_match(ShlAmt, MRI, m_ICstOrSplat(CstShlAmt)) &&
mi_match(LShrAmt, MRI, m_ICstOrSplat(CstLShrAmt)) &&
CstShlAmt + CstLShrAmt == BitWidth) {
FshOpc = TargetOpcode::G_FSHR;
Amt = LShrAmt;

} else if (mi_match(LShrAmt, MRI,
m_GSub(m_SpecificICstOrSplat(BitWidth), m_Reg(Amt))) &&
ShlAmt == Amt) {
// (or (shl x, amt), (lshr y, (sub bw, amt))) -> (fshl x, y, amt)
FshOpc = TargetOpcode::G_FSHL;

} else if (mi_match(ShlAmt, MRI,
m_GSub(m_SpecificICstOrSplat(BitWidth), m_Reg(Amt))) &&
LShrAmt == Amt) {
// (or (shl x, (sub bw, amt)), (lshr y, amt)) -> (fshr x, y, amt)
FshOpc = TargetOpcode::G_FSHR;

} else {
return false;
}

LLT AmtTy = MRI.getType(Amt);
if (!isLegalOrBeforeLegalizer({FshOpc, {Ty, AmtTy}}))
if (!isLegalOrBeforeLegalizer({FshOpc, {Ty, AmtTy}}) &&
(!ScalarConstantsAreLegal || CstShlAmt == 0 || !Ty.isScalar()))
return false;

MatchInfo = [=](MachineIRBuilder &B) {
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Target/AArch64/AArch64Combine.td
Original file line number Diff line number Diff line change
Expand Up @@ -367,5 +367,6 @@ def AArch64PostLegalizerCombiner
select_to_minmax, or_to_bsp, combine_concat_vector,
commute_constant_to_rhs, extract_vec_elt_combines,
push_freeze_to_prevent_poison_from_propagating,
combine_mul_cmlt, combine_use_vector_truncate, extmultomull]> {
combine_mul_cmlt, combine_use_vector_truncate, extmultomull,
funnel_shift_from_or_shift_constants_are_legal]> {
}
6 changes: 2 additions & 4 deletions llvm/test/CodeGen/AArch64/adc.ll
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,8 @@ define i128 @test_shifted(i128 %a, i128 %b) {
;
; CHECK-GI-LABEL: test_shifted:
; CHECK-GI: ; %bb.0:
; CHECK-GI-NEXT: lsr x8, x2, #19
; CHECK-GI-NEXT: extr x8, x3, x2, #19
; CHECK-GI-NEXT: adds x0, x0, x2, lsl #45
; CHECK-GI-NEXT: orr x8, x8, x3, lsl #45
; CHECK-GI-NEXT: adc x1, x1, x8
; CHECK-GI-NEXT: ret
%rhs = shl i128 %b, 45
Expand Down Expand Up @@ -108,8 +107,7 @@ define i128 @test_extended(i128 %a, i16 %b) {
; CHECK-GI-NEXT: sxth x8, w2
; CHECK-GI-NEXT: adds x0, x0, w2, sxth #3
; CHECK-GI-NEXT: asr x9, x8, #63
; CHECK-GI-NEXT: lsr x8, x8, #61
; CHECK-GI-NEXT: orr x8, x8, x9, lsl #3
; CHECK-GI-NEXT: extr x8, x9, x8, #61
; CHECK-GI-NEXT: adc x1, x1, x8
; CHECK-GI-NEXT: ret
%ext = sext i16 %b to i128
Expand Down
Loading