|
25 | 25 | #include "llvm/CodeGen/MachineConstantPool.h"
|
26 | 26 | #include "llvm/CodeGen/MachineFrameInfo.h"
|
27 | 27 | #include "llvm/CodeGen/MachineRegisterInfo.h"
|
| 28 | +#include "llvm/CodeGen/RuntimeLibcalls.h" |
28 | 29 | #include "llvm/CodeGen/TargetFrameLowering.h"
|
29 | 30 | #include "llvm/CodeGen/TargetInstrInfo.h"
|
30 | 31 | #include "llvm/CodeGen/TargetLowering.h"
|
@@ -796,6 +797,132 @@ llvm::createMemLibcall(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
|
796 | 797 | return LegalizerHelper::Legalized;
|
797 | 798 | }
|
798 | 799 |
|
| 800 | +static RTLIB::Libcall getOutlineAtomicLibcall(MachineInstr &MI) { |
| 801 | + unsigned Opc = MI.getOpcode(); |
| 802 | + auto &AtomicMI = cast<GMemOperation>(MI); |
| 803 | + auto &MMO = AtomicMI.getMMO(); |
| 804 | + auto Ordering = MMO.getMergedOrdering(); |
| 805 | + LLT MemType = MMO.getMemoryType(); |
| 806 | + uint64_t MemSize = MemType.getSizeInBytes(); |
| 807 | + if (MemType.isVector()) |
| 808 | + return RTLIB::UNKNOWN_LIBCALL; |
| 809 | + |
| 810 | +#define LCALLS(A, B) \ |
| 811 | + { A##B##_RELAX, A##B##_ACQ, A##B##_REL, A##B##_ACQ_REL } |
| 812 | +#define LCALL5(A) \ |
| 813 | + LCALLS(A, 1), LCALLS(A, 2), LCALLS(A, 4), LCALLS(A, 8), LCALLS(A, 16) |
| 814 | + switch (Opc) { |
| 815 | + case TargetOpcode::G_ATOMIC_CMPXCHG: |
| 816 | + case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: { |
| 817 | + const RTLIB::Libcall LC[5][4] = {LCALL5(RTLIB::OUTLINE_ATOMIC_CAS)}; |
| 818 | + return getOutlineAtomicHelper(LC, Ordering, MemSize); |
| 819 | + } |
| 820 | + case TargetOpcode::G_ATOMICRMW_XCHG: { |
| 821 | + const RTLIB::Libcall LC[5][4] = {LCALL5(RTLIB::OUTLINE_ATOMIC_SWP)}; |
| 822 | + return getOutlineAtomicHelper(LC, Ordering, MemSize); |
| 823 | + } |
| 824 | + case TargetOpcode::G_ATOMICRMW_ADD: |
| 825 | + case TargetOpcode::G_ATOMICRMW_SUB: { |
| 826 | + const RTLIB::Libcall LC[5][4] = {LCALL5(RTLIB::OUTLINE_ATOMIC_LDADD)}; |
| 827 | + return getOutlineAtomicHelper(LC, Ordering, MemSize); |
| 828 | + } |
| 829 | + case TargetOpcode::G_ATOMICRMW_AND: { |
| 830 | + const RTLIB::Libcall LC[5][4] = {LCALL5(RTLIB::OUTLINE_ATOMIC_LDCLR)}; |
| 831 | + return getOutlineAtomicHelper(LC, Ordering, MemSize); |
| 832 | + } |
| 833 | + case TargetOpcode::G_ATOMICRMW_OR: { |
| 834 | + const RTLIB::Libcall LC[5][4] = {LCALL5(RTLIB::OUTLINE_ATOMIC_LDSET)}; |
| 835 | + return getOutlineAtomicHelper(LC, Ordering, MemSize); |
| 836 | + } |
| 837 | + case TargetOpcode::G_ATOMICRMW_XOR: { |
| 838 | + const RTLIB::Libcall LC[5][4] = {LCALL5(RTLIB::OUTLINE_ATOMIC_LDEOR)}; |
| 839 | + return getOutlineAtomicHelper(LC, Ordering, MemSize); |
| 840 | + } |
| 841 | + default: |
| 842 | + return RTLIB::UNKNOWN_LIBCALL; |
| 843 | + } |
| 844 | +#undef LCALLS |
| 845 | +#undef LCALL5 |
| 846 | +} |
| 847 | + |
| 848 | +static LegalizerHelper::LegalizeResult |
| 849 | +createAtomicLibcall(MachineIRBuilder &MIRBuilder, MachineInstr &MI) { |
| 850 | + auto &Ctx = MIRBuilder.getMF().getFunction().getContext(); |
| 851 | + |
| 852 | + Type *RetTy; |
| 853 | + SmallVector<Register> RetRegs; |
| 854 | + SmallVector<CallLowering::ArgInfo, 3> Args; |
| 855 | + unsigned Opc = MI.getOpcode(); |
| 856 | + switch (Opc) { |
| 857 | + case TargetOpcode::G_ATOMIC_CMPXCHG: |
| 858 | + case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: { |
| 859 | + Register Success; |
| 860 | + LLT SuccessLLT; |
| 861 | + auto [Ret, RetLLT, Mem, MemLLT, Cmp, CmpLLT, New, NewLLT] = |
| 862 | + MI.getFirst4RegLLTs(); |
| 863 | + RetRegs.push_back(Ret); |
| 864 | + RetTy = IntegerType::get(Ctx, RetLLT.getSizeInBits()); |
| 865 | + if (Opc == TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS) { |
| 866 | + std::tie(Ret, RetLLT, Success, SuccessLLT, Mem, MemLLT, Cmp, CmpLLT, New, |
| 867 | + NewLLT) = MI.getFirst5RegLLTs(); |
| 868 | + RetRegs.push_back(Success); |
| 869 | + RetTy = StructType::get( |
| 870 | + Ctx, {RetTy, IntegerType::get(Ctx, SuccessLLT.getSizeInBits())}); |
| 871 | + } |
| 872 | + Args.push_back({Cmp, IntegerType::get(Ctx, CmpLLT.getSizeInBits()), 0}); |
| 873 | + Args.push_back({New, IntegerType::get(Ctx, NewLLT.getSizeInBits()), 0}); |
| 874 | + Args.push_back({Mem, PointerType::get(Ctx, MemLLT.getAddressSpace()), 0}); |
| 875 | + break; |
| 876 | + } |
| 877 | + case TargetOpcode::G_ATOMICRMW_XCHG: |
| 878 | + case TargetOpcode::G_ATOMICRMW_ADD: |
| 879 | + case TargetOpcode::G_ATOMICRMW_SUB: |
| 880 | + case TargetOpcode::G_ATOMICRMW_AND: |
| 881 | + case TargetOpcode::G_ATOMICRMW_OR: |
| 882 | + case TargetOpcode::G_ATOMICRMW_XOR: { |
| 883 | + auto [Ret, RetLLT, Mem, MemLLT, Val, ValLLT] = MI.getFirst3RegLLTs(); |
| 884 | + RetRegs.push_back(Ret); |
| 885 | + RetTy = IntegerType::get(Ctx, RetLLT.getSizeInBits()); |
| 886 | + if (Opc == TargetOpcode::G_ATOMICRMW_AND) |
| 887 | + Val = |
| 888 | + MIRBuilder.buildXor(ValLLT, MIRBuilder.buildConstant(ValLLT, -1), Val) |
| 889 | + .getReg(0); |
| 890 | + else if (Opc == TargetOpcode::G_ATOMICRMW_SUB) |
| 891 | + Val = |
| 892 | + MIRBuilder.buildSub(ValLLT, MIRBuilder.buildConstant(ValLLT, 0), Val) |
| 893 | + .getReg(0); |
| 894 | + Args.push_back({Val, IntegerType::get(Ctx, ValLLT.getSizeInBits()), 0}); |
| 895 | + Args.push_back({Mem, PointerType::get(Ctx, MemLLT.getAddressSpace()), 0}); |
| 896 | + break; |
| 897 | + } |
| 898 | + default: |
| 899 | + llvm_unreachable("unsupported opcode"); |
| 900 | + } |
| 901 | + |
| 902 | + auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering(); |
| 903 | + auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering(); |
| 904 | + RTLIB::Libcall RTLibcall = getOutlineAtomicLibcall(MI); |
| 905 | + const char *Name = TLI.getLibcallName(RTLibcall); |
| 906 | + |
| 907 | + // Unsupported libcall on the target. |
| 908 | + if (!Name) { |
| 909 | + LLVM_DEBUG(dbgs() << ".. .. Could not find libcall name for " |
| 910 | + << MIRBuilder.getTII().getName(Opc) << "\n"); |
| 911 | + return LegalizerHelper::UnableToLegalize; |
| 912 | + } |
| 913 | + |
| 914 | + CallLowering::CallLoweringInfo Info; |
| 915 | + Info.CallConv = TLI.getLibcallCallingConv(RTLibcall); |
| 916 | + Info.Callee = MachineOperand::CreateES(Name); |
| 917 | + Info.OrigRet = CallLowering::ArgInfo(RetRegs, RetTy, 0); |
| 918 | + |
| 919 | + std::copy(Args.begin(), Args.end(), std::back_inserter(Info.OrigArgs)); |
| 920 | + if (!CLI.lowerCall(MIRBuilder, Info)) |
| 921 | + return LegalizerHelper::UnableToLegalize; |
| 922 | + |
| 923 | + return LegalizerHelper::Legalized; |
| 924 | +} |
| 925 | + |
799 | 926 | static RTLIB::Libcall getConvRTLibDesc(unsigned Opcode, Type *ToType,
|
800 | 927 | Type *FromType) {
|
801 | 928 | auto ToMVT = MVT::getVT(ToType);
|
@@ -1081,6 +1208,19 @@ LegalizerHelper::libcall(MachineInstr &MI, LostDebugLocObserver &LocObserver) {
|
1081 | 1208 | return Status;
|
1082 | 1209 | break;
|
1083 | 1210 | }
|
| 1211 | + case TargetOpcode::G_ATOMICRMW_XCHG: |
| 1212 | + case TargetOpcode::G_ATOMICRMW_ADD: |
| 1213 | + case TargetOpcode::G_ATOMICRMW_SUB: |
| 1214 | + case TargetOpcode::G_ATOMICRMW_AND: |
| 1215 | + case TargetOpcode::G_ATOMICRMW_OR: |
| 1216 | + case TargetOpcode::G_ATOMICRMW_XOR: |
| 1217 | + case TargetOpcode::G_ATOMIC_CMPXCHG: |
| 1218 | + case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: { |
| 1219 | + auto Status = createAtomicLibcall(MIRBuilder, MI); |
| 1220 | + if (Status != Legalized) |
| 1221 | + return Status; |
| 1222 | + break; |
| 1223 | + } |
1084 | 1224 | case TargetOpcode::G_BZERO:
|
1085 | 1225 | case TargetOpcode::G_MEMCPY:
|
1086 | 1226 | case TargetOpcode::G_MEMMOVE:
|
|
0 commit comments