From 5851b04bc2480a86c5cffd558dd715e23b355147 Mon Sep 17 00:00:00 2001 From: Dominic Kempf Date: Thu, 28 Sep 2017 22:07:25 +0200 Subject: [PATCH 1/6] [bugfix] Avoid vanishing predicates Previously predicates, that could be hoisted up to a CallKernel schedule item were silently dropped by the DummyHostASTBuilder. This commit fixes the issue, by introducing a property whether an AST builder is able to implement conditionals. If not so, the hoisting of predicates is turned off (aka delayed until device code is generated). --- loopy/codegen/control.py | 7 +++++++ loopy/target/__init__.py | 7 ++++--- loopy/target/c/__init__.py | 4 ++++ loopy/target/python.py | 4 ++++ 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/loopy/codegen/control.py b/loopy/codegen/control.py index 789c00d33..3df79495f 100644 --- a/loopy/codegen/control.py +++ b/loopy/codegen/control.py @@ -417,6 +417,13 @@ def build_loop_nest(codegen_state, schedule_index): or candidate_group_length == 1): # length-1 must always be an option to reach the recursion base # case below + if (current_pred_set and not + codegen_state.ast_builder.can_implement_conditionals): + # Do not try to implement conditionals, if the AST builder + # cannot do it, this happens if we are still generating host + # code, but the conditional should be implemented in device code + found_hoists.append((candidate_group_length, bounds_checks, [])) + found_hoists.append((candidate_group_length, bounds_checks, current_pred_set)) diff --git a/loopy/target/__init__.py b/loopy/target/__init__.py index 5d5743bae..2b2ec9149 100644 --- a/loopy/target/__init__.py +++ b/loopy/target/__init__.py @@ -210,6 +210,10 @@ class ASTBuilderBase(object): static_lbound, static_ubound, inner): raise NotImplementedError() + @property + def can_implement_conditionals(self): + return False + def emit_if(self, condition_str, ast): raise NotImplementedError() @@ -284,9 +288,6 @@ class DummyHostASTBuilder(ASTBuilderBase): static_lbound, static_ubound, inner): return None - def emit_if(self, condition_str, ast): - return None - def emit_initializer(self, codegen_state, dtype, name, val_str, is_const): return None diff --git a/loopy/target/c/__init__.py b/loopy/target/c/__init__.py index a2ad68250..dfffcfae7 100644 --- a/loopy/target/c/__init__.py +++ b/loopy/target/c/__init__.py @@ -789,6 +789,10 @@ class CASTBuilder(ASTBuilderBase): from cgen import Comment return Comment(s) + @property + def can_implement_conditionals(self): + return True + def emit_if(self, condition_str, ast): from cgen import If return If(condition_str, ast) diff --git a/loopy/target/python.py b/loopy/target/python.py index 11951abcf..ce04986d3 100644 --- a/loopy/target/python.py +++ b/loopy/target/python.py @@ -283,6 +283,10 @@ class PythonASTBuilderBase(ASTBuilderBase): from genpy import Comment return Comment(s) + @property + def can_implement_conditionals(self): + return True + def emit_if(self, condition_str, ast): from genpy import If return If(condition_str, ast) -- GitLab From 31754b743319d03af903b00b2c36f0b4962b09b9 Mon Sep 17 00:00:00 2001 From: Dominic Kempf Date: Thu, 28 Sep 2017 22:15:45 +0200 Subject: [PATCH 2/6] flake8... --- loopy/codegen/control.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loopy/codegen/control.py b/loopy/codegen/control.py index 3df79495f..46aa5189c 100644 --- a/loopy/codegen/control.py +++ b/loopy/codegen/control.py @@ -418,7 +418,7 @@ def build_loop_nest(codegen_state, schedule_index): # length-1 must always be an option to reach the recursion base # case below if (current_pred_set and not - codegen_state.ast_builder.can_implement_conditionals): + codegen_state.ast_builder.can_implement_conditionals): # Do not try to implement conditionals, if the AST builder # cannot do it, this happens if we are still generating host # code, but the conditional should be implemented in device code -- GitLab From 95bc0b63ab4d3460cb3c9778d7dce802d3056f30 Mon Sep 17 00:00:00 2001 From: Dominic Kempf Date: Fri, 29 Sep 2017 08:35:18 +0200 Subject: [PATCH 3/6] Have DummyHostASTBuilder raise NotImplementedErrors whenever asked for something it does not do. This matches the behaviour of the base class ASTBuilderBase. --- loopy/target/__init__.py | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/loopy/target/__init__.py b/loopy/target/__init__.py index 2b2ec9149..239442f2f 100644 --- a/loopy/target/__init__.py +++ b/loopy/target/__init__.py @@ -257,19 +257,12 @@ class DummyHostASTBuilder(ASTBuilderBase): schedule_index, function_decl, function_body): return function_body - def get_function_declaration(self, codegen_state, codegen_result, - schedule_index): - return None - def get_temporary_decls(self, codegen_state, schedule_index): return [] def get_expression_to_code_mapper(self, codegen_state): return _DummyExpressionToCodeMapper() - def get_kernel_call(self, codegen_state, name, gsize, lsize, extra_args): - return None - @property def ast_block_class(self): return _DummyASTBlock @@ -278,25 +271,6 @@ class DummyHostASTBuilder(ASTBuilderBase): def ast_block_scope_class(self): return _DummyASTBlock - def emit_assignment(self, codegen_state, insn): - return None - - def emit_multiple_assignment(self, codegen_state, insn): - return None - - def emit_sequential_loop(self, codegen_state, iname, iname_dtype, - static_lbound, static_ubound, inner): - return None - - def emit_initializer(self, codegen_state, dtype, name, val_str, is_const): - return None - - def emit_blank_line(self): - return None - - def emit_comment(self, s): - return None - # }}} -- GitLab From 70ea44719922e5359a329e37ef7fff581ea30733 Mon Sep 17 00:00:00 2001 From: Dominic Kempf Date: Fri, 29 Sep 2017 08:57:43 +0200 Subject: [PATCH 4/6] Put back no-op implementation of get_kernel_call --- loopy/target/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/loopy/target/__init__.py b/loopy/target/__init__.py index 239442f2f..03e71f9e9 100644 --- a/loopy/target/__init__.py +++ b/loopy/target/__init__.py @@ -263,6 +263,9 @@ class DummyHostASTBuilder(ASTBuilderBase): def get_expression_to_code_mapper(self, codegen_state): return _DummyExpressionToCodeMapper() + def get_kernel_call(self, codegen_state, name, gsize, lsize, extra_args): + return None + @property def ast_block_class(self): return _DummyASTBlock -- GitLab From 9a7083a08904a562d6976579288906c9478f2984 Mon Sep 17 00:00:00 2001 From: Dominic Kempf Date: Fri, 29 Sep 2017 09:09:44 +0200 Subject: [PATCH 5/6] Also restore get_function_declaration on the DummyHostASTBuilder --- loopy/target/__init__.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/loopy/target/__init__.py b/loopy/target/__init__.py index 03e71f9e9..59d051c50 100644 --- a/loopy/target/__init__.py +++ b/loopy/target/__init__.py @@ -257,6 +257,10 @@ class DummyHostASTBuilder(ASTBuilderBase): schedule_index, function_decl, function_body): return function_body + def get_function_declaration(self, codegen_state, codegen_result, + schedule_index): + return None + def get_temporary_decls(self, codegen_state, schedule_index): return [] -- GitLab From 74de82b8537ede591ac487e52eff3c6042faf75f Mon Sep 17 00:00:00 2001 From: Dominic Kempf Date: Fri, 29 Sep 2017 09:35:24 +0200 Subject: [PATCH 6/6] Directly go into recursion if the ast builder does not implement conditionals --- loopy/codegen/control.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/loopy/codegen/control.py b/loopy/codegen/control.py index 46aa5189c..e18a51c4d 100644 --- a/loopy/codegen/control.py +++ b/loopy/codegen/control.py @@ -240,6 +240,15 @@ def build_loop_nest(codegen_state, schedule_index): kernel = codegen_state.kernel + # If the AST builder does not implement conditionals, we can save us + # some work about hoisting conditionals and directly go into recursion. + if not codegen_state.ast_builder.can_implement_conditionals: + result = [] + inner = generate_code_for_sched_index(codegen_state, schedule_index) + if inner is not None: + result.append(inner) + return merge_codegen_results(codegen_state, result) + # {{{ pass 1: pre-scan schedule for my schedule item's siblings' indices # i.e. go up to the next LeaveLoop, and skip over inner loops. @@ -417,13 +426,6 @@ def build_loop_nest(codegen_state, schedule_index): or candidate_group_length == 1): # length-1 must always be an option to reach the recursion base # case below - if (current_pred_set and not - codegen_state.ast_builder.can_implement_conditionals): - # Do not try to implement conditionals, if the AST builder - # cannot do it, this happens if we are still generating host - # code, but the conditional should be implemented in device code - found_hoists.append((candidate_group_length, bounds_checks, [])) - found_hoists.append((candidate_group_length, bounds_checks, current_pred_set)) -- GitLab