blob: ef28a90004dee88c01ad9c1ee0dd16a805120d63 [file] [log] [blame]
Rafael Espindola7bc59bc2006-05-14 22:18:28 +00001//===-- ARMISelDAGToDAG.cpp - A dag to dag inst selector for ARM ----------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Chris Lattner and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines an instruction selector for the ARM target.
11//
12//===----------------------------------------------------------------------===//
13
14#include "ARM.h"
15#include "ARMTargetMachine.h"
Rafael Espindola84b19be2006-07-16 01:02:57 +000016#include "llvm/CallingConv.h"
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000017#include "llvm/DerivedTypes.h"
18#include "llvm/Function.h"
Rafael Espindola7246d332006-09-21 11:29:52 +000019#include "llvm/Constants.h"
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000020#include "llvm/Intrinsics.h"
Rafael Espindola462af9a2006-12-05 17:37:31 +000021#include "llvm/ADT/VectorExtras.h"
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000022#include "llvm/CodeGen/MachineFrameInfo.h"
23#include "llvm/CodeGen/MachineFunction.h"
24#include "llvm/CodeGen/MachineInstrBuilder.h"
25#include "llvm/CodeGen/SelectionDAG.h"
26#include "llvm/CodeGen/SelectionDAGISel.h"
27#include "llvm/CodeGen/SSARegMap.h"
28#include "llvm/Target/TargetLowering.h"
29#include "llvm/Support/Debug.h"
Rafael Espindolaa2845842006-10-05 16:48:49 +000030#include <vector>
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000031using namespace llvm;
32
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000033namespace {
34 class ARMTargetLowering : public TargetLowering {
Rafael Espindola755be9b2006-08-25 17:55:16 +000035 int VarArgsFrameIndex; // FrameIndex for start of varargs area.
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000036 public:
37 ARMTargetLowering(TargetMachine &TM);
38 virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG);
Rafael Espindola84b19be2006-07-16 01:02:57 +000039 virtual const char *getTargetNodeName(unsigned Opcode) const;
Rafael Espindola462af9a2006-12-05 17:37:31 +000040 std::vector<unsigned>
41 getRegClassForInlineAsmConstraint(const std::string &Constraint,
42 MVT::ValueType VT) const;
Rafael Espindola7bc59bc2006-05-14 22:18:28 +000043 };
44
45}
46
47ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)
48 : TargetLowering(TM) {
Rafael Espindola3717ca92006-08-20 01:49:49 +000049 addRegisterClass(MVT::i32, ARM::IntRegsRegisterClass);
Rafael Espindola27185192006-09-29 21:20:16 +000050 addRegisterClass(MVT::f32, ARM::FPRegsRegisterClass);
51 addRegisterClass(MVT::f64, ARM::DFPRegsRegisterClass);
Rafael Espindola3717ca92006-08-20 01:49:49 +000052
Rafael Espindolaad557f92006-10-09 14:13:40 +000053 setLoadXAction(ISD::EXTLOAD, MVT::f32, Expand);
54
Rafael Espindolab47e1d02006-10-10 18:55:14 +000055 setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);
Rafael Espindola27185192006-09-29 21:20:16 +000056 setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom);
Rafael Espindola3717ca92006-08-20 01:49:49 +000057
Rafael Espindola493a7fc2006-10-10 20:38:57 +000058 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom);
Rafael Espindolae5bbd6d2006-10-07 14:24:52 +000059 setOperationAction(ISD::UINT_TO_FP, MVT::i32, Custom);
60
Rafael Espindola06c1e7e2006-08-01 12:58:43 +000061 setOperationAction(ISD::RET, MVT::Other, Custom);
62 setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
63 setOperationAction(ISD::ConstantPool, MVT::i32, Custom);
Rafael Espindola341b8642006-08-04 12:48:42 +000064
Rafael Espindola6495bdd2006-10-19 12:06:50 +000065 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand);
66 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8 , Expand);
67 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1 , Expand);
68
Rafael Espindola48bc9fb2006-10-09 16:28:33 +000069 setOperationAction(ISD::SELECT, MVT::i32, Expand);
Lauro Ramos Venancioca1f66d2007-01-04 14:01:38 +000070 setOperationAction(ISD::SELECT, MVT::f32, Expand);
71 setOperationAction(ISD::SELECT, MVT::f64, Expand);
Rafael Espindola48bc9fb2006-10-09 16:28:33 +000072
Rafael Espindola3c000bf2006-08-21 22:00:32 +000073 setOperationAction(ISD::SETCC, MVT::i32, Expand);
Rafael Espindola4b20fbc2006-10-10 12:56:00 +000074 setOperationAction(ISD::SETCC, MVT::f32, Expand);
75 setOperationAction(ISD::SETCC, MVT::f64, Expand);
76
Rafael Espindola3c000bf2006-08-21 22:00:32 +000077 setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
Lauro Ramos Venancio301009a2006-12-28 13:11:14 +000078 setOperationAction(ISD::SELECT_CC, MVT::f32, Custom);
79 setOperationAction(ISD::SELECT_CC, MVT::f64, Custom);
Rafael Espindolad8ed7f82006-10-23 20:08:22 +000080
Rafael Espindola97815c62006-12-05 17:57:23 +000081 setOperationAction(ISD::MEMMOVE, MVT::Other, Expand);
Rafael Espindolad8ed7f82006-10-23 20:08:22 +000082 setOperationAction(ISD::MEMSET, MVT::Other, Expand);
Rafael Espindola97815c62006-12-05 17:57:23 +000083 setOperationAction(ISD::MEMCPY, MVT::Other, Expand);
Rafael Espindolad8ed7f82006-10-23 20:08:22 +000084
Evan Chengc35497f2006-10-30 08:02:39 +000085 setOperationAction(ISD::BR_JT, MVT::Other, Expand);
86 setOperationAction(ISD::BRIND, MVT::Other, Expand);
Rafael Espindola687bc492006-08-24 13:45:55 +000087 setOperationAction(ISD::BR_CC, MVT::i32, Custom);
Rafael Espindola4b20fbc2006-10-10 12:56:00 +000088 setOperationAction(ISD::BR_CC, MVT::f32, Custom);
89 setOperationAction(ISD::BR_CC, MVT::f64, Custom);
Rafael Espindola3c000bf2006-08-21 22:00:32 +000090
Rafael Espindolad2b56682006-10-14 17:59:54 +000091 setOperationAction(ISD::BRCOND, MVT::Other, Expand);
92
Rafael Espindola0505be02006-10-16 21:10:32 +000093 setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);
94 setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand);
95 setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand);
Rafael Espindola226f8bc2006-10-17 21:05:33 +000096 setOperationAction(ISD::SDIV, MVT::i32, Expand);
97 setOperationAction(ISD::UDIV, MVT::i32, Expand);
98 setOperationAction(ISD::SREM, MVT::i32, Expand);
99 setOperationAction(ISD::UREM, MVT::i32, Expand);
Rafael Espindola0505be02006-10-16 21:10:32 +0000100
Rafael Espindola755be9b2006-08-25 17:55:16 +0000101 setOperationAction(ISD::VASTART, MVT::Other, Custom);
Rafael Espindola0e5e3aa2006-10-24 20:15:21 +0000102 setOperationAction(ISD::VACOPY, MVT::Other, Expand);
Rafael Espindola755be9b2006-08-25 17:55:16 +0000103 setOperationAction(ISD::VAEND, MVT::Other, Expand);
Rafael Espindola7ae68ab2006-10-26 13:31:26 +0000104 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand);
Rafael Espindola755be9b2006-08-25 17:55:16 +0000105
Rafael Espindolacd71da52006-10-03 17:27:58 +0000106 setOperationAction(ISD::ConstantFP, MVT::f64, Expand);
107 setOperationAction(ISD::ConstantFP, MVT::f32, Expand);
108
Lauro Ramos Venancioca1f66d2007-01-04 14:01:38 +0000109 setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
110 setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
111
Rafael Espindola7ae68ab2006-10-26 13:31:26 +0000112 setStackPointerRegisterToSaveRestore(ARM::R13);
113
Rafael Espindola341b8642006-08-04 12:48:42 +0000114 setSchedulingPreference(SchedulingForRegPressure);
Rafael Espindola3717ca92006-08-20 01:49:49 +0000115 computeRegisterProperties();
Rafael Espindola7bc59bc2006-05-14 22:18:28 +0000116}
117
Rafael Espindola84b19be2006-07-16 01:02:57 +0000118namespace llvm {
119 namespace ARMISD {
120 enum NodeType {
121 // Start the numbering where the builting ops and target ops leave off.
122 FIRST_NUMBER = ISD::BUILTIN_OP_END+ARM::INSTRUCTION_LIST_END,
123 /// CALL - A direct function call.
Rafael Espindolaf4fda802006-08-03 17:02:20 +0000124 CALL,
125
126 /// Return with a flag operand.
Rafael Espindola3c000bf2006-08-21 22:00:32 +0000127 RET_FLAG,
128
129 CMP,
130
Rafael Espindola687bc492006-08-24 13:45:55 +0000131 SELECT,
132
Rafael Espindola27185192006-09-29 21:20:16 +0000133 BR,
134
Rafael Espindola9e071f02006-10-02 19:30:56 +0000135 FSITOS,
Rafael Espindolab47e1d02006-10-10 18:55:14 +0000136 FTOSIS,
Rafael Espindola9e071f02006-10-02 19:30:56 +0000137
138 FSITOD,
Rafael Espindolab47e1d02006-10-10 18:55:14 +0000139 FTOSID,
Rafael Espindola9e071f02006-10-02 19:30:56 +0000140
Rafael Espindolae5bbd6d2006-10-07 14:24:52 +0000141 FUITOS,
Rafael Espindola493a7fc2006-10-10 20:38:57 +0000142 FTOUIS,
Rafael Espindolae5bbd6d2006-10-07 14:24:52 +0000143
144 FUITOD,
Rafael Espindola493a7fc2006-10-10 20:38:57 +0000145 FTOUID,
Rafael Espindolae5bbd6d2006-10-07 14:24:52 +0000146
Rafael Espindolaa2845842006-10-05 16:48:49 +0000147 FMRRD,
148
Rafael Espindola4b20fbc2006-10-10 12:56:00 +0000149 FMDRR,
150
151 FMSTAT
Rafael Espindola84b19be2006-07-16 01:02:57 +0000152 };
153 }
154}
155
Rafael Espindola42b62f32006-10-13 13:14:59 +0000156/// DAGFPCCToARMCC - Convert a DAG fp condition code to an ARM CC
Rafael Espindola6c5ae3e2006-10-14 13:42:53 +0000157// Unordered = !N & !Z & C & V = V
158// Ordered = N | Z | !C | !V = N | Z | !V
Rafael Espindola9985f9f2006-12-31 18:52:39 +0000159static std::vector<unsigned> DAGFPCCToARMCC(ISD::CondCode CC) {
Rafael Espindola6f602de2006-08-24 16:13:15 +0000160 switch (CC) {
Rafael Espindolaebdabda2006-09-21 13:06:26 +0000161 default:
Rafael Espindola42b62f32006-10-13 13:14:59 +0000162 assert(0 && "Unknown fp condition code!");
Rafael Espindola6c5ae3e2006-10-14 13:42:53 +0000163// SETOEQ = (N | Z | !V) & Z = Z = EQ
164 case ISD::SETEQ:
Rafael Espindola9985f9f2006-12-31 18:52:39 +0000165 case ISD::SETOEQ: return make_vector<unsigned>(ARMCC::EQ, 0);
Rafael Espindola6c5ae3e2006-10-14 13:42:53 +0000166// SETOGT = (N | Z | !V) & !N & !Z = !V &!N &!Z = (N = V) & !Z = GT
167 case ISD::SETGT:
Rafael Espindola9985f9f2006-12-31 18:52:39 +0000168 case ISD::SETOGT: return make_vector<unsigned>(ARMCC::GT, 0);
Rafael Espindola6c5ae3e2006-10-14 13:42:53 +0000169// SETOGE = (N | Z | !V) & !N = (Z | !V) & !N = !V & !N = GE
170 case ISD::SETGE:
Rafael Espindola9985f9f2006-12-31 18:52:39 +0000171 case ISD::SETOGE: return make_vector<unsigned>(ARMCC::GE, 0);
Rafael Espindola6c5ae3e2006-10-14 13:42:53 +0000172// SETOLT = (N | Z | !V) & N = N = MI
173 case ISD::SETLT:
Rafael Espindola9985f9f2006-12-31 18:52:39 +0000174 case ISD::SETOLT: return make_vector<unsigned>(ARMCC::MI, 0);
Rafael Espindola6c5ae3e2006-10-14 13:42:53 +0000175// SETOLE = (N | Z | !V) & (N | Z) = N | Z = !C | Z = LS
176 case ISD::SETLE:
Rafael Espindola9985f9f2006-12-31 18:52:39 +0000177 case ISD::SETOLE: return make_vector<unsigned>(ARMCC::LS, 0);
178// SETONE = OGT | OLT
179 case ISD::SETONE: return make_vector<unsigned>(ARMCC::GT, ARMCC::MI, 0);
Rafael Espindola6c5ae3e2006-10-14 13:42:53 +0000180// SETO = N | Z | !V = Z | !V = !V = VC
Rafael Espindola9985f9f2006-12-31 18:52:39 +0000181 case ISD::SETO: return make_vector<unsigned>(ARMCC::VC, 0);
Rafael Espindola6c5ae3e2006-10-14 13:42:53 +0000182// SETUO = V = VS
Rafael Espindola9985f9f2006-12-31 18:52:39 +0000183 case ISD::SETUO: return make_vector<unsigned>(ARMCC::VS, 0);
184// SETUEQ = V | Z (need two instructions) = EQ/VS
185 case ISD::SETUEQ: return make_vector<unsigned>(ARMCC::EQ, ARMCC::VS, 0);
Rafael Espindola6c5ae3e2006-10-14 13:42:53 +0000186// SETUGT = V | (!Z & !N) = !Z & !N = !Z & C = HI
Rafael Espindola9985f9f2006-12-31 18:52:39 +0000187 case ISD::SETUGT: return make_vector<unsigned>(ARMCC::HI, 0);
Rafael Espindola6c5ae3e2006-10-14 13:42:53 +0000188// SETUGE = V | !N = !N = PL
Rafael Espindola9985f9f2006-12-31 18:52:39 +0000189 case ISD::SETUGE: return make_vector<unsigned>(ARMCC::PL, 0);
190// SETULT = V | N = LT
191 case ISD::SETULT: return make_vector<unsigned>(ARMCC::LT, 0);
192// SETULE = V | Z | N = LE
193 case ISD::SETULE: return make_vector<unsigned>(ARMCC::LE, 0);
Rafael Espindola6c5ae3e2006-10-14 13:42:53 +0000194// SETUNE = V | !Z = !Z = NE
Rafael Espindola9985f9f2006-12-31 18:52:39 +0000195 case ISD::SETNE:
196 case ISD::SETUNE: return make_vector<unsigned>(ARMCC::NE, 0);
Rafael Espindola42b62f32006-10-13 13:14:59 +0000197 }
198}
199
200/// DAGIntCCToARMCC - Convert a DAG integer condition code to an ARM CC
Rafael Espindola9985f9f2006-12-31 18:52:39 +0000201static std::vector<unsigned> DAGIntCCToARMCC(ISD::CondCode CC) {
Rafael Espindola42b62f32006-10-13 13:14:59 +0000202 switch (CC) {
203 default:
204 assert(0 && "Unknown integer condition code!");
Rafael Espindola9985f9f2006-12-31 18:52:39 +0000205 case ISD::SETEQ: return make_vector<unsigned>(ARMCC::EQ, 0);
206 case ISD::SETNE: return make_vector<unsigned>(ARMCC::NE, 0);
207 case ISD::SETLT: return make_vector<unsigned>(ARMCC::LT, 0);
208 case ISD::SETLE: return make_vector<unsigned>(ARMCC::LE, 0);
209 case ISD::SETGT: return make_vector<unsigned>(ARMCC::GT, 0);
210 case ISD::SETGE: return make_vector<unsigned>(ARMCC::GE, 0);
211 case ISD::SETULT: return make_vector<unsigned>(ARMCC::CC, 0);
212 case ISD::SETULE: return make_vector<unsigned>(ARMCC::LS, 0);
213 case ISD::SETUGT: return make_vector<unsigned>(ARMCC::HI, 0);
214 case ISD::SETUGE: return make_vector<unsigned>(ARMCC::CS, 0);
Rafael Espindola6f602de2006-08-24 16:13:15 +0000215 }
216}
217
Rafael Espindola462af9a2006-12-05 17:37:31 +0000218std::vector<unsigned> ARMTargetLowering::
219getRegClassForInlineAsmConstraint(const std::string &Constraint,
220 MVT::ValueType VT) const {
221 if (Constraint.size() == 1) {
222 // FIXME: handling only r regs
223 switch (Constraint[0]) {
224 default: break; // Unknown constraint letter
225
226 case 'r': // GENERAL_REGS
227 case 'R': // LEGACY_REGS
228 if (VT == MVT::i32)
229 return make_vector<unsigned>(ARM::R0, ARM::R1, ARM::R2, ARM::R3,
230 ARM::R4, ARM::R5, ARM::R6, ARM::R7,
231 ARM::R8, ARM::R9, ARM::R10, ARM::R11,
232 ARM::R12, ARM::R13, ARM::R14, 0);
233 break;
234
235 }
236 }
237
238 return std::vector<unsigned>();
239}
240
Rafael Espindola84b19be2006-07-16 01:02:57 +0000241const char *ARMTargetLowering::getTargetNodeName(unsigned Opcode) const {
242 switch (Opcode) {
243 default: return 0;
244 case ARMISD::CALL: return "ARMISD::CALL";
Rafael Espindolaf4fda802006-08-03 17:02:20 +0000245 case ARMISD::RET_FLAG: return "ARMISD::RET_FLAG";
Rafael Espindola3c000bf2006-08-21 22:00:32 +0000246 case ARMISD::SELECT: return "ARMISD::SELECT";
247 case ARMISD::CMP: return "ARMISD::CMP";
Rafael Espindola687bc492006-08-24 13:45:55 +0000248 case ARMISD::BR: return "ARMISD::BR";
Rafael Espindola27185192006-09-29 21:20:16 +0000249 case ARMISD::FSITOS: return "ARMISD::FSITOS";
Rafael Espindolab47e1d02006-10-10 18:55:14 +0000250 case ARMISD::FTOSIS: return "ARMISD::FTOSIS";
Rafael Espindola9e071f02006-10-02 19:30:56 +0000251 case ARMISD::FSITOD: return "ARMISD::FSITOD";
Rafael Espindolab47e1d02006-10-10 18:55:14 +0000252 case ARMISD::FTOSID: return "ARMISD::FTOSID";
Rafael Espindolae5bbd6d2006-10-07 14:24:52 +0000253 case ARMISD::FUITOS: return "ARMISD::FUITOS";
Rafael Espindola493a7fc2006-10-10 20:38:57 +0000254 case ARMISD::FTOUIS: return "ARMISD::FTOUIS";
Rafael Espindolae5bbd6d2006-10-07 14:24:52 +0000255 case ARMISD::FUITOD: return "ARMISD::FUITOD";
Rafael Espindola493a7fc2006-10-10 20:38:57 +0000256 case ARMISD::FTOUID: return "ARMISD::FTOUID";
Rafael Espindola9e071f02006-10-02 19:30:56 +0000257 case ARMISD::FMRRD: return "ARMISD::FMRRD";
Rafael Espindolaa2845842006-10-05 16:48:49 +0000258 case ARMISD::FMDRR: return "ARMISD::FMDRR";
Rafael Espindola4b20fbc2006-10-10 12:56:00 +0000259 case ARMISD::FMSTAT: return "ARMISD::FMSTAT";
Rafael Espindola84b19be2006-07-16 01:02:57 +0000260 }
261}
262
Rafael Espindolaa2845842006-10-05 16:48:49 +0000263class ArgumentLayout {
264 std::vector<bool> is_reg;
265 std::vector<unsigned> pos;
266 std::vector<MVT::ValueType> types;
267public:
Rafael Espindola39b5a212006-10-05 17:46:48 +0000268 ArgumentLayout(const std::vector<MVT::ValueType> &Types) {
Rafael Espindolaa2845842006-10-05 16:48:49 +0000269 types = Types;
270
271 unsigned RegNum = 0;
272 unsigned StackOffset = 0;
Rafael Espindola39b5a212006-10-05 17:46:48 +0000273 for(std::vector<MVT::ValueType>::const_iterator I = Types.begin();
Rafael Espindolaa2845842006-10-05 16:48:49 +0000274 I != Types.end();
275 ++I) {
276 MVT::ValueType VT = *I;
277 assert(VT == MVT::i32 || VT == MVT::f32 || VT == MVT::f64);
278 unsigned size = MVT::getSizeInBits(VT)/32;
279
280 RegNum = ((RegNum + size - 1) / size) * size;
281 if (RegNum < 4) {
282 pos.push_back(RegNum);
283 is_reg.push_back(true);
284 RegNum += size;
285 } else {
286 unsigned bytes = size * 32/8;
287 StackOffset = ((StackOffset + bytes - 1) / bytes) * bytes;
288 pos.push_back(StackOffset);
289 is_reg.push_back(false);
290 StackOffset += bytes;
291 }
292 }
293 }
294 unsigned getRegisterNum(unsigned argNum) {
295 assert(isRegister(argNum));
296 return pos[argNum];
297 }
298 unsigned getOffset(unsigned argNum) {
299 assert(isOffset(argNum));
300 return pos[argNum];
301 }
302 unsigned isRegister(unsigned argNum) {
303 assert(argNum < is_reg.size());
304 return is_reg[argNum];
305 }
306 unsigned isOffset(unsigned argNum) {
307 return !isRegister(argNum);
308 }
309 MVT::ValueType getType(unsigned argNum) {
310 assert(argNum < types.size());
311 return types[argNum];
312 }
313 unsigned getStackSize(void) {
314 int last = is_reg.size() - 1;
Rafael Espindolaaf1dabe2006-10-06 17:26:30 +0000315 if (last < 0)
316 return 0;
Rafael Espindolaa2845842006-10-05 16:48:49 +0000317 if (isRegister(last))
318 return 0;
319 return getOffset(last) + MVT::getSizeInBits(getType(last))/8;
320 }
321 int lastRegArg(void) {
322 int size = is_reg.size();
323 int last = 0;
324 while(last < size && isRegister(last))
325 last++;
326 last--;
327 return last;
328 }
Rafael Espindolaaf1dabe2006-10-06 17:26:30 +0000329 int lastRegNum(void) {
Rafael Espindolaa2845842006-10-05 16:48:49 +0000330 int l = lastRegArg();
331 if (l < 0)
332 return -1;
333 unsigned r = getRegisterNum(l);
334 MVT::ValueType t = getType(l);
335 assert(t == MVT::i32 || t == MVT::f32 || t == MVT::f64);
336 if (t == MVT::f64)
337 return r + 1;
338 return r;
339 }
340};
341
Rafael Espindola84b19be2006-07-16 01:02:57 +0000342// This transforms a ISD::CALL node into a
343// callseq_star <- ARMISD:CALL <- callseq_end
344// chain
Rafael Espindolac3c1a862006-05-25 11:00:18 +0000345static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) {
Rafael Espindola84b19be2006-07-16 01:02:57 +0000346 SDOperand Chain = Op.getOperand(0);
347 unsigned CallConv = cast<ConstantSDNode>(Op.getOperand(1))->getValue();
Rafael Espindola5f1b6982006-10-18 12:03:07 +0000348 assert((CallConv == CallingConv::C ||
349 CallConv == CallingConv::Fast)
350 && "unknown calling convention");
Rafael Espindola84b19be2006-07-16 01:02:57 +0000351 SDOperand Callee = Op.getOperand(4);
352 unsigned NumOps = (Op.getNumOperands() - 5) / 2;
Rafael Espindola1a009462006-08-08 13:02:29 +0000353 SDOperand StackPtr = DAG.getRegister(ARM::R13, MVT::i32);
Rafael Espindolaa2845842006-10-05 16:48:49 +0000354 static const unsigned regs[] = {
Rafael Espindolafac00a92006-07-25 20:17:20 +0000355 ARM::R0, ARM::R1, ARM::R2, ARM::R3
356 };
357
Rafael Espindolaa2845842006-10-05 16:48:49 +0000358 std::vector<MVT::ValueType> Types;
359 for (unsigned i = 0; i < NumOps; ++i) {
360 MVT::ValueType VT = Op.getOperand(5+2*i).getValueType();
361 Types.push_back(VT);
362 }
363 ArgumentLayout Layout(Types);
Rafael Espindolafac00a92006-07-25 20:17:20 +0000364
Rafael Espindolaa2845842006-10-05 16:48:49 +0000365 unsigned NumBytes = Layout.getStackSize();
366
367 Chain = DAG.getCALLSEQ_START(Chain,
368 DAG.getConstant(NumBytes, MVT::i32));
369
370 //Build a sequence of stores
371 std::vector<SDOperand> MemOpChains;
372 for (unsigned i = Layout.lastRegArg() + 1; i < NumOps; ++i) {
373 SDOperand Arg = Op.getOperand(5+2*i);
374 unsigned ArgOffset = Layout.getOffset(i);
375 SDOperand PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType());
376 PtrOff = DAG.getNode(ISD::ADD, MVT::i32, StackPtr, PtrOff);
Evan Cheng8b2794a2006-10-13 21:14:26 +0000377 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
Rafael Espindolafac00a92006-07-25 20:17:20 +0000378 }
Rafael Espindola1a009462006-08-08 13:02:29 +0000379 if (!MemOpChains.empty())
Chris Lattnere2199452006-08-11 17:38:39 +0000380 Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
381 &MemOpChains[0], MemOpChains.size());
Rafael Espindolafac00a92006-07-25 20:17:20 +0000382
Rafael Espindola0505be02006-10-16 21:10:32 +0000383 // If the callee is a GlobalAddress node (quite common, every direct call is)
384 // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
385 // Likewise ExternalSymbol -> TargetExternalSymbol.
386 assert(Callee.getValueType() == MVT::i32);
Rafael Espindola84b19be2006-07-16 01:02:57 +0000387 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
Rafael Espindola0505be02006-10-16 21:10:32 +0000388 Callee = DAG.getTargetGlobalAddress(G->getGlobal(), MVT::i32);
389 else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))
390 Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32);
Rafael Espindola84b19be2006-07-16 01:02:57 +0000391
392 // If this is a direct call, pass the chain and the callee.
393 assert (Callee.Val);
394 std::vector<SDOperand> Ops;
395 Ops.push_back(Chain);
396 Ops.push_back(Callee);
397
Rafael Espindolaa2845842006-10-05 16:48:49 +0000398 // Build a sequence of copy-to-reg nodes chained together with token chain
399 // and flag operands which copy the outgoing args into the appropriate regs.
400 SDOperand InFlag;
Rafael Espindolaaf1dabe2006-10-06 17:26:30 +0000401 for (int i = 0, e = Layout.lastRegArg(); i <= e; ++i) {
Rafael Espindola4a408d42006-10-06 12:50:22 +0000402 SDOperand Arg = Op.getOperand(5+2*i);
403 unsigned RegNum = Layout.getRegisterNum(i);
404 unsigned Reg1 = regs[RegNum];
405 MVT::ValueType VT = Layout.getType(i);
406 assert(VT == Arg.getValueType());
407 assert(VT == MVT::i32 || VT == MVT::f32 || VT == MVT::f64);
Rafael Espindolaa2845842006-10-05 16:48:49 +0000408
409 // Add argument register to the end of the list so that it is known live
410 // into the call.
Rafael Espindola4a408d42006-10-06 12:50:22 +0000411 Ops.push_back(DAG.getRegister(Reg1, MVT::i32));
412 if (VT == MVT::f64) {
413 unsigned Reg2 = regs[RegNum + 1];
414 SDOperand SDReg1 = DAG.getRegister(Reg1, MVT::i32);
415 SDOperand SDReg2 = DAG.getRegister(Reg2, MVT::i32);
416
417 Ops.push_back(DAG.getRegister(Reg2, MVT::i32));
418 SDVTList VTs = DAG.getVTList(MVT::Other, MVT::Flag);
Rafael Espindola935b1f82006-10-06 20:33:26 +0000419 SDOperand Ops[] = {Chain, SDReg1, SDReg2, Arg, InFlag};
420 Chain = DAG.getNode(ARMISD::FMRRD, VTs, Ops, InFlag.Val ? 5 : 4);
Rafael Espindola4a408d42006-10-06 12:50:22 +0000421 } else {
422 if (VT == MVT::f32)
423 Arg = DAG.getNode(ISD::BIT_CONVERT, MVT::i32, Arg);
424 Chain = DAG.getCopyToReg(Chain, Reg1, Arg, InFlag);
425 }
426 InFlag = Chain.getValue(1);
Rafael Espindolaa2845842006-10-05 16:48:49 +0000427 }
428
429 std::vector<MVT::ValueType> NodeTys;
430 NodeTys.push_back(MVT::Other); // Returns a chain
431 NodeTys.push_back(MVT::Flag); // Returns a flag for retval copy to use.
Rafael Espindola7a53bd02006-08-09 16:41:12 +0000432
Rafael Espindola84b19be2006-07-16 01:02:57 +0000433 unsigned CallOpc = ARMISD::CALL;
Rafael Espindolafac00a92006-07-25 20:17:20 +0000434 if (InFlag.Val)
435 Ops.push_back(InFlag);
Chris Lattner87428672006-08-11 17:22:35 +0000436 Chain = DAG.getNode(CallOpc, NodeTys, &Ops[0], Ops.size());
Rafael Espindolafac00a92006-07-25 20:17:20 +0000437 InFlag = Chain.getValue(1);
Rafael Espindola84b19be2006-07-16 01:02:57 +0000438
Rafael Espindolafac00a92006-07-25 20:17:20 +0000439 std::vector<SDOperand> ResultVals;
440 NodeTys.clear();
441
442 // If the call has results, copy the values out of the ret val registers.
Rafael Espindola614057b2006-10-06 19:10:05 +0000443 MVT::ValueType VT = Op.Val->getValueType(0);
444 if (VT != MVT::Other) {
445 assert(VT == MVT::i32 || VT == MVT::f32 || VT == MVT::f64);
Rafael Espindola614057b2006-10-06 19:10:05 +0000446
447 SDOperand Value1 = DAG.getCopyFromReg(Chain, ARM::R0, MVT::i32, InFlag);
448 Chain = Value1.getValue(1);
449 InFlag = Value1.getValue(2);
Rafael Espindola26a76d12006-10-13 16:47:22 +0000450 NodeTys.push_back(VT);
451 if (VT == MVT::i32) {
452 ResultVals.push_back(Value1);
453 if (Op.Val->getValueType(1) == MVT::i32) {
454 SDOperand Value2 = DAG.getCopyFromReg(Chain, ARM::R1, MVT::i32, InFlag);
455 Chain = Value2.getValue(1);
456 ResultVals.push_back(Value2);
457 NodeTys.push_back(VT);
458 }
459 }
460 if (VT == MVT::f32) {
461 SDOperand Value = DAG.getNode(ISD::BIT_CONVERT, MVT::f32, Value1);
462 ResultVals.push_back(Value);
463 }
Rafael Espindola614057b2006-10-06 19:10:05 +0000464 if (VT == MVT::f64) {
465 SDOperand Value2 = DAG.getCopyFromReg(Chain, ARM::R1, MVT::i32, InFlag);
466 Chain = Value2.getValue(1);
Rafael Espindola26a76d12006-10-13 16:47:22 +0000467 SDOperand Value = DAG.getNode(ARMISD::FMDRR, MVT::f64, Value1, Value2);
468 ResultVals.push_back(Value);
Rafael Espindola614057b2006-10-06 19:10:05 +0000469 }
Rafael Espindolafac00a92006-07-25 20:17:20 +0000470 }
Rafael Espindola84b19be2006-07-16 01:02:57 +0000471
472 Chain = DAG.getNode(ISD::CALLSEQ_END, MVT::Other, Chain,
473 DAG.getConstant(NumBytes, MVT::i32));
Rafael Espindolafac00a92006-07-25 20:17:20 +0000474 NodeTys.push_back(MVT::Other);
Rafael Espindola84b19be2006-07-16 01:02:57 +0000475
Rafael Espindolafac00a92006-07-25 20:17:20 +0000476 if (ResultVals.empty())
477 return Chain;
478
479 ResultVals.push_back(Chain);
Chris Lattner87428672006-08-11 17:22:35 +0000480 SDOperand Res = DAG.getNode(ISD::MERGE_VALUES, NodeTys, &ResultVals[0],
481 ResultVals.size());
Rafael Espindolafac00a92006-07-25 20:17:20 +0000482 return Res.getValue(Op.ResNo);
Rafael Espindola7bc59bc2006-05-14 22:18:28 +0000483}
484
485static SDOperand LowerRET(SDOperand Op, SelectionDAG &DAG) {
486 SDOperand Copy;
Rafael Espindola4b023672006-06-05 22:26:14 +0000487 SDOperand Chain = Op.getOperand(0);
Rafael Espindola9e071f02006-10-02 19:30:56 +0000488 SDOperand R0 = DAG.getRegister(ARM::R0, MVT::i32);
489 SDOperand R1 = DAG.getRegister(ARM::R1, MVT::i32);
490
Rafael Espindola7bc59bc2006-05-14 22:18:28 +0000491 switch(Op.getNumOperands()) {
492 default:
493 assert(0 && "Do not know how to return this many arguments!");
494 abort();
Rafael Espindola4b023672006-06-05 22:26:14 +0000495 case 1: {
496 SDOperand LR = DAG.getRegister(ARM::R14, MVT::i32);
Rafael Espindola6312da02006-08-03 22:50:11 +0000497 return DAG.getNode(ARMISD::RET_FLAG, MVT::Other, Chain);
Rafael Espindola4b023672006-06-05 22:26:14 +0000498 }
Rafael Espindola27185192006-09-29 21:20:16 +0000499 case 3: {
500 SDOperand Val = Op.getOperand(1);
501 assert(Val.getValueType() == MVT::i32 ||
Rafael Espindola9e071f02006-10-02 19:30:56 +0000502 Val.getValueType() == MVT::f32 ||
503 Val.getValueType() == MVT::f64);
Rafael Espindola27185192006-09-29 21:20:16 +0000504
Rafael Espindola9e071f02006-10-02 19:30:56 +0000505 if (Val.getValueType() == MVT::f64) {
506 SDVTList VTs = DAG.getVTList(MVT::Other, MVT::Flag);
507 SDOperand Ops[] = {Chain, R0, R1, Val};
508 Copy = DAG.getNode(ARMISD::FMRRD, VTs, Ops, 4);
509 } else {
510 if (Val.getValueType() == MVT::f32)
511 Val = DAG.getNode(ISD::BIT_CONVERT, MVT::i32, Val);
512 Copy = DAG.getCopyToReg(Chain, R0, Val, SDOperand());
513 }
514
515 if (DAG.getMachineFunction().liveout_empty()) {
Rafael Espindola4b023672006-06-05 22:26:14 +0000516 DAG.getMachineFunction().addLiveOut(ARM::R0);
Rafael Espindola9e071f02006-10-02 19:30:56 +0000517 if (Val.getValueType() == MVT::f64)
518 DAG.getMachineFunction().addLiveOut(ARM::R1);
519 }
Rafael Espindola7bc59bc2006-05-14 22:18:28 +0000520 break;
Rafael Espindola27185192006-09-29 21:20:16 +0000521 }
Rafael Espindola3a02f022006-09-04 19:05:01 +0000522 case 5:
523 Copy = DAG.getCopyToReg(Chain, ARM::R1, Op.getOperand(3), SDOperand());
524 Copy = DAG.getCopyToReg(Copy, ARM::R0, Op.getOperand(1), Copy.getValue(1));
525 // If we haven't noted the R0+R1 are live out, do so now.
526 if (DAG.getMachineFunction().liveout_empty()) {
527 DAG.getMachineFunction().addLiveOut(ARM::R0);
528 DAG.getMachineFunction().addLiveOut(ARM::R1);
529 }
530 break;
Rafael Espindola7bc59bc2006-05-14 22:18:28 +0000531 }
Rafael Espindola4b023672006-06-05 22:26:14 +0000532
Rafael Espindolaf4fda802006-08-03 17:02:20 +0000533 //We must use RET_FLAG instead of BRIND because BRIND doesn't have a flag
534 return DAG.getNode(ARMISD::RET_FLAG, MVT::Other, Copy, Copy.getValue(1));
Rafael Espindola7bc59bc2006-05-14 22:18:28 +0000535}
536
Rafael Espindola06c1e7e2006-08-01 12:58:43 +0000537static SDOperand LowerConstantPool(SDOperand Op, SelectionDAG &DAG) {
538 MVT::ValueType PtrVT = Op.getValueType();
539 ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
Evan Chengc356a572006-09-12 21:04:05 +0000540 Constant *C = CP->getConstVal();
Rafael Espindola06c1e7e2006-08-01 12:58:43 +0000541 SDOperand CPI = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment());
542
543 return CPI;
544}
545
546static SDOperand LowerGlobalAddress(SDOperand Op,
547 SelectionDAG &DAG) {
548 GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
Rafael Espindola61369da2006-08-14 19:01:24 +0000549 int alignment = 2;
550 SDOperand CPAddr = DAG.getConstantPool(GV, MVT::i32, alignment);
Evan Cheng466685d2006-10-09 20:57:25 +0000551 return DAG.getLoad(MVT::i32, DAG.getEntryNode(), CPAddr, NULL, 0);
Rafael Espindola06c1e7e2006-08-01 12:58:43 +0000552}
553
Rafael Espindola755be9b2006-08-25 17:55:16 +0000554static SDOperand LowerVASTART(SDOperand Op, SelectionDAG &DAG,
555 unsigned VarArgsFrameIndex) {
556 // vastart just stores the address of the VarArgsFrameIndex slot into the
557 // memory location argument.
558 MVT::ValueType PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
559 SDOperand FR = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
Evan Cheng8b2794a2006-10-13 21:14:26 +0000560 SrcValueSDNode *SV = cast<SrcValueSDNode>(Op.getOperand(2));
561 return DAG.getStore(Op.getOperand(0), FR, Op.getOperand(1), SV->getValue(),
562 SV->getOffset());
Rafael Espindola755be9b2006-08-25 17:55:16 +0000563}
564
565static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG,
566 int &VarArgsFrameIndex) {
Rafael Espindolaa2845842006-10-05 16:48:49 +0000567 MachineFunction &MF = DAG.getMachineFunction();
568 MachineFrameInfo *MFI = MF.getFrameInfo();
569 SSARegMap *RegMap = MF.getSSARegMap();
570 unsigned NumArgs = Op.Val->getNumValues()-1;
571 SDOperand Root = Op.getOperand(0);
572 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
573 static const unsigned REGS[] = {
574 ARM::R0, ARM::R1, ARM::R2, ARM::R3
575 };
576
577 std::vector<MVT::ValueType> Types(Op.Val->value_begin(), Op.Val->value_end() - 1);
578 ArgumentLayout Layout(Types);
579
Rafael Espindola337c4ad62006-06-12 12:28:08 +0000580 std::vector<SDOperand> ArgValues;
Rafael Espindola755be9b2006-08-25 17:55:16 +0000581 for (unsigned ArgNo = 0; ArgNo < NumArgs; ++ArgNo) {
Rafael Espindolaa2845842006-10-05 16:48:49 +0000582 MVT::ValueType VT = Types[ArgNo];
Rafael Espindola4b442b52006-05-23 02:48:20 +0000583
Rafael Espindolaa2845842006-10-05 16:48:49 +0000584 SDOperand Value;
585 if (Layout.isRegister(ArgNo)) {
586 assert(VT == MVT::i32 || VT == MVT::f32 || VT == MVT::f64);
587 unsigned RegNum = Layout.getRegisterNum(ArgNo);
588 unsigned Reg1 = REGS[RegNum];
589 unsigned VReg1 = RegMap->createVirtualRegister(&ARM::IntRegsRegClass);
590 SDOperand Value1 = DAG.getCopyFromReg(Root, VReg1, MVT::i32);
591 MF.addLiveIn(Reg1, VReg1);
592 if (VT == MVT::f64) {
593 unsigned Reg2 = REGS[RegNum + 1];
594 unsigned VReg2 = RegMap->createVirtualRegister(&ARM::IntRegsRegClass);
595 SDOperand Value2 = DAG.getCopyFromReg(Root, VReg2, MVT::i32);
596 MF.addLiveIn(Reg2, VReg2);
597 Value = DAG.getNode(ARMISD::FMDRR, MVT::f64, Value1, Value2);
598 } else {
599 Value = Value1;
600 if (VT == MVT::f32)
601 Value = DAG.getNode(ISD::BIT_CONVERT, VT, Value);
602 }
603 } else {
604 // If the argument is actually used, emit a load from the right stack
605 // slot.
606 if (!Op.Val->hasNUsesOfValue(0, ArgNo)) {
607 unsigned Offset = Layout.getOffset(ArgNo);
608 unsigned Size = MVT::getSizeInBits(VT)/8;
609 int FI = MFI->CreateFixedObject(Size, Offset);
610 SDOperand FIN = DAG.getFrameIndex(FI, VT);
Evan Cheng466685d2006-10-09 20:57:25 +0000611 Value = DAG.getLoad(VT, Root, FIN, NULL, 0);
Rafael Espindolaa2845842006-10-05 16:48:49 +0000612 } else {
613 Value = DAG.getNode(ISD::UNDEF, VT);
614 }
615 }
616 ArgValues.push_back(Value);
Rafael Espindola4b442b52006-05-23 02:48:20 +0000617 }
618
Rafael Espindolaa2845842006-10-05 16:48:49 +0000619 unsigned NextRegNum = Layout.lastRegNum() + 1;
620
Rafael Espindola755be9b2006-08-25 17:55:16 +0000621 if (isVarArg) {
Rafael Espindolaa2845842006-10-05 16:48:49 +0000622 //If this function is vararg we must store the remaing
623 //registers so that they can be acessed with va_start
Rafael Espindola755be9b2006-08-25 17:55:16 +0000624 VarArgsFrameIndex = MFI->CreateFixedObject(MVT::getSizeInBits(MVT::i32)/8,
Rafael Espindolaa2845842006-10-05 16:48:49 +0000625 -16 + NextRegNum * 4);
Rafael Espindola755be9b2006-08-25 17:55:16 +0000626
Rafael Espindola755be9b2006-08-25 17:55:16 +0000627 SmallVector<SDOperand, 4> MemOps;
Rafael Espindolaa2845842006-10-05 16:48:49 +0000628 for (unsigned RegNo = NextRegNum; RegNo < 4; ++RegNo) {
629 int RegOffset = - (4 - RegNo) * 4;
Rafael Espindola755be9b2006-08-25 17:55:16 +0000630 int FI = MFI->CreateFixedObject(MVT::getSizeInBits(MVT::i32)/8,
Rafael Espindolaa2845842006-10-05 16:48:49 +0000631 RegOffset);
Rafael Espindola755be9b2006-08-25 17:55:16 +0000632 SDOperand FIN = DAG.getFrameIndex(FI, MVT::i32);
633
Rafael Espindolaa2845842006-10-05 16:48:49 +0000634 unsigned VReg = RegMap->createVirtualRegister(&ARM::IntRegsRegClass);
635 MF.addLiveIn(REGS[RegNo], VReg);
Rafael Espindola755be9b2006-08-25 17:55:16 +0000636
637 SDOperand Val = DAG.getCopyFromReg(Root, VReg, MVT::i32);
Evan Cheng8b2794a2006-10-13 21:14:26 +0000638 SDOperand Store = DAG.getStore(Val.getValue(1), Val, FIN, NULL, 0);
Rafael Espindola755be9b2006-08-25 17:55:16 +0000639 MemOps.push_back(Store);
640 }
641 Root = DAG.getNode(ISD::TokenFactor, MVT::Other,&MemOps[0],MemOps.size());
642 }
Rafael Espindola4b442b52006-05-23 02:48:20 +0000643
644 ArgValues.push_back(Root);
645
646 // Return the new list of results.
647 std::vector<MVT::ValueType> RetVT(Op.Val->value_begin(),
648 Op.Val->value_end());
Chris Lattner87428672006-08-11 17:22:35 +0000649 return DAG.getNode(ISD::MERGE_VALUES, RetVT, &ArgValues[0], ArgValues.size());
Rafael Espindoladc124a22006-05-18 21:45:49 +0000650}
651
Rafael Espindola4b20fbc2006-10-10 12:56:00 +0000652static SDOperand GetCMP(ISD::CondCode CC, SDOperand LHS, SDOperand RHS,
653 SelectionDAG &DAG) {
654 MVT::ValueType vt = LHS.getValueType();
Rafael Espindola0d9fe762006-10-10 16:33:47 +0000655 assert(vt == MVT::i32 || vt == MVT::f32 || vt == MVT::f64);
Rafael Espindola4b20fbc2006-10-10 12:56:00 +0000656
Rafael Espindola6c5ae3e2006-10-14 13:42:53 +0000657 SDOperand Cmp = DAG.getNode(ARMISD::CMP, MVT::Flag, LHS, RHS);
Rafael Espindola42b62f32006-10-13 13:14:59 +0000658
Rafael Espindola4b20fbc2006-10-10 12:56:00 +0000659 if (vt != MVT::i32)
660 Cmp = DAG.getNode(ARMISD::FMSTAT, MVT::Flag, Cmp);
661 return Cmp;
662}
663
Rafael Espindola9985f9f2006-12-31 18:52:39 +0000664static std::vector<SDOperand> GetARMCC(ISD::CondCode CC, MVT::ValueType vt,
Rafael Espindola42b62f32006-10-13 13:14:59 +0000665 SelectionDAG &DAG) {
666 assert(vt == MVT::i32 || vt == MVT::f32 || vt == MVT::f64);
Rafael Espindola9985f9f2006-12-31 18:52:39 +0000667 std::vector<unsigned> vcc;
Rafael Espindola42b62f32006-10-13 13:14:59 +0000668 if (vt == MVT::i32)
Rafael Espindola9985f9f2006-12-31 18:52:39 +0000669 vcc = DAGIntCCToARMCC(CC);
Rafael Espindola42b62f32006-10-13 13:14:59 +0000670 else
Rafael Espindola9985f9f2006-12-31 18:52:39 +0000671 vcc = DAGFPCCToARMCC(CC);
672
673 std::vector<unsigned>::iterator it;
674 std::vector<SDOperand> result;
675 for( it = vcc.begin(); it != vcc.end(); it++ )
676 result.push_back(DAG.getConstant(*it,MVT::i32));
677 return result;
Rafael Espindola42b62f32006-10-13 13:14:59 +0000678}
679
Rafael Espindola8897a7b2006-12-14 18:58:37 +0000680static bool isUInt8Immediate(uint32_t x) {
681 return x < (1 << 8);
682}
683
684static uint32_t rotateL(uint32_t x) {
685 uint32_t bit31 = (x & (1 << 31)) >> 31;
686 uint32_t t = x << 1;
687 return t | bit31;
688}
689
690static bool isRotInt8Immediate(uint32_t x) {
691 int r;
692 for (r = 0; r < 16; r++) {
693 if (isUInt8Immediate(x))
694 return true;
695 x = rotateL(rotateL(x));
696 }
697 return false;
698}
699
Rafael Espindola9985f9f2006-12-31 18:52:39 +0000700static void LowerCMP(SDOperand &Cmp, std::vector<SDOperand> &ARMCC,
701 SDOperand LHS, SDOperand RHS, ISD::CondCode CC,
702 SelectionDAG &DAG) {
Rafael Espindola8897a7b2006-12-14 18:58:37 +0000703 MVT::ValueType vt = LHS.getValueType();
704 if (vt == MVT::i32) {
705 assert(!isa<ConstantSDNode>(LHS));
706 if (ConstantSDNode *SD_C = dyn_cast<ConstantSDNode>(RHS.Val)) {
707 uint32_t C = SD_C->getValue();
708
709 uint32_t NC;
710 switch(CC) {
711 default:
712 NC = C; break;
713 case ISD::SETLT:
714 case ISD::SETULT:
715 case ISD::SETGE:
716 case ISD::SETUGE:
717 NC = C - 1; break;
718 case ISD::SETLE:
719 case ISD::SETULE:
720 case ISD::SETGT:
721 case ISD::SETUGT:
722 NC = C + 1; break;
723 }
724
725 ISD::CondCode NCC;
726 switch(CC) {
727 default:
728 NCC = CC; break;
729 case ISD::SETLT:
730 NCC = ISD::SETLE; break;
731 case ISD::SETULT:
732 NCC = ISD::SETULE; break;
733 case ISD::SETGE:
734 NCC = ISD::SETGT; break;
735 case ISD::SETUGE:
736 NCC = ISD::SETUGT; break;
737 case ISD::SETLE:
738 NCC = ISD::SETLT; break;
739 case ISD::SETULE:
740 NCC = ISD::SETULT; break;
741 case ISD::SETGT:
742 NCC = ISD::SETGE; break;
743 case ISD::SETUGT:
744 NCC = ISD::SETUGE; break;
745 }
746
747 if (!isRotInt8Immediate(C) && isRotInt8Immediate(NC)) {
748 RHS = DAG.getConstant(NC, MVT::i32);
749 CC = NCC;
750 }
751 }
752 }
753 Cmp = GetCMP(CC, LHS, RHS, DAG);
754 ARMCC = GetARMCC(CC, vt, DAG);
755}
756
Rafael Espindola3c000bf2006-08-21 22:00:32 +0000757static SDOperand LowerSELECT_CC(SDOperand Op, SelectionDAG &DAG) {
758 SDOperand LHS = Op.getOperand(0);
759 SDOperand RHS = Op.getOperand(1);
760 ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get();
761 SDOperand TrueVal = Op.getOperand(2);
762 SDOperand FalseVal = Op.getOperand(3);
Rafael Espindola8897a7b2006-12-14 18:58:37 +0000763 SDOperand Cmp;
Rafael Espindola9985f9f2006-12-31 18:52:39 +0000764 std::vector<SDOperand> ARMCC;
Rafael Espindola8897a7b2006-12-14 18:58:37 +0000765 LowerCMP(Cmp, ARMCC, LHS, RHS, CC, DAG);
Rafael Espindola9985f9f2006-12-31 18:52:39 +0000766
767 SDOperand Aux = FalseVal;
768 SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Flag);
769 std::vector<SDOperand>::iterator it;
770 for (it = ARMCC.begin(); it != ARMCC.end(); ++it){
771 SDOperand Flag = it == ARMCC.begin() ? Cmp : Aux.getValue(1);
772 SDOperand Ops[] = {TrueVal, Aux, *it, Flag};
773 Aux = DAG.getNode(ARMISD::SELECT, VTs, Ops, 4);
774 }
775 return Aux;
Rafael Espindola3c000bf2006-08-21 22:00:32 +0000776}
777
Rafael Espindola687bc492006-08-24 13:45:55 +0000778static SDOperand LowerBR_CC(SDOperand Op, SelectionDAG &DAG) {
779 SDOperand Chain = Op.getOperand(0);
780 ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get();
781 SDOperand LHS = Op.getOperand(2);
782 SDOperand RHS = Op.getOperand(3);
783 SDOperand Dest = Op.getOperand(4);
Rafael Espindola8897a7b2006-12-14 18:58:37 +0000784 SDOperand Cmp;
Rafael Espindola9985f9f2006-12-31 18:52:39 +0000785 std::vector<SDOperand> ARMCC;
Rafael Espindola8897a7b2006-12-14 18:58:37 +0000786 LowerCMP(Cmp, ARMCC, LHS, RHS, CC, DAG);
Rafael Espindola9985f9f2006-12-31 18:52:39 +0000787
788 SDOperand Aux = Chain;
789 SDVTList VTs = DAG.getVTList(MVT::Other, MVT::Flag);
790 std::vector<SDOperand>::iterator it;
791 for (it = ARMCC.begin(); it != ARMCC.end(); it++){
792 SDOperand Flag = it == ARMCC.begin() ? Cmp : Aux.getValue(1);
793 SDOperand Ops[] = {Aux, Dest, *it, Flag};
794 Aux = DAG.getNode(ARMISD::BR, VTs, Ops, 4);
795 }
796 return Aux;
Rafael Espindola687bc492006-08-24 13:45:55 +0000797}
798
Rafael Espindola27185192006-09-29 21:20:16 +0000799static SDOperand LowerSINT_TO_FP(SDOperand Op, SelectionDAG &DAG) {
Rafael Espindola9e071f02006-10-02 19:30:56 +0000800 SDOperand IntVal = Op.getOperand(0);
Rafael Espindola27185192006-09-29 21:20:16 +0000801 assert(IntVal.getValueType() == MVT::i32);
Rafael Espindola9e071f02006-10-02 19:30:56 +0000802 MVT::ValueType vt = Op.getValueType();
803 assert(vt == MVT::f32 ||
804 vt == MVT::f64);
Rafael Espindola27185192006-09-29 21:20:16 +0000805
806 SDOperand Tmp = DAG.getNode(ISD::BIT_CONVERT, MVT::f32, IntVal);
Rafael Espindola9e071f02006-10-02 19:30:56 +0000807 ARMISD::NodeType op = vt == MVT::f32 ? ARMISD::FSITOS : ARMISD::FSITOD;
808 return DAG.getNode(op, vt, Tmp);
Rafael Espindola27185192006-09-29 21:20:16 +0000809}
810
Rafael Espindolab47e1d02006-10-10 18:55:14 +0000811static SDOperand LowerFP_TO_SINT(SDOperand Op, SelectionDAG &DAG) {
812 assert(Op.getValueType() == MVT::i32);
813 SDOperand FloatVal = Op.getOperand(0);
814 MVT::ValueType vt = FloatVal.getValueType();
815 assert(vt == MVT::f32 || vt == MVT::f64);
816
817 ARMISD::NodeType op = vt == MVT::f32 ? ARMISD::FTOSIS : ARMISD::FTOSID;
818 SDOperand Tmp = DAG.getNode(op, MVT::f32, FloatVal);
819 return DAG.getNode(ISD::BIT_CONVERT, MVT::i32, Tmp);
820}
821
Rafael Espindolae5bbd6d2006-10-07 14:24:52 +0000822static SDOperand LowerUINT_TO_FP(SDOperand Op, SelectionDAG &DAG) {
823 SDOperand IntVal = Op.getOperand(0);
824 assert(IntVal.getValueType() == MVT::i32);
825 MVT::ValueType vt = Op.getValueType();
826 assert(vt == MVT::f32 ||
827 vt == MVT::f64);
828
829 SDOperand Tmp = DAG.getNode(ISD::BIT_CONVERT, MVT::f32, IntVal);
830 ARMISD::NodeType op = vt == MVT::f32 ? ARMISD::FUITOS : ARMISD::FUITOD;
831 return DAG.getNode(op, vt, Tmp);
832}
833
Rafael Espindola493a7fc2006-10-10 20:38:57 +0000834static SDOperand LowerFP_TO_UINT(SDOperand Op, SelectionDAG &DAG) {
835 assert(Op.getValueType() == MVT::i32);
836 SDOperand FloatVal = Op.getOperand(0);
837 MVT::ValueType vt = FloatVal.getValueType();
838 assert(vt == MVT::f32 || vt == MVT::f64);
839
840 ARMISD::NodeType op = vt == MVT::f32 ? ARMISD::FTOUIS : ARMISD::FTOUID;
841 SDOperand Tmp = DAG.getNode(op, MVT::f32, FloatVal);
842 return DAG.getNode(ISD::BIT_CONVERT, MVT::i32, Tmp);
843}
844
Rafael Espindola7bc59bc2006-05-14 22:18:28 +0000845SDOperand ARMTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
846 switch (Op.getOpcode()) {
847 default:
848 assert(0 && "Should not custom lower this!");
Rafael Espindola1c8f0532006-05-15 22:34:39 +0000849 abort();
Rafael Espindola06c1e7e2006-08-01 12:58:43 +0000850 case ISD::ConstantPool:
851 return LowerConstantPool(Op, DAG);
852 case ISD::GlobalAddress:
853 return LowerGlobalAddress(Op, DAG);
Rafael Espindolab47e1d02006-10-10 18:55:14 +0000854 case ISD::FP_TO_SINT:
855 return LowerFP_TO_SINT(Op, DAG);
Rafael Espindola27185192006-09-29 21:20:16 +0000856 case ISD::SINT_TO_FP:
857 return LowerSINT_TO_FP(Op, DAG);
Rafael Espindola493a7fc2006-10-10 20:38:57 +0000858 case ISD::FP_TO_UINT:
859 return LowerFP_TO_UINT(Op, DAG);
Rafael Espindolae5bbd6d2006-10-07 14:24:52 +0000860 case ISD::UINT_TO_FP:
861 return LowerUINT_TO_FP(Op, DAG);
Rafael Espindoladc124a22006-05-18 21:45:49 +0000862 case ISD::FORMAL_ARGUMENTS:
Rafael Espindola755be9b2006-08-25 17:55:16 +0000863 return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsFrameIndex);
Rafael Espindolac3c1a862006-05-25 11:00:18 +0000864 case ISD::CALL:
865 return LowerCALL(Op, DAG);
Rafael Espindola7bc59bc2006-05-14 22:18:28 +0000866 case ISD::RET:
867 return LowerRET(Op, DAG);
Rafael Espindola3c000bf2006-08-21 22:00:32 +0000868 case ISD::SELECT_CC:
869 return LowerSELECT_CC(Op, DAG);
Rafael Espindola687bc492006-08-24 13:45:55 +0000870 case ISD::BR_CC:
871 return LowerBR_CC(Op, DAG);
Rafael Espindola755be9b2006-08-25 17:55:16 +0000872 case ISD::VASTART:
873 return LowerVASTART(Op, DAG, VarArgsFrameIndex);
Rafael Espindola7bc59bc2006-05-14 22:18:28 +0000874 }
875}
876
877//===----------------------------------------------------------------------===//
878// Instruction Selector Implementation
879//===----------------------------------------------------------------------===//
880
881//===--------------------------------------------------------------------===//
882/// ARMDAGToDAGISel - ARM specific code to select ARM machine
883/// instructions for SelectionDAG operations.
884///
885namespace {
886class ARMDAGToDAGISel : public SelectionDAGISel {
887 ARMTargetLowering Lowering;
888
889public:
890 ARMDAGToDAGISel(TargetMachine &TM)
891 : SelectionDAGISel(Lowering), Lowering(TM) {
892 }
893
Evan Cheng9ade2182006-08-26 05:34:46 +0000894 SDNode *Select(SDOperand Op);
Rafael Espindola7bc59bc2006-05-14 22:18:28 +0000895 virtual void InstructionSelectBasicBlock(SelectionDAG &DAG);
Evan Cheng0d538262006-11-08 20:34:28 +0000896 bool SelectAddrMode1(SDOperand Op, SDOperand N, SDOperand &Arg,
897 SDOperand &Shift, SDOperand &ShiftType);
Rafael Espindolaf64945d2006-12-12 01:03:11 +0000898 bool SelectAddrMode1a(SDOperand Op, SDOperand N, SDOperand &Arg,
899 SDOperand &Shift, SDOperand &ShiftType);
Evan Cheng0d538262006-11-08 20:34:28 +0000900 bool SelectAddrMode2(SDOperand Op, SDOperand N, SDOperand &Arg,
901 SDOperand &Offset);
902 bool SelectAddrMode5(SDOperand Op, SDOperand N, SDOperand &Arg,
903 SDOperand &Offset);
Rafael Espindola7bc59bc2006-05-14 22:18:28 +0000904
905 // Include the pieces autogenerated from the target description.
906#include "ARMGenDAGISel.inc"
907};
908
909void ARMDAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) {
910 DEBUG(BB->dump());
911
912 DAG.setRoot(SelectRoot(DAG.getRoot()));
Rafael Espindola7bc59bc2006-05-14 22:18:28 +0000913 DAG.RemoveDeadNodes();
914
915 ScheduleAndEmitDAG(DAG);
916}
917
Rafael Espindola61369da2006-08-14 19:01:24 +0000918static bool isInt12Immediate(SDNode *N, short &Imm) {
919 if (N->getOpcode() != ISD::Constant)
920 return false;
921
922 int32_t t = cast<ConstantSDNode>(N)->getValue();
Rafael Espindola7246d332006-09-21 11:29:52 +0000923 int max = 1<<12;
Rafael Espindola61369da2006-08-14 19:01:24 +0000924 int min = -max;
925 if (t > min && t < max) {
926 Imm = t;
927 return true;
928 }
929 else
930 return false;
931}
932
933static bool isInt12Immediate(SDOperand Op, short &Imm) {
934 return isInt12Immediate(Op.Val, Imm);
935}
936
Evan Cheng0d538262006-11-08 20:34:28 +0000937bool ARMDAGToDAGISel::SelectAddrMode1(SDOperand Op,
938 SDOperand N,
Rafael Espindola3ad5e5c2006-09-13 12:09:43 +0000939 SDOperand &Arg,
940 SDOperand &Shift,
941 SDOperand &ShiftType) {
Rafael Espindola7cca7c52006-09-11 17:25:40 +0000942 switch(N.getOpcode()) {
Rafael Espindola7cca7c52006-09-11 17:25:40 +0000943 case ISD::Constant: {
Rafael Espindola7246d332006-09-21 11:29:52 +0000944 uint32_t val = cast<ConstantSDNode>(N)->getValue();
945 if(!isRotInt8Immediate(val)) {
Rafael Espindolaa898ce62006-12-12 17:10:13 +0000946 SDOperand Z = CurDAG->getTargetConstant(0, MVT::i32);
947 SDNode *n;
948 if (isRotInt8Immediate(~val)) {
949 SDOperand C = CurDAG->getTargetConstant(~val, MVT::i32);
950 n = CurDAG->getTargetNode(ARM::MVN, MVT::i32, C, Z, Z);
951 } else {
Reid Spencer47857812006-12-31 05:55:36 +0000952 Constant *C = ConstantInt::get(Type::Int32Ty, val);
Rafael Espindolaa898ce62006-12-12 17:10:13 +0000953 int alignment = 2;
954 SDOperand Addr = CurDAG->getTargetConstantPool(C, MVT::i32, alignment);
955 n = CurDAG->getTargetNode(ARM::LDR, MVT::i32, Addr, Z);
956 }
Rafael Espindola7246d332006-09-21 11:29:52 +0000957 Arg = SDOperand(n, 0);
958 } else
959 Arg = CurDAG->getTargetConstant(val, MVT::i32);
960
Rafael Espindola3ad5e5c2006-09-13 12:09:43 +0000961 Shift = CurDAG->getTargetConstant(0, MVT::i32);
962 ShiftType = CurDAG->getTargetConstant(ARMShift::LSL, MVT::i32);
Rafael Espindola7cca7c52006-09-11 17:25:40 +0000963 return true;
964 }
Rafael Espindola3ad5e5c2006-09-13 12:09:43 +0000965 case ISD::SRA:
966 Arg = N.getOperand(0);
967 Shift = N.getOperand(1);
968 ShiftType = CurDAG->getTargetConstant(ARMShift::ASR, MVT::i32);
969 return true;
970 case ISD::SRL:
971 Arg = N.getOperand(0);
972 Shift = N.getOperand(1);
973 ShiftType = CurDAG->getTargetConstant(ARMShift::LSR, MVT::i32);
974 return true;
975 case ISD::SHL:
976 Arg = N.getOperand(0);
977 Shift = N.getOperand(1);
978 ShiftType = CurDAG->getTargetConstant(ARMShift::LSL, MVT::i32);
979 return true;
Rafael Espindola7cca7c52006-09-11 17:25:40 +0000980 }
Rafael Espindola1b3956b2006-09-11 19:23:32 +0000981
Rafael Espindola3ad5e5c2006-09-13 12:09:43 +0000982 Arg = N;
983 Shift = CurDAG->getTargetConstant(0, MVT::i32);
984 ShiftType = CurDAG->getTargetConstant(ARMShift::LSL, MVT::i32);
Rafael Espindola1b3956b2006-09-11 19:23:32 +0000985 return true;
Rafael Espindola7cca7c52006-09-11 17:25:40 +0000986}
987
Evan Cheng0d538262006-11-08 20:34:28 +0000988bool ARMDAGToDAGISel::SelectAddrMode2(SDOperand Op, SDOperand N,
989 SDOperand &Arg, SDOperand &Offset) {
Rafael Espindola6e8c6492006-11-08 17:07:32 +0000990 //TODO: complete and cleanup!
991 SDOperand Zero = CurDAG->getTargetConstant(0, MVT::i32);
992 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(N)) {
993 Arg = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
994 Offset = Zero;
995 return true;
996 }
997 if (N.getOpcode() == ISD::ADD) {
998 short imm = 0;
999 if (isInt12Immediate(N.getOperand(1), imm)) {
1000 Offset = CurDAG->getTargetConstant(imm, MVT::i32);
1001 if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N.getOperand(0))) {
1002 Arg = CurDAG->getTargetFrameIndex(FI->getIndex(), N.getValueType());
1003 } else {
1004 Arg = N.getOperand(0);
1005 }
1006 return true; // [r+i]
1007 }
1008 }
1009 Offset = Zero;
1010 if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N))
1011 Arg = CurDAG->getTargetFrameIndex(FI->getIndex(), N.getValueType());
1012 else
1013 Arg = N;
1014 return true;
1015}
1016
Evan Cheng0d538262006-11-08 20:34:28 +00001017bool ARMDAGToDAGISel::SelectAddrMode5(SDOperand Op,
1018 SDOperand N, SDOperand &Arg,
Rafael Espindola32bd5f42006-10-17 18:04:53 +00001019 SDOperand &Offset) {
1020 //TODO: detect offset
1021 Offset = CurDAG->getTargetConstant(0, MVT::i32);
1022 Arg = N;
1023 return true;
1024}
1025
Evan Cheng9ade2182006-08-26 05:34:46 +00001026SDNode *ARMDAGToDAGISel::Select(SDOperand Op) {
Rafael Espindola337c4ad62006-06-12 12:28:08 +00001027 SDNode *N = Op.Val;
1028
1029 switch (N->getOpcode()) {
1030 default:
Evan Cheng9ade2182006-08-26 05:34:46 +00001031 return SelectCode(Op);
Rafael Espindola337c4ad62006-06-12 12:28:08 +00001032 break;
Rafael Espindolaf819a492006-11-09 13:58:55 +00001033 case ISD::FrameIndex: {
1034 int FI = cast<FrameIndexSDNode>(N)->getIndex();
1035 SDOperand Ops[] = {CurDAG->getTargetFrameIndex(FI, MVT::i32),
1036 CurDAG->getTargetConstant(0, MVT::i32),
1037 CurDAG->getTargetConstant(0, MVT::i32),
1038 CurDAG->getTargetConstant(ARMShift::LSL, MVT::i32)};
1039
1040 return CurDAG->SelectNodeTo(N, ARM::ADD, MVT::i32, Ops,
1041 sizeof(Ops)/sizeof(SDOperand));
1042 break;
Rafael Espindola337c4ad62006-06-12 12:28:08 +00001043 }
Rafael Espindolaf819a492006-11-09 13:58:55 +00001044 }
Rafael Espindola7bc59bc2006-05-14 22:18:28 +00001045}
1046
1047} // end anonymous namespace
1048
1049/// createARMISelDag - This pass converts a legalized DAG into a
1050/// ARM-specific DAG, ready for instruction scheduling.
1051///
1052FunctionPass *llvm::createARMISelDag(TargetMachine &TM) {
1053 return new ARMDAGToDAGISel(TM);
1054}