diff --git a/src/psyclone/psyir/tools/definition_use_chains.py b/src/psyclone/psyir/tools/definition_use_chains.py index 6a68f29233..ac2ba13c9e 100644 --- a/src/psyclone/psyir/tools/definition_use_chains.py +++ b/src/psyclone/psyir/tools/definition_use_chains.py @@ -250,16 +250,20 @@ def find_forward_accesses(self): .abs_position + 1 ) - # We make a copy of the reference to have a detached - # node to avoid handling the special cases based on - # the parents of the reference. - chain = DefinitionUseChain( - self._reference.copy(), - body, - start_point=ancestor.abs_position, - stop_point=sub_stop_point, - ) - chains.insert(0, chain) + # If we have a basic block with no children then skip it, + # e.g. for an if block with no code before the else + # statement, as is found in NEMO4. + if(len(body) > 0): + # We make a copy of the reference to have a detached + # node to avoid handling the special cases based on + # the parents of the reference. + chain = DefinitionUseChain( + self._reference.copy(), + body, + start_point=ancestor.abs_position, + stop_point=sub_stop_point, + ) + chains.insert(0, chain) # If its a while loop, create a basic block for the while # condition. if isinstance(ancestor, WhileLoop): @@ -300,6 +304,11 @@ def find_forward_accesses(self): # Now add all the other standardly handled basic_blocks to the # list of chains. for block in basic_blocks: + # If we have a basic block with no children then skip it, + # e.g. for an if block with no code before the else + # statement, as is found in NEMO4. + if(len(block) == 0): + continue chain = DefinitionUseChain( self._reference, block, @@ -835,6 +844,11 @@ def find_backward_accesses(self): # Now add all the other standardly handled basic_blocks to the # list of chains. for block in basic_blocks: + # If we have a basic block with no children then skip it, + # e.g. for an if block with no code before the else + # statement, as is found in NEMO4. + if(len(block) == 0): + continue chain = DefinitionUseChain( self._reference, block, @@ -874,14 +888,18 @@ def find_backward_accesses(self): ).abs_position else: sub_start_point = self._reference.abs_position - chain = DefinitionUseChain( - self._reference.copy(), - body, - start_point=sub_start_point, - stop_point=sub_stop_point, - ) - chains.append(chain) - control_flow_nodes.append(ancestor) + # If we have a basic block with no children then skip it, + # e.g. for an if block with no code before the else + # statement, as is found in NEMO4. + if(len(body) > 0): + chain = DefinitionUseChain( + self._reference.copy(), + body, + start_point=sub_start_point, + stop_point=sub_stop_point, + ) + chains.append(chain) + control_flow_nodes.append(ancestor) # If its a while loop, create a basic block for the while # condition. if isinstance(ancestor, WhileLoop): diff --git a/src/psyclone/tests/psyir/tools/definition_use_chains_backward_dependence_test.py b/src/psyclone/tests/psyir/tools/definition_use_chains_backward_dependence_test.py index bafc2c92c8..a2e10c42f8 100644 --- a/src/psyclone/tests/psyir/tools/definition_use_chains_backward_dependence_test.py +++ b/src/psyclone/tests/psyir/tools/definition_use_chains_backward_dependence_test.py @@ -687,3 +687,33 @@ def test_definition_use_chains_backward_accesses_nonassign_reference_in_loop( assert reaches[0] is routine.children[1].loop_body.children[1].children[1] assert reaches[1] is routine.children[1].loop_body.children[0].lhs assert reaches[2] is routine.children[0].lhs + +def test_definition_use_chains_backward_accesses_empty_schedules( + fortran_reader, +): + '''Coverage to handle the case where we have empty schedules inside + various type of code.''' + code = """ + subroutine x() + integer :: a, i + a = 1 + do i = 1, 100 + end do + if(.TRUE.) then + else + endif + do while(.FALSE.) + end do + a = a + a + end subroutine x + """ + psyir = fortran_reader.psyir_from_source(code) + routine = psyir.walk(Routine)[0] + chains = DefinitionUseChain( + routine.children[4].lhs + ) + reaches = chains.find_backward_accesses() + assert len(reaches) == 3 + assert reaches[0] is routine.children[4].rhs.children[1] + assert reaches[1] is routine.children[4].rhs.children[0] + assert reaches[2] is routine.children[0].lhs diff --git a/src/psyclone/tests/psyir/tools/definition_use_chains_forward_dependence_test.py b/src/psyclone/tests/psyir/tools/definition_use_chains_forward_dependence_test.py index 6cf86a3874..05ce1f1201 100644 --- a/src/psyclone/tests/psyir/tools/definition_use_chains_forward_dependence_test.py +++ b/src/psyclone/tests/psyir/tools/definition_use_chains_forward_dependence_test.py @@ -937,3 +937,33 @@ def test_definition_use_chains_forward_accesses_multiple_routines( ) reaches = chains.find_forward_accesses() assert len(reaches) == 0 + +def test_definition_use_chains_forward_accesses_empty_schedules( + fortran_reader, +): + '''Coverage to handle the case where we have empty schedules inside + various type of code.''' + code = """ + subroutine x() + integer :: a, i + a = 1 + do i = 1, 100 + end do + if(.TRUE.) then + else + endif + do while(.FALSE.) + end do + a = a + a + end subroutine x + """ + psyir = fortran_reader.psyir_from_source(code) + routine = psyir.walk(Routine)[0] + chains = DefinitionUseChain( + routine.children[0].lhs + ) + reaches = chains.find_forward_accesses() + assert len(reaches) == 3 + assert reaches[0] is routine.children[4].rhs.children[0] + assert reaches[1] is routine.children[4].rhs.children[1] + assert reaches[2] is routine.children[4].lhs