forked from OSchip/llvm-project
[GISel] Add new combines for G_ADD
Patch adds new GICombineRules for G_ADD: G_ADD(x, G_SUB(y, x)) -> y G_ADD(G_SUB(y, x), x) -> y Patch additionally adds new combine tests for AArch64 target for these new rules. Reviewed by: paquette Differential Revision: https://reviews.llvm.org/D87936
This commit is contained in:
parent
99069ab212
commit
b7fcf6632f
|
@ -736,6 +736,10 @@ public:
|
|||
|
||||
bool matchCombineFMinMaxNaN(MachineInstr &MI, unsigned &Info);
|
||||
|
||||
/// Transform G_ADD(x, G_SUB(y, x)) to y.
|
||||
/// Transform G_ADD(G_SUB(y, x), x) to y.
|
||||
bool matchAddSubSameReg(MachineInstr &MI, Register &Src);
|
||||
|
||||
private:
|
||||
/// Given a non-indexed load or store instruction \p MI, find an offset that
|
||||
/// can be usefully and legally folded into it as a post-indexing operation.
|
||||
|
|
|
@ -891,13 +891,21 @@ def combine_fsub_fpext_fneg_fmul_to_fmad_or_fma: GICombineRule<
|
|||
*${root}, ${info}); }]),
|
||||
(apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;
|
||||
|
||||
def combine_minmax_nan_matchinfo: GIDefMatchData<"unsigned">;
|
||||
def combine_minmax_nan: GICombineRule<
|
||||
(defs root:$root, combine_minmax_nan_matchinfo:$info),
|
||||
(defs root:$root, unsigned_matchinfo:$info),
|
||||
(match (wip_match_opcode G_FMINNUM, G_FMAXNUM, G_FMINIMUM, G_FMAXIMUM):$root,
|
||||
[{ return Helper.matchCombineFMinMaxNaN(*${root}, ${info}); }]),
|
||||
(apply [{ Helper.replaceSingleDefInstWithOperand(*${root}, ${info}); }])>;
|
||||
|
||||
// Transform (add x, (sub y, x)) -> y
|
||||
// Transform (add (sub y, x), x) -> y
|
||||
def add_sub_reg: GICombineRule <
|
||||
(defs root:$root, register_matchinfo:$matchinfo),
|
||||
(match (wip_match_opcode G_ADD):$root,
|
||||
[{ return Helper.matchAddSubSameReg(*${root}, ${matchinfo}); }]),
|
||||
(apply [{ return Helper.replaceSingleDefInstWithReg(*${root},
|
||||
${matchinfo}); }])>;
|
||||
|
||||
// FIXME: These should use the custom predicate feature once it lands.
|
||||
def undef_combines : GICombineGroup<[undef_to_fp_zero, undef_to_int_zero,
|
||||
undef_to_negative_one,
|
||||
|
@ -913,7 +921,8 @@ def identity_combines : GICombineGroup<[select_same_val, right_identity_zero,
|
|||
binop_same_val, binop_left_to_zero,
|
||||
binop_right_to_zero, p2i_to_i2p,
|
||||
i2p_to_p2i, anyext_trunc_fold,
|
||||
fneg_fneg_fold, right_identity_one]>;
|
||||
fneg_fneg_fold, right_identity_one,
|
||||
add_sub_reg]>;
|
||||
|
||||
def const_combines : GICombineGroup<[constant_fp_op, const_ptradd_to_i2p,
|
||||
overlapping_and, mulo_by_2, mulo_by_0,
|
||||
|
|
|
@ -5633,6 +5633,22 @@ bool CombinerHelper::matchCombineFMinMaxNaN(MachineInstr &MI,
|
|||
return MatchNaN(1) || MatchNaN(2);
|
||||
}
|
||||
|
||||
bool CombinerHelper::matchAddSubSameReg(MachineInstr &MI, Register &Src) {
|
||||
assert(MI.getOpcode() == TargetOpcode::G_ADD && "Expected a G_ADD");
|
||||
Register LHS = MI.getOperand(1).getReg();
|
||||
Register RHS = MI.getOperand(2).getReg();
|
||||
|
||||
// Helper lambda to check for opportunities for
|
||||
// A + (B - A) -> B
|
||||
// (B - A) + A -> B
|
||||
auto CheckFold = [&](Register MaybeSub, Register MaybeSameReg) {
|
||||
Register Reg;
|
||||
return mi_match(MaybeSub, MRI, m_GSub(m_Reg(Src), m_Reg(Reg))) &&
|
||||
Reg == MaybeSameReg;
|
||||
};
|
||||
return CheckFold(LHS, RHS) || CheckFold(RHS, LHS);
|
||||
}
|
||||
|
||||
bool CombinerHelper::tryCombine(MachineInstr &MI) {
|
||||
if (tryCombineCopy(MI))
|
||||
return true;
|
||||
|
|
|
@ -0,0 +1,129 @@
|
|||
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
|
||||
# RUN: llc -run-pass=aarch64-prelegalizer-combiner -verify-machineinstrs -mtriple aarch64-unknown-unknown %s -o - | FileCheck %s
|
||||
|
||||
---
|
||||
name: add_lhs_sub_reg
|
||||
alignment: 4
|
||||
tracksRegLiveness: true
|
||||
frameInfo:
|
||||
maxAlignment: 1
|
||||
machineFunctionInfo: {}
|
||||
body: |
|
||||
bb.0:
|
||||
liveins: $w0, $w1
|
||||
; CHECK-LABEL: name: add_lhs_sub_reg
|
||||
; CHECK: liveins: $w0, $w1
|
||||
; CHECK-NEXT: {{ $}}
|
||||
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
|
||||
; CHECK-NEXT: $w0 = COPY [[COPY]](s32)
|
||||
%0:_(s32) = COPY $w0
|
||||
%1:_(s32) = COPY $w1
|
||||
%2:_(s32) = G_SUB %0, %1
|
||||
%3:_(s32) = G_ADD %2, %1
|
||||
$w0 = COPY %3
|
||||
...
|
||||
---
|
||||
name: add_lhs_sub_reg_wide
|
||||
alignment: 4
|
||||
tracksRegLiveness: true
|
||||
frameInfo:
|
||||
maxAlignment: 1
|
||||
machineFunctionInfo: {}
|
||||
body: |
|
||||
bb.0:
|
||||
liveins: $q0, $q1
|
||||
; CHECK-LABEL: name: add_lhs_sub_reg_wide
|
||||
; CHECK: liveins: $q0, $q1
|
||||
; CHECK-NEXT: {{ $}}
|
||||
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s128) = COPY $q0
|
||||
; CHECK-NEXT: $q0 = COPY [[COPY]](s128)
|
||||
%0:_(s128) = COPY $q0
|
||||
%1:_(s128) = COPY $q1
|
||||
%2:_(s128) = G_SUB %0, %1
|
||||
%3:_(s128) = G_ADD %2, %1
|
||||
$q0 = COPY %3
|
||||
...
|
||||
---
|
||||
name: add_lhs_sub_reg_vec
|
||||
alignment: 4
|
||||
tracksRegLiveness: true
|
||||
frameInfo:
|
||||
maxAlignment: 1
|
||||
machineFunctionInfo: {}
|
||||
body: |
|
||||
bb.0:
|
||||
liveins: $x0, $x1
|
||||
; CHECK-LABEL: name: add_lhs_sub_reg_vec
|
||||
; CHECK: liveins: $x0, $x1
|
||||
; CHECK-NEXT: {{ $}}
|
||||
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $x0
|
||||
; CHECK-NEXT: $x0 = COPY [[COPY]](<4 x s16>)
|
||||
%0:_(<4 x s16>) = COPY $x0
|
||||
%1:_(<4 x s16>) = COPY $x1
|
||||
%2:_(<4 x s16>) = G_SUB %0, %1
|
||||
%3:_(<4 x s16>) = G_ADD %2, %1
|
||||
$x0 = COPY %3
|
||||
...
|
||||
---
|
||||
name: add_rhs_sub_reg
|
||||
alignment: 4
|
||||
tracksRegLiveness: true
|
||||
frameInfo:
|
||||
maxAlignment: 1
|
||||
machineFunctionInfo: {}
|
||||
body: |
|
||||
bb.0:
|
||||
liveins: $w0, $w1
|
||||
; CHECK-LABEL: name: add_rhs_sub_reg
|
||||
; CHECK: liveins: $w0, $w1
|
||||
; CHECK-NEXT: {{ $}}
|
||||
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
|
||||
; CHECK-NEXT: $w0 = COPY [[COPY]](s32)
|
||||
%0:_(s32) = COPY $w0
|
||||
%1:_(s32) = COPY $w1
|
||||
%2:_(s32) = G_SUB %0, %1
|
||||
%3:_(s32) = G_ADD %1, %2
|
||||
$w0 = COPY %3
|
||||
...
|
||||
---
|
||||
name: add_rhs_sub_reg_wide
|
||||
alignment: 4
|
||||
tracksRegLiveness: true
|
||||
frameInfo:
|
||||
maxAlignment: 1
|
||||
machineFunctionInfo: {}
|
||||
body: |
|
||||
bb.0:
|
||||
liveins: $q0, $q1
|
||||
; CHECK-LABEL: name: add_rhs_sub_reg_wide
|
||||
; CHECK: liveins: $q0, $q1
|
||||
; CHECK-NEXT: {{ $}}
|
||||
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s128) = COPY $q0
|
||||
; CHECK-NEXT: $q0 = COPY [[COPY]](s128)
|
||||
%0:_(s128) = COPY $q0
|
||||
%1:_(s128) = COPY $q1
|
||||
%2:_(s128) = G_SUB %0, %1
|
||||
%3:_(s128) = G_ADD %1, %2
|
||||
$q0 = COPY %3
|
||||
...
|
||||
---
|
||||
name: add_rhs_sub_reg_vec
|
||||
alignment: 4
|
||||
tracksRegLiveness: true
|
||||
frameInfo:
|
||||
maxAlignment: 1
|
||||
machineFunctionInfo: {}
|
||||
body: |
|
||||
bb.0:
|
||||
liveins: $x0, $x1
|
||||
; CHECK-LABEL: name: add_rhs_sub_reg_vec
|
||||
; CHECK: liveins: $x0, $x1
|
||||
; CHECK-NEXT: {{ $}}
|
||||
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $x0
|
||||
; CHECK-NEXT: $x0 = COPY [[COPY]](<4 x s16>)
|
||||
%0:_(<4 x s16>) = COPY $x0
|
||||
%1:_(<4 x s16>) = COPY $x1
|
||||
%2:_(<4 x s16>) = G_SUB %0, %1
|
||||
%3:_(<4 x s16>) = G_ADD %1, %2
|
||||
$x0 = COPY %3
|
||||
...
|
Loading…
Reference in New Issue