OLD | NEW |
---|---|
1 //===- subzero/src/IceTargetLoweringARM32.cpp - ARM32 lowering ------------===// | 1 //===- subzero/src/IceTargetLoweringARM32.cpp - ARM32 lowering ------------===// |
2 // | 2 // |
3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 // | 9 // |
10 // This file implements the TargetLoweringARM32 class, which consists almost | 10 // This file implements the TargetLoweringARM32 class, which consists almost |
(...skipping 21 matching lines...) Loading... | |
32 | 32 |
33 namespace { | 33 namespace { |
34 void UnimplementedError(const ClFlags &Flags) { | 34 void UnimplementedError(const ClFlags &Flags) { |
35 if (!Flags.getSkipUnimplemented()) { | 35 if (!Flags.getSkipUnimplemented()) { |
36 // Use llvm_unreachable instead of report_fatal_error, which gives better | 36 // Use llvm_unreachable instead of report_fatal_error, which gives better |
37 // stack traces. | 37 // stack traces. |
38 llvm_unreachable("Not yet implemented"); | 38 llvm_unreachable("Not yet implemented"); |
39 abort(); | 39 abort(); |
40 } | 40 } |
41 } | 41 } |
42 | |
43 // The maximum number of arguments to pass in GPR registers. | |
44 const uint32_t ARM32_MAX_GPR_ARG = 4; | |
45 | |
42 } // end of anonymous namespace | 46 } // end of anonymous namespace |
43 | 47 |
44 TargetARM32::TargetARM32(Cfg *Func) | 48 TargetARM32::TargetARM32(Cfg *Func) |
45 : TargetLowering(Func), UsesFramePointer(false) { | 49 : TargetLowering(Func), UsesFramePointer(false) { |
46 // TODO: Don't initialize IntegerRegisters and friends every time. | 50 // TODO: Don't initialize IntegerRegisters and friends every time. |
47 // Instead, initialize in some sort of static initializer for the | 51 // Instead, initialize in some sort of static initializer for the |
48 // class. | 52 // class. |
49 llvm::SmallBitVector IntegerRegisters(RegARM32::Reg_NUM); | 53 llvm::SmallBitVector IntegerRegisters(RegARM32::Reg_NUM); |
50 llvm::SmallBitVector FloatRegisters(RegARM32::Reg_NUM); | 54 llvm::SmallBitVector FloatRegisters(RegARM32::Reg_NUM); |
51 llvm::SmallBitVector VectorRegisters(RegARM32::Reg_NUM); | 55 llvm::SmallBitVector VectorRegisters(RegARM32::Reg_NUM); |
(...skipping 216 matching lines...) Loading... | |
268 int32_t Offset = Var->getStackOffset(); | 272 int32_t Offset = Var->getStackOffset(); |
269 if (!hasFramePointer()) | 273 if (!hasFramePointer()) |
270 Offset += getStackAdjustment(); | 274 Offset += getStackAdjustment(); |
271 // TODO(jvoung): Handle out of range. Perhaps we need a scratch register | 275 // TODO(jvoung): Handle out of range. Perhaps we need a scratch register |
272 // to materialize a larger offset. | 276 // to materialize a larger offset. |
273 const bool SignExt = false; | 277 const bool SignExt = false; |
274 if (!OperandARM32Mem::canHoldOffset(Var->getType(), SignExt, Offset)) { | 278 if (!OperandARM32Mem::canHoldOffset(Var->getType(), SignExt, Offset)) { |
275 llvm::report_fatal_error("Illegal stack offset"); | 279 llvm::report_fatal_error("Illegal stack offset"); |
276 } | 280 } |
277 const Type FrameSPTy = IceType_i32; | 281 const Type FrameSPTy = IceType_i32; |
278 Str << "[" << getRegName(getFrameOrStackReg(), FrameSPTy) << ", " << Offset | 282 Str << "[" << getRegName(getFrameOrStackReg(), FrameSPTy); |
279 << "]"; | 283 if (Offset != 0) { |
284 Str << ", " << getConstantPrefix() << Offset; | |
285 } | |
286 Str << "]"; | |
280 } | 287 } |
281 | 288 |
282 void TargetARM32::lowerArguments() { | 289 void TargetARM32::lowerArguments() { |
283 UnimplementedError(Func->getContext()->getFlags()); | 290 VarList &Args = Func->getArgs(); |
291 // The first few integer type parameters can use r0-r3, regardless of their | |
292 // position relative to the floating-point/vector arguments in the argument | |
293 // list. Floating-point and vector arguments can use q0-q3 (aka d0-d7, | |
294 // s0-s15). | |
295 unsigned NumGPRRegsUsed = 0; | |
296 | |
297 // For each register argument, replace Arg in the argument list with the | |
298 // home register. Then generate an instruction in the prolog to copy the | |
299 // home register to the assigned location of Arg. | |
300 Context.init(Func->getEntryNode()); | |
301 Context.setInsertPoint(Context.getCur()); | |
302 | |
303 for (SizeT I = 0, E = Args.size(); I < E; ++I) { | |
304 Variable *Arg = Args[I]; | |
305 Type Ty = Arg->getType(); | |
306 // TODO(jvoung): handle float/vector types. | |
307 if (isVectorType(Ty)) { | |
308 UnimplementedError(Func->getContext()->getFlags()); | |
309 continue; | |
310 } else if (isFloatingType(Ty)) { | |
311 UnimplementedError(Func->getContext()->getFlags()); | |
312 continue; | |
313 } else if (Ty == IceType_i64) { | |
314 if (NumGPRRegsUsed >= ARM32_MAX_GPR_ARG) | |
315 continue; | |
316 int32_t RegLo = RegARM32::Reg_r0 + NumGPRRegsUsed; | |
317 int32_t RegHi = 0; | |
318 ++NumGPRRegsUsed; | |
319 // Always start i64 registers at an even register, so this may end | |
320 // up padding away a register. | |
321 if (RegLo % 2 != 0) { | |
322 ++RegLo; | |
323 ++NumGPRRegsUsed; | |
324 } | |
325 // If this leaves us without room to consume another register, | |
326 // leave any previously speculatively consumed registers as consumed. | |
327 if (NumGPRRegsUsed >= ARM32_MAX_GPR_ARG) | |
328 continue; | |
329 RegHi = RegARM32::Reg_r0 + NumGPRRegsUsed; | |
330 ++NumGPRRegsUsed; | |
331 Variable *RegisterArg = Func->makeVariable(Ty); | |
332 Variable *RegisterLo = Func->makeVariable(IceType_i32); | |
333 Variable *RegisterHi = Func->makeVariable(IceType_i32); | |
334 if (ALLOW_DUMP) { | |
335 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); | |
336 RegisterLo->setName(Func, "home_reg_lo:" + Arg->getName(Func)); | |
337 RegisterHi->setName(Func, "home_reg_hi:" + Arg->getName(Func)); | |
338 } | |
339 RegisterLo->setRegNum(RegLo); | |
340 RegisterLo->setIsArg(); | |
341 RegisterHi->setRegNum(RegHi); | |
342 RegisterHi->setIsArg(); | |
343 RegisterArg->setLoHi(RegisterLo, RegisterHi); | |
344 RegisterArg->setIsArg(); | |
345 Arg->setIsArg(false); | |
346 | |
347 Args[I] = RegisterArg; | |
348 Context.insert(InstAssign::create(Func, Arg, RegisterArg)); | |
349 continue; | |
350 } else { | |
351 assert(Ty == IceType_i32); | |
352 if (NumGPRRegsUsed >= ARM32_MAX_GPR_ARG) | |
353 continue; | |
354 int32_t RegNum = RegARM32::Reg_r0 + NumGPRRegsUsed; | |
355 ++NumGPRRegsUsed; | |
356 Variable *RegisterArg = Func->makeVariable(Ty); | |
357 if (ALLOW_DUMP) { | |
358 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); | |
359 } | |
360 RegisterArg->setRegNum(RegNum); | |
361 RegisterArg->setIsArg(); | |
362 Arg->setIsArg(false); | |
363 | |
364 Args[I] = RegisterArg; | |
365 Context.insert(InstAssign::create(Func, Arg, RegisterArg)); | |
366 } | |
367 } | |
284 } | 368 } |
285 | 369 |
286 Type TargetARM32::stackSlotType() { return IceType_i32; } | 370 Type TargetARM32::stackSlotType() { return IceType_i32; } |
287 | 371 |
288 void TargetARM32::addProlog(CfgNode *Node) { | 372 void TargetARM32::addProlog(CfgNode *Node) { |
289 (void)Node; | 373 (void)Node; |
290 UnimplementedError(Func->getContext()->getFlags()); | 374 UnimplementedError(Func->getContext()->getFlags()); |
291 } | 375 } |
292 | 376 |
293 void TargetARM32::addEpilog(CfgNode *Node) { | 377 void TargetARM32::addEpilog(CfgNode *Node) { |
294 (void)Node; | 378 (void)Node; |
295 UnimplementedError(Func->getContext()->getFlags()); | 379 UnimplementedError(Func->getContext()->getFlags()); |
296 } | 380 } |
297 | 381 |
382 void TargetARM32::split64(Variable *Var) { | |
383 assert(Var->getType() == IceType_i64); | |
384 Variable *Lo = Var->getLo(); | |
385 Variable *Hi = Var->getHi(); | |
386 if (Lo) { | |
387 assert(Hi); | |
388 return; | |
389 } | |
390 assert(Hi == nullptr); | |
391 Lo = Func->makeVariable(IceType_i32); | |
392 Hi = Func->makeVariable(IceType_i32); | |
393 if (ALLOW_DUMP) { | |
394 Lo->setName(Func, Var->getName(Func) + "__lo"); | |
395 Hi->setName(Func, Var->getName(Func) + "__hi"); | |
396 } | |
397 Var->setLoHi(Lo, Hi); | |
398 if (Var->getIsArg()) { | |
399 Lo->setIsArg(); | |
400 Hi->setIsArg(); | |
401 } | |
402 } | |
403 | |
404 Operand *TargetARM32::loOperand(Operand *Operand) { | |
405 assert(Operand->getType() == IceType_i64); | |
406 if (Operand->getType() != IceType_i64) | |
407 return Operand; | |
408 if (Variable *Var = llvm::dyn_cast<Variable>(Operand)) { | |
409 split64(Var); | |
410 return Var->getLo(); | |
411 } | |
412 if (ConstantInteger64 *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { | |
413 return Ctx->getConstantInt32(static_cast<uint32_t>(Const->getValue())); | |
414 } | |
415 if (OperandARM32Mem *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand)) { | |
416 // Conservatively disallow memory operands with side-effects (pre/post | |
417 // increment) in case of duplication. | |
418 assert(Mem->getAddrMode() == OperandARM32Mem::Offset || | |
419 Mem->getAddrMode() == OperandARM32Mem::NegOffset); | |
420 if (Mem->isRegReg()) { | |
421 return OperandARM32Mem::create(Func, IceType_i32, Mem->getBase(), | |
422 Mem->getIndex(), Mem->getShiftOp(), | |
423 Mem->getShiftAmt(), Mem->getAddrMode()); | |
424 } else { | |
425 return OperandARM32Mem::create(Func, IceType_i32, Mem->getBase(), | |
426 Mem->getOffset(), Mem->getAddrMode()); | |
427 } | |
428 } | |
429 llvm_unreachable("Unsupported operand type"); | |
430 return nullptr; | |
431 } | |
432 | |
433 Operand *TargetARM32::hiOperand(Operand *Operand) { | |
434 assert(Operand->getType() == IceType_i64); | |
435 if (Operand->getType() != IceType_i64) | |
436 return Operand; | |
437 if (Variable *Var = llvm::dyn_cast<Variable>(Operand)) { | |
438 split64(Var); | |
439 return Var->getHi(); | |
440 } | |
441 if (ConstantInteger64 *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { | |
442 return Ctx->getConstantInt32( | |
443 static_cast<uint32_t>(Const->getValue() >> 32)); | |
444 } | |
445 if (OperandARM32Mem *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand)) { | |
446 // Conservatively disallow memory operands with side-effects | |
447 // in case of duplication. | |
448 assert(Mem->getAddrMode() == OperandARM32Mem::Offset || | |
449 Mem->getAddrMode() == OperandARM32Mem::NegOffset); | |
450 const Type SplitType = IceType_i32; | |
451 if (Mem->isRegReg()) { | |
452 // We have to make a temp variable T, and add 4 to either Base or Index. | |
453 // The Index may be shifted, so adding 4 can mean something else. | |
454 // Thus, prefer T := Base + 4, and use T as the new Base. | |
455 Variable *Base = Mem->getBase(); | |
456 Constant *Four = Ctx->getConstantInt32(4); | |
457 Variable *NewBase = Func->makeVariable(Base->getType()); | |
458 lowerArithmetic(InstArithmetic::create(Func, InstArithmetic::Add, NewBase, | |
459 Base, Four)); | |
460 return OperandARM32Mem::create(Func, SplitType, NewBase, Mem->getIndex(), | |
461 Mem->getShiftOp(), Mem->getShiftAmt(), | |
462 Mem->getAddrMode()); | |
463 } else { | |
464 Variable *Base = Mem->getBase(); | |
465 ConstantInteger32 *Offset = Mem->getOffset(); | |
466 assert(!Utils::WouldOverflowAdd(Offset->getValue(), 4)); | |
467 int32_t NextOffsetVal = Offset->getValue() + 4; | |
468 const bool SignExt = false; | |
469 if (!OperandARM32Mem::canHoldOffset(SplitType, SignExt, NextOffsetVal)) { | |
470 // We have to make a temp variable and add 4 to either Base or Offset. | |
471 // If we add 4 to Offset, this will convert a non-RegReg addressing | |
472 // mode into a RegReg addressing mode. Since NaCl sandboxing disallows | |
473 // RegReg addressing modes, prefer adding to base and replacing instead. | |
474 // Thus we leave the old offset alone. | |
475 Constant *Four = Ctx->getConstantInt32(4); | |
476 Variable *NewBase = Func->makeVariable(Base->getType()); | |
477 lowerArithmetic(InstArithmetic::create(Func, InstArithmetic::Add, | |
478 NewBase, Base, Four)); | |
479 Base = NewBase; | |
480 } else { | |
481 Offset = | |
482 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(NextOffsetVal)); | |
483 } | |
484 return OperandARM32Mem::create(Func, SplitType, Base, Offset, | |
485 Mem->getAddrMode()); | |
486 } | |
487 } | |
488 llvm_unreachable("Unsupported operand type"); | |
489 return nullptr; | |
490 } | |
491 | |
298 llvm::SmallBitVector TargetARM32::getRegisterSet(RegSetMask Include, | 492 llvm::SmallBitVector TargetARM32::getRegisterSet(RegSetMask Include, |
299 RegSetMask Exclude) const { | 493 RegSetMask Exclude) const { |
300 llvm::SmallBitVector Registers(RegARM32::Reg_NUM); | 494 llvm::SmallBitVector Registers(RegARM32::Reg_NUM); |
301 | 495 |
302 #define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \ | 496 #define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \ |
303 isFP) \ | 497 isFP) \ |
304 if (scratch && (Include & RegSet_CallerSave)) \ | 498 if (scratch && (Include & RegSet_CallerSave)) \ |
305 Registers[RegARM32::val] = true; \ | 499 Registers[RegARM32::val] = true; \ |
306 if (preserved && (Include & RegSet_CalleeSave)) \ | 500 if (preserved && (Include & RegSet_CalleeSave)) \ |
307 Registers[RegARM32::val] = true; \ | 501 Registers[RegARM32::val] = true; \ |
(...skipping 23 matching lines...) Loading... | |
331 // adjustment operations implemented below assume that the stack is | 525 // adjustment operations implemented below assume that the stack is |
332 // aligned before the alloca. All the alloca code ensures that the | 526 // aligned before the alloca. All the alloca code ensures that the |
333 // stack alignment is preserved after the alloca. The stack alignment | 527 // stack alignment is preserved after the alloca. The stack alignment |
334 // restriction can be relaxed in some cases. | 528 // restriction can be relaxed in some cases. |
335 NeedsStackAlignment = true; | 529 NeedsStackAlignment = true; |
336 (void)Inst; | 530 (void)Inst; |
337 UnimplementedError(Func->getContext()->getFlags()); | 531 UnimplementedError(Func->getContext()->getFlags()); |
338 } | 532 } |
339 | 533 |
340 void TargetARM32::lowerArithmetic(const InstArithmetic *Inst) { | 534 void TargetARM32::lowerArithmetic(const InstArithmetic *Inst) { |
341 switch (Inst->getOp()) { | 535 Variable *Dest = Inst->getDest(); |
342 case InstArithmetic::_num: | 536 // TODO(jvoung): Should be able to flip Src0 and Src1 if it is easier |
343 llvm_unreachable("Unknown arithmetic operator"); | 537 // to legalize Src0 to flex or Src1 to flex and there is a reversible |
344 break; | 538 // instruction. E.g., reverse subtract with immediate, register vs |
345 case InstArithmetic::Add: | 539 // register, immediate. |
540 // Or it may be the case that the operands aren't swapped, but the | |
541 // bits can be flipped and a different operation applied. | |
542 // E.g., use BIC (bit clear) instead of AND for some masks. | |
543 Variable *Src0 = legalizeToVar(Inst->getSrc(0)); | |
544 Operand *Src1 = legalize(Inst->getSrc(1), Legal_Reg | Legal_Flex); | |
545 (void)Src0; | |
546 (void)Src1; | |
547 if (Dest->getType() == IceType_i64) { | |
346 UnimplementedError(Func->getContext()->getFlags()); | 548 UnimplementedError(Func->getContext()->getFlags()); |
347 break; | 549 } else if (isVectorType(Dest->getType())) { |
348 case InstArithmetic::And: | |
349 UnimplementedError(Func->getContext()->getFlags()); | 550 UnimplementedError(Func->getContext()->getFlags()); |
350 break; | 551 } else { // Dest->getType() is non-i64 scalar |
351 case InstArithmetic::Or: | 552 switch (Inst->getOp()) { |
352 UnimplementedError(Func->getContext()->getFlags()); | 553 case InstArithmetic::_num: |
353 break; | 554 llvm_unreachable("Unknown arithmetic operator"); |
354 case InstArithmetic::Xor: | 555 break; |
355 UnimplementedError(Func->getContext()->getFlags()); | 556 case InstArithmetic::Add: { |
356 break; | 557 UnimplementedError(Func->getContext()->getFlags()); |
357 case InstArithmetic::Sub: | 558 // Variable *T = makeReg(Dest->getType()); |
358 UnimplementedError(Func->getContext()->getFlags()); | 559 // _add(T, Src0, Src1); |
359 break; | 560 // _mov(Dest, T); |
360 case InstArithmetic::Mul: | 561 } break; |
361 UnimplementedError(Func->getContext()->getFlags()); | 562 case InstArithmetic::And: |
362 break; | 563 UnimplementedError(Func->getContext()->getFlags()); |
363 case InstArithmetic::Shl: | 564 break; |
364 UnimplementedError(Func->getContext()->getFlags()); | 565 case InstArithmetic::Or: |
365 break; | 566 UnimplementedError(Func->getContext()->getFlags()); |
366 case InstArithmetic::Lshr: | 567 break; |
367 UnimplementedError(Func->getContext()->getFlags()); | 568 case InstArithmetic::Xor: |
368 break; | 569 UnimplementedError(Func->getContext()->getFlags()); |
369 case InstArithmetic::Ashr: | 570 break; |
370 UnimplementedError(Func->getContext()->getFlags()); | 571 case InstArithmetic::Sub: |
371 break; | 572 UnimplementedError(Func->getContext()->getFlags()); |
372 case InstArithmetic::Udiv: | 573 break; |
373 UnimplementedError(Func->getContext()->getFlags()); | 574 case InstArithmetic::Mul: |
374 break; | 575 UnimplementedError(Func->getContext()->getFlags()); |
375 case InstArithmetic::Sdiv: | 576 break; |
376 UnimplementedError(Func->getContext()->getFlags()); | 577 case InstArithmetic::Shl: |
377 break; | 578 UnimplementedError(Func->getContext()->getFlags()); |
378 case InstArithmetic::Urem: | 579 break; |
379 UnimplementedError(Func->getContext()->getFlags()); | 580 case InstArithmetic::Lshr: |
380 break; | 581 UnimplementedError(Func->getContext()->getFlags()); |
381 case InstArithmetic::Srem: | 582 break; |
382 UnimplementedError(Func->getContext()->getFlags()); | 583 case InstArithmetic::Ashr: |
383 break; | 584 UnimplementedError(Func->getContext()->getFlags()); |
384 case InstArithmetic::Fadd: | 585 break; |
385 UnimplementedError(Func->getContext()->getFlags()); | 586 case InstArithmetic::Udiv: |
386 break; | 587 UnimplementedError(Func->getContext()->getFlags()); |
387 case InstArithmetic::Fsub: | 588 break; |
388 UnimplementedError(Func->getContext()->getFlags()); | 589 case InstArithmetic::Sdiv: |
389 break; | 590 UnimplementedError(Func->getContext()->getFlags()); |
390 case InstArithmetic::Fmul: | 591 break; |
391 UnimplementedError(Func->getContext()->getFlags()); | 592 case InstArithmetic::Urem: |
392 break; | 593 UnimplementedError(Func->getContext()->getFlags()); |
393 case InstArithmetic::Fdiv: | 594 break; |
394 UnimplementedError(Func->getContext()->getFlags()); | 595 case InstArithmetic::Srem: |
395 break; | 596 UnimplementedError(Func->getContext()->getFlags()); |
396 case InstArithmetic::Frem: | 597 break; |
397 UnimplementedError(Func->getContext()->getFlags()); | 598 case InstArithmetic::Fadd: |
398 break; | 599 UnimplementedError(Func->getContext()->getFlags()); |
600 break; | |
601 case InstArithmetic::Fsub: | |
602 UnimplementedError(Func->getContext()->getFlags()); | |
603 break; | |
604 case InstArithmetic::Fmul: | |
605 UnimplementedError(Func->getContext()->getFlags()); | |
606 break; | |
607 case InstArithmetic::Fdiv: | |
608 UnimplementedError(Func->getContext()->getFlags()); | |
609 break; | |
610 case InstArithmetic::Frem: | |
611 UnimplementedError(Func->getContext()->getFlags()); | |
612 break; | |
613 } | |
399 } | 614 } |
400 } | 615 } |
401 | 616 |
402 void TargetARM32::lowerAssign(const InstAssign *Inst) { | 617 void TargetARM32::lowerAssign(const InstAssign *Inst) { |
403 (void)Inst; | 618 Variable *Dest = Inst->getDest(); |
404 UnimplementedError(Func->getContext()->getFlags()); | 619 Operand *Src0 = Inst->getSrc(0); |
620 assert(Dest->getType() == Src0->getType()); | |
621 if (Dest->getType() == IceType_i64) { | |
622 Src0 = legalize(Src0); | |
623 Operand *Src0Lo = loOperand(Src0); | |
624 Operand *Src0Hi = hiOperand(Src0); | |
625 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); | |
626 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | |
627 Variable *T_Lo = nullptr, *T_Hi = nullptr; | |
628 _mov(T_Lo, Src0Lo); | |
629 _mov(DestLo, T_Lo); | |
630 _mov(T_Hi, Src0Hi); | |
631 _mov(DestHi, T_Hi); | |
632 } else { | |
633 Operand *SrcR; | |
634 if (Dest->hasReg()) { | |
635 // If Dest already has a physical register, then legalize the | |
636 // Src operand into a Variable with the same register | |
637 // assignment. This is mostly a workaround for advanced phi | |
638 // lowering's ad-hoc register allocation which assumes no | |
639 // register allocation is needed when at least one of the | |
640 // operands is non-memory. | |
641 // TODO(jvoung): check this for ARM. | |
642 SrcR = legalize(Src0, Legal_Reg, Dest->getRegNum()); | |
643 } else { | |
644 // Dest could be a stack operand. Since we could potentially need | |
645 // to do a Store (and store can only have Register operands), | |
646 // legalize this to a register. | |
647 SrcR = legalize(Src0, Legal_Reg); | |
648 } | |
649 if (isVectorType(Dest->getType())) { | |
650 UnimplementedError(Func->getContext()->getFlags()); | |
651 } else { | |
652 _mov(Dest, SrcR); | |
653 } | |
654 } | |
405 } | 655 } |
406 | 656 |
407 void TargetARM32::lowerBr(const InstBr *Inst) { | 657 void TargetARM32::lowerBr(const InstBr *Inst) { |
408 (void)Inst; | 658 (void)Inst; |
409 UnimplementedError(Func->getContext()->getFlags()); | 659 UnimplementedError(Func->getContext()->getFlags()); |
410 } | 660 } |
411 | 661 |
412 void TargetARM32::lowerCall(const InstCall *Inst) { | 662 void TargetARM32::lowerCall(const InstCall *Inst) { |
413 (void)Inst; | 663 (void)Inst; |
414 UnimplementedError(Func->getContext()->getFlags()); | 664 UnimplementedError(Func->getContext()->getFlags()); |
(...skipping 207 matching lines...) Loading... | |
622 } | 872 } |
623 } | 873 } |
624 | 874 |
625 void TargetARM32::lowerPhi(const InstPhi * /*Inst*/) { | 875 void TargetARM32::lowerPhi(const InstPhi * /*Inst*/) { |
626 Func->setError("Phi found in regular instruction list"); | 876 Func->setError("Phi found in regular instruction list"); |
627 } | 877 } |
628 | 878 |
629 void TargetARM32::lowerRet(const InstRet *Inst) { | 879 void TargetARM32::lowerRet(const InstRet *Inst) { |
630 Variable *Reg = nullptr; | 880 Variable *Reg = nullptr; |
631 if (Inst->hasRetValue()) { | 881 if (Inst->hasRetValue()) { |
632 UnimplementedError(Func->getContext()->getFlags()); | 882 Operand *Src0 = Inst->getRetValue(); |
883 if (Src0->getType() == IceType_i64) { | |
884 Variable *R0 = legalizeToVar(loOperand(Src0), RegARM32::Reg_r0); | |
885 Variable *R1 = legalizeToVar(hiOperand(Src0), RegARM32::Reg_r1); | |
886 Reg = R0; | |
887 Context.insert(InstFakeUse::create(Func, R1)); | |
888 } else if (isScalarFloatingType(Src0->getType())) { | |
889 UnimplementedError(Func->getContext()->getFlags()); | |
890 } else if (isVectorType(Src0->getType())) { | |
891 UnimplementedError(Func->getContext()->getFlags()); | |
892 } else { | |
893 Operand *Src0F = legalize(Src0, Legal_Reg | Legal_Flex); | |
894 _mov(Reg, Src0F, RegARM32::Reg_r0); | |
895 } | |
633 } | 896 } |
634 // Add a ret instruction even if sandboxing is enabled, because | 897 // Add a ret instruction even if sandboxing is enabled, because |
635 // addEpilog explicitly looks for a ret instruction as a marker for | 898 // addEpilog explicitly looks for a ret instruction as a marker for |
636 // where to insert the frame removal instructions. | 899 // where to insert the frame removal instructions. |
637 // addEpilog is responsible for restoring the "lr" register as needed | 900 // addEpilog is responsible for restoring the "lr" register as needed |
638 // prior to this ret instruction. | 901 // prior to this ret instruction. |
639 _ret(getPhysicalRegister(RegARM32::Reg_lr), Reg); | 902 _ret(getPhysicalRegister(RegARM32::Reg_lr), Reg); |
640 // Add a fake use of sp to make sure sp stays alive for the entire | 903 // Add a fake use of sp to make sure sp stays alive for the entire |
641 // function. Otherwise post-call sp adjustments get dead-code | 904 // function. Otherwise post-call sp adjustments get dead-code |
642 // eliminated. TODO: Are there more places where the fake use | 905 // eliminated. TODO: Are there more places where the fake use |
(...skipping 16 matching lines...) Loading... | |
659 void TargetARM32::doAddressOptStore() { | 922 void TargetARM32::doAddressOptStore() { |
660 UnimplementedError(Func->getContext()->getFlags()); | 923 UnimplementedError(Func->getContext()->getFlags()); |
661 } | 924 } |
662 | 925 |
663 void TargetARM32::lowerSwitch(const InstSwitch *Inst) { | 926 void TargetARM32::lowerSwitch(const InstSwitch *Inst) { |
664 (void)Inst; | 927 (void)Inst; |
665 UnimplementedError(Func->getContext()->getFlags()); | 928 UnimplementedError(Func->getContext()->getFlags()); |
666 } | 929 } |
667 | 930 |
668 void TargetARM32::lowerUnreachable(const InstUnreachable * /*Inst*/) { | 931 void TargetARM32::lowerUnreachable(const InstUnreachable * /*Inst*/) { |
669 llvm_unreachable("Not yet implemented"); | 932 UnimplementedError(Func->getContext()->getFlags()); |
670 } | 933 } |
671 | 934 |
672 // Turn an i64 Phi instruction into a pair of i32 Phi instructions, to | 935 // Turn an i64 Phi instruction into a pair of i32 Phi instructions, to |
673 // preserve integrity of liveness analysis. Undef values are also | 936 // preserve integrity of liveness analysis. Undef values are also |
674 // turned into zeroes, since loOperand() and hiOperand() don't expect | 937 // turned into zeroes, since loOperand() and hiOperand() don't expect |
675 // Undef input. | 938 // Undef input. |
676 void TargetARM32::prelowerPhis() { | 939 void TargetARM32::prelowerPhis() { |
677 UnimplementedError(Func->getContext()->getFlags()); | 940 UnimplementedError(Func->getContext()->getFlags()); |
678 } | 941 } |
679 | 942 |
680 // Lower the pre-ordered list of assignments into mov instructions. | 943 // Lower the pre-ordered list of assignments into mov instructions. |
681 // Also has to do some ad-hoc register allocation as necessary. | 944 // Also has to do some ad-hoc register allocation as necessary. |
682 void TargetARM32::lowerPhiAssignments(CfgNode *Node, | 945 void TargetARM32::lowerPhiAssignments(CfgNode *Node, |
683 const AssignList &Assignments) { | 946 const AssignList &Assignments) { |
684 (void)Node; | 947 (void)Node; |
685 (void)Assignments; | 948 (void)Assignments; |
686 UnimplementedError(Func->getContext()->getFlags()); | 949 UnimplementedError(Func->getContext()->getFlags()); |
687 } | 950 } |
688 | 951 |
952 Variable *TargetARM32::makeVectorOfZeros(Type Ty, int32_t RegNum) { | |
953 Variable *Reg = makeReg(Ty, RegNum); | |
954 UnimplementedError(Func->getContext()->getFlags()); | |
955 return Reg; | |
956 } | |
957 | |
958 // Helper for legalize() to emit the right code to lower an operand to a | |
959 // register of the appropriate type. | |
960 Variable *TargetARM32::copyToReg(Operand *Src, int32_t RegNum) { | |
961 Type Ty = Src->getType(); | |
962 Variable *Reg = makeReg(Ty, RegNum); | |
963 if (isVectorType(Ty)) { | |
964 UnimplementedError(Func->getContext()->getFlags()); | |
965 } else { | |
966 // Mov's Src operand can really only be the flexible second operand type | |
967 // or a register. Users should guarantee that. | |
968 _mov(Reg, Src); | |
969 } | |
970 return Reg; | |
971 } | |
972 | |
973 Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed, | |
974 int32_t RegNum) { | |
975 // Assert that a physical register is allowed. To date, all calls | |
976 // to legalize() allow a physical register. Legal_Flex converts | |
977 // registers to the right type OperandARM32FlexReg as needed. | |
978 assert(Allowed & Legal_Reg); | |
979 // Go through the various types of operands: | |
980 // OperandARM32Mem, OperandARM32Flex, Constant, and Variable. | |
981 // Given the above assertion, if type of operand is not legal | |
982 // (e.g., OperandARM32Mem and !Legal_Mem), we can always copy | |
983 // to a register. | |
984 if (auto Mem = llvm::dyn_cast<OperandARM32Mem>(From)) { | |
985 // Before doing anything with a Mem operand, we need to ensure | |
986 // that the Base and Index components are in physical registers. | |
987 Variable *Base = Mem->getBase(); | |
988 Variable *Index = Mem->getIndex(); | |
989 Variable *RegBase = nullptr; | |
990 Variable *RegIndex = nullptr; | |
991 if (Base) { | |
992 RegBase = legalizeToVar(Base); | |
993 } | |
994 if (Index) { | |
995 RegIndex = legalizeToVar(Index); | |
996 } | |
997 // Create a new operand if there was a change. | |
998 if (Base != RegBase || Index != RegIndex) { | |
999 // There is only a reg +/- reg or reg + imm form. | |
1000 // Figure out which to re-create. | |
1001 if (Mem->isRegReg()) { | |
1002 Mem = OperandARM32Mem::create(Func, Mem->getType(), RegBase, RegIndex, | |
1003 Mem->getShiftOp(), Mem->getShiftAmt(), | |
1004 Mem->getAddrMode()); | |
1005 } else { | |
1006 Mem = OperandARM32Mem::create(Func, Mem->getType(), RegBase, | |
1007 Mem->getOffset(), Mem->getAddrMode()); | |
1008 } | |
1009 } | |
1010 if (!(Allowed & Legal_Mem)) { | |
1011 Type Ty = Mem->getType(); | |
1012 Variable *Reg = makeReg(Ty, RegNum); | |
1013 _ldr(Reg, Mem); | |
1014 From = Reg; | |
1015 } else { | |
1016 From = Mem; | |
1017 } | |
1018 return From; | |
1019 } | |
1020 | |
1021 if (auto Flex = llvm::dyn_cast<OperandARM32Flex>(From)) { | |
1022 if (!(Allowed & Legal_Flex)) { | |
1023 if (auto FlexReg = llvm::dyn_cast<OperandARM32FlexReg>(Flex)) { | |
1024 if (FlexReg->getShiftOp() == OperandARM32::kNoShift) { | |
1025 From = FlexReg->getReg(); | |
1026 // Fall through and let From be checked as a Variable below, | |
1027 // where it may or may not need a register. | |
1028 } else { | |
1029 return copyToReg(Flex, RegNum); | |
1030 } | |
1031 } else { | |
1032 return copyToReg(Flex, RegNum); | |
1033 } | |
1034 } else { | |
1035 return From; | |
1036 } | |
1037 } | |
1038 | |
1039 if (llvm::isa<Constant>(From)) { | |
1040 if (llvm::isa<ConstantUndef>(From)) { | |
1041 // Lower undefs to zero. Another option is to lower undefs to an | |
1042 // uninitialized register; however, using an uninitialized register | |
1043 // results in less predictable code. | |
1044 if (isVectorType(From->getType())) | |
1045 return makeVectorOfZeros(From->getType(), RegNum); | |
1046 From = Ctx->getConstantZero(From->getType()); | |
1047 } | |
1048 // There should be no constants of vector type (other than undef). | |
1049 assert(!isVectorType(From->getType())); | |
1050 bool CanBeFlex = Allowed & Legal_Flex; | |
1051 if (auto C32 = llvm::dyn_cast<ConstantInteger32>(From)) { | |
1052 uint32_t RotateAmt; | |
1053 uint32_t Immed_8; | |
1054 uint32_t Value = static_cast<uint32_t>(C32->getValue()); | |
1055 // Check if the immediate will fit in a Flexible second operand, | |
1056 // if a Flexible second operand is allowed. We need to know the exact | |
1057 // value, so that rules out relocatable constants. | |
1058 // Also try the inverse and use MVN if possible. | |
1059 if (CanBeFlex && | |
1060 OperandARM32FlexImm::canHoldImm(Value, &RotateAmt, &Immed_8)) { | |
1061 return OperandARM32FlexImm::create(Func, From->getType(), Immed_8, | |
1062 RotateAmt); | |
1063 } else if (CanBeFlex && OperandARM32FlexImm::canHoldImm( | |
1064 ~Value, &RotateAmt, &Immed_8)) { | |
1065 auto InvertedFlex = OperandARM32FlexImm::create(Func, From->getType(), | |
1066 Immed_8, RotateAmt); | |
1067 Type Ty = From->getType(); | |
1068 Variable *Reg = makeReg(Ty, RegNum); | |
1069 _mvn(Reg, InvertedFlex); | |
1070 return Reg; | |
1071 } else { | |
1072 // Do a movw/movt to a register. | |
1073 Type Ty = From->getType(); | |
1074 Variable *Reg = makeReg(Ty, RegNum); | |
1075 uint32_t UpperBits = (Value >> 16) & 0xFFFF; | |
1076 _movw(Reg, | |
1077 UpperBits != 0 ? Ctx->getConstantInt32(Value & 0xFFFF) : C32); | |
1078 if (UpperBits != 0) { | |
1079 _movt(Reg, Ctx->getConstantInt32(UpperBits)); | |
1080 } | |
1081 return Reg; | |
1082 } | |
1083 } else if (auto C = llvm::dyn_cast<ConstantRelocatable>(From)) { | |
1084 Type Ty = From->getType(); | |
1085 Variable *Reg = makeReg(Ty, RegNum); | |
1086 _movw(Reg, C); | |
1087 _movt(Reg, C); | |
1088 return Reg; | |
1089 } else { | |
1090 // Load floats/doubles from literal pool. | |
1091 UnimplementedError(Func->getContext()->getFlags()); | |
1092 From = copyToReg(From, RegNum); | |
1093 } | |
1094 return From; | |
1095 } | |
1096 | |
1097 if (auto Var = llvm::dyn_cast<Variable>(From)) { | |
1098 // Check if the variable is guaranteed a physical register. This | |
1099 // can happen either when the variable is pre-colored or when it is | |
1100 // assigned infinite weight. | |
1101 bool MustHaveRegister = (Var->hasReg() || Var->getWeight().isInf()); | |
1102 // We need a new physical register for the operand if: | |
1103 // Mem is not allowed and Var isn't guaranteed a physical | |
1104 // register, or | |
1105 // RegNum is required and Var->getRegNum() doesn't match. | |
1106 if ((!(Allowed & Legal_Mem) && !MustHaveRegister) || | |
1107 (RegNum != Variable::NoRegister && RegNum != Var->getRegNum())) { | |
1108 From = copyToReg(From, RegNum); | |
1109 } | |
1110 return From; | |
1111 } | |
1112 llvm_unreachable("Unhandled operand kind in legalize()"); | |
1113 | |
1114 return From; | |
1115 } | |
1116 | |
1117 // Provide a trivial wrapper to legalize() for this common usage. | |
1118 Variable *TargetARM32::legalizeToVar(Operand *From, int32_t RegNum) { | |
1119 return llvm::cast<Variable>(legalize(From, Legal_Reg, RegNum)); | |
1120 } | |
1121 | |
1122 Variable *TargetARM32::makeReg(Type Type, int32_t RegNum) { | |
1123 // There aren't any 64-bit integer registers for ARM32. | |
1124 assert(Type != IceType_i64); | |
1125 Variable *Reg = Func->makeVariable(Type); | |
1126 if (RegNum == Variable::NoRegister) | |
1127 Reg->setWeightInfinite(); | |
1128 else | |
1129 Reg->setRegNum(RegNum); | |
1130 return Reg; | |
1131 } | |
1132 | |
689 void TargetARM32::postLower() { | 1133 void TargetARM32::postLower() { |
690 if (Ctx->getFlags().getOptLevel() == Opt_m1) | 1134 if (Ctx->getFlags().getOptLevel() == Opt_m1) |
691 return; | 1135 return; |
692 // Find two-address non-SSA instructions where Dest==Src0, and set | 1136 inferTwoAddress(); |
693 // the DestNonKillable flag to keep liveness analysis consistent. | |
694 UnimplementedError(Func->getContext()->getFlags()); | |
695 } | 1137 } |
696 | 1138 |
697 void TargetARM32::makeRandomRegisterPermutation( | 1139 void TargetARM32::makeRandomRegisterPermutation( |
698 llvm::SmallVectorImpl<int32_t> &Permutation, | 1140 llvm::SmallVectorImpl<int32_t> &Permutation, |
699 const llvm::SmallBitVector &ExcludeRegisters) const { | 1141 const llvm::SmallBitVector &ExcludeRegisters) const { |
700 (void)Permutation; | 1142 (void)Permutation; |
701 (void)ExcludeRegisters; | 1143 (void)ExcludeRegisters; |
702 UnimplementedError(Func->getContext()->getFlags()); | 1144 UnimplementedError(Func->getContext()->getFlags()); |
703 } | 1145 } |
704 | 1146 |
705 void TargetARM32::emit(const ConstantInteger32 *C) const { | 1147 void TargetARM32::emit(const ConstantInteger32 *C) const { |
706 if (!ALLOW_DUMP) | 1148 if (!ALLOW_DUMP) |
707 return; | 1149 return; |
708 Ostream &Str = Ctx->getStrEmit(); | 1150 Ostream &Str = Ctx->getStrEmit(); |
709 Str << getConstantPrefix() << C->getValue(); | 1151 Str << getConstantPrefix() << C->getValue(); |
710 } | 1152 } |
711 | 1153 |
712 void TargetARM32::emit(const ConstantInteger64 *) const { | 1154 void TargetARM32::emit(const ConstantInteger64 *) const { |
713 llvm::report_fatal_error("Not expecting to emit 64-bit integers"); | 1155 llvm::report_fatal_error("Not expecting to emit 64-bit integers"); |
714 } | 1156 } |
715 | 1157 |
716 void TargetARM32::emit(const ConstantFloat *C) const { | 1158 void TargetARM32::emit(const ConstantFloat *C) const { |
Jim Stichnoth
2015/05/18 02:10:52
btw this gives a warning about unused parameter C
jvoung (off chromium)
2015/05/18 16:26:47
Done.
| |
717 UnimplementedError(Ctx->getFlags()); | 1159 UnimplementedError(Ctx->getFlags()); |
718 } | 1160 } |
719 | 1161 |
720 void TargetARM32::emit(const ConstantDouble *C) const { | 1162 void TargetARM32::emit(const ConstantDouble *C) const { |
Jim Stichnoth
2015/05/18 02:10:52
this too
jvoung (off chromium)
2015/05/18 16:26:47
Done.
| |
721 UnimplementedError(Ctx->getFlags()); | 1163 UnimplementedError(Ctx->getFlags()); |
722 } | 1164 } |
723 | 1165 |
724 void TargetARM32::emit(const ConstantUndef *) const { | 1166 void TargetARM32::emit(const ConstantUndef *) const { |
725 llvm::report_fatal_error("undef value encountered by emitter."); | 1167 llvm::report_fatal_error("undef value encountered by emitter."); |
726 } | 1168 } |
727 | 1169 |
728 TargetDataARM32::TargetDataARM32(GlobalContext *Ctx) | 1170 TargetDataARM32::TargetDataARM32(GlobalContext *Ctx) |
729 : TargetDataLowering(Ctx) {} | 1171 : TargetDataLowering(Ctx) {} |
730 | 1172 |
(...skipping 22 matching lines...) Loading... | |
753 } | 1195 } |
754 } | 1196 } |
755 | 1197 |
756 void TargetDataARM32::lowerConstants() const { | 1198 void TargetDataARM32::lowerConstants() const { |
757 if (Ctx->getFlags().getDisableTranslation()) | 1199 if (Ctx->getFlags().getDisableTranslation()) |
758 return; | 1200 return; |
759 UnimplementedError(Ctx->getFlags()); | 1201 UnimplementedError(Ctx->getFlags()); |
760 } | 1202 } |
761 | 1203 |
762 } // end of namespace Ice | 1204 } // end of namespace Ice |
OLD | NEW |