[OpenCL] Handle address space conversions for constexpr (PR44177)
authorSven van Haastregt <sven.vanhaastregt@arm.com>
Mon, 9 Dec 2019 11:08:19 +0000 (11:08 +0000)
committerSven van Haastregt <sven.vanhaastregt@arm.com>
Mon, 9 Dec 2019 11:09:16 +0000 (11:09 +0000)
The AST for the constexpr.cl test contains address space conversion
nodes to cast through the implicit generic address space.  These
caused the evaluator to reject the input as constexpr in C++ for
OpenCL mode, whereas the input was considered constexpr in plain C++
mode as the AST won't have address space cast nodes then.

Fixes PR44177.

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

clang/lib/AST/ExprConstant.cpp
clang/test/CodeGenOpenCLCXX/address-space-deduction.cl
clang/test/CodeGenOpenCLCXX/constexpr.cl [new file with mode: 0644]

index 5aa1519..fbc706b 100644 (file)
@@ -7118,6 +7118,13 @@ public:
         return false;
       return DerivedSuccess(DestValue, E);
     }
+
+    case CK_AddressSpaceConversion: {
+      APValue Value;
+      if (!Evaluate(Value, Info, E->getSubExpr()))
+        return false;
+      return DerivedSuccess(Value, E);
+    }
     }
 
     return Error(E);
index a6ae5af..58502e9 100644 (file)
 //COMMON: @glob = addrspace(1) global i32
 int glob;
 //PTR: @glob_p = addrspace(1) global i32 addrspace(4)* addrspacecast (i32 addrspace(1)* @glob to i32 addrspace(4)*)
-//REF: @glob_p = addrspace(1) global i32 addrspace(4)* null
+//REF: @glob_p = addrspace(1) constant i32 addrspace(4)* addrspacecast (i32 addrspace(1)* @glob to i32 addrspace(4)*)
 int PTR glob_p = ADR(glob);
 
 //COMMON: @_ZZ3fooi{{P|R}}U3AS4iE6loc_st = internal addrspace(1) global i32
 //PTR: @_ZZ3fooiPU3AS4iE8loc_st_p = internal addrspace(1) global i32 addrspace(4)* addrspacecast (i32 addrspace(1)* @_ZZ3fooiPU3AS4iE6loc_st to i32 addrspace(4)*)
-//REF: @_ZZ3fooiRU3AS4iE8loc_st_p = internal addrspace(1) global i32 addrspace(4)* null
+//REF: @_ZZ3fooiRU3AS4iE8loc_st_p = internal addrspace(1) constant i32 addrspace(4)* addrspacecast (i32 addrspace(1)* @_ZZ3fooiRU3AS4iE6loc_st to i32 addrspace(4)*)
 //COMMON: @loc_ext_p = external addrspace(1) {{global|constant}} i32 addrspace(4)*
 //COMMON: @loc_ext = external addrspace(1) global i32
 
-//REF: store i32 addrspace(4)* addrspacecast (i32 addrspace(1)* @glob to i32 addrspace(4)*), i32 addrspace(4)* addrspace(1)* @glob_p
-
 //COMMON: define spir_func i32 @_Z3fooi{{P|R}}U3AS4i(i32 %par, i32 addrspace(4)*{{.*}} %par_p)
 int foo(int par, int PTR par_p){
   //COMMON: %loc = alloca i32
@@ -37,7 +35,6 @@ int foo(int par, int PTR par_p){
 
   // CHECK directives for the following code are located above.
   static int loc_st;
-  //REF: store i32 addrspace(4)* addrspacecast (i32 addrspace(1)* @_ZZ3fooiRU3AS4iE6loc_st to i32 addrspace(4)*), i32 addrspace(4)* addrspace(1)* @_ZZ3fooiRU3AS4iE8loc_st_p
   static int PTR loc_st_p = ADR(loc_st);
   extern int loc_ext;
   extern int PTR loc_ext_p;
diff --git a/clang/test/CodeGenOpenCLCXX/constexpr.cl b/clang/test/CodeGenOpenCLCXX/constexpr.cl
new file mode 100644 (file)
index 0000000..b717502
--- /dev/null
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=clc++ -O0 -emit-llvm -o - | FileCheck %s
+
+struct Storage final {
+  constexpr const float& operator[](const int index) const noexcept {
+    return InternalStorage[index];
+  }
+
+  const float InternalStorage[1];
+};
+
+constexpr Storage getStorage() {
+  return Storage{{1.0f}};
+}
+
+constexpr float compute() {
+  constexpr auto s = getStorage();
+  return 2.0f / (s[0]);
+}
+
+constexpr float FloatConstant = compute();
+
+// CHECK-LABEL: define spir_kernel void @foo
+// CHECK: store float 2.000000e+00
+kernel void foo(global float *x) {
+  *x = FloatConstant;
+}