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

Side by Side Diff: src/IceTargetLoweringARM32.cpp

Issue 1768823002: Subzero. ARM32. Fix bugs uncovered by scons tests. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Fixes build break. Created 4 years, 9 months 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
« no previous file with comments | « src/IceTargetLoweringARM32.h ('k') | tests_lit/llvm2ice_tests/nacl-atomic-intrinsics.ll » ('j') | 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 1394 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
OLDNEW
« no previous file with comments | « src/IceTargetLoweringARM32.h ('k') | tests_lit/llvm2ice_tests/nacl-atomic-intrinsics.ll » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698