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/CallingConvLower.h"
17 #include "llvm/CodeGen/MachineFrameInfo.h"
18 #include "llvm/CodeGen/MachineFunction.h"
19 #include "llvm/CodeGen/MachineInstrBuilder.h"
20 #include "llvm/CodeGen/MachineRegisterInfo.h"
21 #include "llvm/CodeGen/SelectionDAG.h"
22 #include "llvm/CodeGen/MachineRegisterInfo.h"
23 #include "llvm/CodeGen/PseudoSourceValue.h"
24 #include "llvm/Target/TargetLoweringObjectFile.h"
25 #include "llvm/Constants.h"
26 #include "llvm/Function.h"
27 #include "llvm/Module.h"
28 #include "llvm/Intrinsics.h"
29 #include "llvm/Support/CommandLine.h"
30 #include "llvm/Support/ErrorHandling.h"
31 #include "llvm/Support/raw_ostream.h"
34 /// AddLiveIn - This helper function adds the specified physical register to the
35 /// MachineFunction as a live in value. It also creates a corresponding virtual
37 static unsigned AddLiveIn(MachineFunction
&MF
, unsigned PReg
,
38 TargetRegisterClass
*RC
) {
39 assert(RC
->contains(PReg
) && "Not the correct regclass!");
40 unsigned VReg
= MF
.getRegInfo().createVirtualRegister(RC
);
41 MF
.getRegInfo().addLiveIn(PReg
, VReg
);
45 AlphaTargetLowering::AlphaTargetLowering(TargetMachine
&TM
)
46 : TargetLowering(TM
, new TargetLoweringObjectFileELF()) {
47 // Set up the TargetLowering object.
48 //I am having problems with shr n i8 1
49 setShiftAmountType(MVT::i64
);
50 setBooleanContents(ZeroOrOneBooleanContent
);
52 setUsesGlobalOffsetTable(true);
54 addRegisterClass(MVT::i64
, Alpha::GPRCRegisterClass
);
55 addRegisterClass(MVT::f64
, Alpha::F8RCRegisterClass
);
56 addRegisterClass(MVT::f32
, Alpha::F4RCRegisterClass
);
58 // We want to custom lower some of our intrinsics.
59 setOperationAction(ISD::INTRINSIC_WO_CHAIN
, MVT::Other
, Custom
);
61 setLoadExtAction(ISD::EXTLOAD
, MVT::i1
, Promote
);
62 setLoadExtAction(ISD::EXTLOAD
, MVT::f32
, Expand
);
64 setLoadExtAction(ISD::ZEXTLOAD
, MVT::i1
, Promote
);
65 setLoadExtAction(ISD::ZEXTLOAD
, MVT::i32
, Expand
);
67 setLoadExtAction(ISD::SEXTLOAD
, MVT::i1
, Promote
);
68 setLoadExtAction(ISD::SEXTLOAD
, MVT::i8
, Expand
);
69 setLoadExtAction(ISD::SEXTLOAD
, MVT::i16
, Expand
);
71 setTruncStoreAction(MVT::f64
, MVT::f32
, Expand
);
73 // setOperationAction(ISD::BRIND, MVT::Other, Expand);
74 setOperationAction(ISD::BR_JT
, MVT::Other
, Expand
);
75 setOperationAction(ISD::BR_CC
, MVT::Other
, Expand
);
76 setOperationAction(ISD::SELECT_CC
, MVT::Other
, Expand
);
78 setOperationAction(ISD::SIGN_EXTEND_INREG
, MVT::i1
, Expand
);
80 setOperationAction(ISD::FREM
, MVT::f32
, Expand
);
81 setOperationAction(ISD::FREM
, MVT::f64
, Expand
);
83 setOperationAction(ISD::UINT_TO_FP
, MVT::i64
, Expand
);
84 setOperationAction(ISD::SINT_TO_FP
, MVT::i64
, Custom
);
85 setOperationAction(ISD::FP_TO_UINT
, MVT::i64
, Expand
);
86 setOperationAction(ISD::FP_TO_SINT
, MVT::i64
, Custom
);
88 if (!TM
.getSubtarget
<AlphaSubtarget
>().hasCT()) {
89 setOperationAction(ISD::CTPOP
, MVT::i64
, Expand
);
90 setOperationAction(ISD::CTTZ
, MVT::i64
, Expand
);
91 setOperationAction(ISD::CTLZ
, MVT::i64
, Expand
);
93 setOperationAction(ISD::BSWAP
, MVT::i64
, Expand
);
94 setOperationAction(ISD::ROTL
, MVT::i64
, Expand
);
95 setOperationAction(ISD::ROTR
, MVT::i64
, Expand
);
97 setOperationAction(ISD::SREM
, MVT::i64
, Custom
);
98 setOperationAction(ISD::UREM
, MVT::i64
, Custom
);
99 setOperationAction(ISD::SDIV
, MVT::i64
, Custom
);
100 setOperationAction(ISD::UDIV
, MVT::i64
, Custom
);
102 setOperationAction(ISD::ADDC
, MVT::i64
, Expand
);
103 setOperationAction(ISD::ADDE
, MVT::i64
, Expand
);
104 setOperationAction(ISD::SUBC
, MVT::i64
, Expand
);
105 setOperationAction(ISD::SUBE
, MVT::i64
, Expand
);
107 setOperationAction(ISD::UMUL_LOHI
, MVT::i64
, Expand
);
108 setOperationAction(ISD::SMUL_LOHI
, MVT::i64
, Expand
);
110 setOperationAction(ISD::SRL_PARTS
, MVT::i64
, Custom
);
111 setOperationAction(ISD::SRA_PARTS
, MVT::i64
, Expand
);
112 setOperationAction(ISD::SHL_PARTS
, MVT::i64
, Expand
);
114 // We don't support sin/cos/sqrt/pow
115 setOperationAction(ISD::FSIN
, MVT::f64
, Expand
);
116 setOperationAction(ISD::FCOS
, MVT::f64
, Expand
);
117 setOperationAction(ISD::FSIN
, MVT::f32
, Expand
);
118 setOperationAction(ISD::FCOS
, MVT::f32
, Expand
);
120 setOperationAction(ISD::FSQRT
, MVT::f64
, Expand
);
121 setOperationAction(ISD::FSQRT
, MVT::f32
, Expand
);
123 setOperationAction(ISD::FPOW
, MVT::f32
, Expand
);
124 setOperationAction(ISD::FPOW
, MVT::f64
, Expand
);
126 setOperationAction(ISD::SETCC
, MVT::f32
, Promote
);
128 setOperationAction(ISD::BIT_CONVERT
, MVT::f32
, Promote
);
130 // We don't have line number support yet.
131 setOperationAction(ISD::DBG_STOPPOINT
, MVT::Other
, Expand
);
132 setOperationAction(ISD::DEBUG_LOC
, MVT::Other
, Expand
);
133 setOperationAction(ISD::DBG_LABEL
, MVT::Other
, Expand
);
134 setOperationAction(ISD::EH_LABEL
, MVT::Other
, Expand
);
136 // Not implemented yet.
137 setOperationAction(ISD::STACKSAVE
, MVT::Other
, Expand
);
138 setOperationAction(ISD::STACKRESTORE
, MVT::Other
, Expand
);
139 setOperationAction(ISD::DYNAMIC_STACKALLOC
, MVT::i64
, Expand
);
141 // We want to legalize GlobalAddress and ConstantPool and
142 // ExternalSymbols nodes into the appropriate instructions to
143 // materialize the address.
144 setOperationAction(ISD::GlobalAddress
, MVT::i64
, Custom
);
145 setOperationAction(ISD::ConstantPool
, MVT::i64
, Custom
);
146 setOperationAction(ISD::ExternalSymbol
, MVT::i64
, Custom
);
147 setOperationAction(ISD::GlobalTLSAddress
, MVT::i64
, Custom
);
149 setOperationAction(ISD::VASTART
, MVT::Other
, Custom
);
150 setOperationAction(ISD::VAEND
, MVT::Other
, Expand
);
151 setOperationAction(ISD::VACOPY
, MVT::Other
, Custom
);
152 setOperationAction(ISD::VAARG
, MVT::Other
, Custom
);
153 setOperationAction(ISD::VAARG
, MVT::i32
, Custom
);
155 setOperationAction(ISD::JumpTable
, MVT::i64
, Custom
);
156 setOperationAction(ISD::JumpTable
, MVT::i32
, Custom
);
158 setStackPointerRegisterToSaveRestore(Alpha::R30
);
160 addLegalFPImmediate(APFloat(+0.0)); //F31
161 addLegalFPImmediate(APFloat(+0.0f
)); //F31
162 addLegalFPImmediate(APFloat(-0.0)); //-F31
163 addLegalFPImmediate(APFloat(-0.0f
)); //-F31
166 setJumpBufAlignment(16);
168 computeRegisterProperties();
171 MVT::SimpleValueType
AlphaTargetLowering::getSetCCResultType(EVT VT
) const {
175 const char *AlphaTargetLowering::getTargetNodeName(unsigned Opcode
) const {
178 case AlphaISD::CVTQT_
: return "Alpha::CVTQT_";
179 case AlphaISD::CVTQS_
: return "Alpha::CVTQS_";
180 case AlphaISD::CVTTQ_
: return "Alpha::CVTTQ_";
181 case AlphaISD::GPRelHi
: return "Alpha::GPRelHi";
182 case AlphaISD::GPRelLo
: return "Alpha::GPRelLo";
183 case AlphaISD::RelLit
: return "Alpha::RelLit";
184 case AlphaISD::GlobalRetAddr
: return "Alpha::GlobalRetAddr";
185 case AlphaISD::CALL
: return "Alpha::CALL";
186 case AlphaISD::DivCall
: return "Alpha::DivCall";
187 case AlphaISD::RET_FLAG
: return "Alpha::RET_FLAG";
188 case AlphaISD::COND_BRANCH_I
: return "Alpha::COND_BRANCH_I";
189 case AlphaISD::COND_BRANCH_F
: return "Alpha::COND_BRANCH_F";
193 /// getFunctionAlignment - Return the Log2 alignment of this function.
194 unsigned AlphaTargetLowering::getFunctionAlignment(const Function
*F
) const {
198 static SDValue
LowerJumpTable(SDValue Op
, SelectionDAG
&DAG
) {
199 EVT PtrVT
= Op
.getValueType();
200 JumpTableSDNode
*JT
= cast
<JumpTableSDNode
>(Op
);
201 SDValue JTI
= DAG
.getTargetJumpTable(JT
->getIndex(), PtrVT
);
202 SDValue Zero
= DAG
.getConstant(0, PtrVT
);
203 // FIXME there isn't really any debug info here
204 DebugLoc dl
= Op
.getDebugLoc();
206 SDValue Hi
= DAG
.getNode(AlphaISD::GPRelHi
, dl
, MVT::i64
, JTI
,
207 DAG
.getGLOBAL_OFFSET_TABLE(MVT::i64
));
208 SDValue Lo
= DAG
.getNode(AlphaISD::GPRelLo
, dl
, MVT::i64
, JTI
, Hi
);
212 //http://www.cs.arizona.edu/computer.help/policy/DIGITAL_unix/
213 //AA-PY8AC-TET1_html/callCH3.html#BLOCK21
215 //For now, just use variable size stack frame format
217 //In a standard call, the first six items are passed in registers $16
218 //- $21 and/or registers $f16 - $f21. (See Section 4.1.2 for details
219 //of argument-to-register correspondence.) The remaining items are
220 //collected in a memory argument list that is a naturally aligned
221 //array of quadwords. In a standard call, this list, if present, must
222 //be passed at 0(SP).
223 //7 ... n 0(SP) ... (n-7)*8(SP)
231 #include "AlphaGenCallingConv.inc"
234 AlphaTargetLowering::LowerCall(SDValue Chain
, SDValue Callee
,
235 CallingConv::ID CallConv
, bool isVarArg
,
237 const SmallVectorImpl
<ISD::OutputArg
> &Outs
,
238 const SmallVectorImpl
<ISD::InputArg
> &Ins
,
239 DebugLoc dl
, SelectionDAG
&DAG
,
240 SmallVectorImpl
<SDValue
> &InVals
) {
242 // Analyze operands of the call, assigning locations to each operand.
243 SmallVector
<CCValAssign
, 16> ArgLocs
;
244 CCState
CCInfo(CallConv
, isVarArg
, getTargetMachine(),
245 ArgLocs
, *DAG
.getContext());
247 CCInfo
.AnalyzeCallOperands(Outs
, CC_Alpha
);
249 // Get a count of how many bytes are to be pushed on the stack.
250 unsigned NumBytes
= CCInfo
.getNextStackOffset();
252 Chain
= DAG
.getCALLSEQ_START(Chain
, DAG
.getConstant(NumBytes
,
253 getPointerTy(), true));
255 SmallVector
<std::pair
<unsigned, SDValue
>, 4> RegsToPass
;
256 SmallVector
<SDValue
, 12> MemOpChains
;
259 // Walk the register/memloc assignments, inserting copies/loads.
260 for (unsigned i
= 0, e
= ArgLocs
.size(); i
!= e
; ++i
) {
261 CCValAssign
&VA
= ArgLocs
[i
];
263 SDValue Arg
= Outs
[i
].Val
;
265 // Promote the value if needed.
266 switch (VA
.getLocInfo()) {
267 default: assert(0 && "Unknown loc info!");
268 case CCValAssign::Full
: break;
269 case CCValAssign::SExt
:
270 Arg
= DAG
.getNode(ISD::SIGN_EXTEND
, dl
, VA
.getLocVT(), Arg
);
272 case CCValAssign::ZExt
:
273 Arg
= DAG
.getNode(ISD::ZERO_EXTEND
, dl
, VA
.getLocVT(), Arg
);
275 case CCValAssign::AExt
:
276 Arg
= DAG
.getNode(ISD::ANY_EXTEND
, dl
, VA
.getLocVT(), Arg
);
280 // Arguments that can be passed on register must be kept at RegsToPass
283 RegsToPass
.push_back(std::make_pair(VA
.getLocReg(), Arg
));
285 assert(VA
.isMemLoc());
287 if (StackPtr
.getNode() == 0)
288 StackPtr
= DAG
.getCopyFromReg(Chain
, dl
, Alpha::R30
, MVT::i64
);
290 SDValue PtrOff
= DAG
.getNode(ISD::ADD
, dl
, getPointerTy(),
292 DAG
.getIntPtrConstant(VA
.getLocMemOffset()));
294 MemOpChains
.push_back(DAG
.getStore(Chain
, dl
, Arg
, PtrOff
,
295 PseudoSourceValue::getStack(), 0));
299 // Transform all store nodes into one single node because all store nodes are
300 // independent of each other.
301 if (!MemOpChains
.empty())
302 Chain
= DAG
.getNode(ISD::TokenFactor
, dl
, MVT::Other
,
303 &MemOpChains
[0], MemOpChains
.size());
305 // Build a sequence of copy-to-reg nodes chained together with token chain and
306 // flag operands which copy the outgoing args into registers. The InFlag in
307 // necessary since all emited instructions must be stuck together.
309 for (unsigned i
= 0, e
= RegsToPass
.size(); i
!= e
; ++i
) {
310 Chain
= DAG
.getCopyToReg(Chain
, dl
, RegsToPass
[i
].first
,
311 RegsToPass
[i
].second
, InFlag
);
312 InFlag
= Chain
.getValue(1);
315 // Returns a chain & a flag for retval copy to use.
316 SDVTList NodeTys
= DAG
.getVTList(MVT::Other
, MVT::Flag
);
317 SmallVector
<SDValue
, 8> Ops
;
318 Ops
.push_back(Chain
);
319 Ops
.push_back(Callee
);
321 // Add argument registers to the end of the list so that they are
322 // known live into the call.
323 for (unsigned i
= 0, e
= RegsToPass
.size(); i
!= e
; ++i
)
324 Ops
.push_back(DAG
.getRegister(RegsToPass
[i
].first
,
325 RegsToPass
[i
].second
.getValueType()));
327 if (InFlag
.getNode())
328 Ops
.push_back(InFlag
);
330 Chain
= DAG
.getNode(AlphaISD::CALL
, dl
, NodeTys
, &Ops
[0], Ops
.size());
331 InFlag
= Chain
.getValue(1);
333 // Create the CALLSEQ_END node.
334 Chain
= DAG
.getCALLSEQ_END(Chain
,
335 DAG
.getConstant(NumBytes
, getPointerTy(), true),
336 DAG
.getConstant(0, getPointerTy(), true),
338 InFlag
= Chain
.getValue(1);
340 // Handle result values, copying them out of physregs into vregs that we
342 return LowerCallResult(Chain
, InFlag
, CallConv
, isVarArg
,
343 Ins
, dl
, DAG
, InVals
);
346 /// LowerCallResult - Lower the result values of a call into the
347 /// appropriate copies out of appropriate physical registers.
350 AlphaTargetLowering::LowerCallResult(SDValue Chain
, SDValue InFlag
,
351 CallingConv::ID CallConv
, bool isVarArg
,
352 const SmallVectorImpl
<ISD::InputArg
> &Ins
,
353 DebugLoc dl
, SelectionDAG
&DAG
,
354 SmallVectorImpl
<SDValue
> &InVals
) {
356 // Assign locations to each value returned by this call.
357 SmallVector
<CCValAssign
, 16> RVLocs
;
358 CCState
CCInfo(CallConv
, isVarArg
, getTargetMachine(), RVLocs
,
361 CCInfo
.AnalyzeCallResult(Ins
, RetCC_Alpha
);
363 // Copy all of the result registers out of their specified physreg.
364 for (unsigned i
= 0; i
!= RVLocs
.size(); ++i
) {
365 CCValAssign
&VA
= RVLocs
[i
];
367 Chain
= DAG
.getCopyFromReg(Chain
, dl
, VA
.getLocReg(),
368 VA
.getLocVT(), InFlag
).getValue(1);
369 SDValue RetValue
= Chain
.getValue(0);
370 InFlag
= Chain
.getValue(2);
372 // If this is an 8/16/32-bit value, it is really passed promoted to 64
373 // bits. Insert an assert[sz]ext to capture this, then truncate to the
375 if (VA
.getLocInfo() == CCValAssign::SExt
)
376 RetValue
= DAG
.getNode(ISD::AssertSext
, dl
, VA
.getLocVT(), RetValue
,
377 DAG
.getValueType(VA
.getValVT()));
378 else if (VA
.getLocInfo() == CCValAssign::ZExt
)
379 RetValue
= DAG
.getNode(ISD::AssertZext
, dl
, VA
.getLocVT(), RetValue
,
380 DAG
.getValueType(VA
.getValVT()));
382 if (VA
.getLocInfo() != CCValAssign::Full
)
383 RetValue
= DAG
.getNode(ISD::TRUNCATE
, dl
, VA
.getValVT(), RetValue
);
385 InVals
.push_back(RetValue
);
392 AlphaTargetLowering::LowerFormalArguments(SDValue Chain
,
393 CallingConv::ID CallConv
, bool isVarArg
,
394 const SmallVectorImpl
<ISD::InputArg
>
396 DebugLoc dl
, SelectionDAG
&DAG
,
397 SmallVectorImpl
<SDValue
> &InVals
) {
399 MachineFunction
&MF
= DAG
.getMachineFunction();
400 MachineFrameInfo
*MFI
= MF
.getFrameInfo();
402 unsigned args_int
[] = {
403 Alpha::R16
, Alpha::R17
, Alpha::R18
, Alpha::R19
, Alpha::R20
, Alpha::R21
};
404 unsigned args_float
[] = {
405 Alpha::F16
, Alpha::F17
, Alpha::F18
, Alpha::F19
, Alpha::F20
, Alpha::F21
};
407 for (unsigned ArgNo
= 0, e
= Ins
.size(); ArgNo
!= e
; ++ArgNo
) {
409 EVT ObjectVT
= Ins
[ArgNo
].VT
;
413 switch (ObjectVT
.getSimpleVT().SimpleTy
) {
415 assert(false && "Invalid value type!");
417 args_float
[ArgNo
] = AddLiveIn(MF
, args_float
[ArgNo
],
418 &Alpha::F8RCRegClass
);
419 ArgVal
= DAG
.getCopyFromReg(Chain
, dl
, args_float
[ArgNo
], ObjectVT
);
422 args_float
[ArgNo
] = AddLiveIn(MF
, args_float
[ArgNo
],
423 &Alpha::F4RCRegClass
);
424 ArgVal
= DAG
.getCopyFromReg(Chain
, dl
, args_float
[ArgNo
], ObjectVT
);
427 args_int
[ArgNo
] = AddLiveIn(MF
, args_int
[ArgNo
],
428 &Alpha::GPRCRegClass
);
429 ArgVal
= DAG
.getCopyFromReg(Chain
, dl
, args_int
[ArgNo
], MVT::i64
);
433 // Create the frame index object for this incoming parameter...
434 int FI
= MFI
->CreateFixedObject(8, 8 * (ArgNo
- 6));
436 // Create the SelectionDAG nodes corresponding to a load
437 //from this parameter
438 SDValue FIN
= DAG
.getFrameIndex(FI
, MVT::i64
);
439 ArgVal
= DAG
.getLoad(ObjectVT
, dl
, Chain
, FIN
, NULL
, 0);
441 InVals
.push_back(ArgVal
);
444 // If the functions takes variable number of arguments, copy all regs to stack
446 VarArgsOffset
= Ins
.size() * 8;
447 std::vector
<SDValue
> LS
;
448 for (int i
= 0; i
< 6; ++i
) {
449 if (TargetRegisterInfo::isPhysicalRegister(args_int
[i
]))
450 args_int
[i
] = AddLiveIn(MF
, args_int
[i
], &Alpha::GPRCRegClass
);
451 SDValue argt
= DAG
.getCopyFromReg(Chain
, dl
, args_int
[i
], MVT::i64
);
452 int FI
= MFI
->CreateFixedObject(8, -8 * (6 - i
));
453 if (i
== 0) VarArgsBase
= FI
;
454 SDValue SDFI
= DAG
.getFrameIndex(FI
, MVT::i64
);
455 LS
.push_back(DAG
.getStore(Chain
, dl
, argt
, SDFI
, NULL
, 0));
457 if (TargetRegisterInfo::isPhysicalRegister(args_float
[i
]))
458 args_float
[i
] = AddLiveIn(MF
, args_float
[i
], &Alpha::F8RCRegClass
);
459 argt
= DAG
.getCopyFromReg(Chain
, dl
, args_float
[i
], MVT::f64
);
460 FI
= MFI
->CreateFixedObject(8, - 8 * (12 - i
));
461 SDFI
= DAG
.getFrameIndex(FI
, MVT::i64
);
462 LS
.push_back(DAG
.getStore(Chain
, dl
, argt
, SDFI
, NULL
, 0));
465 //Set up a token factor with all the stack traffic
466 Chain
= DAG
.getNode(ISD::TokenFactor
, dl
, MVT::Other
, &LS
[0], LS
.size());
473 AlphaTargetLowering::LowerReturn(SDValue Chain
,
474 CallingConv::ID CallConv
, bool isVarArg
,
475 const SmallVectorImpl
<ISD::OutputArg
> &Outs
,
476 DebugLoc dl
, SelectionDAG
&DAG
) {
478 SDValue Copy
= DAG
.getCopyToReg(Chain
, dl
, Alpha::R26
,
479 DAG
.getNode(AlphaISD::GlobalRetAddr
,
480 DebugLoc::getUnknownLoc(),
483 switch (Outs
.size()) {
485 llvm_unreachable("Do not know how to return this many arguments!");
488 //return SDValue(); // ret void is legal
490 EVT ArgVT
= Outs
[0].Val
.getValueType();
492 if (ArgVT
.isInteger())
495 assert(ArgVT
.isFloatingPoint());
498 Copy
= DAG
.getCopyToReg(Copy
, dl
, ArgReg
,
499 Outs
[0].Val
, Copy
.getValue(1));
500 if (DAG
.getMachineFunction().getRegInfo().liveout_empty())
501 DAG
.getMachineFunction().getRegInfo().addLiveOut(ArgReg
);
505 EVT ArgVT
= Outs
[0].Val
.getValueType();
506 unsigned ArgReg1
, ArgReg2
;
507 if (ArgVT
.isInteger()) {
511 assert(ArgVT
.isFloatingPoint());
515 Copy
= DAG
.getCopyToReg(Copy
, dl
, ArgReg1
,
516 Outs
[0].Val
, Copy
.getValue(1));
517 if (std::find(DAG
.getMachineFunction().getRegInfo().liveout_begin(),
518 DAG
.getMachineFunction().getRegInfo().liveout_end(), ArgReg1
)
519 == DAG
.getMachineFunction().getRegInfo().liveout_end())
520 DAG
.getMachineFunction().getRegInfo().addLiveOut(ArgReg1
);
521 Copy
= DAG
.getCopyToReg(Copy
, dl
, ArgReg2
,
522 Outs
[1].Val
, Copy
.getValue(1));
523 if (std::find(DAG
.getMachineFunction().getRegInfo().liveout_begin(),
524 DAG
.getMachineFunction().getRegInfo().liveout_end(), ArgReg2
)
525 == DAG
.getMachineFunction().getRegInfo().liveout_end())
526 DAG
.getMachineFunction().getRegInfo().addLiveOut(ArgReg2
);
530 return DAG
.getNode(AlphaISD::RET_FLAG
, dl
,
531 MVT::Other
, Copy
, Copy
.getValue(1));
534 void AlphaTargetLowering::LowerVAARG(SDNode
*N
, SDValue
&Chain
,
535 SDValue
&DataPtr
, SelectionDAG
&DAG
) {
536 Chain
= N
->getOperand(0);
537 SDValue VAListP
= N
->getOperand(1);
538 const Value
*VAListS
= cast
<SrcValueSDNode
>(N
->getOperand(2))->getValue();
539 DebugLoc dl
= N
->getDebugLoc();
541 SDValue Base
= DAG
.getLoad(MVT::i64
, dl
, Chain
, VAListP
, VAListS
, 0);
542 SDValue Tmp
= DAG
.getNode(ISD::ADD
, dl
, MVT::i64
, VAListP
,
543 DAG
.getConstant(8, MVT::i64
));
544 SDValue Offset
= DAG
.getExtLoad(ISD::SEXTLOAD
, dl
, MVT::i64
, Base
.getValue(1),
545 Tmp
, NULL
, 0, MVT::i32
);
546 DataPtr
= DAG
.getNode(ISD::ADD
, dl
, MVT::i64
, Base
, Offset
);
547 if (N
->getValueType(0).isFloatingPoint())
549 //if fp && Offset < 6*8, then subtract 6*8 from DataPtr
550 SDValue FPDataPtr
= DAG
.getNode(ISD::SUB
, dl
, MVT::i64
, DataPtr
,
551 DAG
.getConstant(8*6, MVT::i64
));
552 SDValue CC
= DAG
.getSetCC(dl
, MVT::i64
, Offset
,
553 DAG
.getConstant(8*6, MVT::i64
), ISD::SETLT
);
554 DataPtr
= DAG
.getNode(ISD::SELECT
, dl
, MVT::i64
, CC
, FPDataPtr
, DataPtr
);
557 SDValue NewOffset
= DAG
.getNode(ISD::ADD
, dl
, MVT::i64
, Offset
,
558 DAG
.getConstant(8, MVT::i64
));
559 Chain
= DAG
.getTruncStore(Offset
.getValue(1), dl
, NewOffset
, Tmp
, NULL
, 0,
563 /// LowerOperation - Provide custom lowering hooks for some operations.
565 SDValue
AlphaTargetLowering::LowerOperation(SDValue Op
, SelectionDAG
&DAG
) {
566 DebugLoc dl
= Op
.getDebugLoc();
567 switch (Op
.getOpcode()) {
568 default: llvm_unreachable("Wasn't expecting to be able to lower this!");
569 case ISD::JumpTable
: return LowerJumpTable(Op
, DAG
);
571 case ISD::INTRINSIC_WO_CHAIN
: {
572 unsigned IntNo
= cast
<ConstantSDNode
>(Op
.getOperand(0))->getZExtValue();
574 default: break; // Don't custom lower most intrinsics.
575 case Intrinsic::alpha_umulh
:
576 return DAG
.getNode(ISD::MULHU
, dl
, MVT::i64
,
577 Op
.getOperand(1), Op
.getOperand(2));
581 case ISD::SRL_PARTS
: {
582 SDValue ShOpLo
= Op
.getOperand(0);
583 SDValue ShOpHi
= Op
.getOperand(1);
584 SDValue ShAmt
= Op
.getOperand(2);
585 SDValue bm
= DAG
.getNode(ISD::SUB
, dl
, MVT::i64
,
586 DAG
.getConstant(64, MVT::i64
), ShAmt
);
587 SDValue BMCC
= DAG
.getSetCC(dl
, MVT::i64
, bm
,
588 DAG
.getConstant(0, MVT::i64
), ISD::SETLE
);
589 // if 64 - shAmt <= 0
590 SDValue Hi_Neg
= DAG
.getConstant(0, MVT::i64
);
591 SDValue ShAmt_Neg
= DAG
.getNode(ISD::SUB
, dl
, MVT::i64
,
592 DAG
.getConstant(0, MVT::i64
), bm
);
593 SDValue Lo_Neg
= DAG
.getNode(ISD::SRL
, dl
, MVT::i64
, ShOpHi
, ShAmt_Neg
);
595 SDValue carries
= DAG
.getNode(ISD::SHL
, dl
, MVT::i64
, ShOpHi
, bm
);
596 SDValue Hi_Pos
= DAG
.getNode(ISD::SRL
, dl
, MVT::i64
, ShOpHi
, ShAmt
);
597 SDValue Lo_Pos
= DAG
.getNode(ISD::SRL
, dl
, MVT::i64
, ShOpLo
, ShAmt
);
598 Lo_Pos
= DAG
.getNode(ISD::OR
, dl
, MVT::i64
, Lo_Pos
, carries
);
600 SDValue Hi
= DAG
.getNode(ISD::SELECT
, dl
, MVT::i64
, BMCC
, Hi_Neg
, Hi_Pos
);
601 SDValue Lo
= DAG
.getNode(ISD::SELECT
, dl
, MVT::i64
, BMCC
, Lo_Neg
, Lo_Pos
);
602 SDValue Ops
[2] = { Lo
, Hi
};
603 return DAG
.getMergeValues(Ops
, 2, dl
);
605 // case ISD::SRA_PARTS:
607 // case ISD::SHL_PARTS:
610 case ISD::SINT_TO_FP
: {
611 assert(Op
.getOperand(0).getValueType() == MVT::i64
&&
612 "Unhandled SINT_TO_FP type in custom expander!");
614 bool isDouble
= Op
.getValueType() == MVT::f64
;
615 LD
= DAG
.getNode(ISD::BIT_CONVERT
, dl
, MVT::f64
, Op
.getOperand(0));
616 SDValue FP
= DAG
.getNode(isDouble
?AlphaISD::CVTQT_
:AlphaISD::CVTQS_
, dl
,
617 isDouble
?MVT::f64
:MVT::f32
, LD
);
620 case ISD::FP_TO_SINT
: {
621 bool isDouble
= Op
.getOperand(0).getValueType() == MVT::f64
;
622 SDValue src
= Op
.getOperand(0);
624 if (!isDouble
) //Promote
625 src
= DAG
.getNode(ISD::FP_EXTEND
, dl
, MVT::f64
, src
);
627 src
= DAG
.getNode(AlphaISD::CVTTQ_
, dl
, MVT::f64
, src
);
629 return DAG
.getNode(ISD::BIT_CONVERT
, dl
, MVT::i64
, src
);
631 case ISD::ConstantPool
: {
632 ConstantPoolSDNode
*CP
= cast
<ConstantPoolSDNode
>(Op
);
633 Constant
*C
= CP
->getConstVal();
634 SDValue CPI
= DAG
.getTargetConstantPool(C
, MVT::i64
, CP
->getAlignment());
635 // FIXME there isn't really any debug info here
637 SDValue Hi
= DAG
.getNode(AlphaISD::GPRelHi
, dl
, MVT::i64
, CPI
,
638 DAG
.getGLOBAL_OFFSET_TABLE(MVT::i64
));
639 SDValue Lo
= DAG
.getNode(AlphaISD::GPRelLo
, dl
, MVT::i64
, CPI
, Hi
);
642 case ISD::GlobalTLSAddress
:
643 llvm_unreachable("TLS not implemented for Alpha.");
644 case ISD::GlobalAddress
: {
645 GlobalAddressSDNode
*GSDN
= cast
<GlobalAddressSDNode
>(Op
);
646 GlobalValue
*GV
= GSDN
->getGlobal();
647 SDValue GA
= DAG
.getTargetGlobalAddress(GV
, MVT::i64
, GSDN
->getOffset());
648 // FIXME there isn't really any debug info here
650 // if (!GV->hasWeakLinkage() && !GV->isDeclaration() && !GV->hasLinkOnceLinkage()) {
651 if (GV
->hasLocalLinkage()) {
652 SDValue Hi
= DAG
.getNode(AlphaISD::GPRelHi
, dl
, MVT::i64
, GA
,
653 DAG
.getGLOBAL_OFFSET_TABLE(MVT::i64
));
654 SDValue Lo
= DAG
.getNode(AlphaISD::GPRelLo
, dl
, MVT::i64
, GA
, Hi
);
657 return DAG
.getNode(AlphaISD::RelLit
, dl
, MVT::i64
, GA
,
658 DAG
.getGLOBAL_OFFSET_TABLE(MVT::i64
));
660 case ISD::ExternalSymbol
: {
661 return DAG
.getNode(AlphaISD::RelLit
, dl
, MVT::i64
,
662 DAG
.getTargetExternalSymbol(cast
<ExternalSymbolSDNode
>(Op
)
663 ->getSymbol(), MVT::i64
),
664 DAG
.getGLOBAL_OFFSET_TABLE(MVT::i64
));
669 //Expand only on constant case
670 if (Op
.getOperand(1).getOpcode() == ISD::Constant
) {
671 EVT VT
= Op
.getNode()->getValueType(0);
672 SDValue Tmp1
= Op
.getNode()->getOpcode() == ISD::UREM
?
673 BuildUDIV(Op
.getNode(), DAG
, NULL
) :
674 BuildSDIV(Op
.getNode(), DAG
, NULL
);
675 Tmp1
= DAG
.getNode(ISD::MUL
, dl
, VT
, Tmp1
, Op
.getOperand(1));
676 Tmp1
= DAG
.getNode(ISD::SUB
, dl
, VT
, Op
.getOperand(0), Tmp1
);
682 if (Op
.getValueType().isInteger()) {
683 if (Op
.getOperand(1).getOpcode() == ISD::Constant
)
684 return Op
.getOpcode() == ISD::SDIV
? BuildSDIV(Op
.getNode(), DAG
, NULL
)
685 : BuildUDIV(Op
.getNode(), DAG
, NULL
);
686 const char* opstr
= 0;
687 switch (Op
.getOpcode()) {
688 case ISD::UREM
: opstr
= "__remqu"; break;
689 case ISD::SREM
: opstr
= "__remq"; break;
690 case ISD::UDIV
: opstr
= "__divqu"; break;
691 case ISD::SDIV
: opstr
= "__divq"; break;
693 SDValue Tmp1
= Op
.getOperand(0),
694 Tmp2
= Op
.getOperand(1),
695 Addr
= DAG
.getExternalSymbol(opstr
, MVT::i64
);
696 return DAG
.getNode(AlphaISD::DivCall
, dl
, MVT::i64
, Addr
, Tmp1
, Tmp2
);
701 SDValue Chain
, DataPtr
;
702 LowerVAARG(Op
.getNode(), Chain
, DataPtr
, DAG
);
705 if (Op
.getValueType() == MVT::i32
)
706 Result
= DAG
.getExtLoad(ISD::SEXTLOAD
, dl
, MVT::i64
, Chain
, DataPtr
,
709 Result
= DAG
.getLoad(Op
.getValueType(), dl
, Chain
, DataPtr
, NULL
, 0);
713 SDValue Chain
= Op
.getOperand(0);
714 SDValue DestP
= Op
.getOperand(1);
715 SDValue SrcP
= Op
.getOperand(2);
716 const Value
*DestS
= cast
<SrcValueSDNode
>(Op
.getOperand(3))->getValue();
717 const Value
*SrcS
= cast
<SrcValueSDNode
>(Op
.getOperand(4))->getValue();
719 SDValue Val
= DAG
.getLoad(getPointerTy(), dl
, Chain
, SrcP
, SrcS
, 0);
720 SDValue Result
= DAG
.getStore(Val
.getValue(1), dl
, Val
, DestP
, DestS
, 0);
721 SDValue NP
= DAG
.getNode(ISD::ADD
, dl
, MVT::i64
, SrcP
,
722 DAG
.getConstant(8, MVT::i64
));
723 Val
= DAG
.getExtLoad(ISD::SEXTLOAD
, dl
, MVT::i64
, Result
,
724 NP
, NULL
,0, MVT::i32
);
725 SDValue NPD
= DAG
.getNode(ISD::ADD
, dl
, MVT::i64
, DestP
,
726 DAG
.getConstant(8, MVT::i64
));
727 return DAG
.getTruncStore(Val
.getValue(1), dl
, Val
, NPD
, NULL
, 0, MVT::i32
);
730 SDValue Chain
= Op
.getOperand(0);
731 SDValue VAListP
= Op
.getOperand(1);
732 const Value
*VAListS
= cast
<SrcValueSDNode
>(Op
.getOperand(2))->getValue();
734 // vastart stores the address of the VarArgsBase and VarArgsOffset
735 SDValue FR
= DAG
.getFrameIndex(VarArgsBase
, MVT::i64
);
736 SDValue S1
= DAG
.getStore(Chain
, dl
, FR
, VAListP
, VAListS
, 0);
737 SDValue SA2
= DAG
.getNode(ISD::ADD
, dl
, MVT::i64
, VAListP
,
738 DAG
.getConstant(8, MVT::i64
));
739 return DAG
.getTruncStore(S1
, dl
, DAG
.getConstant(VarArgsOffset
, MVT::i64
),
740 SA2
, NULL
, 0, MVT::i32
);
742 case ISD::RETURNADDR
:
743 return DAG
.getNode(AlphaISD::GlobalRetAddr
, DebugLoc::getUnknownLoc(),
746 case ISD::FRAMEADDR
: break;
752 void AlphaTargetLowering::ReplaceNodeResults(SDNode
*N
,
753 SmallVectorImpl
<SDValue
>&Results
,
755 DebugLoc dl
= N
->getDebugLoc();
756 assert(N
->getValueType(0) == MVT::i32
&&
757 N
->getOpcode() == ISD::VAARG
&&
758 "Unknown node to custom promote!");
760 SDValue Chain
, DataPtr
;
761 LowerVAARG(N
, Chain
, DataPtr
, DAG
);
762 SDValue Res
= DAG
.getLoad(N
->getValueType(0), dl
, Chain
, DataPtr
, NULL
, 0);
763 Results
.push_back(Res
);
764 Results
.push_back(SDValue(Res
.getNode(), 1));
770 /// getConstraintType - Given a constraint letter, return the type of
771 /// constraint it is for this target.
772 AlphaTargetLowering::ConstraintType
773 AlphaTargetLowering::getConstraintType(const std::string
&Constraint
) const {
774 if (Constraint
.size() == 1) {
775 switch (Constraint
[0]) {
779 return C_RegisterClass
;
782 return TargetLowering::getConstraintType(Constraint
);
785 std::vector
<unsigned> AlphaTargetLowering::
786 getRegClassForInlineAsmConstraint(const std::string
&Constraint
,
788 if (Constraint
.size() == 1) {
789 switch (Constraint
[0]) {
790 default: break; // Unknown constriant letter
792 return make_vector
<unsigned>(Alpha::F0
, Alpha::F1
, Alpha::F2
,
793 Alpha::F3
, Alpha::F4
, Alpha::F5
,
794 Alpha::F6
, Alpha::F7
, Alpha::F8
,
795 Alpha::F9
, Alpha::F10
, Alpha::F11
,
796 Alpha::F12
, Alpha::F13
, Alpha::F14
,
797 Alpha::F15
, Alpha::F16
, Alpha::F17
,
798 Alpha::F18
, Alpha::F19
, Alpha::F20
,
799 Alpha::F21
, Alpha::F22
, Alpha::F23
,
800 Alpha::F24
, Alpha::F25
, Alpha::F26
,
801 Alpha::F27
, Alpha::F28
, Alpha::F29
,
802 Alpha::F30
, Alpha::F31
, 0);
804 return make_vector
<unsigned>(Alpha::R0
, Alpha::R1
, Alpha::R2
,
805 Alpha::R3
, Alpha::R4
, Alpha::R5
,
806 Alpha::R6
, Alpha::R7
, Alpha::R8
,
807 Alpha::R9
, Alpha::R10
, Alpha::R11
,
808 Alpha::R12
, Alpha::R13
, Alpha::R14
,
809 Alpha::R15
, Alpha::R16
, Alpha::R17
,
810 Alpha::R18
, Alpha::R19
, Alpha::R20
,
811 Alpha::R21
, Alpha::R22
, Alpha::R23
,
812 Alpha::R24
, Alpha::R25
, Alpha::R26
,
813 Alpha::R27
, Alpha::R28
, Alpha::R29
,
814 Alpha::R30
, Alpha::R31
, 0);
818 return std::vector
<unsigned>();
820 //===----------------------------------------------------------------------===//
821 // Other Lowering Code
822 //===----------------------------------------------------------------------===//
825 AlphaTargetLowering::EmitInstrWithCustomInserter(MachineInstr
*MI
,
826 MachineBasicBlock
*BB
) const {
827 const TargetInstrInfo
*TII
= getTargetMachine().getInstrInfo();
828 assert((MI
->getOpcode() == Alpha::CAS32
||
829 MI
->getOpcode() == Alpha::CAS64
||
830 MI
->getOpcode() == Alpha::LAS32
||
831 MI
->getOpcode() == Alpha::LAS64
||
832 MI
->getOpcode() == Alpha::SWAP32
||
833 MI
->getOpcode() == Alpha::SWAP64
) &&
834 "Unexpected instr type to insert");
836 bool is32
= MI
->getOpcode() == Alpha::CAS32
||
837 MI
->getOpcode() == Alpha::LAS32
||
838 MI
->getOpcode() == Alpha::SWAP32
;
840 //Load locked store conditional for atomic ops take on the same form
843 //do stuff (maybe branch to exit)
845 //test sc and maybe branck to start
847 const BasicBlock
*LLVM_BB
= BB
->getBasicBlock();
848 DebugLoc dl
= MI
->getDebugLoc();
849 MachineFunction::iterator It
= BB
;
852 MachineBasicBlock
*thisMBB
= BB
;
853 MachineFunction
*F
= BB
->getParent();
854 MachineBasicBlock
*llscMBB
= F
->CreateMachineBasicBlock(LLVM_BB
);
855 MachineBasicBlock
*sinkMBB
= F
->CreateMachineBasicBlock(LLVM_BB
);
857 sinkMBB
->transferSuccessors(thisMBB
);
859 F
->insert(It
, llscMBB
);
860 F
->insert(It
, sinkMBB
);
862 BuildMI(thisMBB
, dl
, TII
->get(Alpha::BR
)).addMBB(llscMBB
);
864 unsigned reg_res
= MI
->getOperand(0).getReg(),
865 reg_ptr
= MI
->getOperand(1).getReg(),
866 reg_v2
= MI
->getOperand(2).getReg(),
867 reg_store
= F
->getRegInfo().createVirtualRegister(&Alpha::GPRCRegClass
);
869 BuildMI(llscMBB
, dl
, TII
->get(is32
? Alpha::LDL_L
: Alpha::LDQ_L
),
870 reg_res
).addImm(0).addReg(reg_ptr
);
871 switch (MI
->getOpcode()) {
875 = F
->getRegInfo().createVirtualRegister(&Alpha::GPRCRegClass
);
876 BuildMI(llscMBB
, dl
, TII
->get(Alpha::CMPEQ
), reg_cmp
)
877 .addReg(reg_v2
).addReg(reg_res
);
878 BuildMI(llscMBB
, dl
, TII
->get(Alpha::BEQ
))
879 .addImm(0).addReg(reg_cmp
).addMBB(sinkMBB
);
880 BuildMI(llscMBB
, dl
, TII
->get(Alpha::BISr
), reg_store
)
881 .addReg(Alpha::R31
).addReg(MI
->getOperand(3).getReg());
886 BuildMI(llscMBB
, dl
,TII
->get(is32
? Alpha::ADDLr
: Alpha::ADDQr
), reg_store
)
887 .addReg(reg_res
).addReg(reg_v2
);
891 case Alpha::SWAP64
: {
892 BuildMI(llscMBB
, dl
, TII
->get(Alpha::BISr
), reg_store
)
893 .addReg(reg_v2
).addReg(reg_v2
);
897 BuildMI(llscMBB
, dl
, TII
->get(is32
? Alpha::STL_C
: Alpha::STQ_C
), reg_store
)
898 .addReg(reg_store
).addImm(0).addReg(reg_ptr
);
899 BuildMI(llscMBB
, dl
, TII
->get(Alpha::BEQ
))
900 .addImm(0).addReg(reg_store
).addMBB(llscMBB
);
901 BuildMI(llscMBB
, dl
, TII
->get(Alpha::BR
)).addMBB(sinkMBB
);
903 thisMBB
->addSuccessor(llscMBB
);
904 llscMBB
->addSuccessor(llscMBB
);
905 llscMBB
->addSuccessor(sinkMBB
);
906 F
->DeleteMachineInstr(MI
); // The pseudo instruction is gone now.
912 AlphaTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode
*GA
) const {
913 // The Alpha target isn't yet aware of offsets.