[PATCH] D99024: [OpenMP][OMPIRBuilder] Adding support for `omp atomic`
Fady Ghanim via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 5 14:44:31 PDT 2021
fghanim marked 5 inline comments as done.
fghanim added a comment.
In D99024#2667320 <https://reviews.llvm.org/D99024#2667320>, @SouraVX wrote:
> Thanks! @fghanim for the patch :)
Sure! :)
> I noticed following piece of code getting used in `createAtomicRead`, `createAtomicWrite`, `createAtomicCapture`, `createAtomicUpdate`.
>
> if (!updateToLocation(Loc))
> return Loc.IP;
> Type *XTy = X.Var->getType();
> assert(XTy->isPointerTy() && "OMP Atomic expects a pointer to target memory");
> Type *XElemTy = XTy->getPointerElementType();
> assert((XElemTy->isFloatingPointTy() || XElemTy->isIntegerTy() ||
> XElemTy->isPointerTy()) &&
> "OMP atomic read expected a scalar type");
>
> Was wondering if this could be simplified or hoisted out in a tiny innocuous helper function ?
The `return` returns from `createOMPAtomicXXX` calls, and each of `XTy` and `XElemTy` are used inside the function. Also, We are checking different kinds of errors between different atomic clauses, and issuing different error assert messages based on the error, .
> Also right now we have these `4` public interfaces with external front-end's. Can we simplify this into `2` public interfaces as `createAtomicReadOrWrite` and `createAtomicCaptureOrUpdate` ?
> The rationale behind this proposition is that, these functions share a lot common code(at expense of 1 or 2 extra argument needed to handle the other case).
> Can we do this ? Or doing such simplification will render the code more unreadable/complicated ?
> Please Let me know WDYT ?
I don't think we are simplifying things by doing that, because it will cause unnecessary confusion. two parts:
- Regarding atomic read and atomic write, there is nothing in common between the two (other than the initial checks). While at first glance, they may look similar, they are not.
- Regarding atomic update and atomic capture, I already implemented the parts that are common between the two separately into `emitAtomicUpdate`
In general, it is better for someone handling an atomic read, to just call `createOMPAtomicRead`, than call something that is also doing writes. more intuitive.
> + @AMDChirag
================
Comment at: llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h:831
+ /// \param AllocIP Instruction to create AllocaInst before.
+ /// \param X The target atomic pointer to be updated
+ /// \param Expr The value to update X with.
----------------
SouraVX wrote:
> Can we use a better/descriptive name here ? Maybe `TargetAtomicPtr` ?
> Other references should also benefit from descriptive name.
These names are picked to match the naming used in the OMP standard documents for atomic:
https://www.openmp.org/spec-html/5.0/openmpsu95.html
================
Comment at: llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h:934
+ /// \param X The target atomic pointer to be updated
+ /// \param V Memory address where to store captured value
+ /// \param Expr The value to update X with.
----------------
SouraVX wrote:
> This could also benefit from descriptive naming ?
These names are picked to match the naming used in the OMP standard documents for atomic:
https://www.openmp.org/spec-html/5.0/openmpsu95.html
================
Comment at: llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp:2161-2164
+ if (Builder.GetInsertPoint() == ContBB->end())
+ llvm::errs() << "end block\n";
+ else
+ ContBB->dump();
----------------
Meinersbur wrote:
> Debugging leftover?
Yes. Thanks for catching that. removed
================
Comment at: llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp:1922
+bool OpenMPIRBuilder::CheckAndEmitFlushAfterAtomic(
+ const LocationDescription &Loc, llvm::AtomicOrdering AO, AtomicKind AK) {
----------------
Meinersbur wrote:
> Consider making such helpers static functions instead of priviate methods, so they don't need to appear in the public header file.
I call emitFlush() which is private
================
Comment at: llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp:2082-2088
+ case AtomicRMWInst::Xchg:
+ case AtomicRMWInst::FAdd:
+ case AtomicRMWInst::FSub:
+ case AtomicRMWInst::BAD_BINOP:
+ case AtomicRMWInst::Max:
+ case AtomicRMWInst::Min:
+ default:
----------------
Meinersbur wrote:
> fghanim wrote:
> > Meinersbur wrote:
> > > With a default case, no need to enumerate all cases.
> >
> > I intentionally listed all cases. If you want, i'll remove `default` which I added to future proof the code.
> With a default case, the compiler does not warn about unhandled cases anymore. If you want both, you could do:
>
> ```
> [...]
> case AtomicRMWInst::Min:
> llvm_unreachable("Unsupported atomic update operation");
> }
> llvm_unreacheable("Unhandled atomic update operation");
> ```
> Personally I think it just adds clutter lines. In case of some parts of clang's OpenMP implementation it fills entire screens of unsupported cases and there is no chance I miss handling the case during testing due to the llvm_unreachable.
>
> Currently, `return nullptr;` is unreachable code.
The issue here is that, these cases are either not supported in omp (min,max,..), or should be handled by the cmpExch (fadd, fsub,exch). I worry if i don't explicitly list them as unreachable somebody might try to implement them.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D99024/new/
https://reviews.llvm.org/D99024
More information about the llvm-commits
mailing list