diff --git a/llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp b/llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp --- a/llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp +++ b/llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp @@ -65,6 +65,8 @@ bool selectI64Imm(MachineInstr &I, MachineBasicBlock &MBB, MachineRegisterInfo &MRI) const; + ComplexRendererFns SelectForceXForm(MachineOperand &Root) const; + const PPCTargetMachine &TM; const PPCSubtarget &STI; const PPCInstrInfo &TII; @@ -775,6 +777,19 @@ return false; } +InstructionSelector::ComplexRendererFns +PPCInstructionSelector::SelectForceXForm(MachineOperand &Root) const { + if (!Root.isReg()) + return std::nullopt; + Register Reg = Root.getReg(); + if (!Reg) + return std::nullopt; + return {{[=](MachineInstrBuilder &MIB) { + TM.isPPC64() ? MIB.addUse(PPC::ZERO8) : MIB.addUse(PPC::ZERO); + }, + [=](MachineInstrBuilder &MIB) { MIB.addUse(Reg); }}}; +} + namespace llvm { InstructionSelector * createPPCInstructionSelector(const PPCTargetMachine &TM, diff --git a/llvm/lib/Target/PowerPC/GISel/PPCLegalizerInfo.cpp b/llvm/lib/Target/PowerPC/GISel/PPCLegalizerInfo.cpp --- a/llvm/lib/Target/PowerPC/GISel/PPCLegalizerInfo.cpp +++ b/llvm/lib/Target/PowerPC/GISel/PPCLegalizerInfo.cpp @@ -16,6 +16,7 @@ using namespace llvm; using namespace LegalizeActions; +using namespace LegalityPredicates; PPCLegalizerInfo::PPCLegalizerInfo(const PPCSubtarget &ST) { using namespace TargetOpcode; @@ -56,6 +57,10 @@ getActionDefinitionsBuilder(G_FCONSTANT).lowerFor({S32, S64}); getActionDefinitionsBuilder(G_CONSTANT_POOL).legalFor({P0}); + getActionDefinitionsBuilder( + {G_ATOMICRMW_XCHG, G_ATOMICRMW_ADD, G_ATOMICRMW_SUB}) + .clampScalar(0, S8, S64) + .legalIf(all(typeInSet(0, {S8, S16, S32, S64}), typeIs(1, P0))); getLegacyLegalizerInfo().computeTables(); } diff --git a/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.h b/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.h --- a/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.h +++ b/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.h @@ -29,11 +29,13 @@ enum PartialMappingIdx { PMI_None = -1, PMI_GPR32 = 1, - PMI_GPR64 = 2, - PMI_FPR32 = 3, - PMI_FPR64 = 4, - PMI_CR = 5, + PMI_GPR64, + PMI_FPR32, + PMI_FPR64, + PMI_CR, PMI_Min = PMI_GPR32, + PMI_FirstGPR = PMI_GPR32, + PMI_LastGPR = PMI_GPR64, }; static RegisterBankInfo::PartialMapping PartMappings[]; diff --git a/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.cpp b/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.cpp --- a/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.cpp +++ b/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.cpp @@ -178,15 +178,29 @@ getValueMapping(PMI_GPR64)}); break; } - case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS: { - // FIXME: We have to check every operand in this MI and compute value - // mapping accordingly. + default: SmallVector OpdsMapping(NumOperands); + for (unsigned Idx = 0; Idx < NumOperands; ++Idx) { + const MachineOperand &MO = MI.getOperand(Idx); + if (!MO.isReg()) + continue; + Register Reg = MO.getReg(); + if (!Reg) + continue; + LLT Ty = MRI.getType(Reg); + if (!Ty.isValid()) + continue; + unsigned Size = Ty.getSizeInBits(); + const ValueMapping *VM = nullptr; + if (Size == 32) + VM = getValueMapping(PMI_GPR32); + else if (Size == 64) + VM = getValueMapping(PMI_GPR64); + if (!VM || !VM->isValid()) + return getInvalidInstructionMapping(); + OpdsMapping[Idx] = VM; + } OperandsMapping = getOperandsMapping(OpdsMapping); - break; - } - default: - return getInvalidInstructionMapping(); } return getInstructionMapping(MappingID, Cost, OperandsMapping, NumOperands); diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td @@ -695,6 +695,10 @@ def PCRelForm : ComplexPattern; def PDForm : ComplexPattern; +// Mapping complex patterns to GlobalISel equivalence. +def GI_ForceXForm : GIComplexOperandMatcher, + GIComplexPatternEquiv; + //===----------------------------------------------------------------------===// // PowerPC Instruction Predicate Definitions. def In32BitMode : Predicate<"!Subtarget->isPPC64()">; diff --git a/llvm/test/CodeGen/PowerPC/GlobalISel/ppc-isel-atomics.ll b/llvm/test/CodeGen/PowerPC/GlobalISel/ppc-isel-atomics.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/GlobalISel/ppc-isel-atomics.ll @@ -0,0 +1,22 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -verify-machineinstrs -mtriple powerpc64le-unknown-unknown \ +; RUN: -ppc-asm-full-reg-names -global-isel -o - < %s | FileCheck %s + +define i64 @atomic_add_i64(ptr %p, i64 %diff) { +; CHECK-LABEL: atomic_add_i64: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: sync +; CHECK-NEXT: .LBB0_1: # %entry +; CHECK-NEXT: # +; CHECK-NEXT: ldarx r5, 0, r3 +; CHECK-NEXT: add r6, r4, r5 +; CHECK-NEXT: stdcx. r6, 0, r3 +; CHECK-NEXT: bne cr0, .LBB0_1 +; CHECK-NEXT: # %bb.2: # %entry +; CHECK-NEXT: mr r3, r5 +; CHECK-NEXT: lwsync +; CHECK-NEXT: blr +entry: + %ret = atomicrmw add ptr %p, i64 %diff seq_cst, align 8 + ret i64 %ret +}