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:
parent
be0a92b108
commit
4cc65c325c
@ -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
|
||||
|
@ -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,
|
||||
|
67
test/CodeGen/PowerPC/convert-ri-addi-to-ri.mir
Normal file
67
test/CodeGen/PowerPC/convert-ri-addi-to-ri.mir
Normal 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
|
||||
...
|
Loading…
Reference in New Issue
Block a user