OLD | NEW |
---|---|
1 // | 1 // |
2 // The Subzero Code Generator | 2 // The Subzero Code Generator |
3 // | 3 // |
4 // This file is distributed under the University of Illinois Open Source | 4 // This file is distributed under the University of Illinois Open Source |
5 // License. See LICENSE.TXT for details. | 5 // License. See LICENSE.TXT for details. |
6 // | 6 // |
7 //===----------------------------------------------------------------------===// | 7 //===----------------------------------------------------------------------===// |
8 /// | 8 /// |
9 /// \file | 9 /// \file |
10 /// \brief Implements the TargetLoweringMIPS32 class, which consists almost | 10 /// \brief Implements the TargetLoweringMIPS32 class, which consists almost |
(...skipping 602 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
613 } | 613 } |
614 | 614 |
615 Context.insert<InstAssign>(Dest, T); | 615 Context.insert<InstAssign>(Dest, T); |
616 | 616 |
617 Instr->setDeleted(); | 617 Instr->setDeleted(); |
618 return; | 618 return; |
619 } | 619 } |
620 switch (ID) { | 620 switch (ID) { |
621 default: | 621 default: |
622 return; | 622 return; |
623 case Intrinsics::AtomicLoad: { | |
624 if (DestTy != IceType_i64) | |
625 return; | |
626 if (!Intrinsics::isMemoryOrderValid( | |
627 ID, getConstantMemoryOrder(IntrinsicCall->getArg(1)))) { | |
628 Func->setError("Unexpected memory ordering for AtomicLoad"); | |
629 return; | |
630 } | |
631 Operand *Addr = IntrinsicCall->getArg(0); | |
632 Operand *TargetHelper = | |
633 Ctx->getRuntimeHelperFunc(RuntimeHelper::H_sync_val_cx_8); | |
634 static constexpr SizeT MaxArgs = 3; | |
635 auto *ZeroConst = ConstantInteger64::create(Ctx, IceType_i64, 0); | |
Jim Stichnoth
2017/02/07 17:45:43
Here you may want to use GlobalContext::getConstan
jaydeep.patil
2017/02/08 05:08:25
Done.
| |
636 auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, | |
637 NoTailCall, IsTargetHelperCall); | |
638 Call->addArg(Addr); | |
639 Call->addArg(ZeroConst); | |
640 Call->addArg(ZeroConst); | |
641 Context.insert<InstMIPS32Sync>(); | |
642 Instr->setDeleted(); | |
643 return; | |
644 } | |
645 case Intrinsics::AtomicStore: { | |
646 Operand *Val = IntrinsicCall->getArg(0); | |
647 if (Val->getType() != IceType_i64) | |
648 return; | |
649 if (!Intrinsics::isMemoryOrderValid( | |
650 ID, getConstantMemoryOrder(IntrinsicCall->getArg(2)))) { | |
651 Func->setError("Unexpected memory ordering for AtomicStore"); | |
652 return; | |
653 } | |
654 Operand *Addr = IntrinsicCall->getArg(1); | |
655 Variable *NoDest = nullptr; | |
656 Operand *TargetHelper = | |
657 Ctx->getRuntimeHelperFunc(RuntimeHelper::H_sync_lock_tset_8); | |
658 Context.insert<InstMIPS32Sync>(); | |
659 static constexpr SizeT MaxArgs = 2; | |
660 auto *Call = Context.insert<InstCall>(MaxArgs, NoDest, TargetHelper, | |
661 NoTailCall, IsTargetHelperCall); | |
662 Call->addArg(Addr); | |
663 Call->addArg(Val); | |
664 Context.insert<InstMIPS32Sync>(); | |
665 Instr->setDeleted(); | |
666 return; | |
667 } | |
668 case Intrinsics::AtomicCmpxchg: { | |
669 if (DestTy != IceType_i64) | |
670 return; | |
671 if (!Intrinsics::isMemoryOrderValid( | |
672 ID, getConstantMemoryOrder(IntrinsicCall->getArg(3)), | |
673 getConstantMemoryOrder(IntrinsicCall->getArg(4)))) { | |
674 Func->setError("Unexpected memory ordering for AtomicCmpxchg"); | |
675 return; | |
676 } | |
677 Operand *Addr = IntrinsicCall->getArg(0); | |
678 Operand *Oldval = IntrinsicCall->getArg(1); | |
679 Operand *Newval = IntrinsicCall->getArg(2); | |
680 Operand *TargetHelper = | |
681 Ctx->getRuntimeHelperFunc(RuntimeHelper::H_sync_val_cx_8); | |
682 Context.insert<InstMIPS32Sync>(); | |
683 static constexpr SizeT MaxArgs = 3; | |
684 auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, | |
685 NoTailCall, IsTargetHelperCall); | |
686 Call->addArg(Addr); | |
687 Call->addArg(Oldval); | |
688 Call->addArg(Newval); | |
689 Context.insert<InstMIPS32Sync>(); | |
690 Instr->setDeleted(); | |
691 return; | |
692 } | |
693 case Intrinsics::AtomicRMW: { | |
694 if (DestTy != IceType_i64) | |
695 return; | |
696 if (!Intrinsics::isMemoryOrderValid( | |
697 ID, getConstantMemoryOrder(IntrinsicCall->getArg(3)))) { | |
698 Func->setError("Unexpected memory ordering for AtomicRMW"); | |
699 return; | |
700 } | |
701 auto Operation = static_cast<Intrinsics::AtomicRMWOperation>( | |
702 llvm::cast<ConstantInteger32>(IntrinsicCall->getArg(0))->getValue()); | |
703 auto *Addr = IntrinsicCall->getArg(1); | |
704 auto *Newval = IntrinsicCall->getArg(2); | |
705 Operand *TargetHelper; | |
706 switch (Operation) { | |
707 case Intrinsics::AtomicAdd: | |
708 TargetHelper = | |
709 Ctx->getRuntimeHelperFunc(RuntimeHelper::H_sync_f_n_add_8); | |
710 break; | |
711 case Intrinsics::AtomicSub: | |
712 TargetHelper = | |
713 Ctx->getRuntimeHelperFunc(RuntimeHelper::H_sync_f_n_sub_8); | |
714 break; | |
715 case Intrinsics::AtomicOr: | |
716 TargetHelper = | |
717 Ctx->getRuntimeHelperFunc(RuntimeHelper::H_sync_f_n_or_8); | |
718 break; | |
719 case Intrinsics::AtomicAnd: | |
720 TargetHelper = | |
721 Ctx->getRuntimeHelperFunc(RuntimeHelper::H_sync_f_n_and_8); | |
722 break; | |
723 case Intrinsics::AtomicXor: | |
724 TargetHelper = | |
725 Ctx->getRuntimeHelperFunc(RuntimeHelper::H_sync_f_n_xor_8); | |
726 break; | |
727 case Intrinsics::AtomicExchange: | |
728 TargetHelper = | |
729 Ctx->getRuntimeHelperFunc(RuntimeHelper::H_sync_lock_tset_8); | |
730 break; | |
731 default: | |
732 llvm::report_fatal_error("Unknown AtomicRMW operation"); | |
733 return; | |
734 } | |
735 Context.insert<InstMIPS32Sync>(); | |
736 static constexpr SizeT MaxArgs = 2; | |
737 auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, | |
738 NoTailCall, IsTargetHelperCall); | |
739 Call->addArg(Addr); | |
740 Call->addArg(Newval); | |
741 Context.insert<InstMIPS32Sync>(); | |
742 Instr->setDeleted(); | |
743 return; | |
744 } | |
623 case Intrinsics::Ctpop: { | 745 case Intrinsics::Ctpop: { |
624 Operand *Src0 = IntrinsicCall->getArg(0); | 746 Operand *Src0 = IntrinsicCall->getArg(0); |
625 Operand *TargetHelper = | 747 Operand *TargetHelper = |
626 Ctx->getRuntimeHelperFunc(isInt32Asserting32Or64(Src0->getType()) | 748 Ctx->getRuntimeHelperFunc(isInt32Asserting32Or64(Src0->getType()) |
627 ? RuntimeHelper::H_call_ctpop_i32 | 749 ? RuntimeHelper::H_call_ctpop_i32 |
628 : RuntimeHelper::H_call_ctpop_i64); | 750 : RuntimeHelper::H_call_ctpop_i64); |
629 static constexpr SizeT MaxArgs = 1; | 751 static constexpr SizeT MaxArgs = 1; |
630 auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, | 752 auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, |
631 NoTailCall, IsTargetHelperCall); | 753 NoTailCall, IsTargetHelperCall); |
632 Call->addArg(Src0); | 754 Call->addArg(Src0); |
(...skipping 3815 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4448 case Intrinsics::AtomicLoad: { | 4570 case Intrinsics::AtomicLoad: { |
4449 assert(isScalarIntegerType(DestTy)); | 4571 assert(isScalarIntegerType(DestTy)); |
4450 // We require the memory address to be naturally aligned. Given that is the | 4572 // We require the memory address to be naturally aligned. Given that is the |
4451 // case, then normal loads are atomic. | 4573 // case, then normal loads are atomic. |
4452 if (!Intrinsics::isMemoryOrderValid( | 4574 if (!Intrinsics::isMemoryOrderValid( |
4453 ID, getConstantMemoryOrder(Instr->getArg(1)))) { | 4575 ID, getConstantMemoryOrder(Instr->getArg(1)))) { |
4454 Func->setError("Unexpected memory ordering for AtomicLoad"); | 4576 Func->setError("Unexpected memory ordering for AtomicLoad"); |
4455 return; | 4577 return; |
4456 } | 4578 } |
4457 if (DestTy == IceType_i64) { | 4579 if (DestTy == IceType_i64) { |
4580 llvm::report_fatal_error("AtomicLoad.i64 should have been prelowered."); | |
4581 return; | |
4582 } else if (DestTy == IceType_i32) { | |
4583 auto *T1 = makeReg(DestTy); | |
4584 auto *RegAt = getPhysicalRegister(RegMIPS32::Reg_AT); | |
4458 auto *Base = legalizeToReg(Instr->getArg(0)); | 4585 auto *Base = legalizeToReg(Instr->getArg(0)); |
4459 auto *AddrLo = OperandMIPS32Mem::create( | 4586 auto *Addr = formMemoryOperand(Base, DestTy); |
4460 Func, IceType_i32, Base, | 4587 InstMIPS32Label *Retry = InstMIPS32Label::create(Func, this); |
4461 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(0))); | 4588 InstMIPS32Label *Exit = InstMIPS32Label::create(Func, this); |
4462 auto *AddrHi = OperandMIPS32Mem::create( | 4589 constexpr CfgNode *NoTarget = nullptr; |
4463 Func, IceType_i32, Base, | |
4464 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(4))); | |
4465 auto *T_Lo = makeReg(IceType_i32); | |
4466 auto *T_Hi = makeReg(IceType_i32); | |
4467 auto *Dest64 = llvm::cast<Variable64On32>(Dest); | |
4468 lowerLoad(InstLoad::create(Func, T_Lo, AddrLo, IceType_i32)); | |
4469 lowerLoad(InstLoad::create(Func, T_Hi, AddrHi, IceType_i32)); | |
4470 _sync(); | 4590 _sync(); |
4471 _mov(Dest64->getLo(), T_Lo); | 4591 Context.insert(Retry); |
4472 _mov(Dest64->getHi(), T_Hi); | 4592 Sandboxer(this).ll(T1, Addr); |
4473 // Adding a fake-use of T to ensure the atomic load is not removed if Dest | 4593 _br(NoTarget, NoTarget, T1, getZero(), Exit, CondMIPS32::Cond::NE); |
4474 // is unused. | 4594 _addiu(RegAt, getZero(), 0); // Loaded value is zero here, writeback zero |
4475 Context.insert<InstFakeUse>(T_Lo); | 4595 Sandboxer(this).sc(RegAt, Addr); |
4476 Context.insert<InstFakeUse>(T_Hi); | 4596 _br(NoTarget, NoTarget, RegAt, getZero(), Retry, CondMIPS32::Cond::EQ); |
4597 Context.insert(Exit); | |
4598 _sync(); | |
4599 _mov(Dest, T1); | |
4600 Context.insert<InstFakeUse>(T1); | |
4477 } else { | 4601 } else { |
4478 auto *T = makeReg(DestTy); | 4602 const uint32_t Mask = (1 << (CHAR_BITS * typeWidthInBytes(DestTy))) - 1; |
4479 auto *Base = legalizeToReg(Instr->getArg(0)); | 4603 auto *Base = legalizeToReg(Instr->getArg(0)); |
4480 lowerLoad(InstLoad::create(Func, T, formMemoryOperand(Base, DestTy))); | 4604 auto *T1 = makeReg(IceType_i32); |
4605 auto *T2 = makeReg(IceType_i32); | |
4606 auto *T3 = makeReg(IceType_i32); | |
4607 auto *T4 = makeReg(IceType_i32); | |
4608 auto *T5 = makeReg(IceType_i32); | |
4609 auto *T6 = makeReg(IceType_i32); | |
4610 auto *SrcMask = makeReg(IceType_i32); | |
4611 auto *Tdest = makeReg(IceType_i32); | |
4612 auto *RegAt = getPhysicalRegister(RegMIPS32::Reg_AT); | |
4613 InstMIPS32Label *Retry = InstMIPS32Label::create(Func, this); | |
4614 InstMIPS32Label *Exit = InstMIPS32Label::create(Func, this); | |
4615 constexpr CfgNode *NoTarget = nullptr; | |
4481 _sync(); | 4616 _sync(); |
4482 _mov(Dest, T); | 4617 _addiu(T1, getZero(), -4); // Address mask 0xFFFFFFFC |
4483 // Adding a fake-use of T to ensure the atomic load is not removed if Dest | 4618 _andi(T2, Base, 3); // Last two bits of the address |
4484 // is unused. | 4619 _and(T3, Base, T1); // Align the address |
4485 Context.insert<InstFakeUse>(T); | 4620 _sll(T4, T2, 3); |
4621 _ori(T5, getZero(), Mask); | |
4622 _sllv(SrcMask, T5, T4); // Source mask | |
4623 auto *Addr = formMemoryOperand(T3, IceType_i32); | |
4624 Context.insert(Retry); | |
4625 Sandboxer(this).ll(T6, Addr); | |
4626 _and(Tdest, T6, SrcMask); | |
4627 _br(NoTarget, NoTarget, T6, getZero(), Exit, CondMIPS32::Cond::NE); | |
4628 _addiu(RegAt, getZero(), 0); // Loaded value is zero here, writeback zero | |
4629 Sandboxer(this).sc(RegAt, Addr); | |
4630 _br(NoTarget, NoTarget, RegAt, getZero(), Retry, CondMIPS32::Cond::EQ); | |
4631 Context.insert(Exit); | |
4632 auto *T7 = makeReg(IceType_i32); | |
4633 auto *T8 = makeReg(IceType_i32); | |
4634 _srlv(T7, Tdest, T4); | |
4635 _andi(T8, T7, Mask); | |
4636 _sync(); | |
4637 _mov(Dest, T8); | |
4638 Context.insert<InstFakeUse>(T6); | |
4639 Context.insert<InstFakeUse>(SrcMask); | |
4486 } | 4640 } |
4487 return; | 4641 return; |
4488 } | 4642 } |
4489 case Intrinsics::AtomicStore: { | 4643 case Intrinsics::AtomicStore: { |
4490 // We require the memory address to be naturally aligned. Given that is the | 4644 // We require the memory address to be naturally aligned. Given that is the |
4491 // case, then normal stores are atomic. | 4645 // case, then normal stores are atomic. |
4492 if (!Intrinsics::isMemoryOrderValid( | 4646 if (!Intrinsics::isMemoryOrderValid( |
4493 ID, getConstantMemoryOrder(Instr->getArg(2)))) { | 4647 ID, getConstantMemoryOrder(Instr->getArg(2)))) { |
4494 Func->setError("Unexpected memory ordering for AtomicStore"); | 4648 Func->setError("Unexpected memory ordering for AtomicStore"); |
4495 return; | 4649 return; |
4496 } | 4650 } |
4497 auto *Val = Instr->getArg(0); | 4651 auto *Val = Instr->getArg(0); |
4498 auto Ty = Val->getType(); | 4652 auto Ty = Val->getType(); |
4499 if (Ty == IceType_i64) { | 4653 if (Ty == IceType_i64) { |
4500 Variable *ValHi, *ValLo; | 4654 llvm::report_fatal_error("AtomicStore.i64 should have been prelowered."); |
4655 return; | |
4656 } else if (Ty == IceType_i32) { | |
4657 auto *Val = legalizeToReg(Instr->getArg(0)); | |
4658 auto *Base = legalizeToReg(Instr->getArg(1)); | |
4659 auto *Addr = formMemoryOperand(Base, Ty); | |
4660 InstMIPS32Label *Retry = InstMIPS32Label::create(Func, this); | |
4661 constexpr CfgNode *NoTarget = nullptr; | |
4662 auto *T1 = makeReg(IceType_i32); | |
4663 auto *RegAt = getPhysicalRegister(RegMIPS32::Reg_AT); | |
4501 _sync(); | 4664 _sync(); |
4502 if (auto *C64 = llvm::dyn_cast<ConstantInteger64>(Val)) { | 4665 Context.insert(Retry); |
4503 const uint64_t Value = C64->getValue(); | 4666 Sandboxer(this).ll(T1, Addr); |
4504 uint64_t Upper32Bits = (Value >> INT32_BITS) & 0xFFFFFFFF; | 4667 _mov(RegAt, Val); |
4505 uint64_t Lower32Bits = Value & 0xFFFFFFFF; | 4668 Sandboxer(this).sc(RegAt, Addr); |
4506 ValLo = legalizeToReg(Ctx->getConstantInt32(Lower32Bits)); | 4669 _br(NoTarget, NoTarget, RegAt, getZero(), Retry, CondMIPS32::Cond::EQ); |
4507 ValHi = legalizeToReg(Ctx->getConstantInt32(Upper32Bits)); | 4670 Context.insert<InstFakeUse>(T1); // To keep LL alive |
4508 } else { | |
4509 auto *Val64 = llvm::cast<Variable64On32>(Val); | |
4510 ValLo = legalizeToReg(loOperand(Val64)); | |
4511 ValHi = legalizeToReg(hiOperand(Val64)); | |
4512 } | |
4513 | |
4514 auto *Base = legalizeToReg(Instr->getArg(1)); | |
4515 auto *AddrLo = OperandMIPS32Mem::create( | |
4516 Func, IceType_i32, Base, | |
4517 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(0))); | |
4518 auto *AddrHi = OperandMIPS32Mem::create( | |
4519 Func, IceType_i32, Base, | |
4520 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(4))); | |
4521 lowerStore(InstStore::create(Func, ValLo, AddrLo, IceType_i32)); | |
4522 lowerStore(InstStore::create(Func, ValHi, AddrHi, IceType_i32)); | |
4523 _sync(); | 4671 _sync(); |
4524 } else { | 4672 } else { |
4525 _sync(); | |
4526 auto *Val = legalizeToReg(Instr->getArg(0)); | 4673 auto *Val = legalizeToReg(Instr->getArg(0)); |
4527 auto *Base = legalizeToReg(Instr->getArg(1)); | 4674 auto *Base = legalizeToReg(Instr->getArg(1)); |
4528 lowerStore(InstStore::create(Func, Val, formMemoryOperand(Base, DestTy))); | 4675 InstMIPS32Label *Retry = InstMIPS32Label::create(Func, this); |
4676 constexpr CfgNode *NoTarget = nullptr; | |
4677 auto *T1 = makeReg(IceType_i32); | |
4678 auto *T2 = makeReg(IceType_i32); | |
4679 auto *T3 = makeReg(IceType_i32); | |
4680 auto *T4 = makeReg(IceType_i32); | |
4681 auto *T5 = makeReg(IceType_i32); | |
4682 auto *T6 = makeReg(IceType_i32); | |
4683 auto *T7 = makeReg(IceType_i32); | |
4684 auto *RegAt = getPhysicalRegister(RegMIPS32::Reg_AT); | |
4685 auto *SrcMask = makeReg(IceType_i32); | |
4686 auto *DstMask = makeReg(IceType_i32); | |
4687 const uint32_t Mask = (1 << (CHAR_BITS * typeWidthInBytes(Ty))) - 1; | |
4688 _sync(); | |
4689 _addiu(T1, getZero(), -4); | |
4690 _and(T7, Base, T1); | |
4691 auto *Addr = formMemoryOperand(T7, Ty); | |
4692 _andi(T2, Base, 3); | |
4693 _sll(T3, T2, 3); | |
4694 _ori(T4, getZero(), Mask); | |
4695 _sllv(T5, T4, T3); | |
4696 _sllv(T6, Val, T3); | |
4697 _nor(SrcMask, getZero(), T5); | |
4698 _and(DstMask, T6, T5); | |
4699 Context.insert(Retry); | |
4700 Sandboxer(this).ll(RegAt, Addr); | |
4701 _and(RegAt, RegAt, SrcMask); | |
4702 _or(RegAt, RegAt, DstMask); | |
4703 Sandboxer(this).sc(RegAt, Addr); | |
4704 _br(NoTarget, NoTarget, RegAt, getZero(), Retry, CondMIPS32::Cond::EQ); | |
4705 Context.insert<InstFakeUse>(SrcMask); | |
4706 Context.insert<InstFakeUse>(DstMask); | |
4529 _sync(); | 4707 _sync(); |
4530 } | 4708 } |
4531 return; | 4709 return; |
4532 } | 4710 } |
4533 case Intrinsics::AtomicCmpxchg: { | 4711 case Intrinsics::AtomicCmpxchg: { |
4534 assert(isScalarIntegerType(DestTy)); | 4712 assert(isScalarIntegerType(DestTy)); |
4535 // We require the memory address to be naturally aligned. Given that is the | 4713 // We require the memory address to be naturally aligned. Given that is the |
4536 // case, then normal loads are atomic. | 4714 // case, then normal loads are atomic. |
4537 if (!Intrinsics::isMemoryOrderValid( | 4715 if (!Intrinsics::isMemoryOrderValid( |
4538 ID, getConstantMemoryOrder(Instr->getArg(3)), | 4716 ID, getConstantMemoryOrder(Instr->getArg(3)), |
4539 getConstantMemoryOrder(Instr->getArg(4)))) { | 4717 getConstantMemoryOrder(Instr->getArg(4)))) { |
4540 Func->setError("Unexpected memory ordering for AtomicCmpxchg"); | 4718 Func->setError("Unexpected memory ordering for AtomicCmpxchg"); |
4541 return; | 4719 return; |
4542 } | 4720 } |
4543 | 4721 |
4544 InstMIPS32Label *Exit = InstMIPS32Label::create(Func, this); | 4722 InstMIPS32Label *Exit = InstMIPS32Label::create(Func, this); |
4545 InstMIPS32Label *Retry = InstMIPS32Label::create(Func, this); | 4723 InstMIPS32Label *Retry = InstMIPS32Label::create(Func, this); |
4546 constexpr CfgNode *NoTarget = nullptr; | 4724 constexpr CfgNode *NoTarget = nullptr; |
4547 auto *New = Instr->getArg(2); | 4725 auto *New = Instr->getArg(2); |
4548 auto *Expected = Instr->getArg(1); | 4726 auto *Expected = Instr->getArg(1); |
4549 auto *ActualAddress = Instr->getArg(0); | 4727 auto *ActualAddress = Instr->getArg(0); |
4550 | 4728 |
4551 if (DestTy == IceType_i64) { | 4729 if (DestTy == IceType_i64) { |
4552 InstMIPS32Label *Retry1 = InstMIPS32Label::create(Func, this); | 4730 llvm::report_fatal_error( |
4553 auto *T1 = I32Reg(); | 4731 "AtomicCmpxchg.i64 should have been prelowered."); |
4554 auto *T2 = I32Reg(); | 4732 return; |
4555 auto *T3 = I32Reg(); | |
4556 auto *T4 = I32Reg(); | |
4557 auto *T5 = I32Reg(); | |
4558 auto *T6 = I32Reg(); | |
4559 Variable *ValHi, *ValLo, *ExpectedLo, *ExpectedHi; | |
4560 if (llvm::isa<ConstantUndef>(Expected)) { | |
4561 ExpectedLo = legalizeToReg(Ctx->getConstantZero(IceType_i32)); | |
4562 ExpectedHi = legalizeToReg(Ctx->getConstantZero(IceType_i32)); | |
4563 } else if (auto *Expected64 = llvm::dyn_cast<Variable64On32>(Expected)) { | |
4564 ExpectedLo = legalizeToReg(loOperand(Expected64)); | |
4565 ExpectedHi = legalizeToReg(hiOperand(Expected64)); | |
4566 } else if (auto *C64 = llvm::dyn_cast<ConstantInteger64>(Expected)) { | |
4567 const uint64_t Value = C64->getValue(); | |
4568 uint64_t Upper32Bits = (Value >> INT32_BITS) & 0xFFFFFFFF; | |
4569 uint64_t Lower32Bits = Value & 0xFFFFFFFF; | |
4570 ExpectedLo = legalizeToReg(Ctx->getConstantInt32(Lower32Bits)); | |
4571 ExpectedHi = legalizeToReg(Ctx->getConstantInt32(Upper32Bits)); | |
4572 } else { | |
4573 llvm::report_fatal_error( | |
4574 "AtomicCmpxchg: getArg(1) is nor Constant neither Variable64On32"); | |
4575 } | |
4576 if (auto *C64 = llvm::dyn_cast<ConstantInteger64>(New)) { | |
4577 const uint64_t Value = C64->getValue(); | |
4578 uint64_t Upper32Bits = (Value >> INT32_BITS) & 0xFFFFFFFF; | |
4579 uint64_t Lower32Bits = Value & 0xFFFFFFFF; | |
4580 ValLo = legalizeToReg(Ctx->getConstantInt32(Lower32Bits)); | |
4581 ValHi = legalizeToReg(Ctx->getConstantInt32(Upper32Bits)); | |
4582 } else { | |
4583 auto *Val = llvm::cast<Variable64On32>(New); | |
4584 ValLo = legalizeToReg(loOperand(Val)); | |
4585 ValHi = legalizeToReg(hiOperand(Val)); | |
4586 } | |
4587 auto *Dest64 = llvm::cast<Variable64On32>(Dest); | |
4588 auto *BaseR = legalizeToReg(ActualAddress); | |
4589 auto *AddrLo = OperandMIPS32Mem::create( | |
4590 Func, IceType_i32, BaseR, | |
4591 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(0))); | |
4592 auto *AddrHi = OperandMIPS32Mem::create( | |
4593 Func, IceType_i32, BaseR, | |
4594 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(4))); | |
4595 lowerLoad(InstLoad::create(Func, T3, AddrLo)); | |
4596 lowerLoad(InstLoad::create(Func, T4, AddrHi)); | |
4597 _sync(); | |
4598 Context.insert(Retry); | |
4599 Sandboxer(this).ll(T1, AddrLo); | |
4600 _br(NoTarget, NoTarget, T1, ExpectedLo, Exit, CondMIPS32::Cond::NE); | |
4601 _mov(T5, ValLo); | |
4602 Sandboxer(this).sc(T5, AddrLo); | |
4603 Context.insert<InstFakeUse>(ValLo); | |
4604 Context.insert<InstFakeUse>(ExpectedLo); | |
4605 _br(NoTarget, NoTarget, T5, getZero(), Retry, CondMIPS32::Cond::EQ); | |
4606 Context.insert(Retry1); | |
4607 Sandboxer(this).ll(T2, AddrHi); | |
4608 _br(NoTarget, NoTarget, T2, ExpectedHi, Exit, CondMIPS32::Cond::NE); | |
4609 _mov(T6, ValHi); | |
4610 Sandboxer(this).sc(T6, AddrHi); | |
4611 Context.insert<InstFakeUse>(ValHi); | |
4612 Context.insert<InstFakeUse>(ExpectedHi); | |
4613 _br(NoTarget, NoTarget, T6, getZero(), Retry1, CondMIPS32::Cond::EQ); | |
4614 Context.insert<InstFakeUse>(getZero()); | |
4615 Context.insert(Exit); | |
4616 _mov(Dest64->getLo(), T3); | |
4617 _mov(Dest64->getHi(), T4); | |
4618 _sync(); | |
4619 } else if (DestTy == IceType_i8 || DestTy == IceType_i16) { | 4733 } else if (DestTy == IceType_i8 || DestTy == IceType_i16) { |
4620 auto *NewR = legalizeToReg(New); | 4734 auto *NewR = legalizeToReg(New); |
4621 auto *ExpectedR = legalizeToReg(Expected); | 4735 auto *ExpectedR = legalizeToReg(Expected); |
4622 auto *ActualAddressR = legalizeToReg(ActualAddress); | 4736 auto *ActualAddressR = legalizeToReg(ActualAddress); |
4623 const uint32_t ShiftAmount = | 4737 const uint32_t ShiftAmount = |
4624 (INT32_BITS - CHAR_BITS * typeWidthInBytes(DestTy)); | 4738 (INT32_BITS - CHAR_BITS * typeWidthInBytes(DestTy)); |
4625 const uint32_t Mask = (1 << (CHAR_BITS * typeWidthInBytes(DestTy))) - 1; | 4739 const uint32_t Mask = (1 << (CHAR_BITS * typeWidthInBytes(DestTy))) - 1; |
4626 auto *RegAt = getPhysicalRegister(RegMIPS32::Reg_AT); | 4740 auto *RegAt = getPhysicalRegister(RegMIPS32::Reg_AT); |
4627 auto *T1 = I32Reg(); | 4741 auto *T1 = I32Reg(); |
4628 auto *T2 = I32Reg(); | 4742 auto *T2 = I32Reg(); |
4629 auto *T3 = I32Reg(); | 4743 auto *T3 = I32Reg(); |
4630 auto *T4 = I32Reg(); | 4744 auto *T4 = I32Reg(); |
4631 auto *T5 = I32Reg(); | 4745 auto *T5 = I32Reg(); |
4632 auto *T6 = I32Reg(); | 4746 auto *T6 = I32Reg(); |
4633 auto *T7 = I32Reg(); | 4747 auto *T7 = I32Reg(); |
4634 auto *T8 = I32Reg(); | 4748 auto *T8 = I32Reg(); |
4635 auto *T9 = I32Reg(); | 4749 auto *T9 = I32Reg(); |
4636 _addiu(RegAt, getZero(), -4); | 4750 _addiu(RegAt, getZero(), -4); |
4637 _and(T1, ActualAddressR, RegAt); | 4751 _and(T1, ActualAddressR, RegAt); |
4752 auto *Addr = formMemoryOperand(T1, DestTy); | |
4638 _andi(RegAt, ActualAddressR, 3); | 4753 _andi(RegAt, ActualAddressR, 3); |
4639 _sll(T2, RegAt, 3); | 4754 _sll(T2, RegAt, 3); |
4640 _ori(RegAt, getZero(), Mask); | 4755 _ori(RegAt, getZero(), Mask); |
4641 _sllv(T3, RegAt, T2); | 4756 _sllv(T3, RegAt, T2); |
4642 _nor(T4, getZero(), T3); | 4757 _nor(T4, getZero(), T3); |
4643 _andi(RegAt, ExpectedR, Mask); | 4758 _andi(RegAt, ExpectedR, Mask); |
4644 _sllv(T5, RegAt, T2); | 4759 _sllv(T5, RegAt, T2); |
4645 _andi(RegAt, NewR, Mask); | 4760 _andi(RegAt, NewR, Mask); |
4646 _sllv(T6, RegAt, T2); | 4761 _sllv(T6, RegAt, T2); |
4647 _sync(); | 4762 _sync(); |
4648 Context.insert(Retry); | 4763 Context.insert(Retry); |
4649 Sandboxer(this).ll(T7, formMemoryOperand(T1, DestTy)); | 4764 Sandboxer(this).ll(T7, Addr); |
4650 _and(T8, T7, T3); | 4765 _and(T8, T7, T3); |
4651 _br(NoTarget, NoTarget, T8, T5, Exit, CondMIPS32::Cond::NE); | 4766 _br(NoTarget, NoTarget, T8, T5, Exit, CondMIPS32::Cond::NE); |
4652 _and(RegAt, T7, T4); | 4767 _and(RegAt, T7, T4); |
4653 _or(T9, RegAt, T6); | 4768 _or(T9, RegAt, T6); |
4654 Sandboxer(this).sc(T9, formMemoryOperand(T1, DestTy)); | 4769 Sandboxer(this).sc(T9, Addr); |
4655 Context.insert<InstFakeUse>(T6); | |
4656 _br(NoTarget, NoTarget, getZero(), T9, Retry, CondMIPS32::Cond::EQ); | 4770 _br(NoTarget, NoTarget, getZero(), T9, Retry, CondMIPS32::Cond::EQ); |
4657 Context.insert<InstFakeUse>(getZero()); | 4771 Context.insert<InstFakeUse>(getZero()); |
4658 Context.insert(Exit); | 4772 Context.insert(Exit); |
4659 _srlv(RegAt, T8, T2); | 4773 _srlv(RegAt, T8, T2); |
4660 _sll(RegAt, RegAt, ShiftAmount); | 4774 _sll(RegAt, RegAt, ShiftAmount); |
4661 _sra(RegAt, RegAt, ShiftAmount); | 4775 _sra(RegAt, RegAt, ShiftAmount); |
4662 _mov(Dest, RegAt); | 4776 _mov(Dest, RegAt); |
4663 _sync(); | 4777 _sync(); |
4778 Context.insert<InstFakeUse>(T3); | |
4779 Context.insert<InstFakeUse>(T4); | |
4780 Context.insert<InstFakeUse>(T5); | |
4781 Context.insert<InstFakeUse>(T6); | |
4782 Context.insert<InstFakeUse>(T8); | |
4664 Context.insert<InstFakeUse>(ExpectedR); | 4783 Context.insert<InstFakeUse>(ExpectedR); |
4665 Context.insert<InstFakeUse>(NewR); | 4784 Context.insert<InstFakeUse>(NewR); |
4666 } else { | 4785 } else { |
4667 auto *T1 = I32Reg(); | 4786 auto *T1 = I32Reg(); |
4668 auto *T2 = I32Reg(); | 4787 auto *T2 = I32Reg(); |
4669 auto *NewR = legalizeToReg(New); | 4788 auto *NewR = legalizeToReg(New); |
4670 auto *ExpectedR = legalizeToReg(Expected); | 4789 auto *ExpectedR = legalizeToReg(Expected); |
4671 auto *ActualAddressR = legalizeToReg(ActualAddress); | 4790 auto *ActualAddressR = legalizeToReg(ActualAddress); |
4672 _sync(); | 4791 _sync(); |
4673 Context.insert(Retry); | 4792 Context.insert(Retry); |
(...skipping 22 matching lines...) Expand all Loading... | |
4696 } | 4815 } |
4697 | 4816 |
4698 constexpr CfgNode *NoTarget = nullptr; | 4817 constexpr CfgNode *NoTarget = nullptr; |
4699 InstMIPS32Label *Retry = InstMIPS32Label::create(Func, this); | 4818 InstMIPS32Label *Retry = InstMIPS32Label::create(Func, this); |
4700 auto Operation = static_cast<Intrinsics::AtomicRMWOperation>( | 4819 auto Operation = static_cast<Intrinsics::AtomicRMWOperation>( |
4701 llvm::cast<ConstantInteger32>(Instr->getArg(0))->getValue()); | 4820 llvm::cast<ConstantInteger32>(Instr->getArg(0))->getValue()); |
4702 auto *New = Instr->getArg(2); | 4821 auto *New = Instr->getArg(2); |
4703 auto *ActualAddress = Instr->getArg(1); | 4822 auto *ActualAddress = Instr->getArg(1); |
4704 | 4823 |
4705 if (DestTy == IceType_i64) { | 4824 if (DestTy == IceType_i64) { |
4706 InstMIPS32Label *Retry1 = InstMIPS32Label::create(Func, this); | 4825 llvm::report_fatal_error("AtomicRMW.i64 should have been prelowered."); |
4707 _sync(); | 4826 return; |
4708 Variable *ValHi, *ValLo; | |
4709 if (auto *C64 = llvm::dyn_cast<ConstantInteger64>(New)) { | |
4710 const uint64_t Value = C64->getValue(); | |
4711 uint64_t Upper32Bits = (Value >> INT32_BITS) & 0xFFFFFFFF; | |
4712 uint64_t Lower32Bits = Value & 0xFFFFFFFF; | |
4713 ValLo = legalizeToReg(Ctx->getConstantInt32(Lower32Bits)); | |
4714 ValHi = legalizeToReg(Ctx->getConstantInt32(Upper32Bits)); | |
4715 } else { | |
4716 auto *Val = llvm::cast<Variable64On32>(New); | |
4717 ValLo = legalizeToReg(loOperand(Val)); | |
4718 ValHi = legalizeToReg(hiOperand(Val)); | |
4719 } | |
4720 auto *Dest64 = llvm::cast<Variable64On32>(Dest); | |
4721 auto *BaseR = legalizeToReg(ActualAddress); | |
4722 auto *AddrLo = OperandMIPS32Mem::create( | |
4723 Func, IceType_i32, BaseR, | |
4724 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(0))); | |
4725 auto *AddrHi = OperandMIPS32Mem::create( | |
4726 Func, IceType_i32, BaseR, | |
4727 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(4))); | |
4728 auto *RegAt = getPhysicalRegister(RegMIPS32::Reg_AT); | |
4729 auto *T1 = I32Reg(); | |
4730 auto *T2 = I32Reg(); | |
4731 auto *T3 = I32Reg(); | |
4732 Context.insert(Retry); | |
4733 Sandboxer(this).ll(T1, AddrLo); | |
4734 if (Operation == Intrinsics::AtomicExchange) { | |
4735 _mov(RegAt, ValLo); | |
4736 Context.insert<InstFakeUse>(T1); | |
4737 } else if (Operation == Intrinsics::AtomicAdd) { | |
4738 createArithInst(Operation, RegAt, T1, ValLo); | |
4739 _sltu(T2, RegAt, T1); | |
4740 } else if (Operation == Intrinsics::AtomicSub) { | |
4741 createArithInst(Operation, RegAt, T1, ValLo); | |
4742 _sltu(T2, T1, ValLo); | |
4743 } else { | |
4744 createArithInst(Operation, RegAt, T1, ValLo); | |
4745 } | |
4746 Sandboxer(this).sc(RegAt, AddrLo); | |
4747 _br(NoTarget, NoTarget, RegAt, getZero(), Retry, CondMIPS32::Cond::EQ); | |
4748 Context.insert<InstFakeUse>(getZero()); | |
4749 _mov(Dest64->getLo(), T1); | |
4750 Context.insert(Retry1); | |
4751 Sandboxer(this).ll(T3, AddrHi); | |
4752 if (Operation == Intrinsics::AtomicAdd || | |
4753 Operation == Intrinsics::AtomicSub) { | |
4754 _addu(RegAt, T2, ValHi); | |
4755 createArithInst(Operation, RegAt, T3, RegAt); | |
4756 } else if (Operation == Intrinsics::AtomicExchange) { | |
4757 _mov(RegAt, ValHi); | |
4758 Context.insert<InstFakeUse>(T3); | |
4759 } else { | |
4760 createArithInst(Operation, RegAt, T3, ValHi); | |
4761 } | |
4762 Sandboxer(this).sc(RegAt, AddrHi); | |
4763 _br(NoTarget, NoTarget, RegAt, getZero(), Retry1, CondMIPS32::Cond::EQ); | |
4764 Context.insert<InstFakeUse>(getZero()); | |
4765 _mov(Dest64->getHi(), T3); | |
4766 Context.insert<InstFakeUse>(ValLo); | |
4767 Context.insert<InstFakeUse>(ValHi); | |
4768 _sync(); | |
4769 } else if (DestTy == IceType_i8 || DestTy == IceType_i16) { | 4827 } else if (DestTy == IceType_i8 || DestTy == IceType_i16) { |
4770 const uint32_t ShiftAmount = | 4828 const uint32_t ShiftAmount = |
4771 INT32_BITS - (CHAR_BITS * typeWidthInBytes(DestTy)); | 4829 INT32_BITS - (CHAR_BITS * typeWidthInBytes(DestTy)); |
4772 const uint32_t Mask = (1 << (CHAR_BITS * typeWidthInBytes(DestTy))) - 1; | 4830 const uint32_t Mask = (1 << (CHAR_BITS * typeWidthInBytes(DestTy))) - 1; |
4773 auto *NewR = legalizeToReg(New); | 4831 auto *NewR = legalizeToReg(New); |
4774 auto *ActualAddressR = legalizeToReg(ActualAddress); | 4832 auto *ActualAddressR = legalizeToReg(ActualAddress); |
4775 auto *RegAt = getPhysicalRegister(RegMIPS32::Reg_AT); | 4833 auto *RegAt = getPhysicalRegister(RegMIPS32::Reg_AT); |
4776 auto *T1 = I32Reg(); | 4834 auto *T1 = I32Reg(); |
4777 auto *T2 = I32Reg(); | 4835 auto *T2 = I32Reg(); |
4778 auto *T3 = I32Reg(); | 4836 auto *T3 = I32Reg(); |
(...skipping 838 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5617 | 5675 |
5618 void TargetMIPS32::lowerBreakpoint(const InstBreakpoint *Instr) { | 5676 void TargetMIPS32::lowerBreakpoint(const InstBreakpoint *Instr) { |
5619 UnimplementedLoweringError(this, Instr); | 5677 UnimplementedLoweringError(this, Instr); |
5620 } | 5678 } |
5621 | 5679 |
5622 void TargetMIPS32::lowerUnreachable(const InstUnreachable *) { | 5680 void TargetMIPS32::lowerUnreachable(const InstUnreachable *) { |
5623 const uint32_t TrapCodeZero = 0; | 5681 const uint32_t TrapCodeZero = 0; |
5624 _teq(getZero(), getZero(), TrapCodeZero); | 5682 _teq(getZero(), getZero(), TrapCodeZero); |
5625 } | 5683 } |
5626 | 5684 |
5685 void TargetMIPS32::lowerOther(const Inst *Instr) { | |
5686 if (llvm::isa<InstMIPS32Sync>(Instr)) { | |
5687 _sync(); | |
5688 } else { | |
5689 TargetLowering::lowerOther(Instr); | |
5690 } | |
5691 } | |
5692 | |
5627 // Turn an i64 Phi instruction into a pair of i32 Phi instructions, to preserve | 5693 // Turn an i64 Phi instruction into a pair of i32 Phi instructions, to preserve |
5628 // integrity of liveness analysis. Undef values are also turned into zeroes, | 5694 // integrity of liveness analysis. Undef values are also turned into zeroes, |
5629 // since loOperand() and hiOperand() don't expect Undef input. | 5695 // since loOperand() and hiOperand() don't expect Undef input. |
5630 void TargetMIPS32::prelowerPhis() { | 5696 void TargetMIPS32::prelowerPhis() { |
5631 PhiLowering::prelowerPhis32Bit<TargetMIPS32>(this, Context.getNode(), Func); | 5697 PhiLowering::prelowerPhis32Bit<TargetMIPS32>(this, Context.getNode(), Func); |
5632 } | 5698 } |
5633 | 5699 |
5634 void TargetMIPS32::postLower() { | 5700 void TargetMIPS32::postLower() { |
5635 if (Func->getOptLevel() == Opt_m1) | 5701 if (Func->getOptLevel() == Opt_m1) |
5636 return; | 5702 return; |
(...skipping 557 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6194 auto *T6 = Target->makeReg(IceType_i32, RegMIPS32::Reg_T6); | 6260 auto *T6 = Target->makeReg(IceType_i32, RegMIPS32::Reg_T6); |
6195 Target->Context.insert<InstFakeDef>(T6); | 6261 Target->Context.insert<InstFakeDef>(T6); |
6196 Target->_and(CallTargetR, CallTargetR, T6); | 6262 Target->_and(CallTargetR, CallTargetR, T6); |
6197 } | 6263 } |
6198 } | 6264 } |
6199 return Target->Context.insert<InstMIPS32Call>(ReturnReg, CallTarget); | 6265 return Target->Context.insert<InstMIPS32Call>(ReturnReg, CallTarget); |
6200 } | 6266 } |
6201 | 6267 |
6202 } // end of namespace MIPS32 | 6268 } // end of namespace MIPS32 |
6203 } // end of namespace Ice | 6269 } // end of namespace Ice |
OLD | NEW |