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

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: Fixes lit. presubmit cleared. 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
« no previous file with comments | « src/IceTargetLoweringARM32.h ('k') | tests_lit/assembler/arm32/branch-mult-fwd.ll » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 /*
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/IceTargetLoweringARM32.h ('k') | tests_lit/assembler/arm32/branch-mult-fwd.ll » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698