[Mlir-commits] [mlir] ddc6785 - [mlir][LLVMIR] Add translation of AtomicRMW/CmpXchg from LLVM IR
Min-Yih Hsu
llvmlistbot at llvm.org
Mon Sep 26 15:08:48 PDT 2022
Author: Min-Yih Hsu
Date: 2022-09-26T15:07:30-07:00
New Revision: ddc67856eede4004de233133fce5495f2e97383d
URL: https://github.com/llvm/llvm-project/commit/ddc67856eede4004de233133fce5495f2e97383d
DIFF: https://github.com/llvm/llvm-project/commit/ddc67856eede4004de233133fce5495f2e97383d.diff
LOG: [mlir][LLVMIR] Add translation of AtomicRMW/CmpXchg from LLVM IR
Add support for translating AtomicRMWInst and AtomicCmpXchgInst from
LLVM IR.
Differential Revision: https://reviews.llvm.org/D134450
Added:
Modified:
mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp
mlir/test/Target/LLVMIR/Import/basic.ll
Removed:
################################################################################
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index adda259e8dfbb..395980759d13f 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -1666,7 +1666,8 @@ def AtomicOrdering : I64EnumAttr<
def LLVM_AtomicRMWType : AnyTypeOf<[LLVM_AnyFloat, AnyInteger]>;
-// FIXME: Need to add alignment attribute to MLIR atomicrmw operation.
+// FIXME: Need to add alignment and syncscope attribute to MLIR atomicrmw
+// operation.
def LLVM_AtomicRMWOp : LLVM_Op<"atomicrmw"> {
let arguments = (ins AtomicBinOp:$bin_op,
LLVM_PointerTo<LLVM_AtomicRMWType>:$ptr,
diff --git a/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp b/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp
index be208b2ed9ade..df1dd6a180c90 100644
--- a/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp
+++ b/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp
@@ -631,8 +631,8 @@ static StringRef lookupOperationNameFromOpcode(unsigned opcode) {
INST(Load, Load),
INST(Store, Store),
INST(Fence, Fence),
- // FIXME: atomiccmpxchg
- // FIXME: atomicrmw
+ // AtomicCmpXchg is handled specially.
+ // AtomicRMW is handled specially.
// Getelementptr is handled specially.
INST(Trunc, Trunc),
INST(ZExt, ZExt),
@@ -761,6 +761,39 @@ static AtomicOrdering getLLVMAtomicOrdering(llvm::AtomicOrdering ordering) {
llvm_unreachable("incorrect atomic ordering");
}
+static AtomicBinOp getLLVMAtomicBinOp(llvm::AtomicRMWInst::BinOp binOp) {
+ switch (binOp) {
+ case llvm::AtomicRMWInst::Xchg:
+ return LLVM::AtomicBinOp::xchg;
+ case llvm::AtomicRMWInst::Add:
+ return LLVM::AtomicBinOp::add;
+ case llvm::AtomicRMWInst::Sub:
+ return LLVM::AtomicBinOp::sub;
+ case llvm::AtomicRMWInst::And:
+ return LLVM::AtomicBinOp::_and;
+ case llvm::AtomicRMWInst::Nand:
+ return LLVM::AtomicBinOp::nand;
+ case llvm::AtomicRMWInst::Or:
+ return LLVM::AtomicBinOp::_or;
+ case llvm::AtomicRMWInst::Xor:
+ return LLVM::AtomicBinOp::_xor;
+ case llvm::AtomicRMWInst::Max:
+ return LLVM::AtomicBinOp::max;
+ case llvm::AtomicRMWInst::Min:
+ return LLVM::AtomicBinOp::min;
+ case llvm::AtomicRMWInst::UMax:
+ return LLVM::AtomicBinOp::umax;
+ case llvm::AtomicRMWInst::UMin:
+ return LLVM::AtomicBinOp::umin;
+ case llvm::AtomicRMWInst::FAdd:
+ return LLVM::AtomicBinOp::fadd;
+ case llvm::AtomicRMWInst::FSub:
+ return LLVM::AtomicBinOp::fsub;
+ default:
+ llvm_unreachable("unsupported atomic binary operation");
+ }
+}
+
// `br` branches to `target`. Return the branch arguments to `br`, in the
// same order of the PHIs in `target`.
LogicalResult
@@ -1062,6 +1095,45 @@ LogicalResult Importer::processInstruction(llvm::Instruction *inst) {
syncscope);
return success();
}
+ case llvm::Instruction::AtomicRMW: {
+ auto *atomicInst = cast<llvm::AtomicRMWInst>(inst);
+ Value ptr = processValue(atomicInst->getPointerOperand());
+ Value val = processValue(atomicInst->getValOperand());
+ if (!ptr || !val)
+ return failure();
+
+ LLVM::AtomicBinOp binOp = getLLVMAtomicBinOp(atomicInst->getOperation());
+ LLVM::AtomicOrdering ordering =
+ getLLVMAtomicOrdering(atomicInst->getOrdering());
+
+ Type type = processType(inst->getType());
+ if (!type)
+ return failure();
+
+ instMap[inst] = b.create<AtomicRMWOp>(loc, type, binOp, ptr, val, ordering);
+ return success();
+ }
+ case llvm::Instruction::AtomicCmpXchg: {
+ auto *cmpXchgInst = cast<llvm::AtomicCmpXchgInst>(inst);
+ Value ptr = processValue(cmpXchgInst->getPointerOperand());
+ Value cmpVal = processValue(cmpXchgInst->getCompareOperand());
+ Value newVal = processValue(cmpXchgInst->getNewValOperand());
+ if (!ptr || !cmpVal || !newVal)
+ return failure();
+
+ LLVM::AtomicOrdering ordering =
+ getLLVMAtomicOrdering(cmpXchgInst->getSuccessOrdering());
+ LLVM::AtomicOrdering failOrdering =
+ getLLVMAtomicOrdering(cmpXchgInst->getFailureOrdering());
+
+ Type type = processType(inst->getType());
+ if (!type)
+ return failure();
+
+ instMap[inst] = b.create<AtomicCmpXchgOp>(loc, type, ptr, cmpVal, newVal,
+ ordering, failOrdering);
+ return success();
+ }
case llvm::Instruction::GetElementPtr: {
// FIXME: Support inbounds GEPs.
llvm::GetElementPtrInst *gep = cast<llvm::GetElementPtrInst>(inst);
diff --git a/mlir/test/Target/LLVMIR/Import/basic.ll b/mlir/test/Target/LLVMIR/Import/basic.ll
index cc8c5e5d463b5..66732c52dc23d 100644
--- a/mlir/test/Target/LLVMIR/Import/basic.ll
+++ b/mlir/test/Target/LLVMIR/Import/basic.ll
@@ -668,3 +668,46 @@ define void @variadic_function(i32 %X, ...) {
; CHECK: llvm.return
ret void
}
+
+; CHECK-LABEL: llvm.func @atomic_rmw
+define void @atomic_rmw(i32* %ptr0, i32 %v, float* %ptr1, float %f) {
+ ; CHECK: llvm.atomicrmw add %arg0, %arg1 acquire : i32
+ %1 = atomicrmw add i32* %ptr0, i32 %v acquire
+ ; CHECK: llvm.atomicrmw add %arg0, %arg1 release : i32
+ %2 = atomicrmw add i32* %ptr0, i32 %v release
+
+ ; CHECK: llvm.atomicrmw sub %arg0, %arg1 acquire : i32
+ %3 = atomicrmw sub i32* %ptr0, i32 %v acquire
+ ; CHECK: llvm.atomicrmw xchg %arg0, %arg1 acquire : i32
+ %4 = atomicrmw xchg i32* %ptr0, i32 %v acquire
+ ; CHECK: llvm.atomicrmw _and %arg0, %arg1 acquire : i32
+ %5 = atomicrmw and i32* %ptr0, i32 %v acquire
+ ; CHECK: llvm.atomicrmw nand %arg0, %arg1 acquire : i32
+ %6 = atomicrmw nand i32* %ptr0, i32 %v acquire
+ ; CHECK: llvm.atomicrmw _or %arg0, %arg1 acquire : i32
+ %7 = atomicrmw or i32* %ptr0, i32 %v acquire
+ ; CHECK: llvm.atomicrmw _xor %arg0, %arg1 acquire : i32
+ %8 = atomicrmw xor i32* %ptr0, i32 %v acquire
+ ; CHECK: llvm.atomicrmw max %arg0, %arg1 acquire : i32
+ %9 = atomicrmw max i32* %ptr0, i32 %v acquire
+ ; CHECK: llvm.atomicrmw min %arg0, %arg1 acquire : i32
+ %10 = atomicrmw min i32* %ptr0, i32 %v acquire
+ ; CHECK: llvm.atomicrmw umax %arg0, %arg1 acquire : i32
+ %11 = atomicrmw umax i32* %ptr0, i32 %v acquire
+ ; CHECK: llvm.atomicrmw umin %arg0, %arg1 acquire : i32
+ %12 = atomicrmw umin i32* %ptr0, i32 %v acquire
+ ; CHECK: llvm.atomicrmw fadd %arg2, %arg3 acquire : f32
+ %13 = atomicrmw fadd float* %ptr1, float %f acquire
+ ; CHECK: llvm.atomicrmw fsub %arg2, %arg3 acquire : f32
+ %14 = atomicrmw fsub float* %ptr1, float %f acquire
+ ret void
+}
+
+; CHECK-LABEL: llvm.func @atomic_cmpxchg
+define void @atomic_cmpxchg(i32* %ptr0, i32 %v, i32 %c) {
+ ; CHECK: llvm.cmpxchg %arg0, %arg2, %arg1 seq_cst seq_cst : i32
+ %1 = cmpxchg i32* %ptr0, i32 %c, i32 %v seq_cst seq_cst
+ ; CHECK: llvm.cmpxchg %arg0, %arg2, %arg1 monotonic seq_cst : i32
+ %2 = cmpxchg i32* %ptr0, i32 %c, i32 %v monotonic seq_cst
+ ret void
+}
More information about the Mlir-commits
mailing list