#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);
// 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;
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);
switch (N->getOpcode()) {
default: break;
- case ISD::ADD_PARTS: {
- SDOperand LHSL, LHSH, RHSL, RHSH;
- Select(LHSL, N->getOperand(0));
- Select(LHSH, N->getOperand(1));
- Select(RHSL, N->getOperand(2));
- Select(RHSH, N->getOperand(3));
- // FIXME, handle immediate RHS.
- SDOperand Low =
- SDOperand(CurDAG->getTargetNode(SP::ADDCCrr, MVT::i32, MVT::Flag,
- LHSL, RHSL), 0);
- SDOperand Hi =
- SDOperand(CurDAG->getTargetNode(SP::ADDXrr, MVT::i32, LHSH, RHSH,
- Low.getValue(1)), 0);
- CodeGenMap[SDOperand(N, 0)] = Low;
- CodeGenMap[SDOperand(N, 1)] = Hi;
- Result = Op.ResNo ? Hi : Low;
- return;
- }
- case ISD::SUB_PARTS: {
- SDOperand LHSL, LHSH, RHSL, RHSH;
- Select(LHSL, N->getOperand(0));
- Select(LHSH, N->getOperand(1));
- Select(RHSL, N->getOperand(2));
- Select(RHSH, N->getOperand(3));
- SDOperand Low =
- SDOperand(CurDAG->getTargetNode(SP::SUBCCrr, MVT::i32, MVT::Flag,
- LHSL, RHSL), 0);
- SDOperand Hi =
- SDOperand(CurDAG->getTargetNode(SP::SUBXrr, MVT::i32, LHSH, RHSH,
- Low.getValue(1)), 0);
- CodeGenMap[SDOperand(N, 0)] = Low;
- CodeGenMap[SDOperand(N, 1)] = Hi;
- Result = Op.ResNo ? Hi : Low;
- return;
- }
case ISD::SDIV:
case ISD::UDIV: {
// FIXME: should use a custom expander to expose the SRA to the dag.