[GISel] Add new GISel combiners for G_MUL

https://reviews.llvm.org/D87668

Patch adds two new GICombinerRules, one for G_MUL(X, 1) and another for G_MUL(X, -1).
G_MUL(X, 1) is an identity combine, and G_MUL(X, -1) gets replaced with G_SUB(0, X).
Patch additionally adds new combiner tests for the AArch64 target to test these
new combiner rules, as well as updates AMDGPU GISel tests.

Patch by mkitzan
This commit is contained in:
Aditya Nandakumar 2020-09-15 16:06:55 -07:00
parent 61fc10d6a5
commit 97203cfd6b
4 changed files with 170 additions and 2 deletions

View File

@ -311,6 +311,9 @@ public:
bool applyCombineTruncOfShl(MachineInstr &MI,
std::pair<Register, Register> &MatchInfo);
/// Transform G_MUL(x, -1) to G_SUB(0, x)
bool applyCombineMulByNegativeOne(MachineInstr &MI);
/// Return true if any explicit use operand on \p MI is defined by a
/// G_IMPLICIT_DEF.
bool matchAnyExplicitUseIsUndef(MachineInstr &MI);

View File

@ -255,6 +255,14 @@ def right_identity_zero: GICombineRule<
(apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 1); }])
>;
// Fold x op 1 -> x
def right_identity_one: GICombineRule<
(defs root:$root),
(match (wip_match_opcode G_MUL):$root,
[{ return Helper.matchConstantOp(${root}->getOperand(2), 1); }]),
(apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 1); }])
>;
// Fold (x op x) - > x
def binop_same_val: GICombineRule<
(defs root:$root),
@ -455,6 +463,14 @@ def trunc_shl: GICombineRule <
(apply [{ return Helper.applyCombineTruncOfShl(*${root}, ${matchinfo}); }])
>;
// Transform (mul x, -1) -> (sub 0, x)
def mul_by_neg_one: GICombineRule <
(defs root:$root),
(match (wip_match_opcode G_MUL):$root,
[{ return Helper.matchConstantOp(${root}->getOperand(2), -1); }]),
(apply [{ return Helper.applyCombineMulByNegativeOne(*${root}); }])
>;
// 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,
@ -468,7 +484,7 @@ 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]>;
fneg_fneg_fold, right_identity_one]>;
def known_bits_simplifications : GICombineGroup<[
and_trivial_mask, redundant_sext_inreg]>;
@ -477,7 +493,9 @@ def width_reduction_combines : GICombineGroup<[reduce_shl_of_extend]>;
def select_combines : GICombineGroup<[select_undef_cmp, select_constant_cmp]>;
def trivial_combines : GICombineGroup<[copy_prop, mul_to_shl, add_p2i_to_ptradd]>;
def trivial_combines : GICombineGroup<[copy_prop, mul_to_shl, add_p2i_to_ptradd,
mul_by_neg_one]>;
def all_combines : GICombineGroup<[trivial_combines, ptr_add_immed_chain,
combines_for_extload, combine_indexed_load_store, undef_combines,
identity_combines, simplify_add_to_sub,

View File

@ -2008,6 +2008,19 @@ bool CombinerHelper::applyCombineExtOfExt(
return false;
}
bool CombinerHelper::applyCombineMulByNegativeOne(MachineInstr &MI) {
assert(MI.getOpcode() == TargetOpcode::G_MUL && "Expected a G_MUL");
Register DstReg = MI.getOperand(0).getReg();
Register SrcReg = MI.getOperand(1).getReg();
LLT DstTy = MRI.getType(DstReg);
Builder.setInstrAndDebugLoc(MI);
Builder.buildSub(DstReg, Builder.buildConstant(DstTy, 0), SrcReg,
MI.getFlags());
MI.eraseFromParent();
return true;
}
bool CombinerHelper::matchCombineFNegOfFNeg(MachineInstr &MI, Register &Reg) {
assert(MI.getOpcode() == TargetOpcode::G_FNEG && "Expected a G_FNEG");
Register SrcReg = MI.getOperand(1).getReg();

View File

@ -0,0 +1,134 @@
# 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: mul_by_zero
alignment: 4
tracksRegLiveness: true
frameInfo:
maxAlignment: 1
machineFunctionInfo: {}
body: |
bb.0:
liveins: $x0
; CHECK-LABEL: name: mul_by_zero
; CHECK: liveins: $x0
; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
; CHECK: $x0 = COPY [[C]](s64)
%0:_(s64) = COPY $x0
%1:_(s64) = G_CONSTANT i64 0
%2:_(s64) = G_MUL %0, %1(s64)
$x0 = COPY %2(s64)
...
---
name: mul_vector_by_zero
alignment: 4
tracksRegLiveness: true
frameInfo:
maxAlignment: 1
machineFunctionInfo: {}
body: |
bb.0:
liveins: $q0
; Currently not implemented.
; CHECK-LABEL: name: mul_vector_by_zero
; CHECK: liveins: $q0
; CHECK: [[COPY:%[0-9]+]]:_(<4 x s32>) = COPY $q0
; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
; CHECK: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C]](s32), [[C]](s32), [[C]](s32), [[C]](s32)
; CHECK: [[MUL:%[0-9]+]]:_(<4 x s32>) = G_MUL [[COPY]], [[BUILD_VECTOR]]
; CHECK: $q0 = COPY [[MUL]](<4 x s32>)
%0:_(<4 x s32>) = COPY $q0
%1:_(s32) = G_CONSTANT i32 0
%2:_(<4 x s32>) = G_BUILD_VECTOR %1(s32), %1(s32), %1(s32), %1(s32)
%3:_(<4 x s32>) = G_MUL %0, %2(<4 x s32>)
$q0 = COPY %3(<4 x s32>)
...
---
name: mul_by_one
alignment: 4
tracksRegLiveness: true
frameInfo:
maxAlignment: 1
machineFunctionInfo: {}
body: |
bb.0:
liveins: $x0
; CHECK-LABEL: name: mul_by_one
; CHECK: liveins: $x0
; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
; CHECK: $x0 = COPY [[COPY]](s64)
%0:_(s64) = COPY $x0
%1:_(s64) = G_CONSTANT i64 1
%2:_(s64) = G_MUL %0, %1(s64)
$x0 = COPY %2(s64)
...
---
name: mul_vector_by_one
alignment: 4
tracksRegLiveness: true
frameInfo:
maxAlignment: 1
machineFunctionInfo: {}
body: |
bb.0:
liveins: $q0
; Currently not implemented.
; CHECK-LABEL: name: mul_vector_by_one
; CHECK: liveins: $q0
; CHECK: [[COPY:%[0-9]+]]:_(<4 x s32>) = COPY $q0
; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
; CHECK: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C]](s32), [[C]](s32), [[C]](s32), [[C]](s32)
; CHECK: [[MUL:%[0-9]+]]:_(<4 x s32>) = G_MUL [[COPY]], [[BUILD_VECTOR]]
; CHECK: $q0 = COPY [[MUL]](<4 x s32>)
%0:_(<4 x s32>) = COPY $q0
%1:_(s32) = G_CONSTANT i32 1
%2:_(<4 x s32>) = G_BUILD_VECTOR %1(s32), %1(s32), %1(s32), %1(s32)
%3:_(<4 x s32>) = G_MUL %0, %2(<4 x s32>)
$q0 = COPY %3(<4 x s32>)
...
---
name: mul_by_neg_one
alignment: 4
tracksRegLiveness: true
frameInfo:
maxAlignment: 1
machineFunctionInfo: {}
body: |
bb.0:
liveins: $x0
; CHECK-LABEL: name: mul_by_neg_one
; CHECK: liveins: $x0
; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
; CHECK: [[SUB:%[0-9]+]]:_(s64) = G_SUB [[C]], [[COPY]]
; CHECK: $x0 = COPY [[SUB]](s64)
%0:_(s64) = COPY $x0
%1:_(s64) = G_CONSTANT i64 -1
%2:_(s64) = G_MUL %0, %1(s64)
$x0 = COPY %2(s64)
...
---
name: mul_vector_by_neg_one
alignment: 4
tracksRegLiveness: true
frameInfo:
maxAlignment: 1
machineFunctionInfo: {}
body: |
bb.0:
liveins: $q0
; Currently not implemented.
; CHECK-LABEL: name: mul_vector_by_neg_one
; CHECK: liveins: $q0
; CHECK: [[COPY:%[0-9]+]]:_(<4 x s32>) = COPY $q0
; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
; CHECK: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C]](s32), [[C]](s32), [[C]](s32), [[C]](s32)
; CHECK: [[MUL:%[0-9]+]]:_(<4 x s32>) = G_MUL [[COPY]], [[BUILD_VECTOR]]
; CHECK: $q0 = COPY [[MUL]](<4 x s32>)
%0:_(<4 x s32>) = COPY $q0
%1:_(s32) = G_CONSTANT i32 -1
%2:_(<4 x s32>) = G_BUILD_VECTOR %1(s32), %1(s32), %1(s32), %1(s32)
%3:_(<4 x s32>) = G_MUL %0, %2(<4 x s32>)
$q0 = COPY %3(<4 x s32>)
...