2 //===- SparcV8ISelPattern.cpp - A pattern matching isel for SparcV8 -------===//
4 // The LLVM Compiler Infrastructure
6 // This file was developed by the LLVM research group and is distributed under
7 // the University of Illinois Open Source License. See LICENSE.TXT for details.
9 //===----------------------------------------------------------------------===//
11 // This file defines a pattern matching instruction selector for SparcV8.
13 //===----------------------------------------------------------------------===//
15 //Please note that this file is a work in progress, and not a high
16 //priority for anyone.
19 #include "SparcV8RegisterInfo.h"
20 #include "llvm/Constants.h" // FIXME: REMOVE
21 #include "llvm/Function.h"
22 #include "llvm/CodeGen/MachineInstrBuilder.h"
23 #include "llvm/CodeGen/MachineConstantPool.h" // FIXME: REMOVE
24 #include "llvm/CodeGen/MachineFunction.h"
25 #include "llvm/CodeGen/MachineFrameInfo.h"
26 #include "llvm/CodeGen/SelectionDAG.h"
27 #include "llvm/CodeGen/SelectionDAGISel.h"
28 #include "llvm/CodeGen/SSARegMap.h"
29 #include "llvm/Target/TargetData.h"
30 #include "llvm/Target/TargetLowering.h"
31 #include "llvm/Support/MathExtras.h"
32 #include "llvm/ADT/Statistic.h"
33 #include "llvm/Support/Debug.h"
34 #include "llvm/Support/CommandLine.h"
39 //===----------------------------------------------------------------------===//
40 // V8TargetLowering - SparcV8 Implementation of the TargetLowering interface
42 class V8TargetLowering : public TargetLowering {
43 int VarArgsFrameIndex; // FrameIndex for start of varargs area.
45 V8TargetLowering(TargetMachine &TM) : TargetLowering(TM) {
46 // Set up the TargetLowering object.
47 //I am having problems with shr n ubyte 1
48 setShiftAmountType(MVT::i32);
49 setSetCCResultType(MVT::i32);
50 setSetCCResultContents(ZeroOrOneSetCCResult);
52 //FIXME: get these right
53 addRegisterClass(MVT::i64, V8::GPRCRegisterClass);
54 addRegisterClass(MVT::f64, V8::FPRCRegisterClass);
55 addRegisterClass(MVT::f32, V8::FPRCRegisterClass);
57 setOperationAction(ISD::BRCONDTWOWAY, MVT::Other, Expand);
58 setOperationAction(ISD::BRTWOWAY_CC, MVT::Other, Expand);
59 setOperationAction(ISD::EXTLOAD, MVT::i1, Promote);
60 setOperationAction(ISD::EXTLOAD, MVT::f32, Promote);
62 setOperationAction(ISD::ZEXTLOAD, MVT::i1, Expand);
63 setOperationAction(ISD::SEXTLOAD, MVT::i1, Expand);
65 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
66 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8, Expand);
67 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand);
68 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i32, Expand);
70 setOperationAction(ISD::UREM, MVT::i32, Expand);
71 setOperationAction(ISD::SREM, MVT::i32, Expand);
73 setOperationAction(ISD::CTPOP, MVT::i32, Expand);
74 setOperationAction(ISD::CTTZ, MVT::i32, Expand);
75 setOperationAction(ISD::CTLZ, MVT::i32, Expand);
77 setOperationAction(ISD::MEMMOVE, MVT::Other, Expand);
78 setOperationAction(ISD::MEMSET, MVT::Other, Expand);
79 setOperationAction(ISD::MEMCPY, MVT::Other, Expand);
81 // We don't support sin/cos/sqrt
82 setOperationAction(ISD::FSIN , MVT::f64, Expand);
83 setOperationAction(ISD::FCOS , MVT::f64, Expand);
84 setOperationAction(ISD::FSQRT, MVT::f64, Expand);
85 setOperationAction(ISD::FSIN , MVT::f32, Expand);
86 setOperationAction(ISD::FCOS , MVT::f32, Expand);
87 setOperationAction(ISD::FSQRT, MVT::f32, Expand);
89 computeRegisterProperties();
91 addLegalFPImmediate(+0.0); //F31
92 addLegalFPImmediate(-0.0); //-F31
95 /// LowerArguments - This hook must be implemented to indicate how we should
96 /// lower the arguments for the specified function, into the specified DAG.
97 virtual std::vector<SDOperand>
98 LowerArguments(Function &F, SelectionDAG &DAG);
100 /// LowerCallTo - This hook lowers an abstract call to a function into an
102 virtual std::pair<SDOperand, SDOperand>
103 LowerCallTo(SDOperand Chain, const Type *RetTy, bool isVarArg, unsigned CC,
104 bool isTailCall, SDOperand Callee, ArgListTy &Args,
109 /// AddLiveIn - This helper function adds the specified physical register to the
110 /// MachineFunction as a live in value. It also creates a corresponding virtual
112 static unsigned AddLiveIn(MachineFunction &MF, unsigned PReg,
113 TargetRegisterClass *RC) {
114 assert(RC->contains(PReg) && "Not the correct regclass!");
115 unsigned VReg = MF.getSSARegMap()->createVirtualRegister(RC);
116 MF.addLiveIn(PReg, VReg);
120 std::vector<SDOperand>
121 V8TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG)
123 static const unsigned IncomingArgRegs[] =
124 { V8::I0, V8::I1, V8::I2, V8::I3, V8::I4, V8::I5 };
125 std::vector<SDOperand> ArgValues;
127 MachineFunction &MF = DAG.getMachineFunction();
128 MachineFrameInfo*MFI = MF.getFrameInfo();
130 MachineBasicBlock& BB = MF.front();
133 unsigned ArgOffset = 92;
134 for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end();
135 I != E; ++I, ++ArgNo) {
136 MVT::ValueType VT = getValueType(I->getType());
141 std::cerr << "Unknown Type " << VT << "\n";
145 //FIXME: figure out the build pair thing
146 assert(0 && "doubles and longs not supported yet");
148 argt = DAG.getCopyFromReg(AddLiveIn(MF, IncomingArgRegs[ArgNo],
151 //copy out of Int reg
152 argt = DAG.getNode(ISD::FP_TO_UINT, MVT::f32, argt);
158 argt = DAG.getCopyFromReg(AddLiveIn(MF, IncomingArgRegs[ArgNo],
159 getRegClassFor(MVT::i32)),
162 argt = DAG.getNode(ISD::TRUNCATE, VT, argt);
165 DAG.setRoot(argt.getValue(1));
170 std::cerr << "Unknown Type " << VT << "\n";
174 //FIXME: figure out the build pair thing
175 assert(0 && "doubles and longs not supported yet");
181 // Create the frame index object for this incoming parameter...
182 int FI = MFI->CreateFixedObject(4, ArgOffset);
183 argt = DAG.getLoad(VT,
185 DAG.getFramIndex(FI, MVT::i32),
186 DAG.getSrcValue(NULL));
190 ArgValues.push_back(argt);
194 //return the arguments
198 std::pair<SDOperand, SDOperand>
199 V8TargetLowering::LowerCallTo(SDOperand Chain,
200 const Type *RetTy, bool isVarArg,
201 unsigned CallingConv, bool isTailCall,
202 SDOperand Callee, ArgListTy &Args,
205 return std::make_pair(Chain, Chain);
210 //===--------------------------------------------------------------------===//
211 /// ISel - V8 specific code to select V8 machine instructions for
212 /// SelectionDAG operations.
213 //===--------------------------------------------------------------------===//
214 class ISel : public SelectionDAGISel {
216 /// V8Lowering - This object fully describes how to lower LLVM code to an
217 /// V8-specific SelectionDAG.
218 V8TargetLowering V8Lowering;
220 SelectionDAG *ISelDAG; // Hack to support us having a dag->dag transform
221 // for sdiv and udiv until it is put into the future
224 /// ExprMap - As shared expressions are codegen'd, we keep track of which
225 /// vreg the value is produced in, so we only emit one copy of each compiled
227 static const unsigned notIn = (unsigned)(-1);
228 std::map<SDOperand, unsigned> ExprMap;
231 ISel(TargetMachine &TM) : SelectionDAGISel(V8Lowering), V8Lowering(TM)
234 /// InstructionSelectBasicBlock - This callback is invoked by
235 /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
236 virtual void InstructionSelectBasicBlock(SelectionDAG &DAG) {
239 // Codegen the basic block.
241 max_depth = DAG.getRoot().getNodeDepth();
242 Select(DAG.getRoot());
244 // Clear state used for selection.
248 unsigned SelectExpr(SDOperand N);
249 void Select(SDOperand N);
254 //These describe LDAx
255 static const int IMM_LOW = -32768;
256 static const int IMM_HIGH = 32767;
257 static const int IMM_MULT = 65536;
259 static long getUpper16(long l)
261 long y = l / IMM_MULT;
262 if (l % IMM_MULT > IMM_HIGH)
267 static long getLower16(long l)
269 long h = getUpper16(l);
270 return l - h * IMM_MULT;
273 unsigned ISel::SelectExpr(SDOperand N) {
275 unsigned Tmp1, Tmp2 = 0, Tmp3;
277 unsigned opcode = N.getOpcode();
279 SDNode *Node = N.Val;
280 MVT::ValueType DestType = N.getValueType();
282 unsigned &Reg = ExprMap[N];
285 if (N.getOpcode() != ISD::CALL && N.getOpcode() != ISD::TAILCALL)
286 Reg = Result = (N.getValueType() != MVT::Other) ?
287 MakeReg(N.getValueType()) : notIn;
289 // If this is a call instruction, make sure to prepare ALL of the result
290 // values as well as the chain.
291 if (Node->getNumValues() == 1)
292 Reg = Result = notIn; // Void call, just a chain.
294 Result = MakeReg(Node->getValueType(0));
295 ExprMap[N.getValue(0)] = Result;
296 for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i)
297 ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i));
298 ExprMap[SDOperand(Node, Node->getNumValues()-1)] = notIn;
305 assert(0 && "Node not handled!\n");
312 // Make sure we generate both values.
314 ExprMap[N.getValue(1)] = notIn; // Generate the token
316 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
318 SDOperand Chain = N.getOperand(0);
319 SDOperand Address = N.getOperand(1);
321 unsigned Adr = SelectExpr(Address);
322 switch(cast<VTSDNode>(Node->getOperand(3))->getVT()) {
323 case MVT::i32: Opc = V8::LD;
324 case MVT::i16: Opc = opcode == ISD::ZEXTLOAD ? V8::LDUH : V8::LDSH; break;
325 case MVT::i8: Opc = opcode == ISD::ZEXTLOAD ? V8::LDUB : V8::LDSB; break;
326 case MVT::f64: Opc = V8::LDFSRrr;
327 case MVT::f32: Opc = V8::LDDFrr;
330 assert(0 && "Bad type!");
333 BuildMI(BB, Opc, 1, Result).addReg(Adr);
345 case ISD::CopyFromReg:
347 // Make sure we generate both values.
349 ExprMap[N.getValue(1)] = notIn; // Generate the token
351 Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
353 SDOperand Chain = N.getOperand(0);
355 unsigned r = dyn_cast<RegSDNode>(Node)->getReg();
357 BuildMI(BB, V8::ORrr, 2, Result).addReg(r).addReg(V8::G0);
361 //Most of the plain arithmetic and logic share the same form, and the same
362 //constant immediate test
376 case ISD::XOR: Opc = V8::XORrr; break;
377 case ISD::AND: Opc = V8::ANDrr; break;
378 case ISD::OR: Opc = V8::ORrr; break;
379 case ISD::SHL: Opc = V8::SLLrr; break;
380 case ISD::SRL: Opc = V8::SRLrr; break;
381 case ISD::SRA: Opc = V8::SRArr; break;
382 case ISD::ADD: Opc = V8::ADDrr; break;
383 case ISD::SUB: Opc = V8::SUBrr; break;
384 case ISD::SDIV: Opc = V8::SDIVrr; break;
385 case ISD::UDIV: Opc = V8::UDIVrr; break;
386 case ISD::SMUL: Opc = V8::SMULrr; break;
387 case ISD::UMUL: Opc = V8::UMULrr; break;
389 Tmp1 = SelectExpr(N.getOperand(0));
390 Tmp2 = SelectExpr(N.getOperand(1));
391 BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2);
398 void ISel::Select(SDOperand N) {
399 unsigned Tmp1, Tmp2, Opc;
400 unsigned opcode = N.getOpcode();
402 if (!ExprMap.insert(std::make_pair(N, notIn)).second)
403 return; // Already selected.
405 SDNode *Node = N.Val;
410 Node->dump(); std::cerr << "\n";
411 assert(0 && "Node not handled yet!");
420 MachineBasicBlock *Dest =
421 cast<BasicBlockSDNode>(N.getOperand(1))->getBasicBlock();
423 Select(N.getOperand(0));
424 BuildMI(BB, V8::BA, 1).addMBB(Dest);
428 case ISD::ImplicitDef:
429 Select(N.getOperand(0));
430 BuildMI(BB, V8::IMPLICIT_DEF, 0, cast<RegSDNode>(N)->getReg());
433 case ISD::EntryToken: return; // Noop
435 case ISD::TokenFactor:
436 for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i)
437 Select(Node->getOperand(i));
441 Select(N.getOperand(0));
442 Tmp1 = SelectExpr(N.getOperand(1));
443 Tmp2 = cast<RegSDNode>(N)->getReg();
446 if (N.getOperand(1).getValueType() == MVT::f64 ||
447 N.getOperand(1).getValueType() == MVT::f32)
448 BuildMI(BB, V8::FMOVS, 2, Tmp2).addReg(Tmp1);
450 BuildMI(BB, V8::ORrr, 2, Tmp2).addReg(Tmp1).addReg(V8::G0);
459 case ISD::TRUNCSTORE:
462 SDOperand Chain = N.getOperand(0);
463 SDOperand Value = N.getOperand(1);
464 SDOperand Address = N.getOperand(2);
467 Tmp1 = SelectExpr(Value);
468 Tmp2 = SelectExpr(Address);
470 unsigned VT = opcode == ISD::STORE ?
471 Value.getValueType() : cast<VTSDNode>(Node->getOperand(4))->getVT();
473 default: assert(0 && "unknown Type in store");
474 case MVT::f64: Opc = V8::STDFrr; break;
475 case MVT::f32: Opc = V8::STFrr; break;
476 case MVT::i1: //FIXME: DAG does not promote this load
477 case MVT::i8: Opc = V8::STBrr; break;
478 case MVT::i16: Opc = V8::STHrr; break;
479 case MVT::i32: Opc = V8::STLrr; break;
480 case MVT::i64: Opc = V8::STDrr; break;
483 BuildMI(BB,Opc,2).addReg(Tmp1).addReg(Tmp2);
491 case ISD::CopyFromReg:
494 case ISD::DYNAMIC_STACKALLOC:
499 case ISD::CALLSEQ_START:
500 case ISD::CALLSEQ_END:
501 Select(N.getOperand(0));
502 Tmp1 = cast<ConstantSDNode>(N.getOperand(1))->getValue();
504 Opc = N.getOpcode() == ISD::CALLSEQ_START ? V8::ADJUSTCALLSTACKDOWN :
505 V8::ADJUSTCALLSTACKUP;
506 BuildMI(BB, Opc, 1).addImm(Tmp1);
509 assert(0 && "Should not be reached!");
513 /// createV8PatternInstructionSelector - This pass converts an LLVM function
514 /// into a machine code representation using pattern matching and a machine
515 /// description file.
517 FunctionPass *llvm::createV8PatternInstructionSelector(TargetMachine &TM) {