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 |