| 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 |