# 
#     Copyright (c) 2017, NVIDIA CORPORATION.  All rights reserved.
#
# NVIDIA CORPORATION and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto.  Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA CORPORATION is strictly prohibited.
# 

# Compiler Configurations for compilers using IPA
#

suffix ipo is
	string(ipo)
	help(IPA object file: IPA link);

variable IPARGS is		# set by -L, -l, -Wi
	help(Arguments to IPA linker);

variable IPNOP is		# new one pass?
	help(Arguments to IPA linker)
	default(-nop);

variable IPRM is hide
	help(Default -rm switch)
	default();

variable IPALINK is		# set by -Mipa
	help(Run IPA linker phase 1)
	default($IPALINKENABLE);

variable IPALINKENABLE is
	default();

variable IPAEXTRARGS is hide default();

variable IPADIR is
	help(Directory containing IPA tools)
	default($COMPBIN);

variable IPAVERBOSITY is default($if($VERBOSE,2,1));

variable IPOFILE is
	default($DEFIPOFILE);

variable IPARECOMPILE is
	help()
	default();

variable IPACARGS is
	help(IPA arguments passed to the compiler)
	default();

variable IPAC2ARGS is
	help(IPA arguments passed to the f90 compiler back end)
	default();

variable IPAIGNORE0 is
	help(Command line switches that should not be passed on the recompile)
	default(-c $ifn($KEEPASM,-Mkeepasm) -Mpreprocess);
variable IPAIGNORE1 is
	help(Command line switches that should not be passed on the recompile)
	default(-Mextract -Wi -Minline);
variable IPAIGNORE2 is
	help(Command line switches that should not be passed on the recompile)
	default(-L -I -l -o);

variable IPAADD is
	help(Collected command line switches that should added on the recompile)
	default();

variable IPAADDINLINE is default();

variable IPAADDSW is
	help(Command line switches that should added on the recompile)
	default($if($KEEPASM,-Mkeepasm) $IPAADD $IPAADDINLINE);

variable IPANOARG is default(0);

tool ipaloader is help(IPA Propagation)
	program($IPALD) directory($IPADIR);

command ipalink is
	help(IPA Propagation)
	tool(ipaloader)
	# first object file, if MSlink
	set(FFILE=$if($MSLINK,$first($realfiles)))
	# what will actual executable be named?  either -o, or first object
	set(OOFILE=$if($OUTFILE,$ifn($OUTEXESUFFIX,$OUTFILE,$if($suffix($OUTFILE),$OUTFILE,$OUTFILE$OUTEXESUFFIX)),$if($FFILE,$basename($FFILE)$OUTEXESUFFIX)))
	# if we are running the postlinker, rename the executable
	set(ld=$lookup($LDDIR,$LD$EXESUFFIX))
	set(outfile=$ifn($OUTEXESUFFIX,$OUTFILE,$if($suffix($OUTFILE),$OUTFILE,$OUTFILE$OUTEXESUFFIX)))
	set(PDBFILE=$if($and($DEBUGSET,$or($equal($TARGET,win64),$equal($TARGET,win64-llvm))),$dirname($OOFILE)/$basename($OOFILE).pdb))
	set(iresponse=$if($MSLINK,$if($KEEPLNK,pgi.lnk,$tempfile(lnk)),dummy))
	set(arguments=
	    $ifn($NOSTARTUP,$DEFLDSTARTUP
		$FTNALT
		$if($I8STORAGE,$lookup($COMPLIBOBJ,f90i8st.$HOSTOBJSUFFIX))
	    )
	    $DEFLDARGS 
	    $LDLIBARGS
	    $ifn($NOSTDLIBDIRS,
		$if($DEFSTDDIRS,$STDDIRPRE$replace($DEFSTDDIRS,,$STDDIRIN)))
	    $LDINPUTPRE $input $LDINPUTPOST
	    $ifn($NOSTDLIBPATHS,$DEFSTDPATHS)
	    $LDSWITCHES $if($OOFILE,$ifn($MSLINK,-o $OOFILE,"-out:"$OOFILE))
	    $if($PDBFILE,-pdb:$PDBFILE)
	    $if($SITELIB,$LDIRSW$replace($SITELIB,, $LDIRSW))
	    $LDLIB1 $LDLIB2 $LDARGS $OVLFILES
	    $EXTRALDARGS $LDLIB3
	    $ifn($NOSTDLIBPATHS,$GCCLIBS)
	    $ifn($NOSTDCPPLIBS,$DEFCPPLIBS)
	    $DEFSTDLIBS
	    $ifn($NOSTARTUP,$DEFLDENDUP)
	)
	write(iresponse=$if($MSLINK,$arguments))
	arguments(
	    $ifn($equal($IPAADDSW,),-swadd $quote($IPAADDSW))
	    -v$IPAVERBOSITY
	    $if($OOFILE,-finalo $OOFILE)
	    -ignore $quote($IPAIGNORE0)
	    -ignore1 $quote($IPAIGNORE1)
	    -ignore2 $quote($IPAIGNORE2)
	    $DEFIPARGS $IPAEXTRARGS $IPNOP $IPARGS 
	    $IPAINLINELIST
	    $IPRM $DEFIPALIBS
	    -ilinkpath
	    $ACCLINK $tool(loader) -ilinkargs $ifn($MSLINK,$arguments,$NOLOGO @$iresponse)
	)
	execute(
	    condition($notequal($POSTLINK,))
	    input($OOFILE)
	    command($POSTLINK)
	);

phase IPALink is
	help(IPA Linker)
	forall
	before(Link)
	execute(
	    condition($and($notequal($IPALINK,),$equal($COMPILEONLY,),$equal($PRELINKONLY,)))
	    input($DEFLINKFILES $linkfiles)
	    command(ipalink)
	);

variable IPA89 is default(0x80800842);
variable IPA66 is default(0x20000);
variable IPA14 is default(0x104);
variable IPA14r is default($if($and($CONCURCOMPILE,$equal($ACCELS,)),0x4000000));

variable IPACGARGS is default($IPAVALUE);
variable IPAVALUE is default();
variable IPAVAL is
	default($if($IPA89,-x 89 $IPA89) $if($IPA66,-x 66 $IPA66) $if($IPA14,-x 14 $IPA14) $if($IPA14r,-x 14 $IPA14r) -y 89 0x40);
variable FIPAVALUE is default();
variable FIPACGARGS is default($FIPAVALUE);
variable FIPAVAL is
	default($if($IPA89,-x 89 $IPA89) $if($IPA66,-x 66 $IPA66) -y 89 0x40);

variable IPAEXPORT is
	default();

variable DEFIPAEXPORTVAL is default();
variable IPAEXPORTVAL is default($DEFIPAEXPORTVAL);

variable IPALIBCSW is default($if($index($TARGET,win64,linux86-64,arm,linuxarm,androidarm,win64-llvm),--Mipainlinelibc));

variable IPACP is default(-cp) hide;

switch -Mipa is hide
	warning(The option -Mipa has been deprecated and is ignored.)
	help(Enable Interprocedural Analysis)
	helpname(-M[no]ipa)
	helpgroup(opt)
	# default is to enable all optimizations in the compiler
	append(MPROFNOCOUNT=-Mipa)
	append(IPARGS=$IPACP -enable -const)
	set(IPAEXPORT=$IPAEXPORTVAL)
	set(DEFIPAEXPORTVAL=1)
	keyword(
	    all=fast( hide )
	    align(or(IPA66=0x2000)
		append(IPARGS=-align)
		helpname([no]align)
		help(Recognize when targets of pointer dummy are aligned))
	    noalign(andnot(IPA66=0x2000)
		append(IPARGS=-noalign)
		hide help("Don't recognize when targets of pointer dummy are aligned"))
	    arg(or(IPA66=0x12)
		append(IPARGS=-arg)
		helpname([no]arg)
		help(Remove arguments replaced by -Mipa=ptr,const))
	    noarg(andnot(IPA66=0x1a)
		append(IPARGS=-noarg -noarglocal)
		hide help("Don't remove arguments replaced by -Mipa=ptr,const; implies -Mipa=nolocalarg"))
	    ast(or(IPA89=0x40000) hide
		append(IPARGS=-trans)
		helpname([no]ast)
		help(Look for array-of-struct transpose opportunities))
	    noast(andnot(IPA89=0x40000) hide
		append(IPARGS=-notrans)
		helpname([no]ast)
		help(Look for array-of-struct transpose opportunities))
	    cg(append(IPARGS=-ipsinfo) hide
		helpname([no]cg)
		help(Generate call graph information for pgicg tool))
	    nocg(append(IPARGS=-noipsinfo) hide
		hide help(Don't generate call graph information for pgicg tool))
	    collect(help(Just collect IPO information in .ipo files) hide
		andnot(IPA89=0x40) or(IPA89=0x08)
		set(NOASM=YES)
		set(IPOFILE=YES))
	    const(or(IPA89=0x10000800)
		append(IPARGS=-const -range)
		helpname([no]const)
		help(Interprocedural constant propagation))
	    noconst(andnot(IPA89=0x10000800)
		append(IPARGS=-noconst -norange)
		hide help(Disable interprocedural constant propagation))
	    div(hide help(Enable divide optimization)
		append(IPARGS=-div))
	    nodiv(hide help(Disable divide optimization)
		append(IPARGS=-nodiv))
	    enable( hide help("Force enable IPA") append(IPARGS=-force_enable))
	    error=errorcheck(hide help(Same as -Mipa=errorcheck))
	    errorcheck( hide help("Perform some interprocedural error checking")
		append(IPARGS=-errorcheck))
	    except:func( help("Used with -Mipa=inline, don't inline func")
		append(IPARGS=-noinl $func))
	    fast(or(IPA89=0x30871b00) or(IPA66=0x503201a)
		append(IPARGS=-align -const -range -globals -div -pure -trans $ifn($IPANOARG,-arg -arglocal) -alias -ptr -f90ptr -shape -yeslibc -reaggregation)
		append(CARGS=-x 53 0x80000) # part of -Mipa=alias
		append(CARGS=-x 53 0x100000)# part of -Mipa=reaggregation
		set(IPAADDINLINE=$IPALIBCSW)	# part of -Mipa=libc
		help(Equivalant to -Mipa=align,arg,const,f90ptr,shape,libc,globals,localarg,alias,ptr,pure))
	    force(append(IPARGS=-force)
		helpname([no]force)
		help(Force all objects to recompile regardless of whether IPA information has changed))
	    noforce(hide
		append(IPARGS=-noforce)
		help("Don't force all objects to recompile regardless of whether IPA information has changed"))
	    globals(or(IPA89=0x60000)
		append(IPARGS=-globals -trans -div)
		helpname([no]globals)
		help(Optimize references to globals))
	    noglobals(andnot(IPA89=0x60000)
		append(IPARGS=-noglobals -notrans -nodiv)
		hide help("Don't optimize references to globals"))
	    # inlimit:n(append(IPARGS=$if($isnum($n),-growth $n,$error(Invalid argument to -Mipa=inlimit))))
	    inline(or(IPA89=0x8000) or(IPA14=0x0034)
		append(IPARGS=-inline)
		set(IPAINLINE=YES)
                #disable -Minline with -Mipa=inline (deferred to when making -Minline default with -fast)
	        #append(CARGS=-noinline)
                #append(F902ARGS=-noinline)
                #set(INLINEARGS=)
                #set(INLINE=)
		#disable -Mautoinline with -Mipa=inline
		append(CARGS=-noautoinl -x 14 0x200000)
		set(AUTOINLINE=)
		help(Automatically determine which functions to inline)
		keyword(
		    "":n(once numeric help(Limit to n levels of inlining)
			append(IPARGS=-ilevels $n))
		    except:func( help("Don't inline func")
			append(IPARGS=-noinl $func))
		    nopfo( help(Ignore PFO frequency information)
			   append(IPARGS=-noinlinepfo))
		    reshape(set(IPA14r=0x4000000)
			helpname([no]reshape)
			help(Inline with mismatched array shapes))
		    noreshape(set(IPA14r=) hide help(Don't inline with mismatched array shapes))
		    static(hide or(IPA14=0x4000) help(Enables inlining with static/save data))
		    staticfunc(hide or(IPA14=0x40000000) help(Enables inlining of C static functions))
		)
	    )
	    inlinenopfo:n(or(IPA89=0x8000) or(IPA14=0x0034) hide
		append(IPARGS=-inline -noinlinepfo -ilevels $n)
		set(IPAINLINE=YES)
		help(Equivalent to -Mipa=inline:n,nopfo))
	    inlinenopfo(or(IPA89=0x8000) or(IPA14=0x0034) hide
		append(IPARGS=-inline -noinlinepfo)
		set(IPAINLINE=YES)
		help(Equivalent to -Mipa=inline,nopfo))
	    ipofile(help(Save IPO information in .ipo files)
		set(IPOFILE=YES))
	    jobs:n(help(Recompile n jobs in parallel)
		append(IPARGS=-jobs $n))
	    keepobj(
		append(IPARGS=-mangle)
		helpname([no]keepobj)
		help(Keep IPA-optimized object files)
		)
	    nokeepobj( hide
		append(IPARGS=-nomangle)
		help("Don't keep IPA-optimized object files")
		)
	    libc(
		helpname([no]libc)
		help("Optimize calls to certain libc functions")
		set(IPAADDINLINE=$IPALIBCSW)
		append(IPARGS=-yeslibc)
		)
	    nolibc( hide
		help("Don't optimize calls to certain libc functions")
		set(IPAADDINLINE=)
		append(IPARGS=-nolibc)
		)
	    libinline(append(IPARGS=-mlibinline -inline)
		set(IPAINLINE=YES)
		helpname([no]libinline)
		help("Inline (don't inline) routines even from libraries; implies -Mipa=inline"))
	    nolibinline(append(IPARGS=-nomlibinline)
		hide
		help("Don't inline routines from libraries"))
	    libopt(append(IPARGS=-mlibopt)
		helpname([no]libopt)
		help("Optimize (don't optimize) routines in libraries"))
	    nolibopt(append(IPARGS=-nomlibopt)
		hide
		help("Don't optimize routines in libraries"))
	    localarg(or(IPA66=0x1a)
		append(IPARGS=-arg -arglocal)
		helpname([no]localarg)
		help(-Mipa=arg plus externalizes local pointer targets))
	    nolocalarg(andnot(IPA66=0x08)
		append(IPARGS=-noarglocal)
		hide help(Disable local pointer target externalizing))
	    main:func(
		append(IPARGS=-main $func)
		help(Specify a function to serve as a global entry point";" may appear multiple times";" disables linking))
	    QA(hide append(IPARGS=-error)
		help(Used for quality assurance))
	    nocp(set(IPACP=) andnot(IPA89=0x80000000) andnot(IPA14=0x100) hide)
	    nocpx(set(IPACP=) hide)
	    q(append(IPARGS=-q -nocp) append(IPAADD=-v) andnot(IPA89=0x80000000) andnot(IPA14=0x100) hide)
	    noerror(append(IPARGS=-noerror) hide
		help(Do not return error condition if IPA information changes))
	    none( andnot(IPA89=0) andnot(IPA66=0) hide
		append(IPARGS=-none)
		help(No IPA optimizations))
	    onepass( hide )
	    ptr(or(IPA89=0x20000300)
		append(IPARGS=-ptr)
		helpname([no]ptr)
		help(Pointer disambiguation))
	    noptr(andnot(IPA89=0x20000300)
		append(IPARGS=-noptr)
		hide help(Disable pointer disambiguation))
            alias(or(IPA89=0x20000300)
                append(IPARGS=-alias -ptr)
		append(CARGS=-x 53 0x80000)
                helpname([no]alias)
                help(Pointer alias analysis; implies -Mipa=ptr))
            noalias(andnot(IPA89=0x20000300)
                append(IPARGS=-noalias)
		append(CARGS=-y 53 0x80000)
                hide help(Disable pointer alias analysis))
	    reaggregation(
                append(IPARGS=-reaggregation)
		append(CARGS=-x 53 0x100000)
                helpname([no]reaggregation)
                help(IPA guided structure reaggregation))
            noreaggregation(
                append(IPARGS=-noreaggregation)
		append(CARGS=-y 53 0x100000)
                hide help(Disable IPA guided structure reaggregation))
	    f90ptr(
	        or(IPA66=0x1000000)
		append(IPARGS=-f90ptr)
		helpname([no]f90ptr)
		help(Fortran Pointer disambiguation))
	    nof90ptr(
	        andnot(IPA66=0x1000000)
		append(IPARGS=-nof90ptr)
		hide help(Disable Fortran Pointer disambiguation))
	    pure(or(IPA66=0x10000)
		append(IPARGS=-pure)
		helpname([no]pure)
		help(Pure function detection))
	    nopure(andnot(IPA66=0x10000)
		append(IPARGS=-nopure)
		hide help(Disable pure function detection))
	    quiet(set(IPAVERBOSITY=0))
	    required(append(IPARGS=-required)
		help(Return error condition if IPA is inhibited))
	    norequired(hide append(IPARGS=-norequired)
		help(Don't return error condition if IPA is inhibited))
	    rm(set(IPRM=-rm$OBJSUFFIX)
		hide helpname([no]rm)
		help(Remove stale object files))
	    norm(set(IPRM=)
		hide help(Do not remove stale object files))
	    safe:name(
		append(IPARGS=-safe $name)
		help(Declare a function or all functions in a library to be side-effect free))
	    safe(append(IPARGS=-unsafe) hide
		helpname([no]safeall)
		help(Allow unsafe optimization by assuming unknown function references are unimportant))
	    safeall(append(IPARGS=-unsafe)
		helpname([no]safeall)
		help(Allow unsafe optimization by assuming unknown function references are unimportant))
	    nosafeall(append(IPARGS=-nounsafe)
		hide help("Don't allow unsafe optimization"))
	    shape(
	        or(IPA66=0x4000000)
		append(IPARGS=-shape)
		helpname([no]shape)
		help(Fortran shape propagation))
	    noshape(andnot(IPA66=0x4000000)
		append(IPARGS=-noshape)
		hide help(Disable Fortran shape propagation))
	    summary(set(IPAEXPORTVAL=)
		help(Only collect IPA summary information";" prevents IPA optimization for these files))
	    vestigial(or(IPA89=0x0400)
		append(IPARGS=-vestigial)
		helpname([no]vestigial)
		help(Remove functions that are never called))
	    novestigial(andnot(IPA89=0x0400)
		append(IPARGS=-novestigial)
		hide help("Don't remove functions that are never called"))
	    short(append(F901ARGS=-x 66 0x20000000) hide)
      acc(or(IPA66=0x40000)
    append(IPARGS=-acc)
    helpname(acc)
    help(Automatically mark OpenACC Routine Seq and generate device code))
	)
	nokeyword(
	    or(IPA89=0x800800) help(Default enables constant propagation)
	)
	set(IPALINKENABLE=YES)
	set(KEEPOBJ=YES)
	enable(IPALink)
	max(OPTLEVELDEF=2)
	append(IPAINLINE=$INLINE$AUTOINLINE)	# ensure IPAINLINE is set if -Minline or -Mautoinline is set
	max(OPTLEVELMIN=2)
	append(OPTLEVELMINLIMIT=" -Mipa")
	set(IPAVALUE=$IPAVAL)
	append(CGARGS=$IPACGARGS)	# will be $IPAVALUE unless IPA is disabled
	set(FIPAVALUE=$FIPAVAL)
	append(F901ARGS=$FIPACGARGS -y 89 0x40)
	set(IPAEXPORT=)
	set(IPAVALUE=)
	set(FIPAVALUE=)
	set(IPAINLINE=)
	disable(IPALink)
	enable(Link)
	set(IPALINKENABLE=);

switch -Mipaq=string is hide
	helpgroup(opt)
	append(IPARGS=-iq $quote($string));

switch -Mnoipa is hide	# undo any previous -Mipa switches
	help(Disable Interprocedural Analysis)
	helpgroup(opt)
	set(IPAEXPORT=)
	set(IPAVALUE=)
	set(FIPAVALUE=)
	set(IPAINLINE=)
	disable(IPALink)
	enable(Link)
	set(IPALINKENABLE=);

switch --Mipainlinelibc is hide
	helpgroup(opt)
	help(Used internally to support -Mipa=libc)
	append(INLINEARGS=$if($LIBMEMIL,-ipainlibc $LIBMEMIL));

switch -Wi,arg is hide
	help(Pass argument to IPA Linker)
	helpgroup(overall)
	append(IPARGS=$replace($arg,",", ));


switch -Yi,ipadir is hide
	help(Change IPA tools directory)
	helpgroup(overall)
	set(IPADIR=$path($ipadir));

switch --XIPAimport xfile afile is hide
	helpgroup(opt)
	set(IPACARGS=-ipaexport $xfile -ipaimport -ipafile $afile -y 89 2 -y 14 16 -x 14 32 -x 89 0x40 -x 66 0x20000000)
	set(IPAC2ARGS=-y 89 2 -y 14 16 -x 14 32 -ipaimport)
	set(IPARECOMPILE=YES)
	# simulate -c
	stopafter(Compile)
	set(CCOMPCOMMANDS=nvcpfe)
	set(IPALINK=)
	set(IPAINLINE=)
	set(KEEPOBJ=YES);

switch --YIPAimport ofile afile is hide
	helpgroup(opt)
	set(IPACARGS=-ipaexport $ofile -ipximport 0 -ipafile $afile -y 89 2 -y 14 16 -x 14 32 -x 89 0x40 -x 66 0x20000000)
	set(IPAC2ARGS=-y 89 2 -y 14 16 -x 14 32 -ipaimport)
	set(IPARECOMPILE=YES)
	# simulate -c
	stopafter(Compile)
	set(CCOMPCOMMANDS=nvcpfe)
	set(IPALINK=)
	set(IPAINLINE=)
	set(KEEPOBJ=YES);

switch --ZIPAimport offset ofile afile is hide
	helpgroup(opt)
	set(IPACARGS=-ipaexport $ofile -ipximport $offset -ipafile $afile -y 89 2 -y 14 16 -x 14 32 -x 89 0x40 -x 66 0x20000000)
	set(IPAC2ARGS=-y 89 2 -y 14 16 -x 14 32 -ipaimport)
	set(IPARECOMPILE=YES)
	# simulate -c
	stopafter(Compile)
	set(CCOMPCOMMANDS=nvcpfe)
	set(IPALINK=)
	set(IPAINLINE=)
	set(KEEPOBJ=YES)
	set(ASMONLY=YES);

# flag to enable IPA summary information
switch -Msummary is hide
	helpgroup(opt)
	help(Collect program summary information into a file for program analysis tools)
	set(fname=)
	keyword(
	    nocp(set(IPACP=) andnot(IPA89=0x80000000) andnot(IPA14=0x100) hide)
	    "":file(
		help(file into which to save the collected summary information)
		set(fname=$file)
		set(IPACP=)
	    )
	)
	nokeyword()
	set(IPALINKENABLE=YES)
	set(KEEPOBJ=YES)
	enable(IPALink)
	append(IPARGS=$IPACP -export $fname)
	set(IPAVALUE=$IPAVAL)
	append(CGARGS=$IPACGARGS)	# will be $IPAVALUE unless IPA is disabled
	set(FIPAVALUE=$FIPAVAL)
	append(F901ARGS=$FIPACGARGS -y 89 0x40);
	;
