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