#include "AlphaTargetMachine.h"
#include "AlphaISelLowering.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/SSARegMap.h"
#include "llvm/CodeGen/SelectionDAG.h"
CurDAG->SelectNodeTo(N, Alpha::LDAr, MVT::i64, CPI, Tmp);
return SDOperand(N, 0);
}
+ break;
}
case ISD::ConstantFP:
if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(N)) {
} else {
abort();
}
+ break;
}
+ case ISD::SDIV:
+ case ISD::UDIV:
+ case ISD::UREM:
+ case ISD::SREM:
+ if (MVT::isInteger(N->getValueType(0))) {
+ const char* opstr = 0;
+ switch(N->getOpcode()) {
+ case ISD::UREM: opstr = "__remqu"; break;
+ case ISD::SREM: opstr = "__remq"; break;
+ case ISD::UDIV: opstr = "__divqu"; break;
+ case ISD::SDIV: opstr = "__divq"; break;
+ }
+ SDOperand Tmp1 = Select(N->getOperand(0)),
+ Tmp2 = Select(N->getOperand(1)),
+ Addr = CurDAG->getExternalSymbol(opstr, AlphaLowering.getPointerTy());
+ SDOperand Tmp3 = Select(Addr);
+ SDOperand Chain = CurDAG->getCopyToReg(CurDAG->getRoot(), Alpha::R24,
+ Tmp1, SDOperand());
+ Chain = CurDAG->getCopyToReg(CurDAG->getRoot(), Alpha::R25,
+ Tmp2, Chain.getValue(1));
+ Chain = CurDAG->getCopyToReg(CurDAG->getRoot(), Alpha::R27,
+ Tmp3, Chain.getValue(1));
+ Chain = CurDAG->getTargetNode(Alpha::JSRs, MVT::i64, MVT::Flag,
+ CurDAG->getRegister(Alpha::R27, MVT::i64),
+ getI64Imm(0));
+ return CurDAG->getCopyFromReg(Chain.getValue(1), Alpha::R27, MVT::i64,
+ Chain.getValue(1));
+ }
+ break;
+
+ case ISD::SETCC:
+ if (MVT::isFloatingPoint(N->getOperand(0).Val->getValueType(0))) {
+ unsigned Opc = Alpha::WTF;
+ ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get();
+ bool rev = false;
+ switch(CC) {
+ default: N->dump(); assert(0 && "Unknown FP comparison!");
+ case ISD::SETEQ: Opc = Alpha::CMPTEQ; break;
+ case ISD::SETLT: Opc = Alpha::CMPTLT; break;
+ case ISD::SETLE: Opc = Alpha::CMPTLE; break;
+ case ISD::SETGT: Opc = Alpha::CMPTLT; rev = true; break;
+ case ISD::SETGE: Opc = Alpha::CMPTLE; rev = true; break;
+ //case ISD::SETNE: Opc = Alpha::CMPTEQ; inv = true; break;
+ };
+ SDOperand tmp1 = Select(N->getOperand(0)),
+ tmp2 = Select(N->getOperand(1));
+ SDOperand cmp = CurDAG->getTargetNode(Opc, MVT::f64,
+ rev?tmp2:tmp1,
+ rev?tmp1:tmp2);
+ SDOperand LD;
+ if (AlphaLowering.hasITOF()) {
+ LD = CurDAG->getNode(AlphaISD::FTOIT_, MVT::i64, cmp);
+ } else {
+ int FrameIdx =
+ CurDAG->getMachineFunction().getFrameInfo()->CreateStackObject(8, 8);
+ SDOperand FI = CurDAG->getFrameIndex(FrameIdx, MVT::i64);
+ SDOperand ST = CurDAG->getTargetNode(Alpha::STT, MVT::Other,
+ cmp, FI, CurDAG->getRegister(Alpha::R31, MVT::i64));
+ LD = CurDAG->getTargetNode(Alpha::LDQ, MVT::i64, FI,
+ CurDAG->getRegister(Alpha::R31, MVT::i64),
+ ST);
+ }
+ SDOperand FP = CurDAG->getTargetNode(Alpha::CMPULT, MVT::i64,
+ CurDAG->getRegister(Alpha::R31, MVT::i64),
+ LD);
+ return FP;
+ }
+ break;
}
return SelectCode(Op);
for (int i = 0; i < std::min(6, count); ++i) {
if (MVT::isInteger(TypeOperands[i])) {
Chain = CurDAG->getCopyToReg(Chain, args_int[i], CallOperands[i]);
- } else if (TypeOperands[i] == MVT::f64 || TypeOperands[i] == MVT::f64) {
+ } else if (TypeOperands[i] == MVT::f32 || TypeOperands[i] == MVT::f64) {
Chain = CurDAG->getCopyToReg(Chain, args_float[i], CallOperands[i]);
} else
assert(0 && "Unknown operand");
}
-
- assert(CallOperands.size() <= 6 && "Too big a call");
+ for (int i = 6; i < count; ++i) {
+ unsigned Opc = Alpha::WTF;
+ if (MVT::isInteger(TypeOperands[i])) {
+ Opc = Alpha::STQ;
+ } else if (TypeOperands[i] == MVT::f32) {
+ Opc = Alpha::STS;
+ } else if (TypeOperands[i] == MVT::f64) {
+ Opc = Alpha::STT;
+ } else
+ assert(0 && "Unknown operand");
+ Chain = CurDAG->getTargetNode(Opc, MVT::Other, CallOperands[i],
+ getI64Imm((i - 6) * 8),
+ CurDAG->getRegister(Alpha::R30, MVT::i64),
+ Chain);
+ }
Chain = CurDAG->getCopyToReg(Chain, Alpha::R27, Addr);
// Finally, once everything is in registers to pass to the call, emit the
setOperationAction(ISD::FREM, MVT::f64, Expand);
setOperationAction(ISD::UINT_TO_FP, MVT::i64, Expand);
+ setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
if (!TM.getSubtarget<AlphaSubtarget>().hasCT()) {
setOperationAction(ISD::CTPOP , MVT::i64 , Expand);
// We don't have line number support yet.
setOperationAction(ISD::LOCATION, MVT::Other, Expand);
- computeRegisterProperties();
-
addLegalFPImmediate(+0.0); //F31
addLegalFPImmediate(-0.0); //-F31
+
+ computeRegisterProperties();
+
+ useITOF = TM.getSubtarget<AlphaSubtarget>().hasF2I();
}
}
+/// LowerOperation - Provide custom lowering hooks for some operations.
+///
+SDOperand AlphaTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
+ switch (Op.getOpcode()) {
+ default: assert(0 && "Wasn't expecting to be able to lower this!");
+ case ISD::SINT_TO_FP: {
+ assert(MVT::i64 == Op.getOperand(0).getValueType() &&
+ "Unhandled SINT_TO_FP type in custom expander!");
+ SDOperand LD;
+ bool isDouble = MVT::f64 == Op.getValueType();
+ if (useITOF) {
+ LD = DAG.getNode(AlphaISD::ITOFT_, MVT::f64, Op.getOperand(0));
+ } else {
+ int FrameIdx =
+ DAG.getMachineFunction().getFrameInfo()->CreateStackObject(8, 8);
+ SDOperand FI = DAG.getFrameIndex(FrameIdx, MVT::i64);
+ SDOperand ST = DAG.getNode(ISD::STORE, MVT::Other, DAG.getEntryNode(),
+ Op.getOperand(0), FI, DAG.getSrcValue(0));
+ LD = DAG.getLoad(MVT::f64, ST, FI, DAG.getSrcValue(0));
+ }
+ SDOperand FP = DAG.getNode(isDouble?AlphaISD::CVTQT_:AlphaISD::CVTQS_,
+ isDouble?MVT::f64:MVT::f32, LD);
+ return FP;
+ }
+ }
+ return SDOperand();
+}
+
enum NodeType {
// Start the numbering where the builting ops and target ops leave off.
FIRST_NUMBER = ISD::BUILTIN_OP_END+Alpha::INSTRUCTION_LIST_END,
+ //These corrospond to the identical Instruction
+ ITOFT_, FTOIT_, CVTQT_, CVTQS_,
};
}
int VarArgsBase; // What is the base FrameIndex
unsigned GP; //GOT vreg
unsigned RA; //Return Address
+ bool useITOF;
public:
AlphaTargetLowering(TargetMachine &TM);
-
+
+ /// LowerOperation - Provide custom lowering hooks for some operations.
+ ///
+ virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG);
+
/// LowerArguments - This hook must be implemented to indicate how we should
/// lower the arguments for the specified function, into the specified DAG.
virtual std::vector<SDOperand>
void restoreRA(MachineBasicBlock* BB);
unsigned getVRegGP() { return GP; }
unsigned getVRegRA() { return RA; }
+ bool hasITOF() { return useITOF; }
};
}
}
return Result;
- case ISD::SINT_TO_FP:
- {
- assert (N.getOperand(0).getValueType() == MVT::i64
- && "only quads can be loaded from");
- Tmp1 = SelectExpr(N.getOperand(0)); // Get the operand register
- Tmp2 = MakeReg(MVT::f64);
- MoveInt2FP(Tmp1, Tmp2, true);
- Opc = DestType == MVT::f64 ? Alpha::CVTQT : Alpha::CVTQS;
- BuildMI(BB, Opc, 1, Result).addReg(Tmp2);
- return Result;
- }
+ case AlphaISD::CVTQT_:
+ BuildMI(BB, Alpha::CVTQT, 1, Result).addReg(SelectExpr(N.getOperand(0)));
+ return Result;
+
+ case AlphaISD::CVTQS_:
+ BuildMI(BB, Alpha::CVTQS, 1, Result).addReg(SelectExpr(N.getOperand(0)));
+ return Result;
+
+ case AlphaISD::ITOFT_:
+ BuildMI(BB, Alpha::ITOFT, 1, Result).addReg(SelectExpr(N.getOperand(0)));
+ return Result;
case ISD::AssertSext:
case ISD::AssertZext:
}
//3.3.1
+class MFormAlt<bits<6> opcode, string asmstr>
+ : InstAlphaAlt<opcode, asmstr> {
+ bits<5> Ra;
+ bits<16> disp;
+ bits<5> Rb;
+
+ let Inst{25-21} = Ra;
+ let Inst{20-16} = Rb;
+ let Inst{15-0} = disp;
+}
class MForm<bits<6> opcode, string asmstr>
: InstAlpha<opcode, (ops GPRC:$RA, s16imm:$DISP, GPRC:$RB), asmstr> {
bits<5> Ra;
include "AlphaInstrFormats.td"
+//********************
+//Custom DAG Nodes
+//********************
+
+def SDTFPUnaryOpUnC : SDTypeProfile<1, 1, [
+ SDTCisFP<1>, SDTCisFP<0>
+]>;
+
+def Alpha_itoft : SDNode<"AlphaISD::ITOFT_", SDTIntToFPOp, []>;
+def Alpha_ftoit : SDNode<"AlphaISD::FTOIT_", SDTFPToIntOp, []>;
+def Alpha_cvtqt : SDNode<"AlphaISD::CVTQT_", SDTFPUnaryOpUnC, []>;
+def Alpha_cvtqs : SDNode<"AlphaISD::CVTQS_", SDTFPUnaryOpUnC, []>;
+
+
//********************
//Paterns for matching
//********************
def CMOVNE : OForm4< 0x11, 0x26, "cmovne $RCOND,$RSRC,$RDEST">; //CMOVE if RCOND != zero
def CMOVNEi : OForm4L< 0x11, 0x26, "cmovne $RCOND,$L,$RDEST">; //CMOVE if RCOND != zero
+//FIXME: fold setcc with select
+def : Pat<(select GPRC:$which, GPRC:$src1, GPRC:$src2),
+ (CMOVEQ GPRC:$src1, GPRC:$src2, GPRC:$which)>;
+
//conditional moves, fp
let OperandList = (ops F8RC:$RDEST, F8RC:$RSRC2, F8RC:$RSRC, F8RC:$RCOND),
isTwoAddress = 1 in {
def LDWU : MForm<0x0C, "ldwu $RA,$DISP($RB)">; //Load zero-extended word
//Stores, float
-def STS : MForm<0x26, "sts $RA,$DISP($RB)">; //Store S_floating
-def STT : MForm<0x27, "stt $RA,$DISP($RB)">; //Store T_floating
+let OperandList = (ops F4RC:$RA, s16imm:$DISP, GPRC:$RB) in
+def STS : MFormAlt<0x26, "sts $RA,$DISP($RB)">; //Store S_floating
+let OperandList = (ops F8RC:$RA, s16imm:$DISP, GPRC:$RB) in
+def STT : MFormAlt<0x27, "stt $RA,$DISP($RB)">; //Store T_floating
//Loads, float
-def LDS : MForm<0x22, "lds $RA,$DISP($RB)">; //Load S_floating
-def LDT : MForm<0x23, "ldt $RA,$DISP($RB)">; //Load T_floating
+let OperandList = (ops F4RC:$RA, s16imm:$DISP, GPRC:$RB) in
+def LDS : MFormAlt<0x22, "lds $RA,$DISP($RB)">; //Load S_floating
+let OperandList = (ops F8RC:$RA, s16imm:$DISP, GPRC:$RB) in
+def LDT : MFormAlt<0x23, "ldt $RA,$DISP($RB)">; //Load T_floating
//Load address
def LDA : MForm<0x08, "lda $RA,$DISP($RB)">; //Load address
def LDWUr : MForm<0x0C, "ldwu $RA,$DISP($RB)\t\t!gprellow">; //Load zero-extended word
//Loads, float, Rellocated Low form
-def LDSr : MForm<0x22, "lds $RA,$DISP($RB)\t\t!gprellow">; //Load S_floating
-def LDTr : MForm<0x23, "ldt $RA,$DISP($RB)\t\t!gprellow">; //Load T_floating
+let OperandList = (ops F4RC:$RA, s16imm:$DISP, GPRC:$RB) in
+def LDSr : MFormAlt<0x22, "lds $RA,$DISP($RB)\t\t!gprellow">; //Load S_floating
+let OperandList = (ops F8RC:$RA, s16imm:$DISP, GPRC:$RB) in
+def LDTr : MFormAlt<0x23, "ldt $RA,$DISP($RB)\t\t!gprellow">; //Load T_floating
//Load address, rellocated low and high form
def LDAr : MForm<0x08, "lda $RA,$DISP($RB)\t\t!gprellow">; //Load address
def STQr : MForm<0x2D, "stq $RA,$DISP($RB)\t\t!gprellow">; //Store quadword
//Stores, float
-def STSr : MForm<0x26, "sts $RA,$DISP($RB)\t\t!gprellow">; //Store S_floating
-def STTr : MForm<0x27, "stt $RA,$DISP($RB)\t\t!gprellow">; //Store T_floating
+let OperandList = (ops F4RC:$RA, s16imm:$DISP, GPRC:$RB) in
+def STSr : MFormAlt<0x26, "sts $RA,$DISP($RB)\t\t!gprellow">; //Store S_floating
+let OperandList = (ops F8RC:$RA, s16imm:$DISP, GPRC:$RB) in
+def STTr : MFormAlt<0x27, "stt $RA,$DISP($RB)\t\t!gprellow">; //Store T_floating
//Branches, int
let OperandList = (ops GPRC:$RC, F4RC:$RA), Fb = 31 in
def FTOIS : FPForm<0x1C, 0x078, "ftois $RA,$RC",[]>; //Floating to integer move, S_floating
let OperandList = (ops GPRC:$RC, F8RC:$RA), Fb = 31 in
-def FTOIT : FPForm<0x1C, 0x070, "ftoit $RA,$RC",[]>; //Floating to integer move, T_floating
+def FTOIT : FPForm<0x1C, 0x070, "ftoit $RA,$RC",
+ [(set GPRC:$RC, (Alpha_ftoit F8RC:$RA))]>; //Floating to integer move
let OperandList = (ops F4RC:$RC, GPRC:$RA), Fb = 31 in
def ITOFS : FPForm<0x14, 0x004, "itofs $RA,$RC",[]>; //Integer to floating move, S_floating
let OperandList = (ops F8RC:$RC, GPRC:$RA), Fb = 31 in
-def ITOFT : FPForm<0x14, 0x024, "itoft $RA,$RC",[]>; //Integer to floating move, T_floating
+def ITOFT : FPForm<0x14, 0x024, "itoft $RA,$RC",
+ [(set F8RC:$RC, (Alpha_itoft GPRC:$RA))]>; //Integer to floating move
let OperandList = (ops F4RC:$RC, F8RC:$RB), Fa = 31 in
-def CVTQS : FPForm<0x16, 0x7BC, "cvtqs/sui $RB,$RC",[]>; //Convert quadword to S_floating
+def CVTQS : FPForm<0x16, 0x7BC, "cvtqs/sui $RB,$RC",
+ [(set F4RC:$RC, (Alpha_cvtqs F8RC:$RB))]>;
let OperandList = (ops F8RC:$RC, F8RC:$RB), Fa = 31 in
-def CVTQT : FPForm<0x16, 0x7BE, "cvtqt/sui $RB,$RC",[]>; //Convert quadword to T_floating
+def CVTQT : FPForm<0x16, 0x7BE, "cvtqt/sui $RB,$RC",
+ [(set F8RC:$RC, (Alpha_cvtqt F8RC:$RB))]>;
let OperandList = (ops F8RC:$RC, F8RC:$RB), Fa = 31 in
def CVTTQ : FPForm<0x16, 0x52F, "cvttq/svc $RB,$RC",[]>; //Convert T_floating to quadword
let OperandList = (ops F8RC:$RC, F4RC:$RB), Fa = 31 in
def : Pat<(select GPRC:$which, GPRC:$src1, GPRC:$src2),
(CMOVEQ GPRC:$src1, GPRC:$src2, GPRC:$which)>; //may be CMOVNE
+def : Pat<(fabs F8RC:$RB),
+ (CPYST F31, F8RC:$RB)>;
+def : Pat<(fabs F4RC:$RB),
+ (CPYSS F31, F4RC:$RB)>;
+def : Pat<(fneg F8RC:$RB),
+ (CPYSNT F8RC:$RB, F8RC:$RB)>;
+def : Pat<(fneg F4RC:$RB),
+ (CPYSNS F4RC:$RB, F4RC:$RB)>;
// $28 is undefined after any and all calls
/// Register classes
-// Don't allocate 15, 28, 30, 31
def GPRC : RegisterClass<"Alpha", i64, 64,
// Volatile
[R0, R1, R2, R3, R4, R5, R6, R7, R8, R16, R17, R18, R19, R20, R21, R22,
R29, //global offset table address
// Non-volatile
R9, R10, R11, R12, R13, R14,
- R31 ]> //zero
+// Don't allocate 15, 30, 31
+ R15, R30, R31 ]> //zero
{
let MethodProtos = [{
iterator allocation_order_end(MachineFunction &MF) const;
let MethodBodies = [{
GPRCClass::iterator
GPRCClass::allocation_order_end(MachineFunction &MF) const {
- return end()-1;
+ return end()-3;
}
}];
}