From 4bbdebc49a9853461322cf3e9911f16f06a2ac3b Mon Sep 17 00:00:00 2001
From: Yaxun Liu <Yaxun.Liu@amd.com>
Date: Thu, 8 Nov 2018 16:55:46 +0000
Subject: [PATCH] Fix bitcast to address space cast for coerced load/stores

Coerced load/stores through memory do not take into account potential
address space differences when it creates its bitcasts.

Patch by David Salinas.

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

llvm-svn: 346413
---
 clang/lib/CodeGen/CGCall.cpp                  |  8 +--
 .../CodeGenCXX/address-space-cast-coerce.cpp  | 53 +++++++++++++++++++
 2 files changed, 57 insertions(+), 4 deletions(-)
 create mode 100644 clang/test/CodeGenCXX/address-space-cast-coerce.cpp

diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index cf6aec0ff243..4237d3d39166 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -1253,8 +1253,8 @@ static llvm::Value *CreateCoercedLoad(Address Src, llvm::Type *Ty,
 
   // Otherwise do coercion through memory. This is stupid, but simple.
   Address Tmp = CreateTempAllocaForCoercion(CGF, Ty, Src.getAlignment());
-  Address Casted = CGF.Builder.CreateBitCast(Tmp, CGF.AllocaInt8PtrTy);
-  Address SrcCasted = CGF.Builder.CreateBitCast(Src, CGF.AllocaInt8PtrTy);
+  Address Casted = CGF.Builder.CreateElementBitCast(Tmp,CGF.Int8Ty);
+  Address SrcCasted = CGF.Builder.CreateElementBitCast(Src,CGF.Int8Ty);
   CGF.Builder.CreateMemCpy(Casted, SrcCasted,
       llvm::ConstantInt::get(CGF.IntPtrTy, SrcSize),
       false);
@@ -1335,8 +1335,8 @@ static void CreateCoercedStore(llvm::Value *Src,
     // to that information.
     Address Tmp = CreateTempAllocaForCoercion(CGF, SrcTy, Dst.getAlignment());
     CGF.Builder.CreateStore(Src, Tmp);
-    Address Casted = CGF.Builder.CreateBitCast(Tmp, CGF.AllocaInt8PtrTy);
-    Address DstCasted = CGF.Builder.CreateBitCast(Dst, CGF.AllocaInt8PtrTy);
+    Address Casted = CGF.Builder.CreateElementBitCast(Tmp,CGF.Int8Ty);
+    Address DstCasted = CGF.Builder.CreateElementBitCast(Dst,CGF.Int8Ty);
     CGF.Builder.CreateMemCpy(DstCasted, Casted,
         llvm::ConstantInt::get(CGF.IntPtrTy, DstSize),
         false);
diff --git a/clang/test/CodeGenCXX/address-space-cast-coerce.cpp b/clang/test/CodeGenCXX/address-space-cast-coerce.cpp
new file mode 100644
index 000000000000..940a4f55b47a
--- /dev/null
+++ b/clang/test/CodeGenCXX/address-space-cast-coerce.cpp
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 %s -triple=amdgcn-amd-amdhsa -emit-llvm -o - | FileCheck %s
+
+template<typename T, unsigned int n> struct my_vector_base;
+
+    template<typename T>
+    struct my_vector_base<T, 1> {
+        typedef T Native_vec_ __attribute__((ext_vector_type(1)));
+
+        union {
+            Native_vec_ data;
+            struct {
+                T x;
+            };
+        };
+    };
+
+    template<typename T, unsigned int rank>
+    struct my_vector_type : public my_vector_base<T, rank> {
+        using my_vector_base<T, rank>::data;
+        using typename my_vector_base<T, rank>::Native_vec_;
+
+        template< typename U>
+        my_vector_type(U x) noexcept
+        {
+            for (auto i = 0u; i != rank; ++i) data[i] = x;
+        }
+        my_vector_type& operator+=(const my_vector_type& x) noexcept
+        {
+            data += x.data;
+            return *this;
+        }
+    };
+
+template<typename T, unsigned int n>
+    inline
+    my_vector_type<T, n> operator+(
+        const my_vector_type<T, n>& x, const my_vector_type<T, n>& y) noexcept
+    {
+        return my_vector_type<T, n>{x} += y;
+    }
+
+using char1 = my_vector_type<char, 1>;
+
+int mane() {
+
+    char1 f1{1};
+    char1 f2{1};
+
+// CHECK: %[[a:[^ ]+]] = addrspacecast i16 addrspace(5)* %{{[^ ]+}} to i16*
+// CHECK: %[[a:[^ ]+]] = addrspacecast %{{[^ ]+}} addrspace(5)* %{{[^ ]+}} to %{{[^ ]+}} 
+
+    char1 f3 = f1 + f2;
+}