mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
[GlobalISel] Combine (x op 0) -> x for operations with a right identity of 0
Implement identity combines for operations like the following: ``` %a = G_SUB %b, 0 ``` This can just be replaced with %b. Over CTMark, this gives some minor size improvements at -O3. Differential Revision: https://reviews.llvm.org/D76640
This commit is contained in:
parent
e2e7135db3
commit
c18856f48a
@ -221,6 +221,10 @@ public:
|
||||
/// equivalent instructions.
|
||||
bool matchEqualDefs(const MachineOperand &MOP1, const MachineOperand &MOP2);
|
||||
|
||||
/// Return true if \p MOP is defined by a G_CONSTANT with a value equal to
|
||||
/// \p C.
|
||||
bool matchConstantOp(const MachineOperand &MOP, int64_t C);
|
||||
|
||||
/// Optimize (cond ? x : x) -> x
|
||||
bool matchSelectSameVal(MachineInstr &MI);
|
||||
|
||||
|
@ -192,6 +192,14 @@ def select_same_val: GICombineRule<
|
||||
(apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 2); }])
|
||||
>;
|
||||
|
||||
// Fold x op 0 -> x
|
||||
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):$root,
|
||||
[{ return Helper.matchConstantOp(${root}->getOperand(2), 0); }]),
|
||||
(apply [{ return Helper.replaceSingleDefInstWithOperand(*${root}, 1); }])
|
||||
>;
|
||||
|
||||
// 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,
|
||||
@ -199,7 +207,7 @@ def undef_combines : GICombineGroup<[undef_to_fp_zero, undef_to_int_zero,
|
||||
propagate_undef_all_ops,
|
||||
propagate_undef_shuffle_mask]>;
|
||||
|
||||
def identity_combines : GICombineGroup<[select_same_val]>;
|
||||
def identity_combines : GICombineGroup<[select_same_val, right_identity_zero]>;
|
||||
|
||||
def trivial_combines : GICombineGroup<[copy_prop, mul_to_shl]>;
|
||||
def all_combines : GICombineGroup<[trivial_combines, ptr_add_immed_chain,
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "llvm/CodeGen/GlobalISel/Combiner.h"
|
||||
#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
|
||||
#include "llvm/CodeGen/GlobalISel/GISelKnownBits.h"
|
||||
#include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
|
||||
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
|
||||
#include "llvm/CodeGen/GlobalISel/Utils.h"
|
||||
#include "llvm/CodeGen/MachineDominators.h"
|
||||
@ -23,6 +24,7 @@
|
||||
#define DEBUG_TYPE "gi-combiner"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace MIPatternMatch;
|
||||
|
||||
// Option to allow testing of the combiner while no targets know about indexed
|
||||
// addressing.
|
||||
@ -1546,6 +1548,13 @@ bool CombinerHelper::matchEqualDefs(const MachineOperand &MOP1,
|
||||
return Builder.getTII().produceSameValue(*I1, *I2, &MRI);
|
||||
}
|
||||
|
||||
bool CombinerHelper::matchConstantOp(const MachineOperand &MOP, int64_t C) {
|
||||
if (!MOP.isReg())
|
||||
return false;
|
||||
int64_t Cst;
|
||||
return mi_match(MOP.getReg(), MRI, m_ICst(Cst)) && Cst == C;
|
||||
}
|
||||
|
||||
bool CombinerHelper::replaceSingleDefInstWithOperand(MachineInstr &MI,
|
||||
unsigned OpIdx) {
|
||||
assert(MI.getNumExplicitDefs() == 1 && "Expected one explicit def?");
|
||||
|
@ -0,0 +1,163 @@
|
||||
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
|
||||
# RUN: llc -mtriple aarch64 -run-pass=aarch64-prelegalizer-combiner -verify-machineinstrs %s -o - | FileCheck %s
|
||||
|
||||
name: right_ident_sub
|
||||
tracksRegLiveness: true
|
||||
body: |
|
||||
bb.1.entry:
|
||||
liveins: $w0
|
||||
; Fold (x - 0) -> x
|
||||
;
|
||||
; CHECK-LABEL: name: right_ident_sub
|
||||
; CHECK: liveins: $w0
|
||||
; CHECK: %x:_(s32) = COPY $w0
|
||||
; CHECK: $w0 = COPY %x(s32)
|
||||
; CHECK: RET_ReallyLR implicit $w0
|
||||
%x:_(s32) = COPY $w0
|
||||
%cst:_(s32) = G_CONSTANT i32 0
|
||||
%op:_(s32) = G_SUB %x(s32), %cst
|
||||
$w0 = COPY %op(s32)
|
||||
RET_ReallyLR implicit $w0
|
||||
|
||||
...
|
||||
---
|
||||
name: right_ident_add
|
||||
tracksRegLiveness: true
|
||||
body: |
|
||||
bb.1.entry:
|
||||
liveins: $w0
|
||||
; Fold (x + 0) -> x
|
||||
;
|
||||
; CHECK-LABEL: name: right_ident_add
|
||||
; CHECK: liveins: $w0
|
||||
; CHECK: %x:_(s32) = COPY $w0
|
||||
; CHECK: $w0 = COPY %x(s32)
|
||||
; CHECK: RET_ReallyLR implicit $w0
|
||||
%x:_(s32) = COPY $w0
|
||||
%cst:_(s32) = G_CONSTANT i32 0
|
||||
%op:_(s32) = G_ADD %x(s32), %cst
|
||||
$w0 = COPY %op(s32)
|
||||
RET_ReallyLR implicit $w0
|
||||
|
||||
...
|
||||
---
|
||||
name: right_ident_or
|
||||
tracksRegLiveness: true
|
||||
body: |
|
||||
bb.1.entry:
|
||||
liveins: $w0
|
||||
; Fold (x || 0) -> x
|
||||
;
|
||||
; CHECK-LABEL: name: right_ident_or
|
||||
; CHECK: liveins: $w0
|
||||
; CHECK: %x:_(s32) = COPY $w0
|
||||
; CHECK: $w0 = COPY %x(s32)
|
||||
; CHECK: RET_ReallyLR implicit $w0
|
||||
%x:_(s32) = COPY $w0
|
||||
%cst:_(s32) = G_CONSTANT i32 0
|
||||
%op:_(s32) = G_OR %x(s32), %cst
|
||||
$w0 = COPY %op(s32)
|
||||
RET_ReallyLR implicit $w0
|
||||
|
||||
...
|
||||
---
|
||||
name: right_ident_xor
|
||||
tracksRegLiveness: true
|
||||
body: |
|
||||
bb.1.entry:
|
||||
liveins: $w0
|
||||
; Fold (x | 0) -> x
|
||||
;
|
||||
; CHECK-LABEL: name: right_ident_xor
|
||||
; CHECK: liveins: $w0
|
||||
; CHECK: %x:_(s32) = COPY $w0
|
||||
; CHECK: $w0 = COPY %x(s32)
|
||||
; CHECK: RET_ReallyLR implicit $w0
|
||||
%x:_(s32) = COPY $w0
|
||||
%cst:_(s32) = G_CONSTANT i32 0
|
||||
%op:_(s32) = G_XOR %x(s32), %cst
|
||||
$w0 = COPY %op(s32)
|
||||
RET_ReallyLR implicit $w0
|
||||
|
||||
...
|
||||
---
|
||||
name: right_ident_shl
|
||||
tracksRegLiveness: true
|
||||
body: |
|
||||
bb.1.entry:
|
||||
liveins: $w0
|
||||
; Fold (x << 0) -> x
|
||||
;
|
||||
; CHECK-LABEL: name: right_ident_shl
|
||||
; CHECK: liveins: $w0
|
||||
; CHECK: %x:_(s32) = COPY $w0
|
||||
; CHECK: $w0 = COPY %x(s32)
|
||||
; CHECK: RET_ReallyLR implicit $w0
|
||||
%x:_(s32) = COPY $w0
|
||||
%cst:_(s32) = G_CONSTANT i32 0
|
||||
%op:_(s32) = G_SHL %x(s32), %cst
|
||||
$w0 = COPY %op(s32)
|
||||
RET_ReallyLR implicit $w0
|
||||
|
||||
...
|
||||
---
|
||||
name: right_ident_ashr
|
||||
tracksRegLiveness: true
|
||||
body: |
|
||||
bb.1.entry:
|
||||
liveins: $w0
|
||||
; Fold (x ashr 0) -> x
|
||||
;
|
||||
; CHECK-LABEL: name: right_ident_ashr
|
||||
; CHECK: liveins: $w0
|
||||
; CHECK: %x:_(s32) = COPY $w0
|
||||
; CHECK: $w0 = COPY %x(s32)
|
||||
; CHECK: RET_ReallyLR implicit $w0
|
||||
%x:_(s32) = COPY $w0
|
||||
%cst:_(s32) = G_CONSTANT i32 0
|
||||
%op:_(s32) = G_ASHR %x(s32), %cst
|
||||
$w0 = COPY %op(s32)
|
||||
RET_ReallyLR implicit $w0
|
||||
|
||||
...
|
||||
---
|
||||
name: right_ident_lshr
|
||||
tracksRegLiveness: true
|
||||
body: |
|
||||
bb.1.entry:
|
||||
liveins: $w0
|
||||
; Fold (x lshr 0) -> x
|
||||
;
|
||||
; CHECK-LABEL: name: right_ident_lshr
|
||||
; CHECK: liveins: $w0
|
||||
; CHECK: %x:_(s32) = COPY $w0
|
||||
; CHECK: $w0 = COPY %x(s32)
|
||||
; CHECK: RET_ReallyLR implicit $w0
|
||||
%x:_(s32) = COPY $w0
|
||||
%cst:_(s32) = G_CONSTANT i32 0
|
||||
%op:_(s32) = G_LSHR %x(s32), %cst
|
||||
$w0 = COPY %op(s32)
|
||||
RET_ReallyLR implicit $w0
|
||||
|
||||
...
|
||||
---
|
||||
name: dont_fold_sub
|
||||
tracksRegLiveness: true
|
||||
body: |
|
||||
bb.1.entry:
|
||||
liveins: $w0
|
||||
; Not an identity, no folding.
|
||||
;
|
||||
; CHECK-LABEL: name: dont_fold_sub
|
||||
; CHECK: liveins: $w0
|
||||
; CHECK: %x:_(s32) = COPY $w0
|
||||
; CHECK: %cst:_(s32) = G_CONSTANT i32 1
|
||||
; CHECK: %op:_(s32) = G_SUB %x, %cst
|
||||
; CHECK: $w0 = COPY %op(s32)
|
||||
; CHECK: RET_ReallyLR implicit $w0
|
||||
%x:_(s32) = COPY $w0
|
||||
%cst:_(s32) = G_CONSTANT i32 1
|
||||
%op:_(s32) = G_SUB %x(s32), %cst
|
||||
$w0 = COPY %op(s32)
|
||||
RET_ReallyLR implicit $w0
|
||||
...
|
Loading…
x
Reference in New Issue
Block a user