Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(298)

Side by Side Diff: src/IceTargetLoweringARM32.cpp

Issue 1474883002: Subzero. ARM32. Pre-lowers calls to ARM32 Helpers. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« src/IceTargetLoweringARM32.h ('K') | « src/IceTargetLoweringARM32.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« src/IceTargetLoweringARM32.h ('K') | « src/IceTargetLoweringARM32.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698