//
// The LLVM Compiler Infrastructure
//
-// This file was developed by Chris Lattner and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
-#include "llvm/CodeGen/SSARegMap.h"
#include "llvm/Target/TargetLowering.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
-#include <iostream>
#include <queue>
#include <set>
using namespace llvm;
/// 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,
+ const APInt &Mask,
+ APInt &KnownZero,
+ APInt &KnownOne,
+ const SelectionDAG &DAG,
unsigned Depth = 0) const;
virtual std::vector<SDOperand>
LowerArguments(Function &F, SelectionDAG &DAG);
virtual std::pair<SDOperand, SDOperand>
- LowerCallTo(SDOperand Chain, const Type *RetTy, bool isVarArg,
- unsigned CC,
- bool isTailCall, SDOperand Callee, ArgListTy &Args,
- SelectionDAG &DAG);
- virtual MachineBasicBlock *InsertAtEndOfBasicBlock(MachineInstr *MI,
- MachineBasicBlock *MBB);
+ LowerCallTo(SDOperand Chain, const Type *RetTy,
+ bool RetSExt, bool RetZExt, bool isVarArg,
+ unsigned CC, bool isTailCall, SDOperand Callee,
+ ArgListTy &Args, SelectionDAG &DAG);
+ virtual MachineBasicBlock *EmitInstrWithCustomInserter(MachineInstr *MI,
+ MachineBasicBlock *MBB);
virtual const char *getTargetNodeName(unsigned Opcode) const;
};
// Turn FP extload into load/fextend
setLoadXAction(ISD::EXTLOAD, MVT::f32, Expand);
-
+ // Sparc doesn't have i1 sign extending load
+ setLoadXAction(ISD::SEXTLOAD, MVT::i1, Promote);
+ // Turn FP truncstore into trunc + store.
+ setTruncStoreAction(MVT::f64, MVT::f32, Expand);
+
// Custom legalize GlobalAddress nodes into LO/HI parts.
setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
+ setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom);
setOperationAction(ISD::ConstantPool , MVT::i32, Custom);
// Sparc doesn't have sext_inreg, replace them with shl/sra
setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8 , Expand);
setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1 , Expand);
- // Sparc has no REM operation.
+ // Sparc has no REM or DIVREM operations.
setOperationAction(ISD::UREM, MVT::i32, Expand);
setOperationAction(ISD::SREM, MVT::i32, Expand);
+ setOperationAction(ISD::SDIVREM, MVT::i32, Expand);
+ setOperationAction(ISD::UDIVREM, MVT::i32, Expand);
// Custom expand fp<->sint
setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);
setOperationAction(ISD::MEMMOVE, MVT::Other, Expand);
setOperationAction(ISD::MEMSET, MVT::Other, Expand);
setOperationAction(ISD::MEMCPY, MVT::Other, Expand);
-
+ setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
+
setOperationAction(ISD::FSIN , MVT::f64, Expand);
setOperationAction(ISD::FCOS , MVT::f64, Expand);
+ setOperationAction(ISD::FREM , MVT::f64, Expand);
setOperationAction(ISD::FSIN , MVT::f32, Expand);
setOperationAction(ISD::FCOS , MVT::f32, Expand);
+ setOperationAction(ISD::FREM , MVT::f32, Expand);
setOperationAction(ISD::CTPOP, MVT::i32, Expand);
setOperationAction(ISD::CTTZ , MVT::i32, Expand);
setOperationAction(ISD::CTLZ , MVT::i32, Expand);
setOperationAction(ISD::BSWAP, MVT::i32, Expand);
setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
+ setOperationAction(ISD::FPOW , MVT::f64, Expand);
+ setOperationAction(ISD::FPOW , MVT::f32, Expand);
setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);
setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand);
setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand);
+ // FIXME: Sparc provides these multiplies, but we don't have them yet.
+ setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand);
+
// We don't have line number support yet.
setOperationAction(ISD::LOCATION, MVT::Other, Expand);
setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
- setOperationAction(ISD::DEBUG_LABEL, MVT::Other, Expand);
+ setOperationAction(ISD::LABEL, MVT::Other, Expand);
// RET must be custom lowered, to meet ABI requirements
setOperationAction(ISD::RET , MVT::Other, Custom);
-
+
// VASTART needs to be custom lowered to use the VarArgsFrameIndex.
setOperationAction(ISD::VASTART , MVT::Other, Custom);
// VAARG needs to be lowered to not do unaligned accesses for doubles.
setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand);
setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Custom);
- setOperationAction(ISD::ConstantFP, MVT::f64, Expand);
- setOperationAction(ISD::ConstantFP, MVT::f32, Expand);
-
+ // No debug info support yet.
+ setOperationAction(ISD::LOCATION, MVT::Other, Expand);
+ setOperationAction(ISD::LABEL, MVT::Other, Expand);
+ setOperationAction(ISD::DECLARE, MVT::Other, Expand);
+
setStackPointerRegisterToSaveRestore(SP::O6);
- if (TM.getSubtarget<SparcSubtarget>().isV9()) {
+ if (TM.getSubtarget<SparcSubtarget>().isV9())
setOperationAction(ISD::CTPOP, MVT::i32, Legal);
- }
computeRegisterProperties();
}
/// be zero. Op is expected to be a target specific node. Used by DAG
/// combiner.
void SparcTargetLowering::computeMaskedBitsForTargetNode(const SDOperand Op,
- uint64_t Mask,
- uint64_t &KnownZero,
- uint64_t &KnownOne,
+ const APInt &Mask,
+ APInt &KnownZero,
+ APInt &KnownOne,
+ const SelectionDAG &DAG,
unsigned Depth) const {
- uint64_t KnownZero2, KnownOne2;
- KnownZero = KnownOne = 0; // Don't know anything.
+ APInt KnownZero2, KnownOne2;
+ KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0); // Don't know anything.
switch (Op.getOpcode()) {
default: break;
case SPISD::SELECT_ICC:
case SPISD::SELECT_FCC:
- ComputeMaskedBits(Op.getOperand(1), Mask, KnownZero, KnownOne, Depth+1);
- ComputeMaskedBits(Op.getOperand(0), Mask, KnownZero2, KnownOne2, Depth+1);
+ DAG.ComputeMaskedBits(Op.getOperand(1), Mask, KnownZero, KnownOne,
+ Depth+1);
+ DAG.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?");
std::vector<SDOperand>
SparcTargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
MachineFunction &MF = DAG.getMachineFunction();
- SSARegMap *RegMap = MF.getSSARegMap();
+ MachineRegisterInfo &RegInfo = MF.getRegInfo();
std::vector<SDOperand> ArgValues;
static const unsigned ArgRegs[] = {
if (CurArgReg < ArgRegEnd) ++CurArgReg;
ArgValues.push_back(DAG.getNode(ISD::UNDEF, ObjectVT));
} else if (CurArgReg < ArgRegEnd) { // Lives in an incoming GPR
- unsigned VReg = RegMap->createVirtualRegister(&SP::IntRegsRegClass);
- MF.addLiveIn(*CurArgReg++, VReg);
+ unsigned VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
+ MF.getRegInfo().addLiveIn(*CurArgReg++, VReg);
SDOperand Arg = DAG.getCopyFromReg(Root, VReg, MVT::i32);
if (ObjectVT != MVT::i32) {
- unsigned AssertOp = I->getType()->isSigned() ? ISD::AssertSext
- : ISD::AssertZext;
+ unsigned AssertOp = ISD::AssertSext;
Arg = DAG.getNode(AssertOp, MVT::i32, Arg,
DAG.getValueType(ObjectVT));
Arg = DAG.getNode(ISD::TRUNCATE, ObjectVT, Arg);
if (ObjectVT == MVT::i32) {
Load = DAG.getLoad(MVT::i32, Root, FIPtr, NULL, 0);
} else {
- ISD::LoadExtType LoadOp =
- I->getType()->isSigned() ? ISD::SEXTLOAD : ISD::ZEXTLOAD;
+ ISD::LoadExtType LoadOp = ISD::SEXTLOAD;
// Sparc is big endian, so add an offset based on the ObjectVT.
unsigned Offset = 4-std::max(1U, MVT::getSizeInBits(ObjectVT)/8);
ArgValues.push_back(DAG.getNode(ISD::UNDEF, ObjectVT));
} else if (CurArgReg < ArgRegEnd) { // Lives in an incoming GPR
// FP value is passed in an integer register.
- unsigned VReg = RegMap->createVirtualRegister(&SP::IntRegsRegClass);
- MF.addLiveIn(*CurArgReg++, VReg);
+ unsigned VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
+ MF.getRegInfo().addLiveIn(*CurArgReg++, VReg);
SDOperand Arg = DAG.getCopyFromReg(Root, VReg, MVT::i32);
Arg = DAG.getNode(ISD::BIT_CONVERT, MVT::f32, Arg);
} else {
SDOperand HiVal;
if (CurArgReg < ArgRegEnd) { // Lives in an incoming GPR
- unsigned VRegHi = RegMap->createVirtualRegister(&SP::IntRegsRegClass);
- MF.addLiveIn(*CurArgReg++, VRegHi);
+ unsigned VRegHi = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
+ MF.getRegInfo().addLiveIn(*CurArgReg++, VRegHi);
HiVal = DAG.getCopyFromReg(Root, VRegHi, MVT::i32);
} else {
int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset);
SDOperand LoVal;
if (CurArgReg < ArgRegEnd) { // Lives in an incoming GPR
- unsigned VRegLo = RegMap->createVirtualRegister(&SP::IntRegsRegClass);
- MF.addLiveIn(*CurArgReg++, VRegLo);
+ unsigned VRegLo = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
+ MF.getRegInfo().addLiveIn(*CurArgReg++, VRegLo);
LoVal = DAG.getCopyFromReg(Root, VRegLo, MVT::i32);
} else {
int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset+4);
VarArgsFrameOffset = ArgOffset;
for (; CurArgReg != ArgRegEnd; ++CurArgReg) {
- unsigned VReg = RegMap->createVirtualRegister(&SP::IntRegsRegClass);
- MF.addLiveIn(*CurArgReg, VReg);
+ unsigned VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
+ MF.getRegInfo().addLiveIn(*CurArgReg, VReg);
SDOperand Arg = DAG.getCopyFromReg(DAG.getRoot(), VReg, MVT::i32);
int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset);
case MVT::i8:
case MVT::i16:
case MVT::i32:
- MF.addLiveOut(SP::I0);
+ MF.getRegInfo().addLiveOut(SP::I0);
break;
case MVT::i64:
- MF.addLiveOut(SP::I0);
- MF.addLiveOut(SP::I1);
+ MF.getRegInfo().addLiveOut(SP::I0);
+ MF.getRegInfo().addLiveOut(SP::I1);
break;
case MVT::f32:
- MF.addLiveOut(SP::F0);
+ MF.getRegInfo().addLiveOut(SP::F0);
break;
case MVT::f64:
- MF.addLiveOut(SP::D0);
+ MF.getRegInfo().addLiveOut(SP::D0);
break;
}
std::pair<SDOperand, SDOperand>
SparcTargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy,
- bool isVarArg, unsigned CC,
- bool isTailCall, SDOperand Callee,
+ bool RetSExt, bool RetZExt, bool isVarArg,
+ unsigned CC, bool isTailCall, SDOperand Callee,
ArgListTy &Args, SelectionDAG &DAG) {
// Count the size of the outgoing arguments.
unsigned ArgsSize = 0;
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
- switch (getValueType(Args[i].second)) {
+ switch (getValueType(Args[i].Ty)) {
default: assert(0 && "Unknown value type!");
case MVT::i1:
case MVT::i8:
std::vector<SDOperand> RegValuesToPass;
unsigned ArgOffset = 68;
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
- SDOperand Val = Args[i].first;
+ SDOperand Val = Args[i].Node;
MVT::ValueType ObjectVT = Val.getValueType();
SDOperand ValToStore(0, 0);
unsigned ObjSize;
default: assert(0 && "Unhandled argument type!");
case MVT::i1:
case MVT::i8:
- case MVT::i16:
+ case MVT::i16: {
// Promote the integer to 32-bits. If the input type is signed, use a
// sign extend, otherwise use a zero extend.
- if (Args[i].second->isSigned())
- Val = DAG.getNode(ISD::SIGN_EXTEND, MVT::i32, Val);
- else
- Val = DAG.getNode(ISD::ZERO_EXTEND, MVT::i32, Val);
+ ISD::NodeType ExtendKind = ISD::ANY_EXTEND;
+ if (Args[i].isSExt)
+ ExtendKind = ISD::SIGN_EXTEND;
+ else if (Args[i].isZExt)
+ ExtendKind = ISD::ZERO_EXTEND;
+ Val = DAG.getNode(ExtendKind, MVT::i32, Val);
// FALL THROUGH
+ }
case MVT::i32:
ObjSize = 4;
default: assert(0 && "Unknown value type to return!");
case MVT::i1:
case MVT::i8:
- case MVT::i16:
+ case MVT::i16: {
RetVal = DAG.getCopyFromReg(Chain, SP::O0, MVT::i32, InFlag);
Chain = RetVal.getValue(1);
// Add a note to keep track of whether it is sign or zero extended.
- RetVal = DAG.getNode(RetTy->isSigned() ? ISD::AssertSext :ISD::AssertZext,
- MVT::i32, RetVal, DAG.getValueType(RetTyVT));
+ ISD::NodeType AssertKind = ISD::DELETED_NODE;
+ if (RetSExt)
+ AssertKind = ISD::AssertSext;
+ else if (RetZExt)
+ AssertKind = ISD::AssertZext;
+
+ if (AssertKind != ISD::DELETED_NODE)
+ RetVal = DAG.getNode(AssertKind, MVT::i32, RetVal,
+ DAG.getValueType(RetTyVT));
+
RetVal = DAG.getNode(ISD::TRUNCATE, RetTyVT, RetVal);
break;
+ }
case MVT::i32:
RetVal = DAG.getCopyFromReg(Chain, SP::O0, MVT::i32, InFlag);
Chain = RetVal.getValue(1);
}
}
- Chain = DAG.getNode(ISD::CALLSEQ_END, MVT::Other, Chain,
- DAG.getConstant(ArgsSize, getPointerTy()));
-
+ Chain = DAG.getCALLSEQ_END(Chain,
+ DAG.getConstant(ArgsSize, getPointerTy()),
+ DAG.getConstant(0, getPointerTy()),
+ SDOperand());
return std::make_pair(RetVal, Chain);
}
LowerOperation(SDOperand Op, SelectionDAG &DAG) {
switch (Op.getOpcode()) {
default: assert(0 && "Should not custom lower this!");
+ case ISD::GlobalTLSAddress:
+ assert(0 && "TLS not implemented for Sparc.");
case ISD::GlobalAddress: {
GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
SDOperand GA = DAG.getTargetGlobalAddress(GV, MVT::i32);
SDOperand Offset = DAG.getNode(ISD::ADD, MVT::i32,
DAG.getRegister(SP::I6, MVT::i32),
DAG.getConstant(VarArgsFrameOffset, MVT::i32));
- SrcValueSDNode *SV = cast<SrcValueSDNode>(Op.getOperand(2));
- return DAG.getStore(Op.getOperand(0), Offset,
- Op.getOperand(1), SV->getValue(), SV->getOffset());
+ const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
+ return DAG.getStore(Op.getOperand(0), Offset, Op.getOperand(1), SV, 0);
}
case ISD::VAARG: {
SDNode *Node = Op.Val;
MVT::ValueType VT = Node->getValueType(0);
SDOperand InChain = Node->getOperand(0);
SDOperand VAListPtr = Node->getOperand(1);
- SrcValueSDNode *SV = cast<SrcValueSDNode>(Node->getOperand(2));
- SDOperand VAList = DAG.getLoad(getPointerTy(), InChain, VAListPtr,
- SV->getValue(), SV->getOffset());
+ const Value *SV = cast<SrcValueSDNode>(Node->getOperand(2))->getValue();
+ SDOperand VAList = DAG.getLoad(getPointerTy(), InChain, VAListPtr, SV, 0);
// Increment the pointer, VAList, to the next vaarg
SDOperand NextPtr = DAG.getNode(ISD::ADD, getPointerTy(), VAList,
DAG.getConstant(MVT::getSizeInBits(VT)/8,
getPointerTy()));
// Store the incremented VAList to the legalized pointer
InChain = DAG.getStore(VAList.getValue(1), NextPtr,
- VAListPtr, SV->getValue(), SV->getOffset());
+ VAListPtr, SV, 0);
// Load the actual argument out of the pointer VAList, unless this is an
// f64 load.
if (VT != MVT::f64) {
}
return DAG.getNode(SPISD::RET_FLAG, MVT::Other, Copy, Copy.getValue(1));
}
+ // Frame & Return address. Currently unimplemented
+ case ISD::RETURNADDR: break;
+ case ISD::FRAMEADDR: break;
}
+ return SDOperand();
}
MachineBasicBlock *
-SparcTargetLowering::InsertAtEndOfBasicBlock(MachineInstr *MI,
- MachineBasicBlock *BB) {
+SparcTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
+ MachineBasicBlock *BB) {
+ const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo();
unsigned BROpcode;
unsigned CC;
// Figure out the conditional branch opcode to use for this select_cc.
break;
}
- CC = (SPCC::CondCodes)MI->getOperand(3).getImmedValue();
+ CC = (SPCC::CondCodes)MI->getOperand(3).getImm();
// To "insert" a SELECT_CC instruction, we actually have to insert the diamond
// control-flow pattern. The incoming instruction knows the destination vreg
MachineBasicBlock *thisMBB = BB;
MachineBasicBlock *copy0MBB = new MachineBasicBlock(LLVM_BB);
MachineBasicBlock *sinkMBB = new MachineBasicBlock(LLVM_BB);
- BuildMI(BB, BROpcode, 2).addMBB(sinkMBB).addImm(CC);
+ BuildMI(BB, TII.get(BROpcode)).addMBB(sinkMBB).addImm(CC);
MachineFunction *F = BB->getParent();
F->getBasicBlockList().insert(It, copy0MBB);
F->getBasicBlockList().insert(It, sinkMBB);
// %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ]
// ...
BB = sinkMBB;
- BuildMI(BB, SP::PHI, 4, MI->getOperand(0).getReg())
+ BuildMI(BB, TII.get(SP::PHI), MI->getOperand(0).getReg())
.addReg(MI->getOperand(2).getReg()).addMBB(copy0MBB)
.addReg(MI->getOperand(1).getReg()).addMBB(thisMBB);