forked from OSchip/llvm-project
[GlobalISel] Port some basic undef combines from DAGCombiner.cpp
This ports some combines from DAGCombiner.cpp which perform some trivial transformations on instructions with undef operands. Not having these can make it extremely annoying to find out where we differ from SelectionDAG by looking at existing lit tests. Without them, we tend to produce pretty bad code generation when we run into instructions which use undef operands. Also remove the nonpow2_store_narrowing testcase from arm64-fallback.ll, since we no longer fall back on the add. Differential Revision: https://reviews.llvm.org/D76339
This commit is contained in:
parent
1e4ee0bfc5
commit
dc5f982639
|
@ -190,6 +190,19 @@ public:
|
|||
bool applyCombineShiftToUnmerge(MachineInstr &MI, const unsigned &ShiftVal);
|
||||
bool tryCombineShiftToUnmerge(MachineInstr &MI, unsigned TargetShiftAmount);
|
||||
|
||||
/// Return true if any explicit use operand on \p MI is defined by a
|
||||
/// G_IMPLICIT_DEF.
|
||||
bool matchAnyExplicitUseIsUndef(MachineInstr &MI);
|
||||
|
||||
/// Replace an instruction with a G_FCONSTANT with value \p C.
|
||||
bool replaceInstWithFConstant(MachineInstr &MI, double C);
|
||||
|
||||
/// Replace an instruction with a G_CONSTANT with value \p C.
|
||||
bool replaceInstWithConstant(MachineInstr &MI, int64_t C);
|
||||
|
||||
/// Replace an instruction with a G_IMPLICIT_DEF.
|
||||
bool replaceInstWithUndef(MachineInstr &MI);
|
||||
|
||||
/// Try to transform \p MI by using all of the above
|
||||
/// combine functions. Returns true if changed.
|
||||
bool tryCombine(MachineInstr &MI);
|
||||
|
|
|
@ -142,7 +142,34 @@ def mul_to_shl : GICombineRule<
|
|||
[{ return Helper.matchCombineMulToShl(*${mi}, ${matchinfo}); }]),
|
||||
(apply [{ Helper.applyCombineMulToShl(*${mi}, ${matchinfo}); }])>;
|
||||
|
||||
// [us]itofp(undef) = 0, because the result value is bounded.
|
||||
def undef_to_fp_zero : GICombineRule<
|
||||
(defs root:$root),
|
||||
(match (wip_match_opcode G_UITOFP, G_SITOFP):$root,
|
||||
[{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]),
|
||||
(apply [{ Helper.replaceInstWithFConstant(*${root}, 0.0); }])>;
|
||||
|
||||
def undef_to_int_zero: GICombineRule<
|
||||
(defs root:$root),
|
||||
(match (wip_match_opcode G_AND, G_MUL):$root,
|
||||
[{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]),
|
||||
(apply [{ Helper.replaceInstWithConstant(*${root}, 0); }])>;
|
||||
|
||||
def undef_to_negative_one: GICombineRule<
|
||||
(defs root:$root),
|
||||
(match (wip_match_opcode G_OR):$root,
|
||||
[{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]),
|
||||
(apply [{ Helper.replaceInstWithConstant(*${root}, -1); }])>;
|
||||
|
||||
def propagate_undef: GICombineRule<
|
||||
(defs root:$root),
|
||||
(match (wip_match_opcode G_ADD, G_FPTOSI, G_FPTOUI, G_SUB, G_XOR):$root,
|
||||
[{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]),
|
||||
(apply [{ Helper.replaceInstWithUndef(*${root}); }])>;
|
||||
|
||||
def undef_combines : GICombineGroup<[undef_to_fp_zero, undef_to_int_zero,
|
||||
undef_to_negative_one, propagate_undef]>;
|
||||
|
||||
def trivial_combines : GICombineGroup<[copy_prop, mul_to_shl]>;
|
||||
def all_combines : GICombineGroup<[trivial_combines, ptr_add_immed_chain,
|
||||
combines_for_extload, combine_indexed_load_store]>;
|
||||
|
||||
combines_for_extload, combine_indexed_load_store, undef_combines]>;
|
||||
|
|
|
@ -1483,6 +1483,37 @@ bool CombinerHelper::tryCombineShiftToUnmerge(MachineInstr &MI,
|
|||
return false;
|
||||
}
|
||||
|
||||
bool CombinerHelper::matchAnyExplicitUseIsUndef(MachineInstr &MI) {
|
||||
return any_of(MI.explicit_uses(), [this](const MachineOperand &MO) {
|
||||
return MO.isReg() &&
|
||||
getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, MO.getReg(), MRI);
|
||||
});
|
||||
}
|
||||
|
||||
bool CombinerHelper::replaceInstWithFConstant(MachineInstr &MI, double C) {
|
||||
assert(MI.getNumDefs() == 1 && "Expected only one def?");
|
||||
Builder.setInstr(MI);
|
||||
Builder.buildFConstant(MI.getOperand(0), C);
|
||||
MI.eraseFromParent();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CombinerHelper::replaceInstWithConstant(MachineInstr &MI, int64_t C) {
|
||||
assert(MI.getNumDefs() == 1 && "Expected only one def?");
|
||||
Builder.setInstr(MI);
|
||||
Builder.buildConstant(MI.getOperand(0), C);
|
||||
MI.eraseFromParent();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CombinerHelper::replaceInstWithUndef(MachineInstr &MI) {
|
||||
assert(MI.getNumDefs() == 1 && "Expected only one def?");
|
||||
Builder.setInstr(MI);
|
||||
Builder.buildUndef(MI.getOperand(0));
|
||||
MI.eraseFromParent();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CombinerHelper::tryCombine(MachineInstr &MI) {
|
||||
if (tryCombineCopy(MI))
|
||||
return true;
|
||||
|
|
|
@ -167,16 +167,6 @@ define void @nonpow2_load_narrowing() {
|
|||
ret void
|
||||
}
|
||||
|
||||
; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: cannot select: %{{[0-9]+}}:gpr64(s64), %{{[0-9]+}}:gpr(s1) = G_UADDE %{{[0-9]+}}:gpr, %{{[0-9]+}}:gpr, %{{[0-9]+}}:gpr (in function: nonpow2_store_narrowing)
|
||||
; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for nonpow2_store_narrowing
|
||||
; FALLBACK-WITH-REPORT-OUT-LABEL: nonpow2_store_narrowing:
|
||||
define void @nonpow2_store_narrowing(i96* %c) {
|
||||
%a = add i128 undef, undef
|
||||
%b = trunc i128 %a to i96
|
||||
store i96 %b, i96* %c
|
||||
ret void
|
||||
}
|
||||
|
||||
; Currently can't handle vector lengths that aren't an exact multiple of
|
||||
; natively supported vector lengths. Test that the fall-back works for those.
|
||||
; FALLBACK-WITH-REPORT-ERR-G_IMPLICIT_DEF-LEGALIZABLE: (FIXME: this is what is expected once we can legalize non-pow-of-2 G_IMPLICIT_DEF) remark: <unknown>:0:0: unable to legalize instruction: %1:_(<7 x s64>) = G_ADD %0, %0 (in function: nonpow2_vector_add_fewerelements
|
||||
|
|
|
@ -0,0 +1,168 @@
|
|||
# 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: uitofp_to_zero
|
||||
alignment: 4
|
||||
tracksRegLiveness: true
|
||||
body: |
|
||||
bb.0:
|
||||
; CHECK-LABEL: name: uitofp_to_zero
|
||||
; CHECK: [[C:%[0-9]+]]:_(s32) = G_FCONSTANT float 0.000000e+00
|
||||
; CHECK: $s0 = COPY [[C]](s32)
|
||||
; CHECK: RET_ReallyLR implicit $s0
|
||||
%0:_(s32) = G_IMPLICIT_DEF
|
||||
%1:_(s32) = G_UITOFP %0(s32)
|
||||
$s0 = COPY %1(s32)
|
||||
RET_ReallyLR implicit $s0
|
||||
|
||||
...
|
||||
---
|
||||
name: sitofp_to_zero
|
||||
alignment: 4
|
||||
tracksRegLiveness: true
|
||||
body: |
|
||||
bb.0:
|
||||
; CHECK-LABEL: name: sitofp_to_zero
|
||||
; CHECK: [[C:%[0-9]+]]:_(s32) = G_FCONSTANT float 0.000000e+00
|
||||
; CHECK: $s0 = COPY [[C]](s32)
|
||||
; CHECK: RET_ReallyLR implicit $s0
|
||||
%0:_(s32) = G_IMPLICIT_DEF
|
||||
%1:_(s32) = G_SITOFP %0(s32)
|
||||
$s0 = COPY %1(s32)
|
||||
RET_ReallyLR implicit $s0
|
||||
|
||||
...
|
||||
---
|
||||
name: and_to_zero
|
||||
alignment: 4
|
||||
tracksRegLiveness: true
|
||||
body: |
|
||||
bb.0:
|
||||
; CHECK-LABEL: name: and_to_zero
|
||||
; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
|
||||
; CHECK: $w0 = COPY [[C]](s32)
|
||||
; CHECK: RET_ReallyLR implicit $w0
|
||||
%0:_(s32) = G_CONSTANT i32 10
|
||||
%1:_(s32) = G_IMPLICIT_DEF
|
||||
%2:_(s32) = G_AND %0, %1
|
||||
$w0 = COPY %2(s32)
|
||||
RET_ReallyLR implicit $w0
|
||||
|
||||
...
|
||||
---
|
||||
name: mul_to_zero
|
||||
alignment: 4
|
||||
tracksRegLiveness: true
|
||||
body: |
|
||||
bb.0:
|
||||
; CHECK-LABEL: name: mul_to_zero
|
||||
; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
|
||||
; CHECK: $w0 = COPY [[C]](s32)
|
||||
; CHECK: RET_ReallyLR implicit $w0
|
||||
%0:_(s32) = G_CONSTANT i32 10
|
||||
%1:_(s32) = G_IMPLICIT_DEF
|
||||
%2:_(s32) = G_MUL %0, %1
|
||||
$w0 = COPY %2(s32)
|
||||
RET_ReallyLR implicit $w0
|
||||
|
||||
...
|
||||
---
|
||||
name: or_to_negative_one
|
||||
alignment: 4
|
||||
tracksRegLiveness: true
|
||||
body: |
|
||||
bb.0:
|
||||
; CHECK-LABEL: name: or_to_negative_one
|
||||
; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
|
||||
; CHECK: $w0 = COPY [[C]](s32)
|
||||
; CHECK: RET_ReallyLR implicit $w0
|
||||
%0:_(s32) = G_CONSTANT i32 10
|
||||
%1:_(s32) = G_IMPLICIT_DEF
|
||||
%2:_(s32) = G_OR %0, %1
|
||||
$w0 = COPY %2(s32)
|
||||
RET_ReallyLR implicit $w0
|
||||
|
||||
...
|
||||
---
|
||||
name: xor_to_undef
|
||||
alignment: 4
|
||||
tracksRegLiveness: true
|
||||
body: |
|
||||
bb.0:
|
||||
; CHECK-LABEL: name: xor_to_undef
|
||||
; CHECK: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
|
||||
; CHECK: $w0 = COPY [[DEF]](s32)
|
||||
; CHECK: RET_ReallyLR implicit $w0
|
||||
%0:_(s32) = G_CONSTANT i32 10
|
||||
%1:_(s32) = G_IMPLICIT_DEF
|
||||
%2:_(s32) = G_XOR %0, %1
|
||||
$w0 = COPY %2(s32)
|
||||
RET_ReallyLR implicit $w0
|
||||
|
||||
...
|
||||
---
|
||||
name: add_to_undef
|
||||
alignment: 4
|
||||
tracksRegLiveness: true
|
||||
body: |
|
||||
bb.0:
|
||||
; CHECK-LABEL: name: add_to_undef
|
||||
; CHECK: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
|
||||
; CHECK: $w0 = COPY [[DEF]](s32)
|
||||
; CHECK: RET_ReallyLR implicit $w0
|
||||
%0:_(s32) = G_CONSTANT i32 10
|
||||
%1:_(s32) = G_IMPLICIT_DEF
|
||||
%2:_(s32) = G_ADD %0, %1
|
||||
$w0 = COPY %2(s32)
|
||||
RET_ReallyLR implicit $w0
|
||||
|
||||
...
|
||||
---
|
||||
name: sub_to_undef
|
||||
alignment: 4
|
||||
tracksRegLiveness: true
|
||||
body: |
|
||||
bb.0:
|
||||
; CHECK-LABEL: name: sub_to_undef
|
||||
; CHECK: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
|
||||
; CHECK: $w0 = COPY [[DEF]](s32)
|
||||
; CHECK: RET_ReallyLR implicit $w0
|
||||
%0:_(s32) = G_CONSTANT i32 10
|
||||
%1:_(s32) = G_IMPLICIT_DEF
|
||||
%2:_(s32) = G_SUB %0, %1
|
||||
$w0 = COPY %2(s32)
|
||||
RET_ReallyLR implicit $w0
|
||||
|
||||
...
|
||||
---
|
||||
name: fptoui_to_undef
|
||||
alignment: 4
|
||||
tracksRegLiveness: true
|
||||
body: |
|
||||
bb.0:
|
||||
; CHECK-LABEL: name: fptoui_to_undef
|
||||
; CHECK: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
|
||||
; CHECK: $w0 = COPY [[DEF]](s32)
|
||||
; CHECK: RET_ReallyLR implicit $w0
|
||||
%0:_(s32) = G_IMPLICIT_DEF
|
||||
%1:_(s32) = G_FPTOUI %0(s32)
|
||||
$w0 = COPY %1(s32)
|
||||
RET_ReallyLR implicit $w0
|
||||
|
||||
...
|
||||
---
|
||||
name: fptosi_to_undef
|
||||
alignment: 4
|
||||
tracksRegLiveness: true
|
||||
body: |
|
||||
bb.0:
|
||||
; CHECK-LABEL: name: fptosi_to_undef
|
||||
; CHECK: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
|
||||
; CHECK: $w0 = COPY [[DEF]](s32)
|
||||
; CHECK: RET_ReallyLR implicit $w0
|
||||
%0:_(s32) = G_IMPLICIT_DEF
|
||||
%1:_(s32) = G_FPTOSI %0(s32)
|
||||
$w0 = COPY %1(s32)
|
||||
RET_ReallyLR implicit $w0
|
||||
|
||||
...
|
Loading…
Reference in New Issue