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

Side by Side Diff: src/IceTargetLoweringARM32.cpp

Issue 1457683004: Subzero. ARM32. Removing memory legalization warts. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Addresses comments Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 //===- subzero/src/IceTargetLoweringARM32.cpp - ARM32 lowering ------------===// 1 //===- subzero/src/IceTargetLoweringARM32.cpp - ARM32 lowering ------------===//
2 // 2 //
3 // The Subzero Code Generator 3 // The Subzero Code Generator
4 // 4 //
5 // This file is distributed under the University of Illinois Open Source 5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details. 6 // License. See LICENSE.TXT for details.
7 // 7 //
8 //===----------------------------------------------------------------------===// 8 //===----------------------------------------------------------------------===//
9 /// 9 ///
10 /// \file 10 /// \file
(...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698