llvm.org GIT mirror llvm / a284584
implement a ArgumentLayout class to factor code common to LowerFORMAL_ARGUMENTS and LowerCALL implement FMDRR add support for f64 function arguments git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@30754 91177308-0d34-0410-b5e6-96231b3b80d8 Rafael Espindola 13 years ago
3 changed file(s) with 199 addition(s) and 125 deletion(s). Raw diff Collapse all Expand all
2626 #include "llvm/Target/TargetLowering.h"
2727 #include "llvm/Support/Debug.h"
2828 #include
29 #include
30 #include <set>
29 #include <vector>
3130 using namespace llvm;
3231
3332 namespace {
8887
8988 FSITOD,
9089
91 FMRRD
90 FMRRD,
91
92 FMDRR
9293 };
9394 }
9495 }
123124 case ARMISD::FSITOS: return "ARMISD::FSITOS";
124125 case ARMISD::FSITOD: return "ARMISD::FSITOD";
125126 case ARMISD::FMRRD: return "ARMISD::FMRRD";
126 }
127 }
127 case ARMISD::FMDRR: return "ARMISD::FMDRR";
128 }
129 }
130
131 class ArgumentLayout {
132 std::vector is_reg;
133 std::vector pos;
134 std::vector types;
135 public:
136 ArgumentLayout(std::vector Types) {
137 types = Types;
138
139 unsigned RegNum = 0;
140 unsigned StackOffset = 0;
141 for(std::vector::iterator I = Types.begin();
142 I != Types.end();
143 ++I) {
144 MVT::ValueType VT = *I;
145 assert(VT == MVT::i32 || VT == MVT::f32 || VT == MVT::f64);
146 unsigned size = MVT::getSizeInBits(VT)/32;
147
148 RegNum = ((RegNum + size - 1) / size) * size;
149 if (RegNum < 4) {
150 pos.push_back(RegNum);
151 is_reg.push_back(true);
152 RegNum += size;
153 } else {
154 unsigned bytes = size * 32/8;
155 StackOffset = ((StackOffset + bytes - 1) / bytes) * bytes;
156 pos.push_back(StackOffset);
157 is_reg.push_back(false);
158 StackOffset += bytes;
159 }
160 }
161 }
162 unsigned getRegisterNum(unsigned argNum) {
163 assert(isRegister(argNum));
164 return pos[argNum];
165 }
166 unsigned getOffset(unsigned argNum) {
167 assert(isOffset(argNum));
168 return pos[argNum];
169 }
170 unsigned isRegister(unsigned argNum) {
171 assert(argNum < is_reg.size());
172 return is_reg[argNum];
173 }
174 unsigned isOffset(unsigned argNum) {
175 return !isRegister(argNum);
176 }
177 MVT::ValueType getType(unsigned argNum) {
178 assert(argNum < types.size());
179 return types[argNum];
180 }
181 unsigned getStackSize(void) {
182 int last = is_reg.size() - 1;
183 if (isRegister(last))
184 return 0;
185 return getOffset(last) + MVT::getSizeInBits(getType(last))/8;
186 }
187 int lastRegArg(void) {
188 int size = is_reg.size();
189 int last = 0;
190 while(last < size && isRegister(last))
191 last++;
192 last--;
193 return last;
194 }
195 unsigned lastRegNum(void) {
196 int l = lastRegArg();
197 if (l < 0)
198 return -1;
199 unsigned r = getRegisterNum(l);
200 MVT::ValueType t = getType(l);
201 assert(t == MVT::i32 || t == MVT::f32 || t == MVT::f64);
202 if (t == MVT::f64)
203 return r + 1;
204 return r;
205 }
206 };
128207
129208 // This transforms a ISD::CALL node into a
130209 // callseq_star <- ARMISD:CALL <- callseq_end
138217 assert(isTailCall == false && "tail call not supported");
139218 SDOperand Callee = Op.getOperand(4);
140219 unsigned NumOps = (Op.getNumOperands() - 5) / 2;
141
142 // Count how many bytes are to be pushed on the stack.
143 unsigned NumBytes = 0;
144
145 // Add up all the space actually used.
146 for (unsigned i = 4; i < NumOps; ++i)
147 NumBytes += MVT::getSizeInBits(Op.getOperand(5+2*i).getValueType())/8;
148
149 // Adjust the stack pointer for the new arguments...
150 // These operations are automatically eliminated by the prolog/epilog pass
220 SDOperand StackPtr = DAG.getRegister(ARM::R13, MVT::i32);
221 static const unsigned regs[] = {
222 ARM::R0, ARM::R1, ARM::R2, ARM::R3
223 };
224
225 std::vector Types;
226 for (unsigned i = 0; i < NumOps; ++i) {
227 MVT::ValueType VT = Op.getOperand(5+2*i).getValueType();
228 Types.push_back(VT);
229 }
230 ArgumentLayout Layout(Types);
231
232 unsigned NumBytes = Layout.getStackSize();
233
151234 Chain = DAG.getCALLSEQ_START(Chain,
152235 DAG.getConstant(NumBytes, MVT::i32));
153236
154 SDOperand StackPtr = DAG.getRegister(ARM::R13, MVT::i32);
155
156 static const unsigned int num_regs = 4;
157 static const unsigned regs[num_regs] = {
158 ARM::R0, ARM::R1, ARM::R2, ARM::R3
159 };
160
161 std::vector > RegsToPass;
237 //Build a sequence of stores
162238 std::vector MemOpChains;
163
164 for (unsigned i = 0; i != NumOps; ++i) {
165 SDOperand Arg = Op.getOperand(5+2*i);
166 assert(Arg.getValueType() == MVT::i32);
167 if (i < num_regs)
168 RegsToPass.push_back(std::make_pair(regs[i], Arg));
169 else {
170 unsigned ArgOffset = (i - num_regs) * 4;
171 SDOperand PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType());
172 PtrOff = DAG.getNode(ISD::ADD, MVT::i32, StackPtr, PtrOff);
173 MemOpChains.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
174 Arg, PtrOff, DAG.getSrcValue(NULL)));
175 }
239 for (unsigned i = Layout.lastRegArg() + 1; i < NumOps; ++i) {
240 SDOperand Arg = Op.getOperand(5+2*i);
241 unsigned ArgOffset = Layout.getOffset(i);
242 SDOperand PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType());
243 PtrOff = DAG.getNode(ISD::ADD, MVT::i32, StackPtr, PtrOff);
244 MemOpChains.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
245 Arg, PtrOff, DAG.getSrcValue(NULL)));
176246 }
177247 if (!MemOpChains.empty())
178248 Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
179249 &MemOpChains[0], MemOpChains.size());
180
181 // Build a sequence of copy-to-reg nodes chained together with token chain
182 // and flag operands which copy the outgoing args into the appropriate regs.
183 SDOperand InFlag;
184 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
185 Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second,
186 InFlag);
187 InFlag = Chain.getValue(1);
188 }
189
190 std::vector NodeTys;
191 NodeTys.push_back(MVT::Other); // Returns a chain
192 NodeTys.push_back(MVT::Flag); // Returns a flag for retval copy to use.
193250
194251 // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
195252 // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
203260 Ops.push_back(Chain);
204261 Ops.push_back(Callee);
205262
206 // Add argument registers to the end of the list so that they are known live
207 // into the call.
208 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
209 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
210 RegsToPass[i].second.getValueType()));
263 // Build a sequence of copy-to-reg nodes chained together with token chain
264 // and flag operands which copy the outgoing args into the appropriate regs.
265 SDOperand InFlag;
266 for (unsigned i = 0, e = Layout.lastRegArg(); i <= e; ++i) {
267 SDOperand Arg = Op.getOperand(5+2*i);
268 unsigned Reg = regs[Layout.getRegisterNum(i)];
269 assert(Layout.getType(i) == Arg.getValueType());
270 assert(Layout.getType(i) == MVT::i32);
271 Chain = DAG.getCopyToReg(Chain, Reg, Arg, InFlag);
272 InFlag = Chain.getValue(1);
273
274 // Add argument register to the end of the list so that it is known live
275 // into the call.
276 Ops.push_back(DAG.getRegister(Reg, Arg.getValueType()));
277 }
278
279 std::vector NodeTys;
280 NodeTys.push_back(MVT::Other); // Returns a chain
281 NodeTys.push_back(MVT::Flag); // Returns a flag for retval copy to use.
211282
212283 unsigned CallOpc = ARMISD::CALL;
213284 if (InFlag.Val)
294365 return DAG.getNode(ARMISD::RET_FLAG, MVT::Other, Copy, Copy.getValue(1));
295366 }
296367
297 static SDOperand LowerFORMAL_ARGUMENT(SDOperand Op, SelectionDAG &DAG,
298 unsigned *vRegs,
299 unsigned ArgNo) {
300 MachineFunction &MF = DAG.getMachineFunction();
301 MVT::ValueType ObjectVT = Op.getValue(ArgNo).getValueType();
302 assert (ObjectVT == MVT::i32);
303 SDOperand Root = Op.getOperand(0);
304 SSARegMap *RegMap = MF.getSSARegMap();
305
306 unsigned num_regs = 4;
307 static const unsigned REGS[] = {
308 ARM::R0, ARM::R1, ARM::R2, ARM::R3
309 };
310
311 if(ArgNo < num_regs) {
312 unsigned VReg = RegMap->createVirtualRegister(&ARM::IntRegsRegClass);
313 MF.addLiveIn(REGS[ArgNo], VReg);
314 vRegs[ArgNo] = VReg;
315 return DAG.getCopyFromReg(Root, VReg, MVT::i32);
316 } else {
317 // If the argument is actually used, emit a load from the right stack
318 // slot.
319 if (!Op.Val->hasNUsesOfValue(0, ArgNo)) {
320 unsigned ArgOffset = (ArgNo - num_regs) * 4;
321
322 MachineFrameInfo *MFI = MF.getFrameInfo();
323 unsigned ObjSize = MVT::getSizeInBits(ObjectVT)/8;
324 int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
325 SDOperand FIN = DAG.getFrameIndex(FI, MVT::i32);
326 return DAG.getLoad(ObjectVT, Root, FIN,
327 DAG.getSrcValue(NULL));
328 } else {
329 // Don't emit a dead load.
330 return DAG.getNode(ISD::UNDEF, ObjectVT);
331 }
332 }
333 }
334
335368 static SDOperand LowerConstantPool(SDOperand Op, SelectionDAG &DAG) {
336369 MVT::ValueType PtrVT = Op.getValueType();
337370 ConstantPoolSDNode *CP = cast(Op);
362395
363396 static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG,
364397 int &VarArgsFrameIndex) {
398 MachineFunction &MF = DAG.getMachineFunction();
399 MachineFrameInfo *MFI = MF.getFrameInfo();
400 SSARegMap *RegMap = MF.getSSARegMap();
401 unsigned NumArgs = Op.Val->getNumValues()-1;
402 SDOperand Root = Op.getOperand(0);
403 bool isVarArg = cast(Op.getOperand(2))->getValue() != 0;
404 static const unsigned REGS[] = {
405 ARM::R0, ARM::R1, ARM::R2, ARM::R3
406 };
407
408 std::vector Types(Op.Val->value_begin(), Op.Val->value_end() - 1);
409 ArgumentLayout Layout(Types);
410
365411 std::vector ArgValues;
366 SDOperand Root = Op.getOperand(0);
367 unsigned VRegs[4];
368
369 unsigned NumArgs = Op.Val->getNumValues()-1;
370412 for (unsigned ArgNo = 0; ArgNo < NumArgs; ++ArgNo) {
371 SDOperand ArgVal = LowerFORMAL_ARGUMENT(Op, DAG, VRegs, ArgNo);
372
373 ArgValues.push_back(ArgVal);
374 }
375
376 bool isVarArg = cast(Op.getOperand(2))->getValue() != 0;
413 MVT::ValueType VT = Types[ArgNo];
414
415 SDOperand Value;
416 if (Layout.isRegister(ArgNo)) {
417 assert(VT == MVT::i32 || VT == MVT::f32 || VT == MVT::f64);
418 unsigned RegNum = Layout.getRegisterNum(ArgNo);
419 unsigned Reg1 = REGS[RegNum];
420 unsigned VReg1 = RegMap->createVirtualRegister(&ARM::IntRegsRegClass);
421 SDOperand Value1 = DAG.getCopyFromReg(Root, VReg1, MVT::i32);
422 MF.addLiveIn(Reg1, VReg1);
423 if (VT == MVT::f64) {
424 unsigned Reg2 = REGS[RegNum + 1];
425 unsigned VReg2 = RegMap->createVirtualRegister(&ARM::IntRegsRegClass);
426 SDOperand Value2 = DAG.getCopyFromReg(Root, VReg2, MVT::i32);
427 MF.addLiveIn(Reg2, VReg2);
428 Value = DAG.getNode(ARMISD::FMDRR, MVT::f64, Value1, Value2);
429 } else {
430 Value = Value1;
431 if (VT == MVT::f32)
432 Value = DAG.getNode(ISD::BIT_CONVERT, VT, Value);
433 }
434 } else {
435 // If the argument is actually used, emit a load from the right stack
436 // slot.
437 if (!Op.Val->hasNUsesOfValue(0, ArgNo)) {
438 unsigned Offset = Layout.getOffset(ArgNo);
439 unsigned Size = MVT::getSizeInBits(VT)/8;
440 int FI = MFI->CreateFixedObject(Size, Offset);
441 SDOperand FIN = DAG.getFrameIndex(FI, VT);
442 Value = DAG.getLoad(VT, Root, FIN, DAG.getSrcValue(NULL));
443 } else {
444 Value = DAG.getNode(ISD::UNDEF, VT);
445 }
446 }
447 ArgValues.push_back(Value);
448 }
449
450 unsigned NextRegNum = Layout.lastRegNum() + 1;
451
377452 if (isVarArg) {
378 MachineFunction &MF = DAG.getMachineFunction();
379 SSARegMap *RegMap = MF.getSSARegMap();
380 MachineFrameInfo *MFI = MF.getFrameInfo();
453 //If this function is vararg we must store the remaing
454 //registers so that they can be acessed with va_start
381455 VarArgsFrameIndex = MFI->CreateFixedObject(MVT::getSizeInBits(MVT::i32)/8,
382 -16 + NumArgs * 4);
383
384
385 static const unsigned REGS[] = {
386 ARM::R0, ARM::R1, ARM::R2, ARM::R3
387 };
388 // If this function is vararg, store r0-r3 to their spots on the stack
389 // so that they may be loaded by deferencing the result of va_next.
456 -16 + NextRegNum * 4);
457
390458 SmallVector MemOps;
391 for (unsigned ArgNo = 0; ArgNo < 4; ++ArgNo) {
392 int ArgOffset = - (4 - ArgNo) * 4;
459 for (unsigned RegNo = NextRegNum; RegNo < 4; ++RegNo) {
460 int RegOffset = - (4 - RegNo) * 4;
393461 int FI = MFI->CreateFixedObject(MVT::getSizeInBits(MVT::i32)/8,
394 ArgOffset);
462 RegOffset);
395463 SDOperand FIN = DAG.getFrameIndex(FI, MVT::i32);
396464
397 unsigned VReg;
398 if (ArgNo < NumArgs)
399 VReg = VRegs[ArgNo];
400 else
401 VReg = RegMap->createVirtualRegister(&ARM::IntRegsRegClass);
402 if (ArgNo >= NumArgs)
403 MF.addLiveIn(REGS[ArgNo], VReg);
465 unsigned VReg = RegMap->createVirtualRegister(&ARM::IntRegsRegClass);
466 MF.addLiveIn(REGS[RegNo], VReg);
404467
405468 SDOperand Val = DAG.getCopyFromReg(Root, VReg, MVT::i32);
406469 SDOperand Store = DAG.getNode(ISD::STORE, MVT::Other, Val.getValue(1),
7878
7979 def SDTarmfmrrd : SDTypeProfile<0, 3, [SDTCisInt<0>, SDTCisInt<1>, SDTCisFP<2>]>;
8080 def armfmrrd : SDNode<"ARMISD::FMRRD", SDTarmfmrrd, [SDNPHasChain, SDNPOutFlag]>;
81
82 def SDTarmfmdrr : SDTypeProfile<1, 2, [SDTCisFP<0>, SDTCisInt<1>, SDTCisInt<2>]>;
83 def armfmdrr : SDNode<"ARMISD::FMDRR", SDTarmfmdrr, []>;
8184
8285 def ADJCALLSTACKUP : InstARM<(ops i32imm:$amt),
8386 "!ADJCALLSTACKUP $amt",
174177 def FMRRD : InstARM<(ops IntRegs:$i0, IntRegs:$i1, DFPRegs:$src),
175178 "fmrrd $i0, $i1, $src", [(armfmrrd IntRegs:$i0, IntRegs:$i1, DFPRegs:$src)]>;
176179
180 def FMDRR : InstARM<(ops DFPRegs:$dst, IntRegs:$i0, IntRegs:$i1),
181 "fmdrr $dst, $i0, $i1", [(set DFPRegs:$dst, (armfmdrr IntRegs:$i0, IntRegs:$i1))]>;
182
177183 def FSITOS : InstARM<(ops FPRegs:$dst, FPRegs:$src),
178184 "fsitos $dst, $src", [(set FPRegs:$dst, (armfsitos FPRegs:$src))]>;
179185
0 ; RUN: llvm-as < %s | llc -march=arm &&
1 ; RUN: llvm-as < %s | llc -march=arm | grep fmsr | wc -l | grep 2 &&
1 ; RUN: llvm-as < %s | llc -march=arm | grep fmsr | wc -l | grep 2 &&
22 ; RUN: llvm-as < %s | llc -march=arm | grep fsitos &&
33 ; RUN: llvm-as < %s | llc -march=arm | grep fmrs &&
44 ; RUN: llvm-as < %s | llc -march=arm | grep fsitod &&
5 ; RUN: llvm-as < %s | llc -march=arm | grep fmrrd &&
5 ; RUN: llvm-as < %s | llc -march=arm | grep fmrrd | wc -l | grep 2 &&
6 ; RUN: llvm-as < %s | llc -march=arm | grep fmdrr | wc -l | grep 1 &&
67 ; RUN: llvm-as < %s | llc -march=arm | grep flds &&
78 ; RUN: llvm-as < %s | llc -march=arm | grep ".word.*1065353216"
89
2223 entry:
2324 ret float 1.000000e+00
2425 }
26
27 double %f2(double %a) {
28 ret double %a
29 }