From 7fe7acc6b1b902d1e1207232e3ea31931dad73ab Mon Sep 17 00:00:00 2001 From: Daniel Sanders Date: Tue, 28 Nov 2017 20:21:15 +0000 Subject: [PATCH] [aarch64][globalisel] Define G_ATOMIC_CMPXCHG and G_ATOMICRMW_* and make them legal The IRTranslator cannot generate these instructions at the moment so there's no issue with not having implemented ISel for them yet. D40092 will add G_ATOMIC_CMPXCHG_WITH_SUCCESS and G_ATOMICRMW_* to the IRTranslator and a further patch will add support for lowering G_ATOMIC_CMPXCHG_WITH_SUCCESS into G_ATOMIC_CMPXCHG with an external success check via the `Lower` action. The separation of G_ATOMIC_CMPXCHG_WITH_SUCCESS and G_ATOMIC_CMPXCHG is to import SelectionDAG rules while still supporting targets that prefer to custom lower the original LLVM-IR-like operation. llvm-svn: 319216 --- llvm/include/llvm/CodeGen/TargetOpcodes.def | 16 ++++ llvm/include/llvm/Target/GenericOpcodes.td | 98 ++++++++++++++++++++++++ llvm/lib/Target/AArch64/AArch64LegalizerInfo.cpp | 19 ++++- llvm/lib/Target/AArch64/AArch64LegalizerInfo.h | 3 +- llvm/lib/Target/AArch64/AArch64Subtarget.cpp | 2 +- 5 files changed, 135 insertions(+), 3 deletions(-) diff --git a/llvm/include/llvm/CodeGen/TargetOpcodes.def b/llvm/include/llvm/CodeGen/TargetOpcodes.def index 37e2e41..3497dcf 100644 --- a/llvm/include/llvm/CodeGen/TargetOpcodes.def +++ b/llvm/include/llvm/CodeGen/TargetOpcodes.def @@ -265,6 +265,22 @@ HANDLE_TARGET_OPCODE(G_LOAD) /// Generic store. HANDLE_TARGET_OPCODE(G_STORE) +/// Generic atomic cmpxchg. +HANDLE_TARGET_OPCODE(G_ATOMIC_CMPXCHG) + +/// Generic atomicrmw. +HANDLE_TARGET_OPCODE(G_ATOMICRMW_XCHG) +HANDLE_TARGET_OPCODE(G_ATOMICRMW_ADD) +HANDLE_TARGET_OPCODE(G_ATOMICRMW_SUB) +HANDLE_TARGET_OPCODE(G_ATOMICRMW_AND) +HANDLE_TARGET_OPCODE(G_ATOMICRMW_NAND) +HANDLE_TARGET_OPCODE(G_ATOMICRMW_OR) +HANDLE_TARGET_OPCODE(G_ATOMICRMW_XOR) +HANDLE_TARGET_OPCODE(G_ATOMICRMW_MAX) +HANDLE_TARGET_OPCODE(G_ATOMICRMW_MIN) +HANDLE_TARGET_OPCODE(G_ATOMICRMW_UMAX) +HANDLE_TARGET_OPCODE(G_ATOMICRMW_UMIN) + /// Generic conditional branch instruction. HANDLE_TARGET_OPCODE(G_BRCOND) diff --git a/llvm/include/llvm/Target/GenericOpcodes.td b/llvm/include/llvm/Target/GenericOpcodes.td index 557217c..b1cb302 100644 --- a/llvm/include/llvm/Target/GenericOpcodes.td +++ b/llvm/include/llvm/Target/GenericOpcodes.td @@ -482,6 +482,104 @@ def G_STORE : Instruction { let mayStore = 1; } +// Generic atomic cmpxchg. Expects a MachineMemOperand in addition to explicit +// operands. +def G_ATOMIC_CMPXCHG : Instruction { + let OutOperandList = (outs type0:$oldval); + let InOperandList = (ins ptype1:$addr, type0:$cmpval, type0:$newval); + let hasSideEffects = 0; + let mayLoad = 1; + let mayStore = 1; +} + +// Generic atomicrmw. Expects a MachineMemOperand in addition to explicit +// operands. +class G_ATOMICRMW_OP : Instruction { + let OutOperandList = (outs type0:$oldval); + let InOperandList = (ins ptype1:$addr, type0:$val); + let hasSideEffects = 0; + let mayLoad = 1; + let mayStore = 1; +} + +def G_ATOMICRMW_XCHG : G_ATOMICRMW_OP { + // FIXME: This include is surrounded by a 'let mayLoad = 0, mayStore = 0 in {}' + // block which overrides the value inherited from G_ATOMICRMW_OP. Work + // around this for now. See http://reviews.llvm.org/D40096 + let mayLoad = 1; + let mayStore = 1; +} +def G_ATOMICRMW_ADD : G_ATOMICRMW_OP { + // FIXME: This include is surrounded by a 'let mayLoad = 0, mayStore = 0 in {}' + // block which overrides the value inherited from G_ATOMICRMW_OP. Work + // around this for now. See http://reviews.llvm.org/D40096 + let mayLoad = 1; + let mayStore = 1; +} +def G_ATOMICRMW_SUB : G_ATOMICRMW_OP { + // FIXME: This include is surrounded by a 'let mayLoad = 0, mayStore = 0 in {}' + // block which overrides the value inherited from G_ATOMICRMW_OP. Work + // around this for now. See http://reviews.llvm.org/D40096 + let mayLoad = 1; + let mayStore = 1; +} +def G_ATOMICRMW_AND : G_ATOMICRMW_OP { + // FIXME: This include is surrounded by a 'let mayLoad = 0, mayStore = 0 in {}' + // block which overrides the value inherited from G_ATOMICRMW_OP. Work + // around this for now. See http://reviews.llvm.org/D40096 + let mayLoad = 1; + let mayStore = 1; +} +def G_ATOMICRMW_NAND : G_ATOMICRMW_OP { + // FIXME: This include is surrounded by a 'let mayLoad = 0, mayStore = 0 in {}' + // block which overrides the value inherited from G_ATOMICRMW_OP. Work + // around this for now. See http://reviews.llvm.org/D40096 + let mayLoad = 1; + let mayStore = 1; +} +def G_ATOMICRMW_OR : G_ATOMICRMW_OP { + // FIXME: This include is surrounded by a 'let mayLoad = 0, mayStore = 0 in {}' + // block which overrides the value inherited from G_ATOMICRMW_OP. Work + // around this for now. See http://reviews.llvm.org/D40096 + let mayLoad = 1; + let mayStore = 1; +} +def G_ATOMICRMW_XOR : G_ATOMICRMW_OP { + // FIXME: This include is surrounded by a 'let mayLoad = 0, mayStore = 0 in {}' + // block which overrides the value inherited from G_ATOMICRMW_OP. Work + // around this for now. See http://reviews.llvm.org/D40096 + let mayLoad = 1; + let mayStore = 1; +} +def G_ATOMICRMW_MAX : G_ATOMICRMW_OP { + // FIXME: This include is surrounded by a 'let mayLoad = 0, mayStore = 0 in {}' + // block which overrides the value inherited from G_ATOMICRMW_OP. Work + // around this for now. See http://reviews.llvm.org/D40096 + let mayLoad = 1; + let mayStore = 1; +} +def G_ATOMICRMW_MIN : G_ATOMICRMW_OP { + // FIXME: This include is surrounded by a 'let mayLoad = 0, mayStore = 0 in {}' + // block which overrides the value inherited from G_ATOMICRMW_OP. Work + // around this for now. See http://reviews.llvm.org/D40096 + let mayLoad = 1; + let mayStore = 1; +} +def G_ATOMICRMW_UMAX : G_ATOMICRMW_OP { + // FIXME: This include is surrounded by a 'let mayLoad = 0, mayStore = 0 in {}' + // block which overrides the value inherited from G_ATOMICRMW_OP. Work + // around this for now. See http://reviews.llvm.org/D40096 + let mayLoad = 1; + let mayStore = 1; +} +def G_ATOMICRMW_UMIN : G_ATOMICRMW_OP { + // FIXME: This include is surrounded by a 'let mayLoad = 0, mayStore = 0 in {}' + // block which overrides the value inherited from G_ATOMICRMW_OP. Work + // around this for now. See http://reviews.llvm.org/D40096 + let mayLoad = 1; + let mayStore = 1; +} + //------------------------------------------------------------------------------ // Variadic ops //------------------------------------------------------------------------------ diff --git a/llvm/lib/Target/AArch64/AArch64LegalizerInfo.cpp b/llvm/lib/Target/AArch64/AArch64LegalizerInfo.cpp index f702739..b040315 100644 --- a/llvm/lib/Target/AArch64/AArch64LegalizerInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64LegalizerInfo.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "AArch64LegalizerInfo.h" +#include "AArch64Subtarget.h" #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineRegisterInfo.h" @@ -127,7 +128,7 @@ widen_1_8_16_32(const LegalizerInfo::SizeAndActionsVec &v) { return result; } -AArch64LegalizerInfo::AArch64LegalizerInfo() { +AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST) { using namespace TargetOpcode; const LLT p0 = LLT::pointer(0, 64); const LLT s1 = LLT::scalar(1); @@ -349,6 +350,22 @@ AArch64LegalizerInfo::AArch64LegalizerInfo() { for (auto Ty : {s8, s16, s32, s64, p0}) setAction({G_VAARG, Ty}, Custom); + if (ST.hasLSE()) { + for (auto Ty : {s8, s16, s32, s64}) + setAction({G_ATOMIC_CMPXCHG, Ty}, Legal); + setAction({G_ATOMIC_CMPXCHG, 1, p0}, Legal); + + for (auto Op : + {G_ATOMICRMW_XCHG, G_ATOMICRMW_ADD, G_ATOMICRMW_SUB, G_ATOMICRMW_AND, + G_ATOMICRMW_OR, G_ATOMICRMW_XOR, G_ATOMICRMW_MIN, G_ATOMICRMW_MAX, + G_ATOMICRMW_UMIN, G_ATOMICRMW_UMAX}) { + for (auto Ty : {s8, s16, s32, s64}) { + setAction({Op, Ty}, Legal); + } + setAction({Op, 1, p0}, Legal); + } + } + computeTables(); } diff --git a/llvm/lib/Target/AArch64/AArch64LegalizerInfo.h b/llvm/lib/Target/AArch64/AArch64LegalizerInfo.h index 42d4ac1..a745b0e 100644 --- a/llvm/lib/Target/AArch64/AArch64LegalizerInfo.h +++ b/llvm/lib/Target/AArch64/AArch64LegalizerInfo.h @@ -20,11 +20,12 @@ namespace llvm { class LLVMContext; +class AArch64Subtarget; /// This class provides the information for the target register banks. class AArch64LegalizerInfo : public LegalizerInfo { public: - AArch64LegalizerInfo(); + AArch64LegalizerInfo(const AArch64Subtarget &ST); bool legalizeCustom(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &MIRBuilder) const override; diff --git a/llvm/lib/Target/AArch64/AArch64Subtarget.cpp b/llvm/lib/Target/AArch64/AArch64Subtarget.cpp index 28b8f7c..60cbe54 100644 --- a/llvm/lib/Target/AArch64/AArch64Subtarget.cpp +++ b/llvm/lib/Target/AArch64/AArch64Subtarget.cpp @@ -154,7 +154,7 @@ AArch64Subtarget::AArch64Subtarget(const Triple &TT, const std::string &CPU, InstrInfo(initializeSubtargetDependencies(FS, CPU)), TSInfo(), TLInfo(TM, *this) { CallLoweringInfo.reset(new AArch64CallLowering(*getTargetLowering())); - Legalizer.reset(new AArch64LegalizerInfo()); + Legalizer.reset(new AArch64LegalizerInfo(*this)); auto *RBI = new AArch64RegisterBankInfo(*getRegisterInfo()); -- 2.7.4