[GISel] Add combiners for G_INTTOPTR and G_PTRTOINT

https://reviews.llvm.org/D84909

Patch adds two new GICombinerRules, one for G_INTTOPTR and one for
G_PTRTOINT. The G_INTTOPTR elides ptr2int(int2ptr(x)) to a copy of x, if
the cast is within the same address space. The G_PTRTOINT elides
int2ptr(ptr2int(x)) to a copy of x. Patch additionally adds new combiner
tests for the AArch64 target to test these new combiner rules.

Patch by mkitzan
This commit is contained in:
Aditya Nandakumar 2020-07-31 09:41:06 -07:00
parent 0aee6fdc5e
commit 313711b2cf
5 changed files with 111 additions and 1 deletions

View File

@ -200,6 +200,14 @@ public:
bool applyCombineShiftToUnmerge(MachineInstr &MI, const unsigned &ShiftVal);
bool tryCombineShiftToUnmerge(MachineInstr &MI, unsigned TargetShiftAmount);
/// Transform IntToPtr(PtrToInt(x)) to x if cast is in the same address space.
bool matchCombineI2PToP2I(MachineInstr &MI, Register &Reg);
bool applyCombineI2PToP2I(MachineInstr &MI, Register &Reg);
/// Transform PtrToInt(IntToPtr(x)) to x.
bool matchCombineP2IToI2P(MachineInstr &MI, Register &Reg);
bool applyCombineP2IToI2P(MachineInstr &MI, Register &Reg);
/// Return true if any explicit use operand on \p MI is defined by a
/// G_IMPLICIT_DEF.
bool matchAnyExplicitUseIsUndef(MachineInstr &MI);

View File

@ -257,6 +257,24 @@ def simplify_add_to_sub: GICombineRule <
(apply [{ return Helper.applySimplifyAddToSub(*${root}, ${info});}])
>;
// Fold int2ptr(ptr2int(x)) -> x
def p2i_to_i2p_matchinfo: GIDefMatchData<"Register">;
def p2i_to_i2p: GICombineRule<
(defs root:$root, p2i_to_i2p_matchinfo:$info),
(match (wip_match_opcode G_INTTOPTR):$root,
[{ return Helper.matchCombineI2PToP2I(*${root}, ${info}); }]),
(apply [{ return Helper.applyCombineI2PToP2I(*${root}, ${info}); }])
>;
// Fold ptr2int(int2ptr(x)) -> x
def i2p_to_p2i_matchinfo: GIDefMatchData<"Register">;
def i2p_to_p2i: GICombineRule<
(defs root:$root, i2p_to_p2i_matchinfo:$info),
(match (wip_match_opcode G_PTRTOINT):$root,
[{ return Helper.matchCombineP2IToI2P(*${root}, ${info}); }]),
(apply [{ return Helper.applyCombineP2IToI2P(*${root}, ${info}); }])
>;
// 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,
@ -267,7 +285,8 @@ def undef_combines : GICombineGroup<[undef_to_fp_zero, undef_to_int_zero,
def identity_combines : GICombineGroup<[select_same_val, right_identity_zero,
binop_same_val, binop_left_to_zero,
binop_right_to_zero]>;
binop_right_to_zero, p2i_to_i2p,
i2p_to_p2i]>;
def trivial_combines : GICombineGroup<[copy_prop, mul_to_shl]>;
def all_combines : GICombineGroup<[trivial_combines, ptr_add_immed_chain,

View File

@ -1545,6 +1545,39 @@ bool CombinerHelper::tryCombineShiftToUnmerge(MachineInstr &MI,
return false;
}
bool CombinerHelper::matchCombineI2PToP2I(MachineInstr &MI, Register &Reg) {
assert(MI.getOpcode() == TargetOpcode::G_INTTOPTR && "Expected a G_INTTOPTR");
Register DstReg = MI.getOperand(0).getReg();
LLT DstTy = MRI.getType(DstReg);
Register SrcReg = MI.getOperand(1).getReg();
return mi_match(SrcReg, MRI,
m_GPtrToInt(m_all_of(m_SpecificType(DstTy), m_Reg(Reg))));
}
bool CombinerHelper::applyCombineI2PToP2I(MachineInstr &MI, Register &Reg) {
assert(MI.getOpcode() == TargetOpcode::G_INTTOPTR && "Expected a G_INTTOPTR");
Register DstReg = MI.getOperand(0).getReg();
Builder.setInstr(MI);
Builder.buildCopy(DstReg, Reg);
MI.eraseFromParent();
return true;
}
bool CombinerHelper::matchCombineP2IToI2P(MachineInstr &MI, Register &Reg) {
assert(MI.getOpcode() == TargetOpcode::G_PTRTOINT && "Expected a G_PTRTOINT");
Register SrcReg = MI.getOperand(1).getReg();
return mi_match(SrcReg, MRI, m_GIntToPtr(m_Reg(Reg)));
}
bool CombinerHelper::applyCombineP2IToI2P(MachineInstr &MI, Register &Reg) {
assert(MI.getOpcode() == TargetOpcode::G_PTRTOINT && "Expected a G_PTRTOINT");
Register DstReg = MI.getOperand(0).getReg();
Builder.setInstr(MI);
Builder.buildZExtOrTrunc(DstReg, Reg);
MI.eraseFromParent();
return true;
}
bool CombinerHelper::matchAnyExplicitUseIsUndef(MachineInstr &MI) {
return any_of(MI.explicit_uses(), [this](const MachineOperand &MO) {
return MO.isReg() &&

View File

@ -0,0 +1,33 @@
# 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
# RUN: llc -debugify-and-strip-all-safe -run-pass=aarch64-prelegalizer-combiner -verify-machineinstrs -mtriple aarch64-unknown-unknown %s -o - | FileCheck %s
---
name: test_combine_inttoptr_same_addressspace
body: |
bb.1:
liveins: $x0, $x1
; CHECK-LABEL: name: test_combine_inttoptr_same_addressspace
; CHECK: [[COPY:%[0-9]+]]:_(p64) = COPY $x0
; CHECK: $x1 = COPY [[COPY]](p64)
%0:_(p64) = COPY $x0
%1:_(s64) = G_PTRTOINT %0
%2:_(p64) = G_INTTOPTR %1
$x1 = COPY %2
...
---
name: test_combine_inttoptr_diff_addressspace
body: |
bb.1:
liveins: $x0, $x1
; CHECK-LABEL: name: test_combine_inttoptr_diff_addressspace
; CHECK: [[COPY:%[0-9]+]]:_(p0) = COPY $x0
; CHECK: [[PTRTOINT:%[0-9]+]]:_(s64) = G_PTRTOINT [[COPY]](p0)
; CHECK: [[INTTOPTR:%[0-9]+]]:_(p64) = G_INTTOPTR [[PTRTOINT]](s64)
; CHECK: $x1 = COPY [[INTTOPTR]](p64)
%0:_(p0) = COPY $x0
%1:_(s64) = G_PTRTOINT %0
%2:_(p64) = G_INTTOPTR %1
$x1 = COPY %2
...

View File

@ -0,0 +1,17 @@
# 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
# RUN: llc -debugify-and-strip-all-safe -run-pass=aarch64-prelegalizer-combiner -verify-machineinstrs -mtriple aarch64-unknown-unknown %s -o - | FileCheck %s
---
name: test_combine_ptrtoint
body: |
bb.1:
liveins: $x0, $x1
; CHECK-LABEL: name: test_combine_ptrtoint
; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
; CHECK: $x1 = COPY [[COPY]](s64)
%0:_(s64) = COPY $x0
%1:_(p64) = G_INTTOPTR %0
%2:_(s64) = G_PTRTOINT %1
$x1 = COPY %2
...