1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 18:54:02 +01:00

[PowerPC] fold addi's imm operand to its imm form consumer's displacement

This patch adds a function to do following transformation:

%0:g8rc_and_g8rc_nox0 = ADDI8 %5:g8rc_and_g8rc_nox0, 144
STD killed %7:g8rc, 16, %0:g8rc_and_g8rc_nox0 :: (store 8 into %ir.8)

------>

STD killed %7:g8rc, 160, %5:g8rc_and_g8rc_nox0 :: (store 8 into %ir.8)

Reviewed By: steven.zhang

Differential Revision: https://reviews.llvm.org/D81723
This commit is contained in:
Chen Zheng 2020-06-18 23:31:51 -04:00
parent be0a92b108
commit 4cc65c325c
3 changed files with 193 additions and 12 deletions

View File

@ -2563,7 +2563,8 @@ MachineInstr *PPCInstrInfo::getForwardingDefMI(
MachineRegisterInfo *MRI = &MI.getParent()->getParent()->getRegInfo();
const TargetRegisterInfo *TRI = &getRegisterInfo();
// If we're in SSA, get the defs through the MRI. Otherwise, only look
// within the basic block to see if the register is defined using an LI/LI8.
// within the basic block to see if the register is defined using an
// LI/LI8/ADDI/ADDI8.
if (MRI->isSSA()) {
for (int i = 1, e = MI.getNumOperands(); i < e; i++) {
if (!MI.getOperand(i).isReg())
@ -2574,9 +2575,16 @@ MachineInstr *PPCInstrInfo::getForwardingDefMI(
unsigned TrueReg = TRI->lookThruCopyLike(Reg, MRI);
if (Register::isVirtualRegister(TrueReg)) {
DefMI = MRI->getVRegDef(TrueReg);
if (DefMI->getOpcode() == PPC::LI || DefMI->getOpcode() == PPC::LI8) {
if (DefMI->getOpcode() == PPC::LI || DefMI->getOpcode() == PPC::LI8 ||
DefMI->getOpcode() == PPC::ADDI ||
DefMI->getOpcode() == PPC::ADDI8) {
OpNoForForwarding = i;
break;
// The ADDI and LI operand maybe exist in one instruction at same
// time. we prefer to fold LI operand as LI only has one Imm operand
// and is more possible to be converted. So if current DefMI is
// ADDI/ADDI8, we continue to find possible LI/LI8.
if (DefMI->getOpcode() == PPC::LI || DefMI->getOpcode() == PPC::LI8)
break;
}
}
}
@ -2647,10 +2655,6 @@ const unsigned *PPCInstrInfo::getLoadOpcodesForSpillArray() const {
void PPCInstrInfo::fixupIsDeadOrKill(MachineInstr &StartMI, MachineInstr &EndMI,
unsigned RegNo) const {
const MachineRegisterInfo &MRI =
StartMI.getParent()->getParent()->getRegInfo();
if (MRI.isSSA())
return;
// Instructions between [StartMI, EndMI] should be in same basic block.
assert((StartMI.getParent() == EndMI.getParent()) &&
@ -2973,6 +2977,13 @@ bool PPCInstrInfo::convertToImmediateForm(MachineInstr &MI,
if (KilledDef && KillFwdDefMI)
*KilledDef = DefMI;
// If this is a imm instruction and its register operands is produced by ADDI,
// put the imm into imm inst directly.
if (RI.getMappedIdxOpcForImmOpc(MI.getOpcode()) !=
PPC::INSTRUCTION_LIST_END &&
transformToNewImmFormFedByAdd(MI, *DefMI, ForwardingOperand))
return true;
ImmInstrInfo III;
bool IsVFReg = MI.getOperand(0).isReg()
? isVFRegister(MI.getOperand(0).getReg())
@ -3513,6 +3524,10 @@ bool PPCInstrInfo::isDefMIElgibleForForwarding(MachineInstr &DefMI,
RegMO = &DefMI.getOperand(1);
ImmMO = &DefMI.getOperand(2);
// Before RA, ADDI first operand could be a frame index.
if (!RegMO->isReg())
return false;
// This DefMI is elgible for forwarding if it is:
// 1. add inst
// 2. one of the operands is Imm/CPI/Global.
@ -3561,7 +3576,8 @@ bool PPCInstrInfo::isRegElgibleForForwarding(
bool PPCInstrInfo::isImmElgibleForForwarding(const MachineOperand &ImmMO,
const MachineInstr &DefMI,
const ImmInstrInfo &III,
int64_t &Imm) const {
int64_t &Imm,
int64_t BaseImm) const {
assert(isAnImmediateOperand(ImmMO) && "ImmMO is NOT an immediate");
if (DefMI.getOpcode() == PPC::ADDItocL) {
// The operand for ADDItocL is CPI, which isn't imm at compiling time,
@ -3584,10 +3600,10 @@ bool PPCInstrInfo::isImmElgibleForForwarding(const MachineOperand &ImmMO,
if (ImmMO.isImm()) {
// It is Imm, we need to check if the Imm fit the range.
int64_t Immediate = ImmMO.getImm();
// Sign-extend to 64-bits.
Imm = ((uint64_t)Immediate & ~0x7FFFuLL) != 0 ?
(Immediate | 0xFFFFFFFFFFFF0000) : Immediate;
// DefMI may be folded with another imm form instruction, the result Imm is
// the sum of Imm of DefMI and BaseImm which is from imm form instruction.
Imm = SignExtend64<16>(ImmMO.getImm() + BaseImm);
if (Imm % III.ImmMustBeMultipleOf)
return false;
@ -3840,6 +3856,99 @@ bool PPCInstrInfo::simplifyToLI(MachineInstr &MI, MachineInstr &DefMI,
return false;
}
bool PPCInstrInfo::transformToNewImmFormFedByAdd(
MachineInstr &MI, MachineInstr &DefMI, unsigned OpNoForForwarding) const {
MachineRegisterInfo *MRI = &MI.getParent()->getParent()->getRegInfo();
bool PostRA = !MRI->isSSA();
// FIXME: extend this to post-ra. Need to do some change in getForwardingDefMI
// for post-ra.
if (PostRA)
return false;
// Only handle load/store.
if (!MI.mayLoadOrStore())
return false;
unsigned XFormOpcode = RI.getMappedIdxOpcForImmOpc(MI.getOpcode());
assert((XFormOpcode != PPC::INSTRUCTION_LIST_END) &&
"MI must have x-form opcode");
// get Imm Form info.
ImmInstrInfo III;
bool IsVFReg = MI.getOperand(0).isReg()
? isVFRegister(MI.getOperand(0).getReg())
: false;
if (!instrHasImmForm(XFormOpcode, IsVFReg, III, PostRA))
return false;
if (!III.IsSummingOperands)
return false;
if (OpNoForForwarding != III.OpNoForForwarding)
return false;
MachineOperand ImmOperandMI = MI.getOperand(III.ImmOpNo);
if (!ImmOperandMI.isImm())
return false;
// Check DefMI.
MachineOperand *ImmMO = nullptr;
MachineOperand *RegMO = nullptr;
if (!isDefMIElgibleForForwarding(DefMI, III, ImmMO, RegMO))
return false;
assert(ImmMO && RegMO && "Imm and Reg operand must have been set");
// Check Imm.
// Set ImmBase from imm instruction as base and get new Imm inside
// isImmElgibleForForwarding.
int64_t ImmBase = ImmOperandMI.getImm();
int64_t Imm = 0;
if (!isImmElgibleForForwarding(*ImmMO, DefMI, III, Imm, ImmBase))
return false;
// Get killed info in case fixup needed after transformation.
unsigned ForwardKilledOperandReg = ~0U;
if (MI.getOperand(III.OpNoForForwarding).isKill())
ForwardKilledOperandReg = MI.getOperand(III.OpNoForForwarding).getReg();
// Do the transform
LLVM_DEBUG(dbgs() << "Replacing instruction:\n");
LLVM_DEBUG(MI.dump());
LLVM_DEBUG(dbgs() << "Fed by:\n");
LLVM_DEBUG(DefMI.dump());
MI.getOperand(III.OpNoForForwarding).setReg(RegMO->getReg());
MI.getOperand(III.OpNoForForwarding).setIsKill(RegMO->isKill());
MI.getOperand(III.ImmOpNo).setImm(Imm);
// FIXME: fix kill/dead flag if MI and DefMI are not in same basic block.
if (DefMI.getParent() == MI.getParent()) {
// Check if reg is killed between MI and DefMI.
auto IsKilledFor = [&](unsigned Reg) {
MachineBasicBlock::const_reverse_iterator It = MI;
MachineBasicBlock::const_reverse_iterator E = DefMI;
It++;
for (; It != E; ++It) {
if (It->killsRegister(Reg))
return true;
}
return false;
};
// Update kill flag
if (RegMO->isKill() || IsKilledFor(RegMO->getReg()))
fixupIsDeadOrKill(DefMI, MI, RegMO->getReg());
if (ForwardKilledOperandReg != ~0U)
fixupIsDeadOrKill(DefMI, MI, ForwardKilledOperandReg);
}
LLVM_DEBUG(dbgs() << "With:\n");
LLVM_DEBUG(MI.dump());
return true;
}
// If an X-Form instruction is fed by an add-immediate and one of its operands
// is the literal zero, attempt to forward the source of the add-immediate to
// the corresponding D-Form instruction with the displacement coming from

View File

@ -191,6 +191,10 @@ class PPCInstrInfo : public PPCGenInstrInfo {
// LI8.
bool simplifyToLI(MachineInstr &MI, MachineInstr &DefMI,
unsigned OpNoForForwarding, MachineInstr **KilledDef) const;
// If the inst is imm-form and its register operand is produced by a ADDI, put
// the imm into the inst directly and remove the ADDI if possible.
bool transformToNewImmFormFedByAdd(MachineInstr &MI, MachineInstr &DefMI,
unsigned OpNoForForwarding) const;
// If the inst is x-form and has imm-form and one of its operand is produced
// by a LI, put the imm into the inst directly and remove the LI if possible.
bool transformToImmFormFedByLI(MachineInstr &MI, const ImmInstrInfo &III,
@ -221,7 +225,8 @@ class PPCInstrInfo : public PPCGenInstrInfo {
bool isImmElgibleForForwarding(const MachineOperand &ImmMO,
const MachineInstr &DefMI,
const ImmInstrInfo &III,
int64_t &Imm) const;
int64_t &Imm,
int64_t BaseImm = 0) const;
bool isRegElgibleForForwarding(const MachineOperand &RegMO,
const MachineInstr &DefMI,
const MachineInstr &MI, bool KillDefMI,

View File

@ -0,0 +1,67 @@
# RUN: llc -mtriple=powerpc64le-unknown-linux-gnu -verify-machineinstrs \
# RUN: -run-pass ppc-mi-peepholes -ppc-convert-rr-to-ri %s -o - | FileCheck %s
---
name: foldNewDformStore
# CHECK: name: foldNewDformStore
tracksRegLiveness: true
body: |
bb.0.entry:
liveins: $x3
%0:g8rc_and_g8rc_nox0 = COPY $x3
%1:g8rc_and_g8rc_nox0 = ADDI8 %0:g8rc_and_g8rc_nox0, 144
%2:g8rc = LI8 0
; CHECK: STD killed %2, 160, %0
STD killed %2:g8rc, 16, %1:g8rc_and_g8rc_nox0
BLR8 implicit $lr8, implicit $rm
...
---
name: foldNewDformStoreAlignNotMatch
# CHECK: name: foldNewDformStoreAlignNotMatch
tracksRegLiveness: true
body: |
bb.0.entry:
liveins: $x3
%0:g8rc_and_g8rc_nox0 = COPY $x3
%1:g8rc_and_g8rc_nox0 = ADDI8 %0:g8rc_and_g8rc_nox0, 141
%2:g8rc = LI8 0
; CHECK: STD killed %2, 16, %1
STD killed %2:g8rc, 16, %1:g8rc_and_g8rc_nox0
BLR8 implicit $lr8, implicit $rm
...
---
name: foldNewDformStoreKilledFlag
# CHECK: name: foldNewDformStoreKilledFlag
tracksRegLiveness: true
body: |
bb.0.entry:
liveins: $x3
%0:g8rc_and_g8rc_nox0 = COPY $x3
%1:g8rc_and_g8rc_nox0 = ADDI8 %0:g8rc_and_g8rc_nox0, 144
%2:g8rc = LI8 0
; CHECK: STD %1, 0, %0
STD %1:g8rc_and_g8rc_nox0, 0, killed %0:g8rc_and_g8rc_nox0
; CHECK: STD killed %2, 160, killed %0
STD killed %2:g8rc, 16, %1:g8rc_and_g8rc_nox0
BLR8 implicit $lr8, implicit $rm
...
---
name: foldNewDformPreferLIOperand
# CHECK: name: foldNewDformPreferLIOperand
tracksRegLiveness: true
body: |
bb.0.entry:
liveins: $x3
%0:g8rc_and_g8rc_nox0 = COPY $x3
%1:g8rc = ADDI8 %0:g8rc_and_g8rc_nox0, 1
%2:g8rc = LI8 1
; CHECK: SUBFIC8 killed %1, 1, implicit-def $carry
%3:g8rc = SUBFC8 killed %1:g8rc, %2:g8rc, implicit-def $carry
%4:g8rc = SUBFE8 %2:g8rc, %2:g8rc, implicit-def dead $carry, implicit $carry
%5:g8rc = NEG8 killed %4:g8rc
$x3 = COPY %5:g8rc
BLR8 implicit $lr8, implicit $rm, implicit $x3
...