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 /* | |
Karl
2015/11/18 18:40:42
Remove comment?
John
2015/11/19 13:41:22
Oops, done.
| |
478 if (!isLegalMemOffset(VarTy, Offset)) { | 479 if (!isLegalMemOffset(VarTy, Offset)) { |
479 llvm::report_fatal_error("Illegal stack offset"); | 480 // llvm::report_fatal_error("Illegal stack offset"); |
480 } | 481 } |
482 */ | |
481 Str << "[" << getRegName(BaseRegNum, VarTy); | 483 Str << "[" << getRegName(BaseRegNum, VarTy); |
482 if (Offset != 0) { | 484 if (Offset != 0) { |
483 Str << ", " << getConstantPrefix() << Offset; | 485 Str << ", " << getConstantPrefix() << Offset; |
484 } | 486 } |
485 Str << "]"; | 487 Str << "]"; |
486 } | 488 } |
487 | 489 |
488 bool TargetARM32::CallingConv::I64InRegs(std::pair<int32_t, int32_t> *Regs) { | 490 bool TargetARM32::CallingConv::I64InRegs(std::pair<int32_t, int32_t> *Regs) { |
489 if (NumGPRRegsUsed >= ARM32_MAX_GPR_ARG) | 491 if (NumGPRRegsUsed >= ARM32_MAX_GPR_ARG) |
490 return false; | 492 return false; |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
618 // Helper function for addProlog(). | 620 // Helper function for addProlog(). |
619 // | 621 // |
620 // This assumes Arg is an argument passed on the stack. This sets the frame | 622 // 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 | 623 // 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 | 624 // 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 | 625 // recursively on the components, taking care to handle Lo first because of the |
624 // little-endian architecture. Lastly, this function generates an instruction | 626 // little-endian architecture. Lastly, this function generates an instruction |
625 // to copy Arg into its assigned register if applicable. | 627 // to copy Arg into its assigned register if applicable. |
626 void TargetARM32::finishArgumentLowering(Variable *Arg, Variable *FramePtr, | 628 void TargetARM32::finishArgumentLowering(Variable *Arg, Variable *FramePtr, |
627 size_t BasicFrameOffset, | 629 size_t BasicFrameOffset, |
628 size_t &InArgsSizeBytes) { | 630 size_t *InArgsSizeBytes) { |
629 if (auto *Arg64On32 = llvm::dyn_cast<Variable64On32>(Arg)) { | 631 if (auto *Arg64On32 = llvm::dyn_cast<Variable64On32>(Arg)) { |
630 Variable *Lo = Arg64On32->getLo(); | 632 Variable *Lo = Arg64On32->getLo(); |
631 Variable *Hi = Arg64On32->getHi(); | 633 Variable *Hi = Arg64On32->getHi(); |
632 finishArgumentLowering(Lo, FramePtr, BasicFrameOffset, InArgsSizeBytes); | 634 finishArgumentLowering(Lo, FramePtr, BasicFrameOffset, InArgsSizeBytes); |
633 finishArgumentLowering(Hi, FramePtr, BasicFrameOffset, InArgsSizeBytes); | 635 finishArgumentLowering(Hi, FramePtr, BasicFrameOffset, InArgsSizeBytes); |
634 return; | 636 return; |
635 } | 637 } |
636 Type Ty = Arg->getType(); | 638 Type Ty = Arg->getType(); |
637 InArgsSizeBytes = applyStackAlignmentTy(InArgsSizeBytes, Ty); | 639 assert(Ty != IceType_i64); |
638 Arg->setStackOffset(BasicFrameOffset + InArgsSizeBytes); | 640 |
639 InArgsSizeBytes += typeWidthInBytesOnStack(Ty); | 641 *InArgsSizeBytes = applyStackAlignmentTy(*InArgsSizeBytes, Ty); |
640 // If the argument variable has been assigned a register, we need to load the | 642 const int32_t ArgStackOffset = BasicFrameOffset + *InArgsSizeBytes; |
643 *InArgsSizeBytes += typeWidthInBytesOnStack(Ty); | |
644 | |
645 if (!Arg->hasReg()) { | |
646 Arg->setStackOffset(ArgStackOffset); | |
647 return; | |
648 } | |
649 | |
650 // If the argument variable has been assigned a register, we need to copy the | |
641 // value from the stack slot. | 651 // value from the stack slot. |
642 if (Arg->hasReg()) { | 652 Variable *Parameter = Func->makeVariable(Ty); |
643 assert(Ty != IceType_i64); | 653 Parameter->setMustNotHaveReg(); |
644 // This should be simple, just load the parameter off the stack using a nice | 654 Parameter->setStackOffset(ArgStackOffset); |
645 // sp + imm addressing mode. Because ARM, we can't do that (e.g., VLDR, for | 655 _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 } | 656 } |
658 | 657 |
659 Type TargetARM32::stackSlotType() { return IceType_i32; } | 658 Type TargetARM32::stackSlotType() { return IceType_i32; } |
660 | 659 |
661 void TargetARM32::addProlog(CfgNode *Node) { | 660 void TargetARM32::addProlog(CfgNode *Node) { |
662 // Stack frame layout: | 661 // Stack frame layout: |
663 // | 662 // |
664 // +------------------------+ | 663 // +------------------------+ |
665 // | 1. preserved registers | | 664 // | 1. preserved registers | |
666 // +------------------------+ | 665 // +------------------------+ |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
747 CalleeSaves[RegARM32::Reg_lr] = true; | 746 CalleeSaves[RegARM32::Reg_lr] = true; |
748 RegsUsed[RegARM32::Reg_lr] = true; | 747 RegsUsed[RegARM32::Reg_lr] = true; |
749 } | 748 } |
750 for (SizeT i = 0; i < CalleeSaves.size(); ++i) { | 749 for (SizeT i = 0; i < CalleeSaves.size(); ++i) { |
751 if (RegARM32::isI64RegisterPair(i)) { | 750 if (RegARM32::isI64RegisterPair(i)) { |
752 // We don't save register pairs explicitly. Instead, we rely on the code | 751 // We don't save register pairs explicitly. Instead, we rely on the code |
753 // fake-defing/fake-using each register in the pair. | 752 // fake-defing/fake-using each register in the pair. |
754 continue; | 753 continue; |
755 } | 754 } |
756 if (CalleeSaves[i] && RegsUsed[i]) { | 755 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; | 756 ++NumCallee; |
760 Variable *PhysicalRegister = getPhysicalRegister(i); | 757 Variable *PhysicalRegister = getPhysicalRegister(i); |
761 PreservedRegsSizeBytes += | 758 PreservedRegsSizeBytes += |
762 typeWidthInBytesOnStack(PhysicalRegister->getType()); | 759 typeWidthInBytesOnStack(PhysicalRegister->getType()); |
763 GPRsToPreserve.push_back(getPhysicalRegister(i)); | 760 GPRsToPreserve.push_back(getPhysicalRegister(i)); |
764 } | 761 } |
765 } | 762 } |
766 Ctx->statsUpdateRegistersSaved(NumCallee); | 763 Ctx->statsUpdateRegistersSaved(NumCallee); |
767 if (!GPRsToPreserve.empty()) | 764 if (!GPRsToPreserve.empty()) |
768 _push(GPRsToPreserve); | 765 _push(GPRsToPreserve); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
830 InRegs = CC.FPInReg(Ty, &DummyReg); | 827 InRegs = CC.FPInReg(Ty, &DummyReg); |
831 } else if (Ty == IceType_i64) { | 828 } else if (Ty == IceType_i64) { |
832 std::pair<int32_t, int32_t> DummyRegs; | 829 std::pair<int32_t, int32_t> DummyRegs; |
833 InRegs = CC.I64InRegs(&DummyRegs); | 830 InRegs = CC.I64InRegs(&DummyRegs); |
834 } else { | 831 } else { |
835 assert(Ty == IceType_i32); | 832 assert(Ty == IceType_i32); |
836 int32_t DummyReg; | 833 int32_t DummyReg; |
837 InRegs = CC.I32InReg(&DummyReg); | 834 InRegs = CC.I32InReg(&DummyReg); |
838 } | 835 } |
839 if (!InRegs) | 836 if (!InRegs) |
840 finishArgumentLowering(Arg, FramePtr, BasicFrameOffset, InArgsSizeBytes); | 837 finishArgumentLowering(Arg, FramePtr, BasicFrameOffset, &InArgsSizeBytes); |
841 } | 838 } |
842 | 839 |
843 // Fill in stack offsets for locals. | 840 // Fill in stack offsets for locals. |
844 assignVarStackSlots(SortedSpilledVariables, SpillAreaPaddingBytes, | 841 assignVarStackSlots(SortedSpilledVariables, SpillAreaPaddingBytes, |
845 SpillAreaSizeBytes, GlobalsAndSubsequentPaddingSize, | 842 SpillAreaSizeBytes, GlobalsAndSubsequentPaddingSize, |
846 UsesFramePointer); | 843 UsesFramePointer); |
847 this->HasComputedFrame = true; | 844 this->HasComputedFrame = true; |
848 | 845 |
849 if (BuildDefs::dump() && Func->isVerbose(IceV_Frame)) { | 846 if (BuildDefs::dump() && Func->isVerbose(IceV_Frame)) { |
850 OstreamLocker _(Func->getContext()); | 847 OstreamLocker _(Func->getContext()); |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
974 Operand *OffsetVal = legalize(Ctx->getConstantInt32(Offset), | 971 Operand *OffsetVal = legalize(Ctx->getConstantInt32(Offset), |
975 Legal_Reg | Legal_Flex, getReservedTmpReg()); | 972 Legal_Reg | Legal_Flex, getReservedTmpReg()); |
976 Variable *ScratchReg = makeReg(IceType_i32, getReservedTmpReg()); | 973 Variable *ScratchReg = makeReg(IceType_i32, getReservedTmpReg()); |
977 if (ShouldSub) | 974 if (ShouldSub) |
978 _sub(ScratchReg, OrigBaseReg, OffsetVal); | 975 _sub(ScratchReg, OrigBaseReg, OffsetVal); |
979 else | 976 else |
980 _add(ScratchReg, OrigBaseReg, OffsetVal); | 977 _add(ScratchReg, OrigBaseReg, OffsetVal); |
981 return ScratchReg; | 978 return ScratchReg; |
982 } | 979 } |
983 | 980 |
984 StackVariable *TargetARM32::legalizeStackSlot(Type Ty, int32_t Offset, | 981 OperandARM32Mem *TargetARM32::createMemOperand(Type Ty, int32_t Offset, |
985 int32_t StackAdjust, | 982 int32_t StackAdjust, |
986 Variable *OrigBaseReg, | 983 Variable *OrigBaseReg, |
987 Variable **NewBaseReg, | 984 Variable **NewBaseReg, |
988 int32_t *NewBaseOffset) { | 985 int32_t *NewBaseOffset) { |
986 if (isLegalMemOffset(Ty, Offset + StackAdjust)) { | |
987 return OperandARM32Mem::create( | |
988 Func, Ty, OrigBaseReg, llvm::cast<ConstantInteger32>( | |
989 Ctx->getConstantInt32(Offset + StackAdjust)), | |
990 OperandARM32Mem::Offset); | |
991 } | |
992 | |
989 if (*NewBaseReg == nullptr) { | 993 if (*NewBaseReg == nullptr) { |
990 *NewBaseReg = newBaseRegister(Offset, StackAdjust, OrigBaseReg); | 994 *NewBaseReg = newBaseRegister(Offset, StackAdjust, OrigBaseReg); |
991 *NewBaseOffset = Offset + StackAdjust; | 995 *NewBaseOffset = Offset + StackAdjust; |
992 } | 996 } |
993 | 997 |
994 int32_t OffsetDiff = Offset + StackAdjust - *NewBaseOffset; | 998 int32_t OffsetDiff = Offset + StackAdjust - *NewBaseOffset; |
995 if (!isLegalMemOffset(Ty, OffsetDiff)) { | 999 if (!isLegalMemOffset(Ty, OffsetDiff)) { |
996 *NewBaseReg = newBaseRegister(Offset, StackAdjust, OrigBaseReg); | 1000 *NewBaseReg = newBaseRegister(Offset, StackAdjust, OrigBaseReg); |
997 *NewBaseOffset = Offset + StackAdjust; | 1001 *NewBaseOffset = Offset + StackAdjust; |
998 OffsetDiff = 0; | 1002 OffsetDiff = 0; |
999 } | 1003 } |
1000 | 1004 |
1001 StackVariable *NewDest = Func->makeVariable<StackVariable>(Ty); | 1005 return OperandARM32Mem::create( |
1002 NewDest->setMustNotHaveReg(); | 1006 Func, Ty, *NewBaseReg, |
1003 NewDest->setBaseRegNum((*NewBaseReg)->getRegNum()); | 1007 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(OffsetDiff)), |
1004 NewDest->setStackOffset(OffsetDiff); | 1008 OperandARM32Mem::Offset); |
1005 return NewDest; | |
1006 } | 1009 } |
1007 | 1010 |
1008 void TargetARM32::legalizeMovStackAddrImm(InstARM32Mov *MovInstr, | 1011 void TargetARM32::legalizeMov(InstARM32Mov *MovInstr, int32_t StackAdjust, |
1009 int32_t StackAdjust, | 1012 Variable *OrigBaseReg, Variable **NewBaseReg, |
1010 Variable *OrigBaseReg, | 1013 int32_t *NewBaseOffset) { |
1011 Variable **NewBaseReg, | |
1012 int32_t *NewBaseOffset) { | |
1013 Variable *Dest = MovInstr->getDest(); | 1014 Variable *Dest = MovInstr->getDest(); |
1014 assert(Dest != nullptr); | 1015 assert(Dest != nullptr); |
1015 Type DestTy = Dest->getType(); | 1016 Type DestTy = Dest->getType(); |
1016 assert(DestTy != IceType_i64); | 1017 assert(DestTy != IceType_i64); |
1017 | 1018 |
1018 Operand *Src = MovInstr->getSrc(0); | 1019 Operand *Src = MovInstr->getSrc(0); |
1019 Type SrcTy = Src->getType(); | 1020 Type SrcTy = Src->getType(); |
1021 (void)SrcTy; | |
1020 assert(SrcTy != IceType_i64); | 1022 assert(SrcTy != IceType_i64); |
1021 | 1023 |
1022 if (MovInstr->isMultiDest() || MovInstr->isMultiSource()) | 1024 if (MovInstr->isMultiDest() || MovInstr->isMultiSource()) |
1023 return; | 1025 return; |
1024 | 1026 |
1025 bool Legalized = false; | 1027 bool Legalized = false; |
1026 if (!Dest->hasReg()) { | 1028 if (!Dest->hasReg()) { |
1027 assert(llvm::cast<Variable>(Src)->hasReg()); | 1029 auto *SrcR = llvm::cast<Variable>(Src); |
Karl
2015/11/18 18:40:42
const auto?
John
2015/11/19 13:41:22
done.
| |
1030 assert(SrcR->hasReg()); | |
1028 const int32_t Offset = Dest->getStackOffset(); | 1031 const int32_t Offset = Dest->getStackOffset(); |
1029 if (!isLegalMemOffset(DestTy, Offset + StackAdjust)) { | 1032 // This is a _mov(Mem(), Variable), i.e., a store. |
1030 Legalized = true; | 1033 _str(SrcR, createMemOperand(DestTy, Offset, StackAdjust, OrigBaseReg, |
1031 Dest = legalizeStackSlot(DestTy, Offset, StackAdjust, OrigBaseReg, | 1034 NewBaseReg, NewBaseOffset), |
1032 NewBaseReg, NewBaseOffset); | 1035 MovInstr->getPredicate()); |
1033 } | 1036 // _str() does not have a Dest, so we add a fake-def(Dest). |
1037 Context.insert(InstFakeDef::create(Func, Dest)); | |
1038 Legalized = true; | |
1034 } else if (auto *Var = llvm::dyn_cast<Variable>(Src)) { | 1039 } else if (auto *Var = llvm::dyn_cast<Variable>(Src)) { |
1035 if (!Var->hasReg()) { | 1040 if (!Var->hasReg()) { |
1036 const int32_t Offset = Var->getStackOffset(); | 1041 const int32_t Offset = Var->getStackOffset(); |
1037 if (!isLegalMemOffset(SrcTy, Offset + StackAdjust)) { | 1042 _ldr(Dest, createMemOperand(DestTy, Offset, StackAdjust, OrigBaseReg, |
1038 Legalized = true; | 1043 NewBaseReg, NewBaseOffset), |
1039 Src = legalizeStackSlot(SrcTy, Offset, StackAdjust, OrigBaseReg, | 1044 MovInstr->getPredicate()); |
1040 NewBaseReg, NewBaseOffset); | 1045 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 } | 1046 } |
1054 } | 1047 } |
1055 | 1048 |
1056 if (Legalized) { | 1049 if (Legalized) { |
1057 if (MovInstr->isDestRedefined()) { | 1050 if (MovInstr->isDestRedefined()) { |
1058 _mov_redefined(Dest, Src, MovInstr->getPredicate()); | 1051 _set_dest_redefined(); |
1059 } else { | |
1060 _mov(Dest, Src, MovInstr->getPredicate()); | |
1061 } | 1052 } |
1062 MovInstr->setDeleted(); | 1053 MovInstr->setDeleted(); |
1063 } | 1054 } |
1064 } | 1055 } |
1065 | 1056 |
1066 void TargetARM32::legalizeStackSlots() { | 1057 void TargetARM32::legalizeStackSlots() { |
1067 // If a stack variable's frame offset doesn't fit, convert from: | 1058 // If a stack variable's frame offset doesn't fit, convert from: |
1068 // ldr X, OFF[SP] | 1059 // ldr X, OFF[SP] |
1069 // to: | 1060 // to: |
1070 // movw/movt TMP, OFF_PART | 1061 // movw/movt TMP, OFF_PART |
1071 // add TMP, TMP, SP | 1062 // add TMP, TMP, SP |
1072 // ldr X, OFF_MORE[TMP] | 1063 // ldr X, OFF_MORE[TMP] |
1073 // | 1064 // |
1074 // This is safe because we have reserved TMP, and add for ARM does not | 1065 // This is safe because we have reserved TMP, and add for ARM does not |
1075 // clobber the flags register. | 1066 // clobber the flags register. |
1076 Func->dump("Before legalizeStackSlots"); | 1067 Func->dump("Before legalizeStackSlots"); |
1077 assert(hasComputedFrame()); | 1068 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()); | 1069 Variable *OrigBaseReg = getPhysicalRegister(getFrameOrStackReg()); |
1084 int32_t StackAdjust = 0; | 1070 int32_t StackAdjust = 0; |
1085 // Do a fairly naive greedy clustering for now. Pick the first stack slot | 1071 // 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 | 1072 // 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 | 1073 // 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 | 1074 // 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 | 1075 // 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. | 1076 // 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 | 1077 // 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 | 1078 // help to assign smaller offsets to higher-weight variables so that they |
(...skipping 22 matching lines...) Expand all Loading... | |
1115 NewBaseOffset += AdjInst->getAmount(); | 1101 NewBaseOffset += AdjInst->getAmount(); |
1116 continue; | 1102 continue; |
1117 } | 1103 } |
1118 if (llvm::isa<InstARM32Call>(CurInstr)) { | 1104 if (llvm::isa<InstARM32Call>(CurInstr)) { |
1119 NewBaseOffset -= StackAdjust; | 1105 NewBaseOffset -= StackAdjust; |
1120 StackAdjust = 0; | 1106 StackAdjust = 0; |
1121 continue; | 1107 continue; |
1122 } | 1108 } |
1123 } | 1109 } |
1124 | 1110 |
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)) { | 1111 if (auto *MovInstr = llvm::dyn_cast<InstARM32Mov>(CurInstr)) { |
1128 legalizeMovStackAddrImm(MovInstr, StackAdjust, OrigBaseReg, &NewBaseReg, | 1112 legalizeMov(MovInstr, StackAdjust, OrigBaseReg, &NewBaseReg, |
1129 &NewBaseOffset); | 1113 &NewBaseOffset); |
1130 } | 1114 } |
1131 } | 1115 } |
1132 } | 1116 } |
1133 } | 1117 } |
1134 | 1118 |
1135 Operand *TargetARM32::loOperand(Operand *Operand) { | 1119 Operand *TargetARM32::loOperand(Operand *Operand) { |
1136 assert(Operand->getType() == IceType_i64); | 1120 assert(Operand->getType() == IceType_i64); |
1137 if (Operand->getType() != IceType_i64) | 1121 if (Operand->getType() != IceType_i64) |
1138 return Operand; | 1122 return Operand; |
1139 if (auto *Var64On32 = llvm::dyn_cast<Variable64On32>(Operand)) | 1123 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)); | 4577 Context.insert(InstFakeDef::create(Func, Reg)); |
4594 UnimplementedError(Func->getContext()->getFlags()); | 4578 UnimplementedError(Func->getContext()->getFlags()); |
4595 return Reg; | 4579 return Reg; |
4596 } | 4580 } |
4597 | 4581 |
4598 // Helper for legalize() to emit the right code to lower an operand to a | 4582 // Helper for legalize() to emit the right code to lower an operand to a |
4599 // register of the appropriate type. | 4583 // register of the appropriate type. |
4600 Variable *TargetARM32::copyToReg(Operand *Src, int32_t RegNum) { | 4584 Variable *TargetARM32::copyToReg(Operand *Src, int32_t RegNum) { |
4601 Type Ty = Src->getType(); | 4585 Type Ty = Src->getType(); |
4602 Variable *Reg = makeReg(Ty, RegNum); | 4586 Variable *Reg = makeReg(Ty, RegNum); |
4603 _mov(Reg, Src); | 4587 if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Src)) { |
4588 _ldr(Reg, Mem); | |
4589 } else { | |
4590 _mov(Reg, Src); | |
4591 } | |
4604 return Reg; | 4592 return Reg; |
4605 } | 4593 } |
4606 | 4594 |
4607 Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed, | 4595 Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed, |
4608 int32_t RegNum) { | 4596 int32_t RegNum) { |
4609 Type Ty = From->getType(); | 4597 Type Ty = From->getType(); |
4610 // Assert that a physical register is allowed. To date, all calls to | 4598 // Assert that a physical register is allowed. To date, all calls to |
4611 // legalize() allow a physical register. Legal_Flex converts registers to the | 4599 // legalize() allow a physical register. Legal_Flex converts registers to the |
4612 // right type OperandARM32FlexReg as needed. | 4600 // right type OperandARM32FlexReg as needed. |
4613 assert(Allowed & Legal_Reg); | 4601 assert(Allowed & Legal_Reg); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4646 if (Index) { | 4634 if (Index) { |
4647 assert(Offset == nullptr); | 4635 assert(Offset == nullptr); |
4648 assert(MemTraits[Ty].CanHaveIndex); | 4636 assert(MemTraits[Ty].CanHaveIndex); |
4649 RegIndex = legalizeToReg(Index); | 4637 RegIndex = legalizeToReg(Index); |
4650 } | 4638 } |
4651 if (Offset && Offset->getValue() != 0) { | 4639 if (Offset && Offset->getValue() != 0) { |
4652 assert(Index == nullptr); | 4640 assert(Index == nullptr); |
4653 static constexpr bool ZeroExt = false; | 4641 static constexpr bool ZeroExt = false; |
4654 assert(MemTraits[Ty].CanHaveImm); | 4642 assert(MemTraits[Ty].CanHaveImm); |
4655 if (!OperandARM32Mem::canHoldOffset(Ty, ZeroExt, Offset->getValue())) { | 4643 if (!OperandARM32Mem::canHoldOffset(Ty, ZeroExt, Offset->getValue())) { |
4656 assert(RegBase->hasReg()); | 4644 assert(false); |
Karl
2015/11/18 18:40:42
Why have code below this? Doesn't assert always fa
John
2015/11/19 13:41:22
It used to be the case that TargetARM32::legalizeM
| |
4657 assert(RegBase->getRegNum() == (int32_t)getFrameOrStackReg()); | |
4658 // We are a bit more lenient with invalid immediate when accessing the | 4645 // We are a bit more lenient with invalid immediate when accessing the |
4659 // stack here, and then rely on legalizeStackSlots() to fix things as | 4646 // stack here, and then rely on legalizeStackSlots() to fix things as |
4660 // appropriate. | 4647 // appropriate. |
4661 InvalidImm = true; | 4648 InvalidImm = true; |
4662 } | 4649 } |
4663 } | 4650 } |
4664 | 4651 |
4665 // Create a new operand if there was a change. | 4652 // Create a new operand if there was a change. |
4666 if (Base != RegBase || Index != RegIndex) { | 4653 if (Base != RegBase || Index != RegIndex) { |
4667 // There is only a reg +/- reg or reg + imm form. | 4654 // There is only a reg +/- reg or reg + imm form. |
(...skipping 744 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5412 // Technically R9 is used for TLS with Sandboxing, and we reserve it. | 5399 // Technically R9 is used for TLS with Sandboxing, and we reserve it. |
5413 // However, for compatibility with current NaCl LLVM, don't claim that. | 5400 // 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"; | 5401 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; |
5415 } | 5402 } |
5416 | 5403 |
5417 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[IceType_NUM]; | 5404 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[IceType_NUM]; |
5418 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; | 5405 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; |
5419 llvm::SmallBitVector TargetARM32::ScratchRegs; | 5406 llvm::SmallBitVector TargetARM32::ScratchRegs; |
5420 | 5407 |
5421 } // end of namespace Ice | 5408 } // end of namespace Ice |
OLD | NEW |