//
// The LLVM Compiler Infrastructure
//
-// This file was developed by Chris Lattner and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//
//===----------------------------------------------------------------------===//
+#define DEBUG_TYPE "ppc-codegen"
#include "PPC.h"
+#include "PPCPredicates.h"
#include "PPCTargetMachine.h"
#include "PPCISelLowering.h"
#include "PPCHazardRecognizers.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/CodeGen/SSARegMap.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/Target/TargetOptions.h"
-#include "llvm/ADT/Statistic.h"
#include "llvm/Constants.h"
#include "llvm/GlobalValue.h"
#include "llvm/Intrinsics.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Compiler.h"
-#include <iostream>
#include <queue>
#include <set>
using namespace llvm;
namespace {
- Statistic<> FrameOff("ppc-codegen", "Number of frame idx offsets collapsed");
-
//===--------------------------------------------------------------------===//
/// PPCDAGToDAGISel - PPC specific code to select PPC machine
/// instructions for SelectionDAG operations.
class VISIBILITY_HIDDEN PPCDAGToDAGISel : public SelectionDAGISel {
PPCTargetMachine &TM;
PPCTargetLowering PPCLowering;
+ const PPCSubtarget &PPCSubTarget;
unsigned GlobalBaseReg;
public:
PPCDAGToDAGISel(PPCTargetMachine &tm)
: SelectionDAGISel(PPCLowering), TM(tm),
- PPCLowering(*TM.getTargetLowering()) {}
+ PPCLowering(*TM.getTargetLowering()),
+ PPCSubTarget(*TM.getSubtargetImpl()) {}
virtual bool runOnFunction(Function &Fn) {
// Make sure we re-emit a set of the global base reg if necessary
// In this case, there will be virtual registers of vector type type created
// by the scheduler. Detect them now.
MachineFunction &Fn = MachineFunction::get(&F);
- SSARegMap *RegMap = Fn.getSSARegMap();
bool HasVectorVReg = false;
for (unsigned i = MRegisterInfo::FirstVirtualRegister,
- e = RegMap->getLastVirtReg()+1; i != e; ++i)
- if (RegMap->getRegClass(i) == &PPC::VRRCRegClass) {
+ e = RegInfo->getLastVirtReg()+1; i != e; ++i)
+ if (RegInfo->getRegClass(i) == &PPC::VRRCRegClass) {
HasVectorVReg = true;
break;
}
// Create two vregs - one to hold the VRSAVE register that is live-in to the
// function and one for the value after having bits or'd into it.
- unsigned InVRSAVE = RegMap->createVirtualRegister(&PPC::GPRCRegClass);
- unsigned UpdatedVRSAVE = RegMap->createVirtualRegister(&PPC::GPRCRegClass);
+ unsigned InVRSAVE = RegInfo->createVirtualRegister(&PPC::GPRCRegClass);
+ unsigned UpdatedVRSAVE = RegInfo->createVirtualRegister(&PPC::GPRCRegClass);
+ const TargetInstrInfo &TII = *TM.getInstrInfo();
MachineBasicBlock &EntryBB = *Fn.begin();
// Emit the following code into the entry block:
// InVRSAVE = MFVRSAVE
// UpdatedVRSAVE = UPDATE_VRSAVE InVRSAVE
// MTVRSAVE UpdatedVRSAVE
MachineBasicBlock::iterator IP = EntryBB.begin(); // Insert Point
- BuildMI(EntryBB, IP, PPC::MFVRSAVE, 0, InVRSAVE);
- BuildMI(EntryBB, IP, PPC::UPDATE_VRSAVE, 1, UpdatedVRSAVE).addReg(InVRSAVE);
- BuildMI(EntryBB, IP, PPC::MTVRSAVE, 1).addReg(UpdatedVRSAVE);
+ BuildMI(EntryBB, IP, TII.get(PPC::MFVRSAVE), InVRSAVE);
+ BuildMI(EntryBB, IP, TII.get(PPC::UPDATE_VRSAVE),
+ UpdatedVRSAVE).addReg(InVRSAVE);
+ BuildMI(EntryBB, IP, TII.get(PPC::MTVRSAVE)).addReg(UpdatedVRSAVE);
// Find all return blocks, outputting a restore in each epilog.
- const TargetInstrInfo &TII = *TM.getInstrInfo();
for (MachineFunction::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB) {
if (!BB->empty() && TII.isReturn(BB->back().getOpcode())) {
IP = BB->end(); --IP;
// Skip over all terminator instructions, which are part of the return
// sequence.
MachineBasicBlock::iterator I2 = IP;
- while (I2 != BB->begin() && TII.isTerminatorInstr((--I2)->getOpcode()))
+ while (I2 != BB->begin() && (--I2)->getDesc()->isTerminator())
IP = I2;
// Emit: MTVRSAVE InVRSave
- BuildMI(*BB, IP, PPC::MTVRSAVE, 1).addReg(InVRSAVE);
+ BuildMI(*BB, IP, TII.get(PPC::MTVRSAVE)).addReg(InVRSAVE);
}
}
}
///
SDNode *PPCDAGToDAGISel::getGlobalBaseReg() {
if (!GlobalBaseReg) {
+ const TargetInstrInfo &TII = *TM.getInstrInfo();
// Insert the set of GlobalBaseReg into the first MBB of the function
MachineBasicBlock &FirstMBB = BB->getParent()->front();
MachineBasicBlock::iterator MBBI = FirstMBB.begin();
- SSARegMap *RegMap = BB->getParent()->getSSARegMap();
if (PPCLowering.getPointerTy() == MVT::i32) {
- GlobalBaseReg = RegMap->createVirtualRegister(PPC::GPRCRegisterClass);
- BuildMI(FirstMBB, MBBI, PPC::MovePCtoLR, 0, PPC::LR);
- BuildMI(FirstMBB, MBBI, PPC::MFLR, 1, GlobalBaseReg);
+ GlobalBaseReg = RegInfo->createVirtualRegister(PPC::GPRCRegisterClass);
+ BuildMI(FirstMBB, MBBI, TII.get(PPC::MovePCtoLR), PPC::LR);
+ BuildMI(FirstMBB, MBBI, TII.get(PPC::MFLR), GlobalBaseReg);
} else {
- GlobalBaseReg = RegMap->createVirtualRegister(PPC::G8RCRegisterClass);
- BuildMI(FirstMBB, MBBI, PPC::MovePCtoLR8, 0, PPC::LR8);
- BuildMI(FirstMBB, MBBI, PPC::MFLR8, 1, GlobalBaseReg);
+ GlobalBaseReg = RegInfo->createVirtualRegister(PPC::G8RCRegisterClass);
+ BuildMI(FirstMBB, MBBI, TII.get(PPC::MovePCtoLR8), PPC::LR8);
+ BuildMI(FirstMBB, MBBI, TII.get(PPC::MFLR8), GlobalBaseReg);
}
}
return CurDAG->getRegister(GlobalBaseReg, PPCLowering.getPointerTy()).Val;
SDOperand Op1 = N->getOperand(1);
uint64_t LKZ, LKO, RKZ, RKO;
- TLI.ComputeMaskedBits(Op0, 0xFFFFFFFFULL, LKZ, LKO);
- TLI.ComputeMaskedBits(Op1, 0xFFFFFFFFULL, RKZ, RKO);
+ CurDAG->ComputeMaskedBits(Op0, 0xFFFFFFFFULL, LKZ, LKO);
+ CurDAG->ComputeMaskedBits(Op1, 0xFFFFFFFFULL, RKZ, RKO);
unsigned TargetMask = LKZ;
unsigned InsertMask = RKZ;
return SDOperand(CurDAG->getTargetNode(PPC::CMPLWI, MVT::i32, LHS,
getI32Imm(Imm & 0xFFFF)), 0);
// If this is a 16-bit signed immediate, fold it.
- if (isInt16(Imm))
+ if (isInt16((int)Imm))
return SDOperand(CurDAG->getTargetNode(PPC::CMPWI, MVT::i32, LHS,
getI32Imm(Imm & 0xFFFF)), 0);
return SDOperand(CurDAG->getTargetNode(Opc, MVT::i32, LHS, RHS), 0);
}
-/// getBCCForSetCC - Returns the PowerPC condition branch mnemonic corresponding
-/// to Condition.
-static unsigned getBCCForSetCC(ISD::CondCode CC) {
+static PPC::Predicate getPredicateForSetCC(ISD::CondCode CC) {
switch (CC) {
default: assert(0 && "Unknown condition!"); abort();
case ISD::SETOEQ: // FIXME: This is incorrect see PR642.
case ISD::SETUEQ:
- case ISD::SETEQ: return PPC::BEQ;
+ case ISD::SETEQ: return PPC::PRED_EQ;
case ISD::SETONE: // FIXME: This is incorrect see PR642.
case ISD::SETUNE:
- case ISD::SETNE: return PPC::BNE;
+ case ISD::SETNE: return PPC::PRED_NE;
case ISD::SETOLT: // FIXME: This is incorrect see PR642.
case ISD::SETULT:
- case ISD::SETLT: return PPC::BLT;
+ case ISD::SETLT: return PPC::PRED_LT;
case ISD::SETOLE: // FIXME: This is incorrect see PR642.
case ISD::SETULE:
- case ISD::SETLE: return PPC::BLE;
+ case ISD::SETLE: return PPC::PRED_LE;
case ISD::SETOGT: // FIXME: This is incorrect see PR642.
case ISD::SETUGT:
- case ISD::SETGT: return PPC::BGT;
+ case ISD::SETGT: return PPC::PRED_GT;
case ISD::SETOGE: // FIXME: This is incorrect see PR642.
case ISD::SETUGE:
- case ISD::SETGE: return PPC::BGE;
+ case ISD::SETGE: return PPC::PRED_GE;
- case ISD::SETO: return PPC::BNU;
- case ISD::SETUO: return PPC::BUN;
+ case ISD::SETO: return PPC::PRED_NU;
+ case ISD::SETUO: return PPC::PRED_UN;
}
- return 0;
}
/// getCRIdxForSetCC - Return the index of the condition register field
CCReg = CurDAG->getCopyToReg(CurDAG->getEntryNode(), CR7Reg, CCReg,
InFlag).getValue(1);
- if (TLI.getTargetMachine().getSubtarget<PPCSubtarget>().isGigaProcessor())
+ if (PPCSubTarget.isGigaProcessor())
IntCR = SDOperand(CurDAG->getTargetNode(PPC::MFOCRF, MVT::i32, CR7Reg,
CCReg), 0);
else
switch (N->getOpcode()) {
default: break;
+
+ case ISD::Constant: {
+ if (N->getValueType(0) == MVT::i64) {
+ // Get 64 bit value.
+ int64_t Imm = cast<ConstantSDNode>(N)->getValue();
+ // Assume no remaining bits.
+ unsigned Remainder = 0;
+ // Assume no shift required.
+ unsigned Shift = 0;
+
+ // If it can't be represented as a 32 bit value.
+ if (!isInt32(Imm)) {
+ Shift = CountTrailingZeros_64(Imm);
+ int64_t ImmSh = static_cast<uint64_t>(Imm) >> Shift;
+
+ // If the shifted value fits 32 bits.
+ if (isInt32(ImmSh)) {
+ // Go with the shifted value.
+ Imm = ImmSh;
+ } else {
+ // Still stuck with a 64 bit value.
+ Remainder = Imm;
+ Shift = 32;
+ Imm >>= 32;
+ }
+ }
+
+ // Intermediate operand.
+ SDNode *Result;
+
+ // Handle first 32 bits.
+ unsigned Lo = Imm & 0xFFFF;
+ unsigned Hi = (Imm >> 16) & 0xFFFF;
+
+ // Simple value.
+ if (isInt16(Imm)) {
+ // Just the Lo bits.
+ Result = CurDAG->getTargetNode(PPC::LI8, MVT::i64, getI32Imm(Lo));
+ } else if (Lo) {
+ // Handle the Hi bits.
+ unsigned OpC = Hi ? PPC::LIS8 : PPC::LI8;
+ Result = CurDAG->getTargetNode(OpC, MVT::i64, getI32Imm(Hi));
+ // And Lo bits.
+ Result = CurDAG->getTargetNode(PPC::ORI8, MVT::i64,
+ SDOperand(Result, 0), getI32Imm(Lo));
+ } else {
+ // Just the Hi bits.
+ Result = CurDAG->getTargetNode(PPC::LIS8, MVT::i64, getI32Imm(Hi));
+ }
+
+ // If no shift, we're done.
+ if (!Shift) return Result;
+
+ // Shift for next step if the upper 32-bits were not zero.
+ if (Imm) {
+ Result = CurDAG->getTargetNode(PPC::RLDICR, MVT::i64,
+ SDOperand(Result, 0),
+ getI32Imm(Shift), getI32Imm(63 - Shift));
+ }
+
+ // Add in the last bits as required.
+ if ((Hi = (Remainder >> 16) & 0xFFFF)) {
+ Result = CurDAG->getTargetNode(PPC::ORIS8, MVT::i64,
+ SDOperand(Result, 0), getI32Imm(Hi));
+ }
+ if ((Lo = Remainder & 0xFFFF)) {
+ Result = CurDAG->getTargetNode(PPC::ORI8, MVT::i64,
+ SDOperand(Result, 0), getI32Imm(Lo));
+ }
+
+ return Result;
+ }
+ break;
+ }
+
case ISD::SETCC:
return SelectSETCC(Op);
case PPCISD::GlobalBaseReg:
SDOperand InFlag = N->getOperand(1);
AddToISelQueue(InFlag);
// Use MFOCRF if supported.
- if (TLI.getTargetMachine().getSubtarget<PPCSubtarget>().isGigaProcessor())
+ if (PPCSubTarget.isGigaProcessor())
return CurDAG->getTargetNode(PPC::MFOCRF, MVT::i32,
N->getOperand(0), InFlag);
else
}
SDOperand CCReg = SelectCC(N->getOperand(0), N->getOperand(1), CC);
- unsigned BROpc = getBCCForSetCC(CC);
+ unsigned BROpc = getPredicateForSetCC(CC);
unsigned SelectCCOp;
if (N->getValueType(0) == MVT::i32)
getI32Imm(BROpc) };
return CurDAG->SelectNodeTo(N, SelectCCOp, N->getValueType(0), Ops, 4);
}
+ case PPCISD::COND_BRANCH: {
+ AddToISelQueue(N->getOperand(0)); // Op #0 is the Chain.
+ // Op #1 is the PPC::PRED_* number.
+ // Op #2 is the CR#
+ // Op #3 is the Dest MBB
+ AddToISelQueue(N->getOperand(4)); // Op #4 is the Flag.
+ // Prevent PPC::PRED_* from being selected into LI.
+ SDOperand Pred =
+ getI32Imm(cast<ConstantSDNode>(N->getOperand(1))->getValue());
+ SDOperand Ops[] = { Pred, N->getOperand(2), N->getOperand(3),
+ N->getOperand(0), N->getOperand(4) };
+ return CurDAG->SelectNodeTo(N, PPC::BCC, MVT::Other, Ops, 5);
+ }
case ISD::BR_CC: {
AddToISelQueue(N->getOperand(0));
ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(1))->get();
SDOperand CondCode = SelectCC(N->getOperand(2), N->getOperand(3), CC);
- SDOperand Ops[] = { CondCode, getI32Imm(getBCCForSetCC(CC)),
+ SDOperand Ops[] = { getI32Imm(getPredicateForSetCC(CC)), CondCode,
N->getOperand(4), N->getOperand(0) };
- return CurDAG->SelectNodeTo(N, PPC::COND_BRANCH, MVT::Other, Ops, 4);
+ return CurDAG->SelectNodeTo(N, PPC::BCC, MVT::Other, Ops, 4);
}
case ISD::BRIND: {
// FIXME: Should custom lower this.