[llvm] r326390 - [NVPTX] Lower loads from global constants using ld.global.nc (aka LDG).

Justin Lebar via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 28 15:58:05 PST 2018


Author: jlebar
Date: Wed Feb 28 15:58:05 2018
New Revision: 326390

URL: http://llvm.org/viewvc/llvm-project?rev=326390&view=rev
Log:
[NVPTX] Lower loads from global constants using ld.global.nc (aka LDG).

Summary:
After D43914, loads from global variables in addrspace(1) happen with
ld.global.  But since they're constants, even better would be to use
ld.global.nc, aka ldg.

Reviewers: tra

Subscribers: jholewinski, sanjoy, hiraditya, llvm-commits

Differential Revision: https://reviews.llvm.org/D43915

Added:
    llvm/trunk/test/CodeGen/NVPTX/read-global-variable-constant.ll
Modified:
    llvm/trunk/lib/Target/NVPTX/NVPTXISelDAGToDAG.cpp

Modified: llvm/trunk/lib/Target/NVPTX/NVPTXISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/NVPTX/NVPTXISelDAGToDAG.cpp?rev=326390&r1=326389&r2=326390&view=diff
==============================================================================
--- llvm/trunk/lib/Target/NVPTX/NVPTXISelDAGToDAG.cpp (original)
+++ llvm/trunk/lib/Target/NVPTX/NVPTXISelDAGToDAG.cpp Wed Feb 28 15:58:05 2018
@@ -987,8 +987,10 @@ static bool canLowerToLDG(MemSDNode *N,
   // We have two ways of identifying invariant loads: Loads may be explicitly
   // marked as invariant, or we may infer them to be invariant.
   //
-  // We currently infer invariance only for kernel function pointer params that
-  // are noalias (i.e. __restrict) and never written to.
+  // We currently infer invariance for loads from
+  //  - constant global variables, and
+  //  - kernel function pointer params that are noalias (i.e. __restrict) and
+  //    never written to.
   //
   // TODO: Perform a more powerful invariance analysis (ideally IPO, and ideally
   // not during the SelectionDAG phase).
@@ -1002,23 +1004,22 @@ static bool canLowerToLDG(MemSDNode *N,
   if (N->isInvariant())
     return true;
 
-  // Load wasn't explicitly invariant.  Attempt to infer invariance.
-  if (!isKernelFunction(F->getFunction()))
-    return false;
+  bool IsKernelFn = isKernelFunction(F->getFunction());
 
-  // We use GetUnderlyingObjects() here instead of
-  // GetUnderlyingObject() mainly because the former looks through phi
-  // nodes while the latter does not. We need to look through phi
-  // nodes to handle pointer induction variables.
+  // We use GetUnderlyingObjects() here instead of GetUnderlyingObject() mainly
+  // because the former looks through phi nodes while the latter does not. We
+  // need to look through phi nodes to handle pointer induction variables.
   SmallVector<Value *, 8> Objs;
   GetUnderlyingObjects(const_cast<Value *>(N->getMemOperand()->getValue()),
                        Objs, F->getDataLayout());
-  for (Value *Obj : Objs) {
-    auto *A = dyn_cast<const Argument>(Obj);
-    if (!A || !A->onlyReadsMemory() || !A->hasNoAliasAttr()) return false;
-  }
 
-  return true;
+  return all_of(Objs, [&](Value *V) {
+    if (auto *A = dyn_cast<const Argument>(V))
+      return IsKernelFn && A->onlyReadsMemory() && A->hasNoAliasAttr();
+    if (auto *GV = dyn_cast<const GlobalVariable>(V))
+      return GV->isConstant();
+    return false;
+  });
 }
 
 bool NVPTXDAGToDAGISel::tryIntrinsicNoChain(SDNode *N) {
@@ -1632,6 +1633,7 @@ bool NVPTXDAGToDAGISel::tryLDGLDU(SDNode
     switch (N->getOpcode()) {
     default:
       return false;
+    case ISD::LOAD:
     case ISD::INTRINSIC_W_CHAIN:
       if (IsLDG)
         Opcode = pickOpcodeForVT(EltVT.getSimpleVT().SimpleTy,
@@ -1654,6 +1656,7 @@ bool NVPTXDAGToDAGISel::tryLDGLDU(SDNode
                                      NVPTX::INT_PTX_LDU_GLOBAL_f32avar,
                                      NVPTX::INT_PTX_LDU_GLOBAL_f64avar);
       break;
+    case NVPTXISD::LoadV2:
     case NVPTXISD::LDGV2:
       Opcode = pickOpcodeForVT(EltVT.getSimpleVT().SimpleTy,
                                    NVPTX::INT_PTX_LDG_G_v2i8_ELE_avar,
@@ -1676,6 +1679,7 @@ bool NVPTXDAGToDAGISel::tryLDGLDU(SDNode
                                    NVPTX::INT_PTX_LDU_G_v2f32_ELE_avar,
                                    NVPTX::INT_PTX_LDU_G_v2f64_ELE_avar);
       break;
+    case NVPTXISD::LoadV4:
     case NVPTXISD::LDGV4:
       Opcode = pickOpcodeForVT(EltVT.getSimpleVT().SimpleTy,
                                NVPTX::INT_PTX_LDG_G_v4i8_ELE_avar,

Added: llvm/trunk/test/CodeGen/NVPTX/read-global-variable-constant.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/NVPTX/read-global-variable-constant.ll?rev=326390&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/NVPTX/read-global-variable-constant.ll (added)
+++ llvm/trunk/test/CodeGen/NVPTX/read-global-variable-constant.ll Wed Feb 28 15:58:05 2018
@@ -0,0 +1,29 @@
+; RUN: llc < %s -march=nvptx -mcpu=sm_35 | FileCheck %s
+
+; Check load from constant global variables.  These loads should be
+; ld.global.nc (aka ldg).
+
+ at gv_float = external constant float
+ at gv_float2 = external constant <2 x float>
+ at gv_float4 = external constant <4 x float>
+
+; CHECK-LABEL: test_gv_float()
+define float @test_gv_float() {
+; CHECK: ld.global.nc.f32
+  %v = load float, float* @gv_float
+  ret float %v
+}
+
+; CHECK-LABEL: test_gv_float2()
+define <2 x float> @test_gv_float2() {
+; CHECK: ld.global.nc.v2.f32
+  %v = load <2 x float>, <2 x float>* @gv_float2
+  ret <2 x float> %v
+}
+
+; CHECK-LABEL: test_gv_float4()
+define <4 x float> @test_gv_float4() {
+; CHECK: ld.global.nc.v4.f32
+  %v = load <4 x float>, <4 x float>* @gv_float4
+  ret <4 x float> %v
+}




More information about the llvm-commits mailing list