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 /* | |
|
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 |