#include "SparcTargetMachine.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
+#include "llvm/Intrinsics.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
SparcTargetLowering(TargetMachine &TM);
virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG);
- /// isMaskedValueZeroForTargetNode - Return true if 'Op & Mask' is known to
- /// be zero. Op is expected to be a target specific node. Used by DAG
- /// combiner.
- virtual bool isMaskedValueZeroForTargetNode(const SDOperand &Op,
- uint64_t Mask) const;
+ /// computeMaskedBitsForTargetNode - Determine which of the bits specified
+ /// in Mask are known to be either zero or one and return them in the
+ /// KnownZero/KnownOne bitsets.
+ virtual void computeMaskedBitsForTargetNode(const SDOperand Op,
+ uint64_t Mask,
+ uint64_t &KnownZero,
+ uint64_t &KnownOne,
+ unsigned Depth = 0) const;
virtual std::vector<SDOperand>
LowerArguments(Function &F, SelectionDAG &DAG);
unsigned CC,
bool isTailCall, SDOperand Callee, ArgListTy &Args,
SelectionDAG &DAG);
- virtual std::pair<SDOperand, SDOperand>
- LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
- SelectionDAG &DAG);
virtual MachineBasicBlock *InsertAtEndOfBasicBlock(MachineInstr *MI,
MachineBasicBlock *MBB);
// Sparc doesn't have BRCOND either, it has BR_CC.
setOperationAction(ISD::BRCOND, MVT::Other, Expand);
- setOperationAction(ISD::BRCONDTWOWAY, MVT::Other, Expand);
- setOperationAction(ISD::BRTWOWAY_CC, MVT::Other, Expand);
+ setOperationAction(ISD::BRIND, MVT::i32, Expand);
setOperationAction(ISD::BR_CC, MVT::i32, Custom);
setOperationAction(ISD::BR_CC, MVT::f32, Custom);
setOperationAction(ISD::BR_CC, MVT::f64, Custom);
setOperationAction(ISD::ROTL , MVT::i32, Expand);
setOperationAction(ISD::ROTR , MVT::i32, Expand);
setOperationAction(ISD::BSWAP, MVT::i32, Expand);
+ setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
+ setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);
setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand);
setOperationAction(ISD::VAEND , MVT::Other, Expand);
setOperationAction(ISD::STACKSAVE , MVT::Other, Expand);
setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand);
- setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Expand);
+ setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Custom);
setOperationAction(ISD::ConstantFP, MVT::f64, Expand);
setOperationAction(ISD::ConstantFP, MVT::f32, Expand);
/// isMaskedValueZeroForTargetNode - Return true if 'Op & Mask' is known to
/// be zero. Op is expected to be a target specific node. Used by DAG
/// combiner.
-bool SparcTargetLowering::
-isMaskedValueZeroForTargetNode(const SDOperand &Op, uint64_t Mask) const {
+void SparcTargetLowering::computeMaskedBitsForTargetNode(const SDOperand Op,
+ uint64_t Mask,
+ uint64_t &KnownZero,
+ uint64_t &KnownOne,
+ unsigned Depth) const {
+ uint64_t KnownZero2, KnownOne2;
+ KnownZero = KnownOne = 0; // Don't know anything.
+
switch (Op.getOpcode()) {
- default: return false;
+ default: break;
case SPISD::SELECT_ICC:
case SPISD::SELECT_FCC:
- assert(MVT::isInteger(Op.getValueType()) && "Not an integer select!");
- // These operations are masked zero if both the left and the right are zero.
- return MaskedValueIsZero(Op.getOperand(0), Mask) &&
- MaskedValueIsZero(Op.getOperand(1), Mask);
+ ComputeMaskedBits(Op.getOperand(1), Mask, KnownZero, KnownOne, Depth+1);
+ ComputeMaskedBits(Op.getOperand(0), Mask, KnownZero2, KnownOne2, Depth+1);
+ assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
+ assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?");
+
+ // Only known if known in both the LHS and RHS.
+ KnownOne &= KnownOne2;
+ KnownZero &= KnownZero2;
+ break;
}
}
-
/// LowerArguments - V8 uses a very simple ABI, where all values are passed in
/// either one or two GPRs, including FP values. TODO: we should pass FP values
/// in FP registers for fastcc functions.
// Keep stack frames 8-byte aligned.
ArgsSize = (ArgsSize+7) & ~7;
- Chain = DAG.getNode(ISD::CALLSEQ_START, MVT::Other, Chain,
- DAG.getConstant(ArgsSize, getPointerTy()));
+ Chain = DAG.getCALLSEQ_START(Chain,DAG.getConstant(ArgsSize, getPointerTy()));
SDOperand StackPtr, NullSV;
std::vector<SDOperand> Stores;
// If the callee is a GlobalAddress node (quite common, every direct call is)
// turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
+ // Likewise ExternalSymbol -> TargetExternalSymbol.
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
Callee = DAG.getTargetGlobalAddress(G->getGlobal(), MVT::i32);
+ else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))
+ Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32);
std::vector<MVT::ValueType> NodeTys;
NodeTys.push_back(MVT::Other); // Returns a chain
return std::make_pair(RetVal, Chain);
}
-std::pair<SDOperand, SDOperand> SparcTargetLowering::
-LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
- SelectionDAG &DAG) {
- assert(0 && "Unimp");
- abort();
-}
-
// Look at LHS/RHS/CC and see if they are a lowered setcc instruction. If so
// set LHS/RHS and SPCC to the LHS/RHS of the setcc and SPCC to the condition.
static void LookThroughSetCC(SDOperand &LHS, SDOperand &RHS,
return DAG.getNode(ISD::MERGE_VALUES, Tys, Ops);
}
}
+ case ISD::DYNAMIC_STACKALLOC: {
+ SDOperand Chain = Op.getOperand(0); // Legalize the chain.
+ SDOperand Size = Op.getOperand(1); // Legalize the size.
+
+ unsigned SPReg = SP::O6;
+ SDOperand SP = DAG.getCopyFromReg(Chain, SPReg, MVT::i32);
+ SDOperand NewSP = DAG.getNode(ISD::SUB, MVT::i32, SP, Size); // Value
+ Chain = DAG.getCopyToReg(SP.getValue(1), SPReg, NewSP); // Output chain
+
+ // The resultant pointer is actually 16 words from the bottom of the stack,
+ // to provide a register spill area.
+ SDOperand NewVal = DAG.getNode(ISD::ADD, MVT::i32, NewSP,
+ DAG.getConstant(96, MVT::i32));
+ std::vector<MVT::ValueType> Tys;
+ Tys.push_back(MVT::i32);
+ Tys.push_back(MVT::Other);
+ std::vector<SDOperand> Ops;
+ Ops.push_back(NewVal);
+ Ops.push_back(Chain);
+ return DAG.getNode(ISD::MERGE_VALUES, Tys, Ops);
+ }
case ISD::RET: {
SDOperand Copy;
MachineFunction *F = BB->getParent();
F->getBasicBlockList().insert(It, copy0MBB);
F->getBasicBlockList().insert(It, sinkMBB);
- // Update machine-CFG edges
+ // Update machine-CFG edges by first adding all successors of the current
+ // block to the new block which will contain the Phi node for the select.
+ for(MachineBasicBlock::succ_iterator i = BB->succ_begin(),
+ e = BB->succ_end(); i != e; ++i)
+ sinkMBB->addSuccessor(*i);
+ // Next, remove all successors of the current block, and add the true
+ // and fallthrough blocks as its successors.
+ while(!BB->succ_empty())
+ BB->removeSuccessor(BB->succ_begin());
BB->addSuccessor(copy0MBB);
BB->addSuccessor(sinkMBB);
Subtarget(TM.getSubtarget<SparcSubtarget>()) {
}
- SDOperand Select(SDOperand Op);
+ void Select(SDOperand &Result, SDOperand Op);
// Complex Pattern Selectors.
bool SelectADDRrr(SDOperand N, SDOperand &R1, SDOperand &R2);
}
bool SparcDAGToDAGISel::SelectADDRri(SDOperand Addr, SDOperand &Base,
- SDOperand &Offset) {
+ SDOperand &Offset) {
if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
Offset = CurDAG->getTargetConstant(0, MVT::i32);
return true;
}
+ if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
+ Addr.getOpcode() == ISD::TargetGlobalAddress)
+ return false; // direct calls.
if (Addr.getOpcode() == ISD::ADD) {
if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) {
bool SparcDAGToDAGISel::SelectADDRrr(SDOperand Addr, SDOperand &R1,
SDOperand &R2) {
- if (Addr.getOpcode() == ISD::FrameIndex) return false;
+ if (Addr.getOpcode() == ISD::FrameIndex) return false;
+ if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
+ Addr.getOpcode() == ISD::TargetGlobalAddress)
+ return false; // direct calls.
+
if (Addr.getOpcode() == ISD::ADD) {
if (isa<ConstantSDNode>(Addr.getOperand(1)) &&
Predicate_simm13(Addr.getOperand(1).Val))
return true;
}
-SDOperand SparcDAGToDAGISel::Select(SDOperand Op) {
+void SparcDAGToDAGISel::Select(SDOperand &Result, SDOperand Op) {
SDNode *N = Op.Val;
if (N->getOpcode() >= ISD::BUILTIN_OP_END &&
- N->getOpcode() < SPISD::FIRST_NUMBER)
- return Op; // Already selected.
+ N->getOpcode() < SPISD::FIRST_NUMBER) {
+ Result = Op;
+ return; // Already selected.
+ }
+
// If this has already been converted, use it.
std::map<SDOperand, SDOperand>::iterator CGMI = CodeGenMap.find(Op);
- if (CGMI != CodeGenMap.end()) return CGMI->second;
+ if (CGMI != CodeGenMap.end()) {
+ Result = CGMI->second;
+ return;
+ }
switch (N->getOpcode()) {
default: break;
- case ISD::FrameIndex: {
- int FI = cast<FrameIndexSDNode>(N)->getIndex();
- if (N->hasOneUse())
- return CurDAG->SelectNodeTo(N, SP::ADDri, MVT::i32,
- CurDAG->getTargetFrameIndex(FI, MVT::i32),
- CurDAG->getTargetConstant(0, MVT::i32));
- return CodeGenMap[Op] =
- CurDAG->getTargetNode(SP::ADDri, MVT::i32,
- CurDAG->getTargetFrameIndex(FI, MVT::i32),
- CurDAG->getTargetConstant(0, MVT::i32));
- }
- case ISD::ADD_PARTS: {
- SDOperand LHSL = Select(N->getOperand(0));
- SDOperand LHSH = Select(N->getOperand(1));
- SDOperand RHSL = Select(N->getOperand(2));
- SDOperand RHSH = Select(N->getOperand(3));
- // FIXME, handle immediate RHS.
- SDOperand Low = CurDAG->getTargetNode(SP::ADDCCrr, MVT::i32, MVT::Flag,
- LHSL, RHSL);
- SDOperand Hi = CurDAG->getTargetNode(SP::ADDXrr, MVT::i32, LHSH, RHSH,
- Low.getValue(1));
- CodeGenMap[SDOperand(N, 0)] = Low;
- CodeGenMap[SDOperand(N, 1)] = Hi;
- return Op.ResNo ? Hi : Low;
- }
- case ISD::SUB_PARTS: {
- SDOperand LHSL = Select(N->getOperand(0));
- SDOperand LHSH = Select(N->getOperand(1));
- SDOperand RHSL = Select(N->getOperand(2));
- SDOperand RHSH = Select(N->getOperand(3));
- // FIXME, handle immediate RHS.
- SDOperand Low = CurDAG->getTargetNode(SP::SUBCCrr, MVT::i32, MVT::Flag,
- LHSL, RHSL);
- SDOperand Hi = CurDAG->getTargetNode(SP::SUBXrr, MVT::i32, LHSH, RHSH,
- Low.getValue(1));
- CodeGenMap[SDOperand(N, 0)] = Low;
- CodeGenMap[SDOperand(N, 1)] = Hi;
- return Op.ResNo ? Hi : Low;
- }
case ISD::SDIV:
case ISD::UDIV: {
// FIXME: should use a custom expander to expose the SRA to the dag.
- SDOperand DivLHS = Select(N->getOperand(0));
- SDOperand DivRHS = Select(N->getOperand(1));
+ SDOperand DivLHS, DivRHS;
+ Select(DivLHS, N->getOperand(0));
+ Select(DivRHS, N->getOperand(1));
// Set the Y register to the high-part.
SDOperand TopPart;
if (N->getOpcode() == ISD::SDIV) {
- TopPart = CurDAG->getTargetNode(SP::SRAri, MVT::i32, DivLHS,
- CurDAG->getTargetConstant(31, MVT::i32));
+ TopPart = SDOperand(CurDAG->getTargetNode(SP::SRAri, MVT::i32, DivLHS,
+ CurDAG->getTargetConstant(31, MVT::i32)), 0);
} else {
TopPart = CurDAG->getRegister(SP::G0, MVT::i32);
}
- TopPart = CurDAG->getTargetNode(SP::WRYrr, MVT::Flag, TopPart,
- CurDAG->getRegister(SP::G0, MVT::i32));
+ TopPart = SDOperand(CurDAG->getTargetNode(SP::WRYrr, MVT::Flag, TopPart,
+ CurDAG->getRegister(SP::G0, MVT::i32)), 0);
// FIXME: Handle div by immediate.
unsigned Opcode = N->getOpcode() == ISD::SDIV ? SP::SDIVrr : SP::UDIVrr;
- return CurDAG->SelectNodeTo(N, Opcode, MVT::i32, DivLHS, DivRHS, TopPart);
+ Result = CurDAG->SelectNodeTo(N, Opcode, MVT::i32, DivLHS, DivRHS, TopPart);
+ return;
}
case ISD::MULHU:
case ISD::MULHS: {
// FIXME: Handle mul by immediate.
- SDOperand MulLHS = Select(N->getOperand(0));
- SDOperand MulRHS = Select(N->getOperand(1));
+ SDOperand MulLHS, MulRHS;
+ Select(MulLHS, N->getOperand(0));
+ Select(MulRHS, N->getOperand(1));
unsigned Opcode = N->getOpcode() == ISD::MULHU ? SP::UMULrr : SP::SMULrr;
- SDOperand Mul = CurDAG->getTargetNode(Opcode, MVT::i32, MVT::Flag,
- MulLHS, MulRHS);
+ SDNode *Mul = CurDAG->getTargetNode(Opcode, MVT::i32, MVT::Flag,
+ MulLHS, MulRHS);
// The high part is in the Y register.
- return CurDAG->SelectNodeTo(N, SP::RDY, MVT::i32, Mul.getValue(1));
- }
- case SPISD::CALL:
- // FIXME: This is a workaround for a bug in tblgen.
- { // Pattern #47: (call:Flag (tglobaladdr:i32):$dst, ICC:Flag)
- // Emits: (CALL:void (tglobaladdr:i32):$dst)
- // Pattern complexity = 2 cost = 1
- SDOperand N1 = N->getOperand(1);
- if (N1.getOpcode() != ISD::TargetGlobalAddress &&
- N1.getOpcode() != ISD::ExternalSymbol) goto P47Fail;
- SDOperand InFlag = SDOperand(0, 0);
- SDOperand Chain = N->getOperand(0);
- SDOperand Tmp0 = N1;
- Chain = Select(Chain);
- SDOperand Result;
- if (N->getNumOperands() == 3) {
- InFlag = Select(N->getOperand(2));
- Result = CurDAG->getTargetNode(SP::CALL, MVT::Other, MVT::Flag, Tmp0,
- Chain, InFlag);
- } else {
- Result = CurDAG->getTargetNode(SP::CALL, MVT::Other, MVT::Flag, Tmp0,
- Chain);
- }
- Chain = CodeGenMap[SDOperand(N, 0)] = Result.getValue(0);
- CodeGenMap[SDOperand(N, 1)] = Result.getValue(1);
- return Result.getValue(Op.ResNo);
+ Result = CurDAG->SelectNodeTo(N, SP::RDY, MVT::i32, SDOperand(Mul, 1));
+ return;
}
- P47Fail:;
-
}
- return SelectCode(Op);
+ SelectCode(Result, Op);
}