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

Side by Side Diff: src/IceTargetLoweringMIPS32.cpp

Issue 2027773002: Subzero, MIPS32: Handling floating point instructions fadd, fsub, fmul, fdiv (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Rebase for applying prerequisites Created 4 years, 6 months 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/IceTargetLoweringMIPS32.h ('k') | src/IceTargetLoweringX8632.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // 1 //
2 // The Subzero Code Generator 2 // The Subzero Code Generator
3 // 3 //
4 // This file is distributed under the University of Illinois Open Source 4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details. 5 // License. See LICENSE.TXT for details.
6 // 6 //
7 //===----------------------------------------------------------------------===// 7 //===----------------------------------------------------------------------===//
8 /// 8 ///
9 /// \file 9 /// \file
10 /// \brief Implements the TargetLoweringMIPS32 class, which consists almost 10 /// \brief Implements the TargetLoweringMIPS32 class, which consists almost
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
57 namespace Ice { 57 namespace Ice {
58 namespace MIPS32 { 58 namespace MIPS32 {
59 59
60 using llvm::isInt; 60 using llvm::isInt;
61 61
62 namespace { 62 namespace {
63 63
64 // The maximum number of arguments to pass in GPR registers. 64 // The maximum number of arguments to pass in GPR registers.
65 constexpr uint32_t MIPS32_MAX_GPR_ARG = 4; 65 constexpr uint32_t MIPS32_MAX_GPR_ARG = 4;
66 66
67 std::array<RegNumT, MIPS32_MAX_GPR_ARG> GPRArgInitializer;
68 std::array<RegNumT, MIPS32_MAX_GPR_ARG / 2> I64ArgInitializer;
69
70 constexpr uint32_t MIPS32_MAX_FP_ARG = 2;
71
72 std::array<RegNumT, MIPS32_MAX_FP_ARG> FP32ArgInitializer;
73 std::array<RegNumT, MIPS32_MAX_FP_ARG> FP64ArgInitializer;
74
67 const char *getRegClassName(RegClass C) { 75 const char *getRegClassName(RegClass C) {
68 auto ClassNum = static_cast<RegClassMIPS32>(C); 76 auto ClassNum = static_cast<RegClassMIPS32>(C);
69 assert(ClassNum < RCMIPS32_NUM); 77 assert(ClassNum < RCMIPS32_NUM);
70 switch (ClassNum) { 78 switch (ClassNum) {
71 default: 79 default:
72 assert(C < RC_Target); 80 assert(C < RC_Target);
73 return regClassString(C); 81 return regClassString(C);
74 // Add handling of new register classes below. 82 // Add handling of new register classes below.
75 } 83 }
76 } 84 }
77 85
86 // Stack alignment
87 constexpr uint32_t MIPS32_STACK_ALIGNMENT_BYTES = 8;
88
89 // Value is in bytes. Return Value adjusted to the next highest multiple of the
90 // stack alignment required for the given type.
91 uint32_t applyStackAlignmentTy(uint32_t Value, Type Ty) {
92 size_t typeAlignInBytes = typeWidthInBytes(Ty);
93 if (isVectorType(Ty))
94 UnimplementedError(getFlags());
95 return Utils::applyAlignment(Value, typeAlignInBytes);
96 }
97
78 } // end of anonymous namespace 98 } // end of anonymous namespace
79 99
80 TargetMIPS32::TargetMIPS32(Cfg *Func) : TargetLowering(Func) {} 100 TargetMIPS32::TargetMIPS32(Cfg *Func) : TargetLowering(Func) {}
81 101
82 void TargetMIPS32::staticInit(GlobalContext *Ctx) { 102 void TargetMIPS32::staticInit(GlobalContext *Ctx) {
83 (void)Ctx; 103 (void)Ctx;
84 RegNumT::setLimit(RegMIPS32::Reg_NUM); 104 RegNumT::setLimit(RegMIPS32::Reg_NUM);
85 SmallBitVector IntegerRegisters(RegMIPS32::Reg_NUM); 105 SmallBitVector IntegerRegisters(RegMIPS32::Reg_NUM);
86 SmallBitVector I64PairRegisters(RegMIPS32::Reg_NUM); 106 SmallBitVector I64PairRegisters(RegMIPS32::Reg_NUM);
87 SmallBitVector Float32Registers(RegMIPS32::Reg_NUM); 107 SmallBitVector Float32Registers(RegMIPS32::Reg_NUM);
(...skipping 10 matching lines...) Expand all
98 RegisterAliases[RegMIPS32::val].resize(RegMIPS32::Reg_NUM); \ 118 RegisterAliases[RegMIPS32::val].resize(RegMIPS32::Reg_NUM); \
99 for (SizeT RegAlias : alias_init) { \ 119 for (SizeT RegAlias : alias_init) { \
100 assert(!RegisterAliases[RegMIPS32::val][RegAlias] && \ 120 assert(!RegisterAliases[RegMIPS32::val][RegAlias] && \
101 "Duplicate alias for " #val); \ 121 "Duplicate alias for " #val); \
102 RegisterAliases[RegMIPS32::val].set(RegAlias); \ 122 RegisterAliases[RegMIPS32::val].set(RegAlias); \
103 } \ 123 } \
104 RegisterAliases[RegMIPS32::val].resize(RegMIPS32::Reg_NUM); \ 124 RegisterAliases[RegMIPS32::val].resize(RegMIPS32::Reg_NUM); \
105 assert(RegisterAliases[RegMIPS32::val][RegMIPS32::val]); 125 assert(RegisterAliases[RegMIPS32::val][RegMIPS32::val]);
106 REGMIPS32_TABLE; 126 REGMIPS32_TABLE;
107 #undef X 127 #undef X
128
129 // TODO(mohit.bhakkad): Change these inits once we provide argument related
130 // field in register tables
131 for (size_t i = 0; i < MIPS32_MAX_GPR_ARG; i++)
132 GPRArgInitializer[i] = RegNumT::fixme(RegMIPS32::Reg_A0 + i);
133
134 for (size_t i = 0; i < MIPS32_MAX_GPR_ARG / 2; i++)
135 I64ArgInitializer[i] = RegNumT::fixme(RegMIPS32::Reg_A0A1 + i);
136
137 for (size_t i = 0; i < MIPS32_MAX_FP_ARG; i++) {
138 FP32ArgInitializer[i] = RegNumT::fixme(RegMIPS32::Reg_F12 + i * 2);
139 FP64ArgInitializer[i] = RegNumT::fixme(RegMIPS32::Reg_F12F13 + i);
140 }
141
108 TypeToRegisterSet[IceType_void] = InvalidRegisters; 142 TypeToRegisterSet[IceType_void] = InvalidRegisters;
109 TypeToRegisterSet[IceType_i1] = IntegerRegisters; 143 TypeToRegisterSet[IceType_i1] = IntegerRegisters;
110 TypeToRegisterSet[IceType_i8] = IntegerRegisters; 144 TypeToRegisterSet[IceType_i8] = IntegerRegisters;
111 TypeToRegisterSet[IceType_i16] = IntegerRegisters; 145 TypeToRegisterSet[IceType_i16] = IntegerRegisters;
112 TypeToRegisterSet[IceType_i32] = IntegerRegisters; 146 TypeToRegisterSet[IceType_i32] = IntegerRegisters;
113 TypeToRegisterSet[IceType_i64] = IntegerRegisters; 147 TypeToRegisterSet[IceType_i64] = IntegerRegisters;
114 TypeToRegisterSet[IceType_f32] = Float32Registers; 148 TypeToRegisterSet[IceType_f32] = Float32Registers;
115 TypeToRegisterSet[IceType_f64] = Float64Registers; 149 TypeToRegisterSet[IceType_f64] = Float64Registers;
116 TypeToRegisterSet[IceType_v4i1] = VectorRegisters; 150 TypeToRegisterSet[IceType_v4i1] = VectorRegisters;
117 TypeToRegisterSet[IceType_v8i1] = VectorRegisters; 151 TypeToRegisterSet[IceType_v8i1] = VectorRegisters;
118 TypeToRegisterSet[IceType_v16i1] = VectorRegisters; 152 TypeToRegisterSet[IceType_v16i1] = VectorRegisters;
119 TypeToRegisterSet[IceType_v16i8] = VectorRegisters; 153 TypeToRegisterSet[IceType_v16i8] = VectorRegisters;
120 TypeToRegisterSet[IceType_v8i16] = VectorRegisters; 154 TypeToRegisterSet[IceType_v8i16] = VectorRegisters;
121 TypeToRegisterSet[IceType_v4i32] = VectorRegisters; 155 TypeToRegisterSet[IceType_v4i32] = VectorRegisters;
122 TypeToRegisterSet[IceType_v4f32] = VectorRegisters; 156 TypeToRegisterSet[IceType_v4f32] = VectorRegisters;
123 157
124 for (size_t i = 0; i < llvm::array_lengthof(TypeToRegisterSet); ++i) 158 for (size_t i = 0; i < llvm::array_lengthof(TypeToRegisterSet); ++i)
125 TypeToRegisterSetUnfiltered[i] = TypeToRegisterSet[i]; 159 TypeToRegisterSetUnfiltered[i] = TypeToRegisterSet[i];
126 160
127 filterTypeToRegisterSet(Ctx, RegMIPS32::Reg_NUM, TypeToRegisterSet, 161 filterTypeToRegisterSet(Ctx, RegMIPS32::Reg_NUM, TypeToRegisterSet,
128 llvm::array_lengthof(TypeToRegisterSet), 162 llvm::array_lengthof(TypeToRegisterSet),
129 RegMIPS32::getRegName, getRegClassName); 163 RegMIPS32::getRegName, getRegClassName);
130 } 164 }
131 165
166 void TargetMIPS32::findMaxStackOutArgsSize() {
167 // MinNeededOutArgsBytes should be updated if the Target ever creates a
168 // high-level InstCall that requires more stack bytes.
169 constexpr size_t MinNeededOutArgsBytes = 16;
170 MaxOutArgsSizeBytes = MinNeededOutArgsBytes;
171 for (CfgNode *Node : Func->getNodes()) {
172 Context.init(Node);
173 while (!Context.atEnd()) {
174 PostIncrLoweringContext PostIncrement(Context);
175 Inst *CurInstr = iteratorToInst(Context.getCur());
176 if (auto *Call = llvm::dyn_cast<InstCall>(CurInstr)) {
177 SizeT OutArgsSizeBytes = getCallStackArgumentsSizeBytes(Call);
178 MaxOutArgsSizeBytes = std::max(MaxOutArgsSizeBytes, OutArgsSizeBytes);
179 }
180 }
181 }
182 }
183
132 void TargetMIPS32::translateO2() { 184 void TargetMIPS32::translateO2() {
133 TimerMarker T(TimerStack::TT_O2, Func); 185 TimerMarker T(TimerStack::TT_O2, Func);
134 186
135 // TODO(stichnot): share passes with X86? 187 // TODO(stichnot): share passes with X86?
136 // https://code.google.com/p/nativeclient/issues/detail?id=4094 188 // https://code.google.com/p/nativeclient/issues/detail?id=4094
137 genTargetHelperCalls(); 189 genTargetHelperCalls();
138 190
191 findMaxStackOutArgsSize();
192
139 // Merge Alloca instructions, and lay out the stack. 193 // Merge Alloca instructions, and lay out the stack.
140 static constexpr bool SortAndCombineAllocas = false; 194 static constexpr bool SortAndCombineAllocas = false;
141 Func->processAllocas(SortAndCombineAllocas); 195 Func->processAllocas(SortAndCombineAllocas);
142 Func->dump("After Alloca processing"); 196 Func->dump("After Alloca processing");
143 197
144 if (!getFlags().getEnablePhiEdgeSplit()) { 198 if (!getFlags().getEnablePhiEdgeSplit()) {
145 // Lower Phi instructions. 199 // Lower Phi instructions.
146 Func->placePhiLoads(); 200 Func->placePhiLoads();
147 if (Func->hasError()) 201 if (Func->hasError())
148 return; 202 return;
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
230 Func->doNopInsertion(); 284 Func->doNopInsertion();
231 } 285 }
232 } 286 }
233 287
234 void TargetMIPS32::translateOm1() { 288 void TargetMIPS32::translateOm1() {
235 TimerMarker T(TimerStack::TT_Om1, Func); 289 TimerMarker T(TimerStack::TT_Om1, Func);
236 290
237 // TODO: share passes with X86? 291 // TODO: share passes with X86?
238 genTargetHelperCalls(); 292 genTargetHelperCalls();
239 293
294 findMaxStackOutArgsSize();
295
240 // Do not merge Alloca instructions, and lay out the stack. 296 // Do not merge Alloca instructions, and lay out the stack.
241 static constexpr bool SortAndCombineAllocas = false; 297 static constexpr bool SortAndCombineAllocas = false;
242 Func->processAllocas(SortAndCombineAllocas); 298 Func->processAllocas(SortAndCombineAllocas);
243 Func->dump("After Alloca processing"); 299 Func->dump("After Alloca processing");
244 300
245 Func->placePhiLoads(); 301 Func->placePhiLoads();
246 if (Func->hasError()) 302 if (Func->hasError())
247 return; 303 return;
248 Func->placePhiStores(); 304 Func->placePhiStores();
249 if (Func->hasError()) 305 if (Func->hasError())
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
396 const Type FrameSPTy = IceType_i32; 452 const Type FrameSPTy = IceType_i32;
397 if (Var->hasReg()) { 453 if (Var->hasReg()) {
398 Str << '$' << getRegName(Var->getRegNum(), Var->getType()); 454 Str << '$' << getRegName(Var->getRegNum(), Var->getType());
399 return; 455 return;
400 } else { 456 } else {
401 int32_t Offset = Var->getStackOffset(); 457 int32_t Offset = Var->getStackOffset();
402 Str << Offset; 458 Str << Offset;
403 Str << "($" << getRegName(getFrameOrStackReg(), FrameSPTy); 459 Str << "($" << getRegName(getFrameOrStackReg(), FrameSPTy);
404 Str << ")"; 460 Str << ")";
405 } 461 }
462 // UnimplementedError(getFlags());
Jim Stichnoth 2016/06/13 20:14:19 remove this
463 }
464
465 TargetMIPS32::CallingConv::CallingConv()
466 : GPRegsUsed(RegMIPS32::Reg_NUM),
467 GPRArgs(GPRArgInitializer.rbegin(), GPRArgInitializer.rend()),
468 I64Args(I64ArgInitializer.rbegin(), I64ArgInitializer.rend()),
469 VFPRegsUsed(RegMIPS32::Reg_NUM),
470 FP32Args(FP32ArgInitializer.rbegin(), FP32ArgInitializer.rend()),
471 FP64Args(FP64ArgInitializer.rbegin(), FP64ArgInitializer.rend()) {}
472
473 // In MIPS O32 abi FP argument registers can be used only if first argument is
474 // of type float/double. UseFPRegs flag is used to care of that. Also FP arg
475 // registers can be used only for first 2 arguments, so we require argument
476 // number to make register allocation decisions.
477 bool TargetMIPS32::CallingConv::argInReg(Type Ty, uint32_t ArgNo,
478 RegNumT *Reg) {
479 if (isScalarIntegerType(Ty))
480 return argInGPR(Ty, Reg);
481 if (isScalarFloatingType(Ty)) {
482 if (ArgNo == 0) {
483 UseFPRegs = true;
484 return argInVFP(Ty, Reg);
485 }
486 if (UseFPRegs && ArgNo == 1) {
487 UseFPRegs = false;
488 return argInVFP(Ty, Reg);
489 }
490 return argInGPR(Ty, Reg);
491 }
406 UnimplementedError(getFlags()); 492 UnimplementedError(getFlags());
493 return false;
494 }
495
496 bool TargetMIPS32::CallingConv::argInGPR(Type Ty, RegNumT *Reg) {
497 CfgVector<RegNumT> *Source;
498
499 switch (Ty) {
500 default: {
501 UnimplementedError(getFlags());
502 return false;
503 } break;
504 case IceType_i32:
505 case IceType_f32: {
506 Source = &GPRArgs;
507 } break;
508 case IceType_i64:
509 case IceType_f64: {
510 Source = &I64Args;
511 } break;
512 }
513
514 discardUnavailableGPRsAndTheirAliases(Source);
515
516 if (Source->empty()) {
517 GPRegsUsed.set();
518 return false;
519 }
520
521 *Reg = Source->back();
522 // Note that we don't Source->pop_back() here. This is intentional. Notice how
523 // we mark all of Reg's aliases as Used. So, for the next argument,
524 // Source->back() is marked as unavailable, and it is thus implicitly popped
525 // from the stack.
526 GPRegsUsed |= RegisterAliases[*Reg];
527 return true;
528 }
529
530 inline void TargetMIPS32::CallingConv::discardNextGPRAndItsAliases(
531 CfgVector<RegNumT> *Regs) {
532 GPRegsUsed |= RegisterAliases[Regs->back()];
533 Regs->pop_back();
534 }
535
536 // GPR are not packed when passing parameters. Thus, a function foo(i32, i64,
537 // i32) will have the first argument in a0, the second in a2-a3, and the third
538 // on the stack. To model this behavior, whenever we pop a register from Regs,
539 // we remove all of its aliases from the pool of available GPRs. This has the
540 // effect of computing the "closure" on the GPR registers.
541 void TargetMIPS32::CallingConv::discardUnavailableGPRsAndTheirAliases(
542 CfgVector<RegNumT> *Regs) {
543 while (!Regs->empty() && GPRegsUsed[Regs->back()]) {
544 discardNextGPRAndItsAliases(Regs);
545 }
546 }
547
548 bool TargetMIPS32::CallingConv::argInVFP(Type Ty, RegNumT *Reg) {
549 CfgVector<RegNumT> *Source;
550
551 switch (Ty) {
552 default: {
553 UnimplementedError(getFlags());
554 return false;
555 } break;
556 case IceType_f32: {
557 Source = &FP32Args;
558 } break;
559 case IceType_f64: {
560 Source = &FP64Args;
561 } break;
562 }
563
564 discardUnavailableVFPRegsAndTheirAliases(Source);
565
566 if (Source->empty()) {
567 VFPRegsUsed.set();
568 return false;
569 }
570
571 *Reg = Source->back();
572 VFPRegsUsed |= RegisterAliases[*Reg];
573
574 // In MIPS O32 abi if fun arguments are (f32, i32) then one can not use reg_a0
575 // for second argument even though it's free. f32 arg goes in reg_f12, i32 arg
576 // goes in reg_a1. Similarly if arguments are (f64, i32) second argument goes
577 // in reg_a3 and a0, a1 are not used.
578 Source = &GPRArgs;
579 // Discard one GPR reg for f32(4 bytes), two for f64(4 + 4 bytes)
580 discardNextGPRAndItsAliases(Source);
581 if (Ty == IceType_f64)
582 discardNextGPRAndItsAliases(Source);
583
584 return true;
585 }
586
587 void TargetMIPS32::CallingConv::discardUnavailableVFPRegsAndTheirAliases(
588 CfgVector<RegNumT> *Regs) {
589 while (!Regs->empty() && VFPRegsUsed[Regs->back()]) {
590 Regs->pop_back();
591 }
407 } 592 }
408 593
409 void TargetMIPS32::lowerArguments() { 594 void TargetMIPS32::lowerArguments() {
410 VarList &Args = Func->getArgs(); 595 VarList &Args = Func->getArgs();
411 // We are only handling integer registers for now. The Mips o32 ABI is 596 TargetMIPS32::CallingConv CC;
412 // somewhat complex but will be implemented in its totality through follow 597
413 // on patches. 598 // For each register argument, replace Arg in the argument list with the home
414 // 599 // register. Then generate an instruction in the prolog to copy the home
415 unsigned NumGPRRegsUsed = 0; 600 // register to the assigned location of Arg.
416 // For each register argument, replace Arg in the argument list with the
417 // home register. Then generate an instruction in the prolog to copy the
418 // home register to the assigned location of Arg.
419 Context.init(Func->getEntryNode()); 601 Context.init(Func->getEntryNode());
420 Context.setInsertPoint(Context.getCur()); 602 Context.setInsertPoint(Context.getCur());
603
421 for (SizeT I = 0, E = Args.size(); I < E; ++I) { 604 for (SizeT I = 0, E = Args.size(); I < E; ++I) {
422 Variable *Arg = Args[I]; 605 Variable *Arg = Args[I];
423 Type Ty = Arg->getType(); 606 Type Ty = Arg->getType();
424 // TODO(rkotler): handle float/vector types. 607 RegNumT RegNum;
425 if (isVectorType(Ty)) { 608 if (!CC.argInReg(Ty, I, &RegNum)) {
426 UnimplementedError(getFlags());
427 continue; 609 continue;
428 } 610 }
429 if (isFloatingType(Ty)) { 611 Variable *RegisterArg = Func->makeVariable(Ty);
430 UnimplementedError(getFlags()); 612 if (BuildDefs::dump()) {
613 RegisterArg->setName(Func, "home_reg:" + Arg->getName());
614 }
615 RegisterArg->setIsArg();
616 Arg->setIsArg(false);
617 Args[I] = RegisterArg;
618 switch (Ty) {
619 default: { RegisterArg->setRegNum(RegNum); } break;
620 case IceType_i64: {
621 auto *RegisterArg64 = llvm::cast<Variable64On32>(RegisterArg);
622 RegisterArg64->initHiLo(Func);
623 RegisterArg64->getLo()->setRegNum(
624 RegNumT::fixme(RegMIPS32::getI64PairFirstGPRNum(RegNum)));
625 RegisterArg64->getHi()->setRegNum(
626 RegNumT::fixme(RegMIPS32::getI64PairSecondGPRNum(RegNum)));
627 } break;
628 }
629 Context.insert<InstAssign>(Arg, RegisterArg);
630 }
631 }
632
633 Type TargetMIPS32::stackSlotType() { return IceType_i32; }
634
635 // Helper function for addProlog().
636 //
637 // This assumes Arg is an argument passed on the stack. This sets the frame
638 // offset for Arg and updates InArgsSizeBytes according to Arg's width. For an
639 // I64 arg that has been split into Lo and Hi components, it calls itself
640 // recursively on the components, taking care to handle Lo first because of the
641 // little-endian architecture. Lastly, this function generates an instruction
642 // to copy Arg into its assigned register if applicable.
643 void TargetMIPS32::finishArgumentLowering(Variable *Arg, Variable *FramePtr,
644 size_t BasicFrameOffset,
645 size_t *InArgsSizeBytes) {
646 const Type Ty = Arg->getType();
647 *InArgsSizeBytes = applyStackAlignmentTy(*InArgsSizeBytes, Ty);
648
649 if (auto *Arg64On32 = llvm::dyn_cast<Variable64On32>(Arg)) {
650 Variable *const Lo = Arg64On32->getLo();
651 Variable *const Hi = Arg64On32->getHi();
652 finishArgumentLowering(Lo, FramePtr, BasicFrameOffset, InArgsSizeBytes);
653 finishArgumentLowering(Hi, FramePtr, BasicFrameOffset, InArgsSizeBytes);
654 return;
655 }
656 assert(Ty != IceType_i64);
657
658 const int32_t ArgStackOffset = BasicFrameOffset + *InArgsSizeBytes;
659 *InArgsSizeBytes += typeWidthInBytesOnStack(Ty);
660
661 if (!Arg->hasReg()) {
662 Arg->setStackOffset(ArgStackOffset);
663 return;
664 }
665
666 // If the argument variable has been assigned a register, we need to copy the
667 // value from the stack slot.
668 Variable *Parameter = Func->makeVariable(Ty);
669 Parameter->setMustNotHaveReg();
670 Parameter->setStackOffset(ArgStackOffset);
671 _mov(Arg, Parameter);
672 }
673
674 void TargetMIPS32::addProlog(CfgNode *Node) {
675 // Stack frame layout:
676 //
677 // +------------------------+
678 // | 1. preserved registers |
679 // +------------------------+
680 // | 2. padding |
681 // +------------------------+
682 // | 3. global spill area |
683 // +------------------------+
684 // | 4. padding |
685 // +------------------------+
686 // | 5. local spill area |
687 // +------------------------+
688 // | 6. padding |
689 // +------------------------+
690 // | 7. allocas |
691 // +------------------------+
692 // | 8. padding |
693 // +------------------------+
694 // | 9. out args |
695 // +------------------------+ <--- StackPointer
696 //
697 // The following variables record the size in bytes of the given areas:
698 // * PreservedRegsSizeBytes: area 1
699 // * SpillAreaPaddingBytes: area 2
700 // * GlobalsSize: area 3
701 // * GlobalsAndSubsequentPaddingSize: areas 3 - 4
702 // * LocalsSpillAreaSize: area 5
703 // * SpillAreaSizeBytes: areas 2 - 9
704 // * maxOutArgsSizeBytes(): area 9
705
706 Context.init(Node);
707 Context.setInsertPoint(Context.getCur());
708
709 SmallBitVector CalleeSaves = getRegisterSet(RegSet_CalleeSave, RegSet_None);
710 RegsUsed = SmallBitVector(CalleeSaves.size());
711
712 VarList SortedSpilledVariables;
713
714 size_t GlobalsSize = 0;
715 // If there is a separate locals area, this represents that area. Otherwise
716 // it counts any variable not counted by GlobalsSize.
717 SpillAreaSizeBytes = 0;
718 // If there is a separate locals area, this specifies the alignment for it.
719 uint32_t LocalsSlotsAlignmentBytes = 0;
720 // The entire spill locations area gets aligned to largest natural alignment
721 // of the variables that have a spill slot.
722 uint32_t SpillAreaAlignmentBytes = 0;
723 // For now, we don't have target-specific variables that need special
724 // treatment (no stack-slot-linked SpillVariable type).
725 std::function<bool(Variable *)> TargetVarHook = [](Variable *Var) {
726 static constexpr bool AssignStackSlot = false;
727 static constexpr bool DontAssignStackSlot = !AssignStackSlot;
728 if (llvm::isa<Variable64On32>(Var)) {
729 return DontAssignStackSlot;
730 }
731 return AssignStackSlot;
732 };
733
734 // Compute the list of spilled variables and bounds for GlobalsSize, etc.
735 getVarStackSlotParams(SortedSpilledVariables, RegsUsed, &GlobalsSize,
736 &SpillAreaSizeBytes, &SpillAreaAlignmentBytes,
737 &LocalsSlotsAlignmentBytes, TargetVarHook);
738 uint32_t LocalsSpillAreaSize = SpillAreaSizeBytes;
739 SpillAreaSizeBytes += GlobalsSize;
740
741 PreservedGPRs.reserve(CalleeSaves.size());
742
743 // Consider FP and RA as callee-save / used as needed.
744 if (UsesFramePointer) {
745 if (RegsUsed[RegMIPS32::Reg_FP]) {
746 llvm::report_fatal_error("Frame pointer has been used.");
747 }
748 CalleeSaves[RegMIPS32::Reg_FP] = true;
749 RegsUsed[RegMIPS32::Reg_FP] = true;
750 }
751 if (!MaybeLeafFunc) {
752 CalleeSaves[RegMIPS32::Reg_RA] = true;
753 RegsUsed[RegMIPS32::Reg_RA] = true;
754 }
755
756 // Make two passes over the used registers. The first pass records all the
757 // used registers -- and their aliases. Then, we figure out which GPR
758 // registers should be saved.
759 SmallBitVector ToPreserve(RegMIPS32::Reg_NUM);
760 for (SizeT i = 0; i < CalleeSaves.size(); ++i) {
761 if (CalleeSaves[i] && RegsUsed[i]) {
762 ToPreserve |= RegisterAliases[i];
763 }
764 }
765
766 uint32_t NumCallee = 0;
767 size_t PreservedRegsSizeBytes = 0;
768
769 // RegClasses is a tuple of
770 //
771 // <First Register in Class, Last Register in Class, Vector of Save Registers>
772 //
773 // We use this tuple to figure out which register we should save/restore
774 // during
775 // prolog/epilog.
776 using RegClassType = std::tuple<uint32_t, uint32_t, VarList *>;
777 const RegClassType RegClass = RegClassType(
778 RegMIPS32::Reg_GPR_First, RegMIPS32::Reg_GPR_Last, &PreservedGPRs);
779 const uint32_t FirstRegInClass = std::get<0>(RegClass);
780 const uint32_t LastRegInClass = std::get<1>(RegClass);
781 VarList *const PreservedRegsInClass = std::get<2>(RegClass);
782 for (uint32_t Reg = LastRegInClass; Reg > FirstRegInClass; Reg--) {
783 if (!ToPreserve[Reg]) {
431 continue; 784 continue;
432 } 785 }
433 if (Ty == IceType_i64) { 786 ++NumCallee;
434 if (NumGPRRegsUsed >= MIPS32_MAX_GPR_ARG) 787 Variable *PhysicalRegister = getPhysicalRegister(RegNumT::fromInt(Reg));
435 continue; 788 PreservedRegsSizeBytes +=
436 auto RegLo = RegNumT::fixme(RegMIPS32::Reg_A0 + NumGPRRegsUsed); 789 typeWidthInBytesOnStack(PhysicalRegister->getType());
437 auto RegHi = RegNumT::fixme(RegLo + 1); 790 PreservedRegsInClass->push_back(PhysicalRegister);
438 ++NumGPRRegsUsed; 791 }
439 // Always start i64 registers at an even register, so this may end 792
440 // up padding away a register. 793 Ctx->statsUpdateRegistersSaved(NumCallee);
441 if (RegLo % 2 != 0) { 794
442 RegLo = RegNumT::fixme(RegLo + 1); 795 // Align the variables area. SpillAreaPaddingBytes is the size of the region
443 ++NumGPRRegsUsed; 796 // after the preserved registers and before the spill areas.
444 } 797 // LocalsSlotsPaddingBytes is the amount of padding between the globals and
445 // If this leaves us without room to consume another register, 798 // locals area if they are separate.
446 // leave any previously speculatively consumed registers as consumed. 799 assert(SpillAreaAlignmentBytes <= MIPS32_STACK_ALIGNMENT_BYTES);
447 if (NumGPRRegsUsed >= MIPS32_MAX_GPR_ARG) 800 (void)MIPS32_STACK_ALIGNMENT_BYTES;
448 continue; 801 assert(LocalsSlotsAlignmentBytes <= SpillAreaAlignmentBytes);
449 // RegHi = RegNumT::fixme(RegMIPS32::Reg_A0 + NumGPRRegsUsed); 802 uint32_t SpillAreaPaddingBytes = 0;
450 ++NumGPRRegsUsed; 803 uint32_t LocalsSlotsPaddingBytes = 0;
451 Variable *RegisterArg = Func->makeVariable(Ty); 804 alignStackSpillAreas(PreservedRegsSizeBytes, SpillAreaAlignmentBytes,
452 auto *RegisterArg64On32 = llvm::cast<Variable64On32>(RegisterArg); 805 GlobalsSize, LocalsSlotsAlignmentBytes,
453 if (BuildDefs::dump()) 806 &SpillAreaPaddingBytes, &LocalsSlotsPaddingBytes);
454 RegisterArg64On32->setName(Func, "home_reg:" + Arg->getName()); 807 SpillAreaSizeBytes += SpillAreaPaddingBytes + LocalsSlotsPaddingBytes;
455 RegisterArg64On32->initHiLo(Func); 808 uint32_t GlobalsAndSubsequentPaddingSize =
456 RegisterArg64On32->setIsArg(); 809 GlobalsSize + LocalsSlotsPaddingBytes;
457 RegisterArg64On32->getLo()->setRegNum(RegLo); 810
458 RegisterArg64On32->getHi()->setRegNum(RegHi); 811 if (MaybeLeafFunc)
459 Arg->setIsArg(false); 812 MaxOutArgsSizeBytes = 0;
460 Args[I] = RegisterArg64On32; 813
461 Context.insert<InstAssign>(Arg, RegisterArg); 814 // Adds the out args space to the stack, and align SP if necessary.
815 uint32_t TotalStackSizeBytes = PreservedRegsSizeBytes + SpillAreaSizeBytes;
816
817 // TODO(sagar.thakur): Combine fixed alloca and maximum out argument size with
818 // TotalStackSizeBytes once lowerAlloca is implemented and leaf function
819 // information is generated by lowerCall.
820
821 // Generate "addiu sp, sp, -TotalStackSizeBytes"
822 if (TotalStackSizeBytes) {
823 // Use the scratch register if needed to legalize the immediate.
824 Variable *SP = getPhysicalRegister(RegMIPS32::Reg_SP);
825 _addiu(SP, SP, -(TotalStackSizeBytes));
826 }
827
828 Ctx->statsUpdateFrameBytes(TotalStackSizeBytes);
829
830 if (!PreservedGPRs.empty()) {
831 uint32_t StackOffset = TotalStackSizeBytes;
832 for (Variable *Var : *PreservedRegsInClass) {
833 Variable *PhysicalRegister = getPhysicalRegister(Var->getRegNum());
834 StackOffset -= typeWidthInBytesOnStack(PhysicalRegister->getType());
835 Variable *SP = getPhysicalRegister(RegMIPS32::Reg_SP);
836 OperandMIPS32Mem *MemoryLocation = OperandMIPS32Mem::create(
837 Func, IceType_i32, SP,
838 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(StackOffset)));
839 _sw(PhysicalRegister, MemoryLocation);
840 }
841 }
842
843 Variable *FP = getPhysicalRegister(RegMIPS32::Reg_FP);
844
845 // Generate "mov FP, SP" if needed.
846 if (UsesFramePointer) {
847 Variable *SP = getPhysicalRegister(RegMIPS32::Reg_SP);
848 _mov(FP, SP);
849 // Keep FP live for late-stage liveness analysis (e.g. asm-verbose mode).
850 Context.insert<InstFakeUse>(FP);
851 }
852
853 // Fill in stack offsets for stack args, and copy args into registers for
854 // those that were register-allocated. Args are pushed right to left, so
855 // Arg[0] is closest to the stack/frame pointer.
856 const VarList &Args = Func->getArgs();
857 size_t InArgsSizeBytes = 0;
858 TargetMIPS32::CallingConv CC;
859 uint32_t ArgNo = 0;
860
861 for (Variable *Arg : Args) {
862 RegNumT DummyReg;
863 const Type Ty = Arg->getType();
864 // Skip arguments passed in registers.
865 if (CC.argInReg(Ty, ArgNo, &DummyReg)) {
866 ArgNo++;
462 continue; 867 continue;
463 } else { 868 } else {
464 assert(Ty == IceType_i32); 869 finishArgumentLowering(Arg, FP, TotalStackSizeBytes, &InArgsSizeBytes);
465 if (NumGPRRegsUsed >= MIPS32_MAX_GPR_ARG) 870 }
466 continue; 871 }
467 const auto RegNum = RegNumT::fixme(RegMIPS32::Reg_A0 + NumGPRRegsUsed); 872
468 ++NumGPRRegsUsed; 873 // Fill in stack offsets for locals.
469 Variable *RegisterArg = Func->makeVariable(Ty); 874 assignVarStackSlots(SortedSpilledVariables, SpillAreaPaddingBytes,
470 if (BuildDefs::dump()) { 875 SpillAreaSizeBytes, GlobalsAndSubsequentPaddingSize,
471 RegisterArg->setName(Func, "home_reg:" + Arg->getName()); 876 UsesFramePointer);
472 } 877 this->HasComputedFrame = true;
473 RegisterArg->setRegNum(RegNum); 878
474 RegisterArg->setIsArg(); 879 if (BuildDefs::dump() && Func->isVerbose(IceV_Frame)) {
475 Arg->setIsArg(false); 880 OstreamLocker _(Func->getContext());
476 Args[I] = RegisterArg; 881 Ostream &Str = Func->getContext()->getStrDump();
477 Context.insert<InstAssign>(Arg, RegisterArg); 882
478 } 883 Str << "Stack layout:\n";
479 } 884 uint32_t SPAdjustmentPaddingSize =
480 } 885 SpillAreaSizeBytes - LocalsSpillAreaSize -
481 886 GlobalsAndSubsequentPaddingSize - SpillAreaPaddingBytes -
482 Type TargetMIPS32::stackSlotType() { return IceType_i32; } 887 MaxOutArgsSizeBytes;
483 888 Str << " in-args = " << InArgsSizeBytes << " bytes\n"
484 void TargetMIPS32::addProlog(CfgNode *Node) { 889 << " preserved registers = " << PreservedRegsSizeBytes << " bytes\n"
485 (void)Node; 890 << " spill area padding = " << SpillAreaPaddingBytes << " bytes\n"
891 << " globals spill area = " << GlobalsSize << " bytes\n"
892 << " globals-locals spill areas intermediate padding = "
893 << GlobalsAndSubsequentPaddingSize - GlobalsSize << " bytes\n"
894 << " locals spill area = " << LocalsSpillAreaSize << " bytes\n"
895 << " SP alignment padding = " << SPAdjustmentPaddingSize << " bytes\n";
896
897 Str << "Stack details:\n"
898 << " SP adjustment = " << SpillAreaSizeBytes << " bytes\n"
899 << " spill area alignment = " << SpillAreaAlignmentBytes << " bytes\n"
900 << " outgoing args size = " << MaxOutArgsSizeBytes << " bytes\n"
901 << " locals spill area alignment = " << LocalsSlotsAlignmentBytes
902 << " bytes\n"
903 << " is FP based = " << 1 << "\n";
904 }
486 return; 905 return;
487 UnimplementedError(getFlags());
488 } 906 }
489 907
490 void TargetMIPS32::addEpilog(CfgNode *Node) { 908 void TargetMIPS32::addEpilog(CfgNode *Node) {
491 (void)Node; 909 (void)Node;
492 return; 910 return;
493 UnimplementedError(getFlags()); 911 UnimplementedError(getFlags());
494 } 912 }
495 913
496 Operand *TargetMIPS32::loOperand(Operand *Operand) { 914 Operand *TargetMIPS32::loOperand(Operand *Operand) {
497 assert(Operand->getType() == IceType_i64); 915 assert(Operand->getType() == IceType_i64);
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
700 Operand *Src0 = legalizeUndef(Instr->getSrc(0)); 1118 Operand *Src0 = legalizeUndef(Instr->getSrc(0));
701 Operand *Src1 = legalizeUndef(Instr->getSrc(1)); 1119 Operand *Src1 = legalizeUndef(Instr->getSrc(1));
702 if (DestTy == IceType_i64) { 1120 if (DestTy == IceType_i64) {
703 lowerInt64Arithmetic(Instr, Instr->getDest(), Src0, Src1); 1121 lowerInt64Arithmetic(Instr, Instr->getDest(), Src0, Src1);
704 return; 1122 return;
705 } 1123 }
706 if (isVectorType(Dest->getType())) { 1124 if (isVectorType(Dest->getType())) {
707 UnimplementedLoweringError(this, Instr); 1125 UnimplementedLoweringError(this, Instr);
708 return; 1126 return;
709 } 1127 }
710 switch (Instr->getOp()) {
711 default:
712 break;
713 case InstArithmetic::Fadd:
714 case InstArithmetic::Fsub:
715 case InstArithmetic::Fmul:
716 case InstArithmetic::Fdiv:
717 case InstArithmetic::Frem:
718 UnimplementedLoweringError(this, Instr);
719 return;
720 }
721 1128
722 // At this point Dest->getType() is non-i64 scalar 1129 // At this point Dest->getType() is non-i64 scalar
723 1130
724 Variable *T = makeReg(Dest->getType()); 1131 Variable *T = makeReg(Dest->getType());
725 Variable *Src0R = legalizeToReg(Src0); 1132 Variable *Src0R = legalizeToReg(Src0);
726 Variable *Src1R = legalizeToReg(Src1); 1133 Variable *Src1R = legalizeToReg(Src1);
727 1134
728 switch (Instr->getOp()) { 1135 switch (Instr->getOp()) {
729 case InstArithmetic::_num: 1136 case InstArithmetic::_num:
730 break; 1137 break;
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
789 _mov(Dest, T); 1196 _mov(Dest, T);
790 return; 1197 return;
791 } 1198 }
792 case InstArithmetic::Srem: { 1199 case InstArithmetic::Srem: {
793 auto *T_Zero = I32Reg(RegMIPS32::Reg_ZERO); 1200 auto *T_Zero = I32Reg(RegMIPS32::Reg_ZERO);
794 _div(T_Zero, Src0R, Src1R); 1201 _div(T_Zero, Src0R, Src1R);
795 _mfhi(T, T_Zero); 1202 _mfhi(T, T_Zero);
796 _mov(Dest, T); 1203 _mov(Dest, T);
797 return; 1204 return;
798 } 1205 }
799 case InstArithmetic::Fadd: 1206 case InstArithmetic::Fadd: {
1207 if (DestTy == IceType_f32) {
1208 _add_s(T, Src0R, Src1R);
1209 _mov_s(Dest, T);
Jim Stichnoth 2016/06/13 20:14:19 From this, I am seeing invalid asm code being gene
1210 return;
1211 }
1212 if (DestTy == IceType_f64) {
1213 _add_d(T, Src0R, Src1R);
1214 _mov_d(Dest, T);
1215 return;
1216 }
800 break; 1217 break;
1218 }
801 case InstArithmetic::Fsub: 1219 case InstArithmetic::Fsub:
1220 if (DestTy == IceType_f32) {
1221 _sub_s(T, Src0R, Src1R);
1222 _mov_s(Dest, T);
1223 return;
1224 }
1225 if (DestTy == IceType_f64) {
1226 _sub_d(T, Src0R, Src1R);
1227 _mov_d(Dest, T);
1228 return;
1229 }
802 break; 1230 break;
803 case InstArithmetic::Fmul: 1231 case InstArithmetic::Fmul:
1232 if (DestTy == IceType_f32) {
1233 _mul_s(T, Src0R, Src1R);
1234 _mov_s(Dest, T);
1235 return;
1236 }
1237 if (DestTy == IceType_f64) {
1238 _mul_d(T, Src0R, Src1R);
1239 _mov_d(Dest, T);
1240 return;
1241 }
804 break; 1242 break;
805 case InstArithmetic::Fdiv: 1243 case InstArithmetic::Fdiv:
1244 if (DestTy == IceType_f32) {
1245 _div_s(T, Src0R, Src1R);
1246 _mov_s(Dest, T);
1247 return;
1248 }
1249 if (DestTy == IceType_f64) {
1250 _div_d(T, Src0R, Src1R);
1251 _mov_d(Dest, T);
1252 return;
1253 }
806 break; 1254 break;
807 case InstArithmetic::Frem: 1255 case InstArithmetic::Frem:
Jim Stichnoth 2016/06/13 20:14:19 For now, avoid a liveness validation error by addi
808 break; 1256 break;
809 } 1257 }
810 UnimplementedLoweringError(this, Instr); 1258 UnimplementedLoweringError(this, Instr);
811 } 1259 }
812 1260
813 void TargetMIPS32::lowerAssign(const InstAssign *Instr) { 1261 void TargetMIPS32::lowerAssign(const InstAssign *Instr) {
814 Variable *Dest = Instr->getDest(); 1262 Variable *Dest = Instr->getDest();
815 Operand *Src0 = Instr->getSrc(0); 1263 Operand *Src0 = Instr->getSrc(0);
816 assert(Dest->getType() == Src0->getType()); 1264 assert(Dest->getType() == Src0->getType());
817 if (Dest->getType() == IceType_i64) { 1265 if (Dest->getType() == IceType_i64) {
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
927 _slt(DestT, Src1R, Src0R); 1375 _slt(DestT, Src1R, Src0R);
928 _br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::NEZ); 1376 _br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::NEZ);
929 break; 1377 break;
930 } 1378 }
931 } 1379 }
932 } 1380 }
933 } 1381 }
934 1382
935 void TargetMIPS32::lowerCall(const InstCall *Instr) { 1383 void TargetMIPS32::lowerCall(const InstCall *Instr) {
936 // TODO(rkotler): assign arguments to registers and stack. Also reserve stack. 1384 // TODO(rkotler): assign arguments to registers and stack. Also reserve stack.
937 if (Instr->getNumArgs()) { 1385 // if (Instr->getNumArgs()) {
Jim Stichnoth 2016/06/13 20:14:19 remove this
938 UnimplementedLoweringError(this, Instr); 1386 // UnimplementedLoweringError(this, Instr);
939 return; 1387 // return;
940 } 1388 //}
941 // Generate the call instruction. Assign its result to a temporary with high 1389 // Generate the call instruction. Assign its result to a temporary with high
942 // register allocation weight. 1390 // register allocation weight.
943 Variable *Dest = Instr->getDest(); 1391 Variable *Dest = Instr->getDest();
944 // ReturnReg doubles as ReturnRegLo as necessary. 1392 // ReturnReg doubles as ReturnRegLo as necessary.
945 Variable *ReturnReg = nullptr; 1393 Variable *ReturnReg = nullptr;
946 Variable *ReturnRegHi = nullptr; 1394 Variable *ReturnRegHi = nullptr;
947 if (Dest) { 1395 if (Dest) {
948 switch (Dest->getType()) { 1396 switch (Dest->getType()) {
949 case IceType_NUM: 1397 case IceType_NUM:
950 llvm_unreachable("Invalid Call dest type"); 1398 llvm_unreachable("Invalid Call dest type");
951 return; 1399 return;
952 case IceType_void: 1400 case IceType_void:
953 break; 1401 break;
954 case IceType_i1: 1402 case IceType_i1:
955 case IceType_i8: 1403 case IceType_i8:
956 case IceType_i16: 1404 case IceType_i16:
957 case IceType_i32: 1405 case IceType_i32:
958 ReturnReg = makeReg(Dest->getType(), RegMIPS32::Reg_V0); 1406 ReturnReg = makeReg(Dest->getType(), RegMIPS32::Reg_V0);
959 break; 1407 break;
960 case IceType_i64: 1408 case IceType_i64:
961 ReturnReg = I32Reg(RegMIPS32::Reg_V0); 1409 ReturnReg = I32Reg(RegMIPS32::Reg_V0);
962 ReturnRegHi = I32Reg(RegMIPS32::Reg_V1); 1410 ReturnRegHi = I32Reg(RegMIPS32::Reg_V1);
963 break; 1411 break;
964 case IceType_f32: 1412 case IceType_f32:
1413 ReturnReg = makeReg(Dest->getType(), RegMIPS32::Reg_F0);
1414 break;
965 case IceType_f64: 1415 case IceType_f64:
966 UnimplementedLoweringError(this, Instr); 1416 ReturnReg = makeReg(Dest->getType(), RegMIPS32::Reg_F0F1);
967 return; 1417 break;
968 case IceType_v4i1: 1418 case IceType_v4i1:
969 case IceType_v8i1: 1419 case IceType_v8i1:
970 case IceType_v16i1: 1420 case IceType_v16i1:
971 case IceType_v16i8: 1421 case IceType_v16i8:
972 case IceType_v8i16: 1422 case IceType_v8i16:
973 case IceType_v4i32: 1423 case IceType_v4i32:
974 case IceType_v4f32: 1424 case IceType_v4f32: {
975 UnimplementedLoweringError(this, Instr); 1425 UnimplementedLoweringError(this, Instr);
976 return; 1426 return;
977 } 1427 }
1428 }
978 } 1429 }
979 Operand *CallTarget = Instr->getCallTarget(); 1430 Operand *CallTarget = Instr->getCallTarget();
980 // Allow ConstantRelocatable to be left alone as a direct call, 1431 // Allow ConstantRelocatable to be left alone as a direct call,
981 // but force other constants like ConstantInteger32 to be in 1432 // but force other constants like ConstantInteger32 to be in
982 // a register and make it an indirect call. 1433 // a register and make it an indirect call.
983 if (!llvm::isa<ConstantRelocatable>(CallTarget)) { 1434 if (!llvm::isa<ConstantRelocatable>(CallTarget)) {
984 CallTarget = legalize(CallTarget, Legal_Reg); 1435 CallTarget = legalize(CallTarget, Legal_Reg);
985 } 1436 }
986 Inst *NewCall = InstMIPS32Call::create(Func, ReturnReg, CallTarget); 1437 Inst *NewCall = InstMIPS32Call::create(Func, ReturnReg, CallTarget);
987 Context.insert(NewCall); 1438 Context.insert(NewCall);
988 if (ReturnRegHi) 1439 if (ReturnRegHi)
989 Context.insert(InstFakeDef::create(Func, ReturnRegHi)); 1440 Context.insert(InstFakeDef::create(Func, ReturnRegHi));
990 // Insert a register-kill pseudo instruction. 1441 // Insert a register-kill pseudo instruction.
991 Context.insert(InstFakeKill::create(Func, NewCall)); 1442 Context.insert(InstFakeKill::create(Func, NewCall));
992 // Generate a FakeUse to keep the call live if necessary. 1443 // Generate a FakeUse to keep the call live if necessary.
993 if (Instr->hasSideEffects() && ReturnReg) { 1444 if (Instr->hasSideEffects() && ReturnReg) {
994 Context.insert<InstFakeDef>(ReturnReg); 1445 Context.insert<InstFakeDef>(ReturnReg);
Jim Stichnoth 2016/06/13 20:14:19 InstFakeUse
995 } 1446 }
996 if (Dest == nullptr) 1447 if (Dest == nullptr)
997 return; 1448 return;
998 1449
999 // Assign the result of the call to Dest. 1450 // Assign the result of the call to Dest.
1000 if (ReturnReg) { 1451 if (ReturnReg) {
1001 if (ReturnRegHi) { 1452 auto *Zero = getZero();
1002 assert(Dest->getType() == IceType_i64); 1453 switch (Dest->getType()) {
1454 default:
1455 UnimplementedLoweringError(this, Instr);
1456 case IceType_i1:
1457 case IceType_i8:
1458 case IceType_i16:
1459 case IceType_i32: {
1460 _addu(Dest, Zero, ReturnReg);
1461 break;
1462 }
1463 case IceType_i64: {
1003 auto *Dest64On32 = llvm::cast<Variable64On32>(Dest); 1464 auto *Dest64On32 = llvm::cast<Variable64On32>(Dest);
1004 Variable *DestLo = Dest64On32->getLo(); 1465 Variable *DestLo = Dest64On32->getLo();
1005 Variable *DestHi = Dest64On32->getHi(); 1466 Variable *DestHi = Dest64On32->getHi();
1006 _mov(DestLo, ReturnReg); 1467 _addu(DestLo, Zero, ReturnReg);
1007 _mov(DestHi, ReturnRegHi); 1468 _addu(DestHi, Zero, ReturnRegHi);
1008 } else { 1469 break;
1009 assert(Dest->getType() == IceType_i32 || Dest->getType() == IceType_i16 || 1470 }
1010 Dest->getType() == IceType_i8 || Dest->getType() == IceType_i1 || 1471 case IceType_f32: {
1011 isVectorType(Dest->getType())); 1472 _mov_s(Dest, ReturnReg);
1012 if (isFloatingType(Dest->getType()) || isVectorType(Dest->getType())) { 1473 break;
1013 UnimplementedLoweringError(this, Instr); 1474 }
1014 return; 1475 case IceType_f64: {
1015 } else { 1476 _mov_d(Dest, ReturnReg);
1016 _mov(Dest, ReturnReg); 1477 break;
1017 } 1478 }
1479 case IceType_v4i1:
1480 case IceType_v8i1:
1481 case IceType_v16i1:
1482 case IceType_v16i8:
1483 case IceType_v8i16:
1484 case IceType_v4i32:
1485 case IceType_v4f32: {
1486 UnimplementedLoweringError(this, Instr);
1487 return;
1488 }
1018 } 1489 }
1019 } 1490 }
1020 } 1491 }
1021 1492
1022 void TargetMIPS32::lowerCast(const InstCast *Instr) { 1493 void TargetMIPS32::lowerCast(const InstCast *Instr) {
1023 InstCast::OpKind CastKind = Instr->getCastKind(); 1494 InstCast::OpKind CastKind = Instr->getCastKind();
1024 Variable *Dest = Instr->getDest(); 1495 Variable *Dest = Instr->getDest();
1025 Operand *Src0 = legalizeUndef(Instr->getSrc(0)); 1496 Operand *Src0 = legalizeUndef(Instr->getSrc(0));
1026 const Type DestTy = Dest->getType(); 1497 const Type DestTy = Dest->getType();
1027 const Type Src0Ty = Src0->getType(); 1498 const Type Src0Ty = Src0->getType();
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after
1416 } 1887 }
1417 1888
1418 void TargetMIPS32::lowerPhi(const InstPhi * /*Instr*/) { 1889 void TargetMIPS32::lowerPhi(const InstPhi * /*Instr*/) {
1419 Func->setError("Phi found in regular instruction list"); 1890 Func->setError("Phi found in regular instruction list");
1420 } 1891 }
1421 1892
1422 void TargetMIPS32::lowerRet(const InstRet *Instr) { 1893 void TargetMIPS32::lowerRet(const InstRet *Instr) {
1423 Variable *Reg = nullptr; 1894 Variable *Reg = nullptr;
1424 if (Instr->hasRetValue()) { 1895 if (Instr->hasRetValue()) {
1425 Operand *Src0 = Instr->getRetValue(); 1896 Operand *Src0 = Instr->getRetValue();
1897
1426 switch (Src0->getType()) { 1898 switch (Src0->getType()) {
1899 default:
1900 UnimplementedLoweringError(this, Instr);
Jim Stichnoth 2016/06/13 20:14:19 You probably want a "break;" after this, otherwise
1901 case IceType_f32: {
1902 if (auto *Src0V = llvm::dyn_cast<Variable>(Src0)) {
1903 Reg = makeReg(Src0V->getType(), RegMIPS32::Reg_F0);
1904 _mov_s(Reg, Src0V);
1905 }
1906 break;
1907 }
1908 case IceType_f64: {
1909 if (auto *Src0V = llvm::dyn_cast<Variable>(Src0)) {
1910 Reg = makeReg(Src0V->getType(), RegMIPS32::Reg_F0F1);
1911 _mov_d(Reg, Src0V);
1912 }
1913 break;
1914 }
1427 case IceType_i1: 1915 case IceType_i1:
1428 case IceType_i8: 1916 case IceType_i8:
1429 case IceType_i16: 1917 case IceType_i16:
1430 case IceType_i32: { 1918 case IceType_i32: {
1431 // Reg = legalizeToReg(Src0, RegMIPS32::Reg_V0); 1919 // Reg = legalizeToReg(Src0, RegMIPS32::Reg_V0);
1432 Operand *Src0F = legalize(Src0, Legal_Reg); 1920 Operand *Src0F = legalize(Src0, Legal_Reg);
1433 Reg = makeReg(Src0F->getType(), RegMIPS32::Reg_V0); 1921 Reg = makeReg(Src0F->getType(), RegMIPS32::Reg_V0);
1434 _mov(Reg, Src0F); 1922 _mov(Reg, Src0F);
1435 break; 1923 break;
1436 } 1924 }
1437 case IceType_i64: { 1925 case IceType_i64: {
1438 Src0 = legalizeUndef(Src0); 1926 Src0 = legalizeUndef(Src0);
1439 Variable *R0 = legalizeToReg(loOperand(Src0), RegMIPS32::Reg_V0); 1927 Variable *R0 = legalizeToReg(loOperand(Src0), RegMIPS32::Reg_V0);
1440 Variable *R1 = legalizeToReg(hiOperand(Src0), RegMIPS32::Reg_V1); 1928 Variable *R1 = legalizeToReg(hiOperand(Src0), RegMIPS32::Reg_V1);
1441 Reg = R0; 1929 Reg = R0;
1442 Context.insert<InstFakeUse>(R1); 1930 Context.insert<InstFakeUse>(R1);
1443 break; 1931 break;
1444 } 1932 }
1445 1933 case IceType_v4i1:
1446 default: 1934 case IceType_v8i1:
1935 case IceType_v16i1:
1936 case IceType_v16i8:
1937 case IceType_v8i16:
1938 case IceType_v4i32:
1939 case IceType_v4f32: {
1447 UnimplementedLoweringError(this, Instr); 1940 UnimplementedLoweringError(this, Instr);
1941 break;
1942 }
1448 } 1943 }
1449 } 1944 }
1450 _ret(getPhysicalRegister(RegMIPS32::Reg_RA), Reg); 1945 _ret(getPhysicalRegister(RegMIPS32::Reg_RA), Reg);
1451 } 1946 }
1452 1947
1453 void TargetMIPS32::lowerSelect(const InstSelect *Instr) { 1948 void TargetMIPS32::lowerSelect(const InstSelect *Instr) {
1454 UnimplementedLoweringError(this, Instr); 1949 UnimplementedLoweringError(this, Instr);
1455 } 1950 }
1456 1951
1457 void TargetMIPS32::lowerShuffleVector(const InstShuffleVector *Instr) { 1952 void TargetMIPS32::lowerShuffleVector(const InstShuffleVector *Instr) {
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
1544 emitGlobal(*Var, SectionSuffix); 2039 emitGlobal(*Var, SectionSuffix);
1545 } 2040 }
1546 } 2041 }
1547 } break; 2042 } break;
1548 } 2043 }
1549 } 2044 }
1550 2045
1551 void TargetDataMIPS32::lowerConstants() { 2046 void TargetDataMIPS32::lowerConstants() {
1552 if (getFlags().getDisableTranslation()) 2047 if (getFlags().getDisableTranslation())
1553 return; 2048 return;
1554 UnimplementedError(getFlags()); 2049 // UnimplementedError(getFlags());
Jim Stichnoth 2016/06/13 20:14:19 remove this
1555 } 2050 }
1556 2051
1557 void TargetDataMIPS32::lowerJumpTables() { 2052 void TargetDataMIPS32::lowerJumpTables() {
1558 if (getFlags().getDisableTranslation()) 2053 if (getFlags().getDisableTranslation())
1559 return; 2054 return;
1560 UnimplementedError(getFlags()); 2055 // UnimplementedError(getFlags());
Jim Stichnoth 2016/06/13 20:14:19 remove this
1561 } 2056 }
1562 2057
1563 // Helper for legalize() to emit the right code to lower an operand to a 2058 // Helper for legalize() to emit the right code to lower an operand to a
1564 // register of the appropriate type. 2059 // register of the appropriate type.
1565 Variable *TargetMIPS32::copyToReg(Operand *Src, RegNumT RegNum) { 2060 Variable *TargetMIPS32::copyToReg(Operand *Src, RegNumT RegNum) {
1566 Type Ty = Src->getType(); 2061 Type Ty = Src->getType();
1567 Variable *Reg = makeReg(Ty, RegNum); 2062 Variable *Reg = makeReg(Ty, RegNum);
1568 if (isVectorType(Ty) || isFloatingType(Ty)) { 2063 if (isVectorType(Ty)) {
1569 UnimplementedError(getFlags()); 2064 UnimplementedError(getFlags());
2065 } else if (isFloatingType(Ty)) {
2066 (Ty == IceType_f32) ? _mov_s(Reg, llvm::dyn_cast<Variable>(Src))
2067 : _mov_d(Reg, llvm::dyn_cast<Variable>(Src));
1570 } else { 2068 } else {
1571 // Mov's Src operand can really only be the flexible second operand type 2069 // Mov's Src operand can really only be the flexible second operand type
1572 // or a register. Users should guarantee that. 2070 // or a register. Users should guarantee that.
1573 _mov(Reg, Src); 2071 _mov(Reg, Src);
1574 } 2072 }
1575 return Reg; 2073 return Reg;
1576 } 2074 }
1577 2075
1578 Operand *TargetMIPS32::legalize(Operand *From, LegalMask Allowed, 2076 Operand *TargetMIPS32::legalize(Operand *From, LegalMask Allowed,
1579 RegNumT RegNum) { 2077 RegNumT RegNum) {
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
1714 Str << "\t.set\t" 2212 Str << "\t.set\t"
1715 << "nomips16\n"; 2213 << "nomips16\n";
1716 } 2214 }
1717 2215
1718 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; 2216 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM];
1719 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; 2217 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM];
1720 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; 2218 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM];
1721 2219
1722 } // end of namespace MIPS32 2220 } // end of namespace MIPS32
1723 } // end of namespace Ice 2221 } // end of namespace Ice
OLDNEW
« no previous file with comments | « src/IceTargetLoweringMIPS32.h ('k') | src/IceTargetLoweringX8632.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698