Use direct-resource-access for workgroup and module-scope variables

Changing how workgroup vars are generated

* Generate new intrinsic functions when descriptors are allocated for
workgroup variables
 * assigns spec ids then
* Apply DRA to workgroup variables

Fixed up first part of change.

* Generates workgroup variables based on allocations in
AllocateResourceDescriptors
* accessor function codegen'd as access chain instead of implicit
generation

Don't access null pointer

* Return early if the local SpecId metadata does not exist

Enable DRA on local vars

* Works, but still end up with two access chains because of how I
codegen

Reworked codegen of workgroup accessors

* Now the accessor function returns the full type of the variable
(pointer to array) and an appropriate gep is generated with it in
AllocateResourceDescriptors
* Accessor function is codegen'd in SPIR-V as an OpCopyObject of the
variable
* DirectResourceAccess collapses the geps so that they can produce a
simple access chain
* Passes ClspvTest for local memory without combine-access-chains

Don't generate OpCopyObject

* Instead just map the workgroup accessor call to the workgroup variable
id

Avoid generating unnecessary runtime array types

* improved comments
* removed dead code
* changed type generation to avoid generating types for the return of
the workgroup accessor function type

Updated tests

Enabled sharing of ptr-to-local SpecIds

* AllocateDescriptorsPass now shares SpecIds for pointer-to-local args
in different kernels if they share a type
* Modified the SPIR-V producer to track the updated way that spec ids
are assigned
* Updated a few tests
 * DRA/local_arg now generates a direct access to a single workgroup
 variable
* Removed some debug output from DRA

Apply DRA to global variables

* Handle global variables in DRA
* updated a couple tests and added a new one
diff --git a/lib/DirectResourceAccessPass.cpp b/lib/DirectResourceAccessPass.cpp
index ab1f267..04dd0b5 100644
--- a/lib/DirectResourceAccessPass.cpp
+++ b/lib/DirectResourceAccessPass.cpp
@@ -34,6 +34,7 @@
 #include "clspv/Passes.h"
 
 #include "ArgKind.h"
+#include "Constants.h"
 
 using namespace llvm;
 
@@ -192,6 +193,7 @@
     case clspv::ArgKind::ReadOnlyImage:
     case clspv::ArgKind::WriteOnlyImage:
     case clspv::ArgKind::Sampler:
+    case clspv::ArgKind::Local:
       Changed |= RewriteAccessesForArg(fn, arg_index, arg);
       break;
     default:
@@ -215,8 +217,9 @@
   // either a direct call to a clspv.resource.var.* or if it a GEP of
   // such a thing (where the GEP can only have zero indices).
   struct ParamInfo {
-    // The resource-access builtin function.  (@clspv.resource.var.*)
-    Function *var_fn;
+    // The base value. It is either a global variable or a resource-access
+    // builtin function. (@clspv.resource.var.* or @clspv.local.var.*)
+    Value *base;
     // The descriptor set.
     uint32_t set;
     // The binding.
@@ -239,7 +242,7 @@
       seen_one = true;
       return true;
     }
-    return pi.var_fn == common.var_fn && pi.set == common.set &&
+    return pi.base == common.base && pi.set == common.set &&
            pi.binding == common.binding &&
            pi.num_gep_zeroes == common.num_gep_zeroes;
   };
@@ -270,19 +273,28 @@
         // If the call is a call to a @clspv.resource.var.* function, then try
         // to merge it, assuming the given number of GEP zero-indices so far.
         if (call->getCalledFunction()->getName().startswith(
-                "clspv.resource.var.")) {
+                clspv::ResourceAccessorFunction())) {
           const auto set = uint32_t(
               dyn_cast<ConstantInt>(call->getOperand(0))->getZExtValue());
           const auto binding = uint32_t(
               dyn_cast<ConstantInt>(call->getOperand(1))->getZExtValue());
           if (!merge_param_info({call->getCalledFunction(), set, binding,
-                                 num_gep_zeroes, call})) {
+                                 num_gep_zeroes, call}))
             return false;
-          }
+        } else if (call->getCalledFunction()->getName().startswith(
+                      clspv::WorkgroupAccessorFunction())) {
+          const uint32_t spec_id = uint32_t(
+              dyn_cast<ConstantInt>(call->getOperand(0))->getZExtValue());
+          if (!merge_param_info({call->getCalledFunction(), spec_id, 0,
+                                 num_gep_zeroes, call}))
+            return false;
         } else {
           // A call but not to a resource access builtin function.
           return false;
         }
+      } else if (isa<GlobalValue>(value)) {
+        if (!merge_param_info({value, 0, 0, num_gep_zeroes, nullptr}))
+          return false;
       } else {
         // Not a call.
         return false;
@@ -295,7 +307,7 @@
   if (ShowDRA) {
     if (seen_one) {
       outs() << "DRA:  Rewrite " << fn->getName() << " arg " << arg_index << " "
-             << arg.getName() << ": " << common.var_fn->getName() << " ("
+             << arg.getName() << ": " << common.base->getName() << " ("
              << common.set << "," << common.binding
              << ") zeroes: " << common.num_gep_zeroes << " sample-call "
              << *(common.sample_call) << "\n";
@@ -309,19 +321,25 @@
   auto *zero = Builder.getInt32(0);
   Builder.SetInsertPoint(fn->getEntryBlock().getFirstNonPHI());
 
-  // Create the call.
-  SmallVector<Value *, 8> args(common.sample_call->arg_begin(),
-                               common.sample_call->arg_end());
-  Value *replacement = Builder.CreateCall(common.var_fn, args);
-  if (ShowDRA) {
-    outs() << "DRA:    Replace: call " << *replacement << "\n";
+  Value *replacement = common.base;
+  if (Function* function = dyn_cast<Function>(replacement)) {
+    // Create the call.
+    SmallVector<Value *, 8> args(common.sample_call->arg_begin(),
+                                 common.sample_call->arg_end());
+    replacement = Builder.CreateCall(function, args);
+    if (ShowDRA) {
+      outs() << "DRA:    Replace: call " << *replacement << "\n";
+    }
   }
   if (common.num_gep_zeroes) {
     SmallVector<Value *, 3> zeroes;
     for (unsigned i = 0; i < common.num_gep_zeroes; i++) {
       zeroes.push_back(zero);
     }
-    replacement = Builder.CreateGEP(replacement, zeroes);
+    // Builder.CreateGEP is not used to avoid creating a GEPConstantExpr in the
+    // case of global variables.
+    replacement = GetElementPtrInst::Create(nullptr, replacement, zeroes);
+    Builder.Insert(cast<Instruction>(replacement));
     if (ShowDRA) {
       outs() << "DRA:    Replace: gep  " << *replacement << "\n";
     }