OLD | NEW |
1 //===- subzero/src/IceTargetLoweringARM32.cpp - ARM32 lowering ------------===// | 1 //===- subzero/src/IceTargetLoweringARM32.cpp - ARM32 lowering ------------===// |
2 // | 2 // |
3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 /// | 9 /// |
10 /// \file | 10 /// \file |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
167 TargetInstructionSet::ARM32InstructionSet_Begin) + | 167 TargetInstructionSet::ARM32InstructionSet_Begin) + |
168 ARM32InstructionSet::Begin); | 168 ARM32InstructionSet::Begin); |
169 } | 169 } |
170 } | 170 } |
171 | 171 |
172 TargetARM32::TargetARM32(Cfg *Func) | 172 TargetARM32::TargetARM32(Cfg *Func) |
173 : TargetLowering(Func), CPUFeatures(Func->getContext()->getFlags()) { | 173 : TargetLowering(Func), CPUFeatures(Func->getContext()->getFlags()) { |
174 // TODO: Don't initialize IntegerRegisters and friends every time. | 174 // TODO: Don't initialize IntegerRegisters and friends every time. |
175 // Instead, initialize in some sort of static initializer for the | 175 // Instead, initialize in some sort of static initializer for the |
176 // class. | 176 // class. |
| 177 // Limit this size (or do all bitsets need to be the same width)??? |
177 llvm::SmallBitVector IntegerRegisters(RegARM32::Reg_NUM); | 178 llvm::SmallBitVector IntegerRegisters(RegARM32::Reg_NUM); |
178 llvm::SmallBitVector FloatRegisters(RegARM32::Reg_NUM); | 179 llvm::SmallBitVector Float32Registers(RegARM32::Reg_NUM); |
| 180 llvm::SmallBitVector Float64Registers(RegARM32::Reg_NUM); |
179 llvm::SmallBitVector VectorRegisters(RegARM32::Reg_NUM); | 181 llvm::SmallBitVector VectorRegisters(RegARM32::Reg_NUM); |
180 llvm::SmallBitVector InvalidRegisters(RegARM32::Reg_NUM); | 182 llvm::SmallBitVector InvalidRegisters(RegARM32::Reg_NUM); |
181 ScratchRegs.resize(RegARM32::Reg_NUM); | 183 ScratchRegs.resize(RegARM32::Reg_NUM); |
182 #define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \ | 184 #define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \ |
183 isFP) \ | 185 isFP32, isFP64, isVec128) \ |
184 IntegerRegisters[RegARM32::val] = isInt; \ | 186 IntegerRegisters[RegARM32::val] = isInt; \ |
185 FloatRegisters[RegARM32::val] = isFP; \ | 187 Float32Registers[RegARM32::val] = isFP32; \ |
186 VectorRegisters[RegARM32::val] = isFP; \ | 188 Float64Registers[RegARM32::val] = isFP64; \ |
| 189 VectorRegisters[RegARM32::val] = isVec128; \ |
187 ScratchRegs[RegARM32::val] = scratch; | 190 ScratchRegs[RegARM32::val] = scratch; |
188 REGARM32_TABLE; | 191 REGARM32_TABLE; |
189 #undef X | 192 #undef X |
190 TypeToRegisterSet[IceType_void] = InvalidRegisters; | 193 TypeToRegisterSet[IceType_void] = InvalidRegisters; |
191 TypeToRegisterSet[IceType_i1] = IntegerRegisters; | 194 TypeToRegisterSet[IceType_i1] = IntegerRegisters; |
192 TypeToRegisterSet[IceType_i8] = IntegerRegisters; | 195 TypeToRegisterSet[IceType_i8] = IntegerRegisters; |
193 TypeToRegisterSet[IceType_i16] = IntegerRegisters; | 196 TypeToRegisterSet[IceType_i16] = IntegerRegisters; |
194 TypeToRegisterSet[IceType_i32] = IntegerRegisters; | 197 TypeToRegisterSet[IceType_i32] = IntegerRegisters; |
195 TypeToRegisterSet[IceType_i64] = IntegerRegisters; | 198 TypeToRegisterSet[IceType_i64] = IntegerRegisters; |
196 TypeToRegisterSet[IceType_f32] = FloatRegisters; | 199 TypeToRegisterSet[IceType_f32] = Float32Registers; |
197 TypeToRegisterSet[IceType_f64] = FloatRegisters; | 200 TypeToRegisterSet[IceType_f64] = Float64Registers; |
198 TypeToRegisterSet[IceType_v4i1] = VectorRegisters; | 201 TypeToRegisterSet[IceType_v4i1] = VectorRegisters; |
199 TypeToRegisterSet[IceType_v8i1] = VectorRegisters; | 202 TypeToRegisterSet[IceType_v8i1] = VectorRegisters; |
200 TypeToRegisterSet[IceType_v16i1] = VectorRegisters; | 203 TypeToRegisterSet[IceType_v16i1] = VectorRegisters; |
201 TypeToRegisterSet[IceType_v16i8] = VectorRegisters; | 204 TypeToRegisterSet[IceType_v16i8] = VectorRegisters; |
202 TypeToRegisterSet[IceType_v8i16] = VectorRegisters; | 205 TypeToRegisterSet[IceType_v8i16] = VectorRegisters; |
203 TypeToRegisterSet[IceType_v4i32] = VectorRegisters; | 206 TypeToRegisterSet[IceType_v4i32] = VectorRegisters; |
204 TypeToRegisterSet[IceType_v4f32] = VectorRegisters; | 207 TypeToRegisterSet[IceType_v4f32] = VectorRegisters; |
205 } | 208 } |
206 | 209 |
207 void TargetARM32::translateO2() { | 210 void TargetARM32::translateO2() { |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
356 return Br->optimizeBranch(NextNode); | 359 return Br->optimizeBranch(NextNode); |
357 } | 360 } |
358 return false; | 361 return false; |
359 } | 362 } |
360 | 363 |
361 IceString TargetARM32::getRegName(SizeT RegNum, Type Ty) const { | 364 IceString TargetARM32::getRegName(SizeT RegNum, Type Ty) const { |
362 assert(RegNum < RegARM32::Reg_NUM); | 365 assert(RegNum < RegARM32::Reg_NUM); |
363 (void)Ty; | 366 (void)Ty; |
364 static const char *RegNames[] = { | 367 static const char *RegNames[] = { |
365 #define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \ | 368 #define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \ |
366 isFP) \ | 369 isFP32, isFP64, isVec128) \ |
367 name, | 370 name, |
368 REGARM32_TABLE | 371 REGARM32_TABLE |
369 #undef X | 372 #undef X |
370 }; | 373 }; |
371 | 374 |
372 return RegNames[RegNum]; | 375 return RegNames[RegNum]; |
373 } | 376 } |
374 | 377 |
375 Variable *TargetARM32::getPhysicalRegister(SizeT RegNum, Type Ty) { | 378 Variable *TargetARM32::getPhysicalRegister(SizeT RegNum, Type Ty) { |
376 if (Ty == IceType_void) | 379 if (Ty == IceType_void) |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
428 } | 431 } |
429 Str << "]"; | 432 Str << "]"; |
430 } | 433 } |
431 | 434 |
432 bool TargetARM32::CallingConv::I64InRegs(std::pair<int32_t, int32_t> *Regs) { | 435 bool TargetARM32::CallingConv::I64InRegs(std::pair<int32_t, int32_t> *Regs) { |
433 if (NumGPRRegsUsed >= ARM32_MAX_GPR_ARG) | 436 if (NumGPRRegsUsed >= ARM32_MAX_GPR_ARG) |
434 return false; | 437 return false; |
435 int32_t RegLo, RegHi; | 438 int32_t RegLo, RegHi; |
436 // Always start i64 registers at an even register, so this may end | 439 // Always start i64 registers at an even register, so this may end |
437 // up padding away a register. | 440 // up padding away a register. |
438 if (NumGPRRegsUsed % 2 != 0) { | 441 NumGPRRegsUsed = Utils::applyAlignment(NumGPRRegsUsed, 2); |
439 ++NumGPRRegsUsed; | |
440 } | |
441 RegLo = RegARM32::Reg_r0 + NumGPRRegsUsed; | 442 RegLo = RegARM32::Reg_r0 + NumGPRRegsUsed; |
442 ++NumGPRRegsUsed; | 443 ++NumGPRRegsUsed; |
443 RegHi = RegARM32::Reg_r0 + NumGPRRegsUsed; | 444 RegHi = RegARM32::Reg_r0 + NumGPRRegsUsed; |
444 ++NumGPRRegsUsed; | 445 ++NumGPRRegsUsed; |
445 // If this bumps us past the boundary, don't allocate to a register | 446 // If this bumps us past the boundary, don't allocate to a register |
446 // and leave any previously speculatively consumed registers as consumed. | 447 // and leave any previously speculatively consumed registers as consumed. |
447 if (NumGPRRegsUsed > ARM32_MAX_GPR_ARG) | 448 if (NumGPRRegsUsed > ARM32_MAX_GPR_ARG) |
448 return false; | 449 return false; |
449 Regs->first = RegLo; | 450 Regs->first = RegLo; |
450 Regs->second = RegHi; | 451 Regs->second = RegHi; |
451 return true; | 452 return true; |
452 } | 453 } |
453 | 454 |
454 bool TargetARM32::CallingConv::I32InReg(int32_t *Reg) { | 455 bool TargetARM32::CallingConv::I32InReg(int32_t *Reg) { |
455 if (NumGPRRegsUsed >= ARM32_MAX_GPR_ARG) | 456 if (NumGPRRegsUsed >= ARM32_MAX_GPR_ARG) |
456 return false; | 457 return false; |
457 *Reg = RegARM32::Reg_r0 + NumGPRRegsUsed; | 458 *Reg = RegARM32::Reg_r0 + NumGPRRegsUsed; |
458 ++NumGPRRegsUsed; | 459 ++NumGPRRegsUsed; |
459 return true; | 460 return true; |
460 } | 461 } |
461 | 462 |
| 463 bool TargetARM32::CallingConv::FPInReg(Type Ty, int32_t *Reg) { |
| 464 if (NumFPRegUnits >= ARM32_MAX_FP_REG_UNITS) |
| 465 return false; |
| 466 if (isVectorType(Ty)) { |
| 467 NumFPRegUnits = Utils::applyAlignment(NumFPRegUnits, 4); |
| 468 *Reg = RegARM32::Reg_q0 + (NumFPRegUnits / 4); |
| 469 NumFPRegUnits += 4; |
| 470 // If this bumps us past the boundary, don't allocate to a register |
| 471 // and leave any previously speculatively consumed registers as consumed. |
| 472 if (NumFPRegUnits > ARM32_MAX_FP_REG_UNITS) |
| 473 return false; |
| 474 } else if (Ty == IceType_f64) { |
| 475 NumFPRegUnits = Utils::applyAlignment(NumFPRegUnits, 2); |
| 476 *Reg = RegARM32::Reg_d0 + (NumFPRegUnits / 2); |
| 477 NumFPRegUnits += 2; |
| 478 // If this bumps us past the boundary, don't allocate to a register |
| 479 // and leave any previously speculatively consumed registers as consumed. |
| 480 if (NumFPRegUnits > ARM32_MAX_FP_REG_UNITS) |
| 481 return false; |
| 482 } else { |
| 483 assert(Ty == IceType_f32); |
| 484 *Reg = RegARM32::Reg_s0 + NumFPRegUnits; |
| 485 ++NumFPRegUnits; |
| 486 } |
| 487 return true; |
| 488 } |
| 489 |
462 void TargetARM32::lowerArguments() { | 490 void TargetARM32::lowerArguments() { |
463 VarList &Args = Func->getArgs(); | 491 VarList &Args = Func->getArgs(); |
464 TargetARM32::CallingConv CC; | 492 TargetARM32::CallingConv CC; |
465 | 493 |
466 // For each register argument, replace Arg in the argument list with the | 494 // For each register argument, replace Arg in the argument list with the |
467 // home register. Then generate an instruction in the prolog to copy the | 495 // home register. Then generate an instruction in the prolog to copy the |
468 // home register to the assigned location of Arg. | 496 // home register to the assigned location of Arg. |
469 Context.init(Func->getEntryNode()); | 497 Context.init(Func->getEntryNode()); |
470 Context.setInsertPoint(Context.getCur()); | 498 Context.setInsertPoint(Context.getCur()); |
471 | 499 |
472 for (SizeT I = 0, E = Args.size(); I < E; ++I) { | 500 for (SizeT I = 0, E = Args.size(); I < E; ++I) { |
473 Variable *Arg = Args[I]; | 501 Variable *Arg = Args[I]; |
474 Type Ty = Arg->getType(); | 502 Type Ty = Arg->getType(); |
475 // TODO(jvoung): handle float/vector types. | 503 if (Ty == IceType_i64) { |
476 if (isVectorType(Ty)) { | |
477 UnimplementedError(Func->getContext()->getFlags()); | |
478 continue; | |
479 } else if (isFloatingType(Ty)) { | |
480 UnimplementedError(Func->getContext()->getFlags()); | |
481 continue; | |
482 } else if (Ty == IceType_i64) { | |
483 std::pair<int32_t, int32_t> RegPair; | 504 std::pair<int32_t, int32_t> RegPair; |
484 if (!CC.I64InRegs(&RegPair)) | 505 if (!CC.I64InRegs(&RegPair)) |
485 continue; | 506 continue; |
486 Variable *RegisterArg = Func->makeVariable(Ty); | 507 Variable *RegisterArg = Func->makeVariable(Ty); |
487 Variable *RegisterLo = Func->makeVariable(IceType_i32); | 508 Variable *RegisterLo = Func->makeVariable(IceType_i32); |
488 Variable *RegisterHi = Func->makeVariable(IceType_i32); | 509 Variable *RegisterHi = Func->makeVariable(IceType_i32); |
489 if (BuildDefs::dump()) { | 510 if (BuildDefs::dump()) { |
490 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); | 511 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); |
491 RegisterLo->setName(Func, "home_reg_lo:" + Arg->getName(Func)); | 512 RegisterLo->setName(Func, "home_reg_lo:" + Arg->getName(Func)); |
492 RegisterHi->setName(Func, "home_reg_hi:" + Arg->getName(Func)); | 513 RegisterHi->setName(Func, "home_reg_hi:" + Arg->getName(Func)); |
493 } | 514 } |
494 RegisterLo->setRegNum(RegPair.first); | 515 RegisterLo->setRegNum(RegPair.first); |
495 RegisterLo->setIsArg(); | 516 RegisterLo->setIsArg(); |
496 RegisterHi->setRegNum(RegPair.second); | 517 RegisterHi->setRegNum(RegPair.second); |
497 RegisterHi->setIsArg(); | 518 RegisterHi->setIsArg(); |
498 RegisterArg->setLoHi(RegisterLo, RegisterHi); | 519 RegisterArg->setLoHi(RegisterLo, RegisterHi); |
499 RegisterArg->setIsArg(); | 520 RegisterArg->setIsArg(); |
500 Arg->setIsArg(false); | 521 Arg->setIsArg(false); |
501 | 522 |
502 Args[I] = RegisterArg; | 523 Args[I] = RegisterArg; |
503 Context.insert(InstAssign::create(Func, Arg, RegisterArg)); | 524 Context.insert(InstAssign::create(Func, Arg, RegisterArg)); |
504 continue; | 525 continue; |
505 } else { | 526 } else { |
506 assert(Ty == IceType_i32); | |
507 int32_t RegNum; | 527 int32_t RegNum; |
508 if (!CC.I32InReg(&RegNum)) | 528 if (isVectorType(Ty) || isFloatingType(Ty)) { |
509 continue; | 529 if (!CC.FPInReg(Ty, &RegNum)) |
| 530 continue; |
| 531 } else { |
| 532 assert(Ty == IceType_i32); |
| 533 if (!CC.I32InReg(&RegNum)) |
| 534 continue; |
| 535 } |
510 Variable *RegisterArg = Func->makeVariable(Ty); | 536 Variable *RegisterArg = Func->makeVariable(Ty); |
511 if (BuildDefs::dump()) { | 537 if (BuildDefs::dump()) { |
512 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); | 538 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); |
513 } | 539 } |
514 RegisterArg->setRegNum(RegNum); | 540 RegisterArg->setRegNum(RegNum); |
515 RegisterArg->setIsArg(); | 541 RegisterArg->setIsArg(); |
516 Arg->setIsArg(false); | 542 Arg->setIsArg(false); |
517 | 543 |
518 Args[I] = RegisterArg; | 544 Args[I] = RegisterArg; |
519 Context.insert(InstAssign::create(Func, Arg, RegisterArg)); | 545 Context.insert(InstAssign::create(Func, Arg, RegisterArg)); |
| 546 continue; |
520 } | 547 } |
521 } | 548 } |
522 } | 549 } |
523 | 550 |
524 // Helper function for addProlog(). | 551 // Helper function for addProlog(). |
525 // | 552 // |
526 // This assumes Arg is an argument passed on the stack. This sets the | 553 // This assumes Arg is an argument passed on the stack. This sets the |
527 // frame offset for Arg and updates InArgsSizeBytes according to Arg's | 554 // frame offset for Arg and updates InArgsSizeBytes according to Arg's |
528 // width. For an I64 arg that has been split into Lo and Hi components, | 555 // width. For an I64 arg that has been split into Lo and Hi components, |
529 // it calls itself recursively on the components, taking care to handle | 556 // it calls itself recursively on the components, taking care to handle |
(...skipping 17 matching lines...) Expand all Loading... |
547 Arg->setStackOffset(BasicFrameOffset + InArgsSizeBytes); | 574 Arg->setStackOffset(BasicFrameOffset + InArgsSizeBytes); |
548 InArgsSizeBytes += typeWidthInBytesOnStack(Ty); | 575 InArgsSizeBytes += typeWidthInBytesOnStack(Ty); |
549 // If the argument variable has been assigned a register, we need to load | 576 // If the argument variable has been assigned a register, we need to load |
550 // the value from the stack slot. | 577 // the value from the stack slot. |
551 if (Arg->hasReg()) { | 578 if (Arg->hasReg()) { |
552 assert(Ty != IceType_i64); | 579 assert(Ty != IceType_i64); |
553 OperandARM32Mem *Mem = OperandARM32Mem::create( | 580 OperandARM32Mem *Mem = OperandARM32Mem::create( |
554 Func, Ty, FramePtr, llvm::cast<ConstantInteger32>( | 581 Func, Ty, FramePtr, llvm::cast<ConstantInteger32>( |
555 Ctx->getConstantInt32(Arg->getStackOffset()))); | 582 Ctx->getConstantInt32(Arg->getStackOffset()))); |
556 if (isVectorType(Arg->getType())) { | 583 if (isVectorType(Arg->getType())) { |
| 584 // Use vld1.$elem or something? |
557 UnimplementedError(Func->getContext()->getFlags()); | 585 UnimplementedError(Func->getContext()->getFlags()); |
| 586 } else if (isFloatingType(Arg->getType())) { |
| 587 _vldr(Arg, Mem); |
558 } else { | 588 } else { |
559 _ldr(Arg, Mem); | 589 _ldr(Arg, Mem); |
560 } | 590 } |
561 // This argument-copying instruction uses an explicit | 591 // This argument-copying instruction uses an explicit |
562 // OperandARM32Mem operand instead of a Variable, so its | 592 // OperandARM32Mem operand instead of a Variable, so its |
563 // fill-from-stack operation has to be tracked separately for | 593 // fill-from-stack operation has to be tracked separately for |
564 // statistics. | 594 // statistics. |
565 Ctx->statsUpdateFills(); | 595 Ctx->statsUpdateFills(); |
566 } | 596 } |
567 } | 597 } |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
718 if (!UsesFramePointer) | 748 if (!UsesFramePointer) |
719 BasicFrameOffset += SpillAreaSizeBytes; | 749 BasicFrameOffset += SpillAreaSizeBytes; |
720 | 750 |
721 const VarList &Args = Func->getArgs(); | 751 const VarList &Args = Func->getArgs(); |
722 size_t InArgsSizeBytes = 0; | 752 size_t InArgsSizeBytes = 0; |
723 TargetARM32::CallingConv CC; | 753 TargetARM32::CallingConv CC; |
724 for (Variable *Arg : Args) { | 754 for (Variable *Arg : Args) { |
725 Type Ty = Arg->getType(); | 755 Type Ty = Arg->getType(); |
726 bool InRegs = false; | 756 bool InRegs = false; |
727 // Skip arguments passed in registers. | 757 // Skip arguments passed in registers. |
728 if (isVectorType(Ty)) { | 758 if (isVectorType(Ty) || isFloatingType(Ty)) { |
729 UnimplementedError(Func->getContext()->getFlags()); | 759 int32_t DummyReg; |
730 continue; | 760 InRegs = CC.FPInReg(Ty, &DummyReg); |
731 } else if (isFloatingType(Ty)) { | |
732 UnimplementedError(Func->getContext()->getFlags()); | |
733 continue; | |
734 } else if (Ty == IceType_i64) { | 761 } else if (Ty == IceType_i64) { |
735 std::pair<int32_t, int32_t> DummyRegs; | 762 std::pair<int32_t, int32_t> DummyRegs; |
736 InRegs = CC.I64InRegs(&DummyRegs); | 763 InRegs = CC.I64InRegs(&DummyRegs); |
737 } else { | 764 } else { |
738 assert(Ty == IceType_i32); | 765 assert(Ty == IceType_i32); |
739 int32_t DummyReg; | 766 int32_t DummyReg; |
740 InRegs = CC.I32InReg(&DummyReg); | 767 InRegs = CC.I32InReg(&DummyReg); |
741 } | 768 } |
742 if (!InRegs) | 769 if (!InRegs) |
743 finishArgumentLowering(Arg, FramePtr, BasicFrameOffset, InArgsSizeBytes); | 770 finishArgumentLowering(Arg, FramePtr, BasicFrameOffset, InArgsSizeBytes); |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
851 RetValue = llvm::cast<Variable>(RI->getSrc(0)); | 878 RetValue = llvm::cast<Variable>(RI->getSrc(0)); |
852 _bundle_lock(); | 879 _bundle_lock(); |
853 _bic(LR, LR, RetMask); | 880 _bic(LR, LR, RetMask); |
854 _ret(LR, RetValue); | 881 _ret(LR, RetValue); |
855 _bundle_unlock(); | 882 _bundle_unlock(); |
856 RI->setDeleted(); | 883 RI->setDeleted(); |
857 } | 884 } |
858 | 885 |
859 bool TargetARM32::isLegalVariableStackOffset(int32_t Offset) const { | 886 bool TargetARM32::isLegalVariableStackOffset(int32_t Offset) const { |
860 constexpr bool SignExt = false; | 887 constexpr bool SignExt = false; |
| 888 // TODO(jvoung): vldr of FP stack slots has a different limit from the |
| 889 // plain stackSlotType(). |
861 return OperandARM32Mem::canHoldOffset(stackSlotType(), SignExt, Offset); | 890 return OperandARM32Mem::canHoldOffset(stackSlotType(), SignExt, Offset); |
862 } | 891 } |
863 | 892 |
864 StackVariable *TargetARM32::legalizeVariableSlot(Variable *Var, | 893 StackVariable *TargetARM32::legalizeVariableSlot(Variable *Var, |
865 Variable *OrigBaseReg) { | 894 Variable *OrigBaseReg) { |
866 int32_t Offset = Var->getStackOffset(); | 895 int32_t Offset = Var->getStackOffset(); |
867 // Legalize will likely need a movw/movt combination, but if the top | 896 // Legalize will likely need a movw/movt combination, but if the top |
868 // bits are all 0 from negating the offset and subtracting, we could | 897 // bits are all 0 from negating the offset and subtracting, we could |
869 // use that instead. | 898 // use that instead. |
870 bool ShouldSub = (-Offset & 0xFFFF0000) == 0; | 899 bool ShouldSub = (-Offset & 0xFFFF0000) == 0; |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1114 } | 1143 } |
1115 llvm_unreachable("Unsupported operand type"); | 1144 llvm_unreachable("Unsupported operand type"); |
1116 return nullptr; | 1145 return nullptr; |
1117 } | 1146 } |
1118 | 1147 |
1119 llvm::SmallBitVector TargetARM32::getRegisterSet(RegSetMask Include, | 1148 llvm::SmallBitVector TargetARM32::getRegisterSet(RegSetMask Include, |
1120 RegSetMask Exclude) const { | 1149 RegSetMask Exclude) const { |
1121 llvm::SmallBitVector Registers(RegARM32::Reg_NUM); | 1150 llvm::SmallBitVector Registers(RegARM32::Reg_NUM); |
1122 | 1151 |
1123 #define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \ | 1152 #define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \ |
1124 isFP) \ | 1153 isFP32, isFP64, isVec128) \ |
1125 if (scratch && (Include & RegSet_CallerSave)) \ | 1154 if (scratch && (Include & RegSet_CallerSave)) \ |
1126 Registers[RegARM32::val] = true; \ | 1155 Registers[RegARM32::val] = true; \ |
1127 if (preserved && (Include & RegSet_CalleeSave)) \ | 1156 if (preserved && (Include & RegSet_CalleeSave)) \ |
1128 Registers[RegARM32::val] = true; \ | 1157 Registers[RegARM32::val] = true; \ |
1129 if (stackptr && (Include & RegSet_StackPointer)) \ | 1158 if (stackptr && (Include & RegSet_StackPointer)) \ |
1130 Registers[RegARM32::val] = true; \ | 1159 Registers[RegARM32::val] = true; \ |
1131 if (frameptr && (Include & RegSet_FramePointer)) \ | 1160 if (frameptr && (Include & RegSet_FramePointer)) \ |
1132 Registers[RegARM32::val] = true; \ | 1161 Registers[RegARM32::val] = true; \ |
1133 if (scratch && (Exclude & RegSet_CallerSave)) \ | 1162 if (scratch && (Exclude & RegSet_CallerSave)) \ |
1134 Registers[RegARM32::val] = false; \ | 1163 Registers[RegARM32::val] = false; \ |
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1511 case InstArithmetic::Sdiv: | 1540 case InstArithmetic::Sdiv: |
1512 case InstArithmetic::Urem: | 1541 case InstArithmetic::Urem: |
1513 case InstArithmetic::Srem: | 1542 case InstArithmetic::Srem: |
1514 llvm_unreachable("Call-helper-involved instruction for i64 type " | 1543 llvm_unreachable("Call-helper-involved instruction for i64 type " |
1515 "should have already been handled before"); | 1544 "should have already been handled before"); |
1516 return; | 1545 return; |
1517 } | 1546 } |
1518 return; | 1547 return; |
1519 } else if (isVectorType(Dest->getType())) { | 1548 } else if (isVectorType(Dest->getType())) { |
1520 UnimplementedError(Func->getContext()->getFlags()); | 1549 UnimplementedError(Func->getContext()->getFlags()); |
| 1550 // Add a fake def to keep liveness consistent in the meantime. |
| 1551 Context.insert(InstFakeDef::create(Func, Dest)); |
1521 return; | 1552 return; |
1522 } | 1553 } |
1523 // Dest->getType() is a non-i64 scalar. | 1554 // Dest->getType() is a non-i64 scalar. |
1524 Variable *Src0R = legalizeToReg(Src0); | 1555 Variable *Src0R = legalizeToReg(Src0); |
1525 Variable *T = makeReg(Dest->getType()); | 1556 Variable *T = makeReg(Dest->getType()); |
1526 // Handle div/rem separately. They require a non-legalized Src1 to inspect | 1557 // Handle div/rem separately. They require a non-legalized Src1 to inspect |
1527 // whether or not Src1 is a non-zero constant. Once legalized it is more | 1558 // whether or not Src1 is a non-zero constant. Once legalized it is more |
1528 // difficult to determine (constant may be moved to a register). | 1559 // difficult to determine (constant may be moved to a register). |
1529 switch (Inst->getOp()) { | 1560 switch (Inst->getOp()) { |
1530 default: | 1561 default: |
(...skipping 15 matching lines...) Expand all Loading... |
1546 lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_uxt, &TargetARM32::_udiv, | 1577 lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_uxt, &TargetARM32::_udiv, |
1547 H_urem_i32, IsRemainder); | 1578 H_urem_i32, IsRemainder); |
1548 return; | 1579 return; |
1549 } | 1580 } |
1550 case InstArithmetic::Srem: { | 1581 case InstArithmetic::Srem: { |
1551 constexpr bool IsRemainder = true; | 1582 constexpr bool IsRemainder = true; |
1552 lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_sxt, &TargetARM32::_sdiv, | 1583 lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_sxt, &TargetARM32::_sdiv, |
1553 H_srem_i32, IsRemainder); | 1584 H_srem_i32, IsRemainder); |
1554 return; | 1585 return; |
1555 } | 1586 } |
| 1587 case InstArithmetic::Frem: { |
| 1588 const SizeT MaxSrcs = 2; |
| 1589 Type Ty = Dest->getType(); |
| 1590 InstCall *Call = makeHelperCall( |
| 1591 isFloat32Asserting32Or64(Ty) ? H_frem_f32 : H_frem_f64, Dest, MaxSrcs); |
| 1592 Call->addArg(Src0R); |
| 1593 Call->addArg(Src1); |
| 1594 lowerCall(Call); |
| 1595 return; |
| 1596 } |
| 1597 } |
| 1598 |
| 1599 // Handle floating point arithmetic separately: they require Src1 to be |
| 1600 // legalized to a register. |
| 1601 switch (Inst->getOp()) { |
| 1602 default: |
| 1603 break; |
| 1604 case InstArithmetic::Fadd: { |
| 1605 Variable *Src1R = legalizeToReg(Src1); |
| 1606 _vadd(T, Src0R, Src1R); |
| 1607 _vmov(Dest, T); |
| 1608 return; |
| 1609 } |
| 1610 case InstArithmetic::Fsub: { |
| 1611 Variable *Src1R = legalizeToReg(Src1); |
| 1612 _vsub(T, Src0R, Src1R); |
| 1613 _vmov(Dest, T); |
| 1614 return; |
| 1615 } |
| 1616 case InstArithmetic::Fmul: { |
| 1617 Variable *Src1R = legalizeToReg(Src1); |
| 1618 _vmul(T, Src0R, Src1R); |
| 1619 _vmov(Dest, T); |
| 1620 return; |
| 1621 } |
| 1622 case InstArithmetic::Fdiv: { |
| 1623 Variable *Src1R = legalizeToReg(Src1); |
| 1624 _vdiv(T, Src0R, Src1R); |
| 1625 _vmov(Dest, T); |
| 1626 return; |
| 1627 } |
1556 } | 1628 } |
1557 | 1629 |
1558 Operand *Src1RF = legalize(Src1, Legal_Reg | Legal_Flex); | 1630 Operand *Src1RF = legalize(Src1, Legal_Reg | Legal_Flex); |
1559 switch (Inst->getOp()) { | 1631 switch (Inst->getOp()) { |
1560 case InstArithmetic::_num: | 1632 case InstArithmetic::_num: |
1561 llvm_unreachable("Unknown arithmetic operator"); | 1633 llvm_unreachable("Unknown arithmetic operator"); |
1562 return; | 1634 return; |
1563 case InstArithmetic::Add: | 1635 case InstArithmetic::Add: |
1564 _add(T, Src0R, Src1RF); | 1636 _add(T, Src0R, Src1RF); |
1565 _mov(Dest, T); | 1637 _mov(Dest, T); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1598 _asr(T, Src0R, Src1RF); | 1670 _asr(T, Src0R, Src1RF); |
1599 _mov(Dest, T); | 1671 _mov(Dest, T); |
1600 return; | 1672 return; |
1601 case InstArithmetic::Udiv: | 1673 case InstArithmetic::Udiv: |
1602 case InstArithmetic::Sdiv: | 1674 case InstArithmetic::Sdiv: |
1603 case InstArithmetic::Urem: | 1675 case InstArithmetic::Urem: |
1604 case InstArithmetic::Srem: | 1676 case InstArithmetic::Srem: |
1605 llvm_unreachable("Integer div/rem should have been handled earlier."); | 1677 llvm_unreachable("Integer div/rem should have been handled earlier."); |
1606 return; | 1678 return; |
1607 case InstArithmetic::Fadd: | 1679 case InstArithmetic::Fadd: |
1608 UnimplementedError(Func->getContext()->getFlags()); | |
1609 return; | |
1610 case InstArithmetic::Fsub: | 1680 case InstArithmetic::Fsub: |
1611 UnimplementedError(Func->getContext()->getFlags()); | |
1612 return; | |
1613 case InstArithmetic::Fmul: | 1681 case InstArithmetic::Fmul: |
1614 UnimplementedError(Func->getContext()->getFlags()); | |
1615 return; | |
1616 case InstArithmetic::Fdiv: | 1682 case InstArithmetic::Fdiv: |
1617 UnimplementedError(Func->getContext()->getFlags()); | |
1618 return; | |
1619 case InstArithmetic::Frem: | 1683 case InstArithmetic::Frem: |
1620 UnimplementedError(Func->getContext()->getFlags()); | 1684 llvm_unreachable("Floating point arith should have been handled earlier."); |
1621 return; | 1685 return; |
1622 } | 1686 } |
1623 } | 1687 } |
1624 | 1688 |
1625 void TargetARM32::lowerAssign(const InstAssign *Inst) { | 1689 void TargetARM32::lowerAssign(const InstAssign *Inst) { |
1626 Variable *Dest = Inst->getDest(); | 1690 Variable *Dest = Inst->getDest(); |
1627 Operand *Src0 = Inst->getSrc(0); | 1691 Operand *Src0 = Inst->getSrc(0); |
1628 assert(Dest->getType() == Src0->getType()); | 1692 assert(Dest->getType() == Src0->getType()); |
1629 if (Dest->getType() == IceType_i64) { | 1693 if (Dest->getType() == IceType_i64) { |
1630 Src0 = legalizeUndef(Src0); | 1694 Src0 = legalizeUndef(Src0); |
(...skipping 14 matching lines...) Expand all Loading... |
1645 // helps allow the use of Flex operands. | 1709 // helps allow the use of Flex operands. |
1646 NewSrc = legalize(Src0, Legal_Reg | Legal_Flex, Dest->getRegNum()); | 1710 NewSrc = legalize(Src0, Legal_Reg | Legal_Flex, Dest->getRegNum()); |
1647 } else { | 1711 } else { |
1648 // Dest could be a stack operand. Since we could potentially need | 1712 // Dest could be a stack operand. Since we could potentially need |
1649 // to do a Store (and store can only have Register operands), | 1713 // to do a Store (and store can only have Register operands), |
1650 // legalize this to a register. | 1714 // legalize this to a register. |
1651 NewSrc = legalize(Src0, Legal_Reg); | 1715 NewSrc = legalize(Src0, Legal_Reg); |
1652 } | 1716 } |
1653 if (isVectorType(Dest->getType())) { | 1717 if (isVectorType(Dest->getType())) { |
1654 UnimplementedError(Func->getContext()->getFlags()); | 1718 UnimplementedError(Func->getContext()->getFlags()); |
| 1719 } else if (isFloatingType(Dest->getType())) { |
| 1720 Variable *SrcR = legalizeToReg(NewSrc); |
| 1721 _vmov(Dest, SrcR); |
1655 } else { | 1722 } else { |
1656 _mov(Dest, NewSrc); | 1723 _mov(Dest, NewSrc); |
1657 } | 1724 } |
1658 } | 1725 } |
1659 } | 1726 } |
1660 | 1727 |
1661 void TargetARM32::lowerBr(const InstBr *Inst) { | 1728 void TargetARM32::lowerBr(const InstBr *Inst) { |
1662 if (Inst->isUnconditional()) { | 1729 if (Inst->isUnconditional()) { |
1663 _br(Inst->getTargetUnconditional()); | 1730 _br(Inst->getTargetUnconditional()); |
1664 return; | 1731 return; |
1665 } | 1732 } |
1666 Operand *Cond = Inst->getCondition(); | 1733 Operand *Cond = Inst->getCondition(); |
1667 // TODO(jvoung): Handle folding opportunities. | 1734 // TODO(jvoung): Handle folding opportunities. |
1668 | 1735 |
1669 Variable *Src0R = legalizeToReg(Cond); | 1736 Variable *Src0R = legalizeToReg(Cond); |
1670 Constant *Zero = Ctx->getConstantZero(IceType_i32); | 1737 Constant *Zero = Ctx->getConstantZero(IceType_i32); |
1671 _cmp(Src0R, Zero); | 1738 _cmp(Src0R, Zero); |
1672 _br(Inst->getTargetTrue(), Inst->getTargetFalse(), CondARM32::NE); | 1739 _br(Inst->getTargetTrue(), Inst->getTargetFalse(), CondARM32::NE); |
1673 } | 1740 } |
1674 | 1741 |
1675 void TargetARM32::lowerCall(const InstCall *Instr) { | 1742 void TargetARM32::lowerCall(const InstCall *Instr) { |
1676 MaybeLeafFunc = false; | 1743 MaybeLeafFunc = false; |
1677 NeedsStackAlignment = true; | 1744 NeedsStackAlignment = true; |
1678 | 1745 |
1679 // Assign arguments to registers and stack. Also reserve stack. | 1746 // Assign arguments to registers and stack. Also reserve stack. |
1680 TargetARM32::CallingConv CC; | 1747 TargetARM32::CallingConv CC; |
1681 // Pair of Arg Operand -> GPR number assignments. | 1748 // Pair of Arg Operand -> GPR number assignments. |
1682 llvm::SmallVector<std::pair<Operand *, int32_t>, | 1749 llvm::SmallVector<std::pair<Operand *, int32_t>, |
1683 TargetARM32::CallingConv::ARM32_MAX_GPR_ARG> GPRArgs; | 1750 TargetARM32::CallingConv::ARM32_MAX_GPR_ARG> GPRArgs; |
| 1751 llvm::SmallVector<std::pair<Operand *, int32_t>, |
| 1752 TargetARM32::CallingConv::ARM32_MAX_FP_REG_UNITS> FPArgs; |
1684 // Pair of Arg Operand -> stack offset. | 1753 // Pair of Arg Operand -> stack offset. |
1685 llvm::SmallVector<std::pair<Operand *, int32_t>, 8> StackArgs; | 1754 llvm::SmallVector<std::pair<Operand *, int32_t>, 8> StackArgs; |
1686 int32_t ParameterAreaSizeBytes = 0; | 1755 int32_t ParameterAreaSizeBytes = 0; |
1687 | 1756 |
1688 // Classify each argument operand according to the location where the | 1757 // Classify each argument operand according to the location where the |
1689 // argument is passed. | 1758 // argument is passed. |
1690 for (SizeT i = 0, NumArgs = Instr->getNumArgs(); i < NumArgs; ++i) { | 1759 for (SizeT i = 0, NumArgs = Instr->getNumArgs(); i < NumArgs; ++i) { |
1691 Operand *Arg = legalizeUndef(Instr->getArg(i)); | 1760 Operand *Arg = legalizeUndef(Instr->getArg(i)); |
1692 Type Ty = Arg->getType(); | 1761 Type Ty = Arg->getType(); |
1693 bool InRegs = false; | 1762 bool InRegs = false; |
1694 if (isVectorType(Ty)) { | 1763 if (Ty == IceType_i64) { |
1695 UnimplementedError(Func->getContext()->getFlags()); | |
1696 } else if (isFloatingType(Ty)) { | |
1697 UnimplementedError(Func->getContext()->getFlags()); | |
1698 } else if (Ty == IceType_i64) { | |
1699 std::pair<int32_t, int32_t> Regs; | 1764 std::pair<int32_t, int32_t> Regs; |
1700 if (CC.I64InRegs(&Regs)) { | 1765 if (CC.I64InRegs(&Regs)) { |
1701 InRegs = true; | 1766 InRegs = true; |
1702 Operand *Lo = loOperand(Arg); | 1767 Operand *Lo = loOperand(Arg); |
1703 Operand *Hi = hiOperand(Arg); | 1768 Operand *Hi = hiOperand(Arg); |
1704 GPRArgs.push_back(std::make_pair(Lo, Regs.first)); | 1769 GPRArgs.push_back(std::make_pair(Lo, Regs.first)); |
1705 GPRArgs.push_back(std::make_pair(Hi, Regs.second)); | 1770 GPRArgs.push_back(std::make_pair(Hi, Regs.second)); |
1706 } | 1771 } |
| 1772 } else if (isVectorType(Ty) || isFloatingType(Ty)) { |
| 1773 int32_t Reg; |
| 1774 if (CC.FPInReg(Ty, &Reg)) { |
| 1775 InRegs = true; |
| 1776 FPArgs.push_back(std::make_pair(Arg, Reg)); |
| 1777 } |
1707 } else { | 1778 } else { |
1708 assert(Ty == IceType_i32); | 1779 assert(Ty == IceType_i32); |
1709 int32_t Reg; | 1780 int32_t Reg; |
1710 if (CC.I32InReg(&Reg)) { | 1781 if (CC.I32InReg(&Reg)) { |
1711 InRegs = true; | 1782 InRegs = true; |
1712 GPRArgs.push_back(std::make_pair(Arg, Reg)); | 1783 GPRArgs.push_back(std::make_pair(Arg, Reg)); |
1713 } | 1784 } |
1714 } | 1785 } |
1715 | 1786 |
1716 if (!InRegs) { | 1787 if (!InRegs) { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1759 } | 1830 } |
1760 | 1831 |
1761 // Copy arguments to be passed in registers to the appropriate registers. | 1832 // Copy arguments to be passed in registers to the appropriate registers. |
1762 for (auto &GPRArg : GPRArgs) { | 1833 for (auto &GPRArg : GPRArgs) { |
1763 Variable *Reg = legalizeToReg(GPRArg.first, GPRArg.second); | 1834 Variable *Reg = legalizeToReg(GPRArg.first, GPRArg.second); |
1764 // Generate a FakeUse of register arguments so that they do not get | 1835 // Generate a FakeUse of register arguments so that they do not get |
1765 // dead code eliminated as a result of the FakeKill of scratch | 1836 // dead code eliminated as a result of the FakeKill of scratch |
1766 // registers after the call. | 1837 // registers after the call. |
1767 Context.insert(InstFakeUse::create(Func, Reg)); | 1838 Context.insert(InstFakeUse::create(Func, Reg)); |
1768 } | 1839 } |
| 1840 for (auto &FPArg : FPArgs) { |
| 1841 Variable *Reg = legalizeToReg(FPArg.first, FPArg.second); |
| 1842 Context.insert(InstFakeUse::create(Func, Reg)); |
| 1843 } |
1769 | 1844 |
1770 // Generate the call instruction. Assign its result to a temporary | 1845 // Generate the call instruction. Assign its result to a temporary |
1771 // with high register allocation weight. | 1846 // with high register allocation weight. |
1772 Variable *Dest = Instr->getDest(); | 1847 Variable *Dest = Instr->getDest(); |
1773 // ReturnReg doubles as ReturnRegLo as necessary. | 1848 // ReturnReg doubles as ReturnRegLo as necessary. |
1774 Variable *ReturnReg = nullptr; | 1849 Variable *ReturnReg = nullptr; |
1775 Variable *ReturnRegHi = nullptr; | 1850 Variable *ReturnRegHi = nullptr; |
1776 if (Dest) { | 1851 if (Dest) { |
1777 switch (Dest->getType()) { | 1852 switch (Dest->getType()) { |
1778 case IceType_NUM: | 1853 case IceType_NUM: |
1779 llvm_unreachable("Invalid Call dest type"); | 1854 llvm_unreachable("Invalid Call dest type"); |
1780 break; | 1855 break; |
1781 case IceType_void: | 1856 case IceType_void: |
1782 break; | 1857 break; |
1783 case IceType_i1: | 1858 case IceType_i1: |
1784 case IceType_i8: | 1859 case IceType_i8: |
1785 case IceType_i16: | 1860 case IceType_i16: |
1786 case IceType_i32: | 1861 case IceType_i32: |
1787 ReturnReg = makeReg(Dest->getType(), RegARM32::Reg_r0); | 1862 ReturnReg = makeReg(Dest->getType(), RegARM32::Reg_r0); |
1788 break; | 1863 break; |
1789 case IceType_i64: | 1864 case IceType_i64: |
1790 ReturnReg = makeReg(IceType_i32, RegARM32::Reg_r0); | 1865 ReturnReg = makeReg(IceType_i32, RegARM32::Reg_r0); |
1791 ReturnRegHi = makeReg(IceType_i32, RegARM32::Reg_r1); | 1866 ReturnRegHi = makeReg(IceType_i32, RegARM32::Reg_r1); |
1792 break; | 1867 break; |
1793 case IceType_f32: | 1868 case IceType_f32: |
| 1869 ReturnReg = makeReg(Dest->getType(), RegARM32::Reg_s0); |
| 1870 break; |
1794 case IceType_f64: | 1871 case IceType_f64: |
1795 // Use S and D regs. | 1872 ReturnReg = makeReg(Dest->getType(), RegARM32::Reg_d0); |
1796 UnimplementedError(Func->getContext()->getFlags()); | |
1797 break; | 1873 break; |
1798 case IceType_v4i1: | 1874 case IceType_v4i1: |
1799 case IceType_v8i1: | 1875 case IceType_v8i1: |
1800 case IceType_v16i1: | 1876 case IceType_v16i1: |
1801 case IceType_v16i8: | 1877 case IceType_v16i8: |
1802 case IceType_v8i16: | 1878 case IceType_v8i16: |
1803 case IceType_v4i32: | 1879 case IceType_v4i32: |
1804 case IceType_v4f32: | 1880 case IceType_v4f32: |
1805 // Use Q regs. | 1881 ReturnReg = makeReg(Dest->getType(), RegARM32::Reg_q0); |
1806 UnimplementedError(Func->getContext()->getFlags()); | |
1807 break; | 1882 break; |
1808 } | 1883 } |
1809 } | 1884 } |
1810 Operand *CallTarget = Instr->getCallTarget(); | 1885 Operand *CallTarget = Instr->getCallTarget(); |
1811 // TODO(jvoung): Handle sandboxing. | 1886 // TODO(jvoung): Handle sandboxing. |
1812 // const bool NeedSandboxing = Ctx->getFlags().getUseSandboxing(); | 1887 // const bool NeedSandboxing = Ctx->getFlags().getUseSandboxing(); |
1813 | 1888 |
1814 // Allow ConstantRelocatable to be left alone as a direct call, | 1889 // Allow ConstantRelocatable to be left alone as a direct call, |
1815 // but force other constants like ConstantInteger32 to be in | 1890 // but force other constants like ConstantInteger32 to be in |
1816 // a register and make it an indirect call. | 1891 // a register and make it an indirect call. |
(...skipping 29 matching lines...) Expand all Loading... |
1846 // Assign the result of the call to Dest. | 1921 // Assign the result of the call to Dest. |
1847 if (ReturnReg) { | 1922 if (ReturnReg) { |
1848 if (ReturnRegHi) { | 1923 if (ReturnRegHi) { |
1849 assert(Dest->getType() == IceType_i64); | 1924 assert(Dest->getType() == IceType_i64); |
1850 split64(Dest); | 1925 split64(Dest); |
1851 Variable *DestLo = Dest->getLo(); | 1926 Variable *DestLo = Dest->getLo(); |
1852 Variable *DestHi = Dest->getHi(); | 1927 Variable *DestHi = Dest->getHi(); |
1853 _mov(DestLo, ReturnReg); | 1928 _mov(DestLo, ReturnReg); |
1854 _mov(DestHi, ReturnRegHi); | 1929 _mov(DestHi, ReturnRegHi); |
1855 } else { | 1930 } else { |
1856 assert(Dest->getType() == IceType_i32 || Dest->getType() == IceType_i16 || | |
1857 Dest->getType() == IceType_i8 || Dest->getType() == IceType_i1 || | |
1858 isVectorType(Dest->getType())); | |
1859 if (isFloatingType(Dest->getType()) || isVectorType(Dest->getType())) { | 1931 if (isFloatingType(Dest->getType()) || isVectorType(Dest->getType())) { |
1860 UnimplementedError(Func->getContext()->getFlags()); | 1932 _vmov(Dest, ReturnReg); |
1861 } else { | 1933 } else { |
| 1934 assert(isIntegerType(Dest->getType()) && |
| 1935 typeWidthInBytes(Dest->getType()) <= 4); |
1862 _mov(Dest, ReturnReg); | 1936 _mov(Dest, ReturnReg); |
1863 } | 1937 } |
1864 } | 1938 } |
1865 } | 1939 } |
1866 } | 1940 } |
1867 | 1941 |
1868 void TargetARM32::lowerCast(const InstCast *Inst) { | 1942 void TargetARM32::lowerCast(const InstCast *Inst) { |
1869 InstCast::OpKind CastKind = Inst->getCastKind(); | 1943 InstCast::OpKind CastKind = Inst->getCastKind(); |
1870 Variable *Dest = Inst->getDest(); | 1944 Variable *Dest = Inst->getDest(); |
1871 Operand *Src0 = legalizeUndef(Inst->getSrc(0)); | 1945 Operand *Src0 = legalizeUndef(Inst->getSrc(0)); |
(...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2284 } else { | 2358 } else { |
2285 ValLoR = legalizeToReg(Val); | 2359 ValLoR = legalizeToReg(Val); |
2286 Variable *T = makeReg(IceType_i32); | 2360 Variable *T = makeReg(IceType_i32); |
2287 _rbit(T, ValLoR); | 2361 _rbit(T, ValLoR); |
2288 ValLoR = T; | 2362 ValLoR = T; |
2289 } | 2363 } |
2290 lowerCLZ(Instr->getDest(), ValLoR, ValHiR); | 2364 lowerCLZ(Instr->getDest(), ValLoR, ValHiR); |
2291 return; | 2365 return; |
2292 } | 2366 } |
2293 case Intrinsics::Fabs: { | 2367 case Intrinsics::Fabs: { |
| 2368 // Add a fake def to keep liveness consistent in the meantime. |
| 2369 Context.insert(InstFakeDef::create(Func, Instr->getDest())); |
2294 UnimplementedError(Func->getContext()->getFlags()); | 2370 UnimplementedError(Func->getContext()->getFlags()); |
2295 return; | 2371 return; |
2296 } | 2372 } |
2297 case Intrinsics::Longjmp: { | 2373 case Intrinsics::Longjmp: { |
2298 InstCall *Call = makeHelperCall(H_call_longjmp, nullptr, 2); | 2374 InstCall *Call = makeHelperCall(H_call_longjmp, nullptr, 2); |
2299 Call->addArg(Instr->getArg(0)); | 2375 Call->addArg(Instr->getArg(0)); |
2300 Call->addArg(Instr->getArg(1)); | 2376 Call->addArg(Instr->getArg(1)); |
2301 lowerCall(Call); | 2377 lowerCall(Call); |
2302 return; | 2378 return; |
2303 } | 2379 } |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2345 } | 2421 } |
2346 return; | 2422 return; |
2347 } | 2423 } |
2348 case Intrinsics::Setjmp: { | 2424 case Intrinsics::Setjmp: { |
2349 InstCall *Call = makeHelperCall(H_call_setjmp, Instr->getDest(), 1); | 2425 InstCall *Call = makeHelperCall(H_call_setjmp, Instr->getDest(), 1); |
2350 Call->addArg(Instr->getArg(0)); | 2426 Call->addArg(Instr->getArg(0)); |
2351 lowerCall(Call); | 2427 lowerCall(Call); |
2352 return; | 2428 return; |
2353 } | 2429 } |
2354 case Intrinsics::Sqrt: { | 2430 case Intrinsics::Sqrt: { |
2355 UnimplementedError(Func->getContext()->getFlags()); | 2431 Variable *Src = legalizeToReg(Instr->getArg(0)); |
| 2432 Variable *Dest = Instr->getDest(); |
| 2433 Variable *T = makeReg(Dest->getType()); |
| 2434 _vsqrt(T, Src); |
| 2435 _vmov(Dest, T); |
2356 return; | 2436 return; |
2357 } | 2437 } |
2358 case Intrinsics::Stacksave: { | 2438 case Intrinsics::Stacksave: { |
2359 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); | 2439 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); |
2360 Variable *Dest = Instr->getDest(); | 2440 Variable *Dest = Instr->getDest(); |
2361 _mov(Dest, SP); | 2441 _mov(Dest, SP); |
2362 return; | 2442 return; |
2363 } | 2443 } |
2364 case Intrinsics::Stackrestore: { | 2444 case Intrinsics::Stackrestore: { |
2365 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); | 2445 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2433 } | 2513 } |
2434 | 2514 |
2435 void TargetARM32::lowerPhi(const InstPhi * /*Inst*/) { | 2515 void TargetARM32::lowerPhi(const InstPhi * /*Inst*/) { |
2436 Func->setError("Phi found in regular instruction list"); | 2516 Func->setError("Phi found in regular instruction list"); |
2437 } | 2517 } |
2438 | 2518 |
2439 void TargetARM32::lowerRet(const InstRet *Inst) { | 2519 void TargetARM32::lowerRet(const InstRet *Inst) { |
2440 Variable *Reg = nullptr; | 2520 Variable *Reg = nullptr; |
2441 if (Inst->hasRetValue()) { | 2521 if (Inst->hasRetValue()) { |
2442 Operand *Src0 = Inst->getRetValue(); | 2522 Operand *Src0 = Inst->getRetValue(); |
2443 if (Src0->getType() == IceType_i64) { | 2523 Type Ty = Src0->getType(); |
| 2524 if (Ty == IceType_i64) { |
2444 Src0 = legalizeUndef(Src0); | 2525 Src0 = legalizeUndef(Src0); |
2445 Variable *R0 = legalizeToReg(loOperand(Src0), RegARM32::Reg_r0); | 2526 Variable *R0 = legalizeToReg(loOperand(Src0), RegARM32::Reg_r0); |
2446 Variable *R1 = legalizeToReg(hiOperand(Src0), RegARM32::Reg_r1); | 2527 Variable *R1 = legalizeToReg(hiOperand(Src0), RegARM32::Reg_r1); |
2447 Reg = R0; | 2528 Reg = R0; |
2448 Context.insert(InstFakeUse::create(Func, R1)); | 2529 Context.insert(InstFakeUse::create(Func, R1)); |
2449 } else if (isScalarFloatingType(Src0->getType())) { | 2530 } else if (Ty == IceType_f32) { |
2450 UnimplementedError(Func->getContext()->getFlags()); | 2531 Variable *S0 = legalizeToReg(Src0, RegARM32::Reg_s0); |
| 2532 Reg = S0; |
| 2533 } else if (Ty == IceType_f64) { |
| 2534 Variable *D0 = legalizeToReg(Src0, RegARM32::Reg_d0); |
| 2535 Reg = D0; |
2451 } else if (isVectorType(Src0->getType())) { | 2536 } else if (isVectorType(Src0->getType())) { |
2452 UnimplementedError(Func->getContext()->getFlags()); | 2537 Variable *Q0 = legalizeToReg(Src0, RegARM32::Reg_q0); |
| 2538 Reg = Q0; |
2453 } else { | 2539 } else { |
2454 Operand *Src0F = legalize(Src0, Legal_Reg | Legal_Flex); | 2540 Operand *Src0F = legalize(Src0, Legal_Reg | Legal_Flex); |
2455 _mov(Reg, Src0F, CondARM32::AL, RegARM32::Reg_r0); | 2541 _mov(Reg, Src0F, CondARM32::AL, RegARM32::Reg_r0); |
2456 } | 2542 } |
2457 } | 2543 } |
2458 // Add a ret instruction even if sandboxing is enabled, because | 2544 // Add a ret instruction even if sandboxing is enabled, because |
2459 // addEpilog explicitly looks for a ret instruction as a marker for | 2545 // addEpilog explicitly looks for a ret instruction as a marker for |
2460 // where to insert the frame removal instructions. | 2546 // where to insert the frame removal instructions. |
2461 // addEpilog is responsible for restoring the "lr" register as needed | 2547 // addEpilog is responsible for restoring the "lr" register as needed |
2462 // prior to this ret instruction. | 2548 // prior to this ret instruction. |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2589 Variable *Reg = makeReg(Ty, RegNum); | 2675 Variable *Reg = makeReg(Ty, RegNum); |
2590 UnimplementedError(Func->getContext()->getFlags()); | 2676 UnimplementedError(Func->getContext()->getFlags()); |
2591 return Reg; | 2677 return Reg; |
2592 } | 2678 } |
2593 | 2679 |
2594 // Helper for legalize() to emit the right code to lower an operand to a | 2680 // Helper for legalize() to emit the right code to lower an operand to a |
2595 // register of the appropriate type. | 2681 // register of the appropriate type. |
2596 Variable *TargetARM32::copyToReg(Operand *Src, int32_t RegNum) { | 2682 Variable *TargetARM32::copyToReg(Operand *Src, int32_t RegNum) { |
2597 Type Ty = Src->getType(); | 2683 Type Ty = Src->getType(); |
2598 Variable *Reg = makeReg(Ty, RegNum); | 2684 Variable *Reg = makeReg(Ty, RegNum); |
2599 if (isVectorType(Ty)) { | 2685 if (isVectorType(Ty) || isFloatingType(Ty)) { |
2600 UnimplementedError(Func->getContext()->getFlags()); | 2686 _vmov(Reg, Src); |
2601 } else { | 2687 } else { |
2602 // Mov's Src operand can really only be the flexible second operand type | 2688 // Mov's Src operand can really only be the flexible second operand type |
2603 // or a register. Users should guarantee that. | 2689 // or a register. Users should guarantee that. |
2604 _mov(Reg, Src); | 2690 _mov(Reg, Src); |
2605 } | 2691 } |
2606 return Reg; | 2692 return Reg; |
2607 } | 2693 } |
2608 | 2694 |
2609 Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed, | 2695 Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed, |
2610 int32_t RegNum) { | 2696 int32_t RegNum) { |
(...skipping 28 matching lines...) Expand all Loading... |
2639 Mem = OperandARM32Mem::create(Func, Ty, RegBase, RegIndex, | 2725 Mem = OperandARM32Mem::create(Func, Ty, RegBase, RegIndex, |
2640 Mem->getShiftOp(), Mem->getShiftAmt(), | 2726 Mem->getShiftOp(), Mem->getShiftAmt(), |
2641 Mem->getAddrMode()); | 2727 Mem->getAddrMode()); |
2642 } else { | 2728 } else { |
2643 Mem = OperandARM32Mem::create(Func, Ty, RegBase, Mem->getOffset(), | 2729 Mem = OperandARM32Mem::create(Func, Ty, RegBase, Mem->getOffset(), |
2644 Mem->getAddrMode()); | 2730 Mem->getAddrMode()); |
2645 } | 2731 } |
2646 } | 2732 } |
2647 if (!(Allowed & Legal_Mem)) { | 2733 if (!(Allowed & Legal_Mem)) { |
2648 Variable *Reg = makeReg(Ty, RegNum); | 2734 Variable *Reg = makeReg(Ty, RegNum); |
2649 _ldr(Reg, Mem); | 2735 if (isVectorType(Ty)) { |
| 2736 UnimplementedError(Func->getContext()->getFlags()); |
| 2737 } else if (isFloatingType(Ty)) { |
| 2738 _vldr(Reg, Mem); |
| 2739 } else { |
| 2740 _ldr(Reg, Mem); |
| 2741 } |
2650 From = Reg; | 2742 From = Reg; |
2651 } else { | 2743 } else { |
2652 From = Mem; | 2744 From = Mem; |
2653 } | 2745 } |
2654 return From; | 2746 return From; |
2655 } | 2747 } |
2656 | 2748 |
2657 if (auto Flex = llvm::dyn_cast<OperandARM32Flex>(From)) { | 2749 if (auto Flex = llvm::dyn_cast<OperandARM32Flex>(From)) { |
2658 if (!(Allowed & Legal_Flex)) { | 2750 if (!(Allowed & Legal_Flex)) { |
2659 if (auto FlexReg = llvm::dyn_cast<OperandARM32FlexReg>(Flex)) { | 2751 if (auto FlexReg = llvm::dyn_cast<OperandARM32FlexReg>(Flex)) { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2709 _movt(Reg, Ctx->getConstantInt32(UpperBits)); | 2801 _movt(Reg, Ctx->getConstantInt32(UpperBits)); |
2710 } | 2802 } |
2711 return Reg; | 2803 return Reg; |
2712 } | 2804 } |
2713 } else if (auto *C = llvm::dyn_cast<ConstantRelocatable>(From)) { | 2805 } else if (auto *C = llvm::dyn_cast<ConstantRelocatable>(From)) { |
2714 Variable *Reg = makeReg(Ty, RegNum); | 2806 Variable *Reg = makeReg(Ty, RegNum); |
2715 _movw(Reg, C); | 2807 _movw(Reg, C); |
2716 _movt(Reg, C); | 2808 _movt(Reg, C); |
2717 return Reg; | 2809 return Reg; |
2718 } else { | 2810 } else { |
| 2811 assert(isScalarFloatingType(Ty)); |
2719 // Load floats/doubles from literal pool. | 2812 // Load floats/doubles from literal pool. |
2720 UnimplementedError(Func->getContext()->getFlags()); | 2813 // TODO(jvoung): Allow certain immediates to be encoded directly in |
2721 From = copyToReg(From, RegNum); | 2814 // an operand. See Table A7-18 of the ARM manual: |
| 2815 // "Floating-point modified immediate constants". |
| 2816 // Or, for 32-bit floating point numbers, just encode the raw bits |
| 2817 // into a movw/movt pair to GPR, and vmov to an SREG, instead of using |
| 2818 // a movw/movt pair to get the const-pool address then loading to SREG. |
| 2819 std::string Buffer; |
| 2820 llvm::raw_string_ostream StrBuf(Buffer); |
| 2821 llvm::cast<Constant>(From)->emitPoolLabel(StrBuf); |
| 2822 llvm::cast<Constant>(From)->setShouldBePooled(true); |
| 2823 Constant *Offset = Ctx->getConstantSym(0, StrBuf.str(), true); |
| 2824 Variable *BaseReg = makeReg(getPointerType()); |
| 2825 _movw(BaseReg, Offset); |
| 2826 _movt(BaseReg, Offset); |
| 2827 From = formMemoryOperand(BaseReg, Ty); |
| 2828 return copyToReg(From, RegNum); |
2722 } | 2829 } |
2723 return From; | |
2724 } | 2830 } |
2725 | 2831 |
2726 if (auto Var = llvm::dyn_cast<Variable>(From)) { | 2832 if (auto Var = llvm::dyn_cast<Variable>(From)) { |
2727 // Check if the variable is guaranteed a physical register. This | 2833 // Check if the variable is guaranteed a physical register. This |
2728 // can happen either when the variable is pre-colored or when it is | 2834 // can happen either when the variable is pre-colored or when it is |
2729 // assigned infinite weight. | 2835 // assigned infinite weight. |
2730 bool MustHaveRegister = (Var->hasReg() || Var->getWeight().isInf()); | 2836 bool MustHaveRegister = (Var->hasReg() || Var->getWeight().isInf()); |
2731 // We need a new physical register for the operand if: | 2837 // We need a new physical register for the operand if: |
2732 // Mem is not allowed and Var isn't guaranteed a physical | 2838 // Mem is not allowed and Var isn't guaranteed a physical |
2733 // register, or | 2839 // register, or |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2931 << ".eabi_attribute 68, 1 @ Tag_Virtualization_use\n"; | 3037 << ".eabi_attribute 68, 1 @ Tag_Virtualization_use\n"; |
2932 if (CPUFeatures.hasFeature(TargetARM32Features::HWDivArm)) { | 3038 if (CPUFeatures.hasFeature(TargetARM32Features::HWDivArm)) { |
2933 Str << ".eabi_attribute 44, 2 @ Tag_DIV_use\n"; | 3039 Str << ".eabi_attribute 44, 2 @ Tag_DIV_use\n"; |
2934 } | 3040 } |
2935 // Technically R9 is used for TLS with Sandboxing, and we reserve it. | 3041 // Technically R9 is used for TLS with Sandboxing, and we reserve it. |
2936 // However, for compatibility with current NaCl LLVM, don't claim that. | 3042 // However, for compatibility with current NaCl LLVM, don't claim that. |
2937 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; | 3043 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; |
2938 } | 3044 } |
2939 | 3045 |
2940 } // end of namespace Ice | 3046 } // end of namespace Ice |
OLD | NEW |