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 457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 468 "Infinite-weight Variable has no register assigned"); | 468 "Infinite-weight Variable has no register assigned"); |
| 469 } | 469 } |
| 470 int32_t Offset = Var->getStackOffset(); | 470 int32_t Offset = Var->getStackOffset(); |
| 471 int32_t BaseRegNum = Var->getBaseRegNum(); | 471 int32_t BaseRegNum = Var->getBaseRegNum(); |
| 472 if (BaseRegNum == Variable::NoRegister) { | 472 if (BaseRegNum == Variable::NoRegister) { |
| 473 BaseRegNum = getFrameOrStackReg(); | 473 BaseRegNum = getFrameOrStackReg(); |
| 474 if (!hasFramePointer()) | 474 if (!hasFramePointer()) |
| 475 Offset += getStackAdjustment(); | 475 Offset += getStackAdjustment(); |
| 476 } | 476 } |
| 477 const Type VarTy = Var->getType(); | 477 const Type VarTy = Var->getType(); |
| 478 if (!isLegalMemOffset(VarTy, Offset)) { | |
| 479 llvm::report_fatal_error("Illegal stack offset"); | |
| 480 } | |
| 481 Str << "[" << getRegName(BaseRegNum, VarTy); | 478 Str << "[" << getRegName(BaseRegNum, VarTy); |
| 482 if (Offset != 0) { | 479 if (Offset != 0) { |
| 483 Str << ", " << getConstantPrefix() << Offset; | 480 Str << ", " << getConstantPrefix() << Offset; |
| 484 } | 481 } |
| 485 Str << "]"; | 482 Str << "]"; |
| 486 } | 483 } |
| 487 | 484 |
| 488 bool TargetARM32::CallingConv::I64InRegs(std::pair<int32_t, int32_t> *Regs) { | 485 bool TargetARM32::CallingConv::I64InRegs(std::pair<int32_t, int32_t> *Regs) { |
| 489 if (NumGPRRegsUsed >= ARM32_MAX_GPR_ARG) | 486 if (NumGPRRegsUsed >= ARM32_MAX_GPR_ARG) |
| 490 return false; | 487 return false; |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 618 // Helper function for addProlog(). | 615 // Helper function for addProlog(). |
| 619 // | 616 // |
| 620 // This assumes Arg is an argument passed on the stack. This sets the frame | 617 // This assumes Arg is an argument passed on the stack. This sets the frame |
| 621 // offset for Arg and updates InArgsSizeBytes according to Arg's width. For an | 618 // offset for Arg and updates InArgsSizeBytes according to Arg's width. For an |
| 622 // I64 arg that has been split into Lo and Hi components, it calls itself | 619 // I64 arg that has been split into Lo and Hi components, it calls itself |
| 623 // recursively on the components, taking care to handle Lo first because of the | 620 // recursively on the components, taking care to handle Lo first because of the |
| 624 // little-endian architecture. Lastly, this function generates an instruction | 621 // little-endian architecture. Lastly, this function generates an instruction |
| 625 // to copy Arg into its assigned register if applicable. | 622 // to copy Arg into its assigned register if applicable. |
| 626 void TargetARM32::finishArgumentLowering(Variable *Arg, Variable *FramePtr, | 623 void TargetARM32::finishArgumentLowering(Variable *Arg, Variable *FramePtr, |
| 627 size_t BasicFrameOffset, | 624 size_t BasicFrameOffset, |
| 628 size_t &InArgsSizeBytes) { | 625 size_t *InArgsSizeBytes) { |
| 629 if (auto *Arg64On32 = llvm::dyn_cast<Variable64On32>(Arg)) { | 626 if (auto *Arg64On32 = llvm::dyn_cast<Variable64On32>(Arg)) { |
| 630 Variable *Lo = Arg64On32->getLo(); | 627 Variable *Lo = Arg64On32->getLo(); |
| 631 Variable *Hi = Arg64On32->getHi(); | 628 Variable *Hi = Arg64On32->getHi(); |
| 632 finishArgumentLowering(Lo, FramePtr, BasicFrameOffset, InArgsSizeBytes); | 629 finishArgumentLowering(Lo, FramePtr, BasicFrameOffset, InArgsSizeBytes); |
| 633 finishArgumentLowering(Hi, FramePtr, BasicFrameOffset, InArgsSizeBytes); | 630 finishArgumentLowering(Hi, FramePtr, BasicFrameOffset, InArgsSizeBytes); |
| 634 return; | 631 return; |
| 635 } | 632 } |
| 636 Type Ty = Arg->getType(); | 633 Type Ty = Arg->getType(); |
| 637 InArgsSizeBytes = applyStackAlignmentTy(InArgsSizeBytes, Ty); | 634 assert(Ty != IceType_i64); |
| 638 Arg->setStackOffset(BasicFrameOffset + InArgsSizeBytes); | 635 |
| 639 InArgsSizeBytes += typeWidthInBytesOnStack(Ty); | 636 *InArgsSizeBytes = applyStackAlignmentTy(*InArgsSizeBytes, Ty); |
| 640 // If the argument variable has been assigned a register, we need to load the | 637 const int32_t ArgStackOffset = BasicFrameOffset + *InArgsSizeBytes; |
| 638 *InArgsSizeBytes += typeWidthInBytesOnStack(Ty); | |
| 639 | |
| 640 if (!Arg->hasReg()) { | |
| 641 Arg->setStackOffset(ArgStackOffset); | |
| 642 return; | |
| 643 } | |
| 644 | |
| 645 // If the argument variable has been assigned a register, we need to copy the | |
| 641 // value from the stack slot. | 646 // value from the stack slot. |
| 642 if (Arg->hasReg()) { | 647 Variable *Parameter = Func->makeVariable(Ty); |
| 643 assert(Ty != IceType_i64); | 648 Parameter->setMustNotHaveReg(); |
| 644 // This should be simple, just load the parameter off the stack using a nice | 649 Parameter->setStackOffset(ArgStackOffset); |
| 645 // sp + imm addressing mode. Because ARM, we can't do that (e.g., VLDR, for | 650 _mov(Arg, Parameter); |
| 646 // fp types, cannot have an index register), so we legalize the memory | |
| 647 // operand instead. | |
| 648 auto *Mem = OperandARM32Mem::create( | |
| 649 Func, Ty, FramePtr, llvm::cast<ConstantInteger32>( | |
| 650 Ctx->getConstantInt32(Arg->getStackOffset()))); | |
| 651 _mov(Arg, legalizeToReg(Mem, Arg->getRegNum())); | |
| 652 // This argument-copying instruction uses an explicit OperandARM32Mem | |
| 653 // operand instead of a Variable, so its fill-from-stack operation has to | |
| 654 // be tracked separately for statistics. | |
| 655 Ctx->statsUpdateFills(); | |
| 656 } | |
| 657 } | 651 } |
| 658 | 652 |
| 659 Type TargetARM32::stackSlotType() { return IceType_i32; } | 653 Type TargetARM32::stackSlotType() { return IceType_i32; } |
| 660 | 654 |
| 661 void TargetARM32::addProlog(CfgNode *Node) { | 655 void TargetARM32::addProlog(CfgNode *Node) { |
| 662 // Stack frame layout: | 656 // Stack frame layout: |
| 663 // | 657 // |
| 664 // +------------------------+ | 658 // +------------------------+ |
| 665 // | 1. preserved registers | | 659 // | 1. preserved registers | |
| 666 // +------------------------+ | 660 // +------------------------+ |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 747 CalleeSaves[RegARM32::Reg_lr] = true; | 741 CalleeSaves[RegARM32::Reg_lr] = true; |
| 748 RegsUsed[RegARM32::Reg_lr] = true; | 742 RegsUsed[RegARM32::Reg_lr] = true; |
| 749 } | 743 } |
| 750 for (SizeT i = 0; i < CalleeSaves.size(); ++i) { | 744 for (SizeT i = 0; i < CalleeSaves.size(); ++i) { |
| 751 if (RegARM32::isI64RegisterPair(i)) { | 745 if (RegARM32::isI64RegisterPair(i)) { |
| 752 // We don't save register pairs explicitly. Instead, we rely on the code | 746 // We don't save register pairs explicitly. Instead, we rely on the code |
| 753 // fake-defing/fake-using each register in the pair. | 747 // fake-defing/fake-using each register in the pair. |
| 754 continue; | 748 continue; |
| 755 } | 749 } |
| 756 if (CalleeSaves[i] && RegsUsed[i]) { | 750 if (CalleeSaves[i] && RegsUsed[i]) { |
| 757 // TODO(jvoung): do separate vpush for each floating point register | |
| 758 // segment and += 4, or 8 depending on type. | |
| 759 ++NumCallee; | 751 ++NumCallee; |
| 760 Variable *PhysicalRegister = getPhysicalRegister(i); | 752 Variable *PhysicalRegister = getPhysicalRegister(i); |
| 761 PreservedRegsSizeBytes += | 753 PreservedRegsSizeBytes += |
| 762 typeWidthInBytesOnStack(PhysicalRegister->getType()); | 754 typeWidthInBytesOnStack(PhysicalRegister->getType()); |
| 763 GPRsToPreserve.push_back(getPhysicalRegister(i)); | 755 GPRsToPreserve.push_back(getPhysicalRegister(i)); |
| 764 } | 756 } |
| 765 } | 757 } |
| 766 Ctx->statsUpdateRegistersSaved(NumCallee); | 758 Ctx->statsUpdateRegistersSaved(NumCallee); |
| 767 if (!GPRsToPreserve.empty()) | 759 if (!GPRsToPreserve.empty()) |
| 768 _push(GPRsToPreserve); | 760 _push(GPRsToPreserve); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 830 InRegs = CC.FPInReg(Ty, &DummyReg); | 822 InRegs = CC.FPInReg(Ty, &DummyReg); |
| 831 } else if (Ty == IceType_i64) { | 823 } else if (Ty == IceType_i64) { |
| 832 std::pair<int32_t, int32_t> DummyRegs; | 824 std::pair<int32_t, int32_t> DummyRegs; |
| 833 InRegs = CC.I64InRegs(&DummyRegs); | 825 InRegs = CC.I64InRegs(&DummyRegs); |
| 834 } else { | 826 } else { |
| 835 assert(Ty == IceType_i32); | 827 assert(Ty == IceType_i32); |
| 836 int32_t DummyReg; | 828 int32_t DummyReg; |
| 837 InRegs = CC.I32InReg(&DummyReg); | 829 InRegs = CC.I32InReg(&DummyReg); |
| 838 } | 830 } |
| 839 if (!InRegs) | 831 if (!InRegs) |
| 840 finishArgumentLowering(Arg, FramePtr, BasicFrameOffset, InArgsSizeBytes); | 832 finishArgumentLowering(Arg, FramePtr, BasicFrameOffset, &InArgsSizeBytes); |
| 841 } | 833 } |
| 842 | 834 |
| 843 // Fill in stack offsets for locals. | 835 // Fill in stack offsets for locals. |
| 844 assignVarStackSlots(SortedSpilledVariables, SpillAreaPaddingBytes, | 836 assignVarStackSlots(SortedSpilledVariables, SpillAreaPaddingBytes, |
| 845 SpillAreaSizeBytes, GlobalsAndSubsequentPaddingSize, | 837 SpillAreaSizeBytes, GlobalsAndSubsequentPaddingSize, |
| 846 UsesFramePointer); | 838 UsesFramePointer); |
| 847 this->HasComputedFrame = true; | 839 this->HasComputedFrame = true; |
| 848 | 840 |
| 849 if (BuildDefs::dump() && Func->isVerbose(IceV_Frame)) { | 841 if (BuildDefs::dump() && Func->isVerbose(IceV_Frame)) { |
| 850 OstreamLocker _(Func->getContext()); | 842 OstreamLocker _(Func->getContext()); |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 974 Operand *OffsetVal = legalize(Ctx->getConstantInt32(Offset), | 966 Operand *OffsetVal = legalize(Ctx->getConstantInt32(Offset), |
| 975 Legal_Reg | Legal_Flex, getReservedTmpReg()); | 967 Legal_Reg | Legal_Flex, getReservedTmpReg()); |
| 976 Variable *ScratchReg = makeReg(IceType_i32, getReservedTmpReg()); | 968 Variable *ScratchReg = makeReg(IceType_i32, getReservedTmpReg()); |
| 977 if (ShouldSub) | 969 if (ShouldSub) |
| 978 _sub(ScratchReg, OrigBaseReg, OffsetVal); | 970 _sub(ScratchReg, OrigBaseReg, OffsetVal); |
| 979 else | 971 else |
| 980 _add(ScratchReg, OrigBaseReg, OffsetVal); | 972 _add(ScratchReg, OrigBaseReg, OffsetVal); |
| 981 return ScratchReg; | 973 return ScratchReg; |
| 982 } | 974 } |
| 983 | 975 |
| 984 StackVariable *TargetARM32::legalizeStackSlot(Type Ty, int32_t Offset, | 976 OperandARM32Mem *TargetARM32::createMemOperand(Type Ty, int32_t Offset, |
| 985 int32_t StackAdjust, | 977 int32_t StackAdjust, |
| 986 Variable *OrigBaseReg, | 978 Variable *OrigBaseReg, |
| 987 Variable **NewBaseReg, | 979 Variable **NewBaseReg, |
| 988 int32_t *NewBaseOffset) { | 980 int32_t *NewBaseOffset) { |
| 981 if (isLegalMemOffset(Ty, Offset + StackAdjust)) { | |
| 982 return OperandARM32Mem::create( | |
| 983 Func, Ty, OrigBaseReg, llvm::cast<ConstantInteger32>( | |
| 984 Ctx->getConstantInt32(Offset + StackAdjust)), | |
| 985 OperandARM32Mem::Offset); | |
| 986 } | |
| 987 | |
| 989 if (*NewBaseReg == nullptr) { | 988 if (*NewBaseReg == nullptr) { |
| 990 *NewBaseReg = newBaseRegister(Offset, StackAdjust, OrigBaseReg); | 989 *NewBaseReg = newBaseRegister(Offset, StackAdjust, OrigBaseReg); |
| 991 *NewBaseOffset = Offset + StackAdjust; | 990 *NewBaseOffset = Offset + StackAdjust; |
| 992 } | 991 } |
| 993 | 992 |
| 994 int32_t OffsetDiff = Offset + StackAdjust - *NewBaseOffset; | 993 int32_t OffsetDiff = Offset + StackAdjust - *NewBaseOffset; |
| 995 if (!isLegalMemOffset(Ty, OffsetDiff)) { | 994 if (!isLegalMemOffset(Ty, OffsetDiff)) { |
| 996 *NewBaseReg = newBaseRegister(Offset, StackAdjust, OrigBaseReg); | 995 *NewBaseReg = newBaseRegister(Offset, StackAdjust, OrigBaseReg); |
| 997 *NewBaseOffset = Offset + StackAdjust; | 996 *NewBaseOffset = Offset + StackAdjust; |
| 998 OffsetDiff = 0; | 997 OffsetDiff = 0; |
| 999 } | 998 } |
| 1000 | 999 |
| 1001 StackVariable *NewDest = Func->makeVariable<StackVariable>(Ty); | 1000 return OperandARM32Mem::create( |
| 1002 NewDest->setMustNotHaveReg(); | 1001 Func, Ty, *NewBaseReg, |
| 1003 NewDest->setBaseRegNum((*NewBaseReg)->getRegNum()); | 1002 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(OffsetDiff)), |
| 1004 NewDest->setStackOffset(OffsetDiff); | 1003 OperandARM32Mem::Offset); |
| 1005 return NewDest; | |
| 1006 } | 1004 } |
| 1007 | 1005 |
| 1008 void TargetARM32::legalizeMovStackAddrImm(InstARM32Mov *MovInstr, | 1006 void TargetARM32::legalizeMov(InstARM32Mov *MovInstr, int32_t StackAdjust, |
| 1009 int32_t StackAdjust, | 1007 Variable *OrigBaseReg, Variable **NewBaseReg, |
| 1010 Variable *OrigBaseReg, | 1008 int32_t *NewBaseOffset) { |
| 1011 Variable **NewBaseReg, | |
| 1012 int32_t *NewBaseOffset) { | |
| 1013 Variable *Dest = MovInstr->getDest(); | 1009 Variable *Dest = MovInstr->getDest(); |
| 1014 assert(Dest != nullptr); | 1010 assert(Dest != nullptr); |
| 1015 Type DestTy = Dest->getType(); | 1011 Type DestTy = Dest->getType(); |
| 1016 assert(DestTy != IceType_i64); | 1012 assert(DestTy != IceType_i64); |
| 1017 | 1013 |
| 1018 Operand *Src = MovInstr->getSrc(0); | 1014 Operand *Src = MovInstr->getSrc(0); |
| 1019 Type SrcTy = Src->getType(); | 1015 Type SrcTy = Src->getType(); |
| 1016 (void)SrcTy; | |
| 1020 assert(SrcTy != IceType_i64); | 1017 assert(SrcTy != IceType_i64); |
| 1021 | 1018 |
| 1022 if (MovInstr->isMultiDest() || MovInstr->isMultiSource()) | 1019 if (MovInstr->isMultiDest() || MovInstr->isMultiSource()) |
| 1023 return; | 1020 return; |
| 1024 | 1021 |
| 1025 bool Legalized = false; | 1022 bool Legalized = false; |
| 1026 if (!Dest->hasReg()) { | 1023 if (!Dest->hasReg()) { |
| 1027 assert(llvm::cast<Variable>(Src)->hasReg()); | 1024 auto *const SrcR = llvm::cast<Variable>(Src); |
|
Jim Stichnoth
2015/11/22 03:40:47
"auto *const" seems odd -- did you mean "const aut
John
2015/11/23 18:52:56
No, I meant auto *const. Removing as git grep 'aut
| |
| 1025 assert(SrcR->hasReg()); | |
| 1028 const int32_t Offset = Dest->getStackOffset(); | 1026 const int32_t Offset = Dest->getStackOffset(); |
| 1029 if (!isLegalMemOffset(DestTy, Offset + StackAdjust)) { | 1027 // This is a _mov(Mem(), Variable), i.e., a store. |
| 1030 Legalized = true; | 1028 _str(SrcR, createMemOperand(DestTy, Offset, StackAdjust, OrigBaseReg, |
| 1031 Dest = legalizeStackSlot(DestTy, Offset, StackAdjust, OrigBaseReg, | 1029 NewBaseReg, NewBaseOffset), |
| 1032 NewBaseReg, NewBaseOffset); | 1030 MovInstr->getPredicate()); |
| 1033 } | 1031 // _str() does not have a Dest, so we add a fake-def(Dest). |
| 1032 Context.insert(InstFakeDef::create(Func, Dest)); | |
| 1033 Legalized = true; | |
| 1034 } else if (auto *Var = llvm::dyn_cast<Variable>(Src)) { | 1034 } else if (auto *Var = llvm::dyn_cast<Variable>(Src)) { |
| 1035 if (!Var->hasReg()) { | 1035 if (!Var->hasReg()) { |
| 1036 const int32_t Offset = Var->getStackOffset(); | 1036 const int32_t Offset = Var->getStackOffset(); |
| 1037 if (!isLegalMemOffset(SrcTy, Offset + StackAdjust)) { | 1037 _ldr(Dest, createMemOperand(DestTy, Offset, StackAdjust, OrigBaseReg, |
| 1038 Legalized = true; | 1038 NewBaseReg, NewBaseOffset), |
| 1039 Src = legalizeStackSlot(SrcTy, Offset, StackAdjust, OrigBaseReg, | 1039 MovInstr->getPredicate()); |
| 1040 NewBaseReg, NewBaseOffset); | 1040 Legalized = true; |
| 1041 } | |
| 1042 } | |
| 1043 } else if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Src)) { | |
| 1044 if (ConstantInteger32 *OffsetOp = Mem->getOffset()) { | |
| 1045 const int32_t Offset = OffsetOp->getValue(); | |
| 1046 if (!isLegalMemOffset(SrcTy, Offset + StackAdjust)) { | |
| 1047 assert(Mem->getBase()->hasReg()); | |
| 1048 assert(Mem->getBase()->getRegNum() == (int32_t)getFrameOrStackReg()); | |
| 1049 Legalized = true; | |
| 1050 Src = legalizeStackSlot(SrcTy, Offset, StackAdjust, OrigBaseReg, | |
| 1051 NewBaseReg, NewBaseOffset); | |
| 1052 } | |
| 1053 } | 1041 } |
| 1054 } | 1042 } |
| 1055 | 1043 |
| 1056 if (Legalized) { | 1044 if (Legalized) { |
| 1057 if (MovInstr->isDestRedefined()) { | 1045 if (MovInstr->isDestRedefined()) { |
| 1058 _mov_redefined(Dest, Src, MovInstr->getPredicate()); | 1046 _set_dest_redefined(); |
| 1059 } else { | |
| 1060 _mov(Dest, Src, MovInstr->getPredicate()); | |
| 1061 } | 1047 } |
| 1062 MovInstr->setDeleted(); | 1048 MovInstr->setDeleted(); |
| 1063 } | 1049 } |
| 1064 } | 1050 } |
| 1065 | 1051 |
| 1066 void TargetARM32::legalizeStackSlots() { | 1052 void TargetARM32::legalizeStackSlots() { |
| 1067 // If a stack variable's frame offset doesn't fit, convert from: | 1053 // If a stack variable's frame offset doesn't fit, convert from: |
| 1068 // ldr X, OFF[SP] | 1054 // ldr X, OFF[SP] |
| 1069 // to: | 1055 // to: |
| 1070 // movw/movt TMP, OFF_PART | 1056 // movw/movt TMP, OFF_PART |
| 1071 // add TMP, TMP, SP | 1057 // add TMP, TMP, SP |
| 1072 // ldr X, OFF_MORE[TMP] | 1058 // ldr X, OFF_MORE[TMP] |
| 1073 // | 1059 // |
| 1074 // This is safe because we have reserved TMP, and add for ARM does not | 1060 // This is safe because we have reserved TMP, and add for ARM does not |
| 1075 // clobber the flags register. | 1061 // clobber the flags register. |
| 1076 Func->dump("Before legalizeStackSlots"); | 1062 Func->dump("Before legalizeStackSlots"); |
| 1077 assert(hasComputedFrame()); | 1063 assert(hasComputedFrame()); |
| 1078 // Early exit, if SpillAreaSizeBytes is really small. | |
| 1079 // TODO(jpp): this is not safe -- loads and stores of q registers can't have | |
| 1080 // offsets. | |
| 1081 if (isLegalMemOffset(IceType_v4i32, SpillAreaSizeBytes)) | |
| 1082 return; | |
| 1083 Variable *OrigBaseReg = getPhysicalRegister(getFrameOrStackReg()); | 1064 Variable *OrigBaseReg = getPhysicalRegister(getFrameOrStackReg()); |
| 1084 int32_t StackAdjust = 0; | 1065 int32_t StackAdjust = 0; |
| 1085 // Do a fairly naive greedy clustering for now. Pick the first stack slot | 1066 // Do a fairly naive greedy clustering for now. Pick the first stack slot |
| 1086 // that's out of bounds and make a new base reg using the architecture's temp | 1067 // that's out of bounds and make a new base reg using the architecture's temp |
| 1087 // register. If that works for the next slot, then great. Otherwise, create a | 1068 // register. If that works for the next slot, then great. Otherwise, create a |
| 1088 // new base register, clobbering the previous base register. Never share a | 1069 // new base register, clobbering the previous base register. Never share a |
| 1089 // base reg across different basic blocks. This isn't ideal if local and | 1070 // base reg across different basic blocks. This isn't ideal if local and |
| 1090 // multi-block variables are far apart and their references are interspersed. | 1071 // multi-block variables are far apart and their references are interspersed. |
| 1091 // It may help to be more coordinated about assign stack slot numbers and may | 1072 // It may help to be more coordinated about assign stack slot numbers and may |
| 1092 // help to assign smaller offsets to higher-weight variables so that they | 1073 // help to assign smaller offsets to higher-weight variables so that they |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 1115 NewBaseOffset += AdjInst->getAmount(); | 1096 NewBaseOffset += AdjInst->getAmount(); |
| 1116 continue; | 1097 continue; |
| 1117 } | 1098 } |
| 1118 if (llvm::isa<InstARM32Call>(CurInstr)) { | 1099 if (llvm::isa<InstARM32Call>(CurInstr)) { |
| 1119 NewBaseOffset -= StackAdjust; | 1100 NewBaseOffset -= StackAdjust; |
| 1120 StackAdjust = 0; | 1101 StackAdjust = 0; |
| 1121 continue; | 1102 continue; |
| 1122 } | 1103 } |
| 1123 } | 1104 } |
| 1124 | 1105 |
| 1125 // The Lowering ensures that ldr and str always have legal Mem operands. | |
| 1126 // The only other instruction that may access memory is mov. | |
| 1127 if (auto *MovInstr = llvm::dyn_cast<InstARM32Mov>(CurInstr)) { | 1106 if (auto *MovInstr = llvm::dyn_cast<InstARM32Mov>(CurInstr)) { |
| 1128 legalizeMovStackAddrImm(MovInstr, StackAdjust, OrigBaseReg, &NewBaseReg, | 1107 legalizeMov(MovInstr, StackAdjust, OrigBaseReg, &NewBaseReg, |
| 1129 &NewBaseOffset); | 1108 &NewBaseOffset); |
| 1130 } | 1109 } |
| 1131 } | 1110 } |
| 1132 } | 1111 } |
| 1133 } | 1112 } |
| 1134 | 1113 |
| 1135 Operand *TargetARM32::loOperand(Operand *Operand) { | 1114 Operand *TargetARM32::loOperand(Operand *Operand) { |
| 1136 assert(Operand->getType() == IceType_i64); | 1115 assert(Operand->getType() == IceType_i64); |
| 1137 if (Operand->getType() != IceType_i64) | 1116 if (Operand->getType() != IceType_i64) |
| 1138 return Operand; | 1117 return Operand; |
| 1139 if (auto *Var64On32 = llvm::dyn_cast<Variable64On32>(Operand)) | 1118 if (auto *Var64On32 = llvm::dyn_cast<Variable64On32>(Operand)) |
| (...skipping 3453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4593 Context.insert(InstFakeDef::create(Func, Reg)); | 4572 Context.insert(InstFakeDef::create(Func, Reg)); |
| 4594 UnimplementedError(Func->getContext()->getFlags()); | 4573 UnimplementedError(Func->getContext()->getFlags()); |
| 4595 return Reg; | 4574 return Reg; |
| 4596 } | 4575 } |
| 4597 | 4576 |
| 4598 // Helper for legalize() to emit the right code to lower an operand to a | 4577 // Helper for legalize() to emit the right code to lower an operand to a |
| 4599 // register of the appropriate type. | 4578 // register of the appropriate type. |
| 4600 Variable *TargetARM32::copyToReg(Operand *Src, int32_t RegNum) { | 4579 Variable *TargetARM32::copyToReg(Operand *Src, int32_t RegNum) { |
| 4601 Type Ty = Src->getType(); | 4580 Type Ty = Src->getType(); |
| 4602 Variable *Reg = makeReg(Ty, RegNum); | 4581 Variable *Reg = makeReg(Ty, RegNum); |
| 4603 _mov(Reg, Src); | 4582 if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Src)) { |
| 4583 _ldr(Reg, Mem); | |
| 4584 } else { | |
| 4585 _mov(Reg, Src); | |
| 4586 } | |
| 4604 return Reg; | 4587 return Reg; |
| 4605 } | 4588 } |
| 4606 | 4589 |
| 4607 Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed, | 4590 Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed, |
| 4608 int32_t RegNum) { | 4591 int32_t RegNum) { |
| 4609 Type Ty = From->getType(); | 4592 Type Ty = From->getType(); |
| 4610 // Assert that a physical register is allowed. To date, all calls to | 4593 // Assert that a physical register is allowed. To date, all calls to |
| 4611 // legalize() allow a physical register. Legal_Flex converts registers to the | 4594 // legalize() allow a physical register. Legal_Flex converts registers to the |
| 4612 // right type OperandARM32FlexReg as needed. | 4595 // right type OperandARM32FlexReg as needed. |
| 4613 assert(Allowed & Legal_Reg); | 4596 assert(Allowed & Legal_Reg); |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 4634 // Before doing anything with a Mem operand, we need to ensure that the | 4617 // Before doing anything with a Mem operand, we need to ensure that the |
| 4635 // Base and Index components are in physical registers. | 4618 // Base and Index components are in physical registers. |
| 4636 Variable *Base = Mem->getBase(); | 4619 Variable *Base = Mem->getBase(); |
| 4637 Variable *Index = Mem->getIndex(); | 4620 Variable *Index = Mem->getIndex(); |
| 4638 ConstantInteger32 *Offset = Mem->getOffset(); | 4621 ConstantInteger32 *Offset = Mem->getOffset(); |
| 4639 assert(Index == nullptr || Offset == nullptr); | 4622 assert(Index == nullptr || Offset == nullptr); |
| 4640 Variable *RegBase = nullptr; | 4623 Variable *RegBase = nullptr; |
| 4641 Variable *RegIndex = nullptr; | 4624 Variable *RegIndex = nullptr; |
| 4642 assert(Base); | 4625 assert(Base); |
| 4643 RegBase = legalizeToReg(Base); | 4626 RegBase = legalizeToReg(Base); |
| 4644 bool InvalidImm = false; | |
| 4645 assert(Ty < MemTraitsSize); | 4627 assert(Ty < MemTraitsSize); |
| 4646 if (Index) { | 4628 if (Index) { |
| 4647 assert(Offset == nullptr); | 4629 assert(Offset == nullptr); |
| 4648 assert(MemTraits[Ty].CanHaveIndex); | 4630 assert(MemTraits[Ty].CanHaveIndex); |
| 4649 RegIndex = legalizeToReg(Index); | 4631 RegIndex = legalizeToReg(Index); |
| 4650 } | 4632 } |
| 4651 if (Offset && Offset->getValue() != 0) { | 4633 if (Offset && Offset->getValue() != 0) { |
| 4652 assert(Index == nullptr); | 4634 assert(Index == nullptr); |
| 4653 static constexpr bool ZeroExt = false; | 4635 static constexpr bool ZeroExt = false; |
| 4654 assert(MemTraits[Ty].CanHaveImm); | 4636 assert(MemTraits[Ty].CanHaveImm); |
| 4655 if (!OperandARM32Mem::canHoldOffset(Ty, ZeroExt, Offset->getValue())) { | 4637 if (!OperandARM32Mem::canHoldOffset(Ty, ZeroExt, Offset->getValue())) { |
| 4656 assert(RegBase->hasReg()); | 4638 llvm::report_fatal_error("Invalid memory offset."); |
| 4657 assert(RegBase->getRegNum() == (int32_t)getFrameOrStackReg()); | |
| 4658 // We are a bit more lenient with invalid immediate when accessing the | |
| 4659 // stack here, and then rely on legalizeStackSlots() to fix things as | |
| 4660 // appropriate. | |
| 4661 InvalidImm = true; | |
| 4662 } | 4639 } |
| 4663 } | 4640 } |
| 4664 | 4641 |
| 4665 // Create a new operand if there was a change. | 4642 // Create a new operand if there was a change. |
| 4666 if (Base != RegBase || Index != RegIndex) { | 4643 if (Base != RegBase || Index != RegIndex) { |
| 4667 // There is only a reg +/- reg or reg + imm form. | 4644 // There is only a reg +/- reg or reg + imm form. |
| 4668 // Figure out which to re-create. | 4645 // Figure out which to re-create. |
| 4669 if (RegIndex) { | 4646 if (RegIndex) { |
| 4670 Mem = OperandARM32Mem::create(Func, Ty, RegBase, RegIndex, | 4647 Mem = OperandARM32Mem::create(Func, Ty, RegBase, RegIndex, |
| 4671 Mem->getShiftOp(), Mem->getShiftAmt(), | 4648 Mem->getShiftOp(), Mem->getShiftAmt(), |
| 4672 Mem->getAddrMode()); | 4649 Mem->getAddrMode()); |
| 4673 } else { | 4650 } else { |
| 4674 Mem = OperandARM32Mem::create(Func, Ty, RegBase, Offset, | 4651 Mem = OperandARM32Mem::create(Func, Ty, RegBase, Offset, |
| 4675 Mem->getAddrMode()); | 4652 Mem->getAddrMode()); |
| 4676 } | 4653 } |
| 4677 } | 4654 } |
| 4678 if (Allowed & Legal_Mem) { | 4655 if (Allowed & Legal_Mem) { |
| 4679 From = Mem; | 4656 From = Mem; |
| 4680 } else { | 4657 } else { |
| 4681 Variable *Reg = makeReg(Ty, RegNum); | 4658 Variable *Reg = makeReg(Ty, RegNum); |
| 4682 if (InvalidImm) { | 4659 _ldr(Reg, Mem); |
| 4683 // If Mem has an invalid immediate, we legalize it to a Reg using mov | |
| 4684 // instead of ldr because legalizeStackSlots() will later kick in and | |
| 4685 // fix the immediate for us. | |
| 4686 _mov(Reg, Mem); | |
| 4687 } else { | |
| 4688 _ldr(Reg, Mem); | |
| 4689 } | |
| 4690 | |
| 4691 From = Reg; | 4660 From = Reg; |
| 4692 } | 4661 } |
| 4693 return From; | 4662 return From; |
| 4694 } | 4663 } |
| 4695 | 4664 |
| 4696 if (auto *Flex = llvm::dyn_cast<OperandARM32Flex>(From)) { | 4665 if (auto *Flex = llvm::dyn_cast<OperandARM32Flex>(From)) { |
| 4697 if (!(Allowed & Legal_Flex)) { | 4666 if (!(Allowed & Legal_Flex)) { |
| 4698 if (auto *FlexReg = llvm::dyn_cast<OperandARM32FlexReg>(Flex)) { | 4667 if (auto *FlexReg = llvm::dyn_cast<OperandARM32FlexReg>(Flex)) { |
| 4699 if (FlexReg->getShiftOp() == OperandARM32::kNoShift) { | 4668 if (FlexReg->getShiftOp() == OperandARM32::kNoShift) { |
| 4700 From = FlexReg->getReg(); | 4669 From = FlexReg->getReg(); |
| (...skipping 711 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5412 // Technically R9 is used for TLS with Sandboxing, and we reserve it. | 5381 // Technically R9 is used for TLS with Sandboxing, and we reserve it. |
| 5413 // However, for compatibility with current NaCl LLVM, don't claim that. | 5382 // However, for compatibility with current NaCl LLVM, don't claim that. |
| 5414 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; | 5383 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; |
| 5415 } | 5384 } |
| 5416 | 5385 |
| 5417 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[IceType_NUM]; | 5386 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[IceType_NUM]; |
| 5418 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; | 5387 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; |
| 5419 llvm::SmallBitVector TargetARM32::ScratchRegs; | 5388 llvm::SmallBitVector TargetARM32::ScratchRegs; |
| 5420 | 5389 |
| 5421 } // end of namespace Ice | 5390 } // end of namespace Ice |
| OLD | NEW |