llvm.org GIT mirror llvm / 30f9ff4
[FastISel] Add target-independent patchpoint intrinsic support. WIP. This implements the target-independent lowering for the patchpoint intrinsic. Targets have to implement the FastLowerCall hook to support this intrinsic. Related to <rdar://problem/17427052> git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@212849 91177308-0d34-0410-b5e6-96231b3b80d8 Juergen Ributzka 5 years ago
2 changed file(s) with 173 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
540540 bool SelectGetElementPtr(const User *I);
541541
542542 bool SelectStackmap(const CallInst *I);
543 bool SelectPatchpoint(const CallInst *I);
543544 bool LowerCall(const CallInst *I);
544545 bool SelectCall(const User *Call);
545546 bool SelectIntrinsicCall(const IntrinsicInst *II);
573574
574575 bool addStackMapLiveVars(SmallVectorImpl &Ops,
575576 const CallInst *CI, unsigned StartIdx);
577 bool lowerCallOperands(const CallInst *CI, unsigned ArgIdx, unsigned NumArgs,
578 const Value *Callee, bool ForceRetVoidTy,
579 CallLoweringInfo &CLI);
576580 };
577581
578582 }
677677 return true;
678678 }
679679
680 /// \brief Lower an argument list according to the target calling convention.
681 ///
682 /// This is a helper for lowering intrinsics that follow a target calling
683 /// convention or require stack pointer adjustment. Only a subset of the
684 /// intrinsic's operands need to participate in the calling convention.
685 bool FastISel::lowerCallOperands(const CallInst *CI, unsigned ArgIdx,
686 unsigned NumArgs, const Value *Callee,
687 bool ForceRetVoidTy, CallLoweringInfo &CLI) {
688 ArgListTy Args;
689 Args.reserve(NumArgs);
690
691 // Populate the argument list.
692 // Attributes for args start at offset 1, after the return attribute.
693 ImmutableCallSite CS(CI);
694 for (unsigned ArgI = ArgIdx, ArgE = ArgIdx + NumArgs, AttrI = ArgIdx + 1;
695 ArgI != ArgE; ++ArgI) {
696 Value *V = CI->getOperand(ArgI);
697
698 assert(!V->getType()->isEmptyTy() && "Empty type passed to intrinsic.");
699
700 ArgListEntry Entry;
701 Entry.Val = V;
702 Entry.Ty = V->getType();
703 Entry.setAttributes(&CS, AttrI);
704 Args.push_back(Entry);
705 }
706
707 Type *RetTy = ForceRetVoidTy ? Type::getVoidTy(CI->getType()->getContext())
708 : CI->getType();
709 CLI.setCallee(CI->getCallingConv(), RetTy, Callee, std::move(Args), NumArgs);
710
711 return LowerCallTo(CLI);
712 }
713
714 bool FastISel::SelectPatchpoint(const CallInst *I) {
715 // void|i64 @llvm.experimental.patchpoint.void|i64(i64 ,
716 // i32 ,
717 // i8* ,
718 // i32 ,
719 // [Args...],
720 // [live variables...])
721 CallingConv::ID CC = I->getCallingConv();
722 bool IsAnyRegCC = CC == CallingConv::AnyReg;
723 bool HasDef = !I->getType()->isVoidTy();
724 Value *Callee = I->getOperand(PatchPointOpers::TargetPos);
725
726 // Get the real number of arguments participating in the call
727 assert(isa(I->getOperand(PatchPointOpers::NArgPos)) &&
728 "Expected a constant integer.");
729 const auto *NumArgsVal =
730 cast(I->getOperand(PatchPointOpers::NArgPos));
731 unsigned NumArgs = NumArgsVal->getZExtValue();
732
733 // Skip the four meta args: , , ,
734 // This includes all meta-operands up to but not including CC.
735 unsigned NumMetaOpers = PatchPointOpers::CCPos;
736 assert(I->getNumArgOperands() >= NumMetaOpers + NumArgs &&
737 "Not enough arguments provided to the patchpoint intrinsic");
738
739 // For AnyRegCC the arguments are lowered later on manually.
740 unsigned NumCallArgs = IsAnyRegCC ? 0 : NumArgs;
741 CallLoweringInfo CLI;
742 if (!lowerCallOperands(I, NumMetaOpers, NumCallArgs, Callee, IsAnyRegCC, CLI))
743 return false;
744
745 assert(CLI.Call && "No call instruction specified.");
746
747 SmallVector Ops;
748
749 // Add an explicit result reg if we use the anyreg calling convention.
750 unsigned ResultReg = 0;
751 if (IsAnyRegCC && HasDef) {
752 ResultReg = createResultReg(TLI.getRegClassFor(MVT::i64));
753 Ops.push_back(MachineOperand::CreateReg(ResultReg, /*IsDef=*/true));
754 }
755
756 // Add the and constants.
757 assert(isa(I->getOperand(PatchPointOpers::IDPos)) &&
758 "Expected a constant integer.");
759 const auto *ID = cast(I->getOperand(PatchPointOpers::IDPos));
760 Ops.push_back(MachineOperand::CreateImm(ID->getZExtValue()));
761
762 assert(isa(I->getOperand(PatchPointOpers::NBytesPos)) &&
763 "Expected a constant integer.");
764 const auto *NumBytes =
765 cast(I->getOperand(PatchPointOpers::NBytesPos));
766 Ops.push_back(MachineOperand::CreateImm(NumBytes->getZExtValue()));
767
768 // Assume that the callee is a constant address or null pointer.
769 // FIXME: handle function symbols in the future.
770 unsigned CalleeAddr;
771 if (const auto *C = dyn_cast(Callee))
772 CalleeAddr = cast(C->getOperand(0))->getZExtValue();
773 else if (const auto *C = dyn_cast(Callee)) {
774 if (C->getOpcode() == Instruction::IntToPtr)
775 CalleeAddr = cast(C->getOperand(0))->getZExtValue();
776 else
777 llvm_unreachable("Unsupported ConstantExpr.");
778 } else if (isa(Callee))
779 CalleeAddr = 0;
780 else
781 llvm_unreachable("Unsupported callee address.");
782
783 Ops.push_back(MachineOperand::CreateImm(CalleeAddr));
784
785 // Adjust to account for any arguments that have been passed on
786 // the stack instead.
787 unsigned NumCallRegArgs = IsAnyRegCC ? NumArgs : CLI.OutRegs.size();
788 Ops.push_back(MachineOperand::CreateImm(NumCallRegArgs));
789
790 // Add the calling convention
791 Ops.push_back(MachineOperand::CreateImm((unsigned)CC));
792
793 // Add the arguments we omitted previously. The register allocator should
794 // place these in any free register.
795 if (IsAnyRegCC) {
796 for (unsigned i = NumMetaOpers, e = NumMetaOpers + NumArgs; i != e; ++i) {
797 unsigned Reg = getRegForValue(I->getArgOperand(i));
798 if (!Reg)
799 return false;
800 Ops.push_back(MachineOperand::CreateReg(Reg, /*IsDef=*/false));
801 }
802 }
803
804 // Push the arguments from the call instruction.
805 for (auto Reg : CLI.OutRegs)
806 Ops.push_back(MachineOperand::CreateReg(Reg, /*IsDef=*/false));
807
808 // Push live variables for the stack map.
809 if (!addStackMapLiveVars(Ops, I, NumMetaOpers + NumArgs))
810 return false;
811
812 // Push the register mask info.
813 Ops.push_back(MachineOperand::CreateRegMask(TRI.getCallPreservedMask(CC)));
814
815 // Add scratch registers as implicit def and early clobber.
816 const MCPhysReg *ScratchRegs = TLI.getScratchRegisters(CC);
817 for (unsigned i = 0; ScratchRegs[i]; ++i)
818 Ops.push_back(MachineOperand::CreateReg(
819 ScratchRegs[i], /*IsDef=*/true, /*IsImp=*/true, /*IsKill=*/false,
820 /*IsDead=*/false, /*IsUndef=*/false, /*IsEarlyClobber=*/true));
821
822 // Add implicit defs (return values).
823 for (auto Reg : CLI.InRegs)
824 Ops.push_back(MachineOperand::CreateReg(Reg, /*IsDef=*/true,
825 /*IsImpl=*/true));
826
827 MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
828 TII.get(TargetOpcode::PATCHPOINT));
829
830 for (auto &MO : Ops)
831 MIB.addOperand(MO);
832
833 MIB->setPhysRegsDeadExcept(CLI.InRegs, TRI);
834
835 // Delete the original call instruction.
836 CLI.Call->eraseFromParent();
837
838 // Inform the Frame Information that we have a patchpoint in this function.
839 FuncInfo.MF->getFrameInfo()->setHasPatchPoint();
840
841 if (ResultReg)
842 UpdateValueMap(I, ResultReg);
843 return true;
844 }
845
680846 /// Returns an AttributeSet representing the attributes applied to the return
681847 /// value of the given call.
682848 static AttributeSet getReturnAttrs(FastISel::CallLoweringInfo &CLI) {
10321198 }
10331199 case Intrinsic::experimental_stackmap:
10341200 return SelectStackmap(II);
1201 case Intrinsic::experimental_patchpoint_void:
1202 case Intrinsic::experimental_patchpoint_i64:
1203 return SelectPatchpoint(II);
10351204 }
10361205
10371206 return FastLowerIntrinsicCall(II);