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

Side by Side Diff: src/IceTargetLoweringARM32.cpp

Issue 1266263003: Add the ARM32 FP register table entries, simple arith, and args. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: format more Created 5 years, 4 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/IceTargetLoweringARM32.h ('k') | tests_lit/llvm2ice_tests/fp.arith.ll » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 //===- subzero/src/IceTargetLoweringARM32.cpp - ARM32 lowering ------------===// 1 //===- subzero/src/IceTargetLoweringARM32.cpp - ARM32 lowering ------------===//
2 // 2 //
3 // The Subzero Code Generator 3 // The Subzero Code Generator
4 // 4 //
5 // This file is distributed under the University of Illinois Open Source 5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details. 6 // License. See LICENSE.TXT for details.
7 // 7 //
8 //===----------------------------------------------------------------------===// 8 //===----------------------------------------------------------------------===//
9 /// 9 ///
10 /// \file 10 /// \file
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/IceTargetLoweringARM32.h ('k') | tests_lit/llvm2ice_tests/fp.arith.ll » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698