This is an archive of the discontinued LLVM Phabricator instance.

[RFC][Clang] Add a check if the target supports atomicrmw instruction with specific operator and type
AbandonedPublic

Authored by tianshilei1992 on May 10 2022, 8:22 PM.

Details

Reviewers
jdoerfert
ABataev
Summary

With respect of atomicrmw instruction, different targets have different
backend support. The front end can always emit the intruction, but when it comes
to the backend, the compiler could crash at instruction selection because the
target doesn't support the instruction/operator at all. Currently we don't have
a way in the front end to tell if an atomicrmw with specific operator and type
is supported. This patch adds a virtual function hasAtomicrmw to the class
TargetInfo and it is expected to be implemented by all targets accordingly.
In this way, we can always try to emit atomicrmw first because it has better
performance than falling back to CAS loop. Currently at the PoC stage, I only make
it in NVPTX, but if the community is happy with this change, I'll add to all the
targets.

For the long term, I'll seek a way to expand the instruction if the target doesn't
support it, probably similar to things in llvm/lib/CodeGen/AtomicExpandPass.cpp.

Diff Detail

Event Timeline

tianshilei1992 created this revision.May 10 2022, 8:22 PM
tianshilei1992 requested review of this revision.May 10 2022, 8:22 PM
Herald added a project: Restricted Project. · View Herald TranscriptMay 10 2022, 8:22 PM
Herald added a subscriber: cfe-commits. · View Herald Transcript

Feel free to add more reviewers

tianshilei1992 added inline comments.May 10 2022, 8:24 PM
clang/lib/Basic/Targets/NVPTX.cpp
311

llvm_unreachable might be more appropriate here.

tianshilei1992 retitled this revision from [PoC][Clang] Add a check if the target supports atomicrmw instruction with specific operator and type to [RFC][Clang] Add a check if the target supports atomicrmw instruction with specific operator and type.May 10 2022, 8:25 PM
tianshilei1992 added a comment.EditedMay 10 2022, 8:31 PM

As for the test, here is a simple code snippet:

#pragma omp begin declare target device_type(nohost)
void foo() {
  double x, y;
#pragma omp atomic update
  x += y;
}
#pragma omp end declare target

sm_35 doesn't support FAdd with double type, then it emits:

define protected void @foo() #0 {
entry:
  %x = alloca double, align 8
  %y = alloca double, align 8
  %atomic-temp = alloca double, align 8
  %0 = load double, ptr %y, align 8
  %atomic-load = load atomic i64, ptr %x monotonic, align 8
  br label %atomic_cont

atomic_cont:                                      ; preds = %atomic_cont, %entry
  %1 = phi i64 [ %atomic-load, %entry ], [ %5, %atomic_cont ]
  %2 = bitcast i64 %1 to double
  %add = fadd double %2, %0
  store double %add, ptr %atomic-temp, align 8
  %3 = load i64, ptr %atomic-temp, align 8
  %4 = cmpxchg ptr %x, i64 %1, i64 %3 monotonic monotonic, align 8
  %5 = extractvalue { i64, i1 } %4, 0
  %6 = extractvalue { i64, i1 } %4, 1
  br i1 %6, label %atomic_exit, label %atomic_cont

atomic_exit:                                      ; preds = %atomic_cont
  ret void
}

Starting from sm_60, it is supported, now we get:

define protected void @foo() #0 {
entry:
  %x = alloca double, align 8
  %y = alloca double, align 8
  %0 = load double, ptr %y, align 8
  %1 = atomicrmw fadd ptr %x, double %0 monotonic, align 8
  ret void
}
tianshilei1992 edited the summary of this revision. (Show Details)May 10 2022, 8:38 PM
tianshilei1992 abandoned this revision.May 20 2022, 2:36 PM

Do it in BE.