Chromium Code Reviews| 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 /// \file | 10 /// \file |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 258 } | 258 } |
| 259 } | 259 } |
| 260 | 260 |
| 261 OutArgsSizeBytes = applyStackAlignmentTy(OutArgsSizeBytes, Ty); | 261 OutArgsSizeBytes = applyStackAlignmentTy(OutArgsSizeBytes, Ty); |
| 262 OutArgsSizeBytes += typeWidthInBytesOnStack(Ty); | 262 OutArgsSizeBytes += typeWidthInBytesOnStack(Ty); |
| 263 } | 263 } |
| 264 | 264 |
| 265 return applyStackAlignment(OutArgsSizeBytes); | 265 return applyStackAlignment(OutArgsSizeBytes); |
| 266 } | 266 } |
| 267 | 267 |
| 268 void TargetARM32::genTargetHelperCallFor(Inst *Instr) { | |
| 269 switch (Instr->getKind()) { | |
| 270 default: | |
| 271 return; | |
| 272 case Inst::Arithmetic: { | |
| 273 Variable *Dest = Instr->getDest(); | |
| 274 const Type DestTy = Dest->getType(); | |
| 275 if (DestTy == IceType_i64) { | |
| 276 const InstArithmetic::OpKind Op = | |
| 277 llvm::cast<InstArithmetic>(Instr)->getOp(); | |
| 278 Operand *TargetHelper = nullptr; | |
| 279 switch (Op) { | |
| 280 default: | |
| 281 break; | |
|
Jim Stichnoth
2015/11/24 22:24:00
maybe just return here?
John
2015/11/25 16:39:56
Done.
| |
| 282 case InstArithmetic::Udiv: | |
| 283 TargetHelper = Ctx->getConstantExternSym(H_udiv_i64); | |
| 284 break; | |
| 285 case InstArithmetic::Sdiv: | |
| 286 TargetHelper = Ctx->getConstantExternSym(H_sdiv_i64); | |
| 287 break; | |
| 288 case InstArithmetic::Urem: | |
| 289 TargetHelper = Ctx->getConstantExternSym(H_urem_i64); | |
| 290 break; | |
| 291 case InstArithmetic::Srem: | |
| 292 TargetHelper = Ctx->getConstantExternSym(H_srem_i64); | |
| 293 break; | |
| 294 } | |
| 295 if (TargetHelper == nullptr) { | |
| 296 return; | |
| 297 } | |
| 298 ARM32Helpers[TargetHelper] = &TargetARM32::DivRem64Helper; | |
| 299 constexpr SizeT MaxArgs = 2; | |
| 300 constexpr bool NoTailCall = false; | |
| 301 constexpr bool IsTargetHelperCall = true; | |
| 302 auto *Call = InstCall::create(Func, MaxArgs, Dest, TargetHelper, | |
| 303 NoTailCall, IsTargetHelperCall); | |
| 304 Call->addArg(Instr->getSrc(0)); | |
| 305 Call->addArg(Instr->getSrc(1)); | |
| 306 Context.insert(Call); | |
| 307 Instr->setDeleted(); | |
| 308 } | |
| 309 return; | |
| 310 } | |
| 311 } | |
| 312 } | |
| 313 | |
| 268 void TargetARM32::findMaxStackOutArgsSize() { | 314 void TargetARM32::findMaxStackOutArgsSize() { |
| 269 // MinNeededOutArgsBytes should be updated if the Target ever creates a | 315 // MinNeededOutArgsBytes should be updated if the Target ever creates a |
| 270 // high-level InstCall that requires more stack bytes. | 316 // high-level InstCall that requires more stack bytes. |
| 271 constexpr size_t MinNeededOutArgsBytes = 0; | 317 constexpr size_t MinNeededOutArgsBytes = 0; |
| 272 MaxOutArgsSizeBytes = MinNeededOutArgsBytes; | 318 MaxOutArgsSizeBytes = MinNeededOutArgsBytes; |
| 273 for (CfgNode *Node : Func->getNodes()) { | 319 for (CfgNode *Node : Func->getNodes()) { |
| 274 Context.init(Node); | 320 Context.init(Node); |
| 275 while (!Context.atEnd()) { | 321 while (!Context.atEnd()) { |
| 276 PostIncrLoweringContext PostIncrement(Context); | 322 PostIncrLoweringContext PostIncrement(Context); |
| 277 Inst *CurInstr = Context.getCur(); | 323 Inst *CurInstr = Context.getCur(); |
| (...skipping 1357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1635 } | 1681 } |
| 1636 | 1682 |
| 1637 Operand *invertedSrc1F(TargetARM32 *Target) const { | 1683 Operand *invertedSrc1F(TargetARM32 *Target) const { |
| 1638 return legalizeToRegOrFlex(Target, | 1684 return legalizeToRegOrFlex(Target, |
| 1639 Target->getCtx()->getConstantInt32( | 1685 Target->getCtx()->getConstantInt32( |
| 1640 ~static_cast<uint32_t>(getConstantValue()))); | 1686 ~static_cast<uint32_t>(getConstantValue()))); |
| 1641 } | 1687 } |
| 1642 }; | 1688 }; |
| 1643 } // end of anonymous namespace | 1689 } // end of anonymous namespace |
| 1644 | 1690 |
| 1691 void TargetARM32::DivRem64Helper(const InstCall *Instr) { | |
| 1692 Operand *Src0 = Instr->getArg(0); | |
| 1693 Operand *Src1 = Instr->getArg(1); | |
| 1694 Int32Operands SrcsLo(loOperand(Src0), loOperand(Src1)); | |
| 1695 Int32Operands SrcsHi(hiOperand(Src0), hiOperand(Src1)); | |
| 1696 // Check for divide by 0 (ARM normally doesn't trap, but we want it to | |
| 1697 // trap for NaCl). Src1Lo and Src1Hi may have already been legalized to a | |
| 1698 // register, which will hide a constant source operand. Instead, check | |
| 1699 // the not-yet-legalized Src1 to optimize-out a divide by 0 check. | |
| 1700 if (!SrcsLo.swappedOperands() && SrcsLo.hasConstOperand()) { | |
| 1701 if (SrcsLo.getConstantValue() == 0 && SrcsHi.getConstantValue() == 0) { | |
| 1702 _trap(); | |
| 1703 return; | |
| 1704 } | |
| 1705 } else { | |
| 1706 Operand *Src1Lo = SrcsLo.unswappedSrc1R(this); | |
| 1707 Operand *Src1Hi = SrcsHi.unswappedSrc1R(this); | |
| 1708 div0Check(IceType_i64, Src1Lo, Src1Hi); | |
| 1709 } | |
| 1710 } | |
| 1711 | |
| 1645 void TargetARM32::lowerInt64Arithmetic(InstArithmetic::OpKind Op, | 1712 void TargetARM32::lowerInt64Arithmetic(InstArithmetic::OpKind Op, |
| 1646 Variable *Dest, Operand *Src0, | 1713 Variable *Dest, Operand *Src0, |
| 1647 Operand *Src1) { | 1714 Operand *Src1) { |
| 1648 Int32Operands SrcsLo(loOperand(Src0), loOperand(Src1)); | 1715 Int32Operands SrcsLo(loOperand(Src0), loOperand(Src1)); |
| 1649 Int32Operands SrcsHi(hiOperand(Src0), hiOperand(Src1)); | 1716 Int32Operands SrcsHi(hiOperand(Src0), hiOperand(Src1)); |
| 1650 assert(SrcsLo.swappedOperands() == SrcsHi.swappedOperands()); | 1717 assert(SrcsLo.swappedOperands() == SrcsHi.swappedOperands()); |
| 1651 assert(SrcsLo.hasConstOperand() == SrcsHi.hasConstOperand()); | 1718 assert(SrcsLo.hasConstOperand() == SrcsHi.hasConstOperand()); |
| 1652 | 1719 |
| 1653 // These helper-call-involved instructions are lowered in this separate | 1720 // These helper-call-involved instructions are lowered in this separate |
| 1654 // switch. This is because we would otherwise assume that we need to | 1721 // switch. This is because we would otherwise assume that we need to |
| 1655 // legalize Src0 to Src0RLo and Src0Hi. However, those go unused with | 1722 // legalize Src0 to Src0RLo and Src0Hi. However, those go unused with |
| 1656 // helper calls, and such unused/redundant instructions will fail liveness | 1723 // helper calls, and such unused/redundant instructions will fail liveness |
| 1657 // analysis under -Om1 setting. | 1724 // analysis under -Om1 setting. |
| 1658 switch (Op) { | 1725 switch (Op) { |
| 1659 default: | 1726 default: |
| 1660 break; | 1727 break; |
| 1661 case InstArithmetic::Udiv: | 1728 case InstArithmetic::Udiv: |
| 1662 case InstArithmetic::Sdiv: | 1729 case InstArithmetic::Sdiv: |
| 1663 case InstArithmetic::Urem: | 1730 case InstArithmetic::Urem: |
| 1664 case InstArithmetic::Srem: { | 1731 case InstArithmetic::Srem: { |
| 1665 // Check for divide by 0 (ARM normally doesn't trap, but we want it to | |
| 1666 // trap for NaCl). Src1Lo and Src1Hi may have already been legalized to a | |
| 1667 // register, which will hide a constant source operand. Instead, check | |
| 1668 // the not-yet-legalized Src1 to optimize-out a divide by 0 check. | |
| 1669 if (!SrcsLo.swappedOperands() && SrcsLo.hasConstOperand()) { | |
| 1670 if (SrcsLo.getConstantValue() == 0 && SrcsHi.getConstantValue() == 0) { | |
| 1671 _trap(); | |
| 1672 return; | |
| 1673 } | |
| 1674 } else { | |
| 1675 Operand *Src1Lo = SrcsLo.unswappedSrc1R(this); | |
| 1676 Operand *Src1Hi = SrcsHi.unswappedSrc1R(this); | |
| 1677 div0Check(IceType_i64, Src1Lo, Src1Hi); | |
| 1678 } | |
| 1679 // Technically, ARM has its own aeabi routines, but we can use the | 1732 // Technically, ARM has its own aeabi routines, but we can use the |
| 1680 // non-aeabi routine as well. LLVM uses __aeabi_ldivmod for div, but uses | 1733 // non-aeabi routine as well. LLVM uses __aeabi_ldivmod for div, but uses |
| 1681 // the more standard __moddi3 for rem. | 1734 // the more standard __moddi3 for rem. |
| 1682 const char *HelperName = ""; | 1735 const char *HelperName = ""; |
| 1683 switch (Op) { | 1736 switch (Op) { |
| 1684 default: | 1737 default: |
| 1685 llvm::report_fatal_error("Should have only matched div ops."); | 1738 llvm::report_fatal_error("Should have only matched div ops."); |
| 1686 break; | 1739 break; |
| 1687 case InstArithmetic::Udiv: | 1740 case InstArithmetic::Udiv: |
| 1688 HelperName = H_udiv_i64; | 1741 HelperName = H_udiv_i64; |
| (...skipping 986 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2675 case CondARM32::kNone: | 2728 case CondARM32::kNone: |
| 2676 _br(TargetFalse); | 2729 _br(TargetFalse); |
| 2677 break; | 2730 break; |
| 2678 case CondARM32::AL: | 2731 case CondARM32::AL: |
| 2679 _br(TargetTrue); | 2732 _br(TargetTrue); |
| 2680 break; | 2733 break; |
| 2681 } | 2734 } |
| 2682 } | 2735 } |
| 2683 | 2736 |
| 2684 void TargetARM32::lowerCall(const InstCall *Instr) { | 2737 void TargetARM32::lowerCall(const InstCall *Instr) { |
| 2738 Operand *CallTarget = Instr->getCallTarget(); | |
| 2739 if (Instr->isTargetHelperCall()) { | |
| 2740 (this->*ARM32Helpers[CallTarget])(Instr); | |
| 2741 } | |
| 2685 MaybeLeafFunc = false; | 2742 MaybeLeafFunc = false; |
| 2686 NeedsStackAlignment = true; | 2743 NeedsStackAlignment = true; |
| 2687 | 2744 |
| 2688 // Assign arguments to registers and stack. Also reserve stack. | 2745 // Assign arguments to registers and stack. Also reserve stack. |
| 2689 TargetARM32::CallingConv CC; | 2746 TargetARM32::CallingConv CC; |
| 2690 // Pair of Arg Operand -> GPR number assignments. | 2747 // Pair of Arg Operand -> GPR number assignments. |
| 2691 llvm::SmallVector<std::pair<Operand *, int32_t>, | 2748 llvm::SmallVector<std::pair<Operand *, int32_t>, |
| 2692 TargetARM32::CallingConv::ARM32_MAX_GPR_ARG> GPRArgs; | 2749 TargetARM32::CallingConv::ARM32_MAX_GPR_ARG> GPRArgs; |
| 2693 llvm::SmallVector<std::pair<Operand *, int32_t>, | 2750 llvm::SmallVector<std::pair<Operand *, int32_t>, |
| 2694 TargetARM32::CallingConv::ARM32_MAX_FP_REG_UNITS> FPArgs; | 2751 TargetARM32::CallingConv::ARM32_MAX_FP_REG_UNITS> FPArgs; |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2797 case IceType_v8i1: | 2854 case IceType_v8i1: |
| 2798 case IceType_v16i1: | 2855 case IceType_v16i1: |
| 2799 case IceType_v16i8: | 2856 case IceType_v16i8: |
| 2800 case IceType_v8i16: | 2857 case IceType_v8i16: |
| 2801 case IceType_v4i32: | 2858 case IceType_v4i32: |
| 2802 case IceType_v4f32: | 2859 case IceType_v4f32: |
| 2803 ReturnReg = makeReg(Dest->getType(), RegARM32::Reg_q0); | 2860 ReturnReg = makeReg(Dest->getType(), RegARM32::Reg_q0); |
| 2804 break; | 2861 break; |
| 2805 } | 2862 } |
| 2806 } | 2863 } |
| 2807 Operand *CallTarget = Instr->getCallTarget(); | |
| 2808 // TODO(jvoung): Handle sandboxing. const bool NeedSandboxing = | 2864 // TODO(jvoung): Handle sandboxing. const bool NeedSandboxing = |
| 2809 // Ctx->getFlags().getUseSandboxing(); | 2865 // Ctx->getFlags().getUseSandboxing(); |
| 2810 | 2866 |
| 2811 // Allow ConstantRelocatable to be left alone as a direct call, but force | 2867 // Allow ConstantRelocatable to be left alone as a direct call, but force |
| 2812 // other constants like ConstantInteger32 to be in a register and make it an | 2868 // other constants like ConstantInteger32 to be in a register and make it an |
| 2813 // indirect call. | 2869 // indirect call. |
| 2814 if (!llvm::isa<ConstantRelocatable>(CallTarget)) { | 2870 if (!llvm::isa<ConstantRelocatable>(CallTarget)) { |
| 2815 CallTarget = legalize(CallTarget, Legal_Reg); | 2871 CallTarget = legalize(CallTarget, Legal_Reg); |
| 2816 } | 2872 } |
| 2817 | 2873 |
| (...skipping 2912 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5730 // Technically R9 is used for TLS with Sandboxing, and we reserve it. | 5786 // Technically R9 is used for TLS with Sandboxing, and we reserve it. |
| 5731 // However, for compatibility with current NaCl LLVM, don't claim that. | 5787 // However, for compatibility with current NaCl LLVM, don't claim that. |
| 5732 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; | 5788 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; |
| 5733 } | 5789 } |
| 5734 | 5790 |
| 5735 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[IceType_NUM]; | 5791 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[IceType_NUM]; |
| 5736 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; | 5792 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; |
| 5737 llvm::SmallBitVector TargetARM32::ScratchRegs; | 5793 llvm::SmallBitVector TargetARM32::ScratchRegs; |
| 5738 | 5794 |
| 5739 } // end of namespace Ice | 5795 } // end of namespace Ice |
| OLD | NEW |