mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2026-04-20 16:17:38 +00:00
Remove trailing whitespace
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@21425 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
//===-- PowerPC.h - Top-level interface for PowerPC representation -*- C++ -*-//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the entry points for global functions defined in the LLVM
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,10 @@
|
||||
//===- PPC32JITInfo.h - PowerPC/Darwin JIT interface --------*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the PowerPC implementation of the TargetJITInfo class.
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
//===-- PPC64CodeEmitter.cpp - JIT Code Emitter for PPC64 -----*- C++ -*-=//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
//
|
||||
// This file was developed by Nate Begeman and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines a pattern matching instruction selector for 64 bit PowerPC.
|
||||
@@ -45,7 +45,7 @@ namespace {
|
||||
addRegisterClass(MVT::i64, PPC64::GPRCRegisterClass);
|
||||
addRegisterClass(MVT::f32, PPC64::FPRCRegisterClass);
|
||||
addRegisterClass(MVT::f64, PPC64::FPRCRegisterClass);
|
||||
|
||||
|
||||
// PowerPC has no intrinsics for these particular operations
|
||||
setOperationAction(ISD::BRCONDTWOWAY, MVT::Other, Expand);
|
||||
setOperationAction(ISD::MEMMOVE, MVT::Other, Expand);
|
||||
@@ -62,7 +62,7 @@ namespace {
|
||||
|
||||
setShiftAmountFlavor(Extend); // shl X, 32 == 0
|
||||
addLegalFPImmediate(+0.0); // Necessary for FSEL
|
||||
addLegalFPImmediate(-0.0); //
|
||||
addLegalFPImmediate(-0.0); //
|
||||
|
||||
computeRegisterProperties();
|
||||
}
|
||||
@@ -71,16 +71,16 @@ namespace {
|
||||
/// lower the arguments for the specified function, into the specified DAG.
|
||||
virtual std::vector<SDOperand>
|
||||
LowerArguments(Function &F, SelectionDAG &DAG);
|
||||
|
||||
|
||||
/// LowerCallTo - This hook lowers an abstract call to a function into an
|
||||
/// actual call.
|
||||
virtual std::pair<SDOperand, SDOperand>
|
||||
LowerCallTo(SDOperand Chain, const Type *RetTy, bool isVarArg,
|
||||
SDOperand Callee, ArgListTy &Args, SelectionDAG &DAG);
|
||||
|
||||
|
||||
virtual std::pair<SDOperand, SDOperand>
|
||||
LowerVAStart(SDOperand Chain, SelectionDAG &DAG);
|
||||
|
||||
|
||||
virtual std::pair<SDOperand,SDOperand>
|
||||
LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList,
|
||||
const Type *ArgTy, SelectionDAG &DAG);
|
||||
@@ -101,8 +101,8 @@ PPC64TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
|
||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
MachineBasicBlock& BB = MF.front();
|
||||
std::vector<SDOperand> ArgValues;
|
||||
|
||||
// Due to the rather complicated nature of the PowerPC ABI, rather than a
|
||||
|
||||
// Due to the rather complicated nature of the PowerPC ABI, rather than a
|
||||
// fixed size array of physical args, for the sake of simplicity let the STL
|
||||
// handle tracking them for us.
|
||||
std::vector<unsigned> argVR, argPR, argOp;
|
||||
@@ -110,7 +110,7 @@ PPC64TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
|
||||
unsigned GPR_remaining = 8;
|
||||
unsigned FPR_remaining = 13;
|
||||
unsigned GPR_idx = 0, FPR_idx = 0;
|
||||
static const unsigned GPR[] = {
|
||||
static const unsigned GPR[] = {
|
||||
PPC::R3, PPC::R4, PPC::R5, PPC::R6,
|
||||
PPC::R7, PPC::R8, PPC::R9, PPC::R10,
|
||||
};
|
||||
@@ -126,13 +126,13 @@ PPC64TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
|
||||
SDOperand newroot, argt;
|
||||
bool needsLoad = false;
|
||||
MVT::ValueType ObjectVT = getValueType(I->getType());
|
||||
|
||||
|
||||
switch (ObjectVT) {
|
||||
default: assert(0 && "Unhandled argument type!");
|
||||
case MVT::i1:
|
||||
case MVT::i8:
|
||||
case MVT::i16:
|
||||
case MVT::i32:
|
||||
case MVT::i32:
|
||||
case MVT::i64:
|
||||
if (GPR_remaining > 0) {
|
||||
BuildMI(&BB, PPC::IMPLICIT_DEF, 0, GPR[GPR_idx]);
|
||||
@@ -148,7 +148,7 @@ PPC64TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
|
||||
case MVT::f64:
|
||||
if (FPR_remaining > 0) {
|
||||
BuildMI(&BB, PPC::IMPLICIT_DEF, 0, FPR[FPR_idx]);
|
||||
argt = newroot = DAG.getCopyFromReg(FPR[FPR_idx], ObjectVT,
|
||||
argt = newroot = DAG.getCopyFromReg(FPR[FPR_idx], ObjectVT,
|
||||
DAG.getRoot());
|
||||
--FPR_remaining;
|
||||
++FPR_idx;
|
||||
@@ -157,9 +157,9 @@ PPC64TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// We need to load the argument to a virtual register if we determined above
|
||||
// that we ran out of physical registers of the appropriate type
|
||||
// that we ran out of physical registers of the appropriate type
|
||||
if (needsLoad) {
|
||||
unsigned SubregOffset = 0;
|
||||
switch (ObjectVT) {
|
||||
@@ -167,18 +167,18 @@ PPC64TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
|
||||
case MVT::i1:
|
||||
case MVT::i8: SubregOffset = 7; break;
|
||||
case MVT::i16: SubregOffset = 6; break;
|
||||
case MVT::i32:
|
||||
case MVT::i32:
|
||||
case MVT::f32: SubregOffset = 4; break;
|
||||
case MVT::i64:
|
||||
case MVT::i64:
|
||||
case MVT::f64: SubregOffset = 0; break;
|
||||
}
|
||||
int FI = MFI->CreateFixedObject(8, ArgOffset);
|
||||
SDOperand FIN = DAG.getFrameIndex(FI, MVT::i64);
|
||||
FIN = DAG.getNode(ISD::ADD, MVT::i64, FIN,
|
||||
FIN = DAG.getNode(ISD::ADD, MVT::i64, FIN,
|
||||
DAG.getConstant(SubregOffset, MVT::i64));
|
||||
argt = newroot = DAG.getLoad(ObjectVT, DAG.getEntryNode(), FIN);
|
||||
}
|
||||
|
||||
|
||||
// Every 4 bytes of argument space consumes one of the GPRs available for
|
||||
// argument passing.
|
||||
if (GPR_remaining > 0) {
|
||||
@@ -186,7 +186,7 @@ PPC64TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
|
||||
++GPR_idx;
|
||||
}
|
||||
ArgOffset += 8;
|
||||
|
||||
|
||||
DAG.setRoot(newroot.getValue(1));
|
||||
ArgValues.push_back(argt);
|
||||
}
|
||||
@@ -203,7 +203,7 @@ PPC64TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
|
||||
for (; GPR_remaining > 0; --GPR_remaining, ++GPR_idx) {
|
||||
BuildMI(&BB, PPC::IMPLICIT_DEF, 0, GPR[GPR_idx]);
|
||||
SDOperand Val = DAG.getCopyFromReg(GPR[GPR_idx], MVT::i64, DAG.getRoot());
|
||||
SDOperand Store = DAG.getNode(ISD::STORE, MVT::Other, Val.getValue(1),
|
||||
SDOperand Store = DAG.getNode(ISD::STORE, MVT::Other, Val.getValue(1),
|
||||
Val, FIN);
|
||||
MemOps.push_back(Store);
|
||||
// Increment the address by eight for the next argument to store
|
||||
@@ -233,8 +233,8 @@ PPC64TargetLowering::LowerCallTo(SDOperand Chain,
|
||||
DAG.getConstant(NumBytes, getPointerTy()));
|
||||
} else {
|
||||
NumBytes = 8 * Args.size(); // All arguments are rounded up to 8 bytes
|
||||
|
||||
// Just to be safe, we'll always reserve the full 48 bytes of linkage area
|
||||
|
||||
// Just to be safe, we'll always reserve the full 48 bytes of linkage area
|
||||
// plus 64 bytes of argument space in case any called code gets funky on us.
|
||||
if (NumBytes < 112) NumBytes = 112;
|
||||
|
||||
@@ -248,7 +248,7 @@ PPC64TargetLowering::LowerCallTo(SDOperand Chain,
|
||||
// passing.
|
||||
SDOperand StackPtr = DAG.getCopyFromReg(PPC::R1, MVT::i32,
|
||||
DAG.getEntryNode());
|
||||
|
||||
|
||||
// Figure out which arguments are going to go in registers, and which in
|
||||
// memory. Also, if this is a vararg function, floating point operations
|
||||
// must be stored to our stack, and loaded into integer regs as well, if
|
||||
@@ -256,7 +256,7 @@ PPC64TargetLowering::LowerCallTo(SDOperand Chain,
|
||||
unsigned ArgOffset = 48;
|
||||
unsigned GPR_remaining = 8;
|
||||
unsigned FPR_remaining = 13;
|
||||
|
||||
|
||||
std::vector<SDOperand> MemOps;
|
||||
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
|
||||
// PtrOff will be used to store the current argument to the stack if a
|
||||
@@ -264,7 +264,7 @@ PPC64TargetLowering::LowerCallTo(SDOperand Chain,
|
||||
SDOperand PtrOff = DAG.getConstant(ArgOffset, getPointerTy());
|
||||
PtrOff = DAG.getNode(ISD::ADD, MVT::i32, StackPtr, PtrOff);
|
||||
MVT::ValueType ArgVT = getValueType(Args[i].second);
|
||||
|
||||
|
||||
switch (ArgVT) {
|
||||
default: assert(0 && "Unexpected ValueType for argument!");
|
||||
case MVT::i1:
|
||||
@@ -323,14 +323,14 @@ PPC64TargetLowering::LowerCallTo(SDOperand Chain,
|
||||
if (!MemOps.empty())
|
||||
Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, MemOps);
|
||||
}
|
||||
|
||||
|
||||
std::vector<MVT::ValueType> RetVals;
|
||||
MVT::ValueType RetTyVT = getValueType(RetTy);
|
||||
if (RetTyVT != MVT::isVoid)
|
||||
RetVals.push_back(RetTyVT);
|
||||
RetVals.push_back(MVT::Other);
|
||||
|
||||
SDOperand TheCall = SDOperand(DAG.getCall(RetVals,
|
||||
SDOperand TheCall = SDOperand(DAG.getCall(RetVals,
|
||||
Chain, Callee, args_to_use), 0);
|
||||
Chain = TheCall.getValue(RetTyVT != MVT::isVoid);
|
||||
Chain = DAG.getNode(ISD::ADJCALLSTACKUP, MVT::Other, Chain,
|
||||
@@ -357,7 +357,7 @@ LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList,
|
||||
}
|
||||
return std::make_pair(Result, Chain);
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::pair<SDOperand, SDOperand> PPC64TargetLowering::
|
||||
LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth,
|
||||
@@ -374,10 +374,10 @@ Statistic<>FusedFP("ppc-codegen", "Number of fused fp operations");
|
||||
/// SelectionDAG operations.
|
||||
//===--------------------------------------------------------------------===//
|
||||
class ISel : public SelectionDAGISel {
|
||||
|
||||
|
||||
/// Comment Here.
|
||||
PPC64TargetLowering PPC64Lowering;
|
||||
|
||||
|
||||
/// ExprMap - As shared expressions are codegen'd, we keep track of which
|
||||
/// vreg the value is produced in, so we only emit one copy of each compiled
|
||||
/// tree.
|
||||
@@ -385,37 +385,37 @@ class ISel : public SelectionDAGISel {
|
||||
|
||||
unsigned GlobalBaseReg;
|
||||
bool GlobalBaseInitialized;
|
||||
|
||||
|
||||
public:
|
||||
ISel(TargetMachine &TM) : SelectionDAGISel(PPC64Lowering), PPC64Lowering(TM)
|
||||
ISel(TargetMachine &TM) : SelectionDAGISel(PPC64Lowering), PPC64Lowering(TM)
|
||||
{}
|
||||
|
||||
|
||||
/// runOnFunction - Override this function in order to reset our per-function
|
||||
/// variables.
|
||||
virtual bool runOnFunction(Function &Fn) {
|
||||
// Make sure we re-emit a set of the global base reg if necessary
|
||||
GlobalBaseInitialized = false;
|
||||
return SelectionDAGISel::runOnFunction(Fn);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// InstructionSelectBasicBlock - This callback is invoked by
|
||||
/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
|
||||
virtual void InstructionSelectBasicBlock(SelectionDAG &DAG) {
|
||||
DEBUG(BB->dump());
|
||||
// Codegen the basic block.
|
||||
Select(DAG.getRoot());
|
||||
|
||||
|
||||
// Clear state used for selection.
|
||||
ExprMap.clear();
|
||||
}
|
||||
|
||||
|
||||
unsigned getGlobalBaseReg();
|
||||
unsigned getConstDouble(double floatVal, unsigned Result);
|
||||
unsigned SelectSetCR0(SDOperand CC);
|
||||
unsigned SelectExpr(SDOperand N);
|
||||
unsigned SelectExprFP(SDOperand N, unsigned Result);
|
||||
void Select(SDOperand N);
|
||||
|
||||
|
||||
bool SelectAddr(SDOperand N, unsigned& Reg, int& offset);
|
||||
void SelectBranchCC(SDOperand N);
|
||||
};
|
||||
@@ -435,7 +435,7 @@ static unsigned ExactLog2(unsigned Val) {
|
||||
/// getImmediateForOpcode - This method returns a value indicating whether
|
||||
/// the ConstantSDNode N can be used as an immediate to Opcode. The return
|
||||
/// values are either 0, 1 or 2. 0 indicates that either N is not a
|
||||
/// ConstantSDNode, or is not suitable for use by that opcode. A return value
|
||||
/// ConstantSDNode, or is not suitable for use by that opcode. A return value
|
||||
/// of 1 indicates that the constant may be used in normal immediate form. A
|
||||
/// return value of 2 indicates that the constant may be used in shifted
|
||||
/// immediate form. A return value of 3 indicates that log base 2 of the
|
||||
@@ -446,7 +446,7 @@ static unsigned getImmediateForOpcode(SDOperand N, unsigned Opcode,
|
||||
if (N.getOpcode() != ISD::Constant) return 0;
|
||||
|
||||
int v = (int)cast<ConstantSDNode>(N)->getSignExtended();
|
||||
|
||||
|
||||
switch(Opcode) {
|
||||
default: return 0;
|
||||
case ISD::ADD:
|
||||
@@ -528,7 +528,7 @@ unsigned ISel::getGlobalBaseReg() {
|
||||
return GlobalBaseReg;
|
||||
}
|
||||
|
||||
/// getConstDouble - Loads a floating point value into a register, via the
|
||||
/// getConstDouble - Loads a floating point value into a register, via the
|
||||
/// Constant Pool. Optionally takes a register in which to load the value.
|
||||
unsigned ISel::getConstDouble(double doubleVal, unsigned Result=0) {
|
||||
unsigned Tmp1 = MakeReg(MVT::i64);
|
||||
@@ -544,9 +544,9 @@ unsigned ISel::getConstDouble(double doubleVal, unsigned Result=0) {
|
||||
|
||||
unsigned ISel::SelectSetCR0(SDOperand CC) {
|
||||
unsigned Opc, Tmp1, Tmp2;
|
||||
static const unsigned CompareOpcodes[] =
|
||||
static const unsigned CompareOpcodes[] =
|
||||
{ PPC::FCMPU, PPC::FCMPU, PPC::CMPW, PPC::CMPLW };
|
||||
|
||||
|
||||
// If the first operand to the select is a SETCC node, then we can fold it
|
||||
// into the branch that selects which value to return.
|
||||
SetCCSDNode* SetCC = dyn_cast<SetCCSDNode>(CC.Val);
|
||||
@@ -557,7 +557,7 @@ unsigned ISel::SelectSetCR0(SDOperand CC) {
|
||||
|
||||
// Pass the optional argument U to getImmediateForOpcode for SETCC,
|
||||
// so that it knows whether the SETCC immediate range is signed or not.
|
||||
if (1 == getImmediateForOpcode(SetCC->getOperand(1), ISD::SETCC,
|
||||
if (1 == getImmediateForOpcode(SetCC->getOperand(1), ISD::SETCC,
|
||||
Tmp2, U)) {
|
||||
if (U)
|
||||
BuildMI(BB, PPC::CMPLWI, 2, PPC::CR0).addReg(Tmp1).addImm(Tmp2);
|
||||
@@ -586,7 +586,7 @@ bool ISel::SelectAddr(SDOperand N, unsigned& Reg, int& offset)
|
||||
if (1 == getImmediateForOpcode(N.getOperand(1), opcode, imm)) {
|
||||
offset = imm;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
offset = SelectExpr(N.getOperand(1));
|
||||
return true;
|
||||
}
|
||||
@@ -598,14 +598,14 @@ bool ISel::SelectAddr(SDOperand N, unsigned& Reg, int& offset)
|
||||
void ISel::SelectBranchCC(SDOperand N)
|
||||
{
|
||||
assert(N.getOpcode() == ISD::BRCOND && "Not a BranchCC???");
|
||||
MachineBasicBlock *Dest =
|
||||
MachineBasicBlock *Dest =
|
||||
cast<BasicBlockSDNode>(N.getOperand(2))->getBasicBlock();
|
||||
|
||||
// Get the MBB we will fall through to so that we can hand it off to the
|
||||
// branch selection pass as an argument to the PPC::COND_BRANCH pseudo op.
|
||||
//ilist<MachineBasicBlock>::iterator It = BB;
|
||||
//MachineBasicBlock *Fallthrough = ++It;
|
||||
|
||||
|
||||
Select(N.getOperand(0)); //chain
|
||||
unsigned Opc = SelectSetCR0(N.getOperand(1));
|
||||
// FIXME: Use this once we have something approximating two-way branches
|
||||
@@ -645,7 +645,7 @@ unsigned ISel::SelectExprFP(SDOperand N, unsigned Result)
|
||||
Tmp1 = SelectExpr(SetCC->getOperand(0)); // Val to compare against
|
||||
unsigned TV = SelectExpr(N.getOperand(1)); // Use if TRUE
|
||||
unsigned FV = SelectExpr(N.getOperand(2)); // Use if FALSE
|
||||
|
||||
|
||||
ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(1));
|
||||
if (CN && (CN->isExactlyValue(-0.0) || CN->isExactlyValue(0.0))) {
|
||||
switch(SetCC->getCondition()) {
|
||||
@@ -704,12 +704,12 @@ unsigned ISel::SelectExprFP(SDOperand N, unsigned Result)
|
||||
assert(0 && "Should never get here");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
unsigned TrueValue = SelectExpr(N.getOperand(1)); //Use if TRUE
|
||||
unsigned FalseValue = SelectExpr(N.getOperand(2)); //Use if FALSE
|
||||
Opc = SelectSetCR0(N.getOperand(0));
|
||||
|
||||
// Create an iterator with which to insert the MBB for copying the false
|
||||
// Create an iterator with which to insert the MBB for copying the false
|
||||
// value and the MBB to hold the PHI instruction for this SetCC.
|
||||
MachineBasicBlock *thisMBB = BB;
|
||||
const BasicBlock *LLVM_BB = BB->getBasicBlock();
|
||||
@@ -749,7 +749,7 @@ unsigned ISel::SelectExprFP(SDOperand N, unsigned Result)
|
||||
}
|
||||
|
||||
case ISD::FNEG:
|
||||
if (!NoExcessFPPrecision &&
|
||||
if (!NoExcessFPPrecision &&
|
||||
ISD::ADD == N.getOperand(0).getOpcode() &&
|
||||
N.getOperand(0).Val->hasOneUse() &&
|
||||
ISD::MUL == N.getOperand(0).getOperand(0).getOpcode() &&
|
||||
@@ -760,7 +760,7 @@ unsigned ISel::SelectExprFP(SDOperand N, unsigned Result)
|
||||
Tmp3 = SelectExpr(N.getOperand(0).getOperand(1));
|
||||
Opc = DestType == MVT::f64 ? PPC::FNMADD : PPC::FNMADDS;
|
||||
BuildMI(BB, Opc, 3, Result).addReg(Tmp1).addReg(Tmp2).addReg(Tmp3);
|
||||
} else if (!NoExcessFPPrecision &&
|
||||
} else if (!NoExcessFPPrecision &&
|
||||
ISD::SUB == N.getOperand(0).getOpcode() &&
|
||||
N.getOperand(0).Val->hasOneUse() &&
|
||||
ISD::MUL == N.getOperand(0).getOperand(0).getOpcode() &&
|
||||
@@ -779,23 +779,23 @@ unsigned ISel::SelectExprFP(SDOperand N, unsigned Result)
|
||||
BuildMI(BB, PPC::FNEG, 1, Result).addReg(Tmp1);
|
||||
}
|
||||
return Result;
|
||||
|
||||
|
||||
case ISD::FABS:
|
||||
Tmp1 = SelectExpr(N.getOperand(0));
|
||||
BuildMI(BB, PPC::FABS, 1, Result).addReg(Tmp1);
|
||||
return Result;
|
||||
|
||||
case ISD::FP_ROUND:
|
||||
assert (DestType == MVT::f32 &&
|
||||
N.getOperand(0).getValueType() == MVT::f64 &&
|
||||
assert (DestType == MVT::f32 &&
|
||||
N.getOperand(0).getValueType() == MVT::f64 &&
|
||||
"only f64 to f32 conversion supported here");
|
||||
Tmp1 = SelectExpr(N.getOperand(0));
|
||||
BuildMI(BB, PPC::FRSP, 1, Result).addReg(Tmp1);
|
||||
return Result;
|
||||
|
||||
case ISD::FP_EXTEND:
|
||||
assert (DestType == MVT::f64 &&
|
||||
N.getOperand(0).getValueType() == MVT::f32 &&
|
||||
assert (DestType == MVT::f64 &&
|
||||
N.getOperand(0).getValueType() == MVT::f32 &&
|
||||
"only f32 to f64 conversion supported here");
|
||||
Tmp1 = SelectExpr(N.getOperand(0));
|
||||
BuildMI(BB, PPC::FMR, 1, Result).addReg(Tmp1);
|
||||
@@ -807,13 +807,13 @@ unsigned ISel::SelectExprFP(SDOperand N, unsigned Result)
|
||||
Tmp1 = dyn_cast<RegSDNode>(Node)->getReg();
|
||||
BuildMI(BB, PPC::FMR, 1, Result).addReg(Tmp1);
|
||||
return Result;
|
||||
|
||||
|
||||
case ISD::ConstantFP: {
|
||||
ConstantFPSDNode *CN = cast<ConstantFPSDNode>(N);
|
||||
Result = getConstDouble(CN->getValue(), Result);
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
case ISD::ADD:
|
||||
if (!NoExcessFPPrecision && N.getOperand(0).getOpcode() == ISD::MUL &&
|
||||
N.getOperand(0).Val->hasOneUse()) {
|
||||
@@ -866,10 +866,10 @@ unsigned ISel::SelectExprFP(SDOperand N, unsigned Result)
|
||||
Tmp2 = MakeReg(MVT::f64); // temp reg to load the integer value into
|
||||
Tmp3 = MakeReg(MVT::i64); // temp reg to hold the conversion constant
|
||||
unsigned ConstF = MakeReg(MVT::f64); // temp reg to hold the fp constant
|
||||
|
||||
|
||||
int FrameIdx = BB->getParent()->getFrameInfo()->CreateStackObject(8, 8);
|
||||
MachineConstantPool *CP = BB->getParent()->getConstantPool();
|
||||
|
||||
|
||||
// FIXME: pull this FP constant generation stuff out into something like
|
||||
// the simple ISel's getReg.
|
||||
if (IsUnsigned) {
|
||||
@@ -935,7 +935,7 @@ unsigned ISel::SelectExpr(SDOperand N) {
|
||||
|
||||
if (ISD::CopyFromReg == opcode)
|
||||
DestType = N.getValue(0).getValueType();
|
||||
|
||||
|
||||
if (DestType == MVT::f64 || DestType == MVT::f32)
|
||||
if (ISD::LOAD != opcode && ISD::EXTLOAD != opcode && ISD::UNDEF != opcode)
|
||||
return SelectExprFP(N, Result);
|
||||
@@ -983,7 +983,7 @@ unsigned ISel::SelectExpr(SDOperand N) {
|
||||
Tmp1 = cast<FrameIndexSDNode>(N)->getIndex();
|
||||
addFrameReference(BuildMI(BB, PPC::ADDI, 2, Result), (int)Tmp1, 0, false);
|
||||
return Result;
|
||||
|
||||
|
||||
case ISD::GlobalAddress: {
|
||||
GlobalValue *GV = cast<GlobalAddressSDNode>(N)->getGlobal();
|
||||
Tmp1 = MakeReg(MVT::i64);
|
||||
@@ -1004,7 +1004,7 @@ unsigned ISel::SelectExpr(SDOperand N) {
|
||||
MVT::ValueType TypeBeingLoaded = (ISD::LOAD == opcode) ?
|
||||
Node->getValueType(0) : cast<MVTSDNode>(Node)->getExtraValueType();
|
||||
bool sext = (ISD::SEXTLOAD == opcode);
|
||||
|
||||
|
||||
// Make sure we generate both values.
|
||||
if (Result != 1)
|
||||
ExprMap[N.getValue(1)] = 1; // Generate the token
|
||||
@@ -1025,7 +1025,7 @@ unsigned ISel::SelectExpr(SDOperand N) {
|
||||
case MVT::f32: Opc = PPC::LFS; break;
|
||||
case MVT::f64: Opc = PPC::LFD; break;
|
||||
}
|
||||
|
||||
|
||||
if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Address)) {
|
||||
Tmp1 = MakeReg(MVT::i64);
|
||||
int CPI = CP->getIndex();
|
||||
@@ -1048,10 +1048,10 @@ unsigned ISel::SelectExpr(SDOperand N) {
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
case ISD::CALL: {
|
||||
unsigned GPR_idx = 0, FPR_idx = 0;
|
||||
static const unsigned GPR[] = {
|
||||
static const unsigned GPR[] = {
|
||||
PPC::R3, PPC::R4, PPC::R5, PPC::R6,
|
||||
PPC::R7, PPC::R8, PPC::R9, PPC::R10,
|
||||
};
|
||||
@@ -1066,13 +1066,13 @@ unsigned ISel::SelectExpr(SDOperand N) {
|
||||
|
||||
MachineInstr *CallMI;
|
||||
// Emit the correct call instruction based on the type of symbol called.
|
||||
if (GlobalAddressSDNode *GASD =
|
||||
if (GlobalAddressSDNode *GASD =
|
||||
dyn_cast<GlobalAddressSDNode>(N.getOperand(1))) {
|
||||
CallMI = BuildMI(PPC::CALLpcrel, 1).addGlobalAddress(GASD->getGlobal(),
|
||||
CallMI = BuildMI(PPC::CALLpcrel, 1).addGlobalAddress(GASD->getGlobal(),
|
||||
true);
|
||||
} else if (ExternalSymbolSDNode *ESSDN =
|
||||
} else if (ExternalSymbolSDNode *ESSDN =
|
||||
dyn_cast<ExternalSymbolSDNode>(N.getOperand(1))) {
|
||||
CallMI = BuildMI(PPC::CALLpcrel, 1).addExternalSymbol(ESSDN->getSymbol(),
|
||||
CallMI = BuildMI(PPC::CALLpcrel, 1).addExternalSymbol(ESSDN->getSymbol(),
|
||||
true);
|
||||
} else {
|
||||
Tmp1 = SelectExpr(N.getOperand(1));
|
||||
@@ -1081,7 +1081,7 @@ unsigned ISel::SelectExpr(SDOperand N) {
|
||||
CallMI = BuildMI(PPC::CALLindirect, 3).addImm(20).addImm(0)
|
||||
.addReg(PPC::R12);
|
||||
}
|
||||
|
||||
|
||||
// Load the register args to virtual regs
|
||||
std::vector<unsigned> ArgVR;
|
||||
for(int i = 2, e = Node->getNumOperands(); i < e; ++i)
|
||||
@@ -1112,7 +1112,7 @@ unsigned ISel::SelectExpr(SDOperand N) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Put the call instruction in the correct place in the MachineBasicBlock
|
||||
BB->push_back(CallMI);
|
||||
|
||||
@@ -1140,20 +1140,20 @@ unsigned ISel::SelectExpr(SDOperand N) {
|
||||
switch(cast<MVTSDNode>(Node)->getExtraValueType()) {
|
||||
default: Node->dump(); assert(0 && "Unhandled SIGN_EXTEND type"); break;
|
||||
case MVT::i32:
|
||||
BuildMI(BB, PPC::EXTSW, 1, Result).addReg(Tmp1);
|
||||
BuildMI(BB, PPC::EXTSW, 1, Result).addReg(Tmp1);
|
||||
break;
|
||||
case MVT::i16:
|
||||
BuildMI(BB, PPC::EXTSH, 1, Result).addReg(Tmp1);
|
||||
BuildMI(BB, PPC::EXTSH, 1, Result).addReg(Tmp1);
|
||||
break;
|
||||
case MVT::i8:
|
||||
BuildMI(BB, PPC::EXTSB, 1, Result).addReg(Tmp1);
|
||||
BuildMI(BB, PPC::EXTSB, 1, Result).addReg(Tmp1);
|
||||
break;
|
||||
case MVT::i1:
|
||||
BuildMI(BB, PPC::SUBFIC, 2, Result).addReg(Tmp1).addSImm(0);
|
||||
break;
|
||||
}
|
||||
return Result;
|
||||
|
||||
|
||||
case ISD::CopyFromReg:
|
||||
if (Result == 1)
|
||||
Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
|
||||
@@ -1172,7 +1172,7 @@ unsigned ISel::SelectExpr(SDOperand N) {
|
||||
BuildMI(BB, PPC::SLD, 2, Result).addReg(Tmp1).addReg(Tmp2);
|
||||
}
|
||||
return Result;
|
||||
|
||||
|
||||
case ISD::SRL:
|
||||
Tmp1 = SelectExpr(N.getOperand(0));
|
||||
if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
|
||||
@@ -1184,7 +1184,7 @@ unsigned ISel::SelectExpr(SDOperand N) {
|
||||
BuildMI(BB, PPC::SRD, 2, Result).addReg(Tmp1).addReg(Tmp2);
|
||||
}
|
||||
return Result;
|
||||
|
||||
|
||||
case ISD::SRA:
|
||||
Tmp1 = SelectExpr(N.getOperand(0));
|
||||
if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
|
||||
@@ -1195,7 +1195,7 @@ unsigned ISel::SelectExpr(SDOperand N) {
|
||||
BuildMI(BB, PPC::SRAD, 2, Result).addReg(Tmp1).addReg(Tmp2);
|
||||
}
|
||||
return Result;
|
||||
|
||||
|
||||
case ISD::ADD:
|
||||
Tmp1 = SelectExpr(N.getOperand(0));
|
||||
switch(getImmediateForOpcode(N.getOperand(1), opcode, Tmp2)) {
|
||||
@@ -1302,7 +1302,7 @@ unsigned ISel::SelectExpr(SDOperand N) {
|
||||
BuildMI(BB, PPC::SUBF, 2, Result).addReg(Tmp2).addReg(Tmp1);
|
||||
}
|
||||
return Result;
|
||||
|
||||
|
||||
case ISD::MUL:
|
||||
Tmp1 = SelectExpr(N.getOperand(0));
|
||||
if (1 == getImmediateForOpcode(N.getOperand(1), opcode, Tmp2))
|
||||
@@ -1338,23 +1338,23 @@ unsigned ISel::SelectExpr(SDOperand N) {
|
||||
addFrameReference(BuildMI(BB, PPC::LD, 2, Result), FrameIdx);
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
case ISD::SETCC:
|
||||
if (SetCCSDNode *SetCC = dyn_cast<SetCCSDNode>(Node)) {
|
||||
Opc = SelectSetCR0(N);
|
||||
|
||||
|
||||
unsigned TrueValue = MakeReg(MVT::i32);
|
||||
BuildMI(BB, PPC::LI, 1, TrueValue).addSImm(1);
|
||||
unsigned FalseValue = MakeReg(MVT::i32);
|
||||
BuildMI(BB, PPC::LI, 1, FalseValue).addSImm(0);
|
||||
|
||||
// Create an iterator with which to insert the MBB for copying the false
|
||||
// Create an iterator with which to insert the MBB for copying the false
|
||||
// value and the MBB to hold the PHI instruction for this SetCC.
|
||||
MachineBasicBlock *thisMBB = BB;
|
||||
const BasicBlock *LLVM_BB = BB->getBasicBlock();
|
||||
ilist<MachineBasicBlock>::iterator It = BB;
|
||||
++It;
|
||||
|
||||
|
||||
// thisMBB:
|
||||
// ...
|
||||
// cmpTY cr0, r1, r2
|
||||
@@ -1387,13 +1387,13 @@ unsigned ISel::SelectExpr(SDOperand N) {
|
||||
}
|
||||
assert(0 && "Is this legal?");
|
||||
return 0;
|
||||
|
||||
|
||||
case ISD::SELECT: {
|
||||
unsigned TrueValue = SelectExpr(N.getOperand(1)); //Use if TRUE
|
||||
unsigned FalseValue = SelectExpr(N.getOperand(2)); //Use if FALSE
|
||||
Opc = SelectSetCR0(N.getOperand(0));
|
||||
|
||||
// Create an iterator with which to insert the MBB for copying the false
|
||||
// Create an iterator with which to insert the MBB for copying the false
|
||||
// value and the MBB to hold the PHI instruction for this SetCC.
|
||||
MachineBasicBlock *thisMBB = BB;
|
||||
const BasicBlock *LLVM_BB = BB->getBasicBlock();
|
||||
@@ -1467,7 +1467,7 @@ void ISel::Select(SDOperand N) {
|
||||
return; // Already selected.
|
||||
|
||||
SDNode *Node = N.Val;
|
||||
|
||||
|
||||
switch (Node->getOpcode()) {
|
||||
default:
|
||||
Node->dump(); std::cerr << "\n";
|
||||
@@ -1492,16 +1492,16 @@ void ISel::Select(SDOperand N) {
|
||||
BuildMI(BB, PPC::B, 1).addMBB(Dest);
|
||||
return;
|
||||
}
|
||||
case ISD::BRCOND:
|
||||
case ISD::BRCOND:
|
||||
SelectBranchCC(N);
|
||||
return;
|
||||
case ISD::CopyToReg:
|
||||
Select(N.getOperand(0));
|
||||
Tmp1 = SelectExpr(N.getOperand(1));
|
||||
Tmp2 = cast<RegSDNode>(N)->getReg();
|
||||
|
||||
|
||||
if (Tmp1 != Tmp2) {
|
||||
if (N.getOperand(1).getValueType() == MVT::f64 ||
|
||||
if (N.getOperand(1).getValueType() == MVT::f64 ||
|
||||
N.getOperand(1).getValueType() == MVT::f32)
|
||||
BuildMI(BB, PPC::FMR, 1, Tmp2).addReg(Tmp1);
|
||||
else
|
||||
@@ -1546,8 +1546,8 @@ void ISel::Select(SDOperand N) {
|
||||
}
|
||||
BuildMI(BB, PPC::BLR, 0); // Just emit a 'ret' instruction
|
||||
return;
|
||||
case ISD::TRUNCSTORE:
|
||||
case ISD::STORE:
|
||||
case ISD::TRUNCSTORE:
|
||||
case ISD::STORE:
|
||||
{
|
||||
SDOperand Chain = N.getOperand(0);
|
||||
SDOperand Value = N.getOperand(1);
|
||||
@@ -1582,7 +1582,7 @@ void ISel::Select(SDOperand N) {
|
||||
{
|
||||
int offset;
|
||||
bool idx = SelectAddr(Address, Tmp2, offset);
|
||||
if (idx) {
|
||||
if (idx) {
|
||||
Opc = IndexedOpForOp(Opc);
|
||||
BuildMI(BB, Opc, 3).addReg(Tmp1).addReg(Tmp2).addReg(offset);
|
||||
} else {
|
||||
@@ -1611,6 +1611,6 @@ void ISel::Select(SDOperand N) {
|
||||
/// description file.
|
||||
///
|
||||
FunctionPass *llvm::createPPC64ISelPattern(TargetMachine &TM) {
|
||||
return new ISel(TM);
|
||||
return new ISel(TM);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===- PPC64InstrInfo.cpp - PowerPC64 Instruction Information ---*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the PowerPC implementation of the TargetInstrInfo class.
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===- PPC64InstrInfo.h - PowerPC64 Instruction Information -----*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the PowerPC64 implementation of the TargetInstrInfo class.
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
case PPC::BGE: return PPC::BLT;
|
||||
case PPC::BGT: return PPC::BLE;
|
||||
case PPC::BLE: return PPC::BGT;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===- PPC64JITInfo.h - PowerPC/AIX impl. of the JIT interface -*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the PowerPC/AIX implementation of the TargetJITInfo class.
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===- PPC64RegisterInfo.cpp - PowerPC64 Register Information ---*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the PowerPC64 implementation of the MRegisterInfo class.
|
||||
@@ -38,7 +38,7 @@ namespace llvm {
|
||||
|
||||
PPC64RegisterInfo::PPC64RegisterInfo()
|
||||
: PPC64GenRegisterInfo(PPC::ADJCALLSTACKDOWN, PPC::ADJCALLSTACKUP) {
|
||||
ImmToIdxMap[PPC::LD] = PPC::LDX; ImmToIdxMap[PPC::STD] = PPC::STDX;
|
||||
ImmToIdxMap[PPC::LD] = PPC::LDX; ImmToIdxMap[PPC::STD] = PPC::STDX;
|
||||
ImmToIdxMap[PPC::LBZ] = PPC::LBZX; ImmToIdxMap[PPC::STB] = PPC::STBX;
|
||||
ImmToIdxMap[PPC::LHZ] = PPC::LHZX; ImmToIdxMap[PPC::LHA] = PPC::LHAX;
|
||||
ImmToIdxMap[PPC::LWZ] = PPC::LWZX; ImmToIdxMap[PPC::LWA] = PPC::LWAX;
|
||||
@@ -62,7 +62,7 @@ static unsigned getIdx(const TargetRegisterClass *RC) {
|
||||
case 1: return 0;
|
||||
case 2: return 1;
|
||||
case 4: return 2;
|
||||
case 8: return 3;
|
||||
case 8: return 3;
|
||||
}
|
||||
} else if (RC == PPC64::FPRCRegisterClass) {
|
||||
switch (RC->getSize()) {
|
||||
@@ -75,12 +75,12 @@ static unsigned getIdx(const TargetRegisterClass *RC) {
|
||||
abort();
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
PPC64RegisterInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MI,
|
||||
unsigned SrcReg, int FrameIdx) const {
|
||||
static const unsigned Opcode[] = {
|
||||
PPC::STB, PPC::STH, PPC::STW, PPC::STD, PPC::STFS, PPC::STFD
|
||||
static const unsigned Opcode[] = {
|
||||
PPC::STB, PPC::STH, PPC::STW, PPC::STD, PPC::STFS, PPC::STFD
|
||||
};
|
||||
unsigned OC = Opcode[getIdx(getClass(SrcReg))];
|
||||
if (SrcReg == PPC::LR) {
|
||||
@@ -97,8 +97,8 @@ void
|
||||
PPC64RegisterInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MI,
|
||||
unsigned DestReg, int FrameIdx) const{
|
||||
static const unsigned Opcode[] = {
|
||||
PPC::LBZ, PPC::LHZ, PPC::LWZ, PPC::LD, PPC::LFS, PPC::LFD
|
||||
static const unsigned Opcode[] = {
|
||||
PPC::LBZ, PPC::LHZ, PPC::LWZ, PPC::LD, PPC::LFS, PPC::LFD
|
||||
};
|
||||
unsigned OC = Opcode[getIdx(getClass(DestReg))];
|
||||
if (DestReg == PPC::LR) {
|
||||
@@ -121,7 +121,7 @@ void PPC64RegisterInfo::copyRegToReg(MachineBasicBlock &MBB,
|
||||
BuildMI(MBB, MI, PPC::OR, 2, DestReg).addReg(SrcReg).addReg(SrcReg);
|
||||
} else if (RC == PPC64::FPRCRegisterClass) {
|
||||
BuildMI(MBB, MI, PPC::FMR, 1, DestReg).addReg(SrcReg);
|
||||
} else {
|
||||
} else {
|
||||
std::cerr << "Attempt to copy register that is not GPR or FPR";
|
||||
abort();
|
||||
}
|
||||
@@ -155,7 +155,7 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
|
||||
// alignment boundary.
|
||||
unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment();
|
||||
Amount = (Amount+Align-1)/Align*Align;
|
||||
|
||||
|
||||
// Replace the pseudo instruction with a new instruction...
|
||||
if (Old->getOpcode() == PPC::ADJCALLSTACKDOWN) {
|
||||
MBB.insert(I, BuildMI(PPC::ADDI, 2, PPC::R1).addReg(PPC::R1)
|
||||
@@ -176,7 +176,7 @@ PPC64RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II) const {
|
||||
MachineInstr &MI = *II;
|
||||
MachineBasicBlock &MBB = *MI.getParent();
|
||||
MachineFunction &MF = *MBB.getParent();
|
||||
|
||||
|
||||
while (!MI.getOperand(i).isFrameIndex()) {
|
||||
++i;
|
||||
assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
|
||||
@@ -198,7 +198,7 @@ PPC64RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II) const {
|
||||
// SP before having the stack size subtracted from it, then add the stack size
|
||||
// to Offset to get the correct offset.
|
||||
Offset += MF.getFrameInfo()->getStackSize();
|
||||
|
||||
|
||||
if (Offset > 32767 || Offset < -32768) {
|
||||
// Insert a set of r0 with the full offset value before the ld, st, or add
|
||||
MachineBasicBlock *MBB = MI.getParent();
|
||||
@@ -208,7 +208,7 @@ PPC64RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II) const {
|
||||
// convert into indexed form of the instruction
|
||||
// sth 0:rA, 1:imm 2:(rB) ==> sthx 0:rA, 2:rB, 1:r0
|
||||
// addi 0:rA 1:rB, 2, imm ==> add 0:rA, 1:rB, 2:r0
|
||||
unsigned NewOpcode =
|
||||
unsigned NewOpcode =
|
||||
const_cast<std::map<unsigned, unsigned>& >(ImmToIdxMap)[MI.getOpcode()];
|
||||
assert(NewOpcode && "No indexed form of load or store available!");
|
||||
MI.setOpcode(NewOpcode);
|
||||
@@ -226,15 +226,15 @@ void PPC64RegisterInfo::emitPrologue(MachineFunction &MF) const {
|
||||
MachineBasicBlock::iterator MBBI = MBB.begin();
|
||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
MachineInstr *MI;
|
||||
|
||||
|
||||
// Get the number of bytes to allocate from the FrameInfo
|
||||
unsigned NumBytes = MFI->getStackSize();
|
||||
|
||||
// If we have calls, we cannot use the red zone to store callee save registers
|
||||
// and we must set up a stack frame, so calculate the necessary size here.
|
||||
if (MFI->hasCalls()) {
|
||||
// We reserve argument space for call sites in the function immediately on
|
||||
// entry to the current function. This eliminates the need for add/sub
|
||||
// We reserve argument space for call sites in the function immediately on
|
||||
// entry to the current function. This eliminates the need for add/sub
|
||||
// brackets around call sites.
|
||||
NumBytes += MFI->getMaxCallFrameSize();
|
||||
}
|
||||
@@ -242,7 +242,7 @@ void PPC64RegisterInfo::emitPrologue(MachineFunction &MF) const {
|
||||
// Do we need to allocate space on the stack?
|
||||
if (NumBytes == 0) return;
|
||||
|
||||
// Add the size of R1 to NumBytes size for the store of R1 to the bottom
|
||||
// Add the size of R1 to NumBytes size for the store of R1 to the bottom
|
||||
// of the stack and round the size to a multiple of the alignment.
|
||||
unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment();
|
||||
unsigned GPRSize = getSpillSize(PPC::R1)/8;
|
||||
@@ -266,7 +266,7 @@ void PPC64RegisterInfo::emitPrologue(MachineFunction &MF) const {
|
||||
MI = BuildMI(PPC::STDUX, 3).addReg(PPC::R1).addReg(PPC::R1).addReg(PPC::R0);
|
||||
MBB.insert(MBBI, MI);
|
||||
}
|
||||
|
||||
|
||||
if (hasFP(MF)) {
|
||||
MI = BuildMI(PPC::STD, 3).addReg(PPC::R31).addSImm(GPRSize).addReg(PPC::R1);
|
||||
MBB.insert(MBBI, MI);
|
||||
@@ -282,7 +282,7 @@ void PPC64RegisterInfo::emitEpilogue(MachineFunction &MF,
|
||||
MachineInstr *MI;
|
||||
assert(MBBI->getOpcode() == PPC::BLR &&
|
||||
"Can only insert epilog into returning blocks");
|
||||
|
||||
|
||||
// Get the number of bytes allocated from the FrameInfo...
|
||||
unsigned NumBytes = MFI->getStackSize();
|
||||
|
||||
@@ -314,7 +314,7 @@ PPC64RegisterInfo::getRegClassForType(const Type* Ty) const {
|
||||
case Type::PointerTyID:
|
||||
case Type::LongTyID:
|
||||
case Type::ULongTyID: return &GPRCInstance;
|
||||
|
||||
|
||||
case Type::FloatTyID:
|
||||
case Type::DoubleTyID: return &FPRCInstance;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===- PPC64RegisterInfo.h - PowerPC64 Register Information Impl -*- C++ -*-==//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the PowerPC implementation of the MRegisterInfo class.
|
||||
@@ -36,7 +36,7 @@ public:
|
||||
void loadRegFromStackSlot(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MBBI,
|
||||
unsigned DestReg, int FrameIndex) const;
|
||||
|
||||
|
||||
void copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
|
||||
unsigned DestReg, unsigned SrcReg,
|
||||
const TargetRegisterClass *RC) const;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
//===-- PPC64TargetMachine.h - Define TargetMachine for PowerPC64 -*- C++ -*-=//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
// This file declares the PowerPC specific subclass of TargetMachine.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===-- PowerPCAsmPrinter.cpp - Print machine instrs to PowerPC assembly --===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains a printer that converts from our internal representation
|
||||
@@ -45,14 +45,14 @@ namespace {
|
||||
struct PowerPCAsmPrinter : public AsmPrinter {
|
||||
std::set<std::string> FnStubs, GVStubs, LinkOnceStubs;
|
||||
std::set<std::string> Strings;
|
||||
|
||||
|
||||
PowerPCAsmPrinter(std::ostream &O, TargetMachine &TM)
|
||||
: AsmPrinter(O, TM), LabelNumber(0) {}
|
||||
|
||||
/// Unique incrementer for label values for referencing Global values.
|
||||
///
|
||||
unsigned LabelNumber;
|
||||
|
||||
|
||||
virtual const char *getPassName() const {
|
||||
return "PowerPC Assembly Printer";
|
||||
}
|
||||
@@ -109,7 +109,7 @@ namespace {
|
||||
if (MI->getOperand(OpNo).isImmediate()) {
|
||||
O << "$+" << MI->getOperand(OpNo).getImmedValue();
|
||||
} else {
|
||||
printOp(MI->getOperand(OpNo),
|
||||
printOp(MI->getOperand(OpNo),
|
||||
TM.getInstrInfo()->isCall(MI->getOpcode()));
|
||||
}
|
||||
}
|
||||
@@ -158,12 +158,12 @@ namespace {
|
||||
}
|
||||
O << 4 * RegNo + value;
|
||||
}
|
||||
|
||||
|
||||
virtual void printConstantPool(MachineConstantPool *MCP) = 0;
|
||||
virtual bool runOnMachineFunction(MachineFunction &F) = 0;
|
||||
virtual bool runOnMachineFunction(MachineFunction &F) = 0;
|
||||
virtual bool doFinalization(Module &M) = 0;
|
||||
};
|
||||
|
||||
|
||||
/// DarwinAsmPrinter - PowerPC assembly printer, customized for Darwin/Mac OS
|
||||
/// X
|
||||
///
|
||||
@@ -183,10 +183,10 @@ namespace {
|
||||
}
|
||||
|
||||
void printConstantPool(MachineConstantPool *MCP);
|
||||
bool runOnMachineFunction(MachineFunction &F);
|
||||
bool runOnMachineFunction(MachineFunction &F);
|
||||
bool doFinalization(Module &M);
|
||||
};
|
||||
|
||||
|
||||
/// AIXAsmPrinter - PowerPC assembly printer, customized for AIX
|
||||
///
|
||||
struct AIXAsmPrinter : public PowerPCAsmPrinter {
|
||||
@@ -202,13 +202,13 @@ namespace {
|
||||
Data64bitsDirective = 0; // we can't emit a 64-bit unit
|
||||
AlignmentIsInBytes = false; // Alignment is by power of 2.
|
||||
}
|
||||
|
||||
|
||||
virtual const char *getPassName() const {
|
||||
return "AIX PPC Assembly Printer";
|
||||
}
|
||||
|
||||
void printConstantPool(MachineConstantPool *MCP);
|
||||
bool runOnMachineFunction(MachineFunction &F);
|
||||
bool runOnMachineFunction(MachineFunction &F);
|
||||
bool doInitialization(Module &M);
|
||||
bool doFinalization(Module &M);
|
||||
};
|
||||
@@ -258,7 +258,7 @@ namespace {
|
||||
|
||||
/// SwitchStringSection - manage the changes required to output bytes as
|
||||
/// characters in a string vs. numeric decimal values
|
||||
///
|
||||
///
|
||||
static inline void SwitchStringSection(std::ostream &O, StringSection NewSect,
|
||||
StringSection &Current) {
|
||||
if (Current == None) {
|
||||
@@ -269,7 +269,7 @@ static inline void SwitchStringSection(std::ostream &O, StringSection NewSect,
|
||||
} else if (Current == Alpha) {
|
||||
if (NewSect == None)
|
||||
O << "\"";
|
||||
else if (NewSect == Numeric)
|
||||
else if (NewSect == Numeric)
|
||||
O << "\"\n"
|
||||
<< "\t.byte ";
|
||||
} else if (Current == Numeric) {
|
||||
@@ -310,8 +310,8 @@ static void printAsCString(std::ostream &O, const ConstantArray *CVA) {
|
||||
O << '\n';
|
||||
}
|
||||
|
||||
/// createDarwinAsmPrinterPass - Returns a pass that prints the PPC assembly
|
||||
/// code for a MachineFunction to the given output stream, in a format that the
|
||||
/// createDarwinAsmPrinterPass - Returns a pass that prints the PPC assembly
|
||||
/// code for a MachineFunction to the given output stream, in a format that the
|
||||
/// Darwin assembler can deal with.
|
||||
///
|
||||
FunctionPass *llvm::createDarwinAsmPrinter(std::ostream &o, TargetMachine &tm) {
|
||||
@@ -319,7 +319,7 @@ FunctionPass *llvm::createDarwinAsmPrinter(std::ostream &o, TargetMachine &tm) {
|
||||
}
|
||||
|
||||
/// createAIXAsmPrinterPass - Returns a pass that prints the PPC assembly code
|
||||
/// for a MachineFunction to the given output stream, in a format that the
|
||||
/// for a MachineFunction to the given output stream, in a format that the
|
||||
/// AIX 5L assembler can deal with.
|
||||
///
|
||||
FunctionPass *llvm::createAIXAsmPrinter(std::ostream &o, TargetMachine &tm) {
|
||||
@@ -332,7 +332,7 @@ FunctionPass *llvm::createAIXAsmPrinter(std::ostream &o, TargetMachine &tm) {
|
||||
void PowerPCAsmPrinter::printOp(const MachineOperand &MO, bool IsCallOp) {
|
||||
const MRegisterInfo &RI = *TM.getRegisterInfo();
|
||||
int new_symbol;
|
||||
|
||||
|
||||
switch (MO.getType()) {
|
||||
case MachineOperand::MO_VirtualRegister:
|
||||
if (Value *V = MO.getVRegValueOrNull()) {
|
||||
@@ -355,7 +355,7 @@ void PowerPCAsmPrinter::printOp(const MachineOperand &MO, bool IsCallOp) {
|
||||
std::cerr << "Shouldn't use addPCDisp() when building PPC MachineInstrs";
|
||||
abort();
|
||||
return;
|
||||
|
||||
|
||||
case MachineOperand::MO_MachineBasicBlock: {
|
||||
MachineBasicBlock *MBBOp = MO.getMachineBasicBlock();
|
||||
O << ".LBB" << Mang->getValueName(MBBOp->getParent()->getFunction())
|
||||
@@ -391,7 +391,7 @@ void PowerPCAsmPrinter::printOp(const MachineOperand &MO, bool IsCallOp) {
|
||||
O << "L" << Name << "$stub";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// External or weakly linked global variables need non-lazily-resolved stubs
|
||||
if ((GV->isExternal() || GV->hasWeakLinkage() || GV->hasLinkOnceLinkage())){
|
||||
if (GV->hasLinkOnceLinkage())
|
||||
@@ -405,7 +405,7 @@ void PowerPCAsmPrinter::printOp(const MachineOperand &MO, bool IsCallOp) {
|
||||
O << Mang->getValueName(GV);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
O << "<unknown operand type: " << MO.getType() << ">";
|
||||
return;
|
||||
@@ -431,17 +431,17 @@ void PowerPCAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
|
||||
SH = 32-SH;
|
||||
}
|
||||
if (FoundMnemonic) {
|
||||
printOperand(MI, 0, MVT::i64);
|
||||
O << ", ";
|
||||
printOperand(MI, 1, MVT::i64);
|
||||
printOperand(MI, 0, MVT::i64);
|
||||
O << ", ";
|
||||
printOperand(MI, 1, MVT::i64);
|
||||
O << ", " << (unsigned int)SH << "\n";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (printInstruction(MI))
|
||||
return; // Printer was automatically generated
|
||||
|
||||
|
||||
assert(0 && "Unhandled instruction in asm writer!");
|
||||
abort();
|
||||
return;
|
||||
@@ -490,7 +490,7 @@ bool DarwinAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
|
||||
void DarwinAsmPrinter::printConstantPool(MachineConstantPool *MCP) {
|
||||
const std::vector<Constant*> &CP = MCP->getConstants();
|
||||
const TargetData &TD = TM.getTargetData();
|
||||
|
||||
|
||||
if (CP.empty()) return;
|
||||
|
||||
for (unsigned i = 0, e = CP.size(); i != e; ++i) {
|
||||
@@ -516,13 +516,13 @@ bool DarwinAsmPrinter::doFinalization(Module &M) {
|
||||
unsigned Align = TD.getTypeAlignmentShift(C->getType());
|
||||
|
||||
if (C->isNullValue() && /* FIXME: Verify correct */
|
||||
(I->hasInternalLinkage() || I->hasWeakLinkage() ||
|
||||
(I->hasInternalLinkage() || I->hasWeakLinkage() ||
|
||||
I->hasLinkOnceLinkage())) {
|
||||
SwitchSection(O, CurSection, ".data");
|
||||
if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
|
||||
if (I->hasInternalLinkage())
|
||||
O << ".lcomm " << name << "," << Size << "," << Align;
|
||||
else
|
||||
else
|
||||
O << ".comm " << name << "," << Size;
|
||||
O << "\t\t; ";
|
||||
WriteAsOperand(O, I, true, true, &M);
|
||||
@@ -535,7 +535,7 @@ bool DarwinAsmPrinter::doFinalization(Module &M) {
|
||||
<< ".private_extern " << name << '\n'
|
||||
<< ".section __DATA,__datacoal_nt,coalesced,no_toc\n";
|
||||
LinkOnceStubs.insert(name);
|
||||
break;
|
||||
break;
|
||||
case GlobalValue::WeakLinkage: // FIXME: Verify correct for weak.
|
||||
// Nonnull linkonce -> weak
|
||||
O << "\t.weak " << name << "\n";
|
||||
@@ -568,7 +568,7 @@ bool DarwinAsmPrinter::doFinalization(Module &M) {
|
||||
}
|
||||
|
||||
// Output stubs for dynamically-linked functions
|
||||
for (std::set<std::string>::iterator i = FnStubs.begin(), e = FnStubs.end();
|
||||
for (std::set<std::string>::iterator i = FnStubs.begin(), e = FnStubs.end();
|
||||
i != e; ++i)
|
||||
{
|
||||
O << ".data\n";
|
||||
@@ -597,22 +597,22 @@ bool DarwinAsmPrinter::doFinalization(Module &M) {
|
||||
// Output stubs for external global variables
|
||||
if (GVStubs.begin() != GVStubs.end())
|
||||
O << ".data\n.non_lazy_symbol_pointer\n";
|
||||
for (std::set<std::string>::iterator i = GVStubs.begin(), e = GVStubs.end();
|
||||
for (std::set<std::string>::iterator i = GVStubs.begin(), e = GVStubs.end();
|
||||
i != e; ++i) {
|
||||
O << "L" << *i << "$non_lazy_ptr:\n";
|
||||
O << "\t.indirect_symbol " << *i << "\n";
|
||||
O << "\t.long\t0\n";
|
||||
}
|
||||
|
||||
|
||||
// Output stubs for link-once variables
|
||||
if (LinkOnceStubs.begin() != LinkOnceStubs.end())
|
||||
O << ".data\n.align 2\n";
|
||||
for (std::set<std::string>::iterator i = LinkOnceStubs.begin(),
|
||||
for (std::set<std::string>::iterator i = LinkOnceStubs.begin(),
|
||||
e = LinkOnceStubs.end(); i != e; ++i) {
|
||||
O << "L" << *i << "$non_lazy_ptr:\n"
|
||||
<< "\t.long\t" << *i << '\n';
|
||||
}
|
||||
|
||||
|
||||
AsmPrinter::doFinalization(M);
|
||||
return false; // success
|
||||
}
|
||||
@@ -672,7 +672,7 @@ bool AIXAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
|
||||
void AIXAsmPrinter::printConstantPool(MachineConstantPool *MCP) {
|
||||
const std::vector<Constant*> &CP = MCP->getConstants();
|
||||
const TargetData &TD = TM.getTargetData();
|
||||
|
||||
|
||||
if (CP.empty()) return;
|
||||
|
||||
for (unsigned i = 0, e = CP.size(); i != e; ++i) {
|
||||
@@ -689,7 +689,7 @@ bool AIXAsmPrinter::doInitialization(Module &M) {
|
||||
const TargetData &TD = TM.getTargetData();
|
||||
std::string CurSection;
|
||||
|
||||
O << "\t.machine \"ppc64\"\n"
|
||||
O << "\t.machine \"ppc64\"\n"
|
||||
<< "\t.toc\n"
|
||||
<< "\t.csect .text[PR]\n";
|
||||
|
||||
@@ -697,11 +697,11 @@ bool AIXAsmPrinter::doInitialization(Module &M) {
|
||||
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) {
|
||||
if (!I->hasInitializer())
|
||||
continue;
|
||||
|
||||
|
||||
std::string Name = I->getName();
|
||||
Constant *C = I->getInitializer();
|
||||
// N.B.: We are defaulting to writable strings
|
||||
if (I->hasExternalLinkage()) {
|
||||
if (I->hasExternalLinkage()) {
|
||||
O << "\t.globl " << Name << '\n'
|
||||
<< "\t.csect .data[RW],3\n";
|
||||
} else {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
//===-- PowerPCBranchSelector.cpp - Emit long conditional branches-*- C++ -*-=//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by Nate Baegeman and is distributed under the
|
||||
// University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains a pass that scans a machine function to determine which
|
||||
// This file contains a pass that scans a machine function to determine which
|
||||
// conditional branches need more than 16 bits of displacement to reach their
|
||||
// target basic block. It does this in two passes; a calculation of basic block
|
||||
// positions pass, and a branch psuedo op to machine branch opcode pass. This
|
||||
@@ -30,32 +30,32 @@ namespace {
|
||||
// OffsetMap - Mapping between BB and byte offset from start of function
|
||||
std::map<MachineBasicBlock*, unsigned> OffsetMap;
|
||||
|
||||
/// bytesForOpcode - A convenience function for totalling up the number of
|
||||
/// bytesForOpcode - A convenience function for totalling up the number of
|
||||
/// bytes in a basic block.
|
||||
///
|
||||
static unsigned bytesForOpcode(unsigned opcode) {
|
||||
switch (opcode) {
|
||||
case PPC::COND_BRANCH:
|
||||
// while this will be 4 most of the time, if we emit 12 it is just a
|
||||
// minor pessimization that saves us from having to worry about
|
||||
// minor pessimization that saves us from having to worry about
|
||||
// keeping the offsets up to date later when we emit long branch glue.
|
||||
return 12;
|
||||
case PPC::IMPLICIT_DEF: // no asm emitted
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
default:
|
||||
return 4; // PowerPC instructions are all 4 bytes
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
virtual bool runOnMachineFunction(MachineFunction &Fn) {
|
||||
// Running total of instructions encountered since beginning of function
|
||||
unsigned ByteCount = 0;
|
||||
|
||||
// For each MBB, add its offset to the offset map, and count up its
|
||||
// instructions
|
||||
for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
|
||||
for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
|
||||
++MFI) {
|
||||
MachineBasicBlock *MBB = MFI;
|
||||
OffsetMap[MBB] = ByteCount;
|
||||
@@ -80,10 +80,10 @@ namespace {
|
||||
// b .L_TARGET_MBB
|
||||
// b .L_FALLTHROUGH_MBB
|
||||
|
||||
for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
|
||||
for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
|
||||
++MFI) {
|
||||
MachineBasicBlock *MBB = MFI;
|
||||
|
||||
|
||||
for (MachineBasicBlock::iterator MBBI = MBB->begin(), EE = MBB->end();
|
||||
MBBI != EE; ++MBBI) {
|
||||
if (MBBI->getOpcode() == PPC::COND_BRANCH) {
|
||||
@@ -92,11 +92,11 @@ namespace {
|
||||
// 1. bc opcode
|
||||
// 2. target MBB
|
||||
// 3. fallthrough MBB
|
||||
MachineBasicBlock *trueMBB =
|
||||
MachineBasicBlock *trueMBB =
|
||||
MBBI->getOperand(2).getMachineBasicBlock();
|
||||
MachineBasicBlock *falseMBB =
|
||||
MachineBasicBlock *falseMBB =
|
||||
MBBI->getOperand(3).getMachineBasicBlock();
|
||||
|
||||
|
||||
int Displacement = OffsetMap[trueMBB] - ByteCount;
|
||||
unsigned Opcode = MBBI->getOperand(1).getImmedValue();
|
||||
unsigned Inverted = PPC32InstrInfo::invertPPCBranchOpcode(Opcode);
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
//===-- PPC32CodeEmitter.cpp - JIT Code Emitter for PowerPC32 -----*- C++ -*-=//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
// This file defines the PowerPC 32-bit CodeEmitter and associated machinery to
|
||||
// JIT-compile bytecode to native PowerPC.
|
||||
//
|
||||
@@ -42,7 +42,7 @@ namespace {
|
||||
int getMachineOpValue(MachineInstr &MI, MachineOperand &MO);
|
||||
|
||||
public:
|
||||
PPC32CodeEmitter(TargetMachine &T, MachineCodeEmitter &M)
|
||||
PPC32CodeEmitter(TargetMachine &T, MachineCodeEmitter &M)
|
||||
: TM(T), MCE(M) {}
|
||||
|
||||
const char *getPassName() const { return "PowerPC Machine Code Emitter"; }
|
||||
@@ -58,7 +58,7 @@ namespace {
|
||||
/// emitWord - write a 32-bit word to memory at the current PC
|
||||
///
|
||||
void emitWord(unsigned w) { MCE.emitWord(w); }
|
||||
|
||||
|
||||
/// getValueBit - return the particular bit of Val
|
||||
///
|
||||
unsigned getValueBit(int64_t Val, unsigned bit) { return (Val >> bit) & 1; }
|
||||
@@ -80,7 +80,7 @@ namespace {
|
||||
bool PPC32TargetMachine::addPassesToEmitMachineCode(FunctionPassManager &PM,
|
||||
MachineCodeEmitter &MCE) {
|
||||
// Machine code emitter pass for PowerPC
|
||||
PM.add(new PPC32CodeEmitter(*this, MCE));
|
||||
PM.add(new PPC32CodeEmitter(*this, MCE));
|
||||
// Delete machine code for this function after emitting it
|
||||
PM.add(createMachineCodeDeleter());
|
||||
return false;
|
||||
@@ -102,7 +102,7 @@ bool PPC32CodeEmitter::runOnMachineFunction(MachineFunction &MF) {
|
||||
<< "\n");
|
||||
unsigned Instr = *Ref;
|
||||
intptr_t BranchTargetDisp = (Location - (intptr_t)Ref) >> 2;
|
||||
|
||||
|
||||
switch (Instr >> 26) {
|
||||
default: assert(0 && "Unknown branch user!");
|
||||
case 18: // This is B or BL
|
||||
@@ -142,36 +142,36 @@ void PPC32CodeEmitter::emitBasicBlock(MachineBasicBlock &MBB) {
|
||||
|
||||
static unsigned enumRegToMachineReg(unsigned enumReg) {
|
||||
switch (enumReg) {
|
||||
case PPC::R0 : case PPC::F0 : case PPC::CR0: return 0;
|
||||
case PPC::R1 : case PPC::F1 : case PPC::CR1: return 1;
|
||||
case PPC::R0 : case PPC::F0 : case PPC::CR0: return 0;
|
||||
case PPC::R1 : case PPC::F1 : case PPC::CR1: return 1;
|
||||
case PPC::R2 : case PPC::F2 : case PPC::CR2: return 2;
|
||||
case PPC::R3 : case PPC::F3 : case PPC::CR3: return 3;
|
||||
case PPC::R4 : case PPC::F4 : case PPC::CR4: return 4;
|
||||
case PPC::R3 : case PPC::F3 : case PPC::CR3: return 3;
|
||||
case PPC::R4 : case PPC::F4 : case PPC::CR4: return 4;
|
||||
case PPC::R5 : case PPC::F5 : case PPC::CR5: return 5;
|
||||
case PPC::R6 : case PPC::F6 : case PPC::CR6: return 6;
|
||||
case PPC::R7 : case PPC::F7 : case PPC::CR7: return 7;
|
||||
case PPC::R6 : case PPC::F6 : case PPC::CR6: return 6;
|
||||
case PPC::R7 : case PPC::F7 : case PPC::CR7: return 7;
|
||||
case PPC::R8 : case PPC::F8 : return 8;
|
||||
case PPC::R9 : case PPC::F9 : return 9;
|
||||
case PPC::R10: case PPC::F10: return 10;
|
||||
case PPC::R9 : case PPC::F9 : return 9;
|
||||
case PPC::R10: case PPC::F10: return 10;
|
||||
case PPC::R11: case PPC::F11: return 11;
|
||||
case PPC::R12: case PPC::F12: return 12;
|
||||
case PPC::R13: case PPC::F13: return 13;
|
||||
case PPC::R12: case PPC::F12: return 12;
|
||||
case PPC::R13: case PPC::F13: return 13;
|
||||
case PPC::R14: case PPC::F14: return 14;
|
||||
case PPC::R15: case PPC::F15: return 15;
|
||||
case PPC::R16: case PPC::F16: return 16;
|
||||
case PPC::R15: case PPC::F15: return 15;
|
||||
case PPC::R16: case PPC::F16: return 16;
|
||||
case PPC::R17: case PPC::F17: return 17;
|
||||
case PPC::R18: case PPC::F18: return 18;
|
||||
case PPC::R19: case PPC::F19: return 19;
|
||||
case PPC::R18: case PPC::F18: return 18;
|
||||
case PPC::R19: case PPC::F19: return 19;
|
||||
case PPC::R20: case PPC::F20: return 20;
|
||||
case PPC::R21: case PPC::F21: return 21;
|
||||
case PPC::R22: case PPC::F22: return 22;
|
||||
case PPC::R23: case PPC::F23: return 23;
|
||||
case PPC::R22: case PPC::F22: return 22;
|
||||
case PPC::R23: case PPC::F23: return 23;
|
||||
case PPC::R24: case PPC::F24: return 24;
|
||||
case PPC::R25: case PPC::F25: return 25;
|
||||
case PPC::R26: case PPC::F26: return 26;
|
||||
case PPC::R25: case PPC::F25: return 25;
|
||||
case PPC::R26: case PPC::F26: return 26;
|
||||
case PPC::R27: case PPC::F27: return 27;
|
||||
case PPC::R28: case PPC::F28: return 28;
|
||||
case PPC::R29: case PPC::F29: return 29;
|
||||
case PPC::R28: case PPC::F28: return 28;
|
||||
case PPC::R29: case PPC::F29: return 29;
|
||||
case PPC::R30: case PPC::F30: return 30;
|
||||
case PPC::R31: case PPC::F31: return 31;
|
||||
default:
|
||||
@@ -181,7 +181,7 @@ static unsigned enumRegToMachineReg(unsigned enumReg) {
|
||||
}
|
||||
|
||||
int PPC32CodeEmitter::getMachineOpValue(MachineInstr &MI, MachineOperand &MO) {
|
||||
|
||||
|
||||
int rv = 0; // Return value; defaults to 0 for unhandled cases
|
||||
// or things that get fixed up later by the JIT.
|
||||
if (MO.isRegister()) {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===-- PowerPCFrameInfo.h - Define TargetFrameInfo for PowerPC -*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
@@ -22,7 +22,7 @@ namespace llvm {
|
||||
class PowerPCFrameInfo: public TargetFrameInfo {
|
||||
const TargetMachine &TM;
|
||||
std::pair<unsigned, int> LR[1];
|
||||
|
||||
|
||||
public:
|
||||
PowerPCFrameInfo(const TargetMachine &tm, bool LP64)
|
||||
: TargetFrameInfo(TargetFrameInfo::StackGrowsDown, 16, 0), TM(tm) {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
//
|
||||
// This file was developed by Nate Begeman and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines a pattern matching instruction selector for 32 bit PowerPC.
|
||||
@@ -47,7 +47,7 @@ namespace {
|
||||
addRegisterClass(MVT::i32, PPC32::GPRCRegisterClass);
|
||||
addRegisterClass(MVT::f32, PPC32::FPRCRegisterClass);
|
||||
addRegisterClass(MVT::f64, PPC32::FPRCRegisterClass);
|
||||
|
||||
|
||||
// PowerPC has no intrinsics for these particular operations
|
||||
setOperationAction(ISD::MEMMOVE, MVT::Other, Expand);
|
||||
setOperationAction(ISD::MEMSET, MVT::Other, Expand);
|
||||
@@ -56,14 +56,14 @@ namespace {
|
||||
// PowerPC has an i16 but no i8 (or i1) SEXTLOAD
|
||||
setOperationAction(ISD::SEXTLOAD, MVT::i1, Expand);
|
||||
setOperationAction(ISD::SEXTLOAD, MVT::i8, Expand);
|
||||
|
||||
|
||||
// PowerPC has no SREM/UREM instructions
|
||||
setOperationAction(ISD::SREM, MVT::i32, Expand);
|
||||
setOperationAction(ISD::UREM, MVT::i32, Expand);
|
||||
|
||||
setSetCCResultContents(ZeroOrOneSetCCResult);
|
||||
addLegalFPImmediate(+0.0); // Necessary for FSEL
|
||||
addLegalFPImmediate(-0.0); //
|
||||
addLegalFPImmediate(-0.0); //
|
||||
|
||||
computeRegisterProperties();
|
||||
}
|
||||
@@ -72,16 +72,16 @@ namespace {
|
||||
/// lower the arguments for the specified function, into the specified DAG.
|
||||
virtual std::vector<SDOperand>
|
||||
LowerArguments(Function &F, SelectionDAG &DAG);
|
||||
|
||||
|
||||
/// LowerCallTo - This hook lowers an abstract call to a function into an
|
||||
/// actual call.
|
||||
virtual std::pair<SDOperand, SDOperand>
|
||||
LowerCallTo(SDOperand Chain, const Type *RetTy, bool isVarArg,
|
||||
SDOperand Callee, ArgListTy &Args, SelectionDAG &DAG);
|
||||
|
||||
|
||||
virtual std::pair<SDOperand, SDOperand>
|
||||
LowerVAStart(SDOperand Chain, SelectionDAG &DAG);
|
||||
|
||||
|
||||
virtual std::pair<SDOperand,SDOperand>
|
||||
LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList,
|
||||
const Type *ArgTy, SelectionDAG &DAG);
|
||||
@@ -102,8 +102,8 @@ PPC32TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
|
||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
MachineBasicBlock& BB = MF.front();
|
||||
std::vector<SDOperand> ArgValues;
|
||||
|
||||
// Due to the rather complicated nature of the PowerPC ABI, rather than a
|
||||
|
||||
// Due to the rather complicated nature of the PowerPC ABI, rather than a
|
||||
// fixed size array of physical args, for the sake of simplicity let the STL
|
||||
// handle tracking them for us.
|
||||
std::vector<unsigned> argVR, argPR, argOp;
|
||||
@@ -111,7 +111,7 @@ PPC32TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
|
||||
unsigned GPR_remaining = 8;
|
||||
unsigned FPR_remaining = 13;
|
||||
unsigned GPR_idx = 0, FPR_idx = 0;
|
||||
static const unsigned GPR[] = {
|
||||
static const unsigned GPR[] = {
|
||||
PPC::R3, PPC::R4, PPC::R5, PPC::R6,
|
||||
PPC::R7, PPC::R8, PPC::R9, PPC::R10,
|
||||
};
|
||||
@@ -129,13 +129,13 @@ PPC32TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
|
||||
bool needsLoad = false;
|
||||
bool ArgLive = !I->use_empty();
|
||||
MVT::ValueType ObjectVT = getValueType(I->getType());
|
||||
|
||||
|
||||
switch (ObjectVT) {
|
||||
default: assert(0 && "Unhandled argument type!");
|
||||
case MVT::i1:
|
||||
case MVT::i8:
|
||||
case MVT::i16:
|
||||
case MVT::i32:
|
||||
case MVT::i32:
|
||||
ObjSize = 4;
|
||||
if (!ArgLive) break;
|
||||
if (GPR_remaining > 0) {
|
||||
@@ -170,7 +170,7 @@ PPC32TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
|
||||
argt = DAG.getNode(ISD::BUILD_PAIR, MVT::i64, argLo, argHi);
|
||||
newroot = argLo;
|
||||
} else {
|
||||
needsLoad = true;
|
||||
needsLoad = true;
|
||||
}
|
||||
break;
|
||||
case MVT::f32:
|
||||
@@ -179,7 +179,7 @@ PPC32TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
|
||||
if (!ArgLive) break;
|
||||
if (FPR_remaining > 0) {
|
||||
MF.addLiveIn(FPR[FPR_idx]);
|
||||
argt = newroot = DAG.getCopyFromReg(FPR[FPR_idx], ObjectVT,
|
||||
argt = newroot = DAG.getCopyFromReg(FPR[FPR_idx], ObjectVT,
|
||||
DAG.getRoot());
|
||||
--FPR_remaining;
|
||||
++FPR_idx;
|
||||
@@ -188,20 +188,20 @@ PPC32TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// We need to load the argument to a virtual register if we determined above
|
||||
// that we ran out of physical registers of the appropriate type
|
||||
// that we ran out of physical registers of the appropriate type
|
||||
if (needsLoad) {
|
||||
unsigned SubregOffset = 0;
|
||||
if (ObjectVT == MVT::i8 || ObjectVT == MVT::i1) SubregOffset = 3;
|
||||
if (ObjectVT == MVT::i16) SubregOffset = 2;
|
||||
int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
|
||||
SDOperand FIN = DAG.getFrameIndex(FI, MVT::i32);
|
||||
FIN = DAG.getNode(ISD::ADD, MVT::i32, FIN,
|
||||
FIN = DAG.getNode(ISD::ADD, MVT::i32, FIN,
|
||||
DAG.getConstant(SubregOffset, MVT::i32));
|
||||
argt = newroot = DAG.getLoad(ObjectVT, DAG.getEntryNode(), FIN);
|
||||
}
|
||||
|
||||
|
||||
// Every 4 bytes of argument space consumes one of the GPRs available for
|
||||
// argument passing.
|
||||
if (GPR_remaining > 0) {
|
||||
@@ -212,7 +212,7 @@ PPC32TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
|
||||
ArgOffset += ObjSize;
|
||||
if (newroot.Val)
|
||||
DAG.setRoot(newroot.getValue(1));
|
||||
|
||||
|
||||
ArgValues.push_back(argt);
|
||||
}
|
||||
|
||||
@@ -228,7 +228,7 @@ PPC32TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
|
||||
for (; GPR_remaining > 0; --GPR_remaining, ++GPR_idx) {
|
||||
MF.addLiveIn(GPR[GPR_idx]);
|
||||
SDOperand Val = DAG.getCopyFromReg(GPR[GPR_idx], MVT::i32, DAG.getRoot());
|
||||
SDOperand Store = DAG.getNode(ISD::STORE, MVT::Other, Val.getValue(1),
|
||||
SDOperand Store = DAG.getNode(ISD::STORE, MVT::Other, Val.getValue(1),
|
||||
Val, FIN);
|
||||
MemOps.push_back(Store);
|
||||
// Increment the address by four for the next argument to store
|
||||
@@ -292,8 +292,8 @@ PPC32TargetLowering::LowerCallTo(SDOperand Chain,
|
||||
NumBytes += 8;
|
||||
break;
|
||||
}
|
||||
|
||||
// Just to be safe, we'll always reserve the full 24 bytes of linkage area
|
||||
|
||||
// Just to be safe, we'll always reserve the full 24 bytes of linkage area
|
||||
// plus 32 bytes of argument space in case any called code gets funky on us.
|
||||
if (NumBytes < 56) NumBytes = 56;
|
||||
|
||||
@@ -307,7 +307,7 @@ PPC32TargetLowering::LowerCallTo(SDOperand Chain,
|
||||
// passing.
|
||||
SDOperand StackPtr = DAG.getCopyFromReg(PPC::R1, MVT::i32,
|
||||
DAG.getEntryNode());
|
||||
|
||||
|
||||
// Figure out which arguments are going to go in registers, and which in
|
||||
// memory. Also, if this is a vararg function, floating point operations
|
||||
// must be stored to our stack, and loaded into integer regs as well, if
|
||||
@@ -315,7 +315,7 @@ PPC32TargetLowering::LowerCallTo(SDOperand Chain,
|
||||
unsigned ArgOffset = 24;
|
||||
unsigned GPR_remaining = 8;
|
||||
unsigned FPR_remaining = 13;
|
||||
|
||||
|
||||
std::vector<SDOperand> MemOps;
|
||||
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
|
||||
// PtrOff will be used to store the current argument to the stack if a
|
||||
@@ -323,7 +323,7 @@ PPC32TargetLowering::LowerCallTo(SDOperand Chain,
|
||||
SDOperand PtrOff = DAG.getConstant(ArgOffset, getPointerTy());
|
||||
PtrOff = DAG.getNode(ISD::ADD, MVT::i32, StackPtr, PtrOff);
|
||||
MVT::ValueType ArgVT = getValueType(Args[i].second);
|
||||
|
||||
|
||||
switch (ArgVT) {
|
||||
default: assert(0 && "Unexpected ValueType for argument!");
|
||||
case MVT::i1:
|
||||
@@ -351,9 +351,9 @@ PPC32TargetLowering::LowerCallTo(SDOperand Chain,
|
||||
// in it, and store the other half to the stack. If we have two or more
|
||||
// free GPRs, then we can pass both halves of the i64 in registers.
|
||||
if (GPR_remaining > 0) {
|
||||
SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32,
|
||||
SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32,
|
||||
Args[i].first, DAG.getConstant(1, MVT::i32));
|
||||
SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32,
|
||||
SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32,
|
||||
Args[i].first, DAG.getConstant(0, MVT::i32));
|
||||
args_to_use.push_back(Hi);
|
||||
--GPR_remaining;
|
||||
@@ -420,14 +420,14 @@ PPC32TargetLowering::LowerCallTo(SDOperand Chain,
|
||||
if (!MemOps.empty())
|
||||
Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, MemOps);
|
||||
}
|
||||
|
||||
|
||||
std::vector<MVT::ValueType> RetVals;
|
||||
MVT::ValueType RetTyVT = getValueType(RetTy);
|
||||
if (RetTyVT != MVT::isVoid)
|
||||
RetVals.push_back(RetTyVT);
|
||||
RetVals.push_back(MVT::Other);
|
||||
|
||||
SDOperand TheCall = SDOperand(DAG.getCall(RetVals,
|
||||
SDOperand TheCall = SDOperand(DAG.getCall(RetVals,
|
||||
Chain, Callee, args_to_use), 0);
|
||||
Chain = TheCall.getValue(RetTyVT != MVT::isVoid);
|
||||
Chain = DAG.getNode(ISD::ADJCALLSTACKUP, MVT::Other, Chain,
|
||||
@@ -462,7 +462,7 @@ LowerVAArgNext(bool isVANext, SDOperand Chain, SDOperand VAList,
|
||||
}
|
||||
return std::make_pair(Result, Chain);
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::pair<SDOperand, SDOperand> PPC32TargetLowering::
|
||||
LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth,
|
||||
@@ -484,7 +484,7 @@ class ISel : public SelectionDAGISel {
|
||||
SelectionDAG *ISelDAG; // Hack to support us having a dag->dag transform
|
||||
// for sdiv and udiv until it is put into the future
|
||||
// dag combiner.
|
||||
|
||||
|
||||
/// ExprMap - As shared expressions are codegen'd, we keep track of which
|
||||
/// vreg the value is produced in, so we only emit one copy of each compiled
|
||||
/// tree.
|
||||
@@ -496,15 +496,15 @@ class ISel : public SelectionDAGISel {
|
||||
public:
|
||||
ISel(TargetMachine &TM) : SelectionDAGISel(PPC32Lowering), PPC32Lowering(TM),
|
||||
ISelDAG(0) {}
|
||||
|
||||
|
||||
/// runOnFunction - Override this function in order to reset our per-function
|
||||
/// variables.
|
||||
virtual bool runOnFunction(Function &Fn) {
|
||||
// Make sure we re-emit a set of the global base reg if necessary
|
||||
GlobalBaseInitialized = false;
|
||||
return SelectionDAGISel::runOnFunction(Fn);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// InstructionSelectBasicBlock - This callback is invoked by
|
||||
/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
|
||||
virtual void InstructionSelectBasicBlock(SelectionDAG &DAG) {
|
||||
@@ -512,7 +512,7 @@ public:
|
||||
// Codegen the basic block.
|
||||
ISelDAG = &DAG;
|
||||
Select(DAG.getRoot());
|
||||
|
||||
|
||||
// Clear state used for selection.
|
||||
ExprMap.clear();
|
||||
ISelDAG = 0;
|
||||
@@ -521,7 +521,7 @@ public:
|
||||
// dag -> dag expanders for integer divide by constant
|
||||
SDOperand BuildSDIVSequence(SDOperand N);
|
||||
SDOperand BuildUDIVSequence(SDOperand N);
|
||||
|
||||
|
||||
unsigned getGlobalBaseReg();
|
||||
unsigned getConstDouble(double floatVal, unsigned Result);
|
||||
void MoveCRtoGPR(unsigned CCReg, bool Inv, unsigned Idx, unsigned Result);
|
||||
@@ -532,7 +532,7 @@ public:
|
||||
unsigned SelectExpr(SDOperand N, bool Recording=false);
|
||||
unsigned SelectExprFP(SDOperand N, unsigned Result);
|
||||
void Select(SDOperand N);
|
||||
|
||||
|
||||
bool SelectAddr(SDOperand N, unsigned& Reg, int& offset);
|
||||
void SelectBranchCC(SDOperand N);
|
||||
};
|
||||
@@ -555,7 +555,7 @@ static unsigned ExactLog2(unsigned Val) {
|
||||
// not, since all 1's are not contiguous.
|
||||
static bool IsRunOfOnes(unsigned Val, unsigned &MB, unsigned &ME) {
|
||||
bool isRun = true;
|
||||
MB = 0;
|
||||
MB = 0;
|
||||
ME = 0;
|
||||
|
||||
// look for first set bit
|
||||
@@ -567,7 +567,7 @@ static bool IsRunOfOnes(unsigned Val, unsigned &MB, unsigned &ME) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// look for last set bit
|
||||
for (; i < 32; i++) {
|
||||
if ((Val & (1 << (31 - i))) == 0)
|
||||
@@ -580,7 +580,7 @@ static bool IsRunOfOnes(unsigned Val, unsigned &MB, unsigned &ME) {
|
||||
if ((Val & (1 << (31 - i))) != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// if we exhausted all the bits, we found a match at this point for 0*1*0*
|
||||
if (i == 32)
|
||||
return true;
|
||||
@@ -596,7 +596,7 @@ static bool IsRunOfOnes(unsigned Val, unsigned &MB, unsigned &ME) {
|
||||
if ((Val & (1 << (31 - i))) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// if we exhausted all the bits, then we found a match for 1*0*1*, otherwise,
|
||||
// the value is not a run of ones.
|
||||
if (i == 32)
|
||||
@@ -620,7 +620,7 @@ static unsigned getImmediateForOpcode(SDOperand N, unsigned Opcode,
|
||||
if (N.getOpcode() != ISD::Constant) return 0;
|
||||
|
||||
int v = (int)cast<ConstantSDNode>(N)->getSignExtended();
|
||||
|
||||
|
||||
switch(Opcode) {
|
||||
default: return 0;
|
||||
case ISD::ADD:
|
||||
@@ -666,7 +666,7 @@ static bool NodeHasRecordingVariant(unsigned NodeOpcode) {
|
||||
switch(NodeOpcode) {
|
||||
default: return false;
|
||||
case ISD::AND:
|
||||
case ISD::OR:
|
||||
case ISD::OR:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -715,7 +715,7 @@ static unsigned getCROpForSetCC(unsigned Opcode, bool Inv1, bool Inv2) {
|
||||
static unsigned getCRIdxForSetCC(unsigned Condition, bool& Inv) {
|
||||
switch (Condition) {
|
||||
default: assert(0 && "Unknown condition!"); abort();
|
||||
case ISD::SETULT:
|
||||
case ISD::SETULT:
|
||||
case ISD::SETLT: Inv = false; return 0;
|
||||
case ISD::SETUGE:
|
||||
case ISD::SETGE: Inv = true; return 0;
|
||||
@@ -744,7 +744,7 @@ static unsigned IndexedOpForOp(unsigned Opcode) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Structure used to return the necessary information to codegen an SDIV as
|
||||
// Structure used to return the necessary information to codegen an SDIV as
|
||||
// a multiply.
|
||||
struct ms {
|
||||
int m; // magic number
|
||||
@@ -758,14 +758,14 @@ struct mu {
|
||||
};
|
||||
|
||||
/// magic - calculate the magic numbers required to codegen an integer sdiv as
|
||||
/// a sequence of multiply and shifts. Requires that the divisor not be 0, 1,
|
||||
/// a sequence of multiply and shifts. Requires that the divisor not be 0, 1,
|
||||
/// or -1.
|
||||
static struct ms magic(int d) {
|
||||
int p;
|
||||
unsigned int ad, anc, delta, q1, r1, q2, r2, t;
|
||||
const unsigned int two31 = 2147483648U; // 2^31
|
||||
struct ms mag;
|
||||
|
||||
|
||||
ad = abs(d);
|
||||
t = two31 + ((unsigned int)d >> 31);
|
||||
anc = t - 1 - t%ad; // absolute value of nc
|
||||
@@ -847,7 +847,7 @@ SDOperand ISel::BuildSDIVSequence(SDOperand N) {
|
||||
int d = (int)cast<ConstantSDNode>(N.getOperand(1))->getSignExtended();
|
||||
ms magics = magic(d);
|
||||
// Multiply the numerator (operand 0) by the magic value
|
||||
SDOperand Q = ISelDAG->getNode(ISD::MULHS, MVT::i32, N.getOperand(0),
|
||||
SDOperand Q = ISelDAG->getNode(ISD::MULHS, MVT::i32, N.getOperand(0),
|
||||
ISelDAG->getConstant(magics.m, MVT::i32));
|
||||
// If d > 0 and m < 0, add the numerator
|
||||
if (d > 0 && magics.m < 0)
|
||||
@@ -857,10 +857,10 @@ SDOperand ISel::BuildSDIVSequence(SDOperand N) {
|
||||
Q = ISelDAG->getNode(ISD::SUB, MVT::i32, Q, N.getOperand(0));
|
||||
// Shift right algebraic if shift value is nonzero
|
||||
if (magics.s > 0)
|
||||
Q = ISelDAG->getNode(ISD::SRA, MVT::i32, Q,
|
||||
Q = ISelDAG->getNode(ISD::SRA, MVT::i32, Q,
|
||||
ISelDAG->getConstant(magics.s, MVT::i32));
|
||||
// Extract the sign bit and add it to the quotient
|
||||
SDOperand T =
|
||||
SDOperand T =
|
||||
ISelDAG->getNode(ISD::SRL, MVT::i32, Q, ISelDAG->getConstant(31, MVT::i32));
|
||||
return ISelDAG->getNode(ISD::ADD, MVT::i32, Q, T);
|
||||
}
|
||||
@@ -870,21 +870,21 @@ SDOperand ISel::BuildSDIVSequence(SDOperand N) {
|
||||
/// multiplying by a magic number. See:
|
||||
/// <http://the.wall.riscom.net/books/proc/ppc/cwg/code2.html>
|
||||
SDOperand ISel::BuildUDIVSequence(SDOperand N) {
|
||||
unsigned d =
|
||||
unsigned d =
|
||||
(unsigned)cast<ConstantSDNode>(N.getOperand(1))->getSignExtended();
|
||||
mu magics = magicu(d);
|
||||
// Multiply the numerator (operand 0) by the magic value
|
||||
SDOperand Q = ISelDAG->getNode(ISD::MULHU, MVT::i32, N.getOperand(0),
|
||||
SDOperand Q = ISelDAG->getNode(ISD::MULHU, MVT::i32, N.getOperand(0),
|
||||
ISelDAG->getConstant(magics.m, MVT::i32));
|
||||
if (magics.a == 0) {
|
||||
Q = ISelDAG->getNode(ISD::SRL, MVT::i32, Q,
|
||||
Q = ISelDAG->getNode(ISD::SRL, MVT::i32, Q,
|
||||
ISelDAG->getConstant(magics.s, MVT::i32));
|
||||
} else {
|
||||
SDOperand NPQ = ISelDAG->getNode(ISD::SUB, MVT::i32, N.getOperand(0), Q);
|
||||
NPQ = ISelDAG->getNode(ISD::SRL, MVT::i32, NPQ,
|
||||
NPQ = ISelDAG->getNode(ISD::SRL, MVT::i32, NPQ,
|
||||
ISelDAG->getConstant(1, MVT::i32));
|
||||
NPQ = ISelDAG->getNode(ISD::ADD, MVT::i32, NPQ, Q);
|
||||
Q = ISelDAG->getNode(ISD::SRL, MVT::i32, NPQ,
|
||||
Q = ISelDAG->getNode(ISD::SRL, MVT::i32, NPQ,
|
||||
ISelDAG->getConstant(magics.s-1, MVT::i32));
|
||||
}
|
||||
return Q;
|
||||
@@ -906,7 +906,7 @@ unsigned ISel::getGlobalBaseReg() {
|
||||
return GlobalBaseReg;
|
||||
}
|
||||
|
||||
/// getConstDouble - Loads a floating point value into a register, via the
|
||||
/// getConstDouble - Loads a floating point value into a register, via the
|
||||
/// Constant Pool. Optionally takes a register in which to load the value.
|
||||
unsigned ISel::getConstDouble(double doubleVal, unsigned Result=0) {
|
||||
unsigned Tmp1 = MakeReg(MVT::i32);
|
||||
@@ -920,7 +920,7 @@ unsigned ISel::getConstDouble(double doubleVal, unsigned Result=0) {
|
||||
return Result;
|
||||
}
|
||||
|
||||
/// MoveCRtoGPR - Move CCReg[Idx] to the least significant bit of Result. If
|
||||
/// MoveCRtoGPR - Move CCReg[Idx] to the least significant bit of Result. If
|
||||
/// Inv is true, then invert the result.
|
||||
void ISel::MoveCRtoGPR(unsigned CCReg, bool Inv, unsigned Idx, unsigned Result){
|
||||
unsigned IntCR = MakeReg(MVT::i32);
|
||||
@@ -937,7 +937,7 @@ void ISel::MoveCRtoGPR(unsigned CCReg, bool Inv, unsigned Idx, unsigned Result){
|
||||
}
|
||||
}
|
||||
|
||||
/// SelectBitfieldInsert - turn an or of two masked values into
|
||||
/// SelectBitfieldInsert - turn an or of two masked values into
|
||||
/// the rotate left word immediate then mask insert (rlwimi) instruction.
|
||||
/// Returns true on success, false if the caller still needs to select OR.
|
||||
///
|
||||
@@ -951,15 +951,15 @@ bool ISel::SelectBitfieldInsert(SDOperand OR, unsigned Result) {
|
||||
unsigned TgtMask = 0xFFFFFFFF, InsMask = 0xFFFFFFFF, Amount = 0;
|
||||
unsigned Op0Opc = OR.getOperand(0).getOpcode();
|
||||
unsigned Op1Opc = OR.getOperand(1).getOpcode();
|
||||
|
||||
|
||||
// Verify that we have the correct opcodes
|
||||
if (ISD::SHL != Op0Opc && ISD::SRL != Op0Opc && ISD::AND != Op0Opc)
|
||||
return false;
|
||||
if (ISD::SHL != Op1Opc && ISD::SRL != Op1Opc && ISD::AND != Op1Opc)
|
||||
return false;
|
||||
|
||||
|
||||
// Generate Mask value for Target
|
||||
if (ConstantSDNode *CN =
|
||||
if (ConstantSDNode *CN =
|
||||
dyn_cast<ConstantSDNode>(OR.getOperand(0).getOperand(1).Val)) {
|
||||
switch(Op0Opc) {
|
||||
case ISD::SHL: TgtMask <<= (unsigned)CN->getValue(); break;
|
||||
@@ -969,30 +969,30 @@ bool ISel::SelectBitfieldInsert(SDOperand OR, unsigned Result) {
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Generate Mask value for Insert
|
||||
if (ConstantSDNode *CN =
|
||||
if (ConstantSDNode *CN =
|
||||
dyn_cast<ConstantSDNode>(OR.getOperand(1).getOperand(1).Val)) {
|
||||
switch(Op1Opc) {
|
||||
case ISD::SHL:
|
||||
Amount = CN->getValue();
|
||||
case ISD::SHL:
|
||||
Amount = CN->getValue();
|
||||
InsMask <<= Amount;
|
||||
if (Op0Opc == ISD::SRL) IsRotate = true;
|
||||
break;
|
||||
case ISD::SRL:
|
||||
Amount = CN->getValue();
|
||||
InsMask >>= Amount;
|
||||
case ISD::SRL:
|
||||
Amount = CN->getValue();
|
||||
InsMask >>= Amount;
|
||||
Amount = 32-Amount;
|
||||
if (Op0Opc == ISD::SHL) IsRotate = true;
|
||||
break;
|
||||
case ISD::AND:
|
||||
case ISD::AND:
|
||||
InsMask &= (unsigned)CN->getValue();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Verify that the Target mask and Insert mask together form a full word mask
|
||||
// and that the Insert mask is a run of set bits (which implies both are runs
|
||||
// of set bits). Given that, Select the arguments and generate the rlwimi
|
||||
@@ -1002,7 +1002,7 @@ bool ISel::SelectBitfieldInsert(SDOperand OR, unsigned Result) {
|
||||
unsigned Tmp1, Tmp2;
|
||||
// Check for rotlwi / rotrwi here, a special case of bitfield insert
|
||||
// where both bitfield halves are sourced from the same value.
|
||||
if (IsRotate &&
|
||||
if (IsRotate &&
|
||||
OR.getOperand(0).getOperand(0) == OR.getOperand(1).getOperand(0)) {
|
||||
Tmp1 = SelectExpr(OR.getOperand(0).getOperand(0));
|
||||
BuildMI(BB, PPC::RLWINM, 4, Result).addReg(Tmp1).addImm(Amount)
|
||||
@@ -1039,12 +1039,12 @@ unsigned ISel::FoldIfWideZeroExtend(SDOperand N) {
|
||||
unsigned ISel::SelectCC(SDOperand CC, unsigned& Opc, bool &Inv, unsigned& Idx) {
|
||||
unsigned Result, Tmp1, Tmp2;
|
||||
bool AlreadySelected = false;
|
||||
static const unsigned CompareOpcodes[] =
|
||||
static const unsigned CompareOpcodes[] =
|
||||
{ PPC::FCMPU, PPC::FCMPU, PPC::CMPW, PPC::CMPLW };
|
||||
|
||||
|
||||
// Allocate a condition register for this expression
|
||||
Result = RegMap->createVirtualRegister(PPC32::CRRCRegisterClass);
|
||||
|
||||
|
||||
// If the first operand to the select is a SETCC node, then we can fold it
|
||||
// into the branch that selects which value to return.
|
||||
if (SetCCSDNode* SetCC = dyn_cast<SetCCSDNode>(CC.Val)) {
|
||||
@@ -1054,12 +1054,12 @@ unsigned ISel::SelectCC(SDOperand CC, unsigned& Opc, bool &Inv, unsigned& Idx) {
|
||||
|
||||
// Pass the optional argument U to getImmediateForOpcode for SETCC,
|
||||
// so that it knows whether the SETCC immediate range is signed or not.
|
||||
if (1 == getImmediateForOpcode(SetCC->getOperand(1), ISD::SETCC,
|
||||
if (1 == getImmediateForOpcode(SetCC->getOperand(1), ISD::SETCC,
|
||||
Tmp2, U)) {
|
||||
// For comparisons against zero, we can implicity set CR0 if a recording
|
||||
// For comparisons against zero, we can implicity set CR0 if a recording
|
||||
// variant (e.g. 'or.' instead of 'or') of the instruction that defines
|
||||
// operand zero of the SetCC node is available.
|
||||
if (0 == Tmp2 &&
|
||||
if (0 == Tmp2 &&
|
||||
NodeHasRecordingVariant(SetCC->getOperand(0).getOpcode()) &&
|
||||
SetCC->getOperand(0).Val->hasOneUse()) {
|
||||
RecordSuccess = false;
|
||||
@@ -1098,7 +1098,7 @@ unsigned ISel::SelectCC(SDOperand CC, unsigned& Opc, bool &Inv, unsigned& Idx) {
|
||||
return Result;
|
||||
}
|
||||
|
||||
unsigned ISel::SelectCCExpr(SDOperand N, unsigned& Opc, bool &Inv,
|
||||
unsigned ISel::SelectCCExpr(SDOperand N, unsigned& Opc, bool &Inv,
|
||||
unsigned &Idx) {
|
||||
bool Inv0, Inv1;
|
||||
unsigned Idx0, Idx1, CROpc, Opc1, Tmp1, Tmp2;
|
||||
@@ -1148,7 +1148,7 @@ bool ISel::SelectAddr(SDOperand N, unsigned& Reg, int& offset)
|
||||
if (1 == getImmediateForOpcode(N.getOperand(1), opcode, imm)) {
|
||||
offset = imm;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
offset = SelectExpr(N.getOperand(1));
|
||||
return true;
|
||||
}
|
||||
@@ -1159,14 +1159,14 @@ bool ISel::SelectAddr(SDOperand N, unsigned& Reg, int& offset)
|
||||
|
||||
void ISel::SelectBranchCC(SDOperand N)
|
||||
{
|
||||
MachineBasicBlock *Dest =
|
||||
MachineBasicBlock *Dest =
|
||||
cast<BasicBlockSDNode>(N.getOperand(2))->getBasicBlock();
|
||||
|
||||
bool Inv;
|
||||
unsigned Opc, CCReg, Idx;
|
||||
Select(N.getOperand(0)); //chain
|
||||
CCReg = SelectCC(N.getOperand(1), Opc, Inv, Idx);
|
||||
|
||||
|
||||
// Iterate to the next basic block, unless we're already at the end of the
|
||||
ilist<MachineBasicBlock>::iterator It = BB, E = BB->getParent()->end();
|
||||
if (++It == E) It = BB;
|
||||
@@ -1176,7 +1176,7 @@ void ISel::SelectBranchCC(SDOperand N)
|
||||
// if necessary by the branch selection pass. Otherwise, emit a standard
|
||||
// conditional branch.
|
||||
if (N.getOpcode() == ISD::BRCONDTWOWAY) {
|
||||
MachineBasicBlock *Fallthrough =
|
||||
MachineBasicBlock *Fallthrough =
|
||||
cast<BasicBlockSDNode>(N.getOperand(3))->getBasicBlock();
|
||||
if (Dest != It) {
|
||||
BuildMI(BB, PPC::COND_BRANCH, 4).addReg(CCReg).addImm(Opc)
|
||||
@@ -1221,7 +1221,7 @@ unsigned ISel::SelectExprFP(SDOperand N, unsigned Result)
|
||||
MVT::ValueType VT = SetCC->getOperand(0).getValueType();
|
||||
unsigned TV = SelectExpr(N.getOperand(1)); // Use if TRUE
|
||||
unsigned FV = SelectExpr(N.getOperand(2)); // Use if FALSE
|
||||
|
||||
|
||||
ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(SetCC->getOperand(1));
|
||||
if (CN && (CN->isExactlyValue(-0.0) || CN->isExactlyValue(0.0))) {
|
||||
switch(SetCC->getCondition()) {
|
||||
@@ -1282,13 +1282,13 @@ unsigned ISel::SelectExprFP(SDOperand N, unsigned Result)
|
||||
assert(0 && "Should never get here");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool Inv;
|
||||
unsigned TrueValue = SelectExpr(N.getOperand(1)); //Use if TRUE
|
||||
unsigned FalseValue = SelectExpr(N.getOperand(2)); //Use if FALSE
|
||||
unsigned CCReg = SelectCC(N.getOperand(0), Opc, Inv, Tmp3);
|
||||
|
||||
// Create an iterator with which to insert the MBB for copying the false
|
||||
// Create an iterator with which to insert the MBB for copying the false
|
||||
// value and the MBB to hold the PHI instruction for this SetCC.
|
||||
MachineBasicBlock *thisMBB = BB;
|
||||
const BasicBlock *LLVM_BB = BB->getBasicBlock();
|
||||
@@ -1328,7 +1328,7 @@ unsigned ISel::SelectExprFP(SDOperand N, unsigned Result)
|
||||
}
|
||||
|
||||
case ISD::FNEG:
|
||||
if (!NoExcessFPPrecision &&
|
||||
if (!NoExcessFPPrecision &&
|
||||
ISD::ADD == N.getOperand(0).getOpcode() &&
|
||||
N.getOperand(0).Val->hasOneUse() &&
|
||||
ISD::MUL == N.getOperand(0).getOperand(0).getOpcode() &&
|
||||
@@ -1339,7 +1339,7 @@ unsigned ISel::SelectExprFP(SDOperand N, unsigned Result)
|
||||
Tmp3 = SelectExpr(N.getOperand(0).getOperand(1));
|
||||
Opc = DestType == MVT::f64 ? PPC::FNMADD : PPC::FNMADDS;
|
||||
BuildMI(BB, Opc, 3, Result).addReg(Tmp1).addReg(Tmp2).addReg(Tmp3);
|
||||
} else if (!NoExcessFPPrecision &&
|
||||
} else if (!NoExcessFPPrecision &&
|
||||
ISD::ADD == N.getOperand(0).getOpcode() &&
|
||||
N.getOperand(0).Val->hasOneUse() &&
|
||||
ISD::MUL == N.getOperand(0).getOperand(1).getOpcode() &&
|
||||
@@ -1358,23 +1358,23 @@ unsigned ISel::SelectExprFP(SDOperand N, unsigned Result)
|
||||
BuildMI(BB, PPC::FNEG, 1, Result).addReg(Tmp1);
|
||||
}
|
||||
return Result;
|
||||
|
||||
|
||||
case ISD::FABS:
|
||||
Tmp1 = SelectExpr(N.getOperand(0));
|
||||
BuildMI(BB, PPC::FABS, 1, Result).addReg(Tmp1);
|
||||
return Result;
|
||||
|
||||
case ISD::FP_ROUND:
|
||||
assert (DestType == MVT::f32 &&
|
||||
N.getOperand(0).getValueType() == MVT::f64 &&
|
||||
assert (DestType == MVT::f32 &&
|
||||
N.getOperand(0).getValueType() == MVT::f64 &&
|
||||
"only f64 to f32 conversion supported here");
|
||||
Tmp1 = SelectExpr(N.getOperand(0));
|
||||
BuildMI(BB, PPC::FRSP, 1, Result).addReg(Tmp1);
|
||||
return Result;
|
||||
|
||||
case ISD::FP_EXTEND:
|
||||
assert (DestType == MVT::f64 &&
|
||||
N.getOperand(0).getValueType() == MVT::f32 &&
|
||||
assert (DestType == MVT::f64 &&
|
||||
N.getOperand(0).getValueType() == MVT::f32 &&
|
||||
"only f32 to f64 conversion supported here");
|
||||
Tmp1 = SelectExpr(N.getOperand(0));
|
||||
BuildMI(BB, PPC::FMR, 1, Result).addReg(Tmp1);
|
||||
@@ -1386,13 +1386,13 @@ unsigned ISel::SelectExprFP(SDOperand N, unsigned Result)
|
||||
Tmp1 = dyn_cast<RegSDNode>(Node)->getReg();
|
||||
BuildMI(BB, PPC::FMR, 1, Result).addReg(Tmp1);
|
||||
return Result;
|
||||
|
||||
|
||||
case ISD::ConstantFP: {
|
||||
ConstantFPSDNode *CN = cast<ConstantFPSDNode>(N);
|
||||
Result = getConstDouble(CN->getValue(), Result);
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
case ISD::ADD:
|
||||
if (!NoExcessFPPrecision && N.getOperand(0).getOpcode() == ISD::MUL &&
|
||||
N.getOperand(0).Val->hasOneUse()) {
|
||||
@@ -1460,16 +1460,16 @@ unsigned ISel::SelectExprFP(SDOperand N, unsigned Result)
|
||||
|
||||
case ISD::UINT_TO_FP:
|
||||
case ISD::SINT_TO_FP: {
|
||||
assert (N.getOperand(0).getValueType() == MVT::i32
|
||||
assert (N.getOperand(0).getValueType() == MVT::i32
|
||||
&& "int to float must operate on i32");
|
||||
bool IsUnsigned = (ISD::UINT_TO_FP == opcode);
|
||||
Tmp1 = SelectExpr(N.getOperand(0)); // Get the operand register
|
||||
Tmp2 = MakeReg(MVT::f64); // temp reg to load the integer value into
|
||||
Tmp3 = MakeReg(MVT::i32); // temp reg to hold the conversion constant
|
||||
|
||||
|
||||
int FrameIdx = BB->getParent()->getFrameInfo()->CreateStackObject(8, 8);
|
||||
MachineConstantPool *CP = BB->getParent()->getConstantPool();
|
||||
|
||||
|
||||
if (IsUnsigned) {
|
||||
unsigned ConstF = getConstDouble(0x1.000000p52);
|
||||
// Store the hi & low halves of the fp value, currently in int regs
|
||||
@@ -1542,9 +1542,9 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
|
||||
|
||||
if (ISD::CopyFromReg == opcode)
|
||||
DestType = N.getValue(0).getValueType();
|
||||
|
||||
|
||||
if (DestType == MVT::f64 || DestType == MVT::f32)
|
||||
if (ISD::LOAD != opcode && ISD::EXTLOAD != opcode &&
|
||||
if (ISD::LOAD != opcode && ISD::EXTLOAD != opcode &&
|
||||
ISD::UNDEF != opcode && ISD::CALL != opcode)
|
||||
return SelectExprFP(N, Result);
|
||||
|
||||
@@ -1591,7 +1591,7 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
|
||||
Tmp1 = cast<FrameIndexSDNode>(N)->getIndex();
|
||||
addFrameReference(BuildMI(BB, PPC::ADDI, 2, Result), (int)Tmp1, 0, false);
|
||||
return Result;
|
||||
|
||||
|
||||
case ISD::GlobalAddress: {
|
||||
GlobalValue *GV = cast<GlobalAddressSDNode>(N)->getGlobal();
|
||||
Tmp1 = MakeReg(MVT::i32);
|
||||
@@ -1612,7 +1612,7 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
|
||||
MVT::ValueType TypeBeingLoaded = (ISD::LOAD == opcode) ?
|
||||
Node->getValueType(0) : cast<MVTSDNode>(Node)->getExtraValueType();
|
||||
bool sext = (ISD::SEXTLOAD == opcode);
|
||||
|
||||
|
||||
// Make sure we generate both values.
|
||||
if (Result != 1)
|
||||
ExprMap[N.getValue(1)] = 1; // Generate the token
|
||||
@@ -1632,7 +1632,7 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
|
||||
case MVT::f32: Opc = PPC::LFS; break;
|
||||
case MVT::f64: Opc = PPC::LFD; break;
|
||||
}
|
||||
|
||||
|
||||
if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Address)) {
|
||||
Tmp1 = MakeReg(MVT::i32);
|
||||
int CPI = CP->getIndex();
|
||||
@@ -1655,10 +1655,10 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
case ISD::CALL: {
|
||||
unsigned GPR_idx = 0, FPR_idx = 0;
|
||||
static const unsigned GPR[] = {
|
||||
static const unsigned GPR[] = {
|
||||
PPC::R3, PPC::R4, PPC::R5, PPC::R6,
|
||||
PPC::R7, PPC::R8, PPC::R9, PPC::R10,
|
||||
};
|
||||
@@ -1673,13 +1673,13 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
|
||||
|
||||
MachineInstr *CallMI;
|
||||
// Emit the correct call instruction based on the type of symbol called.
|
||||
if (GlobalAddressSDNode *GASD =
|
||||
if (GlobalAddressSDNode *GASD =
|
||||
dyn_cast<GlobalAddressSDNode>(N.getOperand(1))) {
|
||||
CallMI = BuildMI(PPC::CALLpcrel, 1).addGlobalAddress(GASD->getGlobal(),
|
||||
CallMI = BuildMI(PPC::CALLpcrel, 1).addGlobalAddress(GASD->getGlobal(),
|
||||
true);
|
||||
} else if (ExternalSymbolSDNode *ESSDN =
|
||||
} else if (ExternalSymbolSDNode *ESSDN =
|
||||
dyn_cast<ExternalSymbolSDNode>(N.getOperand(1))) {
|
||||
CallMI = BuildMI(PPC::CALLpcrel, 1).addExternalSymbol(ESSDN->getSymbol(),
|
||||
CallMI = BuildMI(PPC::CALLpcrel, 1).addExternalSymbol(ESSDN->getSymbol(),
|
||||
true);
|
||||
} else {
|
||||
Tmp1 = SelectExpr(N.getOperand(1));
|
||||
@@ -1688,7 +1688,7 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
|
||||
CallMI = BuildMI(PPC::CALLindirect, 3).addImm(20).addImm(0)
|
||||
.addReg(PPC::R12);
|
||||
}
|
||||
|
||||
|
||||
// Load the register args to virtual regs
|
||||
std::vector<unsigned> ArgVR;
|
||||
for(int i = 2, e = Node->getNumOperands(); i < e; ++i)
|
||||
@@ -1718,7 +1718,7 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Put the call instruction in the correct place in the MachineBasicBlock
|
||||
BB->push_back(CallMI);
|
||||
|
||||
@@ -1750,17 +1750,17 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
|
||||
switch(cast<MVTSDNode>(Node)->getExtraValueType()) {
|
||||
default: Node->dump(); assert(0 && "Unhandled SIGN_EXTEND type"); break;
|
||||
case MVT::i16:
|
||||
BuildMI(BB, PPC::EXTSH, 1, Result).addReg(Tmp1);
|
||||
BuildMI(BB, PPC::EXTSH, 1, Result).addReg(Tmp1);
|
||||
break;
|
||||
case MVT::i8:
|
||||
BuildMI(BB, PPC::EXTSB, 1, Result).addReg(Tmp1);
|
||||
BuildMI(BB, PPC::EXTSB, 1, Result).addReg(Tmp1);
|
||||
break;
|
||||
case MVT::i1:
|
||||
BuildMI(BB, PPC::SUBFIC, 2, Result).addReg(Tmp1).addSImm(0);
|
||||
break;
|
||||
}
|
||||
return Result;
|
||||
|
||||
|
||||
case ISD::CopyFromReg:
|
||||
if (Result == 1)
|
||||
Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
|
||||
@@ -1779,7 +1779,7 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
|
||||
BuildMI(BB, PPC::SLW, 2, Result).addReg(Tmp1).addReg(Tmp2);
|
||||
}
|
||||
return Result;
|
||||
|
||||
|
||||
case ISD::SRL:
|
||||
Tmp1 = SelectExpr(N.getOperand(0));
|
||||
if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
|
||||
@@ -1791,7 +1791,7 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
|
||||
BuildMI(BB, PPC::SRW, 2, Result).addReg(Tmp1).addReg(Tmp2);
|
||||
}
|
||||
return Result;
|
||||
|
||||
|
||||
case ISD::SRA:
|
||||
Tmp1 = SelectExpr(N.getOperand(0));
|
||||
if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
|
||||
@@ -1802,7 +1802,7 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
|
||||
BuildMI(BB, PPC::SRAW, 2, Result).addReg(Tmp1).addReg(Tmp2);
|
||||
}
|
||||
return Result;
|
||||
|
||||
|
||||
case ISD::ADD:
|
||||
assert (DestType == MVT::i32 && "Only do arithmetic on i32s!");
|
||||
Tmp1 = SelectExpr(N.getOperand(0));
|
||||
@@ -1823,7 +1823,7 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
|
||||
|
||||
case ISD::AND:
|
||||
if (PPCCRopts) {
|
||||
if (N.getOperand(0).getOpcode() == ISD::SETCC ||
|
||||
if (N.getOperand(0).getOpcode() == ISD::SETCC ||
|
||||
N.getOperand(1).getOpcode() == ISD::SETCC) {
|
||||
bool Inv;
|
||||
Tmp1 = SelectCCExpr(N, Opc, Inv, Tmp2);
|
||||
@@ -1858,12 +1858,12 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
|
||||
}
|
||||
RecordSuccess = true;
|
||||
return Result;
|
||||
|
||||
|
||||
case ISD::OR:
|
||||
if (SelectBitfieldInsert(N, Result))
|
||||
return Result;
|
||||
if (PPCCRopts) {
|
||||
if (N.getOperand(0).getOpcode() == ISD::SETCC ||
|
||||
if (N.getOperand(0).getOpcode() == ISD::SETCC ||
|
||||
N.getOperand(1).getOpcode() == ISD::SETCC) {
|
||||
bool Inv;
|
||||
Tmp1 = SelectCCExpr(N, Opc, Inv, Tmp2);
|
||||
@@ -1951,7 +1951,7 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
|
||||
BuildMI(BB, PPC::SUBF, 2, Result).addReg(Tmp2).addReg(Tmp1);
|
||||
}
|
||||
return Result;
|
||||
|
||||
|
||||
case ISD::MUL:
|
||||
Tmp1 = SelectExpr(N.getOperand(0));
|
||||
if (1 == getImmediateForOpcode(N.getOperand(1), opcode, Tmp2))
|
||||
@@ -1992,7 +1992,7 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
|
||||
// constants to implement it as a multiply instead.
|
||||
case 4:
|
||||
ExprMap.erase(N);
|
||||
if (opcode == ISD::SDIV)
|
||||
if (opcode == ISD::SDIV)
|
||||
return SelectExpr(BuildSDIVSequence(N));
|
||||
else
|
||||
return SelectExpr(BuildUDIVSequence(N));
|
||||
@@ -2080,7 +2080,7 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
|
||||
}
|
||||
return Result+N.ResNo;
|
||||
}
|
||||
|
||||
|
||||
case ISD::FP_TO_UINT:
|
||||
case ISD::FP_TO_SINT: {
|
||||
bool U = (ISD::FP_TO_UINT == opcode);
|
||||
@@ -2151,10 +2151,10 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
|
||||
assert(0 && "Should never get here");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
case ISD::SETCC:
|
||||
if (SetCCSDNode *SetCC = dyn_cast<SetCCSDNode>(Node)) {
|
||||
if (ConstantSDNode *CN =
|
||||
if (ConstantSDNode *CN =
|
||||
dyn_cast<ConstantSDNode>(SetCC->getOperand(1).Val)) {
|
||||
// We can codegen setcc op, imm very efficiently compared to a brcond.
|
||||
// Check for those cases here.
|
||||
@@ -2226,7 +2226,7 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Inv;
|
||||
unsigned CCReg = SelectCC(N, Opc, Inv, Tmp2);
|
||||
MoveCRtoGPR(CCReg, Inv, Tmp2, Result);
|
||||
@@ -2234,14 +2234,14 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
|
||||
}
|
||||
assert(0 && "Is this legal?");
|
||||
return 0;
|
||||
|
||||
|
||||
case ISD::SELECT: {
|
||||
bool Inv;
|
||||
unsigned TrueValue = SelectExpr(N.getOperand(1)); //Use if TRUE
|
||||
unsigned FalseValue = SelectExpr(N.getOperand(2)); //Use if FALSE
|
||||
unsigned CCReg = SelectCC(N.getOperand(0), Opc, Inv, Tmp3);
|
||||
|
||||
// Create an iterator with which to insert the MBB for copying the false
|
||||
// Create an iterator with which to insert the MBB for copying the false
|
||||
// value and the MBB to hold the PHI instruction for this SetCC.
|
||||
MachineBasicBlock *thisMBB = BB;
|
||||
const BasicBlock *LLVM_BB = BB->getBasicBlock();
|
||||
@@ -2313,7 +2313,7 @@ void ISel::Select(SDOperand N) {
|
||||
return; // Already selected.
|
||||
|
||||
SDNode *Node = N.Val;
|
||||
|
||||
|
||||
switch (Node->getOpcode()) {
|
||||
default:
|
||||
Node->dump(); std::cerr << "\n";
|
||||
@@ -2338,7 +2338,7 @@ void ISel::Select(SDOperand N) {
|
||||
BuildMI(BB, PPC::B, 1).addMBB(Dest);
|
||||
return;
|
||||
}
|
||||
case ISD::BRCOND:
|
||||
case ISD::BRCOND:
|
||||
case ISD::BRCONDTWOWAY:
|
||||
SelectBranchCC(N);
|
||||
return;
|
||||
@@ -2346,9 +2346,9 @@ void ISel::Select(SDOperand N) {
|
||||
Select(N.getOperand(0));
|
||||
Tmp1 = SelectExpr(N.getOperand(1));
|
||||
Tmp2 = cast<RegSDNode>(N)->getReg();
|
||||
|
||||
|
||||
if (Tmp1 != Tmp2) {
|
||||
if (N.getOperand(1).getValueType() == MVT::f64 ||
|
||||
if (N.getOperand(1).getValueType() == MVT::f64 ||
|
||||
N.getOperand(1).getValueType() == MVT::f32)
|
||||
BuildMI(BB, PPC::FMR, 1, Tmp2).addReg(Tmp1);
|
||||
else
|
||||
@@ -2393,8 +2393,8 @@ void ISel::Select(SDOperand N) {
|
||||
}
|
||||
BuildMI(BB, PPC::BLR, 0); // Just emit a 'ret' instruction
|
||||
return;
|
||||
case ISD::TRUNCSTORE:
|
||||
case ISD::STORE:
|
||||
case ISD::TRUNCSTORE:
|
||||
case ISD::STORE:
|
||||
{
|
||||
SDOperand Chain = N.getOperand(0);
|
||||
SDOperand Value = N.getOperand(1);
|
||||
@@ -2428,7 +2428,7 @@ void ISel::Select(SDOperand N) {
|
||||
{
|
||||
int offset;
|
||||
bool idx = SelectAddr(Address, Tmp2, offset);
|
||||
if (idx) {
|
||||
if (idx) {
|
||||
Opc = IndexedOpForOp(Opc);
|
||||
BuildMI(BB, Opc, 3).addReg(Tmp1).addReg(Tmp2).addReg(offset);
|
||||
} else {
|
||||
@@ -2457,6 +2457,6 @@ void ISel::Select(SDOperand N) {
|
||||
/// description file.
|
||||
///
|
||||
FunctionPass *llvm::createPPC32ISelPattern(TargetMachine &TM) {
|
||||
return new ISel(TM);
|
||||
return new ISel(TM);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===-- PowerPCInstrBuilder.h - Aides for building PPC insts ----*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file exposes functions that may be used with BuildMI from the
|
||||
@@ -30,7 +30,7 @@ namespace llvm {
|
||||
/// This allows a constant offset to be specified as well...
|
||||
///
|
||||
inline const MachineInstrBuilder&
|
||||
addFrameReference(const MachineInstrBuilder &MIB, int FI, int Offset = 0,
|
||||
addFrameReference(const MachineInstrBuilder &MIB, int FI, int Offset = 0,
|
||||
bool mem = true) {
|
||||
if (mem)
|
||||
return MIB.addSImm(Offset).addFrameIndex(FI);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===- PPC32InstrInfo.cpp - PowerPC32 Instruction Information ---*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the PowerPC implementation of the TargetInstrInfo class.
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===- PPC32InstrInfo.h - PowerPC32 Instruction Information -----*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the PowerPC implementation of the TargetInstrInfo class.
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
case PPC::BGE: return PPC::BLT;
|
||||
case PPC::BGT: return PPC::BLE;
|
||||
case PPC::BLE: return PPC::BGT;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===-- PPC32JITInfo.cpp - Implement the JIT interfaces for the PowerPC ---===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements the JIT interfaces for the 32-bit PowerPC target.
|
||||
@@ -66,9 +66,9 @@ asm(
|
||||
"stw r11, 280(r1)\n" // Set up a proper stack frame
|
||||
"stmw r3, 156(r1)\n" // Save all of the integer registers
|
||||
// Save all call-clobbered FP regs.
|
||||
"stfd f1, 44(r1)\n" "stfd f2, 52(r1)\n" "stfd f3, 60(r1)\n"
|
||||
"stfd f4, 68(r1)\n" "stfd f5, 76(r1)\n" "stfd f6, 84(r1)\n"
|
||||
"stfd f7, 92(r1)\n" "stfd f8, 100(r1)\n" "stfd f9, 108(r1)\n"
|
||||
"stfd f1, 44(r1)\n" "stfd f2, 52(r1)\n" "stfd f3, 60(r1)\n"
|
||||
"stfd f4, 68(r1)\n" "stfd f5, 76(r1)\n" "stfd f6, 84(r1)\n"
|
||||
"stfd f7, 92(r1)\n" "stfd f8, 100(r1)\n" "stfd f9, 108(r1)\n"
|
||||
"stfd f10, 116(r1)\n" "stfd f11, 124(r1)\n" "stfd f12, 132(r1)\n"
|
||||
"stfd f13, 140(r1)\n"
|
||||
|
||||
@@ -112,7 +112,7 @@ extern "C" void PPC32CompilationCallbackC(unsigned *IntRegs, double *FPRegs) {
|
||||
CameFromOrig[-1] = CameFromOrigInst;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Locate the start of the stub. If this is a short call, adjust backwards
|
||||
// the short amount, otherwise the full amount.
|
||||
bool isShortStub = (*CameFromStub >> 26) == 18;
|
||||
@@ -135,9 +135,9 @@ extern "C" void PPC32CompilationCallbackC(unsigned *IntRegs, double *FPRegs) {
|
||||
register unsigned *IRR asm ("r2") = IntRegs;
|
||||
register double *FRR asm ("r3") = FPRegs;
|
||||
__asm__ __volatile__ (
|
||||
"lfd f1, 0(%0)\n" "lfd f2, 8(%0)\n" "lfd f3, 16(%0)\n"
|
||||
"lfd f4, 24(%0)\n" "lfd f5, 32(%0)\n" "lfd f6, 40(%0)\n"
|
||||
"lfd f7, 48(%0)\n" "lfd f8, 56(%0)\n" "lfd f9, 64(%0)\n"
|
||||
"lfd f1, 0(%0)\n" "lfd f2, 8(%0)\n" "lfd f3, 16(%0)\n"
|
||||
"lfd f4, 24(%0)\n" "lfd f5, 32(%0)\n" "lfd f6, 40(%0)\n"
|
||||
"lfd f7, 48(%0)\n" "lfd f8, 56(%0)\n" "lfd f9, 64(%0)\n"
|
||||
"lfd f10, 72(%0)\n" "lfd f11, 80(%0)\n" "lfd f12, 88(%0)\n"
|
||||
"lfd f13, 96(%0)\n"
|
||||
"lmw r3, 0(%1)\n" // Load all integer regs
|
||||
@@ -147,13 +147,13 @@ extern "C" void PPC32CompilationCallbackC(unsigned *IntRegs, double *FPRegs) {
|
||||
"mtctr r0\n" // Put it into the CTR register
|
||||
"lwz r1,0(r1)\n" // Pop two frames off
|
||||
"bctr\n" :: // Return to stub!
|
||||
"b" (FRR), "b" (IRR));
|
||||
"b" (FRR), "b" (IRR));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
TargetJITInfo::LazyResolverFn
|
||||
TargetJITInfo::LazyResolverFn
|
||||
PPC32JITInfo::getLazyResolverFunction(JITCompilerFn Fn) {
|
||||
JITCompilerFunction = Fn;
|
||||
return PPC32CompilationCallback;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===- PowerPCJITInfo.h - PowerPC impl. of the JIT interface ----*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the PowerPC implementation of the TargetJITInfo class.
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===- PPC32RegisterInfo.cpp - PowerPC32 Register Information ---*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the PowerPC32 implementation of the MRegisterInfo class.
|
||||
@@ -38,7 +38,7 @@ namespace llvm {
|
||||
|
||||
PPC32RegisterInfo::PPC32RegisterInfo()
|
||||
: PPC32GenRegisterInfo(PPC::ADJCALLSTACKDOWN, PPC::ADJCALLSTACKUP) {
|
||||
ImmToIdxMap[PPC::LD] = PPC::LDX; ImmToIdxMap[PPC::STD] = PPC::STDX;
|
||||
ImmToIdxMap[PPC::LD] = PPC::LDX; ImmToIdxMap[PPC::STD] = PPC::STDX;
|
||||
ImmToIdxMap[PPC::LBZ] = PPC::LBZX; ImmToIdxMap[PPC::STB] = PPC::STBX;
|
||||
ImmToIdxMap[PPC::LHZ] = PPC::LHZX; ImmToIdxMap[PPC::LHA] = PPC::LHAX;
|
||||
ImmToIdxMap[PPC::LWZ] = PPC::LWZX; ImmToIdxMap[PPC::LWA] = PPC::LWAX;
|
||||
@@ -79,12 +79,12 @@ static unsigned getIdx(const TargetRegisterClass *RC) {
|
||||
abort();
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
PPC32RegisterInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MI,
|
||||
unsigned SrcReg, int FrameIdx) const {
|
||||
static const unsigned Opcode[] = {
|
||||
PPC::STB, PPC::STH, PPC::STW, PPC::STFS, PPC::STFD
|
||||
static const unsigned Opcode[] = {
|
||||
PPC::STB, PPC::STH, PPC::STW, PPC::STFS, PPC::STFD
|
||||
};
|
||||
unsigned OC = Opcode[getIdx(getClass(SrcReg))];
|
||||
if (SrcReg == PPC::LR) {
|
||||
@@ -102,8 +102,8 @@ void
|
||||
PPC32RegisterInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MI,
|
||||
unsigned DestReg, int FrameIdx) const{
|
||||
static const unsigned Opcode[] = {
|
||||
PPC::LBZ, PPC::LHZ, PPC::LWZ, PPC::LFS, PPC::LFD
|
||||
static const unsigned Opcode[] = {
|
||||
PPC::LBZ, PPC::LHZ, PPC::LWZ, PPC::LFS, PPC::LFD
|
||||
};
|
||||
unsigned OC = Opcode[getIdx(getClass(DestReg))];
|
||||
if (DestReg == PPC::LR) {
|
||||
@@ -163,7 +163,7 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
|
||||
// alignment boundary.
|
||||
unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment();
|
||||
Amount = (Amount+Align-1)/Align*Align;
|
||||
|
||||
|
||||
// Replace the pseudo instruction with a new instruction...
|
||||
if (Old->getOpcode() == PPC::ADJCALLSTACKDOWN) {
|
||||
MBB.insert(I, BuildMI(PPC::ADDI, 2, PPC::R1).addReg(PPC::R1)
|
||||
@@ -184,7 +184,7 @@ PPC32RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II) const {
|
||||
MachineInstr &MI = *II;
|
||||
MachineBasicBlock &MBB = *MI.getParent();
|
||||
MachineFunction &MF = *MBB.getParent();
|
||||
|
||||
|
||||
while (!MI.getOperand(i).isFrameIndex()) {
|
||||
++i;
|
||||
assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
|
||||
@@ -206,7 +206,7 @@ PPC32RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II) const {
|
||||
// SP before having the stack size subtracted from it, then add the stack size
|
||||
// to Offset to get the correct offset.
|
||||
Offset += MF.getFrameInfo()->getStackSize();
|
||||
|
||||
|
||||
if (Offset > 32767 || Offset < -32768) {
|
||||
// Insert a set of r0 with the full offset value before the ld, st, or add
|
||||
MachineBasicBlock *MBB = MI.getParent();
|
||||
@@ -232,15 +232,15 @@ void PPC32RegisterInfo::emitPrologue(MachineFunction &MF) const {
|
||||
MachineBasicBlock::iterator MBBI = MBB.begin();
|
||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
MachineInstr *MI;
|
||||
|
||||
|
||||
// Get the number of bytes to allocate from the FrameInfo
|
||||
unsigned NumBytes = MFI->getStackSize();
|
||||
|
||||
// If we have calls, we cannot use the red zone to store callee save registers
|
||||
// and we must set up a stack frame, so calculate the necessary size here.
|
||||
if (MFI->hasCalls()) {
|
||||
// We reserve argument space for call sites in the function immediately on
|
||||
// entry to the current function. This eliminates the need for add/sub
|
||||
// We reserve argument space for call sites in the function immediately on
|
||||
// entry to the current function. This eliminates the need for add/sub
|
||||
// brackets around call sites.
|
||||
NumBytes += MFI->getMaxCallFrameSize();
|
||||
}
|
||||
@@ -248,7 +248,7 @@ void PPC32RegisterInfo::emitPrologue(MachineFunction &MF) const {
|
||||
// Do we need to allocate space on the stack?
|
||||
if (NumBytes == 0) return;
|
||||
|
||||
// Add the size of R1 to NumBytes size for the store of R1 to the bottom
|
||||
// Add the size of R1 to NumBytes size for the store of R1 to the bottom
|
||||
// of the stack and round the size to a multiple of the alignment.
|
||||
unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment();
|
||||
unsigned GPRSize = getSpillSize(PPC::R1)/8;
|
||||
@@ -272,7 +272,7 @@ void PPC32RegisterInfo::emitPrologue(MachineFunction &MF) const {
|
||||
MI = BuildMI(PPC::STWUX, 3).addReg(PPC::R1).addReg(PPC::R1).addReg(PPC::R0);
|
||||
MBB.insert(MBBI, MI);
|
||||
}
|
||||
|
||||
|
||||
if (hasFP(MF)) {
|
||||
MI = BuildMI(PPC::STW, 3).addReg(PPC::R31).addSImm(GPRSize).addReg(PPC::R1);
|
||||
MBB.insert(MBBI, MI);
|
||||
@@ -288,7 +288,7 @@ void PPC32RegisterInfo::emitEpilogue(MachineFunction &MF,
|
||||
MachineInstr *MI;
|
||||
assert(MBBI->getOpcode() == PPC::BLR &&
|
||||
"Can only insert epilog into returning blocks");
|
||||
|
||||
|
||||
// Get the number of bytes allocated from the FrameInfo...
|
||||
unsigned NumBytes = MFI->getStackSize();
|
||||
unsigned GPRSize = getSpillSize(PPC::R31)/8;
|
||||
@@ -319,7 +319,7 @@ PPC32RegisterInfo::getRegClassForType(const Type* Ty) const {
|
||||
case Type::IntTyID:
|
||||
case Type::UIntTyID:
|
||||
case Type::PointerTyID: return &GPRCInstance;
|
||||
|
||||
|
||||
case Type::FloatTyID:
|
||||
case Type::DoubleTyID: return &FPRCInstance;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===- PPC32RegisterInfo.h - PowerPC32 Register Information Impl -*- C++ -*-==//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the PowerPC implementation of the MRegisterInfo class.
|
||||
@@ -36,7 +36,7 @@ public:
|
||||
void loadRegFromStackSlot(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MBBI,
|
||||
unsigned DestReg, int FrameIndex) const;
|
||||
|
||||
|
||||
void copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
|
||||
unsigned DestReg, unsigned SrcReg,
|
||||
const TargetRegisterClass *RC) const;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===- PPC32Relocations.h - PPC32 Code Relocations --------------*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the PowerPC 32-bit target-specific relocation types.
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
//===-- PowerPCTargetMachine.cpp - Define TargetMachine for PowerPC -------===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -31,13 +31,13 @@ using namespace llvm;
|
||||
|
||||
namespace llvm {
|
||||
bool PPCCRopts;
|
||||
cl::opt<bool> AIX("aix",
|
||||
cl::desc("Generate AIX/xcoff instead of Darwin/MachO"),
|
||||
cl::opt<bool> AIX("aix",
|
||||
cl::desc("Generate AIX/xcoff instead of Darwin/MachO"),
|
||||
cl::Hidden);
|
||||
cl::opt<bool> EnablePPCLSR("enable-lsr-for-ppc",
|
||||
cl::desc("Enable LSR for PPC (beta)"),
|
||||
cl::opt<bool> EnablePPCLSR("enable-lsr-for-ppc",
|
||||
cl::desc("Enable LSR for PPC (beta)"),
|
||||
cl::Hidden);
|
||||
cl::opt<bool, true> EnablePPCCRopts("enable-cc-opts",
|
||||
cl::opt<bool, true> EnablePPCCRopts("enable-cc-opts",
|
||||
cl::desc("Enable opts using condition regs (beta)"),
|
||||
cl::location(PPCCRopts),
|
||||
cl::init(false),
|
||||
@@ -47,13 +47,13 @@ namespace llvm {
|
||||
namespace {
|
||||
const std::string PPC32ID = "PowerPC/32bit";
|
||||
const std::string PPC64ID = "PowerPC/64bit";
|
||||
|
||||
|
||||
// Register the targets
|
||||
RegisterTarget<PPC32TargetMachine>
|
||||
RegisterTarget<PPC32TargetMachine>
|
||||
X("ppc32", " PowerPC 32-bit");
|
||||
|
||||
#if 0
|
||||
RegisterTarget<PPC64TargetMachine>
|
||||
RegisterTarget<PPC64TargetMachine>
|
||||
Y("ppc64", " PowerPC 64-bit (unimplemented)");
|
||||
#endif
|
||||
}
|
||||
@@ -84,7 +84,7 @@ bool PowerPCTargetMachine::addPassesToEmitAssembly(PassManager &PM,
|
||||
PM.add(createLoopStrengthReducePass());
|
||||
PM.add(createCFGSimplificationPass());
|
||||
}
|
||||
|
||||
|
||||
// FIXME: Implement efficient support for garbage collection intrinsics.
|
||||
PM.add(createLowerGCPass());
|
||||
|
||||
@@ -116,15 +116,15 @@ bool PowerPCTargetMachine::addPassesToEmitAssembly(PassManager &PM,
|
||||
PM.add(createMachineFunctionPrinterPass(&std::cerr));
|
||||
|
||||
PM.add(createPrologEpilogCodeInserter());
|
||||
|
||||
|
||||
// Must run branch selection immediately preceding the asm printer
|
||||
PM.add(createPPCBranchSelectionPass());
|
||||
|
||||
|
||||
if (AIX)
|
||||
PM.add(createAIXAsmPrinter(Out, *this));
|
||||
else
|
||||
PM.add(createDarwinAsmPrinter(Out, *this));
|
||||
|
||||
|
||||
PM.add(createMachineCodeDeleter());
|
||||
return false;
|
||||
}
|
||||
@@ -172,7 +172,7 @@ void PowerPCJITInfo::addPassesToJITCompile(FunctionPassManager &PM) {
|
||||
/// PowerPCTargetMachine ctor - Create an ILP32 architecture model
|
||||
///
|
||||
PPC32TargetMachine::PPC32TargetMachine(const Module &M, IntrinsicLowering *IL)
|
||||
: PowerPCTargetMachine(PPC32ID, IL,
|
||||
: PowerPCTargetMachine(PPC32ID, IL,
|
||||
TargetData(PPC32ID,false,4,4,4,4,4,4,2,1,1),
|
||||
PowerPCFrameInfo(*this, false)), JITInfo(*this) {}
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
//===-- PPC32TargetMachine.h - Define TargetMachine for PowerPC -*- C++ -*-=//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
// This file declares the PowerPC specific subclass of TargetMachine.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===- PowerPCInstrInfo.h - PowerPC Instruction Information -----*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the PowerPC implementation of the TargetInstrInfo class.
|
||||
@@ -23,7 +23,7 @@ namespace llvm {
|
||||
VMX = 1 << 0,
|
||||
PPC64 = 1 << 1,
|
||||
};
|
||||
|
||||
|
||||
enum {
|
||||
None = 0,
|
||||
Gpr = 1,
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
//===-- PowerPCTargetMachine.h - Define TargetMachine for PowerPC -*- C++ -*-=//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
// This file declares the PowerPC-specific subclass of TargetMachine.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===-- Skeleton.h - Target private header file -----------------*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the definitions shared among the various components of the
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===- SkeletonInstrInfo.cpp - Instruction Information ----------*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This is where you implement methods for the TargetInstrInfo class.
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===- SkeletonInstrInfo.h - Instruction Information ------------*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file is where the target-specific implementation of the TargetInstrInfo
|
||||
@@ -24,7 +24,7 @@ namespace llvm {
|
||||
const SkeletonRegisterInfo RI;
|
||||
public:
|
||||
SkeletonInstrInfo();
|
||||
|
||||
|
||||
/// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As
|
||||
/// such, whenever a client has an instance of instruction info, it should
|
||||
/// always be able to get register info as well (through this method).
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
//===-- SkeletonCodeEmitter.cpp - JIT Code Emitter --------------*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
// This is a stub for a JIT code generator, which is obviously not implemented.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===- SkeletonJITInfo.h - Skeleton impl of JIT interface -------*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the skeleton implementation of the TargetJITInfo class.
|
||||
@@ -30,7 +30,7 @@ namespace llvm {
|
||||
/// is not supported for this target.
|
||||
///
|
||||
virtual void addPassesToJITCompile(FunctionPassManager &PM);
|
||||
|
||||
|
||||
/// replaceMachineCodeForFunction - Make it so that calling the function
|
||||
/// whose machine code is at OLD turns into a call to NEW, perhaps by
|
||||
/// overwriting OLD with a branch to NEW. This is used for self-modifying
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===- SkeletonRegisterInfo.cpp - Skeleton Register Information -*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the Skeleton implementation of the MRegisterInfo class.
|
||||
@@ -45,7 +45,7 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
|
||||
abort();
|
||||
}
|
||||
|
||||
void SkeletonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II)
|
||||
void SkeletonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II)
|
||||
const {
|
||||
abort();
|
||||
}
|
||||
@@ -81,7 +81,7 @@ SkeletonRegisterInfo::getRegClassForType(const Type* Ty) const {
|
||||
case Type::IntTyID:
|
||||
case Type::UIntTyID:
|
||||
case Type::PointerTyID: return &GPRCInstance;
|
||||
|
||||
|
||||
case Type::FloatTyID:
|
||||
case Type::DoubleTyID: return &FPRCInstance;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===- SkeletonRegisterInfo.h - Skeleton Register Information Impl -*- C++ -*-==//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the Skeleton implementation of the MRegisterInfo class.
|
||||
@@ -22,27 +22,27 @@ namespace llvm {
|
||||
struct SkeletonRegisterInfo : public SkeletonGenRegisterInfo {
|
||||
SkeletonRegisterInfo();
|
||||
const TargetRegisterClass* getRegClassForType(const Type* Ty) const;
|
||||
|
||||
|
||||
void storeRegToStackSlot(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MBBI,
|
||||
unsigned SrcReg, int FrameIndex) const;
|
||||
|
||||
|
||||
void loadRegFromStackSlot(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MBBI,
|
||||
unsigned DestReg, int FrameIndex) const;
|
||||
|
||||
|
||||
void copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
|
||||
unsigned DestReg, unsigned SrcReg,
|
||||
const TargetRegisterClass *RC) const;
|
||||
|
||||
|
||||
void eliminateCallFramePseudoInstr(MachineFunction &MF,
|
||||
MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator I) const;
|
||||
|
||||
|
||||
void eliminateFrameIndex(MachineBasicBlock::iterator II) const;
|
||||
|
||||
|
||||
void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
|
||||
|
||||
|
||||
void emitPrologue(MachineFunction &MF) const;
|
||||
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
||||
};
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
//===-- SkeletonTargetMachine.cpp - Define TargetMachine for Skeleton -----===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
//===-- SkeletonTargetMachine.h - TargetMachine for Skeleton ----*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
// This file declares the Skeleton specific subclass of TargetMachine.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
@@ -41,7 +41,7 @@ namespace llvm {
|
||||
|
||||
virtual bool addPassesToEmitMachineCode(FunctionPassManager &PM,
|
||||
MachineCodeEmitter &MCE);
|
||||
|
||||
|
||||
virtual bool addPassesToEmitAssembly(PassManager &PM, std::ostream &Out);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===-- DelaySlotFiller.cpp - SparcV8 delay slot filler -------------------===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This is a simple local pass that fills delay slots with NOPs.
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===-- FPMover.cpp - SparcV8 double-precision floating point move fixer --===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Turns FpMOVD instructions into FMOVS pairs after regalloc.
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===-- SparcV8.h - Top-level interface for SparcV8 representation -*- C++ -*-//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the entry points for global functions defined in the LLVM
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===-- SparcV8AsmPrinter.cpp - SparcV8 LLVM assembly writer --------------===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains a printer that converts from our internal representation
|
||||
@@ -71,7 +71,7 @@ namespace {
|
||||
void printOperand(const MachineInstr *MI, int opNum);
|
||||
void printBaseOffsetPair (const MachineInstr *MI, int i, bool brackets=true);
|
||||
void printMachineInstruction(const MachineInstr *MI);
|
||||
bool runOnMachineFunction(MachineFunction &F);
|
||||
bool runOnMachineFunction(MachineFunction &F);
|
||||
bool doInitialization(Module &M);
|
||||
bool doFinalization(Module &M);
|
||||
};
|
||||
@@ -203,7 +203,7 @@ void V8Printer::emitConstantValueOnly(const Constant *CV) {
|
||||
|
||||
// Print a constant value or values, with the appropriate storage class as a
|
||||
// prefix.
|
||||
void V8Printer::emitGlobalConstant(const Constant *CV) {
|
||||
void V8Printer::emitGlobalConstant(const Constant *CV) {
|
||||
const TargetData &TD = TM.getTargetData();
|
||||
|
||||
if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) {
|
||||
@@ -235,7 +235,7 @@ void V8Printer::emitGlobalConstant(const Constant *CV) {
|
||||
|
||||
// Insert the field padding unless it's zero bytes...
|
||||
if (padSize)
|
||||
O << "\t.skip\t " << padSize << "\n";
|
||||
O << "\t.skip\t " << padSize << "\n";
|
||||
}
|
||||
assert(sizeSoFar == cvsLayout->StructSize &&
|
||||
"Layout of constant struct may be incorrect!");
|
||||
@@ -268,7 +268,7 @@ void V8Printer::emitGlobalConstant(const Constant *CV) {
|
||||
}
|
||||
} else if (isa<UndefValue> (CV)) {
|
||||
unsigned size = TD.getTypeSize (CV->getType ());
|
||||
O << "\t.skip\t " << size << "\n";
|
||||
O << "\t.skip\t " << size << "\n";
|
||||
return;
|
||||
} else if (isa<ConstantAggregateZero> (CV)) {
|
||||
unsigned size = TD.getTypeSize (CV->getType ());
|
||||
@@ -311,7 +311,7 @@ void V8Printer::emitGlobalConstant(const Constant *CV) {
|
||||
void V8Printer::printConstantPool(MachineConstantPool *MCP) {
|
||||
const std::vector<Constant*> &CP = MCP->getConstants();
|
||||
const TargetData &TD = TM.getTargetData();
|
||||
|
||||
|
||||
if (CP.empty()) return;
|
||||
|
||||
for (unsigned i = 0, e = CP.size(); i != e; ++i) {
|
||||
@@ -424,7 +424,7 @@ void V8Printer::printOperand(const MachineInstr *MI, int opNum) {
|
||||
O << ".CPI" << CurrentFnName << "_" << MO.getConstantPoolIndex();
|
||||
break;
|
||||
default:
|
||||
O << "<unknown operand type>"; abort (); break;
|
||||
O << "<unknown operand type>"; abort (); break;
|
||||
}
|
||||
if (CloseParen) O << ")";
|
||||
}
|
||||
@@ -511,7 +511,7 @@ void V8Printer::printMachineInstruction(const MachineInstr *MI) {
|
||||
O << "! ";
|
||||
|
||||
O << Desc.Name << " ";
|
||||
|
||||
|
||||
// Printing memory instructions is a special case.
|
||||
// for loads: %dest = op %base, offset --> op [%base + offset], %dest
|
||||
// for stores: op %base, offset, %src --> op %src, [%base + offset]
|
||||
@@ -550,7 +550,7 @@ void V8Printer::printMachineInstruction(const MachineInstr *MI) {
|
||||
for (unsigned i = 0; i < MI->getNumOperands (); ++i)
|
||||
if (MI->getOperand (i).isRegister () && MI->getOperand (i).isDef ())
|
||||
print_order.push_back (i);
|
||||
for (unsigned i = 0, e = print_order.size (); i != e; ++i) {
|
||||
for (unsigned i = 0, e = print_order.size (); i != e; ++i) {
|
||||
printOperand (MI, print_order[i]);
|
||||
if (i != (print_order.size () - 1))
|
||||
O << ", ";
|
||||
@@ -588,13 +588,13 @@ bool V8Printer::doFinalization(Module &M) {
|
||||
unsigned Size = TD.getTypeSize(C->getType());
|
||||
unsigned Align = TD.getTypeAlignment(C->getType());
|
||||
|
||||
if (C->isNullValue() &&
|
||||
if (C->isNullValue() &&
|
||||
(I->hasLinkOnceLinkage() || I->hasInternalLinkage() ||
|
||||
I->hasWeakLinkage() /* FIXME: Verify correct */)) {
|
||||
SwitchSection(O, CurSection, ".data");
|
||||
if (I->hasInternalLinkage())
|
||||
O << "\t.local " << name << "\n";
|
||||
|
||||
|
||||
O << "\t.comm " << name << "," << TD.getTypeSize(C->getType())
|
||||
<< "," << (unsigned)TD.getTypeAlignment(C->getType());
|
||||
O << "\t\t! ";
|
||||
@@ -609,7 +609,7 @@ bool V8Printer::doFinalization(Module &M) {
|
||||
SwitchSection(O, CurSection, "");
|
||||
O << "\t.section\t\".llvm.linkonce.d." << name << "\",\"aw\",@progbits\n";
|
||||
break;
|
||||
|
||||
|
||||
case GlobalValue::AppendingLinkage:
|
||||
// FIXME: appending linkage variables should go into a section of
|
||||
// their name or something. For now, just emit them as external.
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===- SparcV8InstrInfo.cpp - SparcV8 Instruction Information ---*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the SparcV8 implementation of the TargetInstrInfo class.
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===- SparcV8InstrInfo.h - SparcV8 Instruction Information -----*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the SparcV8 implementation of the TargetInstrInfo class.
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===- SparcV8RegisterInfo.cpp - SparcV8 Register Information ---*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the SparcV8 implementation of the MRegisterInfo class.
|
||||
@@ -44,7 +44,7 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
||||
const TargetRegisterClass *RC = getClass(SrcReg);
|
||||
|
||||
// On the order of operands here: think "[FrameIdx + 0] = SrcReg".
|
||||
if (RC == SparcV8::IntRegsRegisterClass)
|
||||
if (RC == SparcV8::IntRegsRegisterClass)
|
||||
BuildMI (MBB, I, V8::ST, 3).addFrameIndex (FrameIdx).addSImm (0)
|
||||
.addReg (SrcReg);
|
||||
else if (RC == SparcV8::FPRegsRegisterClass)
|
||||
@@ -61,7 +61,7 @@ void SparcV8RegisterInfo::
|
||||
loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
||||
unsigned DestReg, int FrameIdx) const {
|
||||
const TargetRegisterClass *RC = getClass(DestReg);
|
||||
if (RC == SparcV8::IntRegsRegisterClass)
|
||||
if (RC == SparcV8::IntRegsRegisterClass)
|
||||
BuildMI (MBB, I, V8::LD, 2, DestReg).addFrameIndex (FrameIdx).addSImm (0);
|
||||
else if (RC == SparcV8::FPRegsRegisterClass)
|
||||
BuildMI (MBB, I, V8::LDFri, 2, DestReg).addFrameIndex (FrameIdx)
|
||||
@@ -77,7 +77,7 @@ void SparcV8RegisterInfo::copyRegToReg(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator I,
|
||||
unsigned DestReg, unsigned SrcReg,
|
||||
const TargetRegisterClass *RC) const {
|
||||
if (RC == SparcV8::IntRegsRegisterClass)
|
||||
if (RC == SparcV8::IntRegsRegisterClass)
|
||||
BuildMI (MBB, I, V8::ORrr, 2, DestReg).addReg (V8::G0).addReg (SrcReg);
|
||||
else if (RC == SparcV8::FPRegsRegisterClass)
|
||||
BuildMI (MBB, I, V8::FMOVS, 1, DestReg).addReg (SrcReg);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===- SparcV8RegisterInfo.h - SparcV8 Register Information Impl -*- C++ -*-==//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the SparcV8 implementation of the MRegisterInfo class.
|
||||
@@ -33,7 +33,7 @@ struct SparcV8RegisterInfo : public SparcV8GenRegisterInfo {
|
||||
void loadRegFromStackSlot(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MBBI,
|
||||
unsigned DestReg, int FrameIndex) const;
|
||||
|
||||
|
||||
void copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
|
||||
unsigned DestReg, unsigned SrcReg,
|
||||
const TargetRegisterClass *RC) const;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
//===-- SparcV8TargetMachine.cpp - Define TargetMachine for SparcV8 -------===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -87,7 +87,7 @@ bool SparcV8TargetMachine::addPassesToEmitAssembly(PassManager &PM,
|
||||
// Print LLVM code input to instruction selector:
|
||||
if (PrintMachineCode)
|
||||
PM.add(new PrintFunctionPass());
|
||||
|
||||
|
||||
PM.add(createSparcV8SimpleInstructionSelector(*this));
|
||||
|
||||
// Print machine instructions as they were initially generated.
|
||||
@@ -126,7 +126,7 @@ void SparcV8JITInfo::addPassesToJITCompile(FunctionPassManager &PM) {
|
||||
|
||||
// Replace malloc and free instructions with library calls.
|
||||
PM.add(createLowerAllocationsPass());
|
||||
|
||||
|
||||
// FIXME: implement the switch instruction in the instruction selector.
|
||||
PM.add(createLowerSwitchPass());
|
||||
|
||||
@@ -134,17 +134,17 @@ void SparcV8JITInfo::addPassesToJITCompile(FunctionPassManager &PM) {
|
||||
PM.add(createLowerInvokePass());
|
||||
|
||||
PM.add(createLowerConstantExpressionsPass());
|
||||
|
||||
|
||||
// Make sure that no unreachable blocks are instruction selected.
|
||||
PM.add(createUnreachableBlockEliminationPass());
|
||||
|
||||
// FIXME: implement the select instruction in the instruction selector.
|
||||
PM.add(createLowerSelectPass());
|
||||
|
||||
|
||||
// Print LLVM code input to instruction selector:
|
||||
if (PrintMachineCode)
|
||||
PM.add(new PrintFunctionPass());
|
||||
|
||||
|
||||
PM.add(createSparcV8SimpleInstructionSelector(TM));
|
||||
|
||||
// Print machine instructions as they were initially generated.
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
//===-- SparcV8TargetMachine.h - Define TargetMachine for SparcV8 -*- C++ -*-=//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
// This file declares the SparcV8 specific subclass of TargetMachine.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
@@ -52,7 +52,7 @@ public:
|
||||
///
|
||||
virtual bool addPassesToEmitMachineCode(FunctionPassManager &PM,
|
||||
MachineCodeEmitter &MCE);
|
||||
|
||||
|
||||
virtual bool addPassesToEmitAssembly(PassManager &PM, std::ostream &Out);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
//===-- SparcV8CodeEmitter.cpp - JIT Code Emitter for SparcV8 -----*- C++ -*-=//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -78,7 +78,7 @@ bool SparcV8TargetMachine::addPassesToEmitMachineCode(FunctionPassManager &PM,
|
||||
MachineCodeEmitter &MCE) {
|
||||
// Keep as `true' until this is a functional JIT to allow llvm-gcc to build
|
||||
return true;
|
||||
|
||||
|
||||
// Machine code emitter pass for SparcV8
|
||||
PM.add(new SparcV8CodeEmitter(*this, MCE));
|
||||
// Delete machine code for this function after emitting it
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===-- InstSelectSimple.cpp - A simple instruction selector for SparcV8 --===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines a simple peephole instruction selector for the V8 target
|
||||
@@ -318,7 +318,7 @@ void V8ISel::copyConstantToRegister(MachineBasicBlock *MBB,
|
||||
BuildMI (*MBB, IP, V8::ORri, 2, R).addReg (V8::G0).addSImm (0);
|
||||
} else if (GlobalValue *GV = dyn_cast<GlobalValue>(C)) {
|
||||
// Copy it with a SETHI/OR pair; the JIT + asmwriter should recognize
|
||||
// that SETHI %reg,global == SETHI %reg,%hi(global) and
|
||||
// that SETHI %reg,global == SETHI %reg,%hi(global) and
|
||||
// OR %reg,global,%reg == OR %reg,%lo(global),%reg.
|
||||
unsigned TmpReg = makeAnotherReg (C->getType ());
|
||||
BuildMI (*MBB, IP, V8::SETHIi, 1, TmpReg).addGlobalAddress(GV);
|
||||
@@ -362,10 +362,10 @@ void V8ISel::LoadArgumentsToVirtualRegs (Function *LF) {
|
||||
const unsigned *IAR = &IncomingArgRegs[0];
|
||||
unsigned ArgOffset = 68;
|
||||
|
||||
// Store registers onto stack if this is a varargs function.
|
||||
// Store registers onto stack if this is a varargs function.
|
||||
// FIXME: This doesn't really pertain to "loading arguments into
|
||||
// virtual registers", so it's not clear that it really belongs here.
|
||||
// FIXME: We could avoid storing any args onto the stack that don't
|
||||
// FIXME: We could avoid storing any args onto the stack that don't
|
||||
// need to be in memory, because they come before the ellipsis in the
|
||||
// parameter list (and thus could never be accessed through va_arg).
|
||||
if (LF->getFunctionType ()->isVarArg ()) {
|
||||
@@ -505,7 +505,7 @@ void V8ISel::SelectPHINodes() {
|
||||
break;
|
||||
}
|
||||
assert (PredMBB && "Couldn't find incoming machine-cfg edge for phi");
|
||||
|
||||
|
||||
unsigned ValReg;
|
||||
std::map<MachineBasicBlock*, unsigned>::iterator EntryIt =
|
||||
PHIValues.lower_bound(PredMBB);
|
||||
@@ -515,7 +515,7 @@ void V8ISel::SelectPHINodes() {
|
||||
// predecessor. Recycle it.
|
||||
ValReg = EntryIt->second;
|
||||
|
||||
} else {
|
||||
} else {
|
||||
// Get the incoming value into a virtual register.
|
||||
//
|
||||
Value *Val = PN->getIncomingValue(i);
|
||||
@@ -534,11 +534,11 @@ void V8ISel::SelectPHINodes() {
|
||||
// might be arbitrarily complex if it is a constant expression),
|
||||
// just insert the computation at the top of the basic block.
|
||||
MachineBasicBlock::iterator PI = PredMBB->begin();
|
||||
|
||||
|
||||
// Skip over any PHI nodes though!
|
||||
while (PI != PredMBB->end() && PI->getOpcode() == V8::PHI)
|
||||
++PI;
|
||||
|
||||
|
||||
ValReg = getReg(Val, PredMBB, PI);
|
||||
}
|
||||
|
||||
@@ -568,28 +568,28 @@ bool V8ISel::runOnFunction(Function &Fn) {
|
||||
// First pass over the function, lower any unknown intrinsic functions
|
||||
// with the IntrinsicLowering class.
|
||||
LowerUnknownIntrinsicFunctionCalls(Fn);
|
||||
|
||||
|
||||
F = &MachineFunction::construct(&Fn, TM);
|
||||
|
||||
|
||||
// Create all of the machine basic blocks for the function...
|
||||
for (Function::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
|
||||
F->getBasicBlockList().push_back(MBBMap[I] = new MachineBasicBlock(I));
|
||||
|
||||
|
||||
BB = &F->front();
|
||||
|
||||
|
||||
// Set up a frame object for the return address. This is used by the
|
||||
// llvm.returnaddress & llvm.frameaddress intrinisics.
|
||||
//ReturnAddressIndex = F->getFrameInfo()->CreateFixedObject(4, -4);
|
||||
|
||||
|
||||
// Copy incoming arguments off of the stack and out of fixed registers.
|
||||
LoadArgumentsToVirtualRegs(&Fn);
|
||||
|
||||
|
||||
// Instruction select everything except PHI nodes
|
||||
visit(Fn);
|
||||
|
||||
|
||||
// Select the PHI nodes
|
||||
SelectPHINodes();
|
||||
|
||||
|
||||
RegMap.clear();
|
||||
MBBMap.clear();
|
||||
F = 0;
|
||||
@@ -632,11 +632,11 @@ void V8ISel::emitFPToIntegerCast (MachineBasicBlock *BB,
|
||||
const Type *newTy, unsigned DestReg) {
|
||||
unsigned FPCastOpcode, FPStoreOpcode, FPSize, FPAlign;
|
||||
unsigned oldTyClass = getClassB(oldTy);
|
||||
if (oldTyClass == cFloat) {
|
||||
FPCastOpcode = V8::FSTOI; FPStoreOpcode = V8::STFri; FPSize = 4;
|
||||
if (oldTyClass == cFloat) {
|
||||
FPCastOpcode = V8::FSTOI; FPStoreOpcode = V8::STFri; FPSize = 4;
|
||||
FPAlign = TM.getTargetData().getFloatAlignment();
|
||||
} else { // it's a double
|
||||
FPCastOpcode = V8::FDTOI; FPStoreOpcode = V8::STDFri; FPSize = 8;
|
||||
FPCastOpcode = V8::FDTOI; FPStoreOpcode = V8::STDFri; FPSize = 8;
|
||||
FPAlign = TM.getTargetData().getDoubleAlignment();
|
||||
}
|
||||
unsigned TempReg = makeAnotherReg (oldTy);
|
||||
@@ -672,11 +672,11 @@ void V8ISel::emitCastOperation(MachineBasicBlock *BB,
|
||||
case cShort:
|
||||
case cInt:
|
||||
switch (oldTyClass) {
|
||||
case cLong:
|
||||
case cLong:
|
||||
// Treat it like a cast from the lower half of the value.
|
||||
emitIntegerCast (BB, IP, Type::IntTy, SrcReg+1, newTy, DestReg);
|
||||
break;
|
||||
case cFloat:
|
||||
case cFloat:
|
||||
case cDouble:
|
||||
emitFPToIntegerCast (BB, IP, oldTy, SrcReg, newTy, DestReg);
|
||||
break;
|
||||
@@ -742,10 +742,10 @@ void V8ISel::emitCastOperation(MachineBasicBlock *BB,
|
||||
unsigned TempReg = emitIntegerCast (BB, IP, OldHalfTy, SrcReg,
|
||||
NewHalfTy, DestReg+1, true);
|
||||
if (newTy->isSigned ()) {
|
||||
BuildMI (*BB, IP, V8::SRAri, 2, DestReg).addReg (TempReg)
|
||||
BuildMI (*BB, IP, V8::SRAri, 2, DestReg).addReg (TempReg)
|
||||
.addZImm (31);
|
||||
} else {
|
||||
BuildMI (*BB, IP, V8::ORrr, 2, DestReg).addReg (V8::G0)
|
||||
BuildMI (*BB, IP, V8::ORrr, 2, DestReg).addReg (V8::G0)
|
||||
.addReg (V8::G0);
|
||||
}
|
||||
break;
|
||||
@@ -1162,7 +1162,7 @@ void V8ISel::emitGEPOperation (MachineBasicBlock *MBB,
|
||||
if (isa<ConstantIntegral> (idx)) {
|
||||
// If idx is a constant, we don't have to emit the multiply.
|
||||
int64_t Val = cast<ConstantIntegral> (idx)->getRawValue ();
|
||||
if ((Val * elementSize) + 4096 < 8191) {
|
||||
if ((Val * elementSize) + 4096 < 8191) {
|
||||
// (Val * elementSize) is constant and fits in an immediate field.
|
||||
// emit: nextBasePtrReg = ADDri basePtrReg, (Val * elementSize)
|
||||
addImmed = true;
|
||||
@@ -1180,16 +1180,16 @@ void V8ISel::emitGEPOperation (MachineBasicBlock *MBB,
|
||||
OffsetReg = makeAnotherReg (Type::IntTy);
|
||||
unsigned idxReg = getReg (idx, MBB, IP);
|
||||
switch (elementSize) {
|
||||
case 1:
|
||||
case 1:
|
||||
BuildMI (*MBB, IP, V8::ORrr, 2, OffsetReg).addReg (V8::G0).addReg (idxReg);
|
||||
break;
|
||||
case 2:
|
||||
case 2:
|
||||
BuildMI (*MBB, IP, V8::SLLri, 2, OffsetReg).addReg (idxReg).addZImm (1);
|
||||
break;
|
||||
case 4:
|
||||
case 4:
|
||||
BuildMI (*MBB, IP, V8::SLLri, 2, OffsetReg).addReg (idxReg).addZImm (2);
|
||||
break;
|
||||
case 8:
|
||||
case 8:
|
||||
BuildMI (*MBB, IP, V8::SLLri, 2, OffsetReg).addReg (idxReg).addZImm (3);
|
||||
break;
|
||||
default: {
|
||||
@@ -1343,7 +1343,7 @@ void V8ISel::emitShift64 (MachineBasicBlock *MBB,
|
||||
// ba .lshr_continue
|
||||
|
||||
BB = oneShiftMBB;
|
||||
|
||||
|
||||
if (isSigned)
|
||||
BuildMI (BB, V8::SRAri, 2, OneShiftOutReg).addReg (SrcReg).addZImm (31);
|
||||
else
|
||||
@@ -1515,7 +1515,7 @@ void V8ISel::visitBinaryOperator (Instruction &I) {
|
||||
}
|
||||
|
||||
switch (getClassB (I.getType ())) {
|
||||
case cByte:
|
||||
case cByte:
|
||||
if (I.getType ()->isSigned ()) { // add byte
|
||||
BuildMI (BB, V8::ANDri, 2, DestReg).addReg (ResultReg).addZImm (0xff);
|
||||
} else { // add ubyte
|
||||
@@ -1562,7 +1562,7 @@ void V8ISel::visitSetCondInst(SetCondInst &I) {
|
||||
unsigned Op1Reg = getReg (I.getOperand (1));
|
||||
unsigned DestReg = getReg (I);
|
||||
const Type *Ty = I.getOperand (0)->getType ();
|
||||
|
||||
|
||||
// Compare the two values.
|
||||
if (getClass (Ty) < cLong) {
|
||||
BuildMI(BB, V8::SUBCCrr, 2, V8::G0).addReg(Op0Reg).addReg(Op1Reg);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===- SparcV8JITInfo.h - SparcV8 impl. of the JIT interface ----*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the SparcV8 implementation of the TargetJITInfo class.
|
||||
@@ -30,14 +30,14 @@ namespace llvm {
|
||||
/// is not supported for this target.
|
||||
///
|
||||
virtual void addPassesToJITCompile(FunctionPassManager &PM);
|
||||
|
||||
|
||||
/// replaceMachineCodeForFunction - Make it so that calling the function
|
||||
/// whose machine code is at OLD turns into a call to NEW, perhaps by
|
||||
/// overwriting OLD with a branch to NEW. This is used for self-modifying
|
||||
/// code.
|
||||
///
|
||||
virtual void replaceMachineCodeForFunction(void *Old, void *New);
|
||||
|
||||
|
||||
/// getJITStubForFunction - Create or return a stub for the specified
|
||||
/// function. This stub acts just like the specified function, except that
|
||||
/// it allows the "address" of the function to be taken without having to
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===-- DelaySlotFiller.cpp - SparcV8 delay slot filler -------------------===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This is a simple local pass that fills delay slots with NOPs.
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===-- FPMover.cpp - SparcV8 double-precision floating point move fixer --===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Turns FpMOVD instructions into FMOVS pairs after regalloc.
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===-- SparcV8.h - Top-level interface for SparcV8 representation -*- C++ -*-//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the entry points for global functions defined in the LLVM
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===-- SparcV8AsmPrinter.cpp - SparcV8 LLVM assembly writer --------------===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains a printer that converts from our internal representation
|
||||
@@ -71,7 +71,7 @@ namespace {
|
||||
void printOperand(const MachineInstr *MI, int opNum);
|
||||
void printBaseOffsetPair (const MachineInstr *MI, int i, bool brackets=true);
|
||||
void printMachineInstruction(const MachineInstr *MI);
|
||||
bool runOnMachineFunction(MachineFunction &F);
|
||||
bool runOnMachineFunction(MachineFunction &F);
|
||||
bool doInitialization(Module &M);
|
||||
bool doFinalization(Module &M);
|
||||
};
|
||||
@@ -203,7 +203,7 @@ void V8Printer::emitConstantValueOnly(const Constant *CV) {
|
||||
|
||||
// Print a constant value or values, with the appropriate storage class as a
|
||||
// prefix.
|
||||
void V8Printer::emitGlobalConstant(const Constant *CV) {
|
||||
void V8Printer::emitGlobalConstant(const Constant *CV) {
|
||||
const TargetData &TD = TM.getTargetData();
|
||||
|
||||
if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) {
|
||||
@@ -235,7 +235,7 @@ void V8Printer::emitGlobalConstant(const Constant *CV) {
|
||||
|
||||
// Insert the field padding unless it's zero bytes...
|
||||
if (padSize)
|
||||
O << "\t.skip\t " << padSize << "\n";
|
||||
O << "\t.skip\t " << padSize << "\n";
|
||||
}
|
||||
assert(sizeSoFar == cvsLayout->StructSize &&
|
||||
"Layout of constant struct may be incorrect!");
|
||||
@@ -268,7 +268,7 @@ void V8Printer::emitGlobalConstant(const Constant *CV) {
|
||||
}
|
||||
} else if (isa<UndefValue> (CV)) {
|
||||
unsigned size = TD.getTypeSize (CV->getType ());
|
||||
O << "\t.skip\t " << size << "\n";
|
||||
O << "\t.skip\t " << size << "\n";
|
||||
return;
|
||||
} else if (isa<ConstantAggregateZero> (CV)) {
|
||||
unsigned size = TD.getTypeSize (CV->getType ());
|
||||
@@ -311,7 +311,7 @@ void V8Printer::emitGlobalConstant(const Constant *CV) {
|
||||
void V8Printer::printConstantPool(MachineConstantPool *MCP) {
|
||||
const std::vector<Constant*> &CP = MCP->getConstants();
|
||||
const TargetData &TD = TM.getTargetData();
|
||||
|
||||
|
||||
if (CP.empty()) return;
|
||||
|
||||
for (unsigned i = 0, e = CP.size(); i != e; ++i) {
|
||||
@@ -424,7 +424,7 @@ void V8Printer::printOperand(const MachineInstr *MI, int opNum) {
|
||||
O << ".CPI" << CurrentFnName << "_" << MO.getConstantPoolIndex();
|
||||
break;
|
||||
default:
|
||||
O << "<unknown operand type>"; abort (); break;
|
||||
O << "<unknown operand type>"; abort (); break;
|
||||
}
|
||||
if (CloseParen) O << ")";
|
||||
}
|
||||
@@ -511,7 +511,7 @@ void V8Printer::printMachineInstruction(const MachineInstr *MI) {
|
||||
O << "! ";
|
||||
|
||||
O << Desc.Name << " ";
|
||||
|
||||
|
||||
// Printing memory instructions is a special case.
|
||||
// for loads: %dest = op %base, offset --> op [%base + offset], %dest
|
||||
// for stores: op %base, offset, %src --> op %src, [%base + offset]
|
||||
@@ -550,7 +550,7 @@ void V8Printer::printMachineInstruction(const MachineInstr *MI) {
|
||||
for (unsigned i = 0; i < MI->getNumOperands (); ++i)
|
||||
if (MI->getOperand (i).isRegister () && MI->getOperand (i).isDef ())
|
||||
print_order.push_back (i);
|
||||
for (unsigned i = 0, e = print_order.size (); i != e; ++i) {
|
||||
for (unsigned i = 0, e = print_order.size (); i != e; ++i) {
|
||||
printOperand (MI, print_order[i]);
|
||||
if (i != (print_order.size () - 1))
|
||||
O << ", ";
|
||||
@@ -588,13 +588,13 @@ bool V8Printer::doFinalization(Module &M) {
|
||||
unsigned Size = TD.getTypeSize(C->getType());
|
||||
unsigned Align = TD.getTypeAlignment(C->getType());
|
||||
|
||||
if (C->isNullValue() &&
|
||||
if (C->isNullValue() &&
|
||||
(I->hasLinkOnceLinkage() || I->hasInternalLinkage() ||
|
||||
I->hasWeakLinkage() /* FIXME: Verify correct */)) {
|
||||
SwitchSection(O, CurSection, ".data");
|
||||
if (I->hasInternalLinkage())
|
||||
O << "\t.local " << name << "\n";
|
||||
|
||||
|
||||
O << "\t.comm " << name << "," << TD.getTypeSize(C->getType())
|
||||
<< "," << (unsigned)TD.getTypeAlignment(C->getType());
|
||||
O << "\t\t! ";
|
||||
@@ -609,7 +609,7 @@ bool V8Printer::doFinalization(Module &M) {
|
||||
SwitchSection(O, CurSection, "");
|
||||
O << "\t.section\t\".llvm.linkonce.d." << name << "\",\"aw\",@progbits\n";
|
||||
break;
|
||||
|
||||
|
||||
case GlobalValue::AppendingLinkage:
|
||||
// FIXME: appending linkage variables should go into a section of
|
||||
// their name or something. For now, just emit them as external.
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
//===-- SparcV8CodeEmitter.cpp - JIT Code Emitter for SparcV8 -----*- C++ -*-=//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -78,7 +78,7 @@ bool SparcV8TargetMachine::addPassesToEmitMachineCode(FunctionPassManager &PM,
|
||||
MachineCodeEmitter &MCE) {
|
||||
// Keep as `true' until this is a functional JIT to allow llvm-gcc to build
|
||||
return true;
|
||||
|
||||
|
||||
// Machine code emitter pass for SparcV8
|
||||
PM.add(new SparcV8CodeEmitter(*this, MCE));
|
||||
// Delete machine code for this function after emitting it
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===-- InstSelectSimple.cpp - A simple instruction selector for SparcV8 --===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines a simple peephole instruction selector for the V8 target
|
||||
@@ -318,7 +318,7 @@ void V8ISel::copyConstantToRegister(MachineBasicBlock *MBB,
|
||||
BuildMI (*MBB, IP, V8::ORri, 2, R).addReg (V8::G0).addSImm (0);
|
||||
} else if (GlobalValue *GV = dyn_cast<GlobalValue>(C)) {
|
||||
// Copy it with a SETHI/OR pair; the JIT + asmwriter should recognize
|
||||
// that SETHI %reg,global == SETHI %reg,%hi(global) and
|
||||
// that SETHI %reg,global == SETHI %reg,%hi(global) and
|
||||
// OR %reg,global,%reg == OR %reg,%lo(global),%reg.
|
||||
unsigned TmpReg = makeAnotherReg (C->getType ());
|
||||
BuildMI (*MBB, IP, V8::SETHIi, 1, TmpReg).addGlobalAddress(GV);
|
||||
@@ -362,10 +362,10 @@ void V8ISel::LoadArgumentsToVirtualRegs (Function *LF) {
|
||||
const unsigned *IAR = &IncomingArgRegs[0];
|
||||
unsigned ArgOffset = 68;
|
||||
|
||||
// Store registers onto stack if this is a varargs function.
|
||||
// Store registers onto stack if this is a varargs function.
|
||||
// FIXME: This doesn't really pertain to "loading arguments into
|
||||
// virtual registers", so it's not clear that it really belongs here.
|
||||
// FIXME: We could avoid storing any args onto the stack that don't
|
||||
// FIXME: We could avoid storing any args onto the stack that don't
|
||||
// need to be in memory, because they come before the ellipsis in the
|
||||
// parameter list (and thus could never be accessed through va_arg).
|
||||
if (LF->getFunctionType ()->isVarArg ()) {
|
||||
@@ -505,7 +505,7 @@ void V8ISel::SelectPHINodes() {
|
||||
break;
|
||||
}
|
||||
assert (PredMBB && "Couldn't find incoming machine-cfg edge for phi");
|
||||
|
||||
|
||||
unsigned ValReg;
|
||||
std::map<MachineBasicBlock*, unsigned>::iterator EntryIt =
|
||||
PHIValues.lower_bound(PredMBB);
|
||||
@@ -515,7 +515,7 @@ void V8ISel::SelectPHINodes() {
|
||||
// predecessor. Recycle it.
|
||||
ValReg = EntryIt->second;
|
||||
|
||||
} else {
|
||||
} else {
|
||||
// Get the incoming value into a virtual register.
|
||||
//
|
||||
Value *Val = PN->getIncomingValue(i);
|
||||
@@ -534,11 +534,11 @@ void V8ISel::SelectPHINodes() {
|
||||
// might be arbitrarily complex if it is a constant expression),
|
||||
// just insert the computation at the top of the basic block.
|
||||
MachineBasicBlock::iterator PI = PredMBB->begin();
|
||||
|
||||
|
||||
// Skip over any PHI nodes though!
|
||||
while (PI != PredMBB->end() && PI->getOpcode() == V8::PHI)
|
||||
++PI;
|
||||
|
||||
|
||||
ValReg = getReg(Val, PredMBB, PI);
|
||||
}
|
||||
|
||||
@@ -568,28 +568,28 @@ bool V8ISel::runOnFunction(Function &Fn) {
|
||||
// First pass over the function, lower any unknown intrinsic functions
|
||||
// with the IntrinsicLowering class.
|
||||
LowerUnknownIntrinsicFunctionCalls(Fn);
|
||||
|
||||
|
||||
F = &MachineFunction::construct(&Fn, TM);
|
||||
|
||||
|
||||
// Create all of the machine basic blocks for the function...
|
||||
for (Function::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
|
||||
F->getBasicBlockList().push_back(MBBMap[I] = new MachineBasicBlock(I));
|
||||
|
||||
|
||||
BB = &F->front();
|
||||
|
||||
|
||||
// Set up a frame object for the return address. This is used by the
|
||||
// llvm.returnaddress & llvm.frameaddress intrinisics.
|
||||
//ReturnAddressIndex = F->getFrameInfo()->CreateFixedObject(4, -4);
|
||||
|
||||
|
||||
// Copy incoming arguments off of the stack and out of fixed registers.
|
||||
LoadArgumentsToVirtualRegs(&Fn);
|
||||
|
||||
|
||||
// Instruction select everything except PHI nodes
|
||||
visit(Fn);
|
||||
|
||||
|
||||
// Select the PHI nodes
|
||||
SelectPHINodes();
|
||||
|
||||
|
||||
RegMap.clear();
|
||||
MBBMap.clear();
|
||||
F = 0;
|
||||
@@ -632,11 +632,11 @@ void V8ISel::emitFPToIntegerCast (MachineBasicBlock *BB,
|
||||
const Type *newTy, unsigned DestReg) {
|
||||
unsigned FPCastOpcode, FPStoreOpcode, FPSize, FPAlign;
|
||||
unsigned oldTyClass = getClassB(oldTy);
|
||||
if (oldTyClass == cFloat) {
|
||||
FPCastOpcode = V8::FSTOI; FPStoreOpcode = V8::STFri; FPSize = 4;
|
||||
if (oldTyClass == cFloat) {
|
||||
FPCastOpcode = V8::FSTOI; FPStoreOpcode = V8::STFri; FPSize = 4;
|
||||
FPAlign = TM.getTargetData().getFloatAlignment();
|
||||
} else { // it's a double
|
||||
FPCastOpcode = V8::FDTOI; FPStoreOpcode = V8::STDFri; FPSize = 8;
|
||||
FPCastOpcode = V8::FDTOI; FPStoreOpcode = V8::STDFri; FPSize = 8;
|
||||
FPAlign = TM.getTargetData().getDoubleAlignment();
|
||||
}
|
||||
unsigned TempReg = makeAnotherReg (oldTy);
|
||||
@@ -672,11 +672,11 @@ void V8ISel::emitCastOperation(MachineBasicBlock *BB,
|
||||
case cShort:
|
||||
case cInt:
|
||||
switch (oldTyClass) {
|
||||
case cLong:
|
||||
case cLong:
|
||||
// Treat it like a cast from the lower half of the value.
|
||||
emitIntegerCast (BB, IP, Type::IntTy, SrcReg+1, newTy, DestReg);
|
||||
break;
|
||||
case cFloat:
|
||||
case cFloat:
|
||||
case cDouble:
|
||||
emitFPToIntegerCast (BB, IP, oldTy, SrcReg, newTy, DestReg);
|
||||
break;
|
||||
@@ -742,10 +742,10 @@ void V8ISel::emitCastOperation(MachineBasicBlock *BB,
|
||||
unsigned TempReg = emitIntegerCast (BB, IP, OldHalfTy, SrcReg,
|
||||
NewHalfTy, DestReg+1, true);
|
||||
if (newTy->isSigned ()) {
|
||||
BuildMI (*BB, IP, V8::SRAri, 2, DestReg).addReg (TempReg)
|
||||
BuildMI (*BB, IP, V8::SRAri, 2, DestReg).addReg (TempReg)
|
||||
.addZImm (31);
|
||||
} else {
|
||||
BuildMI (*BB, IP, V8::ORrr, 2, DestReg).addReg (V8::G0)
|
||||
BuildMI (*BB, IP, V8::ORrr, 2, DestReg).addReg (V8::G0)
|
||||
.addReg (V8::G0);
|
||||
}
|
||||
break;
|
||||
@@ -1162,7 +1162,7 @@ void V8ISel::emitGEPOperation (MachineBasicBlock *MBB,
|
||||
if (isa<ConstantIntegral> (idx)) {
|
||||
// If idx is a constant, we don't have to emit the multiply.
|
||||
int64_t Val = cast<ConstantIntegral> (idx)->getRawValue ();
|
||||
if ((Val * elementSize) + 4096 < 8191) {
|
||||
if ((Val * elementSize) + 4096 < 8191) {
|
||||
// (Val * elementSize) is constant and fits in an immediate field.
|
||||
// emit: nextBasePtrReg = ADDri basePtrReg, (Val * elementSize)
|
||||
addImmed = true;
|
||||
@@ -1180,16 +1180,16 @@ void V8ISel::emitGEPOperation (MachineBasicBlock *MBB,
|
||||
OffsetReg = makeAnotherReg (Type::IntTy);
|
||||
unsigned idxReg = getReg (idx, MBB, IP);
|
||||
switch (elementSize) {
|
||||
case 1:
|
||||
case 1:
|
||||
BuildMI (*MBB, IP, V8::ORrr, 2, OffsetReg).addReg (V8::G0).addReg (idxReg);
|
||||
break;
|
||||
case 2:
|
||||
case 2:
|
||||
BuildMI (*MBB, IP, V8::SLLri, 2, OffsetReg).addReg (idxReg).addZImm (1);
|
||||
break;
|
||||
case 4:
|
||||
case 4:
|
||||
BuildMI (*MBB, IP, V8::SLLri, 2, OffsetReg).addReg (idxReg).addZImm (2);
|
||||
break;
|
||||
case 8:
|
||||
case 8:
|
||||
BuildMI (*MBB, IP, V8::SLLri, 2, OffsetReg).addReg (idxReg).addZImm (3);
|
||||
break;
|
||||
default: {
|
||||
@@ -1343,7 +1343,7 @@ void V8ISel::emitShift64 (MachineBasicBlock *MBB,
|
||||
// ba .lshr_continue
|
||||
|
||||
BB = oneShiftMBB;
|
||||
|
||||
|
||||
if (isSigned)
|
||||
BuildMI (BB, V8::SRAri, 2, OneShiftOutReg).addReg (SrcReg).addZImm (31);
|
||||
else
|
||||
@@ -1515,7 +1515,7 @@ void V8ISel::visitBinaryOperator (Instruction &I) {
|
||||
}
|
||||
|
||||
switch (getClassB (I.getType ())) {
|
||||
case cByte:
|
||||
case cByte:
|
||||
if (I.getType ()->isSigned ()) { // add byte
|
||||
BuildMI (BB, V8::ANDri, 2, DestReg).addReg (ResultReg).addZImm (0xff);
|
||||
} else { // add ubyte
|
||||
@@ -1562,7 +1562,7 @@ void V8ISel::visitSetCondInst(SetCondInst &I) {
|
||||
unsigned Op1Reg = getReg (I.getOperand (1));
|
||||
unsigned DestReg = getReg (I);
|
||||
const Type *Ty = I.getOperand (0)->getType ();
|
||||
|
||||
|
||||
// Compare the two values.
|
||||
if (getClass (Ty) < cLong) {
|
||||
BuildMI(BB, V8::SUBCCrr, 2, V8::G0).addReg(Op0Reg).addReg(Op1Reg);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===- SparcV8InstrInfo.cpp - SparcV8 Instruction Information ---*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the SparcV8 implementation of the TargetInstrInfo class.
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===- SparcV8InstrInfo.h - SparcV8 Instruction Information -----*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the SparcV8 implementation of the TargetInstrInfo class.
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===- SparcV8JITInfo.h - SparcV8 impl. of the JIT interface ----*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the SparcV8 implementation of the TargetJITInfo class.
|
||||
@@ -30,14 +30,14 @@ namespace llvm {
|
||||
/// is not supported for this target.
|
||||
///
|
||||
virtual void addPassesToJITCompile(FunctionPassManager &PM);
|
||||
|
||||
|
||||
/// replaceMachineCodeForFunction - Make it so that calling the function
|
||||
/// whose machine code is at OLD turns into a call to NEW, perhaps by
|
||||
/// overwriting OLD with a branch to NEW. This is used for self-modifying
|
||||
/// code.
|
||||
///
|
||||
virtual void replaceMachineCodeForFunction(void *Old, void *New);
|
||||
|
||||
|
||||
/// getJITStubForFunction - Create or return a stub for the specified
|
||||
/// function. This stub acts just like the specified function, except that
|
||||
/// it allows the "address" of the function to be taken without having to
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===- SparcV8RegisterInfo.cpp - SparcV8 Register Information ---*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the SparcV8 implementation of the MRegisterInfo class.
|
||||
@@ -44,7 +44,7 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
||||
const TargetRegisterClass *RC = getClass(SrcReg);
|
||||
|
||||
// On the order of operands here: think "[FrameIdx + 0] = SrcReg".
|
||||
if (RC == SparcV8::IntRegsRegisterClass)
|
||||
if (RC == SparcV8::IntRegsRegisterClass)
|
||||
BuildMI (MBB, I, V8::ST, 3).addFrameIndex (FrameIdx).addSImm (0)
|
||||
.addReg (SrcReg);
|
||||
else if (RC == SparcV8::FPRegsRegisterClass)
|
||||
@@ -61,7 +61,7 @@ void SparcV8RegisterInfo::
|
||||
loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
||||
unsigned DestReg, int FrameIdx) const {
|
||||
const TargetRegisterClass *RC = getClass(DestReg);
|
||||
if (RC == SparcV8::IntRegsRegisterClass)
|
||||
if (RC == SparcV8::IntRegsRegisterClass)
|
||||
BuildMI (MBB, I, V8::LD, 2, DestReg).addFrameIndex (FrameIdx).addSImm (0);
|
||||
else if (RC == SparcV8::FPRegsRegisterClass)
|
||||
BuildMI (MBB, I, V8::LDFri, 2, DestReg).addFrameIndex (FrameIdx)
|
||||
@@ -77,7 +77,7 @@ void SparcV8RegisterInfo::copyRegToReg(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator I,
|
||||
unsigned DestReg, unsigned SrcReg,
|
||||
const TargetRegisterClass *RC) const {
|
||||
if (RC == SparcV8::IntRegsRegisterClass)
|
||||
if (RC == SparcV8::IntRegsRegisterClass)
|
||||
BuildMI (MBB, I, V8::ORrr, 2, DestReg).addReg (V8::G0).addReg (SrcReg);
|
||||
else if (RC == SparcV8::FPRegsRegisterClass)
|
||||
BuildMI (MBB, I, V8::FMOVS, 1, DestReg).addReg (SrcReg);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===- SparcV8RegisterInfo.h - SparcV8 Register Information Impl -*- C++ -*-==//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the SparcV8 implementation of the MRegisterInfo class.
|
||||
@@ -33,7 +33,7 @@ struct SparcV8RegisterInfo : public SparcV8GenRegisterInfo {
|
||||
void loadRegFromStackSlot(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MBBI,
|
||||
unsigned DestReg, int FrameIndex) const;
|
||||
|
||||
|
||||
void copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
|
||||
unsigned DestReg, unsigned SrcReg,
|
||||
const TargetRegisterClass *RC) const;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
//===-- SparcV8TargetMachine.cpp - Define TargetMachine for SparcV8 -------===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -87,7 +87,7 @@ bool SparcV8TargetMachine::addPassesToEmitAssembly(PassManager &PM,
|
||||
// Print LLVM code input to instruction selector:
|
||||
if (PrintMachineCode)
|
||||
PM.add(new PrintFunctionPass());
|
||||
|
||||
|
||||
PM.add(createSparcV8SimpleInstructionSelector(*this));
|
||||
|
||||
// Print machine instructions as they were initially generated.
|
||||
@@ -126,7 +126,7 @@ void SparcV8JITInfo::addPassesToJITCompile(FunctionPassManager &PM) {
|
||||
|
||||
// Replace malloc and free instructions with library calls.
|
||||
PM.add(createLowerAllocationsPass());
|
||||
|
||||
|
||||
// FIXME: implement the switch instruction in the instruction selector.
|
||||
PM.add(createLowerSwitchPass());
|
||||
|
||||
@@ -134,17 +134,17 @@ void SparcV8JITInfo::addPassesToJITCompile(FunctionPassManager &PM) {
|
||||
PM.add(createLowerInvokePass());
|
||||
|
||||
PM.add(createLowerConstantExpressionsPass());
|
||||
|
||||
|
||||
// Make sure that no unreachable blocks are instruction selected.
|
||||
PM.add(createUnreachableBlockEliminationPass());
|
||||
|
||||
// FIXME: implement the select instruction in the instruction selector.
|
||||
PM.add(createLowerSelectPass());
|
||||
|
||||
|
||||
// Print LLVM code input to instruction selector:
|
||||
if (PrintMachineCode)
|
||||
PM.add(new PrintFunctionPass());
|
||||
|
||||
|
||||
PM.add(createSparcV8SimpleInstructionSelector(TM));
|
||||
|
||||
// Print machine instructions as they were initially generated.
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
//===-- SparcV8TargetMachine.h - Define TargetMachine for SparcV8 -*- C++ -*-=//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
// This file declares the SparcV8 specific subclass of TargetMachine.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
@@ -52,7 +52,7 @@ public:
|
||||
///
|
||||
virtual bool addPassesToEmitMachineCode(FunctionPassManager &PM,
|
||||
MachineCodeEmitter &MCE);
|
||||
|
||||
|
||||
virtual bool addPassesToEmitAssembly(PassManager &PM, std::ostream &Out);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===- llvm/Transforms/DecomposeMultiDimRefs.cpp - Lower array refs to 1D -===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// DecomposeMultiDimRefs - Convert multi-dimensional references consisting of
|
||||
@@ -57,28 +57,28 @@ static inline bool isZeroConst (Value *V) {
|
||||
}
|
||||
|
||||
// Function: DecomposeArrayRef()
|
||||
//
|
||||
//
|
||||
// For any GetElementPtrInst with 2 or more array and structure indices:
|
||||
//
|
||||
//
|
||||
// opCode CompositeType* P, [uint|ubyte] idx1, ..., [uint|ubyte] idxN
|
||||
//
|
||||
//
|
||||
// this function generates the following sequence:
|
||||
//
|
||||
//
|
||||
// ptr1 = getElementPtr P, idx1
|
||||
// ptr2 = getElementPtr ptr1, 0, idx2
|
||||
// ...
|
||||
// ptrN-1 = getElementPtr ptrN-2, 0, idxN-1
|
||||
// opCode ptrN-1, 0, idxN // New-MAI
|
||||
//
|
||||
//
|
||||
// Then it replaces the original instruction with this sequence,
|
||||
// and replaces all uses of the original instruction with New-MAI.
|
||||
// If idx1 is 0, we simply omit the first getElementPtr instruction.
|
||||
//
|
||||
//
|
||||
// On return: BBI points to the instruction after the current one
|
||||
// (whether or not *BBI was replaced).
|
||||
//
|
||||
//
|
||||
// Return value: true if the instruction was replaced; false otherwise.
|
||||
//
|
||||
//
|
||||
bool llvm::DecomposeArrayRef(GetElementPtrInst* GEP) {
|
||||
if (GEP->getNumIndices() < 2
|
||||
|| (GEP->getNumIndices() == 2
|
||||
@@ -97,7 +97,7 @@ bool llvm::DecomposeArrayRef(GetElementPtrInst* GEP) {
|
||||
User::const_op_iterator OI = GEP->idx_begin(), OE = GEP->idx_end();
|
||||
for (; OI+1 != OE; ++OI) {
|
||||
std::vector<Value*> Indices;
|
||||
|
||||
|
||||
// If this is the first index and is 0, skip it and move on!
|
||||
if (OI == GEP->idx_begin()) {
|
||||
if (isZeroConst (*OI))
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===-- EmitBytecodeToAssembly.cpp - Emit bytecode to SparcV9 .s File ------==//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements the pass that writes LLVM bytecode as data to a sparc
|
||||
@@ -31,7 +31,7 @@ namespace {
|
||||
typedef int int_type;
|
||||
typedef std::streampos pos_type;
|
||||
typedef std::streamoff off_type;
|
||||
|
||||
|
||||
sparcasmbuf(std::ostream &On) : BaseStr(On) {}
|
||||
|
||||
virtual int_type overflow(int_type C) {
|
||||
@@ -65,19 +65,19 @@ namespace {
|
||||
const std::string &symName) {
|
||||
// Prologue:
|
||||
// Output a comment describing the object.
|
||||
Out << "!" << comment << "\n";
|
||||
Out << "!" << comment << "\n";
|
||||
// Switch the current section to .rodata in the assembly output:
|
||||
Out << "\t.section \".rodata\"\n\t.align 8\n";
|
||||
Out << "\t.section \".rodata\"\n\t.align 8\n";
|
||||
// Output a global symbol naming the object:
|
||||
Out << "\t.global " << symName << "\n";
|
||||
Out << "\t.type " << symName << ",#object\n";
|
||||
Out << symName << ":\n";
|
||||
Out << "\t.global " << symName << "\n";
|
||||
Out << "\t.type " << symName << ",#object\n";
|
||||
Out << symName << ":\n";
|
||||
}
|
||||
|
||||
static void writeEpilogue (std::ostream &Out, const std::string &symName) {
|
||||
// Epilogue:
|
||||
// Output a local symbol marking the end of the object:
|
||||
Out << ".end_" << symName << ":\n";
|
||||
Out << ".end_" << symName << ":\n";
|
||||
// Output size directive giving the size of the object:
|
||||
Out << "\t.size " << symName << ", .end_" << symName << "-" << symName
|
||||
<< "\n";
|
||||
@@ -90,7 +90,7 @@ namespace {
|
||||
SparcV9BytecodeWriter(std::ostream &out) : Out(out) {}
|
||||
|
||||
const char *getPassName() const { return "Emit Bytecode to SparcV9 Assembly";}
|
||||
|
||||
|
||||
virtual bool runOnModule(Module &M) {
|
||||
// Write an object containing the bytecode to the SPARC assembly stream
|
||||
writePrologue (Out, "LLVM BYTECODE OUTPUT", "LLVMBytecode");
|
||||
@@ -101,7 +101,7 @@ namespace {
|
||||
// Write an object containing its length as an integer to the
|
||||
// SPARC assembly stream
|
||||
writePrologue (Out, "LLVM BYTECODE LENGTH", "llvm_length");
|
||||
Out <<"\t.word\t.end_LLVMBytecode-LLVMBytecode\n";
|
||||
Out <<"\t.word\t.end_LLVMBytecode-LLVMBytecode\n";
|
||||
writeEpilogue (Out, "llvm_length");
|
||||
|
||||
return false;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,10 @@
|
||||
//===- SchedGraph.cpp - Scheduling Graph Implementation -------------------===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Scheduling graph based on SSA graph plus extra dependence edges capturing
|
||||
@@ -31,7 +31,7 @@ namespace llvm {
|
||||
|
||||
// The following two types need to be classes, not typedefs, so we can use
|
||||
// opaque declarations in SchedGraph.h
|
||||
//
|
||||
//
|
||||
struct RefVec: public std::vector<std::pair<SchedGraphNode*, int> > {
|
||||
typedef std::vector<std::pair<SchedGraphNode*,int> >::iterator iterator;
|
||||
typedef
|
||||
@@ -49,9 +49,9 @@ struct ValueToDefVecMap: public hash_map<const Value*, RefVec> {
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
// class SchedGraphNode
|
||||
//
|
||||
//
|
||||
|
||||
SchedGraphNode::SchedGraphNode(unsigned NID, MachineBasicBlock *mbb,
|
||||
int indexInBB, const TargetMachine& Target)
|
||||
@@ -82,9 +82,9 @@ SchedGraphNode::SchedGraphNode(unsigned NID, MachineBasicBlock *mbb,
|
||||
SchedGraphNode::~SchedGraphNode() {
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// class SchedGraph
|
||||
//
|
||||
//
|
||||
SchedGraph::SchedGraph(MachineBasicBlock &mbb, const TargetMachine& target)
|
||||
: MBB(mbb) {
|
||||
buildGraph(target);
|
||||
@@ -124,7 +124,7 @@ void SchedGraph::dump() const {
|
||||
|
||||
void SchedGraph::addDummyEdges() {
|
||||
assert(graphRoot->getNumOutEdges() == 0);
|
||||
|
||||
|
||||
for (const_iterator I=begin(); I != end(); ++I) {
|
||||
SchedGraphNode* node = (*I).second;
|
||||
assert(node != graphRoot && node != graphLeaf);
|
||||
@@ -142,9 +142,9 @@ void SchedGraph::addCDEdges(const TerminatorInst* term,
|
||||
const TargetMachine& target) {
|
||||
const TargetInstrInfo& mii = *target.getInstrInfo();
|
||||
MachineCodeForInstruction &termMvec = MachineCodeForInstruction::get(term);
|
||||
|
||||
|
||||
// Find the first branch instr in the sequence of machine instrs for term
|
||||
//
|
||||
//
|
||||
unsigned first = 0;
|
||||
while (! mii.isBranch(termMvec[first]->getOpcode()) &&
|
||||
! mii.isReturn(termMvec[first]->getOpcode()))
|
||||
@@ -153,18 +153,18 @@ void SchedGraph::addCDEdges(const TerminatorInst* term,
|
||||
"No branch instructions for terminator? Ok, but weird!");
|
||||
if (first == termMvec.size())
|
||||
return;
|
||||
|
||||
|
||||
SchedGraphNode* firstBrNode = getGraphNodeForInstr(termMvec[first]);
|
||||
|
||||
|
||||
// Add CD edges from each instruction in the sequence to the
|
||||
// *last preceding* branch instr. in the sequence
|
||||
// *last preceding* branch instr. in the sequence
|
||||
// Use a latency of 0 because we only need to prevent out-of-order issue.
|
||||
//
|
||||
//
|
||||
for (unsigned i = termMvec.size(); i > first+1; --i) {
|
||||
SchedGraphNode* toNode = getGraphNodeForInstr(termMvec[i-1]);
|
||||
assert(toNode && "No node for instr generated for branch/ret?");
|
||||
|
||||
for (unsigned j = i-1; j != 0; --j)
|
||||
|
||||
for (unsigned j = i-1; j != 0; --j)
|
||||
if (mii.isBranch(termMvec[j-1]->getOpcode()) ||
|
||||
mii.isReturn(termMvec[j-1]->getOpcode())) {
|
||||
SchedGraphNode* brNode = getGraphNodeForInstr(termMvec[j-1]);
|
||||
@@ -174,36 +174,36 @@ void SchedGraph::addCDEdges(const TerminatorInst* term,
|
||||
break; // only one incoming edge is enough
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Add CD edges from each instruction preceding the first branch
|
||||
// to the first branch. Use a latency of 0 as above.
|
||||
//
|
||||
//
|
||||
for (unsigned i = first; i != 0; --i) {
|
||||
SchedGraphNode* fromNode = getGraphNodeForInstr(termMvec[i-1]);
|
||||
assert(fromNode && "No node for instr generated for branch?");
|
||||
(void) new SchedGraphEdge(fromNode, firstBrNode, SchedGraphEdge::CtrlDep,
|
||||
SchedGraphEdge::NonDataDep, 0);
|
||||
}
|
||||
|
||||
|
||||
// Now add CD edges to the first branch instruction in the sequence from
|
||||
// all preceding instructions in the basic block. Use 0 latency again.
|
||||
//
|
||||
//
|
||||
for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ++I){
|
||||
if (&*I == termMvec[first]) // reached the first branch
|
||||
break;
|
||||
|
||||
|
||||
SchedGraphNode* fromNode = getGraphNodeForInstr(I);
|
||||
if (fromNode == NULL)
|
||||
continue; // dummy instruction, e.g., PHI
|
||||
|
||||
|
||||
(void) new SchedGraphEdge(fromNode, firstBrNode,
|
||||
SchedGraphEdge::CtrlDep,
|
||||
SchedGraphEdge::NonDataDep, 0);
|
||||
|
||||
|
||||
// If we find any other machine instructions (other than due to
|
||||
// the terminator) that also have delay slots, add an outgoing edge
|
||||
// from the instruction to the instructions in the delay slots.
|
||||
//
|
||||
//
|
||||
unsigned d = mii.getNumDelaySlots(I->getOpcode());
|
||||
|
||||
MachineBasicBlock::iterator J = I; ++J;
|
||||
@@ -239,14 +239,14 @@ static const unsigned int SG_DepOrderArray[][3] = {
|
||||
// instructions, where at least one is a store or a call.
|
||||
// Use latency 1 just to ensure that memory operations are ordered;
|
||||
// latency does not otherwise matter (true dependences enforce that).
|
||||
//
|
||||
//
|
||||
void SchedGraph::addMemEdges(const std::vector<SchedGraphNode*>& memNodeVec,
|
||||
const TargetMachine& target) {
|
||||
const TargetInstrInfo& mii = *target.getInstrInfo();
|
||||
|
||||
|
||||
// Instructions in memNodeVec are in execution order within the basic block,
|
||||
// so simply look at all pairs <memNodeVec[i], memNodeVec[j: j > i]>.
|
||||
//
|
||||
//
|
||||
for (unsigned im=0, NM=memNodeVec.size(); im < NM; im++) {
|
||||
MachineOpCode fromOpCode = memNodeVec[im]->getOpcode();
|
||||
int fromType = (mii.isCall(fromOpCode)? SG_CALL_REF
|
||||
@@ -257,28 +257,28 @@ void SchedGraph::addMemEdges(const std::vector<SchedGraphNode*>& memNodeVec,
|
||||
int toType = (mii.isCall(toOpCode)? SG_CALL_REF
|
||||
: (mii.isLoad(toOpCode)? SG_LOAD_REF
|
||||
: SG_STORE_REF));
|
||||
|
||||
|
||||
if (fromType != SG_LOAD_REF || toType != SG_LOAD_REF)
|
||||
(void) new SchedGraphEdge(memNodeVec[im], memNodeVec[jm],
|
||||
SchedGraphEdge::MemoryDep,
|
||||
SG_DepOrderArray[fromType][toType], 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add edges from/to CC reg instrs to/from call instrs.
|
||||
// Essentially this prevents anything that sets or uses a CC reg from being
|
||||
// reordered w.r.t. a call.
|
||||
// Use a latency of 0 because we only need to prevent out-of-order issue,
|
||||
// like with control dependences.
|
||||
//
|
||||
//
|
||||
void SchedGraph::addCallDepEdges(const std::vector<SchedGraphNode*>& callDepNodeVec,
|
||||
const TargetMachine& target) {
|
||||
const TargetInstrInfo& mii = *target.getInstrInfo();
|
||||
|
||||
|
||||
// Instructions in memNodeVec are in execution order within the basic block,
|
||||
// so simply look at all pairs <memNodeVec[i], memNodeVec[j: j > i]>.
|
||||
//
|
||||
//
|
||||
for (unsigned ic=0, NC=callDepNodeVec.size(); ic < NC; ic++)
|
||||
if (mii.isCall(callDepNodeVec[ic]->getOpcode())) {
|
||||
// Add SG_CALL_REF edges from all preds to this instruction.
|
||||
@@ -286,26 +286,26 @@ void SchedGraph::addCallDepEdges(const std::vector<SchedGraphNode*>& callDepNode
|
||||
(void) new SchedGraphEdge(callDepNodeVec[jc], callDepNodeVec[ic],
|
||||
SchedGraphEdge::MachineRegister,
|
||||
MachineIntRegsRID, 0);
|
||||
|
||||
|
||||
// And do the same from this instruction to all successors.
|
||||
for (unsigned jc=ic+1; jc < NC; jc++)
|
||||
(void) new SchedGraphEdge(callDepNodeVec[ic], callDepNodeVec[jc],
|
||||
SchedGraphEdge::MachineRegister,
|
||||
MachineIntRegsRID, 0);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CALL_DEP_NODE_VEC_CANNOT_WORK
|
||||
// Find the call instruction nodes and put them in a vector.
|
||||
std::vector<SchedGraphNode*> callNodeVec;
|
||||
for (unsigned im=0, NM=memNodeVec.size(); im < NM; im++)
|
||||
if (mii.isCall(memNodeVec[im]->getOpcode()))
|
||||
callNodeVec.push_back(memNodeVec[im]);
|
||||
|
||||
|
||||
// Now walk the entire basic block, looking for CC instructions *and*
|
||||
// call instructions, and keep track of the order of the instructions.
|
||||
// Use the call node vec to quickly find earlier and later call nodes
|
||||
// relative to the current CC instruction.
|
||||
//
|
||||
//
|
||||
int lastCallNodeIdx = -1;
|
||||
for (unsigned i=0, N=bbMvec.size(); i < N; i++)
|
||||
if (mii.isCall(bbMvec[i]->getOpcode())) {
|
||||
@@ -334,12 +334,12 @@ void SchedGraph::addMachineRegEdges(RegToRefVecMap& regToRefVecMap,
|
||||
const TargetMachine& target) {
|
||||
// This code assumes that two registers with different numbers are
|
||||
// not aliased!
|
||||
//
|
||||
//
|
||||
for (RegToRefVecMap::iterator I = regToRefVecMap.begin();
|
||||
I != regToRefVecMap.end(); ++I) {
|
||||
int regNum = (*I).first;
|
||||
RefVec& regRefVec = (*I).second;
|
||||
|
||||
|
||||
// regRefVec is ordered by control flow order in the basic block
|
||||
for (unsigned i=0; i < regRefVec.size(); ++i) {
|
||||
SchedGraphNode* node = regRefVec[i].first;
|
||||
@@ -348,7 +348,7 @@ void SchedGraph::addMachineRegEdges(RegToRefVecMap& regToRefVecMap,
|
||||
node->getMachineInstr()->getExplOrImplOperand(opNum);
|
||||
bool isDef = mop.isDef() && !mop.isUse();
|
||||
bool isDefAndUse = mop.isDef() && mop.isUse();
|
||||
|
||||
|
||||
for (unsigned p=0; p < i; ++p) {
|
||||
SchedGraphNode* prevNode = regRefVec[p].first;
|
||||
if (prevNode != node) {
|
||||
@@ -365,7 +365,7 @@ void SchedGraph::addMachineRegEdges(RegToRefVecMap& regToRefVecMap,
|
||||
new SchedGraphEdge(prevNode, node, regNum,
|
||||
SchedGraphEdge::AntiDep);
|
||||
}
|
||||
|
||||
|
||||
if (prevIsDef)
|
||||
if (!isDef || isDefAndUse)
|
||||
new SchedGraphEdge(prevNode, node, regNum,
|
||||
@@ -380,7 +380,7 @@ void SchedGraph::addMachineRegEdges(RegToRefVecMap& regToRefVecMap,
|
||||
// Adds dependences to/from refNode from/to all other defs
|
||||
// in the basic block. refNode may be a use, a def, or both.
|
||||
// We do not consider other uses because we are not building use-use deps.
|
||||
//
|
||||
//
|
||||
void SchedGraph::addEdgesForValue(SchedGraphNode* refNode,
|
||||
const RefVec& defVec,
|
||||
const Value* defValue,
|
||||
@@ -392,7 +392,7 @@ void SchedGraph::addEdgesForValue(SchedGraphNode* refNode,
|
||||
for (RefVec::const_iterator I=defVec.begin(), E=defVec.end(); I != E; ++I) {
|
||||
if ((*I).first == refNode)
|
||||
continue; // Dont add any self-loops
|
||||
|
||||
|
||||
if ((*I).first->getOrigIndexInBB() < refNode->getOrigIndexInBB()) {
|
||||
// (*).first is before refNode
|
||||
if (refNodeIsDef && !refNodeIsUse)
|
||||
@@ -420,9 +420,9 @@ void SchedGraph::addEdgesForInstruction(const MachineInstr& MI,
|
||||
SchedGraphNode* node = getGraphNodeForInstr(&MI);
|
||||
if (node == NULL)
|
||||
return;
|
||||
|
||||
|
||||
// Add edges for all operands of the machine instruction.
|
||||
//
|
||||
//
|
||||
for (unsigned i = 0, numOps = MI.getNumOperands(); i != numOps; ++i) {
|
||||
switch (MI.getOperand(i).getType()) {
|
||||
case MachineOperand::MO_VirtualRegister:
|
||||
@@ -435,26 +435,26 @@ void SchedGraph::addEdgesForInstruction(const MachineInstr& MI,
|
||||
target);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case MachineOperand::MO_MachineRegister:
|
||||
break;
|
||||
|
||||
break;
|
||||
|
||||
case MachineOperand::MO_SignExtendedImmed:
|
||||
case MachineOperand::MO_UnextendedImmed:
|
||||
case MachineOperand::MO_PCRelativeDisp:
|
||||
case MachineOperand::MO_ConstantPoolIndex:
|
||||
break; // nothing to do for immediate fields
|
||||
|
||||
|
||||
default:
|
||||
assert(0 && "Unknown machine operand type in SchedGraph builder");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Add edges for values implicitly used by the machine instruction.
|
||||
// Examples include function arguments to a Call instructions or the return
|
||||
// value of a Ret instruction.
|
||||
//
|
||||
//
|
||||
for (unsigned i=0, N=MI.getNumImplicitRefs(); i < N; ++i)
|
||||
if (MI.getImplicitOp(i).isUse())
|
||||
if (const Value* srcI = MI.getImplicitRef(i)) {
|
||||
@@ -474,26 +474,26 @@ void SchedGraph::findDefUseInfoAtInstr(const TargetMachine& target,
|
||||
RegToRefVecMap& regToRefVecMap,
|
||||
ValueToDefVecMap& valueToDefVecMap) {
|
||||
const TargetInstrInfo& mii = *target.getInstrInfo();
|
||||
|
||||
|
||||
MachineOpCode opCode = node->getOpcode();
|
||||
|
||||
|
||||
if (mii.isCall(opCode) || mii.isCCInstr(opCode))
|
||||
callDepNodeVec.push_back(node);
|
||||
|
||||
|
||||
if (mii.isLoad(opCode) || mii.isStore(opCode) || mii.isCall(opCode))
|
||||
memNodeVec.push_back(node);
|
||||
|
||||
|
||||
// Collect the register references and value defs. for explicit operands
|
||||
//
|
||||
//
|
||||
const MachineInstr& MI = *node->getMachineInstr();
|
||||
for (int i=0, numOps = (int) MI.getNumOperands(); i < numOps; i++) {
|
||||
const MachineOperand& mop = MI.getOperand(i);
|
||||
|
||||
|
||||
// if this references a register other than the hardwired
|
||||
// "zero" register, record the reference.
|
||||
if (mop.hasAllocatedReg()) {
|
||||
unsigned regNum = mop.getReg();
|
||||
|
||||
|
||||
// If this is not a dummy zero register, record the reference in order
|
||||
if (regNum != target.getRegInfo()->getZeroRegNum())
|
||||
regToRefVecMap[mop.getReg()]
|
||||
@@ -509,27 +509,27 @@ void SchedGraph::findDefUseInfoAtInstr(const TargetMachine& target,
|
||||
->isRegVolatile(regInClass))
|
||||
callDepNodeVec.push_back(node);
|
||||
}
|
||||
|
||||
|
||||
continue; // nothing more to do
|
||||
}
|
||||
|
||||
|
||||
// ignore all other non-def operands
|
||||
if (!MI.getOperand(i).isDef())
|
||||
continue;
|
||||
|
||||
|
||||
// We must be defining a value.
|
||||
assert((mop.getType() == MachineOperand::MO_VirtualRegister ||
|
||||
mop.getType() == MachineOperand::MO_CCRegister)
|
||||
&& "Do not expect any other kind of operand to be defined!");
|
||||
assert(mop.getVRegValue() != NULL && "Null value being defined?");
|
||||
|
||||
valueToDefVecMap[mop.getVRegValue()].push_back(std::make_pair(node, i));
|
||||
|
||||
valueToDefVecMap[mop.getVRegValue()].push_back(std::make_pair(node, i));
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
//
|
||||
// Collect value defs. for implicit operands. They may have allocated
|
||||
// physical registers also.
|
||||
//
|
||||
//
|
||||
for (unsigned i=0, N = MI.getNumImplicitRefs(); i != N; ++i) {
|
||||
const MachineOperand& mop = MI.getImplicitOp(i);
|
||||
if (mop.hasAllocatedReg()) {
|
||||
@@ -543,7 +543,7 @@ void SchedGraph::findDefUseInfoAtInstr(const TargetMachine& target,
|
||||
if (mop.isDef()) {
|
||||
assert(MI.getImplicitRef(i) != NULL && "Null value being defined?");
|
||||
valueToDefVecMap[MI.getImplicitRef(i)].push_back(
|
||||
std::make_pair(node, -i));
|
||||
std::make_pair(node, -i));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -556,7 +556,7 @@ void SchedGraph::buildNodesForBB(const TargetMachine& target,
|
||||
RegToRefVecMap& regToRefVecMap,
|
||||
ValueToDefVecMap& valueToDefVecMap) {
|
||||
const TargetInstrInfo& mii = *target.getInstrInfo();
|
||||
|
||||
|
||||
// Build graph nodes for each VM instruction and gather def/use info.
|
||||
// Do both those together in a single pass over all machine instructions.
|
||||
unsigned i = 0;
|
||||
@@ -565,7 +565,7 @@ void SchedGraph::buildNodesForBB(const TargetMachine& target,
|
||||
if (I->getOpcode() != V9::PHI) {
|
||||
SchedGraphNode* node = new SchedGraphNode(getNumNodes(), &MBB, i, target);
|
||||
noteGraphNodeForInstr(I, node);
|
||||
|
||||
|
||||
// Remember all register references and value defs
|
||||
findDefUseInfoAtInstr(target, node, memNodeVec, callDepNodeVec,
|
||||
regToRefVecMap, valueToDefVecMap);
|
||||
@@ -575,11 +575,11 @@ void SchedGraph::buildNodesForBB(const TargetMachine& target,
|
||||
|
||||
void SchedGraph::buildGraph(const TargetMachine& target) {
|
||||
// Use this data structure to note all machine operands that compute
|
||||
// ordinary LLVM values. These must be computed defs (i.e., instructions).
|
||||
// ordinary LLVM values. These must be computed defs (i.e., instructions).
|
||||
// Note that there may be multiple machine instructions that define
|
||||
// each Value.
|
||||
ValueToDefVecMap valueToDefVecMap;
|
||||
|
||||
|
||||
// Use this data structure to note all memory instructions.
|
||||
// We use this to add memory dependence edges without a second full walk.
|
||||
std::vector<SchedGraphNode*> memNodeVec;
|
||||
@@ -587,7 +587,7 @@ void SchedGraph::buildGraph(const TargetMachine& target) {
|
||||
// Use this data structure to note all instructions that access physical
|
||||
// registers that can be modified by a call (including call instructions)
|
||||
std::vector<SchedGraphNode*> callDepNodeVec;
|
||||
|
||||
|
||||
// Use this data structure to note any uses or definitions of
|
||||
// machine registers so we can add edges for those later without
|
||||
// extra passes over the nodes.
|
||||
@@ -595,9 +595,9 @@ void SchedGraph::buildGraph(const TargetMachine& target) {
|
||||
// ordered according to control-flow order. This only works for a
|
||||
// single basic block, hence the assertion. Each reference is identified
|
||||
// by the pair: <node, operand-number>.
|
||||
//
|
||||
//
|
||||
RegToRefVecMap regToRefVecMap;
|
||||
|
||||
|
||||
// Make a dummy root node. We'll add edges to the real roots later.
|
||||
graphRoot = new SchedGraphNode(0, NULL, -1, target);
|
||||
graphLeaf = new SchedGraphNode(1, NULL, -1, target);
|
||||
@@ -611,7 +611,7 @@ void SchedGraph::buildGraph(const TargetMachine& target) {
|
||||
|
||||
buildNodesForBB(target, MBB, memNodeVec, callDepNodeVec,
|
||||
regToRefVecMap, valueToDefVecMap);
|
||||
|
||||
|
||||
//----------------------------------------------------------------
|
||||
// Now add edges for the following (all are incoming edges except (4)):
|
||||
// (1) operands of the machine instruction, including hidden operands
|
||||
@@ -625,19 +625,19 @@ void SchedGraph::buildGraph(const TargetMachine& target) {
|
||||
// 2-way conditional branches, multiple CD edges are needed
|
||||
// (see addCDEdges for details).
|
||||
// Also, note any uses or defs of machine registers.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------
|
||||
|
||||
|
||||
// First, add edges to the terminator instruction of the basic block.
|
||||
this->addCDEdges(MBB.getBasicBlock()->getTerminator(), target);
|
||||
|
||||
|
||||
// Then add memory dep edges: store->load, load->store, and store->store.
|
||||
// Call instructions are treated as both load and store.
|
||||
this->addMemEdges(memNodeVec, target);
|
||||
|
||||
// Then add edges between call instructions and CC set/use instructions
|
||||
this->addCallDepEdges(callDepNodeVec, target);
|
||||
|
||||
|
||||
// Then add incoming def-use (SSA) edges for each machine instruction.
|
||||
for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ++I)
|
||||
addEdgesForInstruction(*I, valueToDefVecMap, target);
|
||||
@@ -650,9 +650,9 @@ void SchedGraph::buildGraph(const TargetMachine& target) {
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
// class SchedGraphSet
|
||||
//
|
||||
//
|
||||
SchedGraphSet::SchedGraphSet(const Function* _function,
|
||||
const TargetMachine& target) :
|
||||
function(_function) {
|
||||
@@ -669,10 +669,10 @@ SchedGraphSet::~SchedGraphSet() {
|
||||
void SchedGraphSet::dump() const {
|
||||
std::cerr << "======== Sched graphs for function `" << function->getName()
|
||||
<< "' ========\n\n";
|
||||
|
||||
|
||||
for (const_iterator I=begin(); I != end(); ++I)
|
||||
(*I)->dump();
|
||||
|
||||
|
||||
std::cerr << "\n====== End graphs for function `" << function->getName()
|
||||
<< "' ========\n\n";
|
||||
}
|
||||
@@ -689,28 +689,28 @@ void SchedGraphSet::buildGraphsForMethod(const Function *F,
|
||||
void SchedGraphEdge::print(std::ostream &os) const {
|
||||
os << "edge [" << src->getNodeId() << "] -> ["
|
||||
<< sink->getNodeId() << "] : ";
|
||||
|
||||
|
||||
switch(depType) {
|
||||
case SchedGraphEdge::CtrlDep:
|
||||
os<< "Control Dep";
|
||||
os<< "Control Dep";
|
||||
break;
|
||||
case SchedGraphEdge::ValueDep:
|
||||
os<< "Reg Value " << *val;
|
||||
case SchedGraphEdge::ValueDep:
|
||||
os<< "Reg Value " << *val;
|
||||
break;
|
||||
case SchedGraphEdge::MemoryDep:
|
||||
os<< "Memory Dep";
|
||||
os<< "Memory Dep";
|
||||
break;
|
||||
case SchedGraphEdge::MachineRegister:
|
||||
case SchedGraphEdge::MachineRegister:
|
||||
os<< "Reg " << machineRegNum;
|
||||
break;
|
||||
case SchedGraphEdge::MachineResource:
|
||||
os<<"Resource "<< resourceId;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
os << " : delay = " << minDelay << "\n";
|
||||
}
|
||||
|
||||
@@ -718,7 +718,7 @@ void SchedGraphNode::print(std::ostream &os) const {
|
||||
os << std::string(8, ' ')
|
||||
<< "Node " << ID << " : "
|
||||
<< "latency = " << latency << "\n" << std::string(12, ' ');
|
||||
|
||||
|
||||
if (getMachineInstr() == NULL)
|
||||
os << "(Dummy node)\n";
|
||||
else {
|
||||
@@ -726,7 +726,7 @@ void SchedGraphNode::print(std::ostream &os) const {
|
||||
os << inEdges.size() << " Incoming Edges:\n";
|
||||
for (unsigned i=0, N = inEdges.size(); i < N; i++)
|
||||
os << std::string(16, ' ') << *inEdges[i];
|
||||
|
||||
|
||||
os << std::string(12, ' ') << outEdges.size()
|
||||
<< " Outgoing Edges:\n";
|
||||
for (unsigned i=0, N= outEdges.size(); i < N; i++)
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
//===-- SchedGraph.h - Scheduling Graph -------------------------*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This is a scheduling graph based on SSA graph plus extra dependence edges
|
||||
// capturing dependences due to machine resources (machine registers, CC
|
||||
// registers, and any others).
|
||||
//
|
||||
//
|
||||
// This graph tries to leverage the SSA graph as much as possible, but captures
|
||||
// the extra dependences through a common interface.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CODEGEN_SCHEDGRAPH_H
|
||||
@@ -37,7 +37,7 @@ class SchedGraphNode : public SchedGraphNodeCommon {
|
||||
const MachineInstr *MI;
|
||||
|
||||
|
||||
SchedGraphNode(unsigned nodeId, MachineBasicBlock *mbb, int indexInBB,
|
||||
SchedGraphNode(unsigned nodeId, MachineBasicBlock *mbb, int indexInBB,
|
||||
const TargetMachine& Target);
|
||||
~SchedGraphNode();
|
||||
|
||||
@@ -58,21 +58,21 @@ public:
|
||||
class SchedGraph : public SchedGraphCommon {
|
||||
MachineBasicBlock &MBB;
|
||||
hash_map<const MachineInstr*, SchedGraphNode*> GraphMap;
|
||||
|
||||
|
||||
public:
|
||||
typedef hash_map<const MachineInstr*, SchedGraphNode*>::const_iterator iterator;
|
||||
typedef hash_map<const MachineInstr*, SchedGraphNode*>::const_iterator const_iterator;
|
||||
|
||||
|
||||
MachineBasicBlock& getBasicBlock() const{return MBB;}
|
||||
const unsigned int getNumNodes() const { return GraphMap.size()+2; }
|
||||
SchedGraphNode* getGraphNodeForInstr(const MachineInstr* MI) const {
|
||||
const_iterator onePair = find(MI);
|
||||
return (onePair != end())? onePair->second : NULL;
|
||||
}
|
||||
|
||||
|
||||
// Debugging support
|
||||
void dump() const;
|
||||
|
||||
|
||||
protected:
|
||||
SchedGraph(MachineBasicBlock& mbb, const TargetMachine& TM);
|
||||
~SchedGraph();
|
||||
@@ -86,17 +86,17 @@ protected:
|
||||
hash_map<const MachineInstr*, SchedGraphNode*>::const_iterator end() const {
|
||||
return GraphMap.end();
|
||||
}
|
||||
|
||||
|
||||
unsigned size() { return GraphMap.size(); }
|
||||
iterator find(const MachineInstr *MI) const { return GraphMap.find(MI); }
|
||||
|
||||
|
||||
SchedGraphNode *&operator[](const MachineInstr *MI) {
|
||||
return GraphMap[MI];
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
friend class SchedGraphSet; // give access to ctor
|
||||
|
||||
|
||||
inline void noteGraphNodeForInstr (const MachineInstr* minstr,
|
||||
SchedGraphNode* node) {
|
||||
assert((*this)[minstr] == NULL);
|
||||
@@ -107,39 +107,39 @@ private:
|
||||
// Graph builder
|
||||
//
|
||||
void buildGraph(const TargetMachine& target);
|
||||
|
||||
|
||||
void buildNodesForBB(const TargetMachine& target,MachineBasicBlock &MBB,
|
||||
std::vector<SchedGraphNode*>& memNV,
|
||||
std::vector<SchedGraphNode*>& callNV,
|
||||
RegToRefVecMap& regToRefVecMap,
|
||||
ValueToDefVecMap& valueToDefVecMap);
|
||||
|
||||
|
||||
|
||||
void findDefUseInfoAtInstr(const TargetMachine& target, SchedGraphNode* node,
|
||||
std::vector<SchedGraphNode*>& memNV,
|
||||
std::vector<SchedGraphNode*>& callNV,
|
||||
RegToRefVecMap& regToRefVecMap,
|
||||
ValueToDefVecMap& valueToDefVecMap);
|
||||
|
||||
|
||||
void addEdgesForInstruction(const MachineInstr& minstr,
|
||||
const ValueToDefVecMap& valueToDefVecMap,
|
||||
const TargetMachine& target);
|
||||
|
||||
|
||||
void addCDEdges(const TerminatorInst* term, const TargetMachine& target);
|
||||
|
||||
|
||||
void addMemEdges(const std::vector<SchedGraphNode*>& memNod,
|
||||
const TargetMachine& target);
|
||||
|
||||
|
||||
void addCallCCEdges(const std::vector<SchedGraphNode*>& memNod,
|
||||
MachineBasicBlock& bbMvec,
|
||||
const TargetMachine& target);
|
||||
|
||||
void addCallDepEdges(const std::vector<SchedGraphNode*>& callNV,
|
||||
const TargetMachine& target);
|
||||
|
||||
|
||||
void addMachineRegEdges(RegToRefVecMap& regToRefVecMap,
|
||||
const TargetMachine& target);
|
||||
|
||||
|
||||
void addEdgesForValue(SchedGraphNode* refNode, const RefVec& defVec,
|
||||
const Value* defValue, bool refNodeIsDef,
|
||||
bool refNodeIsDefAndUse,
|
||||
@@ -161,12 +161,12 @@ class SchedGraphSet {
|
||||
inline void addGraph(SchedGraph* graph) {
|
||||
assert(graph != NULL);
|
||||
Graphs.push_back(graph);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
SchedGraphSet(const Function *function, const TargetMachine& target);
|
||||
~SchedGraphSet();
|
||||
|
||||
|
||||
//iterators
|
||||
typedef std::vector<SchedGraph*>::const_iterator iterator;
|
||||
typedef std::vector<SchedGraph*>::const_iterator const_iterator;
|
||||
@@ -181,7 +181,7 @@ public:
|
||||
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
// sg_pred_iterator
|
||||
// sg_pred_const_iterator
|
||||
//
|
||||
@@ -204,7 +204,7 @@ inline sg_pred_const_iterator pred_end(const SchedGraphNode *N) {
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
// sg_succ_iterator
|
||||
// sg_succ_const_iterator
|
||||
//
|
||||
@@ -234,10 +234,10 @@ template <> struct GraphTraits<SchedGraph*> {
|
||||
typedef sg_succ_iterator ChildIteratorType;
|
||||
|
||||
static inline NodeType *getEntryNode(SchedGraph *SG) { return (NodeType*)SG->getRoot(); }
|
||||
static inline ChildIteratorType child_begin(NodeType *N) {
|
||||
return succ_begin(N);
|
||||
static inline ChildIteratorType child_begin(NodeType *N) {
|
||||
return succ_begin(N);
|
||||
}
|
||||
static inline ChildIteratorType child_end(NodeType *N) {
|
||||
static inline ChildIteratorType child_end(NodeType *N) {
|
||||
return succ_end(N);
|
||||
}
|
||||
};
|
||||
@@ -249,10 +249,10 @@ template <> struct GraphTraits<const SchedGraph*> {
|
||||
static inline NodeType *getEntryNode(const SchedGraph *SG) {
|
||||
return (NodeType*)SG->getRoot();
|
||||
}
|
||||
static inline ChildIteratorType child_begin(NodeType *N) {
|
||||
return succ_begin(N);
|
||||
static inline ChildIteratorType child_begin(NodeType *N) {
|
||||
return succ_begin(N);
|
||||
}
|
||||
static inline ChildIteratorType child_end(NodeType *N) {
|
||||
static inline ChildIteratorType child_end(NodeType *N) {
|
||||
return succ_end(N);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===- SchedGraphCommon.cpp - Scheduling Graphs Base Class- ---------------===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Scheduling graph base class that contains common information for SchedGraph
|
||||
@@ -23,7 +23,7 @@ class SchedGraphCommon;
|
||||
|
||||
//
|
||||
// class SchedGraphEdge
|
||||
//
|
||||
//
|
||||
SchedGraphEdge::SchedGraphEdge(SchedGraphNodeCommon* _src,
|
||||
SchedGraphNodeCommon* _sink,
|
||||
SchedGraphEdgeDepType _depType,
|
||||
@@ -31,7 +31,7 @@ SchedGraphEdge::SchedGraphEdge(SchedGraphNodeCommon* _src,
|
||||
int _minDelay)
|
||||
: src(_src), sink(_sink), depType(_depType), depOrderType(_depOrderType),
|
||||
minDelay((_minDelay >= 0)? _minDelay : _src->getLatency()), val(NULL) {
|
||||
|
||||
|
||||
iteDiff=0;
|
||||
assert(src != sink && "Self-loop in scheduling graph!");
|
||||
src->addOutEdge(this);
|
||||
@@ -81,7 +81,7 @@ SchedGraphEdge::SchedGraphEdge(SchedGraphNodeCommon* _src,
|
||||
|
||||
|
||||
void SchedGraphEdge::dump(int indent) const {
|
||||
std::cerr << std::string(indent*2, ' ') << *this;
|
||||
std::cerr << std::string(indent*2, ' ') << *this;
|
||||
}
|
||||
|
||||
/*dtor*/
|
||||
@@ -94,7 +94,7 @@ SchedGraphNodeCommon::~SchedGraphNodeCommon()
|
||||
|
||||
void SchedGraphNodeCommon::removeInEdge(const SchedGraphEdge* edge) {
|
||||
assert(edge->getSink() == this);
|
||||
|
||||
|
||||
for (iterator I = beginInEdges(); I != endInEdges(); ++I)
|
||||
if ((*I) == edge) {
|
||||
inEdges.erase(I);
|
||||
@@ -104,7 +104,7 @@ void SchedGraphNodeCommon::removeInEdge(const SchedGraphEdge* edge) {
|
||||
|
||||
void SchedGraphNodeCommon::removeOutEdge(const SchedGraphEdge* edge) {
|
||||
assert(edge->getSrc() == this);
|
||||
|
||||
|
||||
for (iterator I = beginOutEdges(); I != endOutEdges(); ++I)
|
||||
if ((*I) == edge) {
|
||||
outEdges.erase(I);
|
||||
@@ -113,7 +113,7 @@ void SchedGraphNodeCommon::removeOutEdge(const SchedGraphEdge* edge) {
|
||||
}
|
||||
|
||||
void SchedGraphNodeCommon::dump(int indent) const {
|
||||
std::cerr << std::string(indent*2, ' ') << *this;
|
||||
std::cerr << std::string(indent*2, ' ') << *this;
|
||||
}
|
||||
|
||||
//class SchedGraphCommon
|
||||
@@ -124,7 +124,7 @@ SchedGraphCommon::~SchedGraphCommon() {
|
||||
}
|
||||
|
||||
|
||||
void SchedGraphCommon::eraseIncomingEdges(SchedGraphNodeCommon* node,
|
||||
void SchedGraphCommon::eraseIncomingEdges(SchedGraphNodeCommon* node,
|
||||
bool addDummyEdges) {
|
||||
// Delete and disconnect all in-edges for the node
|
||||
for (SchedGraphNodeCommon::iterator I = node->beginInEdges();
|
||||
@@ -132,22 +132,22 @@ void SchedGraphCommon::eraseIncomingEdges(SchedGraphNodeCommon* node,
|
||||
SchedGraphNodeCommon* srcNode = (*I)->getSrc();
|
||||
srcNode->removeOutEdge(*I);
|
||||
delete *I;
|
||||
|
||||
|
||||
if (addDummyEdges && srcNode != getRoot() &&
|
||||
srcNode->beginOutEdges() == srcNode->endOutEdges()) {
|
||||
|
||||
srcNode->beginOutEdges() == srcNode->endOutEdges()) {
|
||||
|
||||
// srcNode has no more out edges, so add an edge to dummy EXIT node
|
||||
assert(node != getLeaf() && "Adding edge that was just removed?");
|
||||
(void) new SchedGraphEdge(srcNode, getLeaf(),
|
||||
SchedGraphEdge::CtrlDep,
|
||||
SchedGraphEdge::CtrlDep,
|
||||
SchedGraphEdge::NonDataDep, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
node->inEdges.clear();
|
||||
}
|
||||
|
||||
void SchedGraphCommon::eraseOutgoingEdges(SchedGraphNodeCommon* node,
|
||||
void SchedGraphCommon::eraseOutgoingEdges(SchedGraphNodeCommon* node,
|
||||
bool addDummyEdges) {
|
||||
// Delete and disconnect all out-edges for the node
|
||||
for (SchedGraphNodeCommon::iterator I = node->beginOutEdges();
|
||||
@@ -155,23 +155,23 @@ void SchedGraphCommon::eraseOutgoingEdges(SchedGraphNodeCommon* node,
|
||||
SchedGraphNodeCommon* sinkNode = (*I)->getSink();
|
||||
sinkNode->removeInEdge(*I);
|
||||
delete *I;
|
||||
|
||||
|
||||
if (addDummyEdges &&
|
||||
sinkNode != getLeaf() &&
|
||||
sinkNode->beginInEdges() == sinkNode->endInEdges()) {
|
||||
|
||||
|
||||
//sinkNode has no more in edges, so add an edge from dummy ENTRY node
|
||||
assert(node != getRoot() && "Adding edge that was just removed?");
|
||||
(void) new SchedGraphEdge(getRoot(), sinkNode,
|
||||
SchedGraphEdge::CtrlDep,
|
||||
SchedGraphEdge::CtrlDep,
|
||||
SchedGraphEdge::NonDataDep, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
node->outEdges.clear();
|
||||
}
|
||||
|
||||
void SchedGraphCommon::eraseIncidentEdges(SchedGraphNodeCommon* node,
|
||||
void SchedGraphCommon::eraseIncidentEdges(SchedGraphNodeCommon* node,
|
||||
bool addDummyEdges) {
|
||||
this->eraseIncomingEdges(node, addDummyEdges);
|
||||
this->eraseOutgoingEdges(node, addDummyEdges);
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
//===-- SchedPriorities.h - Encapsulate scheduling heuristics -------------===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
// Strategy:
|
||||
// Priority ordering rules:
|
||||
// (1) Max delay, which is the order of the heap S.candsAsHeap.
|
||||
@@ -76,23 +76,23 @@ void
|
||||
SchedPriorities::initializeReadyHeap(const SchedGraph* graph) {
|
||||
const SchedGraphNode* graphRoot = (const SchedGraphNode*)graph->getRoot();
|
||||
assert(graphRoot->getMachineInstr() == NULL && "Expect dummy root");
|
||||
|
||||
|
||||
// Insert immediate successors of dummy root, which are the actual roots
|
||||
sg_succ_const_iterator SEnd = succ_end(graphRoot);
|
||||
for (sg_succ_const_iterator S = succ_begin(graphRoot); S != SEnd; ++S)
|
||||
this->insertReady(*S);
|
||||
|
||||
|
||||
#undef TEST_HEAP_CONVERSION
|
||||
#ifdef TEST_HEAP_CONVERSION
|
||||
std::cerr << "Before heap conversion:\n";
|
||||
copy(candsAsHeap.begin(), candsAsHeap.end(),
|
||||
ostream_iterator<NodeDelayPair*>(std::cerr,"\n"));
|
||||
#endif
|
||||
|
||||
|
||||
candsAsHeap.makeHeap();
|
||||
|
||||
|
||||
nextToTry = candsAsHeap.begin();
|
||||
|
||||
|
||||
#ifdef TEST_HEAP_CONVERSION
|
||||
std::cerr << "After heap conversion:\n";
|
||||
copy(candsAsHeap.begin(), candsAsHeap.end(),
|
||||
@@ -107,7 +107,7 @@ SchedPriorities::insertReady(const SchedGraphNode* node) {
|
||||
mcands.clear(); // ensure reset choices is called before any more choices
|
||||
earliestReadyTime = std::min(earliestReadyTime,
|
||||
getEarliestReadyTimeForNode(node));
|
||||
|
||||
|
||||
if (SchedDebugLevel >= Sched_PrintSchedTrace) {
|
||||
std::cerr << " Node " << node->getNodeId() << " will be ready in Cycle "
|
||||
<< getEarliestReadyTimeForNode(node) << "; "
|
||||
@@ -122,26 +122,26 @@ SchedPriorities::issuedReadyNodeAt(CycleCount_t curTime,
|
||||
candsAsHeap.removeNode(node);
|
||||
candsAsSet.erase(node);
|
||||
mcands.clear(); // ensure reset choices is called before any more choices
|
||||
|
||||
|
||||
if (earliestReadyTime == getEarliestReadyTimeForNode(node)) {
|
||||
// earliestReadyTime may have been due to this node, so recompute it
|
||||
earliestReadyTime = HUGE_LATENCY;
|
||||
for (NodeHeap::const_iterator I=candsAsHeap.begin();
|
||||
I != candsAsHeap.end(); ++I)
|
||||
if (candsAsHeap.getNode(I)) {
|
||||
earliestReadyTime =
|
||||
std::min(earliestReadyTime,
|
||||
earliestReadyTime =
|
||||
std::min(earliestReadyTime,
|
||||
getEarliestReadyTimeForNode(candsAsHeap.getNode(I)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Now update ready times for successors
|
||||
for (SchedGraphNode::const_iterator E=node->beginOutEdges();
|
||||
E != node->endOutEdges(); ++E) {
|
||||
CycleCount_t& etime =
|
||||
getEarliestReadyTimeForNodeRef((SchedGraphNode*)(*E)->getSink());
|
||||
etime = std::max(etime, curTime + (*E)->getMinDelay());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -182,7 +182,7 @@ SchedPriorities::chooseByRule3(std::vector<candIndex>& mcands) {
|
||||
indexWithMaxUses = i;
|
||||
}
|
||||
}
|
||||
return indexWithMaxUses;
|
||||
return indexWithMaxUses;
|
||||
}
|
||||
|
||||
const SchedGraphNode*
|
||||
@@ -190,22 +190,22 @@ SchedPriorities::getNextHighest(const SchedulingManager& S,
|
||||
CycleCount_t curTime) {
|
||||
int nextIdx = -1;
|
||||
const SchedGraphNode* nextChoice = NULL;
|
||||
|
||||
|
||||
if (mcands.size() == 0)
|
||||
findSetWithMaxDelay(mcands, S);
|
||||
|
||||
|
||||
while (nextIdx < 0 && mcands.size() > 0) {
|
||||
nextIdx = chooseByRule1(mcands); // rule 1
|
||||
|
||||
|
||||
if (nextIdx == -1)
|
||||
nextIdx = chooseByRule2(mcands); // rule 2
|
||||
|
||||
|
||||
if (nextIdx == -1)
|
||||
nextIdx = chooseByRule3(mcands); // rule 3
|
||||
|
||||
|
||||
if (nextIdx == -1)
|
||||
nextIdx = 0; // default to first choice by delays
|
||||
|
||||
|
||||
// We have found the next best candidate. Check if it ready in
|
||||
// the current cycle, and if it is feasible.
|
||||
// If not, remove it from mcands and continue. Refill mcands if
|
||||
@@ -220,7 +220,7 @@ SchedPriorities::getNextHighest(const SchedulingManager& S,
|
||||
findSetWithMaxDelay(mcands, S);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (nextIdx >= 0) {
|
||||
mcands.erase(mcands.begin() + nextIdx);
|
||||
return nextChoice;
|
||||
@@ -241,9 +241,9 @@ SchedPriorities::findSetWithMaxDelay(std::vector<candIndex>& mcands,
|
||||
for (; next != candsAsHeap.end()
|
||||
&& candsAsHeap.getDelay(next) == maxDelay; ++next)
|
||||
mcands.push_back(next);
|
||||
|
||||
|
||||
nextToTry = next;
|
||||
|
||||
|
||||
if (SchedDebugLevel >= Sched_PrintSchedTrace) {
|
||||
std::cerr << " Cycle " << (long)getTime() << ": "
|
||||
<< "Next highest delay = " << (long)maxDelay << " : "
|
||||
@@ -260,17 +260,17 @@ bool
|
||||
SchedPriorities::instructionHasLastUse(FunctionLiveVarInfo &LVI,
|
||||
const SchedGraphNode* graphNode) {
|
||||
const MachineInstr *MI = graphNode->getMachineInstr();
|
||||
|
||||
|
||||
hash_map<const MachineInstr*, bool>::const_iterator
|
||||
ui = lastUseMap.find(MI);
|
||||
if (ui != lastUseMap.end())
|
||||
return ui->second;
|
||||
|
||||
|
||||
// else check if instruction is a last use and save it in the hash_map
|
||||
bool hasLastUse = false;
|
||||
const BasicBlock* bb = graphNode->getMachineBasicBlock().getBasicBlock();
|
||||
const ValueSet &LVs = LVI.getLiveVarSetBeforeMInst(MI, bb);
|
||||
|
||||
|
||||
for (MachineInstr::const_val_op_iterator OI = MI->begin(), OE = MI->end();
|
||||
OI != OE; ++OI)
|
||||
if (!LVs.count(*OI)) {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
//===-- SchedPriorities.h - Encapsulate scheduling heuristics --*- C++ -*--===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
// Strategy:
|
||||
// Priority ordering rules:
|
||||
// (1) Max delay, which is the order of the heap S.candsAsHeap.
|
||||
@@ -39,7 +39,7 @@ class FunctionLiveVarInfo;
|
||||
enum SchedDebugLevel_t {
|
||||
Sched_NoDebugInfo,
|
||||
Sched_Disable,
|
||||
Sched_PrintMachineCode,
|
||||
Sched_PrintMachineCode,
|
||||
Sched_PrintSchedTrace,
|
||||
Sched_PrintSchedGraphs,
|
||||
};
|
||||
@@ -48,7 +48,7 @@ extern SchedDebugLevel_t SchedDebugLevel;
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Function: instrIsFeasible
|
||||
//
|
||||
//
|
||||
// Purpose:
|
||||
// Used by the priority analysis to filter out instructions
|
||||
// that are not feasible to issue in the current cycle.
|
||||
@@ -78,26 +78,26 @@ class NodeHeap : public std::list<NodeDelayPair*> {
|
||||
public:
|
||||
typedef std::list<NodeDelayPair*>::iterator iterator;
|
||||
typedef std::list<NodeDelayPair*>::const_iterator const_iterator;
|
||||
|
||||
|
||||
public:
|
||||
NodeHeap() : _size(0) {}
|
||||
|
||||
|
||||
inline unsigned size() const { return _size; }
|
||||
|
||||
|
||||
const SchedGraphNode* getNode (const_iterator i) const { return (*i)->node; }
|
||||
CycleCount_t getDelay(const_iterator i) const { return (*i)->delay;}
|
||||
|
||||
inline void makeHeap() {
|
||||
|
||||
inline void makeHeap() {
|
||||
// make_heap(begin(), end(), NDPLessThan);
|
||||
}
|
||||
|
||||
|
||||
inline iterator findNode(const SchedGraphNode* node) {
|
||||
for (iterator I=begin(); I != end(); ++I)
|
||||
if (getNode(I) == node)
|
||||
return I;
|
||||
return end();
|
||||
}
|
||||
|
||||
|
||||
inline void removeNode (const SchedGraphNode* node) {
|
||||
iterator ndpPtr = findNode(node);
|
||||
if (ndpPtr != end())
|
||||
@@ -107,7 +107,7 @@ public:
|
||||
--_size;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void insert(const SchedGraphNode* node, CycleCount_t delay) {
|
||||
NodeDelayPair* ndp = new NodeDelayPair(node, delay);
|
||||
if (_size == 0 || front()->delay < delay)
|
||||
@@ -132,32 +132,32 @@ class SchedPriorities {
|
||||
public:
|
||||
SchedPriorities(const Function *F, const SchedGraph *G,
|
||||
FunctionLiveVarInfo &LVI);
|
||||
|
||||
|
||||
|
||||
|
||||
// This must be called before scheduling begins.
|
||||
void initialize ();
|
||||
|
||||
|
||||
CycleCount_t getTime () const { return curTime; }
|
||||
CycleCount_t getEarliestReadyTime () const { return earliestReadyTime; }
|
||||
unsigned getNumReady () const { return candsAsHeap.size(); }
|
||||
bool nodeIsReady (const SchedGraphNode* node) const {
|
||||
return (candsAsSet.find(node) != candsAsSet.end());
|
||||
}
|
||||
|
||||
|
||||
void issuedReadyNodeAt (CycleCount_t curTime,
|
||||
const SchedGraphNode* node);
|
||||
|
||||
|
||||
void insertReady (const SchedGraphNode* node);
|
||||
|
||||
|
||||
void updateTime (CycleCount_t /*unused*/);
|
||||
|
||||
|
||||
const SchedGraphNode* getNextHighest (const SchedulingManager& S,
|
||||
CycleCount_t curTime);
|
||||
// choose next highest priority instr
|
||||
|
||||
|
||||
private:
|
||||
typedef NodeHeap::iterator candIndex;
|
||||
|
||||
|
||||
private:
|
||||
CycleCount_t curTime;
|
||||
const SchedGraph* graph;
|
||||
@@ -173,21 +173,21 @@ private:
|
||||
std::vector<candIndex> mcands; // holds pointers into cands
|
||||
candIndex nextToTry; // next cand after the last
|
||||
// one tried in this cycle
|
||||
|
||||
|
||||
int chooseByRule1 (std::vector<candIndex>& mcands);
|
||||
int chooseByRule2 (std::vector<candIndex>& mcands);
|
||||
int chooseByRule3 (std::vector<candIndex>& mcands);
|
||||
|
||||
|
||||
void findSetWithMaxDelay (std::vector<candIndex>& mcands,
|
||||
const SchedulingManager& S);
|
||||
|
||||
|
||||
void computeDelays (const SchedGraph* graph);
|
||||
|
||||
|
||||
void initializeReadyHeap (const SchedGraph* graph);
|
||||
|
||||
|
||||
bool instructionHasLastUse (FunctionLiveVarInfo& LVI,
|
||||
const SchedGraphNode* graphNode);
|
||||
|
||||
|
||||
// NOTE: The next two return references to the actual vector entries.
|
||||
// Use the following two if you don't need to modify the value.
|
||||
CycleCount_t& getNodeDelayRef (const SchedGraphNode* node) {
|
||||
@@ -198,9 +198,9 @@ private:
|
||||
assert(node->getNodeId() < earliestReadyTimeForNode.size());
|
||||
return earliestReadyTimeForNode[node->getNodeId()];
|
||||
}
|
||||
|
||||
|
||||
CycleCount_t getNodeDelay (const SchedGraphNode* node) const {
|
||||
return ((SchedPriorities*) this)->getNodeDelayRef(node);
|
||||
return ((SchedPriorities*) this)->getNodeDelayRef(node);
|
||||
}
|
||||
CycleCount_t getEarliestReadyTimeForNode(const SchedGraphNode* node) const {
|
||||
return ((SchedPriorities*) this)->getEarliestReadyTimeForNodeRef(node);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===-- InternalGlobalMapper.cpp - Mapping Info for Internal Globals ------===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// InternalGlobalMapper is a pass that helps the runtime trace optimizer map
|
||||
@@ -71,7 +71,7 @@ bool InternalGlobalMapper::runOnModule(Module &M) {
|
||||
std::vector<Constant *> FieldValues;
|
||||
FieldValues.push_back (ConstantUInt::get (Type::UIntTy, gvvector.size ()));
|
||||
FieldValues.push_back (ConstantArray::get (ATy, gvvector));
|
||||
|
||||
|
||||
// Add the constant struct to M as an external global symbol named
|
||||
// "_llvm_internalGlobals".
|
||||
new GlobalVariable (STy, true, GlobalValue::ExternalLinkage,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===-- BBLiveVar.cpp - Live Variable Analysis for a BasicBlock -----------===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This is a wrapper class for BasicBlock which is used by live var analysis.
|
||||
@@ -43,7 +43,7 @@ void BBLiveVar::calcDefUseSets() {
|
||||
for (MachineBasicBlock::const_reverse_iterator MII = MBB.rbegin(),
|
||||
MIE = MBB.rend(); MII != MIE; ++MII) {
|
||||
const MachineInstr *MI = &*MII;
|
||||
|
||||
|
||||
if (DEBUG_LV >= LV_DEBUG_Verbose) {
|
||||
std::cerr << " *Iterating over machine instr ";
|
||||
MI->dump();
|
||||
@@ -60,7 +60,7 @@ void BBLiveVar::calcDefUseSets() {
|
||||
for (unsigned i = 0; i < MI->getNumImplicitRefs(); ++i)
|
||||
if (MI->getImplicitOp(i).isDef())
|
||||
addDef(MI->getImplicitRef(i));
|
||||
|
||||
|
||||
// iterate over MI operands to find uses
|
||||
for (MachineInstr::const_val_op_iterator OpI = MI->begin(), OpE = MI->end();
|
||||
OpI != OpE; ++OpI) {
|
||||
@@ -75,16 +75,16 @@ void BBLiveVar::calcDefUseSets() {
|
||||
// instructions is untested. The previous code was broken and I
|
||||
// fixed it, but it turned out to be unused as long as Phi
|
||||
// elimination is performed during instruction selection.
|
||||
//
|
||||
//
|
||||
// Put Phi operands in UseSet for the incoming edge, not node.
|
||||
// They must not "hide" later defs, and must be handled specially
|
||||
// during set propagation over the CFG.
|
||||
if (MI->getOpcode() == V9::PHI) { // for a phi node
|
||||
const Value *ArgVal = Op;
|
||||
const BasicBlock *PredBB = cast<BasicBlock>(*++OpI); // next ptr is BB
|
||||
|
||||
PredToEdgeInSetMap[PredBB].insert(ArgVal);
|
||||
|
||||
|
||||
PredToEdgeInSetMap[PredBB].insert(ArgVal);
|
||||
|
||||
if (DEBUG_LV >= LV_DEBUG_Verbose)
|
||||
std::cerr << " - phi operand " << RAV(ArgVal) << " came from BB "
|
||||
<< RAV(PredBB) << "\n";
|
||||
@@ -108,7 +108,7 @@ void BBLiveVar::calcDefUseSets() {
|
||||
addUse(Op);
|
||||
}
|
||||
} // for all machine instructions
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -118,7 +118,7 @@ void BBLiveVar::calcDefUseSets() {
|
||||
void BBLiveVar::addDef(const Value *Op) {
|
||||
DefSet.insert(Op); // operand is a def - so add to def set
|
||||
InSet.erase(Op); // this definition kills any later uses
|
||||
InSetChanged = true;
|
||||
InSetChanged = true;
|
||||
|
||||
if (DEBUG_LV >= LV_DEBUG_Verbose) std::cerr << " +Def: " << RAV(Op) << "\n";
|
||||
}
|
||||
@@ -130,7 +130,7 @@ void BBLiveVar::addDef(const Value *Op) {
|
||||
void BBLiveVar::addUse(const Value *Op) {
|
||||
InSet.insert(Op); // An operand is a use - so add to use set
|
||||
DefSet.erase(Op); // remove if there is a def below this use
|
||||
InSetChanged = true;
|
||||
InSetChanged = true;
|
||||
|
||||
if (DEBUG_LV >= LV_DEBUG_Verbose) std::cerr << " Use: " << RAV(Op) << "\n";
|
||||
}
|
||||
@@ -138,16 +138,16 @@ void BBLiveVar::addUse(const Value *Op) {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Applies the transfer function to a basic block to produce the InSet using
|
||||
// the OutSet.
|
||||
// the OutSet.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool BBLiveVar::applyTransferFunc() {
|
||||
// IMPORTANT: caller should check whether the OutSet changed
|
||||
// IMPORTANT: caller should check whether the OutSet changed
|
||||
// (else no point in calling)
|
||||
|
||||
ValueSet OutMinusDef = set_difference(OutSet, DefSet);
|
||||
InSetChanged = set_union(InSet, OutMinusDef);
|
||||
|
||||
|
||||
OutSetChanged = false; // no change to OutSet since transf func applied
|
||||
return InSetChanged;
|
||||
}
|
||||
@@ -157,31 +157,31 @@ bool BBLiveVar::applyTransferFunc() {
|
||||
// calculates Out set using In sets of the successors
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool BBLiveVar::setPropagate(ValueSet *OutSet, const ValueSet *InSet,
|
||||
bool BBLiveVar::setPropagate(ValueSet *OutSet, const ValueSet *InSet,
|
||||
const BasicBlock *PredBB) {
|
||||
bool Changed = false;
|
||||
|
||||
|
||||
// merge all members of InSet into OutSet of the predecessor
|
||||
for (ValueSet::const_iterator InIt = InSet->begin(), InE = InSet->end();
|
||||
InIt != InE; ++InIt)
|
||||
if ((OutSet->insert(*InIt)).second)
|
||||
Changed = true;
|
||||
|
||||
//
|
||||
|
||||
//
|
||||
//**** WARNING: The following code for handling dummy PHI machine
|
||||
// instructions is untested. See explanation above.
|
||||
//
|
||||
//
|
||||
// then merge all members of the EdgeInSet for the predecessor into the OutSet
|
||||
const ValueSet& EdgeInSet = PredToEdgeInSetMap[PredBB];
|
||||
for (ValueSet::const_iterator InIt = EdgeInSet.begin(), InE = EdgeInSet.end();
|
||||
InIt != InE; ++InIt)
|
||||
if ((OutSet->insert(*InIt)).second)
|
||||
Changed = true;
|
||||
//
|
||||
//
|
||||
//****
|
||||
|
||||
|
||||
return Changed;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -190,25 +190,25 @@ bool BBLiveVar::setPropagate(ValueSet *OutSet, const ValueSet *InSet,
|
||||
|
||||
bool BBLiveVar::applyFlowFunc(hash_map<const BasicBlock*,
|
||||
BBLiveVar*> &BBLiveVarInfo) {
|
||||
// IMPORTANT: caller should check whether inset changed
|
||||
// IMPORTANT: caller should check whether inset changed
|
||||
// (else no point in calling)
|
||||
|
||||
|
||||
// If this BB changed any OutSets of preds whose POID is lower, than we need
|
||||
// another iteration...
|
||||
//
|
||||
bool needAnotherIt = false;
|
||||
bool needAnotherIt = false;
|
||||
|
||||
for (pred_const_iterator PI = pred_begin(&BB), PE = pred_end(&BB);
|
||||
PI != PE ; ++PI) {
|
||||
BBLiveVar *PredLVBB = BBLiveVarInfo[*PI];
|
||||
|
||||
// do set union
|
||||
if (setPropagate(&PredLVBB->OutSet, &InSet, *PI)) {
|
||||
if (setPropagate(&PredLVBB->OutSet, &InSet, *PI)) {
|
||||
PredLVBB->OutSetChanged = true;
|
||||
|
||||
// if the predec POID is lower than mine
|
||||
if (PredLVBB->getPOId() <= POID)
|
||||
needAnotherIt = true;
|
||||
needAnotherIt = true;
|
||||
}
|
||||
} // for
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===-- BBLiveVar.h - Live Variable Analysis for a BasicBlock ---*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This is a BasicBlock annotation class that is used by live var analysis to
|
||||
@@ -46,14 +46,14 @@ class BBLiveVar {
|
||||
// coming in on that edge. such uses have to be
|
||||
// treated differently from ordinary uses.
|
||||
hash_map<const BasicBlock *, ValueSet> PredToEdgeInSetMap;
|
||||
|
||||
|
||||
// method to propagate an InSet to OutSet of a predecessor
|
||||
bool setPropagate(ValueSet *OutSetOfPred,
|
||||
bool setPropagate(ValueSet *OutSetOfPred,
|
||||
const ValueSet *InSetOfThisBB,
|
||||
const BasicBlock *PredBB);
|
||||
|
||||
// To add an operand which is a def
|
||||
void addDef(const Value *Op);
|
||||
void addDef(const Value *Op);
|
||||
|
||||
// To add an operand which is a use
|
||||
void addUse(const Value *Op);
|
||||
@@ -63,14 +63,14 @@ public:
|
||||
|
||||
BBLiveVar(const BasicBlock &BB, const MachineBasicBlock &MBB, unsigned POID);
|
||||
|
||||
inline bool isInSetChanged() const { return InSetChanged; }
|
||||
inline bool isInSetChanged() const { return InSetChanged; }
|
||||
inline bool isOutSetChanged() const { return OutSetChanged; }
|
||||
|
||||
const MachineBasicBlock &getMachineBasicBlock() const { return MBB; }
|
||||
|
||||
inline unsigned getPOId() const { return POID; }
|
||||
|
||||
bool applyTransferFunc(); // calcultes the In in terms of Out
|
||||
bool applyTransferFunc(); // calcultes the In in terms of Out
|
||||
|
||||
// calculates Out set using In sets of the predecessors
|
||||
bool applyFlowFunc(hash_map<const BasicBlock*, BBLiveVar*> &BBLiveVarInfo);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===-- FunctionLiveVarInfo.cpp - Live Variable Analysis for a Function ---===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This is the interface to function level live variable information that is
|
||||
@@ -79,7 +79,7 @@ bool FunctionLiveVarInfo::runOnFunction(Function &F) {
|
||||
unsigned int iter=0;
|
||||
while (doSingleBackwardPass(M, iter++))
|
||||
; // Iterate until we are done.
|
||||
|
||||
|
||||
if (DEBUG_LV) std::cerr << "Live Variable Analysis complete!\n";
|
||||
return false;
|
||||
}
|
||||
@@ -99,7 +99,7 @@ void FunctionLiveVarInfo::constructBBs(const Function *F) {
|
||||
|
||||
MachineFunction &MF = MachineFunction::get(F);
|
||||
for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) {
|
||||
const BasicBlock &BB = *I->getBasicBlock(); // get the current BB
|
||||
const BasicBlock &BB = *I->getBasicBlock(); // get the current BB
|
||||
if (DEBUG_LV) std::cerr << " For BB " << RAV(BB) << ":\n";
|
||||
|
||||
BBLiveVar *LVBB;
|
||||
@@ -116,7 +116,7 @@ void FunctionLiveVarInfo::constructBBs(const Function *F) {
|
||||
LVBB = new BBLiveVar(BB, *I, ++POId);
|
||||
}
|
||||
BBLiveVarInfo[&BB] = LVBB;
|
||||
|
||||
|
||||
if (DEBUG_LV)
|
||||
LVBB->printAllSets();
|
||||
}
|
||||
@@ -140,19 +140,19 @@ bool FunctionLiveVarInfo::doSingleBackwardPass(const Function *M,
|
||||
if (DEBUG_LV) std::cerr << " For BB " << (*BBI)->getName() << ":\n";
|
||||
|
||||
// InSets are initialized to "GenSet". Recompute only if OutSet changed.
|
||||
if(LVBB->isOutSetChanged())
|
||||
if(LVBB->isOutSetChanged())
|
||||
LVBB->applyTransferFunc(); // apply the Tran Func to calc InSet
|
||||
|
||||
|
||||
// OutSets are initialized to EMPTY. Recompute on first iter or if InSet
|
||||
// changed.
|
||||
if (iter == 0 || LVBB->isInSetChanged()) // to calc Outsets of preds
|
||||
NeedAnotherIteration |= LVBB->applyFlowFunc(BBLiveVarInfo);
|
||||
|
||||
|
||||
if (DEBUG_LV) LVBB->printInOutSets();
|
||||
}
|
||||
|
||||
// true if we need to reiterate over the CFG
|
||||
return NeedAnotherIteration;
|
||||
return NeedAnotherIteration;
|
||||
}
|
||||
|
||||
|
||||
@@ -188,10 +188,10 @@ void FunctionLiveVarInfo::releaseMemory() {
|
||||
// Following functions will give the LiveVar info for any machine instr in
|
||||
// a function. It should be called after a call to analyze().
|
||||
//
|
||||
// These functions calculate live var info for all the machine instrs in a
|
||||
// BB when LVInfo for one inst is requested. Hence, this function is useful
|
||||
// when live var info is required for many (or all) instructions in a basic
|
||||
// block. Also, the arguments to this function does not require specific
|
||||
// These functions calculate live var info for all the machine instrs in a
|
||||
// BB when LVInfo for one inst is requested. Hence, this function is useful
|
||||
// when live var info is required for many (or all) instructions in a basic
|
||||
// block. Also, the arguments to this function does not require specific
|
||||
// iterators.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -215,12 +215,12 @@ FunctionLiveVarInfo::getLiveVarSetBeforeMInst(const MachineInstr *MI,
|
||||
// Gives live variable information after a machine instruction
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const ValueSet &
|
||||
const ValueSet &
|
||||
FunctionLiveVarInfo::getLiveVarSetAfterMInst(const MachineInstr *MI,
|
||||
const BasicBlock *BB) {
|
||||
|
||||
ValueSet* &LVSet = MInst2LVSetAI[MI]; // ref. to map entry
|
||||
if (LVSet == NULL && BB != NULL) { // if not found and BB provided
|
||||
if (LVSet == NULL && BB != NULL) { // if not found and BB provided
|
||||
calcLiveVarSetsForBB(BB); // calc LVSet for all instrs in BB
|
||||
assert(LVSet != NULL);
|
||||
}
|
||||
@@ -230,7 +230,7 @@ FunctionLiveVarInfo::getLiveVarSetAfterMInst(const MachineInstr *MI,
|
||||
// This function applies a machine instr to a live var set (accepts OutSet) and
|
||||
// makes necessary changes to it (produces InSet). Note that two for loops are
|
||||
// used to first kill all defs and then to add all uses. This is because there
|
||||
// can be instructions like Val = Val + 1 since we allow multiple defs to a
|
||||
// can be instructions like Val = Val + 1 since we allow multiple defs to a
|
||||
// machine instruction operand.
|
||||
//
|
||||
static void applyTranferFuncForMInst(ValueSet &LVS, const MachineInstr *MInst) {
|
||||
@@ -261,7 +261,7 @@ static void applyTranferFuncForMInst(ValueSet &LVS, const MachineInstr *MInst) {
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// This method calculates the live variable information for all the
|
||||
// This method calculates the live variable information for all the
|
||||
// instructions in a basic block and enter the newly constructed live
|
||||
// variable sets into a the caches (MInst2LVSetAI, MInst2LVSetBI)
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -276,15 +276,15 @@ void FunctionLiveVarInfo::calcLiveVarSetsForBB(const BasicBlock *BB) {
|
||||
if (DEBUG_LV >= LV_DEBUG_Instr)
|
||||
std::cerr << "\n======For BB " << BB->getName()
|
||||
<< ": Live var sets for instructions======\n";
|
||||
|
||||
|
||||
ValueSet *SetAI = &getOutSetOfBB(BB); // init SetAI with OutSet
|
||||
ValueSet CurSet(*SetAI); // CurSet now contains OutSet
|
||||
|
||||
// iterate over all the machine instructions in BB
|
||||
for (MachineBasicBlock::const_reverse_iterator MII = MIVec.rbegin(),
|
||||
MIE = MIVec.rend(); MII != MIE; ++MII) {
|
||||
MIE = MIVec.rend(); MII != MIE; ++MII) {
|
||||
// MI is cur machine inst
|
||||
const MachineInstr *MI = &*MII;
|
||||
const MachineInstr *MI = &*MII;
|
||||
|
||||
MInst2LVSetAI[MI] = SetAI; // record in After Inst map
|
||||
|
||||
@@ -316,7 +316,7 @@ void FunctionLiveVarInfo::calcLiveVarSetsForBB(const BasicBlock *BB) {
|
||||
}
|
||||
|
||||
// SetAI will be used in the next iteration
|
||||
SetAI = NewSet;
|
||||
SetAI = NewSet;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
//===-- CodeGen/FunctionLiveVarInfo.h - LiveVar Analysis --------*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This is the interface for live variable info of a function that is required
|
||||
// This is the interface for live variable info of a function that is required
|
||||
// by any other part of the compiler
|
||||
//
|
||||
// After the analysis, getInSetOfBB or getOutSetofBB can be called to get
|
||||
// After the analysis, getInSetOfBB or getOutSetofBB can be called to get
|
||||
// live var info of a BB.
|
||||
//
|
||||
// The live var set before an instruction can be obtained in 2 ways:
|
||||
//
|
||||
// 1. Use the method getLiveVarSetAfterInst(Instruction *) to get the LV Info
|
||||
// 1. Use the method getLiveVarSetAfterInst(Instruction *) to get the LV Info
|
||||
// just after an instruction. (also exists getLiveVarSetBeforeInst(..))
|
||||
//
|
||||
// This function caluclates the LV info for a BB only once and caches that
|
||||
// info. If the cache does not contain the LV info of the instruction, it
|
||||
// This function caluclates the LV info for a BB only once and caches that
|
||||
// info. If the cache does not contain the LV info of the instruction, it
|
||||
// calculates the LV info for the whole BB and caches them.
|
||||
//
|
||||
// Getting liveVar info this way uses more memory since, LV info should be
|
||||
// Getting liveVar info this way uses more memory since, LV info should be
|
||||
// cached. However, if you need LV info of nearly all the instructions of a
|
||||
// BB, this is the best and simplest interfrace.
|
||||
//
|
||||
// 2. Use the OutSet and applyTranferFuncForInst(const Instruction *const Inst)
|
||||
// declared in LiveVarSet and traverse the instructions of a basic block in
|
||||
// reverse (using const_reverse_iterator in the BB class).
|
||||
// 2. Use the OutSet and applyTranferFuncForInst(const Instruction *const Inst)
|
||||
// declared in LiveVarSet and traverse the instructions of a basic block in
|
||||
// reverse (using const_reverse_iterator in the BB class).
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -47,7 +47,7 @@ class MachineInstr;
|
||||
class FunctionLiveVarInfo : public FunctionPass {
|
||||
// Machine Instr to LiveVarSet Map for providing LVset BEFORE each inst
|
||||
// These sets are owned by this map and will be freed in releaseMemory().
|
||||
hash_map<const MachineInstr *, ValueSet *> MInst2LVSetBI;
|
||||
hash_map<const MachineInstr *, ValueSet *> MInst2LVSetBI;
|
||||
|
||||
// Machine Instr to LiveVarSet Map for providing LVset AFTER each inst.
|
||||
// These sets are just pointers to sets in MInst2LVSetBI or BBLiveVar.
|
||||
@@ -62,13 +62,13 @@ class FunctionLiveVarInfo : public FunctionPass {
|
||||
|
||||
// constructs BBLiveVars and init Def and In sets
|
||||
void constructBBs(const Function *F);
|
||||
|
||||
|
||||
// do one backward pass over the CFG
|
||||
bool doSingleBackwardPass(const Function *F, unsigned int iter);
|
||||
bool doSingleBackwardPass(const Function *F, unsigned int iter);
|
||||
|
||||
// calculates live var sets for instructions in a BB
|
||||
void calcLiveVarSetsForBB(const BasicBlock *BB);
|
||||
|
||||
|
||||
public:
|
||||
// --------- Implement the FunctionPass interface ----------------------
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// FIXME: Eliminate this file.
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
namespace llvm {
|
||||
|
||||
std::ostream &operator<<(std::ostream &O, RAV V) { // func to print a Value
|
||||
std::ostream &operator<<(std::ostream &O, RAV V) { // func to print a Value
|
||||
const Value &v = V.V;
|
||||
if (v.hasName())
|
||||
return O << (void*)&v << "(" << v.getName() << ") ";
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===-- MachineCodeForInstruction.cpp -------------------------------------===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Container for the sequence of MachineInstrs created for a single
|
||||
@@ -13,7 +13,7 @@
|
||||
// they can be deleted when they are no longer needed, and finally, it also
|
||||
// holds some extra information for 'call' Instructions (using the
|
||||
// CallArgsDescriptor object, which is also implemented in this file).
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MachineCodeForInstruction.h"
|
||||
@@ -46,11 +46,11 @@ void MachineCodeForInstruction::dropAllReferences() {
|
||||
MachineCodeForInstruction::~MachineCodeForInstruction() {
|
||||
// Let go of all uses in temp. instructions
|
||||
dropAllReferences();
|
||||
|
||||
|
||||
// Free the Value objects created to hold intermediate values
|
||||
for (unsigned i=0, N=tempVec.size(); i < N; i++)
|
||||
delete tempVec[i];
|
||||
|
||||
|
||||
// do not free the MachineInstr objects allocated. they are managed
|
||||
// by the ilist in MachineBasicBlock
|
||||
|
||||
@@ -76,7 +76,7 @@ CallArgsDescriptor::CallArgsDescriptor(CallInst* _callInstr,
|
||||
|
||||
// Enter this object in the MachineCodeForInstr object of the CallInst.
|
||||
// This transfers ownership of this object.
|
||||
MachineCodeForInstruction::get(callInstr).setCallArgsDescriptor(this);
|
||||
MachineCodeForInstruction::get(callInstr).setCallArgsDescriptor(this);
|
||||
}
|
||||
|
||||
CallInst *CallArgsDescriptor::getReturnValue() const {
|
||||
@@ -90,7 +90,7 @@ CallInst *CallArgsDescriptor::getReturnValue() const {
|
||||
/// the CallArgsDescriptor from the MachineCodeForInstruction object for the
|
||||
/// CallInstr. This is roundabout but avoids adding a new map or annotation
|
||||
/// just to keep track of CallArgsDescriptors.
|
||||
///
|
||||
///
|
||||
CallArgsDescriptor *CallArgsDescriptor::get(const MachineInstr *MI) {
|
||||
const Value *retAddrVal = 0;
|
||||
if ((MI->getOperand (0).getType () == MachineOperand::MO_MachineRegister
|
||||
@@ -110,7 +110,7 @@ CallArgsDescriptor *CallArgsDescriptor::get(const MachineInstr *MI) {
|
||||
const CallInst* callInstr = cast<CallInst>(retAddrReg->getOperand(0));
|
||||
|
||||
CallArgsDescriptor* desc =
|
||||
MachineCodeForInstruction::get(callInstr).getCallArgsDescriptor();
|
||||
MachineCodeForInstruction::get(callInstr).getCallArgsDescriptor();
|
||||
assert(desc->getCallInst()==callInstr && "Incorrect call args descriptor?");
|
||||
return desc;
|
||||
}
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
//===-- MachineCodeForInstruction.h -----------------------------*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// FIXME: This file is SparcV9 specific. Do not rely on this class for new
|
||||
// FIXME: This file is SparcV9 specific. Do not rely on this class for new
|
||||
// targets, it will go away in the future.
|
||||
//
|
||||
// Representation of the sequence of machine instructions created for a single
|
||||
// VM instruction. Additionally records information about hidden and implicit
|
||||
// values used by the machine instructions: about hidden values used by the
|
||||
// machine instructions:
|
||||
//
|
||||
//
|
||||
// "Temporary values" are intermediate values used in the machine instruction
|
||||
// sequence, but not in the VM instruction Note that such values should be
|
||||
// treated as pure SSA values with no interpretation of their operands (i.e., as
|
||||
// a TmpInstruction object which actually represents such a value).
|
||||
//
|
||||
//
|
||||
// (2) "Implicit uses" are values used in the VM instruction but not in
|
||||
// the machine instruction sequence
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef MACHINECODE_FOR_INSTRUCTION_H
|
||||
@@ -44,7 +44,7 @@ class CallArgsDescriptor;
|
||||
public:
|
||||
MachineCodeForInstruction() : callArgsDesc(NULL) {}
|
||||
~MachineCodeForInstruction();
|
||||
|
||||
|
||||
static MachineCodeForInstruction &get(const Instruction *I);
|
||||
static void destroy(const Instruction *I);
|
||||
|
||||
@@ -71,7 +71,7 @@ public:
|
||||
}
|
||||
iterator erase(iterator where) { return Contents.erase(where); }
|
||||
iterator erase(iterator s, iterator e) { return Contents.erase(s, e); }
|
||||
|
||||
|
||||
|
||||
// dropAllReferences() - This function drops all references within
|
||||
// temporary (hidden) instructions created in implementing the original
|
||||
@@ -82,7 +82,7 @@ public:
|
||||
|
||||
const std::vector<Value*> &getTempValues() const { return tempVec; }
|
||||
std::vector<Value*> &getTempValues() { return tempVec; }
|
||||
|
||||
|
||||
MachineCodeForInstruction &addTemp(Value *tmp) {
|
||||
tempVec.push_back(tmp);
|
||||
return *this;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
//===-- SparcV9FunctionInfo.cpp -------------------------------------------===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
// This implements the SparcV9 specific MachineFunctionInfo class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
@@ -25,7 +25,7 @@ ComputeMaxOptionalArgsSize(const TargetMachine& target, const Function *F,
|
||||
unsigned &maxOptionalNumArgs)
|
||||
{
|
||||
unsigned maxSize = 0;
|
||||
|
||||
|
||||
for (Function::const_iterator BB = F->begin(), BBE = F->end(); BB !=BBE; ++BB)
|
||||
for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I != E; ++I)
|
||||
if (const CallInst *callInst = dyn_cast<CallInst>(I))
|
||||
@@ -34,16 +34,16 @@ ComputeMaxOptionalArgsSize(const TargetMachine& target, const Function *F,
|
||||
int numExtra = numOperands-6;
|
||||
if (numExtra <= 0)
|
||||
continue;
|
||||
|
||||
|
||||
unsigned sizeForThisCall = numExtra * 8;
|
||||
|
||||
|
||||
if (maxSize < sizeForThisCall)
|
||||
maxSize = sizeForThisCall;
|
||||
|
||||
|
||||
if ((int)maxOptionalNumArgs < numExtra)
|
||||
maxOptionalNumArgs = (unsigned) numExtra;
|
||||
}
|
||||
|
||||
|
||||
return maxSize;
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ ComputeMaxOptionalArgsSize(const TargetMachine& target, const Function *F,
|
||||
// This function is similar to the corresponding function in EmitAssembly.cpp
|
||||
// but they are unrelated. This one does not align at more than a
|
||||
// double-word boundary whereas that one might.
|
||||
//
|
||||
//
|
||||
inline unsigned
|
||||
SizeToAlignment(unsigned size, const TargetMachine& target)
|
||||
{
|
||||
@@ -108,9 +108,9 @@ int SparcV9FunctionInfo::allocateLocalVar(const Value* val,
|
||||
assert(! automaticVarsAreaFrozen &&
|
||||
"Size of auto vars area has been used to compute an offset so "
|
||||
"no more automatic vars should be allocated!");
|
||||
|
||||
|
||||
// Check if we've allocated a stack slot for this value already
|
||||
//
|
||||
//
|
||||
hash_map<const Value*, int>::const_iterator pair = offsets.find(val);
|
||||
if (pair != offsets.end())
|
||||
return pair->second;
|
||||
@@ -128,19 +128,19 @@ SparcV9FunctionInfo::allocateSpilledValue(const Type* type)
|
||||
assert(! spillsAreaFrozen &&
|
||||
"Size of reg spills area has been used to compute an offset so "
|
||||
"no more register spill slots should be allocated!");
|
||||
|
||||
|
||||
unsigned size = MF.getTarget().getTargetData().getTypeSize(type);
|
||||
unsigned char align = MF.getTarget().getTargetData().getTypeAlignment(type);
|
||||
|
||||
|
||||
bool growUp;
|
||||
int firstOffset = MF.getTarget().getFrameInfo()->getRegSpillAreaOffset(MF, growUp);
|
||||
|
||||
|
||||
int offset = growUp? firstOffset + getRegSpillsSize()
|
||||
: firstOffset - (getRegSpillsSize() + size);
|
||||
|
||||
int aligned = MF.getTarget().getFrameInfo()->adjustAlignment(offset, growUp, align);
|
||||
size += abs(aligned - offset); // include alignment padding in size
|
||||
|
||||
|
||||
incrementRegSpillsSize(size); // update size of reg. spills area
|
||||
|
||||
return aligned;
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
//===-- SparcV9FunctionInfo.h -----------------------------------*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
// This class keeps track of information about the stack frame and about the
|
||||
// per-function constant pool.
|
||||
//
|
||||
// FIXME: This class is completely SparcV9 specific. Do not use it for future
|
||||
// targets. This file will be eliminated in future versions of LLVM.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef MACHINEFUNCTIONINFO_H
|
||||
@@ -62,7 +62,7 @@ public:
|
||||
|
||||
//
|
||||
// Accessors for global information about generated code for a method.
|
||||
//
|
||||
//
|
||||
bool isCompiledAsLeafMethod() const { return compiledAsLeaf; }
|
||||
unsigned getStaticStackSize() const { return staticStackSize; }
|
||||
unsigned getAutomaticVarsSize() const { return automaticVarsSize; }
|
||||
@@ -72,31 +72,31 @@ public:
|
||||
const hash_set<const Constant*> &getConstantPoolValues() const {
|
||||
return constantsForConstPool;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Modifiers used during code generation
|
||||
//
|
||||
//
|
||||
void initializeFrameLayout ();
|
||||
|
||||
|
||||
void addToConstantPool (const Constant* constVal) {
|
||||
constantsForConstPool.insert(constVal);
|
||||
}
|
||||
|
||||
|
||||
void markAsLeafMethod() { compiledAsLeaf = true; }
|
||||
|
||||
|
||||
int computeOffsetforLocalVar (const Value* local,
|
||||
unsigned& getPaddedSize,
|
||||
unsigned sizeToUse = 0);
|
||||
int allocateLocalVar (const Value* local,
|
||||
unsigned sizeToUse = 0);
|
||||
|
||||
|
||||
int allocateSpilledValue (const Type* type);
|
||||
int pushTempValue (unsigned size);
|
||||
void popAllTempValues ();
|
||||
|
||||
void freezeSpillsArea () { spillsAreaFrozen = true; }
|
||||
|
||||
void freezeSpillsArea () { spillsAreaFrozen = true; }
|
||||
void freezeAutomaticVarsArea () { automaticVarsAreaFrozen=true; }
|
||||
|
||||
|
||||
private:
|
||||
void incrementAutomaticVarsSize(int incr) {
|
||||
automaticVarsSize+= incr;
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
//===-- MachineInstrAnnot.h -------------------------------------*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Annotations used to pass information between SparcV9 code generation phases.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef MACHINEINSTRANNOT_H
|
||||
@@ -28,29 +28,29 @@ class CallArgInfo {
|
||||
static const unsigned char IntArgReg = 0x1;
|
||||
static const unsigned char FPArgReg = 0x2;
|
||||
static const unsigned char StackSlot = 0x4;
|
||||
|
||||
|
||||
Value* argVal; // this argument
|
||||
int argCopyReg; // register used for second copy of arg. when
|
||||
// multiple copies must be passed in registers
|
||||
unsigned char passingMethod; // flags recording passing methods
|
||||
|
||||
|
||||
public:
|
||||
// Constructors
|
||||
CallArgInfo(Value* _argVal)
|
||||
: argVal(_argVal), argCopyReg(SparcV9RegInfo::getInvalidRegNum()),
|
||||
passingMethod(0x0) {}
|
||||
|
||||
|
||||
CallArgInfo(const CallArgInfo& obj)
|
||||
: argVal(obj.argVal), argCopyReg(obj.argCopyReg),
|
||||
passingMethod(obj.passingMethod) {}
|
||||
|
||||
|
||||
// Accessor methods
|
||||
Value* getArgVal() { return argVal; }
|
||||
int getArgCopy() { return argCopyReg; }
|
||||
bool usesIntArgReg() { return (bool) (passingMethod & IntArgReg);}
|
||||
bool usesFPArgReg() { return (bool) (passingMethod & FPArgReg); }
|
||||
bool usesStackSlot() { return (bool) (passingMethod & StackSlot);}
|
||||
|
||||
bool usesIntArgReg() { return (bool) (passingMethod & IntArgReg);}
|
||||
bool usesFPArgReg() { return (bool) (passingMethod & FPArgReg); }
|
||||
bool usesStackSlot() { return (bool) (passingMethod & StackSlot);}
|
||||
|
||||
// Modifier methods
|
||||
void replaceArgVal(Value* newVal) { argVal = newVal; }
|
||||
void setUseIntArgReg() { passingMethod |= IntArgReg; }
|
||||
@@ -64,15 +64,15 @@ class CallArgsDescriptor {
|
||||
|
||||
std::vector<CallArgInfo> argInfoVec; // Descriptor for each argument
|
||||
CallInst* callInstr; // The call instruction == result value
|
||||
Value* funcPtr; // Pointer for indirect calls
|
||||
Value* funcPtr; // Pointer for indirect calls
|
||||
TmpInstruction* retAddrReg; // Tmp value for return address reg.
|
||||
bool isVarArgs; // Is this a varargs call?
|
||||
bool noPrototype; // Is this a call with no prototype?
|
||||
|
||||
|
||||
public:
|
||||
CallArgsDescriptor(CallInst* _callInstr, TmpInstruction* _retAddrReg,
|
||||
bool _isVarArgs, bool _noPrototype);
|
||||
|
||||
|
||||
// Accessor methods to retrieve information about the call
|
||||
// Note that operands are numbered 1..#CallArgs
|
||||
unsigned int getNumArgs() const { return argInfoVec.size(); }
|
||||
@@ -86,7 +86,7 @@ public:
|
||||
bool hasNoPrototype() const { return noPrototype; }
|
||||
|
||||
// Mechanism to get the descriptor for a CALL MachineInstr.
|
||||
//
|
||||
//
|
||||
static CallArgsDescriptor *get(const MachineInstr* MI);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===- MappingInfo.cpp - create LLVM info and output to .s file -----------===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains a FunctionPass called MappingInfoAsmPrinter,
|
||||
@@ -36,7 +36,7 @@
|
||||
namespace llvm {
|
||||
|
||||
namespace {
|
||||
class MappingInfoAsmPrinter : public FunctionPass {
|
||||
class MappingInfoAsmPrinter : public FunctionPass {
|
||||
std::ostream &Out;
|
||||
public:
|
||||
MappingInfoAsmPrinter(std::ostream &out) : Out(out){}
|
||||
@@ -78,8 +78,8 @@ bool MappingInfoAsmPrinter::runOnFunction(Function &FI) {
|
||||
// Now, write out the maps.
|
||||
BBMIMap.dumpAssembly (Out);
|
||||
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// writeNumber - Write out the number X as a sequence of .byte
|
||||
/// directives to the current output stream Out. This method performs a
|
||||
@@ -146,7 +146,7 @@ void MappingInfoAsmPrinter::buildBBMIMap(Function &FI, MappingInfo &Map) {
|
||||
create_BB_to_MInumber_Key(FI, BBkey);
|
||||
|
||||
selectOutputMap (Map);
|
||||
MachineFunction &MF = MachineFunction::get(&FI);
|
||||
MachineFunction &MF = MachineFunction::get(&FI);
|
||||
for (MachineFunction::iterator BI = MF.begin(), BE = MF.end();
|
||||
BI != BE; ++BI, ++bb) {
|
||||
MachineBasicBlock &miBB = *BI;
|
||||
@@ -165,19 +165,19 @@ static void writePrologue (std::ostream &Out, const std::string &comment,
|
||||
const std::string &symName) {
|
||||
// Prologue:
|
||||
// Output a comment describing the object.
|
||||
Out << "!" << comment << "\n";
|
||||
Out << "!" << comment << "\n";
|
||||
// Switch the current section to .rodata in the assembly output:
|
||||
Out << "\t.section \".rodata\"\n\t.align 8\n";
|
||||
Out << "\t.section \".rodata\"\n\t.align 8\n";
|
||||
// Output a global symbol naming the object:
|
||||
Out << "\t.global " << symName << "\n";
|
||||
Out << "\t.type " << symName << ",#object\n";
|
||||
Out << symName << ":\n";
|
||||
Out << "\t.global " << symName << "\n";
|
||||
Out << "\t.type " << symName << ",#object\n";
|
||||
Out << symName << ":\n";
|
||||
}
|
||||
|
||||
static void writeEpilogue (std::ostream &Out, const std::string &symName) {
|
||||
// Epilogue:
|
||||
// Output a local symbol marking the end of the object:
|
||||
Out << ".end_" << symName << ":\n";
|
||||
Out << ".end_" << symName << ":\n";
|
||||
// Output size directive giving the size of the object:
|
||||
Out << "\t.size " << symName << ", .end_" << symName << "-" << symName
|
||||
<< "\n";
|
||||
@@ -199,7 +199,7 @@ void MappingInfo::dumpAssembly (std::ostream &Out) {
|
||||
///
|
||||
bool MappingInfoAsmPrinter::doFinalization (Module &M) {
|
||||
unsigned f;
|
||||
|
||||
|
||||
writePrologue(Out, "FUNCTION TO BB MAP", "FunctionBB");
|
||||
f=0;
|
||||
for(Module::iterator FI = M.begin (), FE = M.end (); FE != FI; ++FI) {
|
||||
@@ -209,7 +209,7 @@ bool MappingInfoAsmPrinter::doFinalization (Module &M) {
|
||||
++f;
|
||||
}
|
||||
writeEpilogue(Out, "FunctionBB");
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===- lib/Target/SparcV9/MappingInfo.h -------------------------*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Data structures to support the Reoptimizer's Instruction-to-MachineInstr
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#define DEBUG_TYPE "ModuloSched"
|
||||
|
||||
@@ -23,25 +23,25 @@ using namespace llvm;
|
||||
///
|
||||
namespace llvm {
|
||||
FunctionPass *createDependenceAnalyzer() {
|
||||
return new DependenceAnalyzer();
|
||||
return new DependenceAnalyzer();
|
||||
}
|
||||
}
|
||||
|
||||
bool DependenceAnalyzer::runOnFunction(Function &F) {
|
||||
AA = &getAnalysis<AliasAnalysis>();
|
||||
TD = &getAnalysis<TargetData>();
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static RegisterAnalysis<DependenceAnalyzer>X("depanalyzer", "Dependence Analyzer");
|
||||
|
||||
|
||||
DependenceResult DependenceAnalyzer::getDependenceInfo(Instruction *inst1, Instruction *inst2) {
|
||||
std::vector<Dependence> deps;
|
||||
|
||||
DEBUG(std::cerr << "Inst1: " << *inst1 << "\n");
|
||||
DEBUG(std::cerr << "Inst2: " << *inst2 << "\n");
|
||||
|
||||
|
||||
|
||||
if(LoadInst *ldInst = dyn_cast<LoadInst>(inst1)) {
|
||||
|
||||
@@ -55,7 +55,7 @@ FunctionPass *createDependenceAnalyzer() {
|
||||
if(AA->alias(ldOp, (unsigned)TD->getTypeSize(ldOp->getType()),
|
||||
stOp,(unsigned)TD->getTypeSize(stOp->getType()))
|
||||
!= AliasAnalysis::NoAlias) {
|
||||
|
||||
|
||||
//Anti Dep
|
||||
deps.push_back(Dependence(0, Dependence::AntiDep));
|
||||
}
|
||||
@@ -63,7 +63,7 @@ FunctionPass *createDependenceAnalyzer() {
|
||||
}
|
||||
|
||||
else if(StoreInst *stInst = dyn_cast<StoreInst>(inst1)) {
|
||||
|
||||
|
||||
if(LoadInst *ldInst = dyn_cast<LoadInst>(inst2)) {
|
||||
//Get load mem ref
|
||||
Value *ldOp = ldInst->getOperand(0);
|
||||
@@ -75,7 +75,7 @@ FunctionPass *createDependenceAnalyzer() {
|
||||
if(AA->alias(ldOp, (unsigned)TD->getTypeSize(ldOp->getType()),
|
||||
stOp,(unsigned)TD->getTypeSize(stOp->getType()))
|
||||
!= AliasAnalysis::NoAlias) {
|
||||
|
||||
|
||||
//Anti Dep
|
||||
deps.push_back(Dependence(0, Dependence::TrueDep));
|
||||
}
|
||||
@@ -88,17 +88,17 @@ FunctionPass *createDependenceAnalyzer() {
|
||||
//Get store mem ref
|
||||
Value *stOp2 = stInst2->getOperand(1);
|
||||
|
||||
|
||||
|
||||
if(AA->alias(stOp1, (unsigned)TD->getTypeSize(stOp1->getType()),
|
||||
stOp2,(unsigned)TD->getTypeSize(stOp2->getType()))
|
||||
!= AliasAnalysis::NoAlias) {
|
||||
|
||||
|
||||
//Anti Dep
|
||||
deps.push_back(Dependence(0, Dependence::OutputDep));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
assert("Expected a load or a store\n");
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_DEPENDENCEANALYZER_H
|
||||
@@ -24,22 +24,22 @@ namespace llvm {
|
||||
|
||||
//class to represent a dependence
|
||||
struct Dependence {
|
||||
|
||||
|
||||
enum DataDepType {
|
||||
TrueDep, AntiDep, OutputDep, NonDateDep,
|
||||
};
|
||||
|
||||
|
||||
Dependence(int diff, DataDepType dep) : iteDiff(diff), depType(dep) {}
|
||||
unsigned getIteDiff() { return iteDiff; }
|
||||
unsigned getDepType() { return depType; }
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
unsigned iteDiff;
|
||||
unsigned depType;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct DependenceResult {
|
||||
std::vector<Dependence> dependences;
|
||||
DependenceResult(const std::vector<Dependence> &d) : dependences(d) {}
|
||||
@@ -49,12 +49,12 @@ namespace llvm {
|
||||
class DependenceAnalyzer : public FunctionPass {
|
||||
AliasAnalysis *AA;
|
||||
TargetData *TD;
|
||||
|
||||
|
||||
public:
|
||||
DependenceAnalyzer() { AA = 0; TD = 0; }
|
||||
virtual bool runOnFunction(Function &F);
|
||||
virtual const char* getPassName() const { return "DependenceAnalyzer"; }
|
||||
|
||||
|
||||
// getAnalysisUsage
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#define DEBUG_TYPE "ModuloSched"
|
||||
@@ -21,7 +21,7 @@ using namespace llvm;
|
||||
|
||||
//Returns a boolean indicating if the start cycle needs to be increased/decreased
|
||||
bool MSSchedule::insert(MSchedGraphNode *node, int cycle) {
|
||||
|
||||
|
||||
//First, check if the cycle has a spot free to start
|
||||
if(schedule.find(cycle) != schedule.end()) {
|
||||
//Check if we have a free issue slot at this cycle
|
||||
@@ -48,7 +48,7 @@ bool MSSchedule::insert(MSchedGraphNode *node, int cycle) {
|
||||
|
||||
DEBUG(std::cerr << "All issue slots taken\n");
|
||||
return true;
|
||||
|
||||
|
||||
}
|
||||
|
||||
void MSSchedule::addToSchedule(int cycle, MSchedGraphNode *node) {
|
||||
@@ -64,31 +64,31 @@ void MSSchedule::addToSchedule(int cycle, MSchedGraphNode *node) {
|
||||
std::vector<MSchedGraphNode*> nodes;
|
||||
for(std::map<unsigned, MSchedGraphNode*>::iterator I = indexMap.begin(), E = indexMap.end(); I != E; ++I)
|
||||
nodes.push_back(I->second);
|
||||
|
||||
|
||||
schedule[cycle] = nodes;
|
||||
}
|
||||
|
||||
|
||||
bool MSSchedule::resourcesFree(MSchedGraphNode *node, int cycle) {
|
||||
|
||||
|
||||
//Get Resource usage for this instruction
|
||||
const TargetSchedInfo *msi = node->getParent()->getTarget()->getSchedInfo();
|
||||
int currentCycle = cycle;
|
||||
bool success = true;
|
||||
|
||||
|
||||
//Get resource usage for this instruction
|
||||
InstrRUsage rUsage = msi->getInstrRUsage(node->getInst()->getOpcode());
|
||||
std::vector<std::vector<resourceId_t> > resources = rUsage.resourcesByCycle;
|
||||
|
||||
|
||||
//Loop over resources in each cycle and increments their usage count
|
||||
for(unsigned i=0; i < resources.size(); ++i) {
|
||||
for(unsigned j=0; j < resources[i].size(); ++j) {
|
||||
|
||||
|
||||
//Get Resource to check its availability
|
||||
int resourceNum = resources[i][j];
|
||||
|
||||
|
||||
DEBUG(std::cerr << "Attempting to schedule Resource Num: " << resourceNum << " in cycle: " << currentCycle << "\n");
|
||||
|
||||
|
||||
//Check if this resource is available for this cycle
|
||||
std::map<int, std::map<int,int> >::iterator resourcesForCycle = resourceNumPerCycle.find(currentCycle);
|
||||
|
||||
@@ -100,7 +100,7 @@ bool MSSchedule::resourcesFree(MSchedGraphNode *node, int cycle) {
|
||||
//Check if there are enough of this resource and if so, increase count and move on
|
||||
if(resourceUse->second < CPUResource::getCPUResource(resourceNum)->maxNumUsers)
|
||||
++resourceUse->second;
|
||||
|
||||
|
||||
else {
|
||||
DEBUG(std::cerr << "No resource num " << resourceNum << " available for cycle " << currentCycle << "\n");
|
||||
success = false;
|
||||
@@ -123,18 +123,18 @@ bool MSSchedule::resourcesFree(MSchedGraphNode *node, int cycle) {
|
||||
if(!success)
|
||||
break;
|
||||
|
||||
|
||||
|
||||
//Increase cycle
|
||||
currentCycle++;
|
||||
}
|
||||
|
||||
|
||||
if(!success) {
|
||||
int oldCycle = cycle;
|
||||
DEBUG(std::cerr << "Backtrack\n");
|
||||
//Get resource usage for this instruction
|
||||
InstrRUsage rUsage = msi->getInstrRUsage(node->getInst()->getOpcode());
|
||||
std::vector<std::vector<resourceId_t> > resources = rUsage.resourcesByCycle;
|
||||
|
||||
|
||||
//Loop over resources in each cycle and increments their usage count
|
||||
for(unsigned i=0; i < resources.size(); ++i) {
|
||||
if(oldCycle < currentCycle) {
|
||||
@@ -158,7 +158,7 @@ bool MSSchedule::resourcesFree(MSchedGraphNode *node, int cycle) {
|
||||
oldCycle++;
|
||||
}
|
||||
return false;
|
||||
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -166,7 +166,7 @@ bool MSSchedule::resourcesFree(MSchedGraphNode *node, int cycle) {
|
||||
}
|
||||
|
||||
bool MSSchedule::constructKernel(int II, std::vector<MSchedGraphNode*> &branches, std::map<const MachineInstr*, unsigned> &indVar) {
|
||||
|
||||
|
||||
//Our schedule is allowed to have negative numbers, so lets calculate this offset
|
||||
int offset = schedule.begin()->first;
|
||||
if(offset > 0)
|
||||
@@ -184,12 +184,12 @@ bool MSSchedule::constructKernel(int II, std::vector<MSchedGraphNode*> &branches
|
||||
int maxSN = 0;
|
||||
|
||||
DEBUG(std::cerr << "Number of Stages: " << stageNum << "\n");
|
||||
|
||||
|
||||
for(int index = offset; index < (II+offset); ++index) {
|
||||
int count = 0;
|
||||
for(int i = index; i <= (schedule.rbegin()->first); i+=II) {
|
||||
for(int i = index; i <= (schedule.rbegin()->first); i+=II) {
|
||||
if(schedule.count(i)) {
|
||||
for(std::vector<MSchedGraphNode*>::iterator I = schedule[i].begin(),
|
||||
for(std::vector<MSchedGraphNode*>::iterator I = schedule[i].begin(),
|
||||
E = schedule[i].end(); I != E; ++I) {
|
||||
//Check if its a branch
|
||||
if((*I)->isBranch()) {
|
||||
@@ -228,7 +228,7 @@ bool MSSchedule::constructKernel(int II, std::vector<MSchedGraphNode*> &branches
|
||||
indVar.erase(N->second);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
kernel.push_back(std::make_pair((MachineInstr*) I->first->getInst(), I->second));
|
||||
|
||||
}
|
||||
@@ -256,7 +256,7 @@ bool MSSchedule::constructKernel(int II, std::vector<MSchedGraphNode*> &branches
|
||||
|
||||
void MSSchedule::print(std::ostream &os) const {
|
||||
os << "Schedule:\n";
|
||||
|
||||
|
||||
for(schedule_const_iterator I = schedule.begin(), E = schedule.end(); I != E; ++I) {
|
||||
os << "Cycle: " << I->first << "\n";
|
||||
for(std::vector<MSchedGraphNode*>::const_iterator node = I->second.begin(), nodeEnd = I->second.end(); node != nodeEnd; ++node)
|
||||
@@ -268,4 +268,4 @@ void MSSchedule::print(std::ostream &os) const {
|
||||
E = kernel.end(); I != E; ++I)
|
||||
os << "Node: " << *(I->first) << " Stage: " << I->second << "\n";
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace llvm {
|
||||
class MSSchedule {
|
||||
std::map<int, std::vector<MSchedGraphNode*> > schedule;
|
||||
unsigned numIssue;
|
||||
|
||||
|
||||
//Internal map to keep track of explicit resources
|
||||
std::map<int, std::map<int, int> > resourceNumPerCycle;
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace llvm {
|
||||
bool constructKernel(int II, std::vector<MSchedGraphNode*> &branches, std::map<const MachineInstr*, unsigned> &indVar);
|
||||
int getMaxStage() { return maxStage; }
|
||||
|
||||
|
||||
|
||||
//iterators
|
||||
typedef std::map<int, std::vector<MSchedGraphNode*> >::iterator schedule_iterator;
|
||||
typedef std::map<int, std::vector<MSchedGraphNode*> >::const_iterator schedule_const_iterator;
|
||||
@@ -61,7 +61,7 @@ namespace llvm {
|
||||
typedef std::vector<std::pair<MachineInstr*, int> >::const_iterator kernel_const_iterator;
|
||||
kernel_iterator kernel_begin() { return kernel.begin(); }
|
||||
kernel_iterator kernel_end() { return kernel.end(); }
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
// A graph class for dependencies. This graph only contains true, anti, and
|
||||
// output data dependencies for a given MachineBasicBlock. Dependencies
|
||||
// across iterations are also computed. Unless data dependence analysis
|
||||
// is provided, a conservative approach of adding dependencies between all
|
||||
// is provided, a conservative approach of adding dependencies between all
|
||||
// loads and stores is taken.
|
||||
//===----------------------------------------------------------------------===//
|
||||
#define DEBUG_TYPE "ModuloSched"
|
||||
@@ -31,9 +31,9 @@
|
||||
using namespace llvm;
|
||||
|
||||
//MSchedGraphNode constructor
|
||||
MSchedGraphNode::MSchedGraphNode(const MachineInstr* inst,
|
||||
MSchedGraphNode::MSchedGraphNode(const MachineInstr* inst,
|
||||
MSchedGraph *graph, unsigned idx,
|
||||
unsigned late, bool isBranch)
|
||||
unsigned late, bool isBranch)
|
||||
: Inst(inst), Parent(graph), index(idx), latency(late), isBranchInstr(isBranch) {
|
||||
|
||||
//Add to the graph
|
||||
@@ -41,7 +41,7 @@ MSchedGraphNode::MSchedGraphNode(const MachineInstr* inst,
|
||||
}
|
||||
|
||||
//MSchedGraphNode copy constructor
|
||||
MSchedGraphNode::MSchedGraphNode(const MSchedGraphNode &N)
|
||||
MSchedGraphNode::MSchedGraphNode(const MSchedGraphNode &N)
|
||||
: Predecessors(N.Predecessors), Successors(N.Successors) {
|
||||
|
||||
Inst = N.Inst;
|
||||
@@ -54,7 +54,7 @@ MSchedGraphNode::MSchedGraphNode(const MSchedGraphNode &N)
|
||||
|
||||
//Print the node (instruction and latency)
|
||||
void MSchedGraphNode::print(std::ostream &os) const {
|
||||
os << "MSchedGraphNode: Inst=" << *Inst << ", latency= " << latency << "\n";
|
||||
os << "MSchedGraphNode: Inst=" << *Inst << ", latency= " << latency << "\n";
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ void MSchedGraphNode::print(std::ostream &os) const {
|
||||
MSchedGraphEdge MSchedGraphNode::getInEdge(MSchedGraphNode *pred) {
|
||||
//Loop over all the successors of our predecessor
|
||||
//return the edge the corresponds to this in edge
|
||||
for (MSchedGraphNode::succ_iterator I = pred->succ_begin(),
|
||||
for (MSchedGraphNode::succ_iterator I = pred->succ_begin(),
|
||||
E = pred->succ_end(); I != E; ++I) {
|
||||
if (*I == this)
|
||||
return I.getEdge();
|
||||
@@ -115,24 +115,24 @@ bool MSchedGraphNode::isPredecessor(MSchedGraphNode *pred) {
|
||||
//Add a node to the graph
|
||||
void MSchedGraph::addNode(const MachineInstr *MI,
|
||||
MSchedGraphNode *node) {
|
||||
|
||||
//Make sure node does not already exist
|
||||
assert(GraphMap.find(MI) == GraphMap.end()
|
||||
|
||||
//Make sure node does not already exist
|
||||
assert(GraphMap.find(MI) == GraphMap.end()
|
||||
&& "New MSchedGraphNode already exists for this instruction");
|
||||
|
||||
|
||||
GraphMap[MI] = node;
|
||||
}
|
||||
|
||||
//Delete a node to the graph
|
||||
void MSchedGraph::deleteNode(MSchedGraphNode *node) {
|
||||
|
||||
|
||||
//Delete the edge to this node from all predecessors
|
||||
while(node->pred_size() > 0) {
|
||||
//DEBUG(std::cerr << "Delete edge from: " << **P << " to " << *node << "\n");
|
||||
//DEBUG(std::cerr << "Delete edge from: " << **P << " to " << *node << "\n");
|
||||
MSchedGraphNode *pred = *(node->pred_begin());
|
||||
pred->deleteSuccessor(node);
|
||||
}
|
||||
|
||||
|
||||
//Remove this node from the graph
|
||||
GraphMap.erase(node->getInst());
|
||||
|
||||
@@ -141,15 +141,15 @@ void MSchedGraph::deleteNode(MSchedGraphNode *node) {
|
||||
//Create a graph for a machine block. The ignoreInstrs map is so that we ignore instructions
|
||||
//associated to the index variable since this is a special case in Modulo Scheduling.
|
||||
//We only want to deal with the body of the loop.
|
||||
MSchedGraph::MSchedGraph(const MachineBasicBlock *bb, const TargetMachine &targ,
|
||||
std::map<const MachineInstr*, unsigned> &ignoreInstrs,
|
||||
MSchedGraph::MSchedGraph(const MachineBasicBlock *bb, const TargetMachine &targ,
|
||||
std::map<const MachineInstr*, unsigned> &ignoreInstrs,
|
||||
DependenceAnalyzer &DA, std::map<MachineInstr*, Instruction*> &machineTollvm
|
||||
)
|
||||
: BB(bb), Target(targ) {
|
||||
|
||||
//Make sure BB is not null,
|
||||
|
||||
//Make sure BB is not null,
|
||||
assert(BB != NULL && "Basic Block is null");
|
||||
|
||||
|
||||
//DEBUG(std::cerr << "Constructing graph for " << bb << "\n");
|
||||
|
||||
//Create nodes and edges for this BB
|
||||
@@ -160,22 +160,22 @@ MSchedGraph::MSchedGraph(const MachineBasicBlock *bb, const TargetMachine &targ,
|
||||
}
|
||||
|
||||
//Copies the graph and keeps a map from old to new nodes
|
||||
MSchedGraph::MSchedGraph(const MSchedGraph &G, std::map<MSchedGraphNode*, MSchedGraphNode*> &newNodes)
|
||||
MSchedGraph::MSchedGraph(const MSchedGraph &G, std::map<MSchedGraphNode*, MSchedGraphNode*> &newNodes)
|
||||
: BB(G.BB), Target(G.Target) {
|
||||
|
||||
|
||||
std::map<MSchedGraphNode*, MSchedGraphNode*> oldToNew;
|
||||
//Copy all nodes
|
||||
for(MSchedGraph::const_iterator N = G.GraphMap.begin(), NE = G.GraphMap.end();
|
||||
for(MSchedGraph::const_iterator N = G.GraphMap.begin(), NE = G.GraphMap.end();
|
||||
N != NE; ++N) {
|
||||
MSchedGraphNode *newNode = new MSchedGraphNode(*(N->second));
|
||||
oldToNew[&*(N->second)] = newNode;
|
||||
newNodes[newNode] = &*(N->second);
|
||||
GraphMap[&*(N->first)] = newNode;
|
||||
}
|
||||
|
||||
|
||||
//Loop over nodes and update edges to point to new nodes
|
||||
for(MSchedGraph::iterator N = GraphMap.begin(), NE = GraphMap.end(); N != NE; ++N) {
|
||||
|
||||
|
||||
//Get the node we are dealing with
|
||||
MSchedGraphNode *node = &*(N->second);
|
||||
|
||||
@@ -185,13 +185,13 @@ MSchedGraph::MSchedGraph(const MSchedGraph &G, std::map<MSchedGraphNode*, MSched
|
||||
for(unsigned i = 0; i < node->pred_size(); ++i) {
|
||||
node->setPredecessor(i, oldToNew[node->getPredecessor(i)]);
|
||||
}
|
||||
|
||||
|
||||
for(unsigned i = 0; i < node->succ_size(); ++i) {
|
||||
MSchedGraphEdge *edge = node->getSuccessor(i);
|
||||
MSchedGraphNode *oldDest = edge->getDest();
|
||||
edge->setDest(oldToNew[oldDest]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Deconstructor, deletes all nodes in the graph
|
||||
@@ -202,7 +202,7 @@ MSchedGraph::~MSchedGraph () {
|
||||
|
||||
|
||||
//Experimental code to add edges from the branch to all nodes dependent upon it.
|
||||
void hasPath(MSchedGraphNode *node, std::set<MSchedGraphNode*> &visited,
|
||||
void hasPath(MSchedGraphNode *node, std::set<MSchedGraphNode*> &visited,
|
||||
std::set<MSchedGraphNode*> &branches, MSchedGraphNode *startNode,
|
||||
std::set<std::pair<MSchedGraphNode*,MSchedGraphNode*> > &newEdges ) {
|
||||
|
||||
@@ -214,7 +214,7 @@ void hasPath(MSchedGraphNode *node, std::set<MSchedGraphNode*> &visited,
|
||||
MSchedGraphNode *dest = edge->getDest();
|
||||
if(branches.count(dest))
|
||||
newEdges.insert(std::make_pair(dest, startNode));
|
||||
|
||||
|
||||
//only visit if we have not already
|
||||
else if(!visited.count(dest)) {
|
||||
if(edge->getIteDiff() == 0)
|
||||
@@ -246,26 +246,26 @@ void MSchedGraph::addBranchEdges() {
|
||||
//Spit out all edges we are going to add
|
||||
unsigned min = GraphMap.size();
|
||||
if(newEdges.size() == 1) {
|
||||
((newEdges.begin())->first)->addOutEdge(((newEdges.begin())->second),
|
||||
MSchedGraphEdge::BranchDep,
|
||||
((newEdges.begin())->first)->addOutEdge(((newEdges.begin())->second),
|
||||
MSchedGraphEdge::BranchDep,
|
||||
MSchedGraphEdge::NonDataDep, 1);
|
||||
}
|
||||
else {
|
||||
|
||||
|
||||
unsigned count = 0;
|
||||
MSchedGraphNode *start;
|
||||
MSchedGraphNode *end;
|
||||
for(std::set<std::pair<MSchedGraphNode*, MSchedGraphNode*> >::iterator I = newEdges.begin(), E = newEdges.end(); I != E; ++I) {
|
||||
|
||||
|
||||
DEBUG(std::cerr << "Branch Edge from: " << *(I->first) << " to " << *(I->second) << "\n");
|
||||
|
||||
|
||||
// if(I->second->getIndex() <= min) {
|
||||
start = I->first;
|
||||
end = I->second;
|
||||
//min = I->second->getIndex();
|
||||
//}
|
||||
start->addOutEdge(end,
|
||||
MSchedGraphEdge::BranchDep,
|
||||
start->addOutEdge(end,
|
||||
MSchedGraphEdge::BranchDep,
|
||||
MSchedGraphEdge::NonDataDep, 1);
|
||||
}
|
||||
}
|
||||
@@ -276,7 +276,7 @@ void MSchedGraph::addBranchEdges() {
|
||||
void MSchedGraph::buildNodesAndEdges(std::map<const MachineInstr*, unsigned> &ignoreInstrs,
|
||||
DependenceAnalyzer &DA,
|
||||
std::map<MachineInstr*, Instruction*> &machineTollvm) {
|
||||
|
||||
|
||||
//Get Machine target information for calculating latency
|
||||
const TargetInstrInfo *MTI = Target.getInstrInfo();
|
||||
|
||||
@@ -300,7 +300,7 @@ void MSchedGraph::buildNodesAndEdges(std::map<const MachineInstr*, unsigned> &ig
|
||||
//Get each instruction of machine basic block, get the delay
|
||||
//using the op code, create a new node for it, and add to the
|
||||
//graph.
|
||||
|
||||
|
||||
MachineOpCode opCode = MI->getOpcode();
|
||||
int delay;
|
||||
|
||||
@@ -313,12 +313,12 @@ void MSchedGraph::buildNodesAndEdges(std::map<const MachineInstr*, unsigned> &ig
|
||||
#endif
|
||||
//Get delay
|
||||
delay = MTI->maxLatency(opCode);
|
||||
|
||||
|
||||
//Create new node for this machine instruction and add to the graph.
|
||||
//Create only if not a nop
|
||||
if(MTI->isNop(opCode))
|
||||
continue;
|
||||
|
||||
|
||||
//Sparc BE does not use PHI opcode, so assert on this case
|
||||
assert(opCode != TargetInstrInfo::PHI && "Did not expect PHI opcode");
|
||||
|
||||
@@ -331,9 +331,9 @@ void MSchedGraph::buildNodesAndEdges(std::map<const MachineInstr*, unsigned> &ig
|
||||
//Node is created and added to the graph automatically
|
||||
MSchedGraphNode *node = new MSchedGraphNode(MI, this, index, delay, isBranch);
|
||||
|
||||
DEBUG(std::cerr << "Created Node: " << *node << "\n");
|
||||
DEBUG(std::cerr << "Created Node: " << *node << "\n");
|
||||
|
||||
//Check OpCode to keep track of memory operations to add memory dependencies later.
|
||||
//Check OpCode to keep track of memory operations to add memory dependencies later.
|
||||
if(MTI->isLoad(opCode) || MTI->isStore(opCode))
|
||||
memInstructions.push_back(node);
|
||||
|
||||
@@ -343,8 +343,8 @@ void MSchedGraph::buildNodesAndEdges(std::map<const MachineInstr*, unsigned> &ig
|
||||
for(unsigned i=0; i < MI->getNumOperands(); ++i) {
|
||||
//Get Operand
|
||||
const MachineOperand &mOp = MI->getOperand(i);
|
||||
|
||||
//Check if it has an allocated register
|
||||
|
||||
//Check if it has an allocated register
|
||||
if(mOp.hasAllocatedReg()) {
|
||||
int regNum = mOp.getReg();
|
||||
|
||||
@@ -354,8 +354,8 @@ void MSchedGraph::buildNodesAndEdges(std::map<const MachineInstr*, unsigned> &ig
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//Add virtual registers dependencies
|
||||
//Check if any exist in the value map already and create dependencies
|
||||
//between them.
|
||||
@@ -369,19 +369,19 @@ void MSchedGraph::buildNodesAndEdges(std::map<const MachineInstr*, unsigned> &ig
|
||||
DEBUG(std::cerr << "Read Operation in a PHI node\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (const Value* srcI = mOp.getVRegValue()) {
|
||||
|
||||
|
||||
//Find value in the map
|
||||
std::map<const Value*, std::vector<OpIndexNodePair> >::iterator V
|
||||
std::map<const Value*, std::vector<OpIndexNodePair> >::iterator V
|
||||
= valuetoNodeMap.find(srcI);
|
||||
|
||||
|
||||
//If there is something in the map already, add edges from
|
||||
//those instructions
|
||||
//to this one we are processing
|
||||
if(V != valuetoNodeMap.end()) {
|
||||
addValueEdges(V->second, node, mOp.isUse(), mOp.isDef(), phiInstrs);
|
||||
|
||||
|
||||
//Add to value map
|
||||
V->second.push_back(std::make_pair(i,node));
|
||||
}
|
||||
@@ -390,7 +390,7 @@ void MSchedGraph::buildNodesAndEdges(std::map<const MachineInstr*, unsigned> &ig
|
||||
//Put into value map
|
||||
valuetoNodeMap[mOp.getVRegValue()].push_back(std::make_pair(i, node));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
++index;
|
||||
}
|
||||
@@ -437,7 +437,7 @@ void MSchedGraph::buildNodesAndEdges(std::map<const MachineInstr*, unsigned> &ig
|
||||
if (const Value* srcI = mOp.getVRegValue()) {
|
||||
|
||||
//Find value in the map
|
||||
std::map<const Value*, std::vector<OpIndexNodePair> >::iterator V
|
||||
std::map<const Value*, std::vector<OpIndexNodePair> >::iterator V
|
||||
= valuetoNodeMap.find(srcI);
|
||||
|
||||
//If there is something in the map already, add edges from
|
||||
@@ -449,17 +449,17 @@ void MSchedGraph::buildNodesAndEdges(std::map<const MachineInstr*, unsigned> &ig
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Add dependencies for Value*s
|
||||
void MSchedGraph::addValueEdges(std::vector<OpIndexNodePair> &NodesInMap,
|
||||
MSchedGraphNode *destNode, bool nodeIsUse,
|
||||
MSchedGraphNode *destNode, bool nodeIsUse,
|
||||
bool nodeIsDef, std::vector<const MachineInstr*> &phiInstrs, int diff) {
|
||||
|
||||
for(std::vector<OpIndexNodePair>::iterator I = NodesInMap.begin(),
|
||||
for(std::vector<OpIndexNodePair>::iterator I = NodesInMap.begin(),
|
||||
E = NodesInMap.end(); I != E; ++I) {
|
||||
|
||||
|
||||
//Get node in vectors machine operand that is the same value as node
|
||||
MSchedGraphNode *srcNode = I->second;
|
||||
MachineOperand mOp = srcNode->getInst()->getOperand(I->first);
|
||||
@@ -472,23 +472,23 @@ void MSchedGraph::addValueEdges(std::vector<OpIndexNodePair> &NodesInMap,
|
||||
if(nodeIsDef) {
|
||||
if(mOp.isUse()) {
|
||||
DEBUG(std::cerr << "Edge from " << *srcNode << " to " << *destNode << " (itediff=" << diff << ", type=anti)\n");
|
||||
srcNode->addOutEdge(destNode, MSchedGraphEdge::ValueDep,
|
||||
srcNode->addOutEdge(destNode, MSchedGraphEdge::ValueDep,
|
||||
MSchedGraphEdge::AntiDep, diff);
|
||||
}
|
||||
if(mOp.isDef()) {
|
||||
DEBUG(std::cerr << "Edge from " << *srcNode << " to " << *destNode << " (itediff=" << diff << ", type=output)\n");
|
||||
srcNode->addOutEdge(destNode, MSchedGraphEdge::ValueDep,
|
||||
srcNode->addOutEdge(destNode, MSchedGraphEdge::ValueDep,
|
||||
MSchedGraphEdge::OutputDep, diff);
|
||||
}
|
||||
}
|
||||
if(nodeIsUse) {
|
||||
if(mOp.isDef()) {
|
||||
DEBUG(std::cerr << "Edge from " << *srcNode << " to " << *destNode << " (itediff=" << diff << ", type=true)\n");
|
||||
srcNode->addOutEdge(destNode, MSchedGraphEdge::ValueDep,
|
||||
srcNode->addOutEdge(destNode, MSchedGraphEdge::ValueDep,
|
||||
MSchedGraphEdge::TrueDep, diff);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Add dependencies for machine registers across iterations
|
||||
@@ -502,24 +502,24 @@ void MSchedGraph::addMachRegEdges(std::map<int, std::vector<OpIndexNodePair> >&
|
||||
|
||||
//Get Vector of nodes that use this register
|
||||
std::vector<OpIndexNodePair> Nodes = (*I).second;
|
||||
|
||||
|
||||
//Loop over nodes and determine the dependence between the other
|
||||
//nodes in the vector
|
||||
for(unsigned i =0; i < Nodes.size(); ++i) {
|
||||
|
||||
|
||||
//Get src node operator index that uses this machine register
|
||||
int srcOpIndex = Nodes[i].first;
|
||||
|
||||
|
||||
//Get the actual src Node
|
||||
MSchedGraphNode *srcNode = Nodes[i].second;
|
||||
|
||||
|
||||
//Get Operand
|
||||
const MachineOperand &srcMOp = srcNode->getInst()->getOperand(srcOpIndex);
|
||||
|
||||
|
||||
bool srcIsUseandDef = srcMOp.isDef() && srcMOp.isUse();
|
||||
bool srcIsUse = srcMOp.isUse() && !srcMOp.isDef();
|
||||
|
||||
|
||||
|
||||
|
||||
//Look at all instructions after this in execution order
|
||||
for(unsigned j=i+1; j < Nodes.size(); ++j) {
|
||||
|
||||
@@ -529,11 +529,11 @@ void MSchedGraph::addMachRegEdges(std::map<int, std::vector<OpIndexNodePair> >&
|
||||
if(srcIsUse)
|
||||
srcNode->addOutEdge(Nodes[j].second, MSchedGraphEdge::MachineRegister,
|
||||
MSchedGraphEdge::AntiDep);
|
||||
|
||||
|
||||
else if(srcIsUseandDef) {
|
||||
srcNode->addOutEdge(Nodes[j].second, MSchedGraphEdge::MachineRegister,
|
||||
MSchedGraphEdge::AntiDep);
|
||||
|
||||
|
||||
srcNode->addOutEdge(Nodes[j].second, MSchedGraphEdge::MachineRegister,
|
||||
MSchedGraphEdge::OutputDep);
|
||||
}
|
||||
@@ -547,9 +547,9 @@ void MSchedGraph::addMachRegEdges(std::map<int, std::vector<OpIndexNodePair> >&
|
||||
srcNode->addOutEdge(Nodes[j].second, MSchedGraphEdge::MachineRegister,
|
||||
MSchedGraphEdge::TrueDep);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
//Look at all the instructions before this one since machine registers
|
||||
//could live across iterations.
|
||||
for(unsigned j = 0; j < i; ++j) {
|
||||
@@ -559,11 +559,11 @@ void MSchedGraph::addMachRegEdges(std::map<int, std::vector<OpIndexNodePair> >&
|
||||
if(srcIsUse)
|
||||
srcNode->addOutEdge(Nodes[j].second, MSchedGraphEdge::MachineRegister,
|
||||
MSchedGraphEdge::AntiDep, 1);
|
||||
|
||||
|
||||
else if(srcIsUseandDef) {
|
||||
srcNode->addOutEdge(Nodes[j].second, MSchedGraphEdge::MachineRegister,
|
||||
MSchedGraphEdge::AntiDep, 1);
|
||||
|
||||
|
||||
srcNode->addOutEdge(Nodes[j].second, MSchedGraphEdge::MachineRegister,
|
||||
MSchedGraphEdge::OutputDep, 1);
|
||||
}
|
||||
@@ -582,19 +582,19 @@ void MSchedGraph::addMachRegEdges(std::map<int, std::vector<OpIndexNodePair> >&
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//Add edges between all loads and stores
|
||||
//Can be less strict with alias analysis and data dependence analysis.
|
||||
void MSchedGraph::addMemEdges(const std::vector<MSchedGraphNode*>& memInst, DependenceAnalyzer &DA,
|
||||
void MSchedGraph::addMemEdges(const std::vector<MSchedGraphNode*>& memInst, DependenceAnalyzer &DA,
|
||||
std::map<MachineInstr*, Instruction*> &machineTollvm) {
|
||||
|
||||
//Get Target machine instruction info
|
||||
const TargetInstrInfo *TMI = Target.getInstrInfo();
|
||||
|
||||
|
||||
//Loop over all memory instructions in the vector
|
||||
//Knowing that they are in execution, add true, anti, and output dependencies
|
||||
for (unsigned srcIndex = 0; srcIndex < memInst.size(); ++srcIndex) {
|
||||
@@ -603,12 +603,12 @@ void MSchedGraph::addMemEdges(const std::vector<MSchedGraphNode*>& memInst, Depe
|
||||
|
||||
//Get the machine opCode to determine type of memory instruction
|
||||
MachineOpCode srcNodeOpCode = srcInst->getOpcode();
|
||||
|
||||
|
||||
//All instructions after this one in execution order have an iteration delay of 0
|
||||
for(unsigned destIndex = srcIndex + 1; destIndex < memInst.size(); ++destIndex) {
|
||||
|
||||
|
||||
MachineInstr *destInst = (MachineInstr*) memInst[destIndex]->getInst();
|
||||
|
||||
|
||||
DEBUG(std::cerr << "MInst1: " << *srcInst << "\n");
|
||||
DEBUG(std::cerr << "Inst1: " << *machineTollvm[srcInst] << "\n");
|
||||
DEBUG(std::cerr << "MInst2: " << *destInst << "\n");
|
||||
@@ -619,17 +619,17 @@ void MSchedGraph::addMemEdges(const std::vector<MSchedGraphNode*>& memInst, Depe
|
||||
for(std::vector<Dependence>::iterator d = dr.dependences.begin(), de = dr.dependences.end();
|
||||
d != de; ++d) {
|
||||
//Add edge from load to store
|
||||
memInst[srcIndex]->addOutEdge(memInst[destIndex],
|
||||
MSchedGraphEdge::MemoryDep,
|
||||
memInst[srcIndex]->addOutEdge(memInst[destIndex],
|
||||
MSchedGraphEdge::MemoryDep,
|
||||
d->getDepType(), d->getIteDiff());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//All instructions before the src in execution order have an iteration delay of 1
|
||||
for(unsigned destIndex = 0; destIndex < srcIndex; ++destIndex) {
|
||||
|
||||
|
||||
MachineInstr *destInst = (MachineInstr*) memInst[destIndex]->getInst();
|
||||
bool malias = false;
|
||||
|
||||
@@ -652,14 +652,14 @@ void MSchedGraph::addMemEdges(const std::vector<MSchedGraphNode*>& memInst, Depe
|
||||
malias = true;
|
||||
|
||||
//Only add the edge if we can't verify that they do not alias
|
||||
/*if(AA.alias(mOp2.getVRegValue(),
|
||||
/*if(AA.alias(mOp2.getVRegValue(),
|
||||
(unsigned)TD.getTypeSize(mOp2.getVRegValue()->getType()),
|
||||
mOp.getVRegValue(),
|
||||
mOp.getVRegValue(),
|
||||
(unsigned)TD.getTypeSize(mOp.getVRegValue()->getType()))
|
||||
!= AliasAnalysis::NoAlias) {*/
|
||||
if(TMI->isStore(memInst[destIndex]->getInst()->getOpcode()))
|
||||
memInst[srcIndex]->addOutEdge(memInst[destIndex],
|
||||
MSchedGraphEdge::MemoryDep,
|
||||
memInst[srcIndex]->addOutEdge(memInst[destIndex],
|
||||
MSchedGraphEdge::MemoryDep,
|
||||
MSchedGraphEdge::AntiDep, 1);
|
||||
//}
|
||||
}
|
||||
@@ -681,24 +681,24 @@ void MSchedGraph::addMemEdges(const std::vector<MSchedGraphNode*>& memInst, Depe
|
||||
malias = true;
|
||||
|
||||
//Only add the edge if we can't verify that they do not alias
|
||||
/*if(AA.alias(mOp2.getVRegValue(),
|
||||
/*if(AA.alias(mOp2.getVRegValue(),
|
||||
(unsigned)TD.getTypeSize(mOp2.getVRegValue()->getType()),
|
||||
mOp.getVRegValue(),
|
||||
mOp.getVRegValue(),
|
||||
(unsigned)TD.getTypeSize(mOp.getVRegValue()->getType()))
|
||||
!= AliasAnalysis::NoAlias) {*/
|
||||
|
||||
if(TMI->isStore(memInst[destIndex]->getInst()->getOpcode()))
|
||||
memInst[srcIndex]->addOutEdge(memInst[destIndex],
|
||||
MSchedGraphEdge::MemoryDep,
|
||||
memInst[srcIndex]->addOutEdge(memInst[destIndex],
|
||||
MSchedGraphEdge::MemoryDep,
|
||||
MSchedGraphEdge::OutputDep, 1);
|
||||
else
|
||||
memInst[srcIndex]->addOutEdge(memInst[destIndex],
|
||||
MSchedGraphEdge::MemoryDep,
|
||||
memInst[srcIndex]->addOutEdge(memInst[destIndex],
|
||||
MSchedGraphEdge::MemoryDep,
|
||||
MSchedGraphEdge::TrueDep, 1);
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
// A graph class for dependencies. This graph only contains true, anti, and
|
||||
// output data dependencies for a given MachineBasicBlock. Dependencies
|
||||
// across iterations are also computed. Unless data dependence analysis
|
||||
// is provided, a conservative approach of adding dependencies between all
|
||||
// is provided, a conservative approach of adding dependencies between all
|
||||
// loads and stores is taken.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
|
||||
class MSchedGraph;
|
||||
class MSchedGraphNode;
|
||||
template<class IteratorType, class NodeType>
|
||||
@@ -40,12 +40,12 @@ namespace llvm {
|
||||
enum DataDepOrderType {
|
||||
TrueDep, AntiDep, OutputDep, NonDataDep
|
||||
};
|
||||
|
||||
|
||||
enum MSchedGraphEdgeType {
|
||||
MemoryDep, ValueDep, MachineRegister, BranchDep
|
||||
};
|
||||
|
||||
//Get or set edge data
|
||||
//Get or set edge data
|
||||
MSchedGraphNode *getDest() const { return dest; }
|
||||
unsigned getIteDiff() { return iteDiff; }
|
||||
unsigned getDepOrderType() { return depOrderType; }
|
||||
@@ -53,10 +53,10 @@ namespace llvm {
|
||||
|
||||
private:
|
||||
friend class MSchedGraphNode;
|
||||
MSchedGraphEdge(MSchedGraphNode *destination, MSchedGraphEdgeType type,
|
||||
unsigned deptype, unsigned diff)
|
||||
MSchedGraphEdge(MSchedGraphNode *destination, MSchedGraphEdgeType type,
|
||||
unsigned deptype, unsigned diff)
|
||||
: dest(destination), depType(type), depOrderType(deptype), iteDiff(diff) {}
|
||||
|
||||
|
||||
MSchedGraphNode *dest;
|
||||
MSchedGraphEdgeType depType;
|
||||
unsigned depOrderType;
|
||||
@@ -67,18 +67,18 @@ namespace llvm {
|
||||
//corresponding latency. Each node also contains a list of its
|
||||
//predecessors and sucessors.
|
||||
class MSchedGraphNode {
|
||||
|
||||
|
||||
const MachineInstr* Inst; //Machine Instruction
|
||||
MSchedGraph* Parent; //Graph this node belongs to
|
||||
unsigned index; //Index in BB
|
||||
unsigned latency; //Latency of Instruction
|
||||
bool isBranchInstr; //Is this node the branch instr or not
|
||||
|
||||
|
||||
std::vector<MSchedGraphNode*> Predecessors; //Predecessor Nodes
|
||||
std::vector<MSchedGraphEdge> Successors; //Successor edges
|
||||
|
||||
public:
|
||||
MSchedGraphNode(const MachineInstr *inst, MSchedGraph *graph,
|
||||
MSchedGraphNode(const MachineInstr *inst, MSchedGraph *graph,
|
||||
unsigned index, unsigned late=0, bool isBranch=false);
|
||||
|
||||
MSchedGraphNode(const MSchedGraphNode &N);
|
||||
@@ -92,7 +92,7 @@ namespace llvm {
|
||||
typedef std::vector<MSchedGraphNode*>::const_iterator pred_const_iterator;
|
||||
pred_const_iterator pred_begin() const { return Predecessors.begin(); }
|
||||
pred_const_iterator pred_end() const { return Predecessors.end(); }
|
||||
|
||||
|
||||
typedef MSchedGraphNodeIterator<std::vector<MSchedGraphEdge>::const_iterator,
|
||||
const MSchedGraphNode> succ_const_iterator;
|
||||
succ_const_iterator succ_begin() const;
|
||||
@@ -108,15 +108,15 @@ namespace llvm {
|
||||
void setPredecessor(unsigned index, MSchedGraphNode *dest) {
|
||||
Predecessors[index] = dest;
|
||||
}
|
||||
|
||||
|
||||
MSchedGraphNode* getPredecessor(unsigned index) {
|
||||
return Predecessors[index];
|
||||
}
|
||||
|
||||
|
||||
MSchedGraphEdge* getSuccessor(unsigned index) {
|
||||
return &Successors[index];
|
||||
}
|
||||
|
||||
|
||||
void deleteSuccessor(MSchedGraphNode *node) {
|
||||
for (unsigned i = 0; i != Successors.size(); ++i)
|
||||
if (Successors[i].getDest() == node) {
|
||||
@@ -127,8 +127,8 @@ namespace llvm {
|
||||
}
|
||||
}
|
||||
|
||||
void addOutEdge(MSchedGraphNode *destination,
|
||||
MSchedGraphEdge::MSchedGraphEdgeType type,
|
||||
void addOutEdge(MSchedGraphNode *destination,
|
||||
MSchedGraphEdge::MSchedGraphEdgeType type,
|
||||
unsigned deptype, unsigned diff=0) {
|
||||
Successors.push_back(MSchedGraphEdge(destination, type, deptype,diff));
|
||||
destination->Predecessors.push_back(this);
|
||||
@@ -173,13 +173,13 @@ namespace llvm {
|
||||
return I->getDest();
|
||||
}
|
||||
NodeType* operator->() const { return operator*(); }
|
||||
|
||||
|
||||
MSchedGraphNodeIterator& operator++() { // Preincrement
|
||||
++I;
|
||||
return *this;
|
||||
}
|
||||
MSchedGraphNodeIterator operator++(int) { // Postincrement
|
||||
MSchedGraphNodeIterator tmp = *this; ++*this; return tmp;
|
||||
MSchedGraphNodeIterator tmp = *this; ++*this; return tmp;
|
||||
}
|
||||
|
||||
MSchedGraphEdge &getEdge() {
|
||||
@@ -204,7 +204,7 @@ namespace llvm {
|
||||
}
|
||||
|
||||
// ostream << operator for MSGraphNode class
|
||||
inline std::ostream &operator<<(std::ostream &os,
|
||||
inline std::ostream &operator<<(std::ostream &os,
|
||||
const MSchedGraphNode &node) {
|
||||
node.print(os);
|
||||
return os;
|
||||
@@ -217,56 +217,56 @@ namespace llvm {
|
||||
template <> struct GraphTraits<MSchedGraphNode*> {
|
||||
typedef MSchedGraphNode NodeType;
|
||||
typedef MSchedGraphNode::succ_iterator ChildIteratorType;
|
||||
|
||||
static inline ChildIteratorType child_begin(NodeType *N) {
|
||||
return N->succ_begin();
|
||||
|
||||
static inline ChildIteratorType child_begin(NodeType *N) {
|
||||
return N->succ_begin();
|
||||
}
|
||||
static inline ChildIteratorType child_end(NodeType *N) {
|
||||
static inline ChildIteratorType child_end(NodeType *N) {
|
||||
return N->succ_end();
|
||||
}
|
||||
|
||||
static NodeType *getEntryNode(NodeType* N) { return N; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//Graph class to represent dependence graph
|
||||
class MSchedGraph {
|
||||
|
||||
|
||||
const MachineBasicBlock *BB; //Machine basic block
|
||||
const TargetMachine &Target; //Target Machine
|
||||
|
||||
|
||||
//Nodes
|
||||
std::map<const MachineInstr*, MSchedGraphNode*> GraphMap;
|
||||
|
||||
//Add Nodes and Edges to this graph for our BB
|
||||
typedef std::pair<int, MSchedGraphNode*> OpIndexNodePair;
|
||||
void buildNodesAndEdges(std::map<const MachineInstr*, unsigned> &ignoreInstrs, DependenceAnalyzer &DA, std::map<MachineInstr*, Instruction*> &machineTollvm);
|
||||
void addValueEdges(std::vector<OpIndexNodePair> &NodesInMap,
|
||||
void addValueEdges(std::vector<OpIndexNodePair> &NodesInMap,
|
||||
MSchedGraphNode *node,
|
||||
bool nodeIsUse, bool nodeIsDef, std::vector<const MachineInstr*> &phiInstrs, int diff=0);
|
||||
void addMachRegEdges(std::map<int,
|
||||
void addMachRegEdges(std::map<int,
|
||||
std::vector<OpIndexNodePair> >& regNumtoNodeMap);
|
||||
void addMemEdges(const std::vector<MSchedGraphNode*>& memInst,
|
||||
DependenceAnalyzer &DA, std::map<MachineInstr*, Instruction*> &machineTollvm);
|
||||
void addBranchEdges();
|
||||
|
||||
public:
|
||||
MSchedGraph(const MachineBasicBlock *bb, const TargetMachine &targ,
|
||||
std::map<const MachineInstr*, unsigned> &ignoreInstrs,
|
||||
MSchedGraph(const MachineBasicBlock *bb, const TargetMachine &targ,
|
||||
std::map<const MachineInstr*, unsigned> &ignoreInstrs,
|
||||
DependenceAnalyzer &DA, std::map<MachineInstr*, Instruction*> &machineTollvm);
|
||||
|
||||
//Copy constructor with maps to link old nodes to new nodes
|
||||
MSchedGraph(const MSchedGraph &G, std::map<MSchedGraphNode*, MSchedGraphNode*> &newNodes);
|
||||
|
||||
|
||||
//Deconstructor!
|
||||
~MSchedGraph();
|
||||
|
||||
|
||||
//Add or delete nodes from the Graph
|
||||
void addNode(const MachineInstr* MI, MSchedGraphNode *node);
|
||||
void deleteNode(MSchedGraphNode *node);
|
||||
|
||||
//iterators
|
||||
//iterators
|
||||
typedef std::map<const MachineInstr*, MSchedGraphNode*>::iterator iterator;
|
||||
typedef std::map<const MachineInstr*, MSchedGraphNode*>::const_iterator const_iterator;
|
||||
typedef std::map<const MachineInstr*, MSchedGraphNode*>::reverse_iterator reverse_iterator;
|
||||
@@ -283,7 +283,7 @@ namespace llvm {
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Provide specializations of GraphTraits to be able to use graph
|
||||
@@ -296,11 +296,11 @@ namespace llvm {
|
||||
template <> struct GraphTraits<MSchedGraph*> {
|
||||
typedef MSchedGraphNode NodeType;
|
||||
typedef MSchedGraphNode::succ_iterator ChildIteratorType;
|
||||
|
||||
static inline ChildIteratorType child_begin(NodeType *N) {
|
||||
return N->succ_begin();
|
||||
|
||||
static inline ChildIteratorType child_begin(NodeType *N) {
|
||||
return N->succ_begin();
|
||||
}
|
||||
static inline ChildIteratorType child_end(NodeType *N) {
|
||||
static inline ChildIteratorType child_end(NodeType *N) {
|
||||
return N->succ_end();
|
||||
}
|
||||
|
||||
@@ -316,20 +316,20 @@ namespace llvm {
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
template <> struct GraphTraits<const MSchedGraph*> {
|
||||
typedef const MSchedGraphNode NodeType;
|
||||
typedef MSchedGraphNode::succ_const_iterator ChildIteratorType;
|
||||
|
||||
static inline ChildIteratorType child_begin(NodeType *N) {
|
||||
return N->succ_begin();
|
||||
|
||||
static inline ChildIteratorType child_begin(NodeType *N) {
|
||||
return N->succ_begin();
|
||||
}
|
||||
static inline ChildIteratorType child_end(NodeType *N) {
|
||||
static inline ChildIteratorType child_end(NodeType *N) {
|
||||
return N->succ_end();
|
||||
}
|
||||
typedef std::pointer_to_unary_function<std::pair<const MachineInstr* const,
|
||||
MSchedGraphNode*>&, MSchedGraphNode&> DerefFun;
|
||||
|
||||
|
||||
typedef mapped_iterator<MSchedGraph::iterator, DerefFun> nodes_iterator;
|
||||
static nodes_iterator nodes_begin(MSchedGraph *G) {
|
||||
return map_iterator(((MSchedGraph*)G)->begin(), DerefFun(getSecond));
|
||||
@@ -338,15 +338,15 @@ namespace llvm {
|
||||
return map_iterator(((MSchedGraph*)G)->end(), DerefFun(getSecond));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <> struct GraphTraits<Inverse<MSchedGraph*> > {
|
||||
typedef MSchedGraphNode NodeType;
|
||||
typedef MSchedGraphNode::pred_iterator ChildIteratorType;
|
||||
|
||||
static inline ChildIteratorType child_begin(NodeType *N) {
|
||||
|
||||
static inline ChildIteratorType child_begin(NodeType *N) {
|
||||
return N->pred_begin();
|
||||
}
|
||||
static inline ChildIteratorType child_end(NodeType *N) {
|
||||
static inline ChildIteratorType child_end(NodeType *N) {
|
||||
return N->pred_end();
|
||||
}
|
||||
typedef std::pointer_to_unary_function<std::pair<const MachineInstr* const,
|
||||
@@ -360,21 +360,21 @@ namespace llvm {
|
||||
return map_iterator(((MSchedGraph*)G)->end(), DerefFun(getSecond));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <> struct GraphTraits<Inverse<const MSchedGraph*> > {
|
||||
typedef const MSchedGraphNode NodeType;
|
||||
typedef MSchedGraphNode::pred_const_iterator ChildIteratorType;
|
||||
|
||||
static inline ChildIteratorType child_begin(NodeType *N) {
|
||||
|
||||
static inline ChildIteratorType child_begin(NodeType *N) {
|
||||
return N->pred_begin();
|
||||
}
|
||||
static inline ChildIteratorType child_end(NodeType *N) {
|
||||
static inline ChildIteratorType child_end(NodeType *N) {
|
||||
return N->pred_end();
|
||||
}
|
||||
|
||||
typedef std::pointer_to_unary_function<std::pair<const MachineInstr* const,
|
||||
MSchedGraphNode*>&, MSchedGraphNode&> DerefFun;
|
||||
|
||||
|
||||
typedef mapped_iterator<MSchedGraph::iterator, DerefFun> nodes_iterator;
|
||||
static nodes_iterator nodes_begin(MSchedGraph *G) {
|
||||
return map_iterator(((MSchedGraph*)G)->begin(), DerefFun(getSecond));
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,8 +6,8 @@
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_MODULOSCHEDULING_H
|
||||
@@ -22,7 +22,7 @@
|
||||
#include <set>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
|
||||
|
||||
//Struct to contain ModuloScheduling Specific Information for each node
|
||||
struct MSNodeAttributes {
|
||||
@@ -31,9 +31,9 @@ namespace llvm {
|
||||
int MOB;
|
||||
int depth;
|
||||
int height;
|
||||
MSNodeAttributes(int asap=-1, int alap=-1, int mob=-1,
|
||||
int d=-1, int h=-1) : ASAP(asap), ALAP(alap),
|
||||
MOB(mob), depth(d),
|
||||
MSNodeAttributes(int asap=-1, int alap=-1, int mob=-1,
|
||||
int d=-1, int h=-1) : ASAP(asap), ALAP(alap),
|
||||
MOB(mob), depth(d),
|
||||
height(h) {}
|
||||
};
|
||||
|
||||
@@ -55,19 +55,19 @@ namespace llvm {
|
||||
|
||||
//Map that holds node to node attribute information
|
||||
std::map<MSchedGraphNode*, MSNodeAttributes> nodeToAttributesMap;
|
||||
|
||||
|
||||
//Map to hold all reccurrences
|
||||
std::set<std::pair<int, std::vector<MSchedGraphNode*> > > recurrenceList;
|
||||
|
||||
|
||||
//Set of edges to ignore, stored as src node and index into vector of successors
|
||||
std::set<std::pair<MSchedGraphNode*, unsigned> > edgesToIgnore;
|
||||
|
||||
|
||||
//Vector containing the partial order
|
||||
std::vector<std::set<MSchedGraphNode*> > partialOrder;
|
||||
|
||||
|
||||
//Vector containing the final node order
|
||||
std::vector<MSchedGraphNode*> FinalNodeOrder;
|
||||
|
||||
|
||||
//Schedule table, key is the cycle number and the vector is resource, node pairs
|
||||
MSSchedule schedule;
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace llvm {
|
||||
//Internal functions
|
||||
bool CreateDefMap(MachineBasicBlock *BI);
|
||||
bool MachineBBisValid(const MachineBasicBlock *BI);
|
||||
bool assocIndVar(Instruction *I, std::set<Instruction*> &indVar,
|
||||
bool assocIndVar(Instruction *I, std::set<Instruction*> &indVar,
|
||||
std::vector<Instruction*> &stack, BasicBlock *BB);
|
||||
int calculateResMII(const MachineBasicBlock *BI);
|
||||
int calculateRecMII(MSchedGraph *graph, int MII);
|
||||
@@ -93,59 +93,59 @@ namespace llvm {
|
||||
|
||||
int findMaxASAP();
|
||||
void orderNodes();
|
||||
void findAllReccurrences(MSchedGraphNode *node,
|
||||
void findAllReccurrences(MSchedGraphNode *node,
|
||||
std::vector<MSchedGraphNode*> &visitedNodes, int II);
|
||||
void addReccurrence(std::vector<MSchedGraphNode*> &recurrence, int II, MSchedGraphNode*, MSchedGraphNode*);
|
||||
|
||||
void findAllCircuits(MSchedGraph *MSG, int II);
|
||||
bool circuit(MSchedGraphNode *v, std::vector<MSchedGraphNode*> &stack,
|
||||
std::set<MSchedGraphNode*> &blocked,
|
||||
bool circuit(MSchedGraphNode *v, std::vector<MSchedGraphNode*> &stack,
|
||||
std::set<MSchedGraphNode*> &blocked,
|
||||
std::vector<MSchedGraphNode*> &SCC, MSchedGraphNode *s,
|
||||
std::map<MSchedGraphNode*, std::set<MSchedGraphNode*> > &B, int II,
|
||||
std::map<MSchedGraphNode*, MSchedGraphNode*> &newNodes);
|
||||
|
||||
|
||||
void unblock(MSchedGraphNode *u, std::set<MSchedGraphNode*> &blocked,
|
||||
std::map<MSchedGraphNode*, std::set<MSchedGraphNode*> > &B);
|
||||
|
||||
void searchPath(MSchedGraphNode *node,
|
||||
void searchPath(MSchedGraphNode *node,
|
||||
std::vector<MSchedGraphNode*> &path,
|
||||
std::set<MSchedGraphNode*> &nodesToAdd);
|
||||
|
||||
void pathToRecc(MSchedGraphNode *node,
|
||||
void pathToRecc(MSchedGraphNode *node,
|
||||
std::vector<MSchedGraphNode*> &path,
|
||||
std::set<MSchedGraphNode*> &poSet, std::set<MSchedGraphNode*> &lastNodes);
|
||||
|
||||
|
||||
void computePartialOrder();
|
||||
|
||||
bool computeSchedule(const MachineBasicBlock *BB);
|
||||
bool scheduleNode(MSchedGraphNode *node,
|
||||
bool scheduleNode(MSchedGraphNode *node,
|
||||
int start, int end);
|
||||
|
||||
void predIntersect(std::set<MSchedGraphNode*> &CurrentSet, std::set<MSchedGraphNode*> &IntersectResult);
|
||||
void succIntersect(std::set<MSchedGraphNode*> &CurrentSet, std::set<MSchedGraphNode*> &IntersectResult);
|
||||
|
||||
|
||||
void reconstructLoop(MachineBasicBlock*);
|
||||
|
||||
|
||||
//void saveValue(const MachineInstr*, const std::set<Value*>&, std::vector<Value*>*);
|
||||
|
||||
void fixBranches(std::vector<MachineBasicBlock *> &prologues, std::vector<BasicBlock*> &llvm_prologues, MachineBasicBlock *machineBB, BasicBlock *llvmBB, std::vector<MachineBasicBlock *> &epilogues, std::vector<BasicBlock*> &llvm_epilogues, MachineBasicBlock*);
|
||||
void fixBranches(std::vector<MachineBasicBlock *> &prologues, std::vector<BasicBlock*> &llvm_prologues, MachineBasicBlock *machineBB, BasicBlock *llvmBB, std::vector<MachineBasicBlock *> &epilogues, std::vector<BasicBlock*> &llvm_epilogues, MachineBasicBlock*);
|
||||
|
||||
void writePrologues(std::vector<MachineBasicBlock *> &prologues, MachineBasicBlock *origBB, std::vector<BasicBlock*> &llvm_prologues, std::map<const Value*, std::pair<const MachineInstr*, int> > &valuesToSave, std::map<Value*, std::map<int, Value*> > &newValues, std::map<Value*, MachineBasicBlock*> &newValLocation);
|
||||
|
||||
void writeEpilogues(std::vector<MachineBasicBlock *> &epilogues, const MachineBasicBlock *origBB, std::vector<BasicBlock*> &llvm_epilogues, std::map<const Value*, std::pair<const MachineInstr*, int> > &valuesToSave,std::map<Value*, std::map<int, Value*> > &newValues, std::map<Value*, MachineBasicBlock*> &newValLocation, std::map<Value*, std::map<int, Value*> > &kernelPHIs);
|
||||
|
||||
|
||||
|
||||
|
||||
void writeKernel(BasicBlock *llvmBB, MachineBasicBlock *machineBB, std::map<const Value*, std::pair<const MachineInstr*, int> > &valuesToSave, std::map<Value*, std::map<int, Value*> > &newValues, std::map<Value*, MachineBasicBlock*> &newValLocation, std::map<Value*, std::map<int, Value*> > &kernelPHIs);
|
||||
|
||||
void removePHIs(const MachineBasicBlock *origBB, std::vector<MachineBasicBlock *> &prologues, std::vector<MachineBasicBlock *> &epilogues, MachineBasicBlock *kernelBB, std::map<Value*, MachineBasicBlock*> &newValLocation);
|
||||
|
||||
|
||||
void connectedComponentSet(MSchedGraphNode *node, std::set<MSchedGraphNode*> &ccSet, std::set<MSchedGraphNode*> &lastNodes);
|
||||
|
||||
public:
|
||||
ModuloSchedulingPass(TargetMachine &targ) : target(targ) {}
|
||||
virtual bool runOnFunction(Function &F);
|
||||
virtual const char* getPassName() const { return "ModuloScheduling"; }
|
||||
|
||||
|
||||
// getAnalysisUsage
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.addRequired<DependenceAnalyzer>();
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===-- AllocInfo.h - Store info about regalloc decisions -------*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This header file contains the data structure used to save the state
|
||||
@@ -35,7 +35,7 @@ struct AllocInfo {
|
||||
AllocInfo (int Inst_, int Op_, AllocStateTy State_, int Place_) :
|
||||
Instruction(Inst_), Operand(Op_), AllocState(State_), Placement(Place_) { }
|
||||
|
||||
/// AllocInfo constructor -- Default constructor creates an invalid AllocInfo
|
||||
/// AllocInfo constructor -- Default constructor creates an invalid AllocInfo
|
||||
/// (presumably to be replaced with something meaningful later).
|
||||
///
|
||||
AllocInfo () :
|
||||
@@ -71,8 +71,8 @@ struct AllocInfo {
|
||||
///
|
||||
bool operator== (const AllocInfo &X) const {
|
||||
return (X.AllocState == AllocState) && (X.Placement == Placement);
|
||||
}
|
||||
bool operator!= (const AllocInfo &X) const { return !(*this == X); }
|
||||
}
|
||||
bool operator!= (const AllocInfo &X) const { return !(*this == X); }
|
||||
|
||||
/// Returns a human-readable string representation of the AllocState member.
|
||||
///
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
//===-- IGNode.cpp --------------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
// This file implements an Interference graph node for coloring-based register
|
||||
// allocation.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "IGNode.h"
|
||||
@@ -19,11 +19,11 @@
|
||||
namespace llvm {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Sets this IGNode on stack and reduce the degree of neighbors
|
||||
// Sets this IGNode on stack and reduce the degree of neighbors
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void IGNode::pushOnStack() {
|
||||
OnStack = true;
|
||||
OnStack = true;
|
||||
int neighs = AdjList.size();
|
||||
|
||||
if (neighs < 0) {
|
||||
@@ -34,7 +34,7 @@ void IGNode::pushOnStack() {
|
||||
for (int i=0; i < neighs; i++)
|
||||
AdjList[i]->decCurDegree();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Deletes an adjacency node. IGNodes are deleted when coalescing merges
|
||||
// two IGNodes together.
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
//===-- IGNode.h - Represent a node in an interference graph ----*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file represents a node in an interference graph.
|
||||
// This file represents a node in an interference graph.
|
||||
//
|
||||
// For efficiency, the AdjList is updated only once - ie. we can add but not
|
||||
// remove nodes from AdjList.
|
||||
// remove nodes from AdjList.
|
||||
//
|
||||
// The removal of nodes from IG is simulated by decrementing the CurDegree.
|
||||
// If this node is put on stack (that is removed from IG), the CurDegree of all
|
||||
@@ -44,15 +44,15 @@ class RegClass;
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class IGNode {
|
||||
const unsigned Index; // index within IGNodeList
|
||||
const unsigned Index; // index within IGNodeList
|
||||
bool OnStack; // this has been pushed on to stack for coloring
|
||||
std::vector<IGNode *> AdjList;// adjacency list for this live range
|
||||
|
||||
int CurDegree;
|
||||
int CurDegree;
|
||||
//
|
||||
// set by InterferenceGraph::setCurDegreeOfIGNodes() after calculating
|
||||
// all adjacency lists.
|
||||
// Decremented when a neighbor is pushed on to the stack.
|
||||
// Decremented when a neighbor is pushed on to the stack.
|
||||
// After that, never incremented/set again nor used.
|
||||
|
||||
LiveRange *const ParentLR;
|
||||
@@ -68,15 +68,15 @@ public:
|
||||
|
||||
// adjLists must be updated only once. However, the CurDegree can be changed
|
||||
//
|
||||
inline void addAdjIGNode(IGNode *AdjNode) { AdjList.push_back(AdjNode); }
|
||||
inline void addAdjIGNode(IGNode *AdjNode) { AdjList.push_back(AdjNode); }
|
||||
|
||||
inline IGNode *getAdjIGNode(unsigned ind) const
|
||||
inline IGNode *getAdjIGNode(unsigned ind) const
|
||||
{ assert ( ind < AdjList.size()); return AdjList[ind]; }
|
||||
|
||||
// delete a node in AdjList - node must be in the list
|
||||
// should not be called often
|
||||
//
|
||||
void delAdjIGNode(const IGNode *Node);
|
||||
void delAdjIGNode(const IGNode *Node);
|
||||
|
||||
inline unsigned getNumOfNeighbors() const { return AdjList.size(); }
|
||||
|
||||
@@ -87,7 +87,7 @@ public:
|
||||
|
||||
// remove form IG and pushes on to stack (reduce the degree of neighbors)
|
||||
//
|
||||
void pushOnStack();
|
||||
void pushOnStack();
|
||||
|
||||
// CurDegree is the effective number of neighbors when neighbors are
|
||||
// pushed on to the stack during the coloring phase. Must be called
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
//===-- InterferenceGraph.cpp ---------------------------------------------===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
// Interference graph for coloring-based register allocation for LLVM.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "IGNode.h"
|
||||
@@ -28,12 +28,12 @@ inline static void assertIGNode(const InterferenceGraph *IG,
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructor: Records the RegClass and initalizes IGNodeList.
|
||||
// The matrix is NOT yet created by the constructor. Call createGraph()
|
||||
// The matrix is NOT yet created by the constructor. Call createGraph()
|
||||
// to create it after adding all IGNodes to the IGNodeList.
|
||||
//-----------------------------------------------------------------------------
|
||||
InterferenceGraph::InterferenceGraph(RegClass *const RC) : RegCl(RC) {
|
||||
IG = NULL;
|
||||
Size = 0;
|
||||
IG = NULL;
|
||||
Size = 0;
|
||||
if( DEBUG_RA >= RA_DEBUG_Interference)
|
||||
std::cerr << "Interference graph created!\n";
|
||||
}
|
||||
@@ -58,15 +58,15 @@ InterferenceGraph:: ~InterferenceGraph() {
|
||||
// Creates (dynamically allocates) the bit matrix necessary to hold the
|
||||
// interference graph.
|
||||
//-----------------------------------------------------------------------------
|
||||
void InterferenceGraph::createGraph()
|
||||
{
|
||||
void InterferenceGraph::createGraph()
|
||||
{
|
||||
Size = IGNodeList.size();
|
||||
IG = new char*[Size];
|
||||
IG = new char*[Size];
|
||||
for( unsigned int r=0; r < Size; ++r)
|
||||
IG[r] = new char[Size];
|
||||
|
||||
// init IG matrix
|
||||
for(unsigned int i=0; i < Size; i++)
|
||||
for(unsigned int i=0; i < Size; i++)
|
||||
for(unsigned int j=0; j < Size; j++)
|
||||
IG[i][j] = 0;
|
||||
}
|
||||
@@ -89,27 +89,27 @@ void InterferenceGraph::addLRToIG(LiveRange *const LR)
|
||||
//-----------------------------------------------------------------------------
|
||||
void InterferenceGraph::setInterference(const LiveRange *const LR1,
|
||||
const LiveRange *const LR2 ) {
|
||||
assert(LR1 != LR2);
|
||||
assert(LR1 != LR2);
|
||||
|
||||
IGNode *IGNode1 = LR1->getUserIGNode();
|
||||
IGNode *IGNode2 = LR2->getUserIGNode();
|
||||
|
||||
assertIGNode(this, IGNode1);
|
||||
assertIGNode(this, IGNode1);
|
||||
assertIGNode(this, IGNode2);
|
||||
|
||||
|
||||
unsigned row = IGNode1->getIndex();
|
||||
unsigned col = IGNode2->getIndex();
|
||||
|
||||
char *val;
|
||||
|
||||
if( DEBUG_RA >= RA_DEBUG_Interference)
|
||||
std::cerr << "setting intf for: [" << row << "][" << col << "]\n";
|
||||
if( DEBUG_RA >= RA_DEBUG_Interference)
|
||||
std::cerr << "setting intf for: [" << row << "][" << col << "]\n";
|
||||
|
||||
( row > col) ? val = &IG[row][col]: val = &IG[col][row];
|
||||
( row > col) ? val = &IG[row][col]: val = &IG[col][row];
|
||||
|
||||
if( ! (*val) ) { // if this interf is not previously set
|
||||
*val = 1; // add edges between nodes
|
||||
IGNode1->addAdjIGNode( IGNode2 );
|
||||
*val = 1; // add edges between nodes
|
||||
IGNode1->addAdjIGNode( IGNode2 );
|
||||
IGNode2->addAdjIGNode( IGNode1 );
|
||||
}
|
||||
|
||||
@@ -122,17 +122,17 @@ void InterferenceGraph::setInterference(const LiveRange *const LR1,
|
||||
unsigned InterferenceGraph::getInterference(const LiveRange *const LR1,
|
||||
const LiveRange *const LR2) const {
|
||||
assert(LR1 != LR2);
|
||||
assertIGNode(this, LR1->getUserIGNode());
|
||||
assertIGNode(this, LR1->getUserIGNode());
|
||||
assertIGNode(this, LR2->getUserIGNode());
|
||||
|
||||
const unsigned int row = LR1->getUserIGNode()->getIndex();
|
||||
const unsigned int col = LR2->getUserIGNode()->getIndex();
|
||||
|
||||
char ret;
|
||||
char ret;
|
||||
if (row > col)
|
||||
ret = IG[row][col];
|
||||
else
|
||||
ret = IG[col][row];
|
||||
else
|
||||
ret = IG[col][row];
|
||||
return ret;
|
||||
|
||||
}
|
||||
@@ -141,11 +141,11 @@ unsigned InterferenceGraph::getInterference(const LiveRange *const LR1,
|
||||
//----------------------------------------------------------------------------
|
||||
// Merge 2 IGNodes. The neighbors of the SrcNode will be added to the DestNode.
|
||||
// Then the IGNode2L will be deleted. Necessary for coalescing.
|
||||
// IMPORTANT: The live ranges are NOT merged by this method. Use
|
||||
// IMPORTANT: The live ranges are NOT merged by this method. Use
|
||||
// LiveRangeInfo::unionAndUpdateLRs for that purpose.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void InterferenceGraph::mergeIGNodesOfLRs(const LiveRange *LR1,
|
||||
void InterferenceGraph::mergeIGNodesOfLRs(const LiveRange *LR1,
|
||||
LiveRange *LR2) {
|
||||
|
||||
assert( LR1 != LR2); // cannot merge the same live range
|
||||
@@ -165,31 +165,31 @@ void InterferenceGraph::mergeIGNodesOfLRs(const LiveRange *LR1,
|
||||
|
||||
|
||||
// for all neighs of SrcNode
|
||||
for(unsigned i=0; i < SrcDegree; i++) {
|
||||
IGNode *NeighNode = SrcNode->getAdjIGNode(i);
|
||||
for(unsigned i=0; i < SrcDegree; i++) {
|
||||
IGNode *NeighNode = SrcNode->getAdjIGNode(i);
|
||||
|
||||
LiveRange *const LROfNeigh = NeighNode->getParentLR();
|
||||
|
||||
// delete edge between src and neigh - even neigh == dest
|
||||
NeighNode->delAdjIGNode(SrcNode);
|
||||
NeighNode->delAdjIGNode(SrcNode);
|
||||
|
||||
// set the matrix posn to 0 betn src and neigh - even neigh == dest
|
||||
const unsigned NInd = NeighNode->getIndex();
|
||||
( SrcInd > NInd) ? (IG[SrcInd][NInd]=0) : (IG[NInd][SrcInd]=0) ;
|
||||
( SrcInd > NInd) ? (IG[SrcInd][NInd]=0) : (IG[NInd][SrcInd]=0) ;
|
||||
|
||||
|
||||
if( LR1 != LROfNeigh) { // if the neigh != dest
|
||||
|
||||
if( LR1 != LROfNeigh) { // if the neigh != dest
|
||||
|
||||
// add edge betwn Dest and Neigh - if there is no current edge
|
||||
setInterference(LR1, LROfNeigh );
|
||||
setInterference(LR1, LROfNeigh );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
IGNodeList[ SrcInd ] = NULL;
|
||||
|
||||
// SrcNode is no longer necessary - LR2 must be deleted by the caller
|
||||
delete( SrcNode );
|
||||
delete( SrcNode );
|
||||
|
||||
}
|
||||
|
||||
@@ -216,10 +216,10 @@ void InterferenceGraph::setCurDegreeOfIGNodes()
|
||||
//--------------------- debugging (Printing) methods -----------------------
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Print the IGnodes
|
||||
// Print the IGnodes
|
||||
//----------------------------------------------------------------------------
|
||||
void InterferenceGraph::printIG() const {
|
||||
for(unsigned i=0; i < Size; i++) {
|
||||
for(unsigned i=0; i < Size; i++) {
|
||||
const IGNode *const Node = IGNodeList[i];
|
||||
if(Node) {
|
||||
std::cerr << " [" << i << "] ";
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===-- InterferenceGraph.h - Interference graph for register coloring -*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/* Title: InterferenceGraph.h -*- C++ -*-
|
||||
@@ -12,17 +12,17 @@
|
||||
Date: July 20, 01
|
||||
Purpose: Interference Graph used for register coloring.
|
||||
|
||||
Notes:
|
||||
Adj Info is stored in the lower trangular matrix (i.e., row > col )
|
||||
Notes:
|
||||
Adj Info is stored in the lower trangular matrix (i.e., row > col )
|
||||
|
||||
This class must be used in the following way:
|
||||
|
||||
* Construct class
|
||||
* call addLRToIG as many times to add ALL LRs to this IG
|
||||
* call createGraph to create the actual matrix
|
||||
* Then setInterference, getInterference, mergeIGNodesOfLRs can be
|
||||
* Then setInterference, getInterference, mergeIGNodesOfLRs can be
|
||||
called as desired to modify the graph.
|
||||
* Once the modifications to the graph are over, call
|
||||
* Once the modifications to the graph are over, call
|
||||
setCurDegreeOfIGNodes() before pushing IGNodes on to stack for coloring.
|
||||
*/
|
||||
|
||||
@@ -42,9 +42,9 @@ class InterferenceGraph {
|
||||
unsigned int Size; // size of a side of the IG
|
||||
RegClass *const RegCl; // RegCl contains this IG
|
||||
std::vector<IGNode *> IGNodeList; // a list of all IGNodes in a reg class
|
||||
|
||||
|
||||
public:
|
||||
// the matrix is not yet created by the constructor. Call createGraph()
|
||||
// the matrix is not yet created by the constructor. Call createGraph()
|
||||
// to create it after adding all IGNodes to the IGNodeList
|
||||
InterferenceGraph(RegClass *RC);
|
||||
~InterferenceGraph();
|
||||
@@ -61,8 +61,8 @@ class InterferenceGraph {
|
||||
|
||||
void mergeIGNodesOfLRs(const LiveRange *LR1, LiveRange *LR2);
|
||||
|
||||
std::vector<IGNode *> &getIGNodeList() { return IGNodeList; }
|
||||
const std::vector<IGNode *> &getIGNodeList() const { return IGNodeList; }
|
||||
std::vector<IGNode *> &getIGNodeList() { return IGNodeList; }
|
||||
const std::vector<IGNode *> &getIGNodeList() const { return IGNodeList; }
|
||||
|
||||
void setCurDegreeOfIGNodes();
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//===-- LiveRange.h - Store info about a live range -------------*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Implements a live range using a SetVector of Value *s. We keep only
|
||||
@@ -34,7 +34,7 @@ private:
|
||||
ValueContainerType MyValues; // Values in this LiveRange
|
||||
RegClass *MyRegClass; // register class (e.g., int, FP) for this LR
|
||||
|
||||
/// doesSpanAcrossCalls - Does this live range span across calls?
|
||||
/// doesSpanAcrossCalls - Does this live range span across calls?
|
||||
/// This information is used by graph coloring algo to avoid allocating
|
||||
/// volatile colors to live ranges that span across calls (since they have to
|
||||
/// be saved/restored)
|
||||
@@ -56,7 +56,7 @@ private:
|
||||
/// this live range is not available before graph coloring (e.g., it
|
||||
/// can be allocated to another live range which interferes with
|
||||
/// this)
|
||||
///
|
||||
///
|
||||
bool CanUseSuggestedCol;
|
||||
|
||||
/// SpilledStackOffsetFromFP - If this LR is spilled, its stack
|
||||
@@ -83,7 +83,7 @@ public:
|
||||
void insert(iterator b, iterator e) { MyValues.insert (b, e); }
|
||||
|
||||
LiveRange() {
|
||||
Color = SuggestedColor = -1; // not yet colored
|
||||
Color = SuggestedColor = -1; // not yet colored
|
||||
mustSpill = false;
|
||||
MyRegClass = 0;
|
||||
UserIGNode = 0;
|
||||
@@ -99,21 +99,21 @@ public:
|
||||
unsigned getRegClassID() const;
|
||||
|
||||
bool hasColor() const { return Color != -1; }
|
||||
|
||||
|
||||
unsigned getColor() const { assert(Color != -1); return (unsigned)Color; }
|
||||
|
||||
void setColor(unsigned Col) { Color = (int)Col; }
|
||||
|
||||
inline void setCallInterference() {
|
||||
inline void setCallInterference() {
|
||||
doesSpanAcrossCalls = 1;
|
||||
}
|
||||
inline void clearCallInterference() {
|
||||
inline void clearCallInterference() {
|
||||
doesSpanAcrossCalls = 0;
|
||||
}
|
||||
|
||||
inline bool isCallInterference() const {
|
||||
return doesSpanAcrossCalls == 1;
|
||||
}
|
||||
inline bool isCallInterference() const {
|
||||
return doesSpanAcrossCalls == 1;
|
||||
}
|
||||
|
||||
inline void markForSpill() { mustSpill = true; }
|
||||
|
||||
@@ -150,7 +150,7 @@ public:
|
||||
inline const Type *getType() const {
|
||||
return (*begin())->getType(); // set's don't have a front
|
||||
}
|
||||
|
||||
|
||||
inline void setSuggestedColor(int Col) {
|
||||
if (SuggestedColor == -1)
|
||||
SuggestedColor = Col;
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
//===-- LiveRangeInfo.cpp -------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
// Live range construction for coloring-based register allocation for LLVM.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "IGNode.h"
|
||||
@@ -35,8 +35,8 @@ LiveRangeInfo::LiveRangeInfo(const Function *F, const TargetMachine &tm,
|
||||
|
||||
|
||||
LiveRangeInfo::~LiveRangeInfo() {
|
||||
for (LiveRangeMapType::iterator MI = LiveRangeMap.begin();
|
||||
MI != LiveRangeMap.end(); ++MI) {
|
||||
for (LiveRangeMapType::iterator MI = LiveRangeMap.begin();
|
||||
MI != LiveRangeMap.end(); ++MI) {
|
||||
|
||||
if (MI->first && MI->second) {
|
||||
LiveRange *LR = MI->second;
|
||||
@@ -48,7 +48,7 @@ LiveRangeInfo::~LiveRangeInfo() {
|
||||
|
||||
for (LiveRange::iterator LI = LR->begin(); LI != LR->end(); ++LI)
|
||||
LiveRangeMap[*LI] = 0;
|
||||
|
||||
|
||||
delete LR;
|
||||
}
|
||||
}
|
||||
@@ -70,14 +70,14 @@ void LiveRangeInfo::unionAndUpdateLRs(LiveRange *L1, LiveRange *L2) {
|
||||
|
||||
for(LiveRange::iterator L2It = L2->begin(); L2It != L2->end(); ++L2It) {
|
||||
L1->insert(*L2It); // add the var in L2 to L1
|
||||
LiveRangeMap[*L2It] = L1; // now the elements in L2 should map
|
||||
//to L1
|
||||
LiveRangeMap[*L2It] = L1; // now the elements in L2 should map
|
||||
//to L1
|
||||
}
|
||||
|
||||
|
||||
// set call interference for L1 from L2
|
||||
if (L2->isCallInterference())
|
||||
L1->setCallInterference();
|
||||
|
||||
|
||||
// add the spill costs
|
||||
L1->addSpillCost(L2->getSpillCost());
|
||||
|
||||
@@ -90,7 +90,7 @@ void LiveRangeInfo::unionAndUpdateLRs(LiveRange *L1, LiveRange *L2) {
|
||||
// must have the same color.
|
||||
if (L2->hasSuggestedColor())
|
||||
L1->setSuggestedColor(L2->getSuggestedColor());
|
||||
|
||||
|
||||
delete L2; // delete L2 as it is no longer needed
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ void LiveRangeInfo::unionAndUpdateLRs(LiveRange *L1, LiveRange *L2) {
|
||||
|
||||
LiveRange*
|
||||
LiveRangeInfo::createNewLiveRange(const Value* Def, bool isCC /* = false*/)
|
||||
{
|
||||
{
|
||||
LiveRange* DefRange = new LiveRange(); // Create a new live range,
|
||||
DefRange->insert(Def); // add Def to it,
|
||||
LiveRangeMap[Def] = DefRange; // and update the map.
|
||||
@@ -123,11 +123,11 @@ LiveRangeInfo::createNewLiveRange(const Value* Def, bool isCC /* = false*/)
|
||||
|
||||
LiveRange*
|
||||
LiveRangeInfo::createOrAddToLiveRange(const Value* Def, bool isCC /* = false*/)
|
||||
{
|
||||
{
|
||||
LiveRange *DefRange = LiveRangeMap[Def];
|
||||
|
||||
// check if the LR is already there (because of multiple defs)
|
||||
if (!DefRange) {
|
||||
if (!DefRange) {
|
||||
DefRange = createNewLiveRange(Def, isCC);
|
||||
} else { // live range already exists
|
||||
DefRange->insert(Def); // add the operand to the range
|
||||
@@ -140,13 +140,13 @@ LiveRangeInfo::createOrAddToLiveRange(const Value* Def, bool isCC /* = false*/)
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Method for constructing all live ranges in a function. It creates live
|
||||
// Method for constructing all live ranges in a function. It creates live
|
||||
// ranges for all values defined in the instruction stream. Also, it
|
||||
// creates live ranges for all incoming arguments of the function.
|
||||
//---------------------------------------------------------------------------
|
||||
void LiveRangeInfo::constructLiveRanges() {
|
||||
void LiveRangeInfo::constructLiveRanges() {
|
||||
|
||||
if (DEBUG_RA >= RA_DEBUG_LiveRanges)
|
||||
if (DEBUG_RA >= RA_DEBUG_LiveRanges)
|
||||
std::cerr << "Constructing Live Ranges ...\n";
|
||||
|
||||
// first find the live ranges for all incoming args of the function since
|
||||
@@ -154,14 +154,14 @@ void LiveRangeInfo::constructLiveRanges() {
|
||||
for (Function::const_arg_iterator AI = Meth->arg_begin(); AI != Meth->arg_end(); ++AI)
|
||||
createNewLiveRange(AI, /*isCC*/ false);
|
||||
|
||||
// Now suggest hardware registers for these function args
|
||||
// Now suggest hardware registers for these function args
|
||||
MRI.suggestRegs4MethodArgs(Meth, *this);
|
||||
|
||||
// Now create LRs for machine instructions. A new LR will be created
|
||||
// Now create LRs for machine instructions. A new LR will be created
|
||||
// only for defs in the machine instr since, we assume that all Values are
|
||||
// defined before they are used. However, there can be multiple defs for
|
||||
// the same Value in machine instructions.
|
||||
//
|
||||
//
|
||||
// Also, find CALL and RETURN instructions, which need extra work.
|
||||
//
|
||||
MachineFunction &MF = MachineFunction::get(Meth);
|
||||
@@ -170,21 +170,21 @@ void LiveRangeInfo::constructLiveRanges() {
|
||||
|
||||
// iterate over all the machine instructions in BB
|
||||
for(MachineBasicBlock::iterator MInstIterator = MBB.begin();
|
||||
MInstIterator != MBB.end(); ++MInstIterator) {
|
||||
MachineInstr *MInst = MInstIterator;
|
||||
MInstIterator != MBB.end(); ++MInstIterator) {
|
||||
MachineInstr *MInst = MInstIterator;
|
||||
|
||||
// If the machine instruction is a call/return instruction, add it to
|
||||
// CallRetInstrList for processing its args, ret value, and ret addr.
|
||||
//
|
||||
//
|
||||
if(TM.getInstrInfo()->isReturn(MInst->getOpcode()) ||
|
||||
TM.getInstrInfo()->isCall(MInst->getOpcode()))
|
||||
CallRetInstrList.push_back(MInst);
|
||||
|
||||
CallRetInstrList.push_back(MInst);
|
||||
|
||||
// iterate over explicit MI operands and create a new LR
|
||||
// for each operand that is defined by the instruction
|
||||
for (MachineInstr::val_op_iterator OpI = MInst->begin(),
|
||||
OpE = MInst->end(); OpI != OpE; ++OpI)
|
||||
if (OpI.isDef()) {
|
||||
if (OpI.isDef()) {
|
||||
const Value *Def = *OpI;
|
||||
bool isCC = (OpI.getMachineOperand().getType()
|
||||
== MachineOperand::MO_CCRegister);
|
||||
@@ -201,7 +201,7 @@ void LiveRangeInfo::constructLiveRanges() {
|
||||
|
||||
// iterate over implicit MI operands and create a new LR
|
||||
// for each operand that is defined by the instruction
|
||||
for (unsigned i = 0; i < MInst->getNumImplicitRefs(); ++i)
|
||||
for (unsigned i = 0; i < MInst->getNumImplicitRefs(); ++i)
|
||||
if (MInst->getImplicitOp(i).isDef()) {
|
||||
const Value *Def = MInst->getImplicitRef(i);
|
||||
LiveRange* LR = createOrAddToLiveRange(Def, /*isCC*/ false);
|
||||
@@ -222,10 +222,10 @@ void LiveRangeInfo::constructLiveRanges() {
|
||||
// Now we have to suggest clors for call and return arg live ranges.
|
||||
// Also, if there are implicit defs (e.g., retun value of a call inst)
|
||||
// they must be added to the live range list
|
||||
//
|
||||
//
|
||||
suggestRegs4CallRets();
|
||||
|
||||
if( DEBUG_RA >= RA_DEBUG_LiveRanges)
|
||||
if( DEBUG_RA >= RA_DEBUG_LiveRanges)
|
||||
std::cerr << "Initial Live Ranges constructed!\n";
|
||||
}
|
||||
|
||||
@@ -235,7 +235,7 @@ void LiveRangeInfo::constructLiveRanges() {
|
||||
// (e.g., for outgoing call args), suggesting of colors for such live
|
||||
// ranges is done using target specific function. Those functions are called
|
||||
// from this function. The target specific methods must:
|
||||
// 1) suggest colors for call and return args.
|
||||
// 1) suggest colors for call and return args.
|
||||
// 2) create new LRs for implicit defs in machine instructions
|
||||
//---------------------------------------------------------------------------
|
||||
void LiveRangeInfo::suggestRegs4CallRets() {
|
||||
@@ -248,7 +248,7 @@ void LiveRangeInfo::suggestRegs4CallRets() {
|
||||
MRI.suggestReg4RetValue(MInst, *this);
|
||||
else if (TM.getInstrInfo()->isCall(OpCode))
|
||||
MRI.suggestRegs4CallArgs(MInst, *this);
|
||||
else
|
||||
else
|
||||
assert( 0 && "Non call/ret instr in CallRetInstrList" );
|
||||
}
|
||||
}
|
||||
@@ -268,7 +268,7 @@ void LiveRangeInfo::suggestRegs4CallRets() {
|
||||
if the def and op do not interfere //i.e., not simultaneously live
|
||||
if (degree(LR of def) + degree(LR of op)) <= # avail regs
|
||||
if both LRs do not have suggested colors
|
||||
merge2IGNodes(def, op) // i.e., merge 2 LRs
|
||||
merge2IGNodes(def, op) // i.e., merge 2 LRs
|
||||
|
||||
*/
|
||||
//---------------------------------------------------------------------------
|
||||
@@ -276,7 +276,7 @@ void LiveRangeInfo::suggestRegs4CallRets() {
|
||||
|
||||
// Checks if live range LR interferes with any node assigned or suggested to
|
||||
// be assigned the specified color
|
||||
//
|
||||
//
|
||||
inline bool InterferesWithColor(const LiveRange& LR, unsigned color) {
|
||||
IGNode* lrNode = LR.getUserIGNode();
|
||||
for (unsigned n=0, NN = lrNode->getNumOfNeighbors(); n < NN; n++) {
|
||||
@@ -295,7 +295,7 @@ inline bool InterferesWithColor(const LiveRange& LR, unsigned color) {
|
||||
// (but if the colors are the same, it is definitely safe to coalesce)
|
||||
// (3) LR1 has color and LR2 interferes with any LR that has the same color
|
||||
// (4) LR2 has color and LR1 interferes with any LR that has the same color
|
||||
//
|
||||
//
|
||||
inline bool InterfsPreventCoalescing(const LiveRange& LROfDef,
|
||||
const LiveRange& LROfUse) {
|
||||
// (4) if they have different suggested colors, cannot coalesce
|
||||
@@ -318,9 +318,9 @@ inline bool InterfsPreventCoalescing(const LiveRange& LROfDef,
|
||||
}
|
||||
|
||||
|
||||
void LiveRangeInfo::coalesceLRs()
|
||||
void LiveRangeInfo::coalesceLRs()
|
||||
{
|
||||
if(DEBUG_RA >= RA_DEBUG_LiveRanges)
|
||||
if(DEBUG_RA >= RA_DEBUG_LiveRanges)
|
||||
std::cerr << "\nCoalescing LRs ...\n";
|
||||
|
||||
MachineFunction &MF = MachineFunction::get(Meth);
|
||||
@@ -364,7 +364,7 @@ void LiveRangeInfo::coalesceLRs()
|
||||
if (!RCOfDef->getInterference(LROfDef, LROfUse) ) {
|
||||
|
||||
unsigned CombinedDegree =
|
||||
LROfDef->getUserIGNode()->getNumOfNeighbors() +
|
||||
LROfDef->getUserIGNode()->getNumOfNeighbors() +
|
||||
LROfUse->getUserIGNode()->getNumOfNeighbors();
|
||||
|
||||
if (CombinedDegree > RCOfDef->getNumOfAvailRegs()) {
|
||||
@@ -390,7 +390,7 @@ void LiveRangeInfo::coalesceLRs()
|
||||
} // for all machine instructions
|
||||
} // for all BBs
|
||||
|
||||
if (DEBUG_RA >= RA_DEBUG_LiveRanges)
|
||||
if (DEBUG_RA >= RA_DEBUG_LiveRanges)
|
||||
std::cerr << "\nCoalescing Done!\n";
|
||||
}
|
||||
|
||||
@@ -402,7 +402,7 @@ void LiveRangeInfo::printLiveRanges() {
|
||||
std::cerr << "\nPrinting Live Ranges from Hash Map:\n";
|
||||
for( ; HMI != LiveRangeMap.end(); ++HMI) {
|
||||
if (HMI->first && HMI->second) {
|
||||
std::cerr << " Value* " << RAV(HMI->first) << "\t: ";
|
||||
std::cerr << " Value* " << RAV(HMI->first) << "\t: ";
|
||||
if (IGNode* igNode = HMI->second->getUserIGNode())
|
||||
std::cerr << "LR# " << igNode->getIndex();
|
||||
else
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
//===-- LiveRangeInfo.h - Track all LiveRanges for a Function ----*- C++ -*-==//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the class LiveRangeInfo which constructs and keeps
|
||||
// This file contains the class LiveRangeInfo which constructs and keeps
|
||||
// the LiveRangeMap which contains all the live ranges used in a method.
|
||||
//
|
||||
// Assumptions:
|
||||
// Assumptions:
|
||||
//
|
||||
// All variables (llvm Values) are defined before they are used. However, a
|
||||
// All variables (llvm Values) are defined before they are used. However, a
|
||||
// constant may not be defined in the machine instruction stream if it can be
|
||||
// used as an immediate value within a machine instruction. However, register
|
||||
// allocation does not have to worry about immediate constants since they
|
||||
@@ -45,16 +45,16 @@ typedef hash_map<const Value*, LiveRange*> LiveRangeMapType;
|
||||
//----------------------------------------------------------------------------
|
||||
// Class LiveRangeInfo
|
||||
//
|
||||
// Constructs and keeps the LiveRangeMap which contains all the live
|
||||
// Constructs and keeps the LiveRangeMap which contains all the live
|
||||
// ranges used in a method. Also contain methods to coalesce live ranges.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class LiveRangeInfo {
|
||||
const Function *const Meth; // Func for which live range info is held
|
||||
LiveRangeMapType LiveRangeMap; // A map from Value * to LiveRange * to
|
||||
LiveRangeMapType LiveRangeMap; // A map from Value * to LiveRange * to
|
||||
// record all live ranges in a method
|
||||
// created by constructLiveRanges
|
||||
|
||||
|
||||
const TargetMachine& TM; // target machine description
|
||||
|
||||
std::vector<RegClass *> & RegClassList;// vector containing register classess
|
||||
@@ -76,8 +76,8 @@ class LiveRangeInfo {
|
||||
|
||||
void suggestRegs4CallRets ();
|
||||
public:
|
||||
|
||||
LiveRangeInfo(const Function *F,
|
||||
|
||||
LiveRangeInfo(const Function *F,
|
||||
const TargetMachine& tm,
|
||||
std::vector<RegClass *> & RCList);
|
||||
|
||||
@@ -89,10 +89,10 @@ public:
|
||||
// Main entry point for live range construction
|
||||
//
|
||||
void constructLiveRanges();
|
||||
|
||||
|
||||
/// return the common live range map for this method
|
||||
///
|
||||
inline const LiveRangeMapType *getLiveRangeMap() const
|
||||
inline const LiveRangeMapType *getLiveRangeMap() const
|
||||
{ return &LiveRangeMap; }
|
||||
|
||||
/// Method used to get the live range containing a Value.
|
||||
@@ -109,7 +109,7 @@ public:
|
||||
/// Method for coalescing live ranges. Called only after interference info
|
||||
/// is calculated.
|
||||
///
|
||||
void coalesceLRs();
|
||||
void coalesceLRs();
|
||||
|
||||
/// debugging method to print the live ranges
|
||||
///
|
||||
@@ -118,4 +118,4 @@ public:
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user