1 //===-- AlphaISelLowering.cpp - Alpha DAG Lowering Implementation ---------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the AlphaISelLowering class.
12 //===----------------------------------------------------------------------===//
14 #include "AlphaISelLowering.h"
15 #include "AlphaTargetMachine.h"
16 #include "llvm/CodeGen/MachineFrameInfo.h"
17 #include "llvm/CodeGen/MachineFunction.h"
18 #include "llvm/CodeGen/MachineInstrBuilder.h"
19 #include "llvm/CodeGen/MachineRegisterInfo.h"
20 #include "llvm/CodeGen/SelectionDAG.h"
21 #include "llvm/CodeGen/MachineRegisterInfo.h"
22 #include "llvm/Constants.h"
23 #include "llvm/Function.h"
24 #include "llvm/Module.h"
25 #include "llvm/Intrinsics.h"
26 #include "llvm/Support/CommandLine.h"
27 #include "llvm/Support/ErrorHandling.h"
28 #include "llvm/Support/raw_ostream.h"
31 /// AddLiveIn - This helper function adds the specified physical register to the
32 /// MachineFunction as a live in value. It also creates a corresponding virtual
34 static unsigned AddLiveIn(MachineFunction
&MF
, unsigned PReg
,
35 TargetRegisterClass
*RC
) {
36 assert(RC
->contains(PReg
) && "Not the correct regclass!");
37 unsigned VReg
= MF
.getRegInfo().createVirtualRegister(RC
);
38 MF
.getRegInfo().addLiveIn(PReg
, VReg
);
42 AlphaTargetLowering::AlphaTargetLowering(TargetMachine
&TM
) : TargetLowering(TM
) {
43 // Set up the TargetLowering object.
44 //I am having problems with shr n i8 1
45 setShiftAmountType(MVT::i64
);
46 setBooleanContents(ZeroOrOneBooleanContent
);
48 setUsesGlobalOffsetTable(true);
50 addRegisterClass(MVT::i64
, Alpha::GPRCRegisterClass
);
51 addRegisterClass(MVT::f64
, Alpha::F8RCRegisterClass
);
52 addRegisterClass(MVT::f32
, Alpha::F4RCRegisterClass
);
54 // We want to custom lower some of our intrinsics.
55 setOperationAction(ISD::INTRINSIC_WO_CHAIN
, MVT::Other
, Custom
);
57 setLoadExtAction(ISD::EXTLOAD
, MVT::i1
, Promote
);
58 setLoadExtAction(ISD::EXTLOAD
, MVT::f32
, Expand
);
60 setLoadExtAction(ISD::ZEXTLOAD
, MVT::i1
, Promote
);
61 setLoadExtAction(ISD::ZEXTLOAD
, MVT::i32
, Expand
);
63 setLoadExtAction(ISD::SEXTLOAD
, MVT::i1
, Promote
);
64 setLoadExtAction(ISD::SEXTLOAD
, MVT::i8
, Expand
);
65 setLoadExtAction(ISD::SEXTLOAD
, MVT::i16
, Expand
);
67 // setOperationAction(ISD::BRIND, MVT::Other, Expand);
68 setOperationAction(ISD::BR_JT
, MVT::Other
, Expand
);
69 setOperationAction(ISD::BR_CC
, MVT::Other
, Expand
);
70 setOperationAction(ISD::SELECT_CC
, MVT::Other
, Expand
);
72 setOperationAction(ISD::SIGN_EXTEND_INREG
, MVT::i1
, Expand
);
74 setOperationAction(ISD::FREM
, MVT::f32
, Expand
);
75 setOperationAction(ISD::FREM
, MVT::f64
, Expand
);
77 setOperationAction(ISD::UINT_TO_FP
, MVT::i64
, Expand
);
78 setOperationAction(ISD::SINT_TO_FP
, MVT::i64
, Custom
);
79 setOperationAction(ISD::FP_TO_UINT
, MVT::i64
, Expand
);
80 setOperationAction(ISD::FP_TO_SINT
, MVT::i64
, Custom
);
82 if (!TM
.getSubtarget
<AlphaSubtarget
>().hasCT()) {
83 setOperationAction(ISD::CTPOP
, MVT::i64
, Expand
);
84 setOperationAction(ISD::CTTZ
, MVT::i64
, Expand
);
85 setOperationAction(ISD::CTLZ
, MVT::i64
, Expand
);
87 setOperationAction(ISD::BSWAP
, MVT::i64
, Expand
);
88 setOperationAction(ISD::ROTL
, MVT::i64
, Expand
);
89 setOperationAction(ISD::ROTR
, MVT::i64
, Expand
);
91 setOperationAction(ISD::SREM
, MVT::i64
, Custom
);
92 setOperationAction(ISD::UREM
, MVT::i64
, Custom
);
93 setOperationAction(ISD::SDIV
, MVT::i64
, Custom
);
94 setOperationAction(ISD::UDIV
, MVT::i64
, Custom
);
96 setOperationAction(ISD::ADDC
, MVT::i64
, Expand
);
97 setOperationAction(ISD::ADDE
, MVT::i64
, Expand
);
98 setOperationAction(ISD::SUBC
, MVT::i64
, Expand
);
99 setOperationAction(ISD::SUBE
, MVT::i64
, Expand
);
101 setOperationAction(ISD::UMUL_LOHI
, MVT::i64
, Expand
);
102 setOperationAction(ISD::SMUL_LOHI
, MVT::i64
, Expand
);
105 // We don't support sin/cos/sqrt/pow
106 setOperationAction(ISD::FSIN
, MVT::f64
, Expand
);
107 setOperationAction(ISD::FCOS
, MVT::f64
, Expand
);
108 setOperationAction(ISD::FSIN
, MVT::f32
, Expand
);
109 setOperationAction(ISD::FCOS
, MVT::f32
, Expand
);
111 setOperationAction(ISD::FSQRT
, MVT::f64
, Expand
);
112 setOperationAction(ISD::FSQRT
, MVT::f32
, Expand
);
114 setOperationAction(ISD::FPOW
, MVT::f32
, Expand
);
115 setOperationAction(ISD::FPOW
, MVT::f64
, Expand
);
117 setOperationAction(ISD::SETCC
, MVT::f32
, Promote
);
119 setOperationAction(ISD::BIT_CONVERT
, MVT::f32
, Promote
);
121 // We don't have line number support yet.
122 setOperationAction(ISD::DBG_STOPPOINT
, MVT::Other
, Expand
);
123 setOperationAction(ISD::DEBUG_LOC
, MVT::Other
, Expand
);
124 setOperationAction(ISD::DBG_LABEL
, MVT::Other
, Expand
);
125 setOperationAction(ISD::EH_LABEL
, MVT::Other
, Expand
);
127 // Not implemented yet.
128 setOperationAction(ISD::STACKSAVE
, MVT::Other
, Expand
);
129 setOperationAction(ISD::STACKRESTORE
, MVT::Other
, Expand
);
130 setOperationAction(ISD::DYNAMIC_STACKALLOC
, MVT::i64
, Expand
);
132 // We want to legalize GlobalAddress and ConstantPool and
133 // ExternalSymbols nodes into the appropriate instructions to
134 // materialize the address.
135 setOperationAction(ISD::GlobalAddress
, MVT::i64
, Custom
);
136 setOperationAction(ISD::ConstantPool
, MVT::i64
, Custom
);
137 setOperationAction(ISD::ExternalSymbol
, MVT::i64
, Custom
);
138 setOperationAction(ISD::GlobalTLSAddress
, MVT::i64
, Custom
);
140 setOperationAction(ISD::VASTART
, MVT::Other
, Custom
);
141 setOperationAction(ISD::VAEND
, MVT::Other
, Expand
);
142 setOperationAction(ISD::VACOPY
, MVT::Other
, Custom
);
143 setOperationAction(ISD::VAARG
, MVT::Other
, Custom
);
144 setOperationAction(ISD::VAARG
, MVT::i32
, Custom
);
146 setOperationAction(ISD::RET
, MVT::Other
, Custom
);
148 setOperationAction(ISD::JumpTable
, MVT::i64
, Custom
);
149 setOperationAction(ISD::JumpTable
, MVT::i32
, Custom
);
151 setStackPointerRegisterToSaveRestore(Alpha::R30
);
153 addLegalFPImmediate(APFloat(+0.0)); //F31
154 addLegalFPImmediate(APFloat(+0.0f
)); //F31
155 addLegalFPImmediate(APFloat(-0.0)); //-F31
156 addLegalFPImmediate(APFloat(-0.0f
)); //-F31
159 setJumpBufAlignment(16);
161 computeRegisterProperties();
164 MVT
AlphaTargetLowering::getSetCCResultType(MVT VT
) const {
168 const char *AlphaTargetLowering::getTargetNodeName(unsigned Opcode
) const {
171 case AlphaISD::CVTQT_
: return "Alpha::CVTQT_";
172 case AlphaISD::CVTQS_
: return "Alpha::CVTQS_";
173 case AlphaISD::CVTTQ_
: return "Alpha::CVTTQ_";
174 case AlphaISD::GPRelHi
: return "Alpha::GPRelHi";
175 case AlphaISD::GPRelLo
: return "Alpha::GPRelLo";
176 case AlphaISD::RelLit
: return "Alpha::RelLit";
177 case AlphaISD::GlobalRetAddr
: return "Alpha::GlobalRetAddr";
178 case AlphaISD::CALL
: return "Alpha::CALL";
179 case AlphaISD::DivCall
: return "Alpha::DivCall";
180 case AlphaISD::RET_FLAG
: return "Alpha::RET_FLAG";
181 case AlphaISD::COND_BRANCH_I
: return "Alpha::COND_BRANCH_I";
182 case AlphaISD::COND_BRANCH_F
: return "Alpha::COND_BRANCH_F";
186 /// getFunctionAlignment - Return the Log2 alignment of this function.
187 unsigned AlphaTargetLowering::getFunctionAlignment(const Function
*F
) const {
191 static SDValue
LowerJumpTable(SDValue Op
, SelectionDAG
&DAG
) {
192 MVT PtrVT
= Op
.getValueType();
193 JumpTableSDNode
*JT
= cast
<JumpTableSDNode
>(Op
);
194 SDValue JTI
= DAG
.getTargetJumpTable(JT
->getIndex(), PtrVT
);
195 SDValue Zero
= DAG
.getConstant(0, PtrVT
);
196 // FIXME there isn't really any debug info here
197 DebugLoc dl
= Op
.getDebugLoc();
199 SDValue Hi
= DAG
.getNode(AlphaISD::GPRelHi
, dl
, MVT::i64
, JTI
,
200 DAG
.getGLOBAL_OFFSET_TABLE(MVT::i64
));
201 SDValue Lo
= DAG
.getNode(AlphaISD::GPRelLo
, dl
, MVT::i64
, JTI
, Hi
);
205 //http://www.cs.arizona.edu/computer.help/policy/DIGITAL_unix/
206 //AA-PY8AC-TET1_html/callCH3.html#BLOCK21
208 //For now, just use variable size stack frame format
210 //In a standard call, the first six items are passed in registers $16
211 //- $21 and/or registers $f16 - $f21. (See Section 4.1.2 for details
212 //of argument-to-register correspondence.) The remaining items are
213 //collected in a memory argument list that is a naturally aligned
214 //array of quadwords. In a standard call, this list, if present, must
215 //be passed at 0(SP).
216 //7 ... n 0(SP) ... (n-7)*8(SP)
224 static SDValue
LowerFORMAL_ARGUMENTS(SDValue Op
, SelectionDAG
&DAG
,
226 int &VarArgsOffset
) {
227 MachineFunction
&MF
= DAG
.getMachineFunction();
228 MachineFrameInfo
*MFI
= MF
.getFrameInfo();
229 std::vector
<SDValue
> ArgValues
;
230 SDValue Root
= Op
.getOperand(0);
231 DebugLoc dl
= Op
.getDebugLoc();
233 unsigned args_int
[] = {
234 Alpha::R16
, Alpha::R17
, Alpha::R18
, Alpha::R19
, Alpha::R20
, Alpha::R21
};
235 unsigned args_float
[] = {
236 Alpha::F16
, Alpha::F17
, Alpha::F18
, Alpha::F19
, Alpha::F20
, Alpha::F21
};
238 for (unsigned ArgNo
= 0, e
= Op
.getNode()->getNumValues()-1; ArgNo
!= e
; ++ArgNo
) {
240 MVT ObjectVT
= Op
.getValue(ArgNo
).getValueType();
244 switch (ObjectVT
.getSimpleVT()) {
246 assert(false && "Invalid value type!");
248 args_float
[ArgNo
] = AddLiveIn(MF
, args_float
[ArgNo
],
249 &Alpha::F8RCRegClass
);
250 ArgVal
= DAG
.getCopyFromReg(Root
, dl
, args_float
[ArgNo
], ObjectVT
);
253 args_float
[ArgNo
] = AddLiveIn(MF
, args_float
[ArgNo
],
254 &Alpha::F4RCRegClass
);
255 ArgVal
= DAG
.getCopyFromReg(Root
, dl
, args_float
[ArgNo
], ObjectVT
);
258 args_int
[ArgNo
] = AddLiveIn(MF
, args_int
[ArgNo
],
259 &Alpha::GPRCRegClass
);
260 ArgVal
= DAG
.getCopyFromReg(Root
, dl
, args_int
[ArgNo
], MVT::i64
);
264 // Create the frame index object for this incoming parameter...
265 int FI
= MFI
->CreateFixedObject(8, 8 * (ArgNo
- 6));
267 // Create the SelectionDAG nodes corresponding to a load
268 //from this parameter
269 SDValue FIN
= DAG
.getFrameIndex(FI
, MVT::i64
);
270 ArgVal
= DAG
.getLoad(ObjectVT
, dl
, Root
, FIN
, NULL
, 0);
272 ArgValues
.push_back(ArgVal
);
275 // If the functions takes variable number of arguments, copy all regs to stack
276 bool isVarArg
= cast
<ConstantSDNode
>(Op
.getOperand(2))->getZExtValue() != 0;
278 VarArgsOffset
= (Op
.getNode()->getNumValues()-1) * 8;
279 std::vector
<SDValue
> LS
;
280 for (int i
= 0; i
< 6; ++i
) {
281 if (TargetRegisterInfo::isPhysicalRegister(args_int
[i
]))
282 args_int
[i
] = AddLiveIn(MF
, args_int
[i
], &Alpha::GPRCRegClass
);
283 SDValue argt
= DAG
.getCopyFromReg(Root
, dl
, args_int
[i
], MVT::i64
);
284 int FI
= MFI
->CreateFixedObject(8, -8 * (6 - i
));
285 if (i
== 0) VarArgsBase
= FI
;
286 SDValue SDFI
= DAG
.getFrameIndex(FI
, MVT::i64
);
287 LS
.push_back(DAG
.getStore(Root
, dl
, argt
, SDFI
, NULL
, 0));
289 if (TargetRegisterInfo::isPhysicalRegister(args_float
[i
]))
290 args_float
[i
] = AddLiveIn(MF
, args_float
[i
], &Alpha::F8RCRegClass
);
291 argt
= DAG
.getCopyFromReg(Root
, dl
, args_float
[i
], MVT::f64
);
292 FI
= MFI
->CreateFixedObject(8, - 8 * (12 - i
));
293 SDFI
= DAG
.getFrameIndex(FI
, MVT::i64
);
294 LS
.push_back(DAG
.getStore(Root
, dl
, argt
, SDFI
, NULL
, 0));
297 //Set up a token factor with all the stack traffic
298 Root
= DAG
.getNode(ISD::TokenFactor
, dl
, MVT::Other
, &LS
[0], LS
.size());
301 ArgValues
.push_back(Root
);
303 // Return the new list of results.
304 return DAG
.getNode(ISD::MERGE_VALUES
, dl
, Op
.getNode()->getVTList(),
305 &ArgValues
[0], ArgValues
.size());
308 static SDValue
LowerRET(SDValue Op
, SelectionDAG
&DAG
) {
309 DebugLoc dl
= Op
.getDebugLoc();
310 SDValue Copy
= DAG
.getCopyToReg(Op
.getOperand(0), dl
, Alpha::R26
,
311 DAG
.getNode(AlphaISD::GlobalRetAddr
,
312 DebugLoc::getUnknownLoc(),
315 switch (Op
.getNumOperands()) {
317 llvm_unreachable("Do not know how to return this many arguments!");
320 //return SDValue(); // ret void is legal
322 MVT ArgVT
= Op
.getOperand(1).getValueType();
324 if (ArgVT
.isInteger())
327 assert(ArgVT
.isFloatingPoint());
330 Copy
= DAG
.getCopyToReg(Copy
, dl
, ArgReg
,
331 Op
.getOperand(1), Copy
.getValue(1));
332 if (DAG
.getMachineFunction().getRegInfo().liveout_empty())
333 DAG
.getMachineFunction().getRegInfo().addLiveOut(ArgReg
);
337 MVT ArgVT
= Op
.getOperand(1).getValueType();
338 unsigned ArgReg1
, ArgReg2
;
339 if (ArgVT
.isInteger()) {
343 assert(ArgVT
.isFloatingPoint());
347 Copy
= DAG
.getCopyToReg(Copy
, dl
, ArgReg1
,
348 Op
.getOperand(1), Copy
.getValue(1));
349 if (std::find(DAG
.getMachineFunction().getRegInfo().liveout_begin(),
350 DAG
.getMachineFunction().getRegInfo().liveout_end(), ArgReg1
)
351 == DAG
.getMachineFunction().getRegInfo().liveout_end())
352 DAG
.getMachineFunction().getRegInfo().addLiveOut(ArgReg1
);
353 Copy
= DAG
.getCopyToReg(Copy
, dl
, ArgReg2
,
354 Op
.getOperand(3), Copy
.getValue(1));
355 if (std::find(DAG
.getMachineFunction().getRegInfo().liveout_begin(),
356 DAG
.getMachineFunction().getRegInfo().liveout_end(), ArgReg2
)
357 == DAG
.getMachineFunction().getRegInfo().liveout_end())
358 DAG
.getMachineFunction().getRegInfo().addLiveOut(ArgReg2
);
362 return DAG
.getNode(AlphaISD::RET_FLAG
, dl
,
363 MVT::Other
, Copy
, Copy
.getValue(1));
366 std::pair
<SDValue
, SDValue
>
367 AlphaTargetLowering::LowerCallTo(SDValue Chain
, const Type
*RetTy
,
368 bool RetSExt
, bool RetZExt
, bool isVarArg
,
369 bool isInreg
, unsigned NumFixedArgs
,
370 unsigned CallingConv
,
371 bool isTailCall
, SDValue Callee
,
372 ArgListTy
&Args
, SelectionDAG
&DAG
,
376 NumBytes
= (Args
.size() - 6) * 8;
378 Chain
= DAG
.getCALLSEQ_START(Chain
, DAG
.getIntPtrConstant(NumBytes
, true));
379 std::vector
<SDValue
> args_to_use
;
380 for (unsigned i
= 0, e
= Args
.size(); i
!= e
; ++i
)
382 switch (getValueType(Args
[i
].Ty
).getSimpleVT()) {
383 default: llvm_unreachable("Unexpected ValueType for argument!");
388 // Promote the integer to 64 bits. If the input type is signed use a
389 // sign extend, otherwise use a zero extend.
391 Args
[i
].Node
= DAG
.getNode(ISD::SIGN_EXTEND
, dl
,
392 MVT::i64
, Args
[i
].Node
);
393 else if (Args
[i
].isZExt
)
394 Args
[i
].Node
= DAG
.getNode(ISD::ZERO_EXTEND
, dl
,
395 MVT::i64
, Args
[i
].Node
);
397 Args
[i
].Node
= DAG
.getNode(ISD::ANY_EXTEND
, dl
, MVT::i64
, Args
[i
].Node
);
404 args_to_use
.push_back(Args
[i
].Node
);
407 std::vector
<MVT
> RetVals
;
408 MVT RetTyVT
= getValueType(RetTy
);
409 MVT ActualRetTyVT
= RetTyVT
;
410 if (RetTyVT
.getSimpleVT() >= MVT::i1
&& RetTyVT
.getSimpleVT() <= MVT::i32
)
411 ActualRetTyVT
= MVT::i64
;
413 if (RetTyVT
!= MVT::isVoid
)
414 RetVals
.push_back(ActualRetTyVT
);
415 RetVals
.push_back(MVT::Other
);
417 std::vector
<SDValue
> Ops
;
418 Ops
.push_back(Chain
);
419 Ops
.push_back(Callee
);
420 Ops
.insert(Ops
.end(), args_to_use
.begin(), args_to_use
.end());
421 SDValue TheCall
= DAG
.getNode(AlphaISD::CALL
, dl
,
422 RetVals
, &Ops
[0], Ops
.size());
423 Chain
= TheCall
.getValue(RetTyVT
!= MVT::isVoid
);
424 Chain
= DAG
.getCALLSEQ_END(Chain
, DAG
.getIntPtrConstant(NumBytes
, true),
425 DAG
.getIntPtrConstant(0, true), SDValue());
426 SDValue RetVal
= TheCall
;
428 if (RetTyVT
!= ActualRetTyVT
) {
429 ISD::NodeType AssertKind
= ISD::DELETED_NODE
;
431 AssertKind
= ISD::AssertSext
;
433 AssertKind
= ISD::AssertZext
;
435 if (AssertKind
!= ISD::DELETED_NODE
)
436 RetVal
= DAG
.getNode(AssertKind
, dl
, MVT::i64
, RetVal
,
437 DAG
.getValueType(RetTyVT
));
439 RetVal
= DAG
.getNode(ISD::TRUNCATE
, dl
, RetTyVT
, RetVal
);
442 return std::make_pair(RetVal
, Chain
);
445 void AlphaTargetLowering::LowerVAARG(SDNode
*N
, SDValue
&Chain
,
446 SDValue
&DataPtr
, SelectionDAG
&DAG
) {
447 Chain
= N
->getOperand(0);
448 SDValue VAListP
= N
->getOperand(1);
449 const Value
*VAListS
= cast
<SrcValueSDNode
>(N
->getOperand(2))->getValue();
450 DebugLoc dl
= N
->getDebugLoc();
452 SDValue Base
= DAG
.getLoad(MVT::i64
, dl
, Chain
, VAListP
, VAListS
, 0);
453 SDValue Tmp
= DAG
.getNode(ISD::ADD
, dl
, MVT::i64
, VAListP
,
454 DAG
.getConstant(8, MVT::i64
));
455 SDValue Offset
= DAG
.getExtLoad(ISD::SEXTLOAD
, dl
, MVT::i64
, Base
.getValue(1),
456 Tmp
, NULL
, 0, MVT::i32
);
457 DataPtr
= DAG
.getNode(ISD::ADD
, dl
, MVT::i64
, Base
, Offset
);
458 if (N
->getValueType(0).isFloatingPoint())
460 //if fp && Offset < 6*8, then subtract 6*8 from DataPtr
461 SDValue FPDataPtr
= DAG
.getNode(ISD::SUB
, dl
, MVT::i64
, DataPtr
,
462 DAG
.getConstant(8*6, MVT::i64
));
463 SDValue CC
= DAG
.getSetCC(dl
, MVT::i64
, Offset
,
464 DAG
.getConstant(8*6, MVT::i64
), ISD::SETLT
);
465 DataPtr
= DAG
.getNode(ISD::SELECT
, dl
, MVT::i64
, CC
, FPDataPtr
, DataPtr
);
468 SDValue NewOffset
= DAG
.getNode(ISD::ADD
, dl
, MVT::i64
, Offset
,
469 DAG
.getConstant(8, MVT::i64
));
470 Chain
= DAG
.getTruncStore(Offset
.getValue(1), dl
, NewOffset
, Tmp
, NULL
, 0,
474 /// LowerOperation - Provide custom lowering hooks for some operations.
476 SDValue
AlphaTargetLowering::LowerOperation(SDValue Op
, SelectionDAG
&DAG
) {
477 DebugLoc dl
= Op
.getDebugLoc();
478 switch (Op
.getOpcode()) {
479 default: llvm_unreachable("Wasn't expecting to be able to lower this!");
480 case ISD::FORMAL_ARGUMENTS
: return LowerFORMAL_ARGUMENTS(Op
, DAG
,
484 case ISD::RET
: return LowerRET(Op
,DAG
);
485 case ISD::JumpTable
: return LowerJumpTable(Op
, DAG
);
487 case ISD::INTRINSIC_WO_CHAIN
: {
488 unsigned IntNo
= cast
<ConstantSDNode
>(Op
.getOperand(0))->getZExtValue();
490 default: break; // Don't custom lower most intrinsics.
491 case Intrinsic::alpha_umulh
:
492 return DAG
.getNode(ISD::MULHU
, dl
, MVT::i64
,
493 Op
.getOperand(1), Op
.getOperand(2));
497 case ISD::SINT_TO_FP
: {
498 assert(Op
.getOperand(0).getValueType() == MVT::i64
&&
499 "Unhandled SINT_TO_FP type in custom expander!");
501 bool isDouble
= Op
.getValueType() == MVT::f64
;
502 LD
= DAG
.getNode(ISD::BIT_CONVERT
, dl
, MVT::f64
, Op
.getOperand(0));
503 SDValue FP
= DAG
.getNode(isDouble
?AlphaISD::CVTQT_
:AlphaISD::CVTQS_
, dl
,
504 isDouble
?MVT::f64
:MVT::f32
, LD
);
507 case ISD::FP_TO_SINT
: {
508 bool isDouble
= Op
.getOperand(0).getValueType() == MVT::f64
;
509 SDValue src
= Op
.getOperand(0);
511 if (!isDouble
) //Promote
512 src
= DAG
.getNode(ISD::FP_EXTEND
, dl
, MVT::f64
, src
);
514 src
= DAG
.getNode(AlphaISD::CVTTQ_
, dl
, MVT::f64
, src
);
516 return DAG
.getNode(ISD::BIT_CONVERT
, dl
, MVT::i64
, src
);
518 case ISD::ConstantPool
: {
519 ConstantPoolSDNode
*CP
= cast
<ConstantPoolSDNode
>(Op
);
520 Constant
*C
= CP
->getConstVal();
521 SDValue CPI
= DAG
.getTargetConstantPool(C
, MVT::i64
, CP
->getAlignment());
522 // FIXME there isn't really any debug info here
524 SDValue Hi
= DAG
.getNode(AlphaISD::GPRelHi
, dl
, MVT::i64
, CPI
,
525 DAG
.getGLOBAL_OFFSET_TABLE(MVT::i64
));
526 SDValue Lo
= DAG
.getNode(AlphaISD::GPRelLo
, dl
, MVT::i64
, CPI
, Hi
);
529 case ISD::GlobalTLSAddress
:
530 llvm_unreachable("TLS not implemented for Alpha.");
531 case ISD::GlobalAddress
: {
532 GlobalAddressSDNode
*GSDN
= cast
<GlobalAddressSDNode
>(Op
);
533 GlobalValue
*GV
= GSDN
->getGlobal();
534 SDValue GA
= DAG
.getTargetGlobalAddress(GV
, MVT::i64
, GSDN
->getOffset());
535 // FIXME there isn't really any debug info here
537 // if (!GV->hasWeakLinkage() && !GV->isDeclaration() && !GV->hasLinkOnceLinkage()) {
538 if (GV
->hasLocalLinkage()) {
539 SDValue Hi
= DAG
.getNode(AlphaISD::GPRelHi
, dl
, MVT::i64
, GA
,
540 DAG
.getGLOBAL_OFFSET_TABLE(MVT::i64
));
541 SDValue Lo
= DAG
.getNode(AlphaISD::GPRelLo
, dl
, MVT::i64
, GA
, Hi
);
544 return DAG
.getNode(AlphaISD::RelLit
, dl
, MVT::i64
, GA
,
545 DAG
.getGLOBAL_OFFSET_TABLE(MVT::i64
));
547 case ISD::ExternalSymbol
: {
548 return DAG
.getNode(AlphaISD::RelLit
, dl
, MVT::i64
,
549 DAG
.getTargetExternalSymbol(cast
<ExternalSymbolSDNode
>(Op
)
550 ->getSymbol(), MVT::i64
),
551 DAG
.getGLOBAL_OFFSET_TABLE(MVT::i64
));
556 //Expand only on constant case
557 if (Op
.getOperand(1).getOpcode() == ISD::Constant
) {
558 MVT VT
= Op
.getNode()->getValueType(0);
559 SDValue Tmp1
= Op
.getNode()->getOpcode() == ISD::UREM
?
560 BuildUDIV(Op
.getNode(), DAG
, NULL
) :
561 BuildSDIV(Op
.getNode(), DAG
, NULL
);
562 Tmp1
= DAG
.getNode(ISD::MUL
, dl
, VT
, Tmp1
, Op
.getOperand(1));
563 Tmp1
= DAG
.getNode(ISD::SUB
, dl
, VT
, Op
.getOperand(0), Tmp1
);
569 if (Op
.getValueType().isInteger()) {
570 if (Op
.getOperand(1).getOpcode() == ISD::Constant
)
571 return Op
.getOpcode() == ISD::SDIV
? BuildSDIV(Op
.getNode(), DAG
, NULL
)
572 : BuildUDIV(Op
.getNode(), DAG
, NULL
);
573 const char* opstr
= 0;
574 switch (Op
.getOpcode()) {
575 case ISD::UREM
: opstr
= "__remqu"; break;
576 case ISD::SREM
: opstr
= "__remq"; break;
577 case ISD::UDIV
: opstr
= "__divqu"; break;
578 case ISD::SDIV
: opstr
= "__divq"; break;
580 SDValue Tmp1
= Op
.getOperand(0),
581 Tmp2
= Op
.getOperand(1),
582 Addr
= DAG
.getExternalSymbol(opstr
, MVT::i64
);
583 return DAG
.getNode(AlphaISD::DivCall
, dl
, MVT::i64
, Addr
, Tmp1
, Tmp2
);
588 SDValue Chain
, DataPtr
;
589 LowerVAARG(Op
.getNode(), Chain
, DataPtr
, DAG
);
592 if (Op
.getValueType() == MVT::i32
)
593 Result
= DAG
.getExtLoad(ISD::SEXTLOAD
, dl
, MVT::i64
, Chain
, DataPtr
,
596 Result
= DAG
.getLoad(Op
.getValueType(), dl
, Chain
, DataPtr
, NULL
, 0);
600 SDValue Chain
= Op
.getOperand(0);
601 SDValue DestP
= Op
.getOperand(1);
602 SDValue SrcP
= Op
.getOperand(2);
603 const Value
*DestS
= cast
<SrcValueSDNode
>(Op
.getOperand(3))->getValue();
604 const Value
*SrcS
= cast
<SrcValueSDNode
>(Op
.getOperand(4))->getValue();
606 SDValue Val
= DAG
.getLoad(getPointerTy(), dl
, Chain
, SrcP
, SrcS
, 0);
607 SDValue Result
= DAG
.getStore(Val
.getValue(1), dl
, Val
, DestP
, DestS
, 0);
608 SDValue NP
= DAG
.getNode(ISD::ADD
, dl
, MVT::i64
, SrcP
,
609 DAG
.getConstant(8, MVT::i64
));
610 Val
= DAG
.getExtLoad(ISD::SEXTLOAD
, dl
, MVT::i64
, Result
,
611 NP
, NULL
,0, MVT::i32
);
612 SDValue NPD
= DAG
.getNode(ISD::ADD
, dl
, MVT::i64
, DestP
,
613 DAG
.getConstant(8, MVT::i64
));
614 return DAG
.getTruncStore(Val
.getValue(1), dl
, Val
, NPD
, NULL
, 0, MVT::i32
);
617 SDValue Chain
= Op
.getOperand(0);
618 SDValue VAListP
= Op
.getOperand(1);
619 const Value
*VAListS
= cast
<SrcValueSDNode
>(Op
.getOperand(2))->getValue();
621 // vastart stores the address of the VarArgsBase and VarArgsOffset
622 SDValue FR
= DAG
.getFrameIndex(VarArgsBase
, MVT::i64
);
623 SDValue S1
= DAG
.getStore(Chain
, dl
, FR
, VAListP
, VAListS
, 0);
624 SDValue SA2
= DAG
.getNode(ISD::ADD
, dl
, MVT::i64
, VAListP
,
625 DAG
.getConstant(8, MVT::i64
));
626 return DAG
.getTruncStore(S1
, dl
, DAG
.getConstant(VarArgsOffset
, MVT::i64
),
627 SA2
, NULL
, 0, MVT::i32
);
629 case ISD::RETURNADDR
:
630 return DAG
.getNode(AlphaISD::GlobalRetAddr
, DebugLoc::getUnknownLoc(),
633 case ISD::FRAMEADDR
: break;
639 void AlphaTargetLowering::ReplaceNodeResults(SDNode
*N
,
640 SmallVectorImpl
<SDValue
>&Results
,
642 DebugLoc dl
= N
->getDebugLoc();
643 assert(N
->getValueType(0) == MVT::i32
&&
644 N
->getOpcode() == ISD::VAARG
&&
645 "Unknown node to custom promote!");
647 SDValue Chain
, DataPtr
;
648 LowerVAARG(N
, Chain
, DataPtr
, DAG
);
649 SDValue Res
= DAG
.getLoad(N
->getValueType(0), dl
, Chain
, DataPtr
, NULL
, 0);
650 Results
.push_back(Res
);
651 Results
.push_back(SDValue(Res
.getNode(), 1));
657 /// getConstraintType - Given a constraint letter, return the type of
658 /// constraint it is for this target.
659 AlphaTargetLowering::ConstraintType
660 AlphaTargetLowering::getConstraintType(const std::string
&Constraint
) const {
661 if (Constraint
.size() == 1) {
662 switch (Constraint
[0]) {
666 return C_RegisterClass
;
669 return TargetLowering::getConstraintType(Constraint
);
672 std::vector
<unsigned> AlphaTargetLowering::
673 getRegClassForInlineAsmConstraint(const std::string
&Constraint
,
675 if (Constraint
.size() == 1) {
676 switch (Constraint
[0]) {
677 default: break; // Unknown constriant letter
679 return make_vector
<unsigned>(Alpha::F0
, Alpha::F1
, Alpha::F2
,
680 Alpha::F3
, Alpha::F4
, Alpha::F5
,
681 Alpha::F6
, Alpha::F7
, Alpha::F8
,
682 Alpha::F9
, Alpha::F10
, Alpha::F11
,
683 Alpha::F12
, Alpha::F13
, Alpha::F14
,
684 Alpha::F15
, Alpha::F16
, Alpha::F17
,
685 Alpha::F18
, Alpha::F19
, Alpha::F20
,
686 Alpha::F21
, Alpha::F22
, Alpha::F23
,
687 Alpha::F24
, Alpha::F25
, Alpha::F26
,
688 Alpha::F27
, Alpha::F28
, Alpha::F29
,
689 Alpha::F30
, Alpha::F31
, 0);
691 return make_vector
<unsigned>(Alpha::R0
, Alpha::R1
, Alpha::R2
,
692 Alpha::R3
, Alpha::R4
, Alpha::R5
,
693 Alpha::R6
, Alpha::R7
, Alpha::R8
,
694 Alpha::R9
, Alpha::R10
, Alpha::R11
,
695 Alpha::R12
, Alpha::R13
, Alpha::R14
,
696 Alpha::R15
, Alpha::R16
, Alpha::R17
,
697 Alpha::R18
, Alpha::R19
, Alpha::R20
,
698 Alpha::R21
, Alpha::R22
, Alpha::R23
,
699 Alpha::R24
, Alpha::R25
, Alpha::R26
,
700 Alpha::R27
, Alpha::R28
, Alpha::R29
,
701 Alpha::R30
, Alpha::R31
, 0);
705 return std::vector
<unsigned>();
707 //===----------------------------------------------------------------------===//
708 // Other Lowering Code
709 //===----------------------------------------------------------------------===//
712 AlphaTargetLowering::EmitInstrWithCustomInserter(MachineInstr
*MI
,
713 MachineBasicBlock
*BB
) const {
714 const TargetInstrInfo
*TII
= getTargetMachine().getInstrInfo();
715 assert((MI
->getOpcode() == Alpha::CAS32
||
716 MI
->getOpcode() == Alpha::CAS64
||
717 MI
->getOpcode() == Alpha::LAS32
||
718 MI
->getOpcode() == Alpha::LAS64
||
719 MI
->getOpcode() == Alpha::SWAP32
||
720 MI
->getOpcode() == Alpha::SWAP64
) &&
721 "Unexpected instr type to insert");
723 bool is32
= MI
->getOpcode() == Alpha::CAS32
||
724 MI
->getOpcode() == Alpha::LAS32
||
725 MI
->getOpcode() == Alpha::SWAP32
;
727 //Load locked store conditional for atomic ops take on the same form
730 //do stuff (maybe branch to exit)
732 //test sc and maybe branck to start
734 const BasicBlock
*LLVM_BB
= BB
->getBasicBlock();
735 DebugLoc dl
= MI
->getDebugLoc();
736 MachineFunction::iterator It
= BB
;
739 MachineBasicBlock
*thisMBB
= BB
;
740 MachineFunction
*F
= BB
->getParent();
741 MachineBasicBlock
*llscMBB
= F
->CreateMachineBasicBlock(LLVM_BB
);
742 MachineBasicBlock
*sinkMBB
= F
->CreateMachineBasicBlock(LLVM_BB
);
744 sinkMBB
->transferSuccessors(thisMBB
);
746 F
->insert(It
, llscMBB
);
747 F
->insert(It
, sinkMBB
);
749 BuildMI(thisMBB
, dl
, TII
->get(Alpha::BR
)).addMBB(llscMBB
);
751 unsigned reg_res
= MI
->getOperand(0).getReg(),
752 reg_ptr
= MI
->getOperand(1).getReg(),
753 reg_v2
= MI
->getOperand(2).getReg(),
754 reg_store
= F
->getRegInfo().createVirtualRegister(&Alpha::GPRCRegClass
);
756 BuildMI(llscMBB
, dl
, TII
->get(is32
? Alpha::LDL_L
: Alpha::LDQ_L
),
757 reg_res
).addImm(0).addReg(reg_ptr
);
758 switch (MI
->getOpcode()) {
762 = F
->getRegInfo().createVirtualRegister(&Alpha::GPRCRegClass
);
763 BuildMI(llscMBB
, dl
, TII
->get(Alpha::CMPEQ
), reg_cmp
)
764 .addReg(reg_v2
).addReg(reg_res
);
765 BuildMI(llscMBB
, dl
, TII
->get(Alpha::BEQ
))
766 .addImm(0).addReg(reg_cmp
).addMBB(sinkMBB
);
767 BuildMI(llscMBB
, dl
, TII
->get(Alpha::BISr
), reg_store
)
768 .addReg(Alpha::R31
).addReg(MI
->getOperand(3).getReg());
773 BuildMI(llscMBB
, dl
,TII
->get(is32
? Alpha::ADDLr
: Alpha::ADDQr
), reg_store
)
774 .addReg(reg_res
).addReg(reg_v2
);
778 case Alpha::SWAP64
: {
779 BuildMI(llscMBB
, dl
, TII
->get(Alpha::BISr
), reg_store
)
780 .addReg(reg_v2
).addReg(reg_v2
);
784 BuildMI(llscMBB
, dl
, TII
->get(is32
? Alpha::STL_C
: Alpha::STQ_C
), reg_store
)
785 .addReg(reg_store
).addImm(0).addReg(reg_ptr
);
786 BuildMI(llscMBB
, dl
, TII
->get(Alpha::BEQ
))
787 .addImm(0).addReg(reg_store
).addMBB(llscMBB
);
788 BuildMI(llscMBB
, dl
, TII
->get(Alpha::BR
)).addMBB(sinkMBB
);
790 thisMBB
->addSuccessor(llscMBB
);
791 llscMBB
->addSuccessor(llscMBB
);
792 llscMBB
->addSuccessor(sinkMBB
);
793 F
->DeleteMachineInstr(MI
); // The pseudo instruction is gone now.
799 AlphaTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode
*GA
) const {
800 // The Alpha target isn't yet aware of offsets.