gollvm: reduce compiler-generated const var duplication

At certain points during LLVM IR generation it is necessary to create
a variable to hold an anonymous LLVM constant (for example, if the
constant is an operand of a memcpy call). The helper method for
creating such vars was written to try to avoid creating duplicates
(same contents), but the commoning code was not doing the lookup
correctly. The lookup table key needs to be the constant value, not
the value associated with the resulting global variable (which
incorporates a name); this change fixes the duplicate check to use a
separate lookup table.

Change-Id: Iaa4075fd5d37889997d772f4bff1673d11cf01a8
Reviewed-on: https://go-review.googlesource.com/82175
Reviewed-by: Cherry Zhang <cherryyz@google.com>
diff --git a/llvm-gofrontend/go-llvm.cpp b/llvm-gofrontend/go-llvm.cpp
index 49535d0..553c75c 100644
--- a/llvm-gofrontend/go-llvm.cpp
+++ b/llvm-gofrontend/go-llvm.cpp
@@ -670,8 +670,8 @@
 Bvariable *Llvm_backend::genVarForConstant(llvm::Constant *conval,
                                            Btype *type)
 {
-  auto it = valueVarMap_.find(conval);
-  if (it != valueVarMap_.end())
+  auto it = genVarConstMap_.find(conval);
+  if (it != genVarConstMap_.end())
     return it->second;
 
   std::string ctag(namegen("const"));
@@ -682,6 +682,7 @@
                                 llvm::GlobalValue::PrivateLinkage,
                                 conval, 0);
   assert(llvm::isa<llvm::GlobalVariable>(rv->value()));
+  genVarConstMap_[conval] = rv;
   return rv;
 }
 
diff --git a/llvm-gofrontend/go-llvm.h b/llvm-gofrontend/go-llvm.h
index 03f682c..fcbfbde 100644
--- a/llvm-gofrontend/go-llvm.h
+++ b/llvm-gofrontend/go-llvm.h
@@ -778,6 +778,10 @@
   // module-scope variables, not vars local to a function.
   std::unordered_map<llvm::Value *, Bvariable *> valueVarMap_;
 
+  // This is used to cache compiler-constructed vars to capture
+  // constant values (created in genVarForConstant).
+  std::unordered_map<llvm::Value *, Bvariable *> genVarConstMap_;
+
   // Table for commoning strings by value. String constants have
   // concrete types like "[5 x i8]", whereas we would like to return
   // things that have type "i8*". To manage this, we eagerly create
diff --git a/unittests/BackendCore/BackendArrayStruct.cpp b/unittests/BackendCore/BackendArrayStruct.cpp
index 42b043c..8ae8dec 100644
--- a/unittests/BackendCore/BackendArrayStruct.cpp
+++ b/unittests/BackendCore/BackendArrayStruct.cpp
@@ -725,17 +725,17 @@
   h.mkAssign(ve3, ve4);
 
   const char *exp = R"RAW_RESULT(
-  %cast.0 = bitcast { i8* }* %x1 to i8*
+%cast.0 = bitcast { i8* }* %x1 to i8*
   %cast.1 = bitcast { i8* }* @const.0 to i8*
   call void @llvm.memcpy.p0i8.p0i8.i64(i8* %cast.0, i8* %cast.1, i64 8, i32 8, i1 false)
   %cast.2 = bitcast { i8* }* %y1 to i8*
-  %cast.3 = bitcast { i8* }* @const.1 to i8*
+  %cast.3 = bitcast { i8* }* @const.0 to i8*
   call void @llvm.memcpy.p0i8.p0i8.i64(i8* %cast.2, i8* %cast.3, i64 8, i32 8, i1 false)
   %cast.4 = bitcast { i64, i64, i64, i64, i64, i64 }* %x2 to i8*
-  %cast.5 = bitcast { i64, i64, i64, i64, i64, i64 }* @const.2 to i8*
+  %cast.5 = bitcast { i64, i64, i64, i64, i64, i64 }* @const.1 to i8*
   call void @llvm.memcpy.p0i8.p0i8.i64(i8* %cast.4, i8* %cast.5, i64 48, i32 8, i1 false)
   %cast.6 = bitcast { i64, i64, i64, i64, i64, i64 }* %y2 to i8*
-  %cast.7 = bitcast { i64, i64, i64, i64, i64, i64 }* @const.3 to i8*
+  %cast.7 = bitcast { i64, i64, i64, i64, i64, i64 }* @const.1 to i8*
   call void @llvm.memcpy.p0i8.p0i8.i64(i8* %cast.6, i8* %cast.7, i64 48, i32 8, i1 false)
   %cast.8 = bitcast { i8* }* %x1 to i8*
   %cast.9 = bitcast { i8* }* %y1 to i8*
diff --git a/unittests/BackendCore/BackendExprTests.cpp b/unittests/BackendCore/BackendExprTests.cpp
index 92b53c5..bc30870 100644
--- a/unittests/BackendCore/BackendExprTests.cpp
+++ b/unittests/BackendCore/BackendExprTests.cpp
@@ -494,13 +494,13 @@
   %cast.1 = bitcast { float, float }* @const.0 to i8*
   call void @llvm.memcpy.p0i8.p0i8.i64(i8* %cast.0, i8* %cast.1, i64 8, i32 4, i1 false)
   %cast.2 = bitcast { float, float }* %b to i8*
-  %cast.3 = bitcast { float, float }* @const.1 to i8*
+  %cast.3 = bitcast { float, float }* @const.0 to i8*
   call void @llvm.memcpy.p0i8.p0i8.i64(i8* %cast.2, i8* %cast.3, i64 8, i32 4, i1 false)
   %cast.4 = bitcast { double, double }* %x to i8*
-  %cast.5 = bitcast { double, double }* @const.2 to i8*
+  %cast.5 = bitcast { double, double }* @const.1 to i8*
   call void @llvm.memcpy.p0i8.p0i8.i64(i8* %cast.4, i8* %cast.5, i64 16, i32 8, i1 false)
   %cast.6 = bitcast { double, double }* %y to i8*
-  %cast.7 = bitcast { double, double }* @const.3 to i8*
+  %cast.7 = bitcast { double, double }* @const.1 to i8*
   call void @llvm.memcpy.p0i8.p0i8.i64(i8* %cast.6, i8* %cast.7, i64 16, i32 8, i1 false)
   %cast.8 = bitcast { double, double }* %tmp.0 to i8*
   %cast.9 = bitcast { double, double }* %x to i8*
@@ -1080,10 +1080,10 @@
     %cast.1 = bitcast { double, double }* @const.0 to i8*
     call void @llvm.memcpy.p0i8.p0i8.i64(i8* %cast.0, i8* %cast.1, i64 16, i32 8, i1 false)
     %cast.2 = bitcast { double, double }* %y to i8*
-    %cast.3 = bitcast { double, double }* @const.1 to i8*
+    %cast.3 = bitcast { double, double }* @const.0 to i8*
     call void @llvm.memcpy.p0i8.p0i8.i64(i8* %cast.2, i8* %cast.3, i64 16, i32 8, i1 false)
     %cast.4 = bitcast { double, double }* %z to i8*
-    %cast.5 = bitcast { double, double }* @const.2 to i8*
+    %cast.5 = bitcast { double, double }* @const.0 to i8*
     call void @llvm.memcpy.p0i8.p0i8.i64(i8* %cast.4, i8* %cast.5, i64 16, i32 8, i1 false)
     store i8 0, i8* %b
     %cast.6 = bitcast { double, double }* %tmp.0 to i8*