Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Node transformation applied on a subroutine's clone also impact original routine (possibly caused by ASSOCIATE) #174

Closed
JoeffreyLegaux opened this issue Oct 16, 2023 · 1 comment · Fixed by #175

Comments

@JoeffreyLegaux
Copy link
Contributor

When applying this script :

from loki import Frontend, Sourcefile, FindNodes, Node, Subroutine, Transformer
from loki.ir import Section, Comment, VariableDeclaration, Pragma, Assignment, CallStatement
from loki.expression.symbols import DeferredTypeSymbol

for file in ['./routine.F90' ]:
    source = Sourcefile.from_file(file, frontend=Frontend.FP)

    for routine in source.subroutines:
        new_routine = routine.clone()

        map_nodes={}
        for assign in FindNodes(Assignment).visit(new_routine.body):
            map_nodes[assign] = CallStatement(name = DeferredTypeSymbol(name='TESTCALL'), arguments=(assign.lhs,), scope=new_routine)
        new_routine.body = Transformer(map_nodes).visit(new_routine.body)
            
        f = open('./new_routine.F90', 'w')
        f.write(new_routine.to_fortran())
        f.write('\n') #Add eol so vim doesn't complain
        f.close()

        f = open('./ref_routine.F90', 'w')
        f.write(routine.to_fortran())
        f.write('\n') #Add eol so vim doesn't complain
        f.close()

To the following routine :

SUBROUTINE MYROUTINE(YDCFU, YDCPG_OPTS)

USE PARKIND1                , ONLY : JPIM, JPRB
USE YOMCFU                  , ONLY : TCFU
USE CPG_OPTS_TYPE_MOD       , ONLY : CPG_BNDS_TYPE, CPG_OPTS_TYPE

IMPLICIT NONE

TYPE(TCFU)              ,INTENT(INOUT)            :: YDCFU
TYPE(CPG_OPTS_TYPE)     ,INTENT(IN)               :: YDCPG_OPTS

REAL(KIND=JPRB) :: ZFPREC9(YDCPG_OPTS%KLON) ! past cumulated flux of total precipitations
REAL(KIND=JPRB) :: ZFPREC0(YDCPG_OPTS%KLON) ! instantaneous flux of total precipitations
REAL(KIND=JPRB) :: ZSQPRE(YDCPG_OPTS%KLON)  ! instantaneous flux of total squared precipitations

ZFPREC9(:)=0.0_JPRB

ASSOCIATE(LREACFU=>YDCFU%LREACFU, NFRRC=>YDCFU%NFRRC)

IF (YDCFU%YFDUTP%LACTIVE) THEN
  ZFPREC0(:)=0.0_JPRB
ELSE
  ZSQPRE(:)=0.0_JPRB
END IF

END ASSOCIATE

END SUBROUTINE MYROUTINE

The outputted transformed cloned routine is correct (all Assignment nodes replaced by CallStatements).
However, when outputting back the original routine the two assignements in the conditional block are also transformed.

This could be tied to the ASSOCIATE block, since when it is commented the original routine remains correct in the output file.

@mlange05
Copy link
Collaborator

Hi @JoeffreyLegaux, you are absolutely right, this is a bug due to the initial .clone() not rebuilding nested scopes. For context, the Transformers by default skip rebuilding ScopedNode nodes (Associate and TypeDef) as this would otherwise trigger a lot(!) of rescoping operations that are very expensive.

However, in the deep-copy context, you are of course right in assuming full rebuilds. For this Transformers provide a flag to trigger this behaviour, but this was missed in the original implementation. PR #175 should fix this, but please check if this works as you'd expect.

Thanks again for reporting and the clean reproducer! 🙏

@reuterbal reuterbal linked a pull request Oct 17, 2023 that will close this issue
reuterbal added a commit that referenced this issue Oct 17, 2023
Fix deep-cloning of subroutiens and modules (fix #174)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants