-
Notifications
You must be signed in to change notification settings - Fork 10.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Flang][OpenMP] Fix update operation not found issue #92165
Conversation
If there is only one non-terminator operation in the update region then the update operation can be found and we can try to generate an atomicrmw instruction. Otherwise use the cmpxchg loop. Fixes llvm#91929
@llvm/pr-subscribers-mlir-openmp @llvm/pr-subscribers-mlir-llvm Author: Kiran Chandramohan (kiranchandramohan) ChangesIf there is only one non-terminator operation in the update region then the update operation can be found and we can try to generate an atomicrmw instruction. Otherwise use the cmpxchg loop. Fixes #91929 Full diff: https://github.com/llvm/llvm-project/pull/92165.diff 1 Files Affected:
diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
index a7294632d6667..ed9fb44cf08ed 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
@@ -1623,31 +1623,33 @@ convertOmpAtomicUpdate(omp::AtomicUpdateOp &opInst,
// Convert values and types.
auto &innerOpList = opInst.getRegion().front().getOperations();
- bool isRegionArgUsed{false}, isXBinopExpr{false};
+ bool isXBinopExpr{false};
llvm::AtomicRMWInst::BinOp binop;
mlir::Value mlirExpr;
- // Find the binary update operation that uses the region argument
- // and get the expression to update
- for (Operation &innerOp : innerOpList) {
- if (innerOp.getNumOperands() == 2) {
- binop = convertBinOpToAtomic(innerOp);
- if (!llvm::is_contained(innerOp.getOperands(),
- opInst.getRegion().getArgument(0)))
- continue;
- isRegionArgUsed = true;
- isXBinopExpr = innerOp.getNumOperands() > 0 &&
- innerOp.getOperand(0) == opInst.getRegion().getArgument(0);
- mlirExpr = (isXBinopExpr ? innerOp.getOperand(1) : innerOp.getOperand(0));
- break;
+ llvm::Value *llvmExpr = nullptr;
+ llvm::Value *llvmX = nullptr;
+ llvm::Type *llvmXElementType = nullptr;
+ if (innerOpList.size() == 2) {
+ // The two operations here are the update and the terminator.
+ // Since we can identify the update operation, there is a possibility
+ // that we can generate the atomicrmw instruction.
+ mlir::Operation &innerOp = *opInst.getRegion().front().begin();
+ if (!llvm::is_contained(innerOp.getOperands(),
+ opInst.getRegion().getArgument(0))) {
+ return opInst.emitError("no atomic update operation with region argument"
+ " as operand found inside atomic.update region");
}
+ binop = convertBinOpToAtomic(innerOp);
+ isXBinopExpr = innerOp.getOperand(0) == opInst.getRegion().getArgument(0);
+ mlirExpr = (isXBinopExpr ? innerOp.getOperand(1) : innerOp.getOperand(0));
+ llvmExpr = moduleTranslation.lookupValue(mlirExpr);
+ } else {
+ // Since the update region includes more than one operation
+ // we will resort to generating a cmpxchg loop.
+ binop = llvm::AtomicRMWInst::BinOp::BAD_BINOP;
}
- if (!isRegionArgUsed)
- return opInst.emitError("no atomic update operation with region argument"
- " as operand found inside atomic.update region");
-
- llvm::Value *llvmExpr = moduleTranslation.lookupValue(mlirExpr);
- llvm::Value *llvmX = moduleTranslation.lookupValue(opInst.getX());
- llvm::Type *llvmXElementType = moduleTranslation.convertType(
+ llvmX = moduleTranslation.lookupValue(opInst.getX());
+ llvmXElementType = moduleTranslation.convertType(
opInst.getRegion().getArgument(0).getType());
llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicX = {llvmX, llvmXElementType,
/*isSigned=*/false,
|
@llvm/pr-subscribers-mlir Author: Kiran Chandramohan (kiranchandramohan) ChangesIf there is only one non-terminator operation in the update region then the update operation can be found and we can try to generate an atomicrmw instruction. Otherwise use the cmpxchg loop. Fixes #91929 Full diff: https://github.com/llvm/llvm-project/pull/92165.diff 1 Files Affected:
diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
index a7294632d6667..ed9fb44cf08ed 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
@@ -1623,31 +1623,33 @@ convertOmpAtomicUpdate(omp::AtomicUpdateOp &opInst,
// Convert values and types.
auto &innerOpList = opInst.getRegion().front().getOperations();
- bool isRegionArgUsed{false}, isXBinopExpr{false};
+ bool isXBinopExpr{false};
llvm::AtomicRMWInst::BinOp binop;
mlir::Value mlirExpr;
- // Find the binary update operation that uses the region argument
- // and get the expression to update
- for (Operation &innerOp : innerOpList) {
- if (innerOp.getNumOperands() == 2) {
- binop = convertBinOpToAtomic(innerOp);
- if (!llvm::is_contained(innerOp.getOperands(),
- opInst.getRegion().getArgument(0)))
- continue;
- isRegionArgUsed = true;
- isXBinopExpr = innerOp.getNumOperands() > 0 &&
- innerOp.getOperand(0) == opInst.getRegion().getArgument(0);
- mlirExpr = (isXBinopExpr ? innerOp.getOperand(1) : innerOp.getOperand(0));
- break;
+ llvm::Value *llvmExpr = nullptr;
+ llvm::Value *llvmX = nullptr;
+ llvm::Type *llvmXElementType = nullptr;
+ if (innerOpList.size() == 2) {
+ // The two operations here are the update and the terminator.
+ // Since we can identify the update operation, there is a possibility
+ // that we can generate the atomicrmw instruction.
+ mlir::Operation &innerOp = *opInst.getRegion().front().begin();
+ if (!llvm::is_contained(innerOp.getOperands(),
+ opInst.getRegion().getArgument(0))) {
+ return opInst.emitError("no atomic update operation with region argument"
+ " as operand found inside atomic.update region");
}
+ binop = convertBinOpToAtomic(innerOp);
+ isXBinopExpr = innerOp.getOperand(0) == opInst.getRegion().getArgument(0);
+ mlirExpr = (isXBinopExpr ? innerOp.getOperand(1) : innerOp.getOperand(0));
+ llvmExpr = moduleTranslation.lookupValue(mlirExpr);
+ } else {
+ // Since the update region includes more than one operation
+ // we will resort to generating a cmpxchg loop.
+ binop = llvm::AtomicRMWInst::BinOp::BAD_BINOP;
}
- if (!isRegionArgUsed)
- return opInst.emitError("no atomic update operation with region argument"
- " as operand found inside atomic.update region");
-
- llvm::Value *llvmExpr = moduleTranslation.lookupValue(mlirExpr);
- llvm::Value *llvmX = moduleTranslation.lookupValue(opInst.getX());
- llvm::Type *llvmXElementType = moduleTranslation.convertType(
+ llvmX = moduleTranslation.lookupValue(opInst.getX());
+ llvmXElementType = moduleTranslation.convertType(
opInst.getRegion().getArgument(0).getType());
llvm::OpenMPIRBuilder::AtomicOpValue llvmAtomicX = {llvmX, llvmXElementType,
/*isSigned=*/false,
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fix looks good. Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible to add a test for this case?
Yes. Done. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for adding a test 🙂
If there is only one non-terminator operation in the update region then the update operation can be found and we can try to generate an atomicrmw instruction. Otherwise use the cmpxchg loop. Fixes llvm#91929
If there is only one non-terminator operation in the update region then the update operation can be found and we can try to generate an atomicrmw instruction. Otherwise use the cmpxchg loop.
Fixes #91929