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 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 static_assert( \ | 116 static_assert( \ |
117 _table1_##tag == _table2_##tag, \ | 117 _table1_##tag == _table2_##tag, \ |
118 "Inconsistency between ICMPARM32_TABLE and ICEINSTICMP_TABLE"); | 118 "Inconsistency between ICMPARM32_TABLE and ICEINSTICMP_TABLE"); |
119 ICEINSTICMP_TABLE | 119 ICEINSTICMP_TABLE |
120 #undef X | 120 #undef X |
121 } // end of namespace dummy1 | 121 } // end of namespace dummy1 |
122 | 122 |
123 // The maximum number of arguments to pass in GPR registers. | 123 // The maximum number of arguments to pass in GPR registers. |
124 const uint32_t ARM32_MAX_GPR_ARG = 4; | 124 const uint32_t ARM32_MAX_GPR_ARG = 4; |
125 | 125 |
| 126 // Stack alignment |
| 127 const uint32_t ARM32_STACK_ALIGNMENT_BYTES = 16; |
| 128 |
126 } // end of anonymous namespace | 129 } // end of anonymous namespace |
127 | 130 |
128 TargetARM32::TargetARM32(Cfg *Func) | 131 TargetARM32::TargetARM32(Cfg *Func) |
129 : TargetLowering(Func), UsesFramePointer(false) { | 132 : TargetLowering(Func), UsesFramePointer(false) { |
130 // TODO: Don't initialize IntegerRegisters and friends every time. | 133 // TODO: Don't initialize IntegerRegisters and friends every time. |
131 // Instead, initialize in some sort of static initializer for the | 134 // Instead, initialize in some sort of static initializer for the |
132 // class. | 135 // class. |
133 llvm::SmallBitVector IntegerRegisters(RegARM32::Reg_NUM); | 136 llvm::SmallBitVector IntegerRegisters(RegARM32::Reg_NUM); |
134 llvm::SmallBitVector FloatRegisters(RegARM32::Reg_NUM); | 137 llvm::SmallBitVector FloatRegisters(RegARM32::Reg_NUM); |
135 llvm::SmallBitVector VectorRegisters(RegARM32::Reg_NUM); | 138 llvm::SmallBitVector VectorRegisters(RegARM32::Reg_NUM); |
(...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
600 } | 603 } |
601 | 604 |
602 void TargetARM32::lowerAlloca(const InstAlloca *Inst) { | 605 void TargetARM32::lowerAlloca(const InstAlloca *Inst) { |
603 UsesFramePointer = true; | 606 UsesFramePointer = true; |
604 // Conservatively require the stack to be aligned. Some stack | 607 // Conservatively require the stack to be aligned. Some stack |
605 // adjustment operations implemented below assume that the stack is | 608 // adjustment operations implemented below assume that the stack is |
606 // aligned before the alloca. All the alloca code ensures that the | 609 // aligned before the alloca. All the alloca code ensures that the |
607 // stack alignment is preserved after the alloca. The stack alignment | 610 // stack alignment is preserved after the alloca. The stack alignment |
608 // restriction can be relaxed in some cases. | 611 // restriction can be relaxed in some cases. |
609 NeedsStackAlignment = true; | 612 NeedsStackAlignment = true; |
610 (void)Inst; | 613 |
611 UnimplementedError(Func->getContext()->getFlags()); | 614 // TODO(stichnot): minimize the number of adjustments of SP, etc. |
| 615 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); |
| 616 Variable *Dest = Inst->getDest(); |
| 617 uint32_t AlignmentParam = Inst->getAlignInBytes(); |
| 618 // For default align=0, set it to the real value 1, to avoid any |
| 619 // bit-manipulation problems below. |
| 620 AlignmentParam = std::max(AlignmentParam, 1u); |
| 621 |
| 622 // LLVM enforces power of 2 alignment. |
| 623 assert(llvm::isPowerOf2_32(AlignmentParam)); |
| 624 assert(llvm::isPowerOf2_32(ARM32_STACK_ALIGNMENT_BYTES)); |
| 625 |
| 626 uint32_t Alignment = std::max(AlignmentParam, ARM32_STACK_ALIGNMENT_BYTES); |
| 627 if (Alignment > ARM32_STACK_ALIGNMENT_BYTES) { |
| 628 alignRegisterPow2(SP, Alignment); |
| 629 } |
| 630 Operand *TotalSize = Inst->getSizeInBytes(); |
| 631 if (const auto *ConstantTotalSize = |
| 632 llvm::dyn_cast<ConstantInteger32>(TotalSize)) { |
| 633 uint32_t Value = ConstantTotalSize->getValue(); |
| 634 Value = Utils::applyAlignment(Value, Alignment); |
| 635 Operand *SubAmount = legalize(Ctx->getConstantInt32(Value)); |
| 636 _sub(SP, SP, SubAmount); |
| 637 } else { |
| 638 // Non-constant sizes need to be adjusted to the next highest |
| 639 // multiple of the required alignment at runtime. |
| 640 TotalSize = legalize(TotalSize); |
| 641 Variable *T = makeReg(IceType_i32); |
| 642 _mov(T, TotalSize); |
| 643 Operand *AddAmount = legalize(Ctx->getConstantInt32(Alignment - 1)); |
| 644 _add(T, T, AddAmount); |
| 645 alignRegisterPow2(T, Alignment); |
| 646 _sub(SP, SP, T); |
| 647 } |
| 648 _mov(Dest, SP); |
612 } | 649 } |
613 | 650 |
614 void TargetARM32::lowerArithmetic(const InstArithmetic *Inst) { | 651 void TargetARM32::lowerArithmetic(const InstArithmetic *Inst) { |
615 Variable *Dest = Inst->getDest(); | 652 Variable *Dest = Inst->getDest(); |
616 // TODO(jvoung): Should be able to flip Src0 and Src1 if it is easier | 653 // TODO(jvoung): Should be able to flip Src0 and Src1 if it is easier |
617 // to legalize Src0 to flex or Src1 to flex and there is a reversible | 654 // to legalize Src0 to flex or Src1 to flex and there is a reversible |
618 // instruction. E.g., reverse subtract with immediate, register vs | 655 // instruction. E.g., reverse subtract with immediate, register vs |
619 // register, immediate. | 656 // register, immediate. |
620 // Or it may be the case that the operands aren't swapped, but the | 657 // Or it may be the case that the operands aren't swapped, but the |
621 // bits can be flipped and a different operation applied. | 658 // bits can be flipped and a different operation applied. |
(...skipping 899 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1521 // There aren't any 64-bit integer registers for ARM32. | 1558 // There aren't any 64-bit integer registers for ARM32. |
1522 assert(Type != IceType_i64); | 1559 assert(Type != IceType_i64); |
1523 Variable *Reg = Func->makeVariable(Type); | 1560 Variable *Reg = Func->makeVariable(Type); |
1524 if (RegNum == Variable::NoRegister) | 1561 if (RegNum == Variable::NoRegister) |
1525 Reg->setWeightInfinite(); | 1562 Reg->setWeightInfinite(); |
1526 else | 1563 else |
1527 Reg->setRegNum(RegNum); | 1564 Reg->setRegNum(RegNum); |
1528 return Reg; | 1565 return Reg; |
1529 } | 1566 } |
1530 | 1567 |
| 1568 void TargetARM32::alignRegisterPow2(Variable *Reg, uint32_t Align) { |
| 1569 assert(llvm::isPowerOf2_32(Align)); |
| 1570 uint32_t RotateAmt = 0; |
| 1571 uint32_t Immed_8; |
| 1572 Operand *Mask; |
| 1573 // Use AND or BIC to mask off the bits, depending on which immediate fits |
| 1574 // (if it fits at all). Assume Align is usually small, in which case BIC |
| 1575 // works better. |
| 1576 if (OperandARM32FlexImm::canHoldImm(Align - 1, &RotateAmt, &Immed_8)) { |
| 1577 Mask = legalize(Ctx->getConstantInt32(Align - 1), Legal_Reg | Legal_Flex); |
| 1578 _bic(Reg, Reg, Mask); |
| 1579 } else { |
| 1580 Mask = legalize(Ctx->getConstantInt32(-Align), Legal_Reg | Legal_Flex); |
| 1581 _and(Reg, Reg, Mask); |
| 1582 } |
| 1583 } |
| 1584 |
1531 void TargetARM32::postLower() { | 1585 void TargetARM32::postLower() { |
1532 if (Ctx->getFlags().getOptLevel() == Opt_m1) | 1586 if (Ctx->getFlags().getOptLevel() == Opt_m1) |
1533 return; | 1587 return; |
1534 inferTwoAddress(); | 1588 inferTwoAddress(); |
1535 } | 1589 } |
1536 | 1590 |
1537 void TargetARM32::makeRandomRegisterPermutation( | 1591 void TargetARM32::makeRandomRegisterPermutation( |
1538 llvm::SmallVectorImpl<int32_t> &Permutation, | 1592 llvm::SmallVectorImpl<int32_t> &Permutation, |
1539 const llvm::SmallBitVector &ExcludeRegisters) const { | 1593 const llvm::SmallBitVector &ExcludeRegisters) const { |
1540 (void)Permutation; | 1594 (void)Permutation; |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1595 } | 1649 } |
1596 } | 1650 } |
1597 | 1651 |
1598 void TargetDataARM32::lowerConstants() const { | 1652 void TargetDataARM32::lowerConstants() const { |
1599 if (Ctx->getFlags().getDisableTranslation()) | 1653 if (Ctx->getFlags().getDisableTranslation()) |
1600 return; | 1654 return; |
1601 UnimplementedError(Ctx->getFlags()); | 1655 UnimplementedError(Ctx->getFlags()); |
1602 } | 1656 } |
1603 | 1657 |
1604 } // end of namespace Ice | 1658 } // end of namespace Ice |
OLD | NEW |