[PATCH] D47553: Add TargetLowering::shouldExpandAtomicToLibCall and query it from AtomicExpandPass

Alex Bradbury via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed May 30 13:08:11 PDT 2018


asb created this revision.
asb added reviewers: jfb, jyknight, kparzysz.

Currently, AtomicExpandPass will expand atomic instructions to an `__atomic_*` libcall in the if the size is greater than MaxSizeInBitsSupported or the alignment is less than the value's natural alignment. The only way a target can influence this is by changing MaxSizeInBitsSupported, but this is a very blunt instrument. For RISC-V RV32I or RV64I without the 'A' (atomics) instruction set extension I want to have AtomicExpandPass generate:

- load/store + fences for suitably aligned load/store up to the register width
- `__atomic_*` libcalls otherwise (large or unaligned load/stores, atomicrmw, cmpxchg)

The new TargetLowering::shouldExpandAtomicToLibCall makes this degree of flexibility possible. The default implementation makes use of MaxSizeInBitsSupported so there is no functional change for in-tree or out-of-tree targets that don't implement their own shouldExpandAtomicToLibCall.

I'll shortly post the RISC-V atomics patches that make use of this hook.


Repository:
  rL LLVM

https://reviews.llvm.org/D47553

Files:
  include/llvm/CodeGen/TargetLowering.h
  lib/CodeGen/AtomicExpandPass.cpp


Index: lib/CodeGen/AtomicExpandPass.cpp
===================================================================
--- lib/CodeGen/AtomicExpandPass.cpp
+++ lib/CodeGen/AtomicExpandPass.cpp
@@ -181,16 +181,6 @@
   return DL.getTypeStoreSize(CASI->getCompareOperand()->getType());
 }
 
-// Determine if a particular atomic operation has a supported size,
-// and is of appropriate alignment, to be passed through for target
-// lowering. (Versus turning into a __atomic libcall)
-template <typename Inst>
-static bool atomicSizeSupported(const TargetLowering *TLI, Inst *I) {
-  unsigned Size = getAtomicOpSize(I);
-  unsigned Align = getAtomicOpAlign(I);
-  return Align >= Size && Size <= TLI->getMaxAtomicSizeInBitsSupported() / 8;
-}
-
 bool AtomicExpand::runOnFunction(Function &F) {
   auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
   if (!TPC)
@@ -221,25 +211,29 @@
 
     // If the Size/Alignment is not supported, replace with a libcall.
     if (LI) {
-      if (!atomicSizeSupported(TLI, LI)) {
+      if (TLI->shouldExpandAtomicToLibCall(getAtomicOpSize(LI),
+                                           getAtomicOpAlign(LI), LI)) {
         expandAtomicLoadToLibcall(LI);
         MadeChange = true;
         continue;
       }
     } else if (SI) {
-      if (!atomicSizeSupported(TLI, SI)) {
+      if (TLI->shouldExpandAtomicToLibCall(getAtomicOpSize(SI),
+                                           getAtomicOpAlign(SI), SI)) {
         expandAtomicStoreToLibcall(SI);
         MadeChange = true;
         continue;
       }
     } else if (RMWI) {
-      if (!atomicSizeSupported(TLI, RMWI)) {
+      if (TLI->shouldExpandAtomicToLibCall(getAtomicOpSize(RMWI),
+                                           getAtomicOpAlign(RMWI), RMWI)) {
         expandAtomicRMWToLibcall(RMWI);
         MadeChange = true;
         continue;
       }
     } else if (CASI) {
-      if (!atomicSizeSupported(TLI, CASI)) {
+      if (TLI->shouldExpandAtomicToLibCall(getAtomicOpSize(CASI),
+                                           getAtomicOpAlign(CASI), CASI)) {
         expandAtomicCASToLibcall(CASI);
         MadeChange = true;
         continue;
Index: include/llvm/CodeGen/TargetLowering.h
===================================================================
--- include/llvm/CodeGen/TargetLowering.h
+++ include/llvm/CodeGen/TargetLowering.h
@@ -1481,11 +1481,21 @@
   /// Returns the maximum atomic operation size (in bits) supported by
   /// the backend. Atomic operations greater than this size (as well
   /// as ones that are not naturally aligned), will be expanded by
-  /// AtomicExpandPass into an __atomic_* library call.
+  /// AtomicExpandPass into an __atomic_* library call unless
+  /// shouldExpandAtomicToLibCall is overridden.
   unsigned getMaxAtomicSizeInBitsSupported() const {
     return MaxAtomicSizeInBitsSupported;
   }
 
+  /// Indicates whether this atomic should be expanded to a libcall. Defaults to
+  /// expanding when the atomic is less than naturally aligned or its size is
+  /// greater than MaxAtomicSizeInBitsSupported. If the atomic isn't expanded
+  /// it will be passed through for target lowering.
+  virtual bool shouldExpandAtomicToLibCall(unsigned Size, unsigned Align,
+                                           Instruction *I) const {
+    return Align < Size || Size > getMaxAtomicSizeInBitsSupported() / 8;
+  }
+
   /// Returns the size of the smallest cmpxchg or ll/sc instruction
   /// the backend supports.  Any smaller operations are widened in
   /// AtomicExpandPass.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D47553.149187.patch
Type: text/x-patch
Size: 3539 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180530/afafe0f7/attachment.bin>


More information about the llvm-commits mailing list