From d3939c80f8d11896c4c74da5dddd66b1be04f2de Mon Sep 17 00:00:00 2001 From: Nicolai Haehnle Date: Thu, 17 Mar 2016 16:21:59 +0000 Subject: [PATCH] AMDGPU: mark atomic instructions as sources of divergence Summary: As explained by the comment, threads will typically see different values returned by atomic instructions even if the arguments are equal. Reviewers: arsenm, tstellarAMD Subscribers: arsenm, llvm-commits Differential Revision: http://reviews.llvm.org/D18156 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@263719 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/AMDGPU/AMDGPUTargetTransformInfo.cpp | 7 +++++++ .../Analysis/DivergenceAnalysis/AMDGPU/atomics.ll | 15 +++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 test/Analysis/DivergenceAnalysis/AMDGPU/atomics.ll diff --git a/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.cpp b/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.cpp index 540ca5f399f..ff5558bf4db 100644 --- a/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.cpp +++ b/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.cpp @@ -186,6 +186,13 @@ bool AMDGPUTTIImpl::isSourceOfDivergence(const Value *V) const { if (const LoadInst *Load = dyn_cast(V)) return Load->getPointerAddressSpace() == AMDGPUAS::PRIVATE_ADDRESS; + // Atomics are divergent because they are executed sequentially: when an + // atomic operation refers to the same address in each thread, then each + // thread after the first sees the value written by the previous thread as + // original value. + if (isa(V) || isa(V)) + return true; + if (const IntrinsicInst *Intrinsic = dyn_cast(V)) { const TargetMachine &TM = getTLI()->getTargetMachine(); return isIntrinsicSourceOfDivergence(TM.getIntrinsicInfo(), Intrinsic); diff --git a/test/Analysis/DivergenceAnalysis/AMDGPU/atomics.ll b/test/Analysis/DivergenceAnalysis/AMDGPU/atomics.ll new file mode 100644 index 00000000000..60d0de6035b --- /dev/null +++ b/test/Analysis/DivergenceAnalysis/AMDGPU/atomics.ll @@ -0,0 +1,15 @@ +; RUN: opt -mtriple=amdgcn-- -analyze -divergence %s | FileCheck %s + +; CHECK: DIVERGENT: %orig = atomicrmw xchg i32* %ptr, i32 %val seq_cst +define i32 @test1(i32* %ptr, i32 %val) #0 { + %orig = atomicrmw xchg i32* %ptr, i32 %val seq_cst + ret i32 %orig +} + +; CHECK: DIVERGENT: %orig = cmpxchg i32* %ptr, i32 %cmp, i32 %new seq_cst seq_cst +define {i32, i1} @test2(i32* %ptr, i32 %cmp, i32 %new) { + %orig = cmpxchg i32* %ptr, i32 %cmp, i32 %new seq_cst seq_cst + ret {i32, i1} %orig +} + +attributes #0 = { "ShaderType"="0" }