Skip to content

Commit

Permalink
[GlobalISel] Rewrite some simple rules using MIR Patterns
Browse files Browse the repository at this point in the history
Rewrites some simple rules that cause little to no codegen regressions as MIR patterns.

I may have missed some easy cases, but some other rules have intentionally been left as-is because bigger
changes are needed to make them work.

Reviewed By: arsenm

Differential Revision: https://reviews.llvm.org/D157690
  • Loading branch information
Pierre-vh committed Aug 22, 2023
1 parent bdac6de commit 2d87319
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 64 deletions.
6 changes: 0 additions & 6 deletions llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -386,12 +386,6 @@ class CombinerHelper {
void applyCombineExtOfExt(MachineInstr &MI,
std::tuple<Register, unsigned> &MatchInfo);

/// Transform fabs(fabs(x)) to fabs(x).
void applyCombineFAbsOfFAbs(MachineInstr &MI, Register &Src);

/// Transform fabs(fneg(x)) to fabs(x).
bool matchCombineFAbsOfFNeg(MachineInstr &MI, BuildFnTy &MatchInfo);

/// Transform trunc ([asz]ext x) to x or ([asz]ext x) or (trunc x).
bool matchCombineTruncOfExt(MachineInstr &MI,
std::pair<Register, unsigned> &MatchInfo);
Expand Down
79 changes: 45 additions & 34 deletions llvm/include/llvm/Target/GlobalISel/Combine.td
Original file line number Diff line number Diff line change
Expand Up @@ -358,10 +358,10 @@ def select_same_val: GICombineRule<

// Fold (undef ? x : y) -> y
def select_undef_cmp: GICombineRule<
(defs root:$root),
(match (wip_match_opcode G_SELECT):$root,
[{ return Helper.matchUndefSelectCmp(*${root}); }]),
(apply [{ Helper.replaceSingleDefInstWithOperand(*${root}, 2); }])
(defs root:$dst),
(match (G_IMPLICIT_DEF $undef),
(G_SELECT $dst, $undef, $x, $y)),
(apply (COPY $dst, $y))
>;

// Fold (true ? x : y) -> x
Expand Down Expand Up @@ -400,28 +400,37 @@ def commute_constant_to_rhs : GICombineRule<
>;

// Fold x op 0 -> x
def right_identity_zero_frags : GICombinePatFrag<
(outs root:$dst), (ins $x),
!foreach(op,
[G_SUB, G_ADD, G_OR, G_XOR, G_SHL, G_ASHR,
G_LSHR, G_PTR_ADD, G_ROTL, G_ROTR],
(pattern (op $dst, $x, 0)))>;
def right_identity_zero: GICombineRule<
(defs root:$root),
(match (wip_match_opcode G_SUB, G_ADD, G_OR, G_XOR, G_SHL, G_ASHR, G_LSHR,
G_PTR_ADD, G_ROTL, G_ROTR):$root,
[{ return Helper.matchConstantOp(${root}->getOperand(2), 0); }]),
(apply [{ Helper.replaceSingleDefInstWithOperand(*${root}, 1); }])
(defs root:$dst),
(match (right_identity_zero_frags $dst, $lhs)),
(apply (COPY $dst, $lhs))
>;

// 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 [{ Helper.replaceSingleDefInstWithOperand(*${root}, 1); }])
(defs root:$dst),
(match (G_MUL $dst, $x, 1)),
(apply (COPY $dst, $x))
>;

// Fold (x op x) - > x
def binop_same_val_frags : GICombinePatFrag<
(outs root:$dst), (ins $x),
[
(pattern (G_AND $dst, $x, $x)),
(pattern (G_OR $dst, $x, $x)),
]
>;
def binop_same_val: GICombineRule<
(defs root:$root),
(match (wip_match_opcode G_AND, G_OR):$root,
[{ return Helper.matchBinOpSameVal(*${root}); }]),
(apply [{ Helper.replaceSingleDefInstWithOperand(*${root}, 1); }])
(defs root:$dst),
(match (binop_same_val_frags $dst, $src)),
(apply (COPY $dst, $src))
>;

// Fold (0 op x) - > 0
Expand Down Expand Up @@ -470,10 +479,9 @@ def div_rem_to_divrem : GICombineRule<

// Fold (x op 0) - > 0
def binop_right_to_zero: GICombineRule<
(defs root:$root),
(match (wip_match_opcode G_MUL):$root,
[{ return Helper.matchOperandIsZero(*${root}, 2); }]),
(apply [{ Helper.replaceSingleDefInstWithOperand(*${root}, 2); }])
(defs root:$dst),
(match (G_MUL $dst, $lhs, 0:$zero)),
(apply (COPY $dst, $zero))
>;

// Erase stores of undef values.
Expand Down Expand Up @@ -637,11 +645,10 @@ def not_cmp_fold : GICombineRule<

// Fold (fneg (fneg x)) -> x.
def fneg_fneg_fold: GICombineRule <
(defs root:$dst, register_matchinfo:$matchinfo),
(defs root:$dst),
(match (G_FNEG $t, $src),
(G_FNEG $dst, $t):$mi,
[{ ${matchinfo} = ${src}.getReg(); return true; }]),
(apply [{ Helper.replaceSingleDefInstWithReg(*${mi}, ${matchinfo}); }])
(G_FNEG $dst, $t)),
(apply (COPY $dst, $src))
>;

// Fold (unmerge(merge x, y, z)) -> z, y, z.
Expand All @@ -663,10 +670,10 @@ def merge_unmerge : GICombineRule<

// Fold (fabs (fneg x)) -> (fabs x).
def fabs_fneg_fold: GICombineRule <
(defs root:$root, build_fn_matchinfo:$matchinfo),
(match (wip_match_opcode G_FABS):$root,
[{ return Helper.matchCombineFAbsOfFNeg(*${root}, ${matchinfo}); }]),
(apply [{ Helper.applyBuildFnNoErase(*${root}, ${matchinfo}); }])>;
(defs root:$dst),
(match (G_FNEG $tmp, $x),
(G_FABS $dst, $tmp)),
(apply (G_FABS $dst, $x))>;

// Fold (unmerge cst) -> cst1, cst2, ...
def unmerge_cst_matchinfo : GIDefMatchData<"SmallVector<APInt, 8>">;
Expand Down Expand Up @@ -1036,12 +1043,16 @@ def combine_minmax_nan: GICombineRule<

// Transform (add x, (sub y, x)) -> y
// Transform (add (sub y, x), x) -> y
def add_sub_reg_frags : GICombinePatFrag<
(outs root:$dst), (ins $src),
[
(pattern (G_ADD $dst, $x, $tmp), (G_SUB $tmp, $src, $x)),
(pattern (G_ADD $dst, $tmp, $x), (G_SUB $tmp, $src, $x))
]>;
def add_sub_reg: GICombineRule <
(defs root:$root, register_matchinfo:$matchinfo),
(match (wip_match_opcode G_ADD):$root,
[{ return Helper.matchAddSubSameReg(*${root}, ${matchinfo}); }]),
(apply [{ Helper.replaceSingleDefInstWithReg(*${root},
${matchinfo}); }])>;
(defs root:$dst),
(match (add_sub_reg_frags $dst, $src)),
(apply (COPY $dst, $src))>;

def buildvector_identity_fold : GICombineRule<
(defs root:$build_vector, register_matchinfo:$matchinfo),
Expand Down
17 changes: 0 additions & 17 deletions llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2260,23 +2260,6 @@ void CombinerHelper::applyCombineMulByNegativeOne(MachineInstr &MI) {
MI.eraseFromParent();
}

bool CombinerHelper::matchCombineFAbsOfFNeg(MachineInstr &MI,
BuildFnTy &MatchInfo) {
assert(MI.getOpcode() == TargetOpcode::G_FABS && "Expected a G_FABS");
Register Src = MI.getOperand(1).getReg();
Register NegSrc;

if (!mi_match(Src, MRI, m_GFNeg(m_Reg(NegSrc))))
return false;

MatchInfo = [=, &MI](MachineIRBuilder &B) {
Observer.changingInstr(MI);
MI.getOperand(1).setReg(NegSrc);
Observer.changedInstr(MI);
};
return true;
}

bool CombinerHelper::matchCombineTruncOfExt(
MachineInstr &MI, std::pair<Register, unsigned> &MatchInfo) {
assert(MI.getOpcode() == TargetOpcode::G_TRUNC && "Expected a G_TRUNC");
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/CodeGen/AArch64/GlobalISel/combine-select.mir
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ body: |
; CHECK-LABEL: name: test_combine_select_undef_res0_res1
; CHECK: liveins: $x0, $x1
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x1
; CHECK-NEXT: $x0 = COPY [[COPY]](s64)
%0:_(s64) = COPY $x0
%1:_(s64) = COPY $x1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ body: |
; CHECK-LABEL: name: test_combine_select_undef_res0_res1
; CHECK: liveins: $x0, $x1
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x1
; CHECK-NEXT: $x0 = COPY [[COPY]](s64)
%0:_(s64) = COPY $x0
%1:_(s64) = COPY $x1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,14 @@ body: |
bb.0:
; %load1 || %load2 == %load1 is fine here, because the loads are invariant.
; TODO: Loads need to be CSE'd for this to work.
; CHECK-LABEL: name: invariant_loads
; CHECK: %ptr:_(p0) = G_GLOBAL_VALUE @g
; CHECK-NEXT: %load1:_(s32) = G_LOAD %ptr(p0) :: (dereferenceable invariant load (s32) from @g)
; CHECK-NEXT: %load2:_(s32) = G_LOAD %ptr(p0) :: (dereferenceable invariant load (s32) from @g)
; CHECK-NEXT: G_STORE %load2(s32), %ptr(p0) :: (store (s32) into @g)
; CHECK-NEXT: %or:_(s32) = G_OR %load2, %load1
; CHECK-NEXT: G_STORE %or(s32), %ptr(p0) :: (store (s32) into @g)
; CHECK-NEXT: RET_ReallyLR
%ptr:_(p0) = G_GLOBAL_VALUE @g
%load1:_(s32) = G_LOAD %ptr(p0) :: (dereferenceable invariant load (s32) from @g)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ body: |
...

# FIXME: Probably should be able to replace this.
---
name: mul_0_cant_replace
tracksRegLiveness: true
Expand All @@ -75,9 +74,8 @@ body: |
; CHECK-LABEL: name: mul_0_cant_replace
; CHECK: liveins: $w0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: %x:_(s32) = COPY $w0
; CHECK-NEXT: %cst:_(s32) = G_CONSTANT i32 0
; CHECK-NEXT: %op:gpr(s32) = G_MUL %x, %cst
; CHECK-NEXT: %op:gpr(s32) = COPY %cst(s32)
; CHECK-NEXT: $w0 = COPY %op(s32)
; CHECK-NEXT: RET_ReallyLR implicit $w0
%x:_(s32) = COPY $w0
Expand Down Expand Up @@ -312,7 +310,9 @@ body: |
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: %zero:_(s8) = G_CONSTANT i8 0
; CHECK-NEXT: %zext_zero:_(s64) = G_ZEXT %zero(s8)
; CHECK-NEXT: $x0 = COPY %zext_zero(s64)
; CHECK-NEXT: %c:_(s64) = G_CONSTANT i64 72340172838076673
; CHECK-NEXT: %mul:_(s64) = G_MUL %zext_zero, %c
; CHECK-NEXT: $x0 = COPY %mul(s64)
; CHECK-NEXT: RET_ReallyLR implicit $x0
%zero:_(s8) = G_CONSTANT i8 0
%zext_zero:_(s64) = G_ZEXT %zero(s8)
Expand Down

0 comments on commit 2d87319

Please sign in to comment.