2012-02-18 20:03:15 +08:00
|
|
|
//===-- PPCInstrInfo.cpp - PowerPC Instruction Information ----------------===//
|
2005-04-22 07:30:14 +08:00
|
|
|
//
|
2004-08-17 12:55:41 +08:00
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
2007-12-30 04:36:04 +08:00
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
2005-04-22 07:30:14 +08:00
|
|
|
//
|
2004-08-17 12:55:41 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file contains the PowerPC implementation of the TargetInstrInfo class.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2005-10-15 07:59:06 +08:00
|
|
|
#include "PPCInstrInfo.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "MCTargetDesc/PPCPredicates.h"
|
2011-07-11 11:57:24 +08:00
|
|
|
#include "PPC.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "PPCHazardRecognizers.h"
|
2008-01-02 05:11:32 +08:00
|
|
|
#include "PPCInstrBuilder.h"
|
2008-03-04 06:19:16 +08:00
|
|
|
#include "PPCMachineFunctionInfo.h"
|
2006-06-17 08:01:04 +08:00
|
|
|
#include "PPCTargetMachine.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2010-07-17 02:22:00 +08:00
|
|
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
2004-08-17 12:55:41 +08:00
|
|
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
2010-07-17 02:22:00 +08:00
|
|
|
#include "llvm/CodeGen/MachineMemOperand.h"
|
2010-02-27 05:09:24 +08:00
|
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
2012-04-02 03:22:40 +08:00
|
|
|
#include "llvm/CodeGen/PseudoSourceValue.h"
|
2011-07-11 11:57:24 +08:00
|
|
|
#include "llvm/MC/MCAsmInfo.h"
|
2008-03-05 07:13:51 +08:00
|
|
|
#include "llvm/Support/CommandLine.h"
|
2009-07-09 04:53:28 +08:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2011-08-25 02:08:43 +08:00
|
|
|
#include "llvm/Support/TargetRegistry.h"
|
2009-07-09 04:53:28 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2004-08-17 12:55:41 +08:00
|
|
|
|
2011-07-02 01:57:27 +08:00
|
|
|
#define GET_INSTRINFO_CTOR
|
2011-06-29 04:07:07 +08:00
|
|
|
#include "PPCGenInstrInfo.inc"
|
|
|
|
|
2010-04-16 01:20:57 +08:00
|
|
|
using namespace llvm;
|
2008-03-05 07:13:51 +08:00
|
|
|
|
2012-06-08 23:38:25 +08:00
|
|
|
static cl::
|
2012-06-09 03:19:53 +08:00
|
|
|
opt<bool> DisableCTRLoopAnal("disable-ppc-ctrloop-analysis", cl::Hidden,
|
|
|
|
cl::desc("Disable analysis for CTR loops"));
|
2012-06-08 23:38:25 +08:00
|
|
|
|
2006-06-17 08:01:04 +08:00
|
|
|
PPCInstrInfo::PPCInstrInfo(PPCTargetMachine &tm)
|
2011-07-02 01:57:27 +08:00
|
|
|
: PPCGenInstrInfo(PPC::ADJCALLSTACKDOWN, PPC::ADJCALLSTACKUP),
|
2011-06-29 05:14:33 +08:00
|
|
|
TM(tm), RI(*TM.getSubtargetImpl(), *this) {}
|
2006-06-17 08:01:04 +08:00
|
|
|
|
Various bits of framework needed for precise machine-level selection
DAG scheduling during isel. Most new functionality is currently
guarded by -enable-sched-cycles and -enable-sched-hazard.
Added InstrItineraryData::IssueWidth field, currently derived from
ARM itineraries, but could be initialized differently on other targets.
Added ScheduleHazardRecognizer::MaxLookAhead to indicate whether it is
active, and if so how many cycles of state it holds.
Added SchedulingPriorityQueue::HasReadyFilter to allowing gating entry
into the scheduler's available queue.
ScoreboardHazardRecognizer now accesses the ScheduleDAG in order to
get information about it's SUnits, provides RecedeCycle for bottom-up
scheduling, correctly computes scoreboard depth, tracks IssueCount, and
considers potential stall cycles when checking for hazards.
ScheduleDAGRRList now models machine cycles and hazards (under
flags). It tracks MinAvailableCycle, drives the hazard recognizer and
priority queue's ready filter, manages a new PendingQueue, properly
accounts for stall cycles, etc.
llvm-svn: 122541
2010-12-24 13:03:26 +08:00
|
|
|
/// CreateTargetHazardRecognizer - Return the hazard recognizer to use for
|
|
|
|
/// this target when scheduling the DAG.
|
|
|
|
ScheduleHazardRecognizer *PPCInstrInfo::CreateTargetHazardRecognizer(
|
|
|
|
const TargetMachine *TM,
|
|
|
|
const ScheduleDAG *DAG) const {
|
2011-10-17 12:03:49 +08:00
|
|
|
unsigned Directive = TM->getSubtarget<PPCSubtarget>().getDarwinDirective();
|
2012-08-29 00:12:39 +08:00
|
|
|
if (Directive == PPC::DIR_440 || Directive == PPC::DIR_A2 ||
|
|
|
|
Directive == PPC::DIR_E500mc || Directive == PPC::DIR_E5500) {
|
2011-11-23 00:21:04 +08:00
|
|
|
const InstrItineraryData *II = TM->getInstrItineraryData();
|
2012-03-31 22:45:15 +08:00
|
|
|
return new PPCScoreboardHazardRecognizer(II, DAG);
|
2011-10-17 12:03:49 +08:00
|
|
|
}
|
2011-12-02 12:58:02 +08:00
|
|
|
|
2012-11-28 10:35:17 +08:00
|
|
|
return TargetInstrInfo::CreateTargetHazardRecognizer(TM, DAG);
|
Various bits of framework needed for precise machine-level selection
DAG scheduling during isel. Most new functionality is currently
guarded by -enable-sched-cycles and -enable-sched-hazard.
Added InstrItineraryData::IssueWidth field, currently derived from
ARM itineraries, but could be initialized differently on other targets.
Added ScheduleHazardRecognizer::MaxLookAhead to indicate whether it is
active, and if so how many cycles of state it holds.
Added SchedulingPriorityQueue::HasReadyFilter to allowing gating entry
into the scheduler's available queue.
ScoreboardHazardRecognizer now accesses the ScheduleDAG in order to
get information about it's SUnits, provides RecedeCycle for bottom-up
scheduling, correctly computes scoreboard depth, tracks IssueCount, and
considers potential stall cycles when checking for hazards.
ScheduleDAGRRList now models machine cycles and hazards (under
flags). It tracks MinAvailableCycle, drives the hazard recognizer and
priority queue's ready filter, manages a new PendingQueue, properly
accounts for stall cycles, etc.
llvm-svn: 122541
2010-12-24 13:03:26 +08:00
|
|
|
}
|
|
|
|
|
2011-12-02 12:58:02 +08:00
|
|
|
/// CreateTargetPostRAHazardRecognizer - Return the postRA hazard recognizer
|
|
|
|
/// to use for this target when scheduling the DAG.
|
|
|
|
ScheduleHazardRecognizer *PPCInstrInfo::CreateTargetPostRAHazardRecognizer(
|
|
|
|
const InstrItineraryData *II,
|
|
|
|
const ScheduleDAG *DAG) const {
|
|
|
|
unsigned Directive = TM.getSubtarget<PPCSubtarget>().getDarwinDirective();
|
|
|
|
|
|
|
|
// Most subtargets use a PPC970 recognizer.
|
2012-08-29 00:12:39 +08:00
|
|
|
if (Directive != PPC::DIR_440 && Directive != PPC::DIR_A2 &&
|
|
|
|
Directive != PPC::DIR_E500mc && Directive != PPC::DIR_E5500) {
|
2011-12-02 12:58:02 +08:00
|
|
|
const TargetInstrInfo *TII = TM.getInstrInfo();
|
|
|
|
assert(TII && "No InstrInfo?");
|
|
|
|
|
|
|
|
return new PPCHazardRecognizer970(*TII);
|
|
|
|
}
|
|
|
|
|
2012-04-02 03:22:40 +08:00
|
|
|
return new PPCScoreboardHazardRecognizer(II, DAG);
|
2011-12-02 12:58:02 +08:00
|
|
|
}
|
2012-06-20 05:14:34 +08:00
|
|
|
|
|
|
|
// Detect 32 -> 64-bit extensions where we may reuse the low sub-register.
|
|
|
|
bool PPCInstrInfo::isCoalescableExtInstr(const MachineInstr &MI,
|
|
|
|
unsigned &SrcReg, unsigned &DstReg,
|
|
|
|
unsigned &SubIdx) const {
|
|
|
|
switch (MI.getOpcode()) {
|
|
|
|
default: return false;
|
|
|
|
case PPC::EXTSW:
|
|
|
|
case PPC::EXTSW_32_64:
|
|
|
|
SrcReg = MI.getOperand(1).getReg();
|
|
|
|
DstReg = MI.getOperand(0).getReg();
|
|
|
|
SubIdx = PPC::sub_32;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-12-24 12:28:06 +08:00
|
|
|
unsigned PPCInstrInfo::isLoadFromStackSlot(const MachineInstr *MI,
|
2006-03-17 06:24:02 +08:00
|
|
|
int &FrameIndex) const {
|
2006-02-03 04:12:32 +08:00
|
|
|
switch (MI->getOpcode()) {
|
|
|
|
default: break;
|
|
|
|
case PPC::LD:
|
|
|
|
case PPC::LWZ:
|
|
|
|
case PPC::LFS:
|
|
|
|
case PPC::LFD:
|
2008-10-03 23:45:36 +08:00
|
|
|
if (MI->getOperand(1).isImm() && !MI->getOperand(1).getImm() &&
|
|
|
|
MI->getOperand(2).isFI()) {
|
2007-12-31 07:10:15 +08:00
|
|
|
FrameIndex = MI->getOperand(2).getIndex();
|
2006-02-03 04:12:32 +08:00
|
|
|
return MI->getOperand(0).getReg();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return 0;
|
2006-02-03 04:16:12 +08:00
|
|
|
}
|
2006-02-03 04:12:32 +08:00
|
|
|
|
2010-12-24 12:28:06 +08:00
|
|
|
unsigned PPCInstrInfo::isStoreToStackSlot(const MachineInstr *MI,
|
2006-02-03 04:16:12 +08:00
|
|
|
int &FrameIndex) const {
|
|
|
|
switch (MI->getOpcode()) {
|
|
|
|
default: break;
|
2006-02-03 05:07:50 +08:00
|
|
|
case PPC::STD:
|
2006-02-03 04:16:12 +08:00
|
|
|
case PPC::STW:
|
|
|
|
case PPC::STFS:
|
|
|
|
case PPC::STFD:
|
2008-10-03 23:45:36 +08:00
|
|
|
if (MI->getOperand(1).isImm() && !MI->getOperand(1).getImm() &&
|
|
|
|
MI->getOperand(2).isFI()) {
|
2007-12-31 07:10:15 +08:00
|
|
|
FrameIndex = MI->getOperand(2).getIndex();
|
2006-02-03 04:16:12 +08:00
|
|
|
return MI->getOperand(0).getReg();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2006-02-03 04:12:32 +08:00
|
|
|
|
2005-09-10 02:17:41 +08:00
|
|
|
// commuteInstruction - We can commute rlwimi instructions, but only if the
|
|
|
|
// rotate amt is zero. We also have to munge the immediates a bit.
|
2008-06-16 15:33:11 +08:00
|
|
|
MachineInstr *
|
|
|
|
PPCInstrInfo::commuteInstruction(MachineInstr *MI, bool NewMI) const {
|
2008-07-08 07:14:23 +08:00
|
|
|
MachineFunction &MF = *MI->getParent()->getParent();
|
|
|
|
|
2005-09-10 02:17:41 +08:00
|
|
|
// Normal instructions can be commuted the obvious way.
|
|
|
|
if (MI->getOpcode() != PPC::RLWIMI)
|
2012-11-28 10:35:17 +08:00
|
|
|
return TargetInstrInfo::commuteInstruction(MI, NewMI);
|
2010-12-24 12:28:06 +08:00
|
|
|
|
2005-09-10 02:17:41 +08:00
|
|
|
// Cannot commute if it has a non-zero rotate count.
|
2007-12-31 04:49:49 +08:00
|
|
|
if (MI->getOperand(3).getImm() != 0)
|
2005-09-10 02:17:41 +08:00
|
|
|
return 0;
|
2010-12-24 12:28:06 +08:00
|
|
|
|
2005-09-10 02:17:41 +08:00
|
|
|
// If we have a zero rotate count, we have:
|
|
|
|
// M = mask(MB,ME)
|
|
|
|
// Op0 = (Op1 & ~M) | (Op2 & M)
|
|
|
|
// Change this to:
|
|
|
|
// M = mask((ME+1)&31, (MB-1)&31)
|
|
|
|
// Op0 = (Op2 & ~M) | (Op1 & M)
|
|
|
|
|
|
|
|
// Swap op1/op2
|
2008-02-13 10:46:49 +08:00
|
|
|
unsigned Reg0 = MI->getOperand(0).getReg();
|
2005-09-10 02:17:41 +08:00
|
|
|
unsigned Reg1 = MI->getOperand(1).getReg();
|
|
|
|
unsigned Reg2 = MI->getOperand(2).getReg();
|
2006-11-16 04:58:11 +08:00
|
|
|
bool Reg1IsKill = MI->getOperand(1).isKill();
|
|
|
|
bool Reg2IsKill = MI->getOperand(2).isKill();
|
2008-06-16 15:33:11 +08:00
|
|
|
bool ChangeReg0 = false;
|
2008-02-13 10:46:49 +08:00
|
|
|
// If machine instrs are no longer in two-address forms, update
|
|
|
|
// destination register as well.
|
|
|
|
if (Reg0 == Reg1) {
|
|
|
|
// Must be two address instruction!
|
2011-06-29 03:10:37 +08:00
|
|
|
assert(MI->getDesc().getOperandConstraint(0, MCOI::TIED_TO) &&
|
2008-02-13 10:46:49 +08:00
|
|
|
"Expecting a two-address instruction!");
|
|
|
|
Reg2IsKill = false;
|
2008-06-16 15:33:11 +08:00
|
|
|
ChangeReg0 = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Masks.
|
|
|
|
unsigned MB = MI->getOperand(4).getImm();
|
|
|
|
unsigned ME = MI->getOperand(5).getImm();
|
|
|
|
|
|
|
|
if (NewMI) {
|
|
|
|
// Create a new instruction.
|
|
|
|
unsigned Reg0 = ChangeReg0 ? Reg2 : MI->getOperand(0).getReg();
|
|
|
|
bool Reg0IsDead = MI->getOperand(0).isDead();
|
2009-02-12 08:02:55 +08:00
|
|
|
return BuildMI(MF, MI->getDebugLoc(), MI->getDesc())
|
2009-05-14 05:33:08 +08:00
|
|
|
.addReg(Reg0, RegState::Define | getDeadRegState(Reg0IsDead))
|
|
|
|
.addReg(Reg2, getKillRegState(Reg2IsKill))
|
|
|
|
.addReg(Reg1, getKillRegState(Reg1IsKill))
|
2008-06-16 15:33:11 +08:00
|
|
|
.addImm((ME+1) & 31)
|
|
|
|
.addImm((MB-1) & 31);
|
2008-02-13 10:46:49 +08:00
|
|
|
}
|
2008-06-16 15:33:11 +08:00
|
|
|
|
|
|
|
if (ChangeReg0)
|
|
|
|
MI->getOperand(0).setReg(Reg2);
|
2006-05-05 01:52:23 +08:00
|
|
|
MI->getOperand(2).setReg(Reg1);
|
|
|
|
MI->getOperand(1).setReg(Reg2);
|
2007-12-31 05:56:09 +08:00
|
|
|
MI->getOperand(2).setIsKill(Reg1IsKill);
|
|
|
|
MI->getOperand(1).setIsKill(Reg2IsKill);
|
2010-12-24 12:28:06 +08:00
|
|
|
|
2005-09-10 02:17:41 +08:00
|
|
|
// Swap the mask around.
|
2007-12-31 04:49:49 +08:00
|
|
|
MI->getOperand(4).setImm((ME+1) & 31);
|
|
|
|
MI->getOperand(5).setImm((MB-1) & 31);
|
2005-09-10 02:17:41 +08:00
|
|
|
return MI;
|
|
|
|
}
|
2006-03-06 07:49:55 +08:00
|
|
|
|
2010-12-24 12:28:06 +08:00
|
|
|
void PPCInstrInfo::insertNoop(MachineBasicBlock &MBB,
|
2006-03-06 07:49:55 +08:00
|
|
|
MachineBasicBlock::iterator MI) const {
|
2010-04-03 04:16:16 +08:00
|
|
|
DebugLoc DL;
|
2009-02-12 08:02:55 +08:00
|
|
|
BuildMI(MBB, MI, DL, get(PPC::NOP));
|
2006-03-06 07:49:55 +08:00
|
|
|
}
|
2006-10-14 05:21:17 +08:00
|
|
|
|
|
|
|
|
|
|
|
// Branch analysis.
|
2012-06-08 23:38:21 +08:00
|
|
|
// Note: If the condition register is set to CTR or CTR8 then this is a
|
|
|
|
// BDNZ (imm == 1) or BDZ (imm == 0) branch.
|
2006-10-14 05:21:17 +08:00
|
|
|
bool PPCInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,MachineBasicBlock *&TBB,
|
|
|
|
MachineBasicBlock *&FBB,
|
2009-02-09 15:14:22 +08:00
|
|
|
SmallVectorImpl<MachineOperand> &Cond,
|
|
|
|
bool AllowModify) const {
|
2012-06-08 23:38:21 +08:00
|
|
|
bool isPPC64 = TM.getSubtargetImpl()->isPPC64();
|
|
|
|
|
2006-10-14 05:21:17 +08:00
|
|
|
// If the block has no terminators, it just falls into the block after it.
|
|
|
|
MachineBasicBlock::iterator I = MBB.end();
|
2010-04-02 09:38:09 +08:00
|
|
|
if (I == MBB.begin())
|
|
|
|
return false;
|
|
|
|
--I;
|
|
|
|
while (I->isDebugValue()) {
|
|
|
|
if (I == MBB.begin())
|
|
|
|
return false;
|
|
|
|
--I;
|
|
|
|
}
|
|
|
|
if (!isUnpredicatedTerminator(I))
|
2006-10-14 05:21:17 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
// Get the last instruction in the block.
|
|
|
|
MachineInstr *LastInst = I;
|
2010-12-24 12:28:06 +08:00
|
|
|
|
2006-10-14 05:21:17 +08:00
|
|
|
// If there is only one terminator instruction, process it.
|
2007-06-09 05:59:56 +08:00
|
|
|
if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) {
|
2006-10-14 05:21:17 +08:00
|
|
|
if (LastInst->getOpcode() == PPC::B) {
|
2009-05-09 07:09:25 +08:00
|
|
|
if (!LastInst->getOperand(0).isMBB())
|
|
|
|
return true;
|
2007-12-31 07:10:15 +08:00
|
|
|
TBB = LastInst->getOperand(0).getMBB();
|
2006-10-14 05:21:17 +08:00
|
|
|
return false;
|
2006-11-18 06:14:47 +08:00
|
|
|
} else if (LastInst->getOpcode() == PPC::BCC) {
|
2009-05-09 07:09:25 +08:00
|
|
|
if (!LastInst->getOperand(2).isMBB())
|
|
|
|
return true;
|
2006-10-14 05:21:17 +08:00
|
|
|
// Block ends with fall-through condbranch.
|
2007-12-31 07:10:15 +08:00
|
|
|
TBB = LastInst->getOperand(2).getMBB();
|
2006-10-14 05:21:17 +08:00
|
|
|
Cond.push_back(LastInst->getOperand(0));
|
|
|
|
Cond.push_back(LastInst->getOperand(1));
|
2006-10-21 14:03:11 +08:00
|
|
|
return false;
|
2012-06-08 23:38:21 +08:00
|
|
|
} else if (LastInst->getOpcode() == PPC::BDNZ8 ||
|
|
|
|
LastInst->getOpcode() == PPC::BDNZ) {
|
|
|
|
if (!LastInst->getOperand(0).isMBB())
|
|
|
|
return true;
|
2012-06-09 03:19:53 +08:00
|
|
|
if (DisableCTRLoopAnal)
|
2012-06-08 23:38:25 +08:00
|
|
|
return true;
|
2012-06-08 23:38:21 +08:00
|
|
|
TBB = LastInst->getOperand(0).getMBB();
|
|
|
|
Cond.push_back(MachineOperand::CreateImm(1));
|
|
|
|
Cond.push_back(MachineOperand::CreateReg(isPPC64 ? PPC::CTR8 : PPC::CTR,
|
|
|
|
true));
|
|
|
|
return false;
|
|
|
|
} else if (LastInst->getOpcode() == PPC::BDZ8 ||
|
|
|
|
LastInst->getOpcode() == PPC::BDZ) {
|
|
|
|
if (!LastInst->getOperand(0).isMBB())
|
|
|
|
return true;
|
2012-06-09 03:19:53 +08:00
|
|
|
if (DisableCTRLoopAnal)
|
2012-06-08 23:38:25 +08:00
|
|
|
return true;
|
2012-06-08 23:38:21 +08:00
|
|
|
TBB = LastInst->getOperand(0).getMBB();
|
|
|
|
Cond.push_back(MachineOperand::CreateImm(0));
|
|
|
|
Cond.push_back(MachineOperand::CreateReg(isPPC64 ? PPC::CTR8 : PPC::CTR,
|
|
|
|
true));
|
|
|
|
return false;
|
2006-10-14 05:21:17 +08:00
|
|
|
}
|
2012-06-08 23:38:21 +08:00
|
|
|
|
2006-10-14 05:21:17 +08:00
|
|
|
// Otherwise, don't know what this is.
|
|
|
|
return true;
|
|
|
|
}
|
2010-12-24 12:28:06 +08:00
|
|
|
|
2006-10-14 05:21:17 +08:00
|
|
|
// Get the instruction before it if it's a terminator.
|
|
|
|
MachineInstr *SecondLastInst = I;
|
|
|
|
|
|
|
|
// If there are three terminators, we don't know what sort of block this is.
|
|
|
|
if (SecondLastInst && I != MBB.begin() &&
|
2007-06-09 05:59:56 +08:00
|
|
|
isUnpredicatedTerminator(--I))
|
2006-10-14 05:21:17 +08:00
|
|
|
return true;
|
2010-12-24 12:28:06 +08:00
|
|
|
|
2006-11-18 06:14:47 +08:00
|
|
|
// If the block ends with PPC::B and PPC:BCC, handle it.
|
2010-12-24 12:28:06 +08:00
|
|
|
if (SecondLastInst->getOpcode() == PPC::BCC &&
|
2006-10-14 05:21:17 +08:00
|
|
|
LastInst->getOpcode() == PPC::B) {
|
2009-05-09 07:09:25 +08:00
|
|
|
if (!SecondLastInst->getOperand(2).isMBB() ||
|
|
|
|
!LastInst->getOperand(0).isMBB())
|
|
|
|
return true;
|
2007-12-31 07:10:15 +08:00
|
|
|
TBB = SecondLastInst->getOperand(2).getMBB();
|
2006-10-14 05:21:17 +08:00
|
|
|
Cond.push_back(SecondLastInst->getOperand(0));
|
|
|
|
Cond.push_back(SecondLastInst->getOperand(1));
|
2007-12-31 07:10:15 +08:00
|
|
|
FBB = LastInst->getOperand(0).getMBB();
|
2006-10-14 05:21:17 +08:00
|
|
|
return false;
|
2012-06-08 23:38:21 +08:00
|
|
|
} else if ((SecondLastInst->getOpcode() == PPC::BDNZ8 ||
|
|
|
|
SecondLastInst->getOpcode() == PPC::BDNZ) &&
|
|
|
|
LastInst->getOpcode() == PPC::B) {
|
|
|
|
if (!SecondLastInst->getOperand(0).isMBB() ||
|
|
|
|
!LastInst->getOperand(0).isMBB())
|
|
|
|
return true;
|
2012-06-09 03:19:53 +08:00
|
|
|
if (DisableCTRLoopAnal)
|
2012-06-08 23:38:25 +08:00
|
|
|
return true;
|
2012-06-08 23:38:21 +08:00
|
|
|
TBB = SecondLastInst->getOperand(0).getMBB();
|
|
|
|
Cond.push_back(MachineOperand::CreateImm(1));
|
|
|
|
Cond.push_back(MachineOperand::CreateReg(isPPC64 ? PPC::CTR8 : PPC::CTR,
|
|
|
|
true));
|
|
|
|
FBB = LastInst->getOperand(0).getMBB();
|
|
|
|
return false;
|
|
|
|
} else if ((SecondLastInst->getOpcode() == PPC::BDZ8 ||
|
|
|
|
SecondLastInst->getOpcode() == PPC::BDZ) &&
|
|
|
|
LastInst->getOpcode() == PPC::B) {
|
|
|
|
if (!SecondLastInst->getOperand(0).isMBB() ||
|
|
|
|
!LastInst->getOperand(0).isMBB())
|
|
|
|
return true;
|
2012-06-09 03:19:53 +08:00
|
|
|
if (DisableCTRLoopAnal)
|
2012-06-08 23:38:25 +08:00
|
|
|
return true;
|
2012-06-08 23:38:21 +08:00
|
|
|
TBB = SecondLastInst->getOperand(0).getMBB();
|
|
|
|
Cond.push_back(MachineOperand::CreateImm(0));
|
|
|
|
Cond.push_back(MachineOperand::CreateReg(isPPC64 ? PPC::CTR8 : PPC::CTR,
|
|
|
|
true));
|
|
|
|
FBB = LastInst->getOperand(0).getMBB();
|
|
|
|
return false;
|
2006-10-14 05:21:17 +08:00
|
|
|
}
|
2010-12-24 12:28:06 +08:00
|
|
|
|
2007-06-14 01:59:52 +08:00
|
|
|
// If the block ends with two PPC:Bs, handle it. The second one is not
|
|
|
|
// executed, so remove it.
|
2010-12-24 12:28:06 +08:00
|
|
|
if (SecondLastInst->getOpcode() == PPC::B &&
|
2007-06-14 01:59:52 +08:00
|
|
|
LastInst->getOpcode() == PPC::B) {
|
2009-05-09 07:09:25 +08:00
|
|
|
if (!SecondLastInst->getOperand(0).isMBB())
|
|
|
|
return true;
|
2007-12-31 07:10:15 +08:00
|
|
|
TBB = SecondLastInst->getOperand(0).getMBB();
|
2007-06-14 01:59:52 +08:00
|
|
|
I = LastInst;
|
2009-02-09 15:14:22 +08:00
|
|
|
if (AllowModify)
|
|
|
|
I->eraseFromParent();
|
2007-06-14 01:59:52 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2006-10-14 05:21:17 +08:00
|
|
|
// Otherwise, can't handle this.
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2007-05-18 08:05:48 +08:00
|
|
|
unsigned PPCInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
|
2006-10-14 05:21:17 +08:00
|
|
|
MachineBasicBlock::iterator I = MBB.end();
|
2007-05-18 08:05:48 +08:00
|
|
|
if (I == MBB.begin()) return 0;
|
2006-10-14 05:21:17 +08:00
|
|
|
--I;
|
2010-04-02 09:38:09 +08:00
|
|
|
while (I->isDebugValue()) {
|
|
|
|
if (I == MBB.begin())
|
|
|
|
return 0;
|
|
|
|
--I;
|
|
|
|
}
|
2012-06-08 23:38:21 +08:00
|
|
|
if (I->getOpcode() != PPC::B && I->getOpcode() != PPC::BCC &&
|
|
|
|
I->getOpcode() != PPC::BDNZ8 && I->getOpcode() != PPC::BDNZ &&
|
|
|
|
I->getOpcode() != PPC::BDZ8 && I->getOpcode() != PPC::BDZ)
|
2007-05-18 08:05:48 +08:00
|
|
|
return 0;
|
2010-12-24 12:28:06 +08:00
|
|
|
|
2006-10-14 05:21:17 +08:00
|
|
|
// Remove the branch.
|
|
|
|
I->eraseFromParent();
|
2010-12-24 12:28:06 +08:00
|
|
|
|
2006-10-14 05:21:17 +08:00
|
|
|
I = MBB.end();
|
|
|
|
|
2007-05-18 08:05:48 +08:00
|
|
|
if (I == MBB.begin()) return 1;
|
2006-10-14 05:21:17 +08:00
|
|
|
--I;
|
2012-06-08 23:38:21 +08:00
|
|
|
if (I->getOpcode() != PPC::BCC &&
|
|
|
|
I->getOpcode() != PPC::BDNZ8 && I->getOpcode() != PPC::BDNZ &&
|
|
|
|
I->getOpcode() != PPC::BDZ8 && I->getOpcode() != PPC::BDZ)
|
2007-05-18 08:05:48 +08:00
|
|
|
return 1;
|
2010-12-24 12:28:06 +08:00
|
|
|
|
2006-10-14 05:21:17 +08:00
|
|
|
// Remove the branch.
|
|
|
|
I->eraseFromParent();
|
2007-05-18 08:05:48 +08:00
|
|
|
return 2;
|
2006-10-14 05:21:17 +08:00
|
|
|
}
|
|
|
|
|
2007-05-18 08:05:48 +08:00
|
|
|
unsigned
|
|
|
|
PPCInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
|
|
|
|
MachineBasicBlock *FBB,
|
2010-06-18 06:43:56 +08:00
|
|
|
const SmallVectorImpl<MachineOperand> &Cond,
|
|
|
|
DebugLoc DL) const {
|
2006-10-18 02:06:55 +08:00
|
|
|
// Shouldn't be a fall through.
|
|
|
|
assert(TBB && "InsertBranch must not be told to insert a fallthrough");
|
2010-12-24 12:28:06 +08:00
|
|
|
assert((Cond.size() == 2 || Cond.size() == 0) &&
|
2006-10-21 13:36:13 +08:00
|
|
|
"PPC branch conditions have two components!");
|
2010-12-24 12:28:06 +08:00
|
|
|
|
2012-06-08 23:38:21 +08:00
|
|
|
bool isPPC64 = TM.getSubtargetImpl()->isPPC64();
|
|
|
|
|
2006-10-21 13:36:13 +08:00
|
|
|
// One-way branch.
|
2006-10-18 02:06:55 +08:00
|
|
|
if (FBB == 0) {
|
2006-10-21 13:36:13 +08:00
|
|
|
if (Cond.empty()) // Unconditional branch
|
2010-06-18 06:43:56 +08:00
|
|
|
BuildMI(&MBB, DL, get(PPC::B)).addMBB(TBB);
|
2012-06-08 23:38:21 +08:00
|
|
|
else if (Cond[1].getReg() == PPC::CTR || Cond[1].getReg() == PPC::CTR8)
|
|
|
|
BuildMI(&MBB, DL, get(Cond[0].getImm() ?
|
|
|
|
(isPPC64 ? PPC::BDNZ8 : PPC::BDNZ) :
|
|
|
|
(isPPC64 ? PPC::BDZ8 : PPC::BDZ))).addMBB(TBB);
|
2006-10-21 13:36:13 +08:00
|
|
|
else // Conditional branch
|
2010-06-18 06:43:56 +08:00
|
|
|
BuildMI(&MBB, DL, get(PPC::BCC))
|
2006-11-18 06:37:34 +08:00
|
|
|
.addImm(Cond[0].getImm()).addReg(Cond[1].getReg()).addMBB(TBB);
|
2007-05-18 08:05:48 +08:00
|
|
|
return 1;
|
2006-10-18 02:06:55 +08:00
|
|
|
}
|
2010-12-24 12:28:06 +08:00
|
|
|
|
2006-10-21 13:42:09 +08:00
|
|
|
// Two-way Conditional Branch.
|
2012-06-08 23:38:21 +08:00
|
|
|
if (Cond[1].getReg() == PPC::CTR || Cond[1].getReg() == PPC::CTR8)
|
|
|
|
BuildMI(&MBB, DL, get(Cond[0].getImm() ?
|
|
|
|
(isPPC64 ? PPC::BDNZ8 : PPC::BDNZ) :
|
|
|
|
(isPPC64 ? PPC::BDZ8 : PPC::BDZ))).addMBB(TBB);
|
|
|
|
else
|
|
|
|
BuildMI(&MBB, DL, get(PPC::BCC))
|
|
|
|
.addImm(Cond[0].getImm()).addReg(Cond[1].getReg()).addMBB(TBB);
|
2010-06-18 06:43:56 +08:00
|
|
|
BuildMI(&MBB, DL, get(PPC::B)).addMBB(FBB);
|
2007-05-18 08:05:48 +08:00
|
|
|
return 2;
|
2006-10-14 05:21:17 +08:00
|
|
|
}
|
|
|
|
|
2010-07-11 15:31:00 +08:00
|
|
|
void PPCInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
|
|
|
|
MachineBasicBlock::iterator I, DebugLoc DL,
|
|
|
|
unsigned DestReg, unsigned SrcReg,
|
|
|
|
bool KillSrc) const {
|
|
|
|
unsigned Opc;
|
|
|
|
if (PPC::GPRCRegClass.contains(DestReg, SrcReg))
|
|
|
|
Opc = PPC::OR;
|
|
|
|
else if (PPC::G8RCRegClass.contains(DestReg, SrcReg))
|
|
|
|
Opc = PPC::OR8;
|
|
|
|
else if (PPC::F4RCRegClass.contains(DestReg, SrcReg))
|
|
|
|
Opc = PPC::FMR;
|
|
|
|
else if (PPC::CRRCRegClass.contains(DestReg, SrcReg))
|
|
|
|
Opc = PPC::MCRF;
|
|
|
|
else if (PPC::VRRCRegClass.contains(DestReg, SrcReg))
|
|
|
|
Opc = PPC::VOR;
|
|
|
|
else if (PPC::CRBITRCRegClass.contains(DestReg, SrcReg))
|
|
|
|
Opc = PPC::CROR;
|
|
|
|
else
|
|
|
|
llvm_unreachable("Impossible reg-to-reg copy");
|
2007-12-31 14:32:00 +08:00
|
|
|
|
2011-06-29 03:10:37 +08:00
|
|
|
const MCInstrDesc &MCID = get(Opc);
|
|
|
|
if (MCID.getNumOperands() == 3)
|
|
|
|
BuildMI(MBB, I, DL, MCID, DestReg)
|
2010-07-11 15:31:00 +08:00
|
|
|
.addReg(SrcReg).addReg(SrcReg, getKillRegState(KillSrc));
|
|
|
|
else
|
2011-06-29 03:10:37 +08:00
|
|
|
BuildMI(MBB, I, DL, MCID, DestReg).addReg(SrcReg, getKillRegState(KillSrc));
|
2007-12-31 14:32:00 +08:00
|
|
|
}
|
|
|
|
|
2011-12-06 01:55:17 +08:00
|
|
|
// This function returns true if a CR spill is necessary and false otherwise.
|
2008-03-11 06:49:16 +08:00
|
|
|
bool
|
2008-07-08 07:14:23 +08:00
|
|
|
PPCInstrInfo::StoreRegToStackSlot(MachineFunction &MF,
|
|
|
|
unsigned SrcReg, bool isKill,
|
2008-03-11 06:49:16 +08:00
|
|
|
int FrameIdx,
|
|
|
|
const TargetRegisterClass *RC,
|
|
|
|
SmallVectorImpl<MachineInstr*> &NewMIs) const{
|
2010-04-03 04:16:16 +08:00
|
|
|
DebugLoc DL;
|
2012-04-20 14:31:50 +08:00
|
|
|
if (PPC::GPRCRegClass.hasSubClassEq(RC)) {
|
2008-01-02 05:11:32 +08:00
|
|
|
if (SrcReg != PPC::LR) {
|
2009-02-13 07:08:38 +08:00
|
|
|
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::STW))
|
2009-05-14 05:33:08 +08:00
|
|
|
.addReg(SrcReg,
|
|
|
|
getKillRegState(isKill)),
|
2008-03-11 06:49:16 +08:00
|
|
|
FrameIdx));
|
2008-01-02 05:11:32 +08:00
|
|
|
} else {
|
|
|
|
// FIXME: this spills LR immediately to memory in one step. To do this,
|
|
|
|
// we use R11, which we know cannot be used in the prolog/epilog. This is
|
|
|
|
// a hack.
|
2009-02-13 07:08:38 +08:00
|
|
|
NewMIs.push_back(BuildMI(MF, DL, get(PPC::MFLR), PPC::R11));
|
|
|
|
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::STW))
|
2009-05-14 05:33:08 +08:00
|
|
|
.addReg(PPC::R11,
|
|
|
|
getKillRegState(isKill)),
|
2008-03-11 06:49:16 +08:00
|
|
|
FrameIdx));
|
2008-01-02 05:11:32 +08:00
|
|
|
}
|
2012-04-20 14:31:50 +08:00
|
|
|
} else if (PPC::G8RCRegClass.hasSubClassEq(RC)) {
|
2008-01-02 05:11:32 +08:00
|
|
|
if (SrcReg != PPC::LR8) {
|
2009-02-13 07:08:38 +08:00
|
|
|
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::STD))
|
2009-05-14 05:33:08 +08:00
|
|
|
.addReg(SrcReg,
|
|
|
|
getKillRegState(isKill)),
|
|
|
|
FrameIdx));
|
2008-01-02 05:11:32 +08:00
|
|
|
} else {
|
|
|
|
// FIXME: this spills LR immediately to memory in one step. To do this,
|
2011-12-07 14:32:37 +08:00
|
|
|
// we use X11, which we know cannot be used in the prolog/epilog. This is
|
2008-01-02 05:11:32 +08:00
|
|
|
// a hack.
|
2009-02-13 07:08:38 +08:00
|
|
|
NewMIs.push_back(BuildMI(MF, DL, get(PPC::MFLR8), PPC::X11));
|
|
|
|
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::STD))
|
2009-05-14 05:33:08 +08:00
|
|
|
.addReg(PPC::X11,
|
|
|
|
getKillRegState(isKill)),
|
|
|
|
FrameIdx));
|
2008-01-02 05:11:32 +08:00
|
|
|
}
|
2012-04-20 14:31:50 +08:00
|
|
|
} else if (PPC::F8RCRegClass.hasSubClassEq(RC)) {
|
2009-02-13 07:08:38 +08:00
|
|
|
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::STFD))
|
2009-05-14 05:33:08 +08:00
|
|
|
.addReg(SrcReg,
|
|
|
|
getKillRegState(isKill)),
|
|
|
|
FrameIdx));
|
2012-04-20 14:31:50 +08:00
|
|
|
} else if (PPC::F4RCRegClass.hasSubClassEq(RC)) {
|
2009-02-13 07:08:38 +08:00
|
|
|
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::STFS))
|
2009-05-14 05:33:08 +08:00
|
|
|
.addReg(SrcReg,
|
|
|
|
getKillRegState(isKill)),
|
|
|
|
FrameIdx));
|
2012-04-20 14:31:50 +08:00
|
|
|
} else if (PPC::CRRCRegClass.hasSubClassEq(RC)) {
|
2013-03-12 22:12:16 +08:00
|
|
|
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::SPILL_CR))
|
|
|
|
.addReg(SrcReg,
|
|
|
|
getKillRegState(isKill)),
|
|
|
|
FrameIdx));
|
|
|
|
return true;
|
2012-04-20 14:31:50 +08:00
|
|
|
} else if (PPC::CRBITRCRegClass.hasSubClassEq(RC)) {
|
2008-03-10 22:12:10 +08:00
|
|
|
// FIXME: We use CRi here because there is no mtcrf on a bit. Since the
|
|
|
|
// backend currently only uses CR1EQ as an individual bit, this should
|
|
|
|
// not cause any bug. If we need other uses of CR bits, the following
|
|
|
|
// code may be invalid.
|
2008-03-11 01:46:45 +08:00
|
|
|
unsigned Reg = 0;
|
2009-07-03 14:47:55 +08:00
|
|
|
if (SrcReg == PPC::CR0LT || SrcReg == PPC::CR0GT ||
|
|
|
|
SrcReg == PPC::CR0EQ || SrcReg == PPC::CR0UN)
|
2008-03-11 01:46:45 +08:00
|
|
|
Reg = PPC::CR0;
|
2009-07-03 14:47:55 +08:00
|
|
|
else if (SrcReg == PPC::CR1LT || SrcReg == PPC::CR1GT ||
|
|
|
|
SrcReg == PPC::CR1EQ || SrcReg == PPC::CR1UN)
|
2008-03-11 01:46:45 +08:00
|
|
|
Reg = PPC::CR1;
|
2009-07-03 14:47:55 +08:00
|
|
|
else if (SrcReg == PPC::CR2LT || SrcReg == PPC::CR2GT ||
|
|
|
|
SrcReg == PPC::CR2EQ || SrcReg == PPC::CR2UN)
|
2008-03-11 01:46:45 +08:00
|
|
|
Reg = PPC::CR2;
|
2009-07-03 14:47:55 +08:00
|
|
|
else if (SrcReg == PPC::CR3LT || SrcReg == PPC::CR3GT ||
|
|
|
|
SrcReg == PPC::CR3EQ || SrcReg == PPC::CR3UN)
|
2008-03-11 01:46:45 +08:00
|
|
|
Reg = PPC::CR3;
|
2009-07-03 14:47:55 +08:00
|
|
|
else if (SrcReg == PPC::CR4LT || SrcReg == PPC::CR4GT ||
|
|
|
|
SrcReg == PPC::CR4EQ || SrcReg == PPC::CR4UN)
|
2008-03-11 01:46:45 +08:00
|
|
|
Reg = PPC::CR4;
|
2009-07-03 14:47:55 +08:00
|
|
|
else if (SrcReg == PPC::CR5LT || SrcReg == PPC::CR5GT ||
|
|
|
|
SrcReg == PPC::CR5EQ || SrcReg == PPC::CR5UN)
|
2008-03-11 01:46:45 +08:00
|
|
|
Reg = PPC::CR5;
|
2009-07-03 14:47:55 +08:00
|
|
|
else if (SrcReg == PPC::CR6LT || SrcReg == PPC::CR6GT ||
|
|
|
|
SrcReg == PPC::CR6EQ || SrcReg == PPC::CR6UN)
|
2008-03-11 01:46:45 +08:00
|
|
|
Reg = PPC::CR6;
|
2009-07-03 14:47:55 +08:00
|
|
|
else if (SrcReg == PPC::CR7LT || SrcReg == PPC::CR7GT ||
|
|
|
|
SrcReg == PPC::CR7EQ || SrcReg == PPC::CR7UN)
|
2008-03-11 01:46:45 +08:00
|
|
|
Reg = PPC::CR7;
|
|
|
|
|
2010-12-24 12:28:06 +08:00
|
|
|
return StoreRegToStackSlot(MF, Reg, isKill, FrameIdx,
|
2012-04-20 14:31:50 +08:00
|
|
|
&PPC::CRRCRegClass, NewMIs);
|
2008-03-11 01:46:45 +08:00
|
|
|
|
2012-04-20 14:31:50 +08:00
|
|
|
} else if (PPC::VRRCRegClass.hasSubClassEq(RC)) {
|
2008-01-02 05:11:32 +08:00
|
|
|
// We don't have indexed addressing for vector loads. Emit:
|
|
|
|
// R0 = ADDI FI#
|
|
|
|
// STVX VAL, 0, R0
|
2010-12-24 12:28:06 +08:00
|
|
|
//
|
2008-01-02 05:11:32 +08:00
|
|
|
// FIXME: We use R0 here, because it isn't available for RA.
|
2012-10-11 05:25:01 +08:00
|
|
|
bool Is64Bit = TM.getSubtargetImpl()->isPPC64();
|
|
|
|
unsigned Instr = Is64Bit ? PPC::ADDI8 : PPC::ADDI;
|
|
|
|
unsigned GPR0 = Is64Bit ? PPC::X0 : PPC::R0;
|
|
|
|
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(Instr), GPR0),
|
2008-01-02 05:11:32 +08:00
|
|
|
FrameIdx, 0, 0));
|
2009-02-13 07:08:38 +08:00
|
|
|
NewMIs.push_back(BuildMI(MF, DL, get(PPC::STVX))
|
2009-05-14 05:33:08 +08:00
|
|
|
.addReg(SrcReg, getKillRegState(isKill))
|
2012-10-11 05:25:01 +08:00
|
|
|
.addReg(GPR0)
|
|
|
|
.addReg(GPR0));
|
2008-01-02 05:11:32 +08:00
|
|
|
} else {
|
2009-07-15 00:55:14 +08:00
|
|
|
llvm_unreachable("Unknown regclass!");
|
2008-01-02 05:11:32 +08:00
|
|
|
}
|
2008-03-04 06:19:16 +08:00
|
|
|
|
|
|
|
return false;
|
2008-01-02 05:11:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
PPCInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
|
2008-03-04 06:19:16 +08:00
|
|
|
MachineBasicBlock::iterator MI,
|
|
|
|
unsigned SrcReg, bool isKill, int FrameIdx,
|
2010-05-07 03:06:44 +08:00
|
|
|
const TargetRegisterClass *RC,
|
|
|
|
const TargetRegisterInfo *TRI) const {
|
2008-07-08 07:14:23 +08:00
|
|
|
MachineFunction &MF = *MBB.getParent();
|
2008-01-02 05:11:32 +08:00
|
|
|
SmallVector<MachineInstr*, 4> NewMIs;
|
2008-03-04 06:19:16 +08:00
|
|
|
|
2008-07-08 07:14:23 +08:00
|
|
|
if (StoreRegToStackSlot(MF, SrcReg, isKill, FrameIdx, RC, NewMIs)) {
|
|
|
|
PPCFunctionInfo *FuncInfo = MF.getInfo<PPCFunctionInfo>();
|
2008-03-04 06:19:16 +08:00
|
|
|
FuncInfo->setSpillsCR();
|
|
|
|
}
|
|
|
|
|
2008-01-02 05:11:32 +08:00
|
|
|
for (unsigned i = 0, e = NewMIs.size(); i != e; ++i)
|
|
|
|
MBB.insert(MI, NewMIs[i]);
|
2010-07-17 02:22:00 +08:00
|
|
|
|
|
|
|
const MachineFrameInfo &MFI = *MF.getFrameInfo();
|
|
|
|
MachineMemOperand *MMO =
|
2011-11-15 15:34:52 +08:00
|
|
|
MF.getMachineMemOperand(MachinePointerInfo::getFixedStack(FrameIdx),
|
2010-09-21 12:39:43 +08:00
|
|
|
MachineMemOperand::MOStore,
|
2010-07-17 02:22:00 +08:00
|
|
|
MFI.getObjectSize(FrameIdx),
|
|
|
|
MFI.getObjectAlignment(FrameIdx));
|
|
|
|
NewMIs.back()->addMemOperand(MF, MMO);
|
2008-01-02 05:11:32 +08:00
|
|
|
}
|
|
|
|
|
2011-12-07 04:55:36 +08:00
|
|
|
bool
|
2009-02-12 08:02:55 +08:00
|
|
|
PPCInstrInfo::LoadRegFromStackSlot(MachineFunction &MF, DebugLoc DL,
|
2008-07-08 07:14:23 +08:00
|
|
|
unsigned DestReg, int FrameIdx,
|
2008-03-11 06:49:16 +08:00
|
|
|
const TargetRegisterClass *RC,
|
|
|
|
SmallVectorImpl<MachineInstr*> &NewMIs)const{
|
2012-04-20 14:31:50 +08:00
|
|
|
if (PPC::GPRCRegClass.hasSubClassEq(RC)) {
|
2008-01-02 05:11:32 +08:00
|
|
|
if (DestReg != PPC::LR) {
|
2009-02-12 08:02:55 +08:00
|
|
|
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::LWZ),
|
|
|
|
DestReg), FrameIdx));
|
2008-01-02 05:11:32 +08:00
|
|
|
} else {
|
2009-02-12 08:02:55 +08:00
|
|
|
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::LWZ),
|
|
|
|
PPC::R11), FrameIdx));
|
|
|
|
NewMIs.push_back(BuildMI(MF, DL, get(PPC::MTLR)).addReg(PPC::R11));
|
2008-01-02 05:11:32 +08:00
|
|
|
}
|
2012-04-20 14:31:50 +08:00
|
|
|
} else if (PPC::G8RCRegClass.hasSubClassEq(RC)) {
|
2008-01-02 05:11:32 +08:00
|
|
|
if (DestReg != PPC::LR8) {
|
2009-02-12 08:02:55 +08:00
|
|
|
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::LD), DestReg),
|
2008-01-02 05:11:32 +08:00
|
|
|
FrameIdx));
|
|
|
|
} else {
|
2009-02-12 08:02:55 +08:00
|
|
|
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::LD),
|
2011-12-07 14:32:37 +08:00
|
|
|
PPC::X11), FrameIdx));
|
|
|
|
NewMIs.push_back(BuildMI(MF, DL, get(PPC::MTLR8)).addReg(PPC::X11));
|
2008-01-02 05:11:32 +08:00
|
|
|
}
|
2012-04-20 14:31:50 +08:00
|
|
|
} else if (PPC::F8RCRegClass.hasSubClassEq(RC)) {
|
2009-02-12 08:02:55 +08:00
|
|
|
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::LFD), DestReg),
|
2008-01-02 05:11:32 +08:00
|
|
|
FrameIdx));
|
2012-04-20 14:31:50 +08:00
|
|
|
} else if (PPC::F4RCRegClass.hasSubClassEq(RC)) {
|
2009-02-12 08:02:55 +08:00
|
|
|
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::LFS), DestReg),
|
2008-01-02 05:11:32 +08:00
|
|
|
FrameIdx));
|
2012-04-20 14:31:50 +08:00
|
|
|
} else if (PPC::CRRCRegClass.hasSubClassEq(RC)) {
|
2013-03-12 22:12:16 +08:00
|
|
|
NewMIs.push_back(addFrameReference(BuildMI(MF, DL,
|
|
|
|
get(PPC::RESTORE_CR), DestReg),
|
|
|
|
FrameIdx));
|
|
|
|
return true;
|
2012-04-20 14:31:50 +08:00
|
|
|
} else if (PPC::CRBITRCRegClass.hasSubClassEq(RC)) {
|
2010-12-24 12:28:06 +08:00
|
|
|
|
2008-03-11 01:46:45 +08:00
|
|
|
unsigned Reg = 0;
|
2009-07-03 14:47:55 +08:00
|
|
|
if (DestReg == PPC::CR0LT || DestReg == PPC::CR0GT ||
|
|
|
|
DestReg == PPC::CR0EQ || DestReg == PPC::CR0UN)
|
2008-03-11 01:46:45 +08:00
|
|
|
Reg = PPC::CR0;
|
2009-07-03 14:47:55 +08:00
|
|
|
else if (DestReg == PPC::CR1LT || DestReg == PPC::CR1GT ||
|
|
|
|
DestReg == PPC::CR1EQ || DestReg == PPC::CR1UN)
|
2008-03-11 01:46:45 +08:00
|
|
|
Reg = PPC::CR1;
|
2009-07-03 14:47:55 +08:00
|
|
|
else if (DestReg == PPC::CR2LT || DestReg == PPC::CR2GT ||
|
|
|
|
DestReg == PPC::CR2EQ || DestReg == PPC::CR2UN)
|
2008-03-11 01:46:45 +08:00
|
|
|
Reg = PPC::CR2;
|
2009-07-03 14:47:55 +08:00
|
|
|
else if (DestReg == PPC::CR3LT || DestReg == PPC::CR3GT ||
|
|
|
|
DestReg == PPC::CR3EQ || DestReg == PPC::CR3UN)
|
2008-03-11 01:46:45 +08:00
|
|
|
Reg = PPC::CR3;
|
2009-07-03 14:47:55 +08:00
|
|
|
else if (DestReg == PPC::CR4LT || DestReg == PPC::CR4GT ||
|
|
|
|
DestReg == PPC::CR4EQ || DestReg == PPC::CR4UN)
|
2008-03-11 01:46:45 +08:00
|
|
|
Reg = PPC::CR4;
|
2009-07-03 14:47:55 +08:00
|
|
|
else if (DestReg == PPC::CR5LT || DestReg == PPC::CR5GT ||
|
|
|
|
DestReg == PPC::CR5EQ || DestReg == PPC::CR5UN)
|
2008-03-11 01:46:45 +08:00
|
|
|
Reg = PPC::CR5;
|
2009-07-03 14:47:55 +08:00
|
|
|
else if (DestReg == PPC::CR6LT || DestReg == PPC::CR6GT ||
|
|
|
|
DestReg == PPC::CR6EQ || DestReg == PPC::CR6UN)
|
2008-03-11 01:46:45 +08:00
|
|
|
Reg = PPC::CR6;
|
2009-07-03 14:47:55 +08:00
|
|
|
else if (DestReg == PPC::CR7LT || DestReg == PPC::CR7GT ||
|
|
|
|
DestReg == PPC::CR7EQ || DestReg == PPC::CR7UN)
|
2008-03-11 01:46:45 +08:00
|
|
|
Reg = PPC::CR7;
|
|
|
|
|
2010-12-24 12:28:06 +08:00
|
|
|
return LoadRegFromStackSlot(MF, DL, Reg, FrameIdx,
|
2012-04-20 14:31:50 +08:00
|
|
|
&PPC::CRRCRegClass, NewMIs);
|
2008-03-11 01:46:45 +08:00
|
|
|
|
2012-04-20 14:31:50 +08:00
|
|
|
} else if (PPC::VRRCRegClass.hasSubClassEq(RC)) {
|
2008-01-02 05:11:32 +08:00
|
|
|
// We don't have indexed addressing for vector loads. Emit:
|
|
|
|
// R0 = ADDI FI#
|
|
|
|
// Dest = LVX 0, R0
|
2010-12-24 12:28:06 +08:00
|
|
|
//
|
2008-01-02 05:11:32 +08:00
|
|
|
// FIXME: We use R0 here, because it isn't available for RA.
|
2012-10-11 05:25:01 +08:00
|
|
|
bool Is64Bit = TM.getSubtargetImpl()->isPPC64();
|
|
|
|
unsigned Instr = Is64Bit ? PPC::ADDI8 : PPC::ADDI;
|
|
|
|
unsigned GPR0 = Is64Bit ? PPC::X0 : PPC::R0;
|
|
|
|
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(Instr), GPR0),
|
2008-01-02 05:11:32 +08:00
|
|
|
FrameIdx, 0, 0));
|
2012-10-11 05:25:01 +08:00
|
|
|
NewMIs.push_back(BuildMI(MF, DL, get(PPC::LVX),DestReg).addReg(GPR0)
|
|
|
|
.addReg(GPR0));
|
2008-01-02 05:11:32 +08:00
|
|
|
} else {
|
2009-07-15 00:55:14 +08:00
|
|
|
llvm_unreachable("Unknown regclass!");
|
2008-01-02 05:11:32 +08:00
|
|
|
}
|
2011-12-07 04:55:36 +08:00
|
|
|
|
|
|
|
return false;
|
2008-01-02 05:11:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
PPCInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
|
2008-03-04 06:19:16 +08:00
|
|
|
MachineBasicBlock::iterator MI,
|
|
|
|
unsigned DestReg, int FrameIdx,
|
2010-05-07 03:06:44 +08:00
|
|
|
const TargetRegisterClass *RC,
|
|
|
|
const TargetRegisterInfo *TRI) const {
|
2008-07-08 07:14:23 +08:00
|
|
|
MachineFunction &MF = *MBB.getParent();
|
2008-01-02 05:11:32 +08:00
|
|
|
SmallVector<MachineInstr*, 4> NewMIs;
|
2010-04-03 04:16:16 +08:00
|
|
|
DebugLoc DL;
|
2009-02-12 08:02:55 +08:00
|
|
|
if (MI != MBB.end()) DL = MI->getDebugLoc();
|
2011-12-07 04:55:36 +08:00
|
|
|
if (LoadRegFromStackSlot(MF, DL, DestReg, FrameIdx, RC, NewMIs)) {
|
|
|
|
PPCFunctionInfo *FuncInfo = MF.getInfo<PPCFunctionInfo>();
|
|
|
|
FuncInfo->setSpillsCR();
|
|
|
|
}
|
2008-01-02 05:11:32 +08:00
|
|
|
for (unsigned i = 0, e = NewMIs.size(); i != e; ++i)
|
|
|
|
MBB.insert(MI, NewMIs[i]);
|
2010-07-17 02:22:00 +08:00
|
|
|
|
|
|
|
const MachineFrameInfo &MFI = *MF.getFrameInfo();
|
|
|
|
MachineMemOperand *MMO =
|
2011-11-15 15:34:52 +08:00
|
|
|
MF.getMachineMemOperand(MachinePointerInfo::getFixedStack(FrameIdx),
|
2010-09-21 12:39:43 +08:00
|
|
|
MachineMemOperand::MOLoad,
|
2010-07-17 02:22:00 +08:00
|
|
|
MFI.getObjectSize(FrameIdx),
|
|
|
|
MFI.getObjectAlignment(FrameIdx));
|
|
|
|
NewMIs.back()->addMemOperand(MF, MMO);
|
2008-01-02 05:11:32 +08:00
|
|
|
}
|
|
|
|
|
2010-04-26 15:39:36 +08:00
|
|
|
MachineInstr*
|
|
|
|
PPCInstrInfo::emitFrameIndexDebugValue(MachineFunction &MF,
|
2010-04-29 09:13:30 +08:00
|
|
|
int FrameIx, uint64_t Offset,
|
2010-04-26 15:39:36 +08:00
|
|
|
const MDNode *MDPtr,
|
|
|
|
DebugLoc DL) const {
|
|
|
|
MachineInstrBuilder MIB = BuildMI(MF, DL, get(PPC::DBG_VALUE));
|
|
|
|
addFrameReference(MIB, FrameIx, 0, false).addImm(Offset).addMetadata(MDPtr);
|
|
|
|
return &*MIB;
|
|
|
|
}
|
|
|
|
|
2006-10-14 05:21:17 +08:00
|
|
|
bool PPCInstrInfo::
|
2008-08-15 06:49:33 +08:00
|
|
|
ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
|
2006-10-21 14:03:11 +08:00
|
|
|
assert(Cond.size() == 2 && "Invalid PPC branch opcode!");
|
2012-06-08 23:38:21 +08:00
|
|
|
if (Cond[1].getReg() == PPC::CTR8 || Cond[1].getReg() == PPC::CTR)
|
|
|
|
Cond[0].setImm(Cond[0].getImm() == 0 ? 1 : 0);
|
|
|
|
else
|
|
|
|
// Leave the CR# the same, but invert the condition.
|
|
|
|
Cond[0].setImm(PPC::InvertPredicate((PPC::Predicate)Cond[0].getImm()));
|
2006-10-21 14:03:11 +08:00
|
|
|
return false;
|
2006-10-14 05:21:17 +08:00
|
|
|
}
|
2008-04-17 04:10:13 +08:00
|
|
|
|
|
|
|
/// GetInstSize - Return the number of bytes of code the specified
|
|
|
|
/// instruction may be. This returns the maximum number of bytes.
|
|
|
|
///
|
|
|
|
unsigned PPCInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const {
|
|
|
|
switch (MI->getOpcode()) {
|
|
|
|
case PPC::INLINEASM: { // Inline Asm: Variable size.
|
|
|
|
const MachineFunction *MF = MI->getParent()->getParent();
|
|
|
|
const char *AsmStr = MI->getOperand(0).getSymbolName();
|
2009-08-23 04:48:53 +08:00
|
|
|
return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo());
|
2008-04-17 04:10:13 +08:00
|
|
|
}
|
2010-07-17 06:20:36 +08:00
|
|
|
case PPC::PROLOG_LABEL:
|
2008-07-01 08:05:16 +08:00
|
|
|
case PPC::EH_LABEL:
|
|
|
|
case PPC::GC_LABEL:
|
2010-04-08 03:51:44 +08:00
|
|
|
case PPC::DBG_VALUE:
|
2008-04-17 04:10:13 +08:00
|
|
|
return 0;
|
2012-03-31 22:45:15 +08:00
|
|
|
case PPC::BL8_NOP_ELF:
|
|
|
|
case PPC::BLA8_NOP_ELF:
|
|
|
|
return 8;
|
2008-04-17 04:10:13 +08:00
|
|
|
default:
|
|
|
|
return 4; // PowerPC instructions are all 4 bytes
|
|
|
|
}
|
|
|
|
}
|