Skip to content

Recent cgen update breaks codegen with read_only temporary variables

The release of cgen 2019.1 changed the parentheses emitted in array and pointer-to POD data. As a result, the following kernel is incorrectly transpiled to C:

import numpy
import loopy
k = loopy.make_kernel("{ : }", "a[0] = b[0]",
                      [...],
                      temporary_variables={"b": loopy.TemporaryVariable("b", dtype=float, shape=(1, ),
                                                                        initializer=numpy.arange(1, dtype=float),
                                                                        read_only=True, address_space=loopy.AddressSpace.GLOBAL)},
                      target=loopy.CTarget())

print(loopy.generate_code_v2(k).device_code())
static double (const b)[1] = { 0.0 };

void loopy_kernel(double *__restrict__ (a))
{
  a[0] = b[0];
}

I think this actually just exposes a long-time bug in the handling of temporary variable declarations in the codegen:

https://gitlab.tiker.net/inducer/loopy/blob/master/loopy/target/c/init.py#L719

Effectively declares read-only temporaries as "array of const foo", whereas it should be saying "const array of foo". I think this patch might be right?

diff --git a/loopy/target/c/__init__.py b/loopy/target/c/__init__.py
index 25b19080..892b2fa3 100644
--- a/loopy/target/c/__init__.py
+++ b/loopy/target/c/__init__.py
@@ -759,10 +759,6 @@ class CASTBuilder(ASTBuilderBase):
     def get_temporary_decl(self, codegen_state, schedule_index, temp_var, decl_info):
         temp_var_decl = POD(self, decl_info.dtype, decl_info.name)
 
-        if temp_var.read_only:
-            from cgen import Const
-            temp_var_decl = Const(temp_var_decl)
-
         if decl_info.shape:
             from cgen import ArrayOf
             ecm = self.get_expression_to_code_mapper(codegen_state)
@@ -770,6 +766,10 @@ class CASTBuilder(ASTBuilderBase):
                     ecm(p.flattened_product(decl_info.shape),
                         prec=PREC_NONE, type_context="i"))
 
+        if temp_var.read_only:
+            from cgen import Const
+            temp_var_decl = Const(temp_var_decl)
+
         if temp_var.alignment:
             from cgen import AlignedAttribute
             temp_var_decl = AlignedAttribute(temp_var.alignment, temp_var_decl)
Edited by Lawrence Mitchell