]> granicus.if.org Git - llvm/commitdiff
DivergencyAnalysis patch for review
authorAlexander Timofeev <Alexander.Timofeev@amd.com>
Thu, 15 Jun 2017 19:33:10 +0000 (19:33 +0000)
committerAlexander Timofeev <Alexander.Timofeev@amd.com>
Thu, 15 Jun 2017 19:33:10 +0000 (19:33 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@305494 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Analysis/TargetTransformInfo.h
include/llvm/Analysis/TargetTransformInfoImpl.h
include/llvm/CodeGen/BasicTTIImpl.h
lib/Analysis/DivergenceAnalysis.cpp
lib/Analysis/TargetTransformInfo.cpp
lib/Target/AMDGPU/AMDGPUAnnotateUniformValues.cpp
lib/Target/AMDGPU/AMDGPUTargetTransformInfo.cpp
lib/Target/AMDGPU/AMDGPUTargetTransformInfo.h
test/CodeGen/AMDGPU/always-uniform.ll [new file with mode: 0644]
test/CodeGen/AMDGPU/global_smrd_cfg.ll

index 471b8640cf7372fa26ec6b2e1b4f7063645af976..af2ebb7b6b44f72892a68bce541019ccd314a8a8 100644 (file)
@@ -235,6 +235,11 @@ public:
   /// starting with the sources of divergence.
   bool isSourceOfDivergence(const Value *V) const;
 
+  // \brief Returns true for the target specific
+  // set of operations which produce uniform result
+  // even taking non-unform arguments
+  bool isAlwaysUniform(const Value *V) const;
+
   /// Returns the address space ID for a target's 'flat' address space. Note
   /// this is not necessarily the same as addrspace(0), which LLVM sometimes
   /// refers to as the generic address space. The flat address space is a
@@ -821,6 +826,7 @@ public:
   virtual int getUserCost(const User *U) = 0;
   virtual bool hasBranchDivergence() = 0;
   virtual bool isSourceOfDivergence(const Value *V) = 0;
+  virtual bool isAlwaysUniform(const Value *V) = 0;
   virtual unsigned getFlatAddressSpace() = 0;
   virtual bool isLoweredToCall(const Function *F) = 0;
   virtual void getUnrollingPreferences(Loop *L, UnrollingPreferences &UP) = 0;
@@ -998,6 +1004,10 @@ public:
     return Impl.isSourceOfDivergence(V);
   }
 
+  bool isAlwaysUniform(const Value *V) override {
+    return Impl.isAlwaysUniform(V);
+  }
+
   unsigned getFlatAddressSpace() override {
     return Impl.getFlatAddressSpace();
   }
index 7884ffe8cc226db76d957398231ac64293fbd341..24ac3b1213e160cdf7c465b08a7d20955ce6832d 100644 (file)
@@ -177,6 +177,8 @@ public:
 
   bool isSourceOfDivergence(const Value *V) { return false; }
 
+  bool isAlwaysUniform(const Value *V) { return false; }
+
   unsigned getFlatAddressSpace () {
     return -1;
   }
index 75277cddcfe8fe01109916dc91d6163fda5228a5..5eb7a0f61eec4588fe47899d3674f6402aaf3f28 100644 (file)
@@ -93,6 +93,8 @@ public:
 
   bool isSourceOfDivergence(const Value *V) { return false; }
 
+  bool isAlwaysUniform(const Value *V) { return false; }
+
   unsigned getFlatAddressSpace() {
     // Return an invalid address space.
     return -1;
index 1b36569f7a07c9075a08aabf4299d04d53b5ae7c..2d39a0b021500abe0f7b1ba469a1e3cdd68bd191 100644 (file)
@@ -241,7 +241,7 @@ void DivergencePropagator::exploreDataDependency(Value *V) {
   // Follow def-use chains of V.
   for (User *U : V->users()) {
     Instruction *UserInst = cast<Instruction>(U);
-    if (DV.insert(UserInst).second)
+    if (!TTI.isAlwaysUniform(U) && DV.insert(UserInst).second)
       Worklist.push_back(UserInst);
   }
 }
index 488cb332a0b0ed109aa06a6691b6e11128b0016a..92328f6e5efd58db4d17c389e38fdada793d32b3 100644 (file)
@@ -103,6 +103,10 @@ bool TargetTransformInfo::isSourceOfDivergence(const Value *V) const {
   return TTIImpl->isSourceOfDivergence(V);
 }
 
+bool llvm::TargetTransformInfo::isAlwaysUniform(const Value *V) const {
+  return TTIImpl->isAlwaysUniform(V);
+}
+
 unsigned TargetTransformInfo::getFlatAddressSpace() const {
   return TTIImpl->getFlatAddressSpace();
 }
index 3c788fa1dceadb00e7c71490bcf4542a31b512b1..6f002860044c007ed747a5c46af67fe1d2998baf 100644 (file)
@@ -107,7 +107,7 @@ bool AMDGPUAnnotateUniformValues::isClobberedInFunction(LoadInst * Load) {
 
   DFS(Start, Checklist);
   for (auto &BB : Checklist) {
-    BasicBlock::iterator StartIt = (BB == Load->getParent()) ?
+    BasicBlock::iterator StartIt = (!L && (BB == Load->getParent())) ?
      BasicBlock::iterator(Load) : BB->end();
      if (MDR->getPointerDependencyFrom(MemoryLocation(Ptr),
        true, StartIt, BB, Load).isClobber())
index 65dba7d6055fbd97b58930f8fc7be94cfb0c7941..0d6689bd04c4e2248c6e27cac9454db3e115b2a7 100644 (file)
@@ -489,6 +489,19 @@ bool AMDGPUTTIImpl::isSourceOfDivergence(const Value *V) const {
   return false;
 }
 
+bool AMDGPUTTIImpl::isAlwaysUniform(const Value *V) const {
+  if (const IntrinsicInst *Intrinsic = dyn_cast<IntrinsicInst>(V)) {
+    switch (Intrinsic->getIntrinsicID()) {
+    default:
+      return false;
+    case Intrinsic::amdgcn_readfirstlane:
+    case Intrinsic::amdgcn_readlane:
+      return true;
+    }
+  }
+  return false;
+}
+
 unsigned AMDGPUTTIImpl::getShuffleCost(TTI::ShuffleKind Kind, Type *Tp, int Index,
                                        Type *SubTp) {
   if (ST->hasVOP3PInsts()) {
index 8466f11839504f2743cd906566009a3bcaf3fd87..a60b1bb1b59c70713c7776bae235bd45bc3bc9d1 100644 (file)
@@ -103,6 +103,7 @@ public:
 
   int getVectorInstrCost(unsigned Opcode, Type *ValTy, unsigned Index);
   bool isSourceOfDivergence(const Value *V) const;
+  bool isAlwaysUniform(const Value *V) const;
 
   unsigned getFlatAddressSpace() const {
     // Don't bother running InferAddressSpaces pass on graphics shaders which
diff --git a/test/CodeGen/AMDGPU/always-uniform.ll b/test/CodeGen/AMDGPU/always-uniform.ll
new file mode 100644 (file)
index 0000000..4ba57fb
--- /dev/null
@@ -0,0 +1,21 @@
+; RUN: llc -mtriple amdgcn-amdhsa -mcpu=fiji -amdgpu-scalarize-global-loads -verify-machineinstrs < %s | FileCheck -check-prefix=GCN %s
+
+declare i32 @llvm.amdgcn.workitem.id.x()
+declare i32 @llvm.amdgcn.readfirstlane(i32)
+
+; GCN-LABEL: readfirstlane_uniform
+; GCN:         s_load_dwordx2 s{{\[}}[[IN_ADDR:[0-9]+]]:1{{\]}}, s[4:5], 0x0
+; GCN:  v_readfirstlane_b32 s[[SCALAR:[0-9]+]], v0
+; GCN:         s_add_u32 s[[LOAD_ADDR:[0-9]+]], s[[IN_ADDR]], s[[SCALAR]]
+; GCN: s_load_dword s{{[0-9]+}}, s{{\[}}[[LOAD_ADDR]]
+
+define amdgpu_kernel void @readfirstlane_uniform(float addrspace(1)* noalias nocapture readonly, float addrspace(1)* noalias nocapture readonly) {
+  %tid = tail call i32 @llvm.amdgcn.workitem.id.x()
+  %scalar = tail call i32 @llvm.amdgcn.readfirstlane(i32 %tid)
+  %idx = zext i32 %scalar to i64
+  %gep0 = getelementptr inbounds float, float addrspace(1)* %0, i64 %idx
+  %val = load float, float addrspace(1)* %gep0, align 4
+  %gep1 = getelementptr inbounds float, float addrspace(1)* %1, i64 10
+  store float %val, float addrspace(1)* %gep1, align 4
+  ret void
+}
index a6a04151caa9892f54c4e70f267db0365ff07ce7..be6e3fd05ae7317859c8deb2b33dc938e0c3db99 100644 (file)
@@ -72,6 +72,39 @@ bb22:                                             ; preds = %bb20, %bb11
   br i1 %tmp31, label %bb7, label %bb11
 }
 
+; one more test to ensure that aliasing store after the load
+; is considered clobbering if load parent block is the same 
+; as a loop header block.
+
+; CHECK-LABEL: %bb1
+
+; Load from %arg has alias store that is after the load 
+; but is considered clobbering because of the loop.
+
+; CHECK: flat_load_dword
+
+define amdgpu_kernel void @cfg_selfloop(i32 addrspace(1)* nocapture readonly %arg, i32 addrspace(1)* nocapture %arg1, i32 %arg2) #0 {
+bb:
+  br label %bb1
+
+bb2:
+  ret void
+
+bb1:
+  %tmp13 = phi i32 [ %tmp25, %bb1 ], [ 0, %bb ]
+  %tmp14 = srem i32 %tmp13, %arg2
+  %tmp15 = sext i32 %tmp14 to i64
+  %tmp16 = getelementptr inbounds i32, i32 addrspace(1)* %arg, i64 %tmp15
+  %tmp17 = load i32, i32 addrspace(1)* %tmp16, align 4, !tbaa !0
+  %tmp19 = sext i32 %tmp13 to i64
+  %tmp21 = getelementptr inbounds i32, i32 addrspace(1)* %arg1, i64 %tmp19
+  store i32 %tmp17, i32 addrspace(1)* %tmp21, align 4, !tbaa !0
+  %tmp25 = add nuw nsw i32 %tmp13, 1
+  %tmp31 = icmp eq i32 %tmp25, 100
+  br i1 %tmp31, label %bb2, label %bb1
+}
+
+
 attributes #0 = { "target-cpu"="fiji" }
 
 !0 = !{!1, !1, i64 0}