| 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 1394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1405 // | 1405 // |
| 1406 // This assumes Arg is an argument passed on the stack. This sets the frame | 1406 // This assumes Arg is an argument passed on the stack. This sets the frame |
| 1407 // offset for Arg and updates InArgsSizeBytes according to Arg's width. For an | 1407 // offset for Arg and updates InArgsSizeBytes according to Arg's width. For an |
| 1408 // I64 arg that has been split into Lo and Hi components, it calls itself | 1408 // I64 arg that has been split into Lo and Hi components, it calls itself |
| 1409 // recursively on the components, taking care to handle Lo first because of the | 1409 // recursively on the components, taking care to handle Lo first because of the |
| 1410 // little-endian architecture. Lastly, this function generates an instruction | 1410 // little-endian architecture. Lastly, this function generates an instruction |
| 1411 // to copy Arg into its assigned register if applicable. | 1411 // to copy Arg into its assigned register if applicable. |
| 1412 void TargetARM32::finishArgumentLowering(Variable *Arg, Variable *FramePtr, | 1412 void TargetARM32::finishArgumentLowering(Variable *Arg, Variable *FramePtr, |
| 1413 size_t BasicFrameOffset, | 1413 size_t BasicFrameOffset, |
| 1414 size_t *InArgsSizeBytes) { | 1414 size_t *InArgsSizeBytes) { |
| 1415 const Type Ty = Arg->getType(); |
| 1416 *InArgsSizeBytes = applyStackAlignmentTy(*InArgsSizeBytes, Ty); |
| 1417 |
| 1415 if (auto *Arg64On32 = llvm::dyn_cast<Variable64On32>(Arg)) { | 1418 if (auto *Arg64On32 = llvm::dyn_cast<Variable64On32>(Arg)) { |
| 1416 Variable *Lo = Arg64On32->getLo(); | 1419 Variable *const Lo = Arg64On32->getLo(); |
| 1417 Variable *Hi = Arg64On32->getHi(); | 1420 Variable *const Hi = Arg64On32->getHi(); |
| 1418 finishArgumentLowering(Lo, FramePtr, BasicFrameOffset, InArgsSizeBytes); | 1421 finishArgumentLowering(Lo, FramePtr, BasicFrameOffset, InArgsSizeBytes); |
| 1419 finishArgumentLowering(Hi, FramePtr, BasicFrameOffset, InArgsSizeBytes); | 1422 finishArgumentLowering(Hi, FramePtr, BasicFrameOffset, InArgsSizeBytes); |
| 1420 return; | 1423 return; |
| 1421 } | 1424 } |
| 1422 Type Ty = Arg->getType(); | |
| 1423 assert(Ty != IceType_i64); | 1425 assert(Ty != IceType_i64); |
| 1424 | 1426 |
| 1425 *InArgsSizeBytes = applyStackAlignmentTy(*InArgsSizeBytes, Ty); | |
| 1426 const int32_t ArgStackOffset = BasicFrameOffset + *InArgsSizeBytes; | 1427 const int32_t ArgStackOffset = BasicFrameOffset + *InArgsSizeBytes; |
| 1427 *InArgsSizeBytes += typeWidthInBytesOnStack(Ty); | 1428 *InArgsSizeBytes += typeWidthInBytesOnStack(Ty); |
| 1428 | 1429 |
| 1429 if (!Arg->hasReg()) { | 1430 if (!Arg->hasReg()) { |
| 1430 Arg->setStackOffset(ArgStackOffset); | 1431 Arg->setStackOffset(ArgStackOffset); |
| 1431 return; | 1432 return; |
| 1432 } | 1433 } |
| 1433 | 1434 |
| 1434 // If the argument variable has been assigned a register, we need to copy the | 1435 // If the argument variable has been assigned a register, we need to copy the |
| 1435 // value from the stack slot. | 1436 // value from the stack slot. |
| (...skipping 3160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4596 return Integer->getValue(); | 4597 return Integer->getValue(); |
| 4597 return Intrinsics::MemoryOrderInvalid; | 4598 return Intrinsics::MemoryOrderInvalid; |
| 4598 } | 4599 } |
| 4599 } // end of anonymous namespace | 4600 } // end of anonymous namespace |
| 4600 | 4601 |
| 4601 void TargetARM32::lowerLoadLinkedStoreExclusive( | 4602 void TargetARM32::lowerLoadLinkedStoreExclusive( |
| 4602 Type Ty, Operand *Addr, std::function<Variable *(Variable *)> Operation, | 4603 Type Ty, Operand *Addr, std::function<Variable *(Variable *)> Operation, |
| 4603 CondARM32::Cond Cond) { | 4604 CondARM32::Cond Cond) { |
| 4604 | 4605 |
| 4605 auto *Retry = Context.insert<InstARM32Label>(this); | 4606 auto *Retry = Context.insert<InstARM32Label>(this); |
| 4607 |
| 4606 { // scoping for loop highlighting. | 4608 { // scoping for loop highlighting. |
| 4609 Variable *Success = makeReg(IceType_i32); |
| 4607 Variable *Tmp = (Ty == IceType_i64) ? makeI64RegPair() : makeReg(Ty); | 4610 Variable *Tmp = (Ty == IceType_i64) ? makeI64RegPair() : makeReg(Ty); |
| 4608 auto *Success = makeReg(IceType_i32); | |
| 4609 auto *_0 = Ctx->getConstantZero(IceType_i32); | 4611 auto *_0 = Ctx->getConstantZero(IceType_i32); |
| 4610 | 4612 |
| 4611 Context.insert<InstFakeDef>(Tmp); | 4613 Context.insert<InstFakeDef>(Tmp); |
| 4612 Context.insert<InstFakeUse>(Tmp); | 4614 Context.insert<InstFakeUse>(Tmp); |
| 4613 Variable *AddrR = legalizeToReg(Addr); | 4615 Variable *AddrR = legalizeToReg(Addr); |
| 4614 _ldrex(Tmp, formMemoryOperand(AddrR, Ty))->setDestRedefined(); | 4616 _ldrex(Tmp, formMemoryOperand(AddrR, Ty))->setDestRedefined(); |
| 4615 auto *StoreValue = Operation(Tmp); | 4617 auto *StoreValue = Operation(Tmp); |
| 4616 assert(StoreValue->mustHaveReg()); | 4618 assert(StoreValue->mustHaveReg()); |
| 4617 _strex(Success, StoreValue, formMemoryOperand(AddrR, Ty), Cond); | 4619 // strex requires Dest to be a register other than Value or Addr. This |
| 4618 _cmp(Success, _0, Cond); | 4620 // restriction is cleanly represented by adding an "early" definition of |
| 4621 // Dest (or a latter use of all the sources.) |
| 4622 Context.insert<InstFakeDef>(Success); |
| 4623 if (Cond != CondARM32::AL) { |
| 4624 _mov_redefined(Success, legalize(_0, Legal_Reg | Legal_Flex), |
| 4625 InstARM32::getOppositeCondition(Cond)); |
| 4626 } |
| 4627 _strex(Success, StoreValue, formMemoryOperand(AddrR, Ty), Cond) |
| 4628 ->setDestRedefined(); |
| 4629 _cmp(Success, _0); |
| 4619 } | 4630 } |
| 4631 |
| 4620 _br(Retry, CondARM32::NE); | 4632 _br(Retry, CondARM32::NE); |
| 4621 } | 4633 } |
| 4622 | 4634 |
| 4623 namespace { | 4635 namespace { |
| 4624 InstArithmetic *createArithInst(Cfg *Func, uint32_t Operation, Variable *Dest, | 4636 InstArithmetic *createArithInst(Cfg *Func, uint32_t Operation, Variable *Dest, |
| 4625 Variable *Src0, Operand *Src1) { | 4637 Variable *Src0, Operand *Src1) { |
| 4626 InstArithmetic::OpKind Oper; | 4638 InstArithmetic::OpKind Oper; |
| 4627 switch (Operation) { | 4639 switch (Operation) { |
| 4628 default: | 4640 default: |
| 4629 llvm::report_fatal_error("Unknown AtomicRMW operation"); | 4641 llvm::report_fatal_error("Unknown AtomicRMW operation"); |
| (...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4880 // We require the memory address to be naturally aligned. Given that is the | 4892 // We require the memory address to be naturally aligned. Given that is the |
| 4881 // case, then normal loads are atomic. | 4893 // case, then normal loads are atomic. |
| 4882 if (!Intrinsics::isMemoryOrderValid( | 4894 if (!Intrinsics::isMemoryOrderValid( |
| 4883 ID, getConstantMemoryOrder(Instr->getArg(3)), | 4895 ID, getConstantMemoryOrder(Instr->getArg(3)), |
| 4884 getConstantMemoryOrder(Instr->getArg(4)))) { | 4896 getConstantMemoryOrder(Instr->getArg(4)))) { |
| 4885 Func->setError("Unexpected memory ordering for AtomicCmpxchg"); | 4897 Func->setError("Unexpected memory ordering for AtomicCmpxchg"); |
| 4886 return; | 4898 return; |
| 4887 } | 4899 } |
| 4888 | 4900 |
| 4889 if (DestTy == IceType_i64) { | 4901 if (DestTy == IceType_i64) { |
| 4902 Variable *LoadedValue = nullptr; |
| 4903 |
| 4890 auto *New = makeI64RegPair(); | 4904 auto *New = makeI64RegPair(); |
| 4891 Context.insert<InstFakeDef>(New); | 4905 Context.insert<InstFakeDef>(New); |
| 4892 lowerAssign(InstAssign::create(Func, New, Instr->getArg(2))); | 4906 lowerAssign(InstAssign::create(Func, New, Instr->getArg(2))); |
| 4893 | 4907 |
| 4894 auto *Expected = makeI64RegPair(); | 4908 auto *Expected = makeI64RegPair(); |
| 4895 Context.insert<InstFakeDef>(Expected); | 4909 Context.insert<InstFakeDef>(Expected); |
| 4896 lowerAssign(InstAssign::create(Func, Expected, Instr->getArg(1))); | 4910 lowerAssign(InstAssign::create(Func, Expected, Instr->getArg(1))); |
| 4897 | 4911 |
| 4898 _dmb(); | 4912 _dmb(); |
| 4899 lowerLoadLinkedStoreExclusive( | 4913 lowerLoadLinkedStoreExclusive( |
| 4900 DestTy, Instr->getArg(0), | 4914 DestTy, Instr->getArg(0), |
| 4901 [this, Expected, New, Instr, DestTy](Variable *Tmp) { | 4915 [this, Expected, New, Instr, DestTy, &LoadedValue](Variable *Tmp) { |
| 4902 auto *ExpectedLoR = llvm::cast<Variable>(loOperand(Expected)); | 4916 auto *ExpectedLoR = llvm::cast<Variable>(loOperand(Expected)); |
| 4903 auto *ExpectedHiR = llvm::cast<Variable>(hiOperand(Expected)); | 4917 auto *ExpectedHiR = llvm::cast<Variable>(hiOperand(Expected)); |
| 4904 auto *TmpLoR = llvm::cast<Variable>(loOperand(Tmp)); | 4918 auto *TmpLoR = llvm::cast<Variable>(loOperand(Tmp)); |
| 4905 auto *TmpHiR = llvm::cast<Variable>(hiOperand(Tmp)); | 4919 auto *TmpHiR = llvm::cast<Variable>(hiOperand(Tmp)); |
| 4906 _cmp(TmpLoR, ExpectedLoR); | 4920 _cmp(TmpLoR, ExpectedLoR); |
| 4907 _cmp(TmpHiR, ExpectedHiR, CondARM32::EQ); | 4921 _cmp(TmpHiR, ExpectedHiR, CondARM32::EQ); |
| 4908 // Adding an explicit use of Tmp here, or its live range will not | 4922 LoadedValue = Tmp; |
| 4909 // reach here (only those of Tmp.Lo and Tmp.Hi will.) | |
| 4910 Context.insert<InstFakeUse>(Tmp); | |
| 4911 _mov_redefined(ExpectedLoR, TmpLoR); | |
| 4912 _mov_redefined(ExpectedHiR, TmpHiR); | |
| 4913 // Same as above. | |
| 4914 Context.insert<InstFakeUse>(Tmp); | |
| 4915 return New; | 4923 return New; |
| 4916 }, | 4924 }, |
| 4917 CondARM32::EQ); | 4925 CondARM32::EQ); |
| 4918 _dmb(); | 4926 _dmb(); |
| 4919 | 4927 |
| 4920 lowerAssign(InstAssign::create(Func, Dest, Expected)); | 4928 Context.insert<InstFakeUse>(LoadedValue); |
| 4929 lowerAssign(InstAssign::create(Func, Dest, LoadedValue)); |
| 4921 // The fake-use Expected prevents the assignments to Expected (above) | 4930 // The fake-use Expected prevents the assignments to Expected (above) |
| 4922 // from being removed if Dest is not used. | 4931 // from being removed if Dest is not used. |
| 4923 Context.insert<InstFakeUse>(Expected); | 4932 Context.insert<InstFakeUse>(Expected); |
| 4924 // New needs to be alive here, or its live range will end in the | 4933 // New needs to be alive here, or its live range will end in the |
| 4925 // strex instruction. | 4934 // strex instruction. |
| 4926 Context.insert<InstFakeUse>(New); | 4935 Context.insert<InstFakeUse>(New); |
| 4927 return; | 4936 return; |
| 4928 } | 4937 } |
| 4929 | 4938 |
| 4930 auto *New = legalizeToReg(Instr->getArg(2)); | 4939 auto *New = legalizeToReg(Instr->getArg(2)); |
| 4931 auto *Expected = legalizeToReg(Instr->getArg(1)); | 4940 auto *Expected = legalizeToReg(Instr->getArg(1)); |
| 4941 Variable *LoadedValue = nullptr; |
| 4932 | 4942 |
| 4933 _dmb(); | 4943 _dmb(); |
| 4934 lowerLoadLinkedStoreExclusive( | 4944 lowerLoadLinkedStoreExclusive( |
| 4935 DestTy, | 4945 DestTy, Instr->getArg(0), |
| 4936 Instr->getArg(0), [this, Expected, New, Instr, DestTy](Variable *Tmp) { | 4946 [this, Expected, New, Instr, DestTy, &LoadedValue](Variable *Tmp) { |
| 4937 lowerIcmpCond(InstIcmp::Eq, Tmp, Expected); | 4947 lowerIcmpCond(InstIcmp::Eq, Tmp, Expected); |
| 4938 _mov_redefined(Expected, Tmp); | 4948 LoadedValue = Tmp; |
| 4939 return New; | 4949 return New; |
| 4940 }, CondARM32::EQ); | 4950 }, |
| 4951 CondARM32::EQ); |
| 4941 _dmb(); | 4952 _dmb(); |
| 4942 | 4953 |
| 4943 lowerAssign(InstAssign::create(Func, Dest, Expected)); | 4954 lowerAssign(InstAssign::create(Func, Dest, LoadedValue)); |
| 4944 Context.insert<InstFakeUse>(Expected); | 4955 Context.insert<InstFakeUse>(Expected); |
| 4945 Context.insert<InstFakeUse>(New); | 4956 Context.insert<InstFakeUse>(New); |
| 4946 return; | 4957 return; |
| 4947 } | 4958 } |
| 4948 case Intrinsics::AtomicRMW: { | 4959 case Intrinsics::AtomicRMW: { |
| 4949 if (!Intrinsics::isMemoryOrderValid( | 4960 if (!Intrinsics::isMemoryOrderValid( |
| 4950 ID, getConstantMemoryOrder(Instr->getArg(3)))) { | 4961 ID, getConstantMemoryOrder(Instr->getArg(3)))) { |
| 4951 Func->setError("Unexpected memory ordering for AtomicRMW"); | 4962 Func->setError("Unexpected memory ordering for AtomicRMW"); |
| 4952 return; | 4963 return; |
| 4953 } | 4964 } |
| (...skipping 1928 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6882 // However, for compatibility with current NaCl LLVM, don't claim that. | 6893 // However, for compatibility with current NaCl LLVM, don't claim that. |
| 6883 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; | 6894 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; |
| 6884 } | 6895 } |
| 6885 | 6896 |
| 6886 SmallBitVector TargetARM32::TypeToRegisterSet[RegARM32::RCARM32_NUM]; | 6897 SmallBitVector TargetARM32::TypeToRegisterSet[RegARM32::RCARM32_NUM]; |
| 6887 SmallBitVector TargetARM32::TypeToRegisterSetUnfiltered[RegARM32::RCARM32_NUM]; | 6898 SmallBitVector TargetARM32::TypeToRegisterSetUnfiltered[RegARM32::RCARM32_NUM]; |
| 6888 SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; | 6899 SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; |
| 6889 | 6900 |
| 6890 } // end of namespace ARM32 | 6901 } // end of namespace ARM32 |
| 6891 } // end of namespace Ice | 6902 } // end of namespace Ice |
| OLD | NEW |