#
#     Copyright (c) 2017-2018, 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.
#

# PGI compilers targeting LLVM

append USRDDEF=-D__PGLLVM__ -D__NVCOMPILER_LLVM__ -D__extension__= ;
append USRDEFDEF=-def __PGLLVM__ -def __NVCOMPILER_LLVM__ -def __extension__= ;

append F901ARGS=-x 70 0x40000000;	#enable complex combine as a single entity.
append F902ARGS=-x 70 0x40000000;
append CARGS=-x 70 0x40000000;

append CGARGS=-x 71 0x2000; # Enable CSE of conversions
append CGARGS=-x 71 0x4000; # find_cse_load fixes
append CGARGS=-x 34 0x40000000; # Enable vectorization predicated reductions 

variable ISSTATIC is default(0);
variable OMPATMFLAGS is default();
variable STATICSTR is default();
variable PASSPIE is default(0);  # Whether -pie is passed to linker.
variable NEEDFLANGLIBS is default(0);

variable MATTR_FEATS is default();
variable MCPU_FEATS is default();

switch -mattr=arg is early
   help(Set target processor attributes)
    set(MATTR_FEATS=$replace($arg,+,))
    # prepend --mattr= to each of the features listed.
    append(LLCMATTR=$if($MATTR_FEATS, $foreach(v, $expand($MATTR_FEATS), --mattr=$replace($v,no,-))))
    # keywords do not support identifiers with "-". Convert "-" to "_".
    set(MATTR_FEATS=$replace($expand($MATTR_FEATS),-,_))
    shorthand($if($MATTR_FEATS, $foreach(v, $MATTR_FEATS, -mattr_internal=$v)))
   ;

switch -mcpu=arg is early 
    help(Select target processor. Alias for -tp)
    helpgroup(target)
    set(targ=$first($replace($arg,+,)))
    set(MCPU_FEATS=$rest($replace($arg,+,)))
    # prepend --mattr= to each of the features listed.
    append(LLCMATTR=$if($expand($MCPU_FEATS), $foreach(v, $expand($MCPU_FEATS), --mattr=$replace($v,no,-))))
    # keywords do not support identifiers with "-". Convert "-" to "_".
    set(MCPU_FEATS=$replace($expand($MCPU_FEATS),-,_))

    shorthand($if($targ, -tp $targ, -tp <arg>))
    shorthand($if($MCPU_FEATS, $foreach(v, $MCPU_FEATS, -mattr_internal=$v)))
    ;

switch -march=arg is early 
    help(Select target processor. Alias for -tp)
    helpgroup(target)
    shorthand(-mcpu=$arg)
    ;

switch -mtune=arg is
    help(Provided for makefile compatibility. No operation is performed.)
    helpgroup(target);

switch -Mkeepstb is hide
	help(Preserve the STB file)
	helpgroup(overall)
	set(KEEPSTB=YES);

replace switch -fast is
	help(Common optimizations; includes -O2 -Munroll=c:1 -Mlre -Mautoinline)
	helpgroup(opt)
	set(OPTCGARGS=
		-x 9 1			# -Munroll=c:1
		-x 42 0x14200000	# -Mlre=prefer
		-x 136 0x11		# Branch prediction & BB placement
#		-x 53 10		# Pointer target analysis
	)
	set(OPTF901ARGS=
		-x 53 2			# Pointer target analysis
	)
	set(OPTCARGS=-autoinl $AUTOLEVELS -x 168 $AUTOMAXFUNCSIZE -x 174 $AUTOMAXTOTALSIZE -x 14 0x200000 $ifn($NOSTATIC, -x 14 0x400000))
	append(CGARGS=$OPTCGARGS)
	append(CARGS=$OPTCARGS)
	append(F901ARGS=$OPTF901ARGS)
	set(AUTOINLINE=YES)
	# Enable -Minline
	#append(INLINELIST=-insize $MAXFUNCSIZE -x 221 $MAXTOTALSIZE -x 222 $SMALLSIZE)
	#set(INLINE=YES)
	max(OPTLEVELDEF=2)	# -O2
	max(OPTLEVELMIN=2)	# -O2
        set(LLVMOPTLEVEL=$if($or($ARM,$X86_64), 3, 2))  # LLVM opt -O3
        set(LLVMLLCLEVEL=$if($or($ARM,$X86_64), 3, 2))  # LLVM llc -O3
	or(MVECTFASTFUSE=1)
	set(NOFRAME=YES)	# -Mnoframe
	shorthand(-Mvect=simd -Mflushz -Mcache_align)
    shorthand(-Mno-signed-zeros)
	shorthand(-Minline_cpu_f)
	append(OPTLEVELMINLIMIT=" -fast");

replace switch -fastsse is hide
	shorthand(-fast)
	helpgroup(opt);

variable OPTCGARGS is default();
variable OPTCARGS is default();
variable OPTF901ARGS is default();

replace switch -O0 is
	help(Set opt level.  Creates a basic block for each statement.  No scheduling or global optimizations performed)
	set(OPTLEVEL=0)
	set(OPTCGARGS=)
	set(OPTCARGS=)
	set(OPTF901ARGS=)
	helpgroup(opt)
	;

replace switch -O1 is
	help(Set opt level. Some scheduling and register allocation is enabled. No global optimizations performed)
	helpgroup(opt)
	set(OPTLEVEL=1)
	set(OPTCGARGS=)
	set(OPTCARGS=)
	set(OPTF901ARGS=)
	;

replace switch -O is
	help(Set opt level.  All -O1 optimizations plus traditional global scalar optimizations performed)
	helpgroup(opt)
	set(OPTLEVEL=2)
	set(OPTCGARGS=)
	set(OPTCARGS=)
	set(OPTF901ARGS=)
	;

replace switch -O2 is
	help(Set opt level.  All -O optimizations plus SIMD code generation)
	helpgroup(opt)
	set(OPTLEVEL=2)
	set(OPTCGARGS=
		-x 9 1			# -Munroll=c:1
		-x 136 0x11		# Branch prediction & BB placement
#		-x 53 10		# Pointer target analysis
	)
	set(OPTF901ARGS=
		-x 53 2			# Pointer target analysis
	)
	set(OPTCARGS=-autoinl $AUTOLEVELS -x 168 $AUTOMAXFUNCSIZE -x 174 $AUTOMAXTOTALSIZE -x 14 0x200000 $ifn($NOSTATIC, -x 14 0x400000))
	append(CGARGS=$OPTCGARGS)
	append(CARGS=$OPTCARGS)
	append(F901ARGS=$OPTF901ARGS)
	set(AUTOINLINE=YES)
	set(NOFRAME=YES)	# -Mnoframe
	shorthand(-Mvect=simd)
	shorthand(-Mno-signed-zeros) # NOTE: There are discussions about whether -O2
				     #       should allow unsafe FP math or not.
	shorthand(-Minline_cpu_f)
	or(MVECTFUSE=1)     # Enable loop fustion.
	;

replace switch -O3 is
	help(Set opt level. All -O2 optimizations plus more aggressive code hoisting and scalar replacement, that may or may not be profitable, performed)
	helpgroup(opt)
	set(OPTLEVEL=3)
	set(OPTCGARGS=
        -x 9 1           # -Munroll=c:1
        -x 42 0x14200000 # -Mlre=prefer
        -x 136 0x11	     # Branch prediction & BB placement
#		-x 53 10		 # Pointer target analysis
	)
	set(OPTF901ARGS=
		-x 53 2			# Pointer target analysis
	)
	set(OPTCARGS=-autoinl $AUTOLEVELS -x 168 $AUTOMAXFUNCSIZE -x 174 $AUTOMAXTOTALSIZE -x 14 0x200000 $ifn($NOSTATIC, -x 14 0x400000))
	set(AUTOINLINE=YES)
	set(NOFRAME=YES)	# -Mnoframe
    max(OPTLEVELDEF=3)  # -O3
    max(OPTLEVELMIN=3)  # -O3
    set(LLVMOPTLEVEL=$if($or($ARM,$X86_64), 3, 2))  # LLVM opt -O3
    set(LLVMLLCLEVEL=$if($or($ARM,$X86_64), 3, 2))  # LLVM llc -O3
    or(MVECTFASTFUSE=1)
    set(NOFRAME=YES)    # -Mnoframe

    shorthand(-Mvect=simd -Mflushz -Mcache_align)
    shorthand(-Mfactorize)
    shorthand(-Mno-signed-zeros) # NOTE: There are discussions about whether -O3
                                 #       should allow unsafe FP math or not.
	shorthand(-Minline_cpu_f)
	append(CGARGS=$OPTCGARGS)
	append(CARGS=$OPTCARGS)
	append(F901ARGS=$OPTF901ARGS)
	;

replace switch -O4 is
	help(Set opt level. All -O3 optimizations plus more aggressive hoisting of guarded expressions performed)
	helpgroup(opt)
	set(OPTLEVEL=4)
	set(OPTCGARGS=
		-x 9 1			# -Munroll=c:1
		-x 136 0x11		# Branch prediction & BB placement
#		-x 53 10		# Pointer target analysis
	)
	set(OPTF901ARGS=
		-x 53 2			# Pointer target analysis
	)
	set(OPTCARGS=-autoinl $AUTOLEVELS -x 168 $AUTOMAXFUNCSIZE -x 174 $AUTOMAXTOTALSIZE -x 14 0x200000 $ifn($NOSTATIC, -x 14 0x400000))
	set(AUTOINLINE=YES)
	set(NOFRAME=YES)	# -Mnoframe
	append(CGARGS=$OPTCGARGS)
	append(CARGS=$OPTCARGS)
	append(F901ARGS=$OPTF901ARGS)
	shorthand(-Mvect=simd)
	shorthand(-Mno-signed-zeros)
	shorthand(-Minline_cpu_f)
	;


switch -Ofast is
    help(Enable -O3 -Mfprelaxed -Mstack_arrays -Mno-nan -Mno-inf -fcx-limited-range)
    helpgroup(opt)
    shorthand(-O3)
    shorthand(-Mfprelaxed)
    shorthand(-Mstack_arrays)
    shorthand(-Mno-nan)
    shorthand(-Mno-inf)
    shorthand(-fcx-limited-range)
# enable new "Fast" math calls where scalar and vector implementations are
# not guaranteed to produce bit for bit results.
# aarch64:
# Only enable by default for processors that identify themselves as
# neoverse-v2 or the user explicitly compiles for neoverse-v2 (-tp neoverse-v2).
# For all other processors, user has to opt in using -Mx,15,0x2000.
# x86_64:
# Only enable for processors that have AVX2 support.
    append(CGARGS=$if($or($AVX2,$or($and($NO_TP_OR_TP_HOST,$equal($TP_HOST,neoverse-v2)),$equal($THISTP,neoverse-v2))), -x 15 0x2000))
    append(F902ARGS=$if($or($AVX2,$or($and($NO_TP_OR_TP_HOST,$equal($TP_HOST,neoverse-v2)),$equal($THISTP,neoverse-v2))), -x 15 0x2000))
    ;

# following flags copied from nativerc
# Currently we don't want to show them with Power or llvm compilers
# If we were to show these in any llvm target then we would need
# to split/move into target specific file

replace switch -Manno is hide
	help(Annotate assembly code with source; implies -Mkeepasm)
	helpgroup(overall)
	set(KEEPASM=YES)
	append(CGARGS=-anno);

replace switch -Mdalign is hide
	help(Align doubles on double alignment boundaries)
	helpname(-M[no]dalign)
	helpgroup(language)
	append(CPP1ARGS=--dalign)
	append(CGARGS=-dalign);

replace switch -Mnodalign is hide
	help(Align doubles on float alignment boundaries)
	helpgroup(language)
	append(CPP1ARGS=--nodalign)
	append(CGARGS=-nodalign);

replace switch -Mdwarf1 is hide
	help(Generate DWARF1 debug information with -g)
	helpgroup(debug)
	set(DEBUG2=)
	set(DEBUGCPP=);

replace switch -Mdwarf2 is hide
	help(Generate DWARF2 debug information with -g)
	helpgroup(debug)
	set(DEBUG2=-x 120 0x200)
	set(DEBUGCPP=--dwarf2);

replace switch -Mframe is hide
	help(Generate code to set up a stack frame)
	helpgroup(opt)
	helpname(-M[no]frame)
	set(NOFRAME=);

replace switch -Mlist is hide
	help(Generate a listing file)
	helpgroup(overall)
	helpname(-M[no]list)
	append(CARGS=-list)
	append(FARGS=-list);

replace switch -Mquad is hide
	help(Align large objects on quad-word boundaries)
	helpgroup(opt)
	append(CARGS=-quad);

replace switch -Mstack_arrays is
	help(Place automatic arrays on the stack)
	helpname(-M[no]stack_arrays)
	helpgroup(opt)
	append(CGARGS=$ifn($land($LNGSPA,$STDPARGPU),-x 54 0x08))
	append(F901ARGS=$ifn($land($LNGSPA,$STDPARGPU),-x 54 0x08));

replace switch -Mnostack_arrays is hide
	help(Do not place automatic arrays on the stack)
	helpgroup(opt)
	append(CGARGS=-y 54 0x08)
	append(F901ARGS=-y 54 0x08);

replace switch -Mstride0 is hide
	helpname(-M[no]stride0)
	helpgroup(opt)
	help(Generate code to check for zero loop increments)
	append(CGARGS=-x 70 1);

replace switch -Mnostride0 is hide
	help(Do not generate code to check for zero loop increments)
	helpgroup(opt)
	append(CGARGS=-y 70 1);

replace switch -Mzerotrip is hide
	helpname(-M[no]zerotrip)
	helpgroup(opt)
	help(Assume loops may not execute";" add zero-trip test)
	append(CGARGS=-y 19 0x800);

replace switch -Mnozerotrip is hide
	help(Assume loops always execute";" remove zero-trip test)
	helpgroup(opt)
	append(CGARGS=-x 19 0x800);

replace switch -Mcpp is hide early
	help(Just preprocess the input files)
	helpgroup(prepro)
	# -Mcpp uses the PGI preprocessor, not the EDG preprocessor
	set(OTHERPREPROCESS=otherpreprocess)
	set(GENPREPROCESS=genpreprocess)
	keyword(
	    m(
		append(PREPROARGS=-m)
		set(KEEPPREPRO=)
		help(Print makefile dependencies)
	    )
	    md(
		append(PREPROARGS=-md)
		set(KEEPPREPRO=)
		help(Print makefile dependencies to .d file)
	    )
	    mm(
		append(PREPROARGS=-mm)
		set(KEEPPREPRO=)
		help(Print makefile dependencies";" ignore system includes)
	    )
	    mmd(
		append(PREPROARGS=-mmd)
		set(KEEPPREPRO=)
		help(Print makefile dependencies to .d file";" ignore system includes)
	    )
	    mq:mqtarget(
		append(PREPROARGS=-mq $mqtarget)
		set(KEEPPREPRO=)
		help(Print makefile dependencies)
	    )
	    mt:mttarget(
		append(PREPROARGS=-mt $mttarget)
		set(KEEPPREPRO=)
		help(Print makefile dependencies)
	    )
	    line(
		append(PREPROARGS=-p)
		help(Insert line numbers into preprocess output)
	    )
	    comment(
		helpname([no]comment)
		append(PREPROARGS=-comment)
		help(Keep comments in preprocessed output)
	    )
	    nocomment( hide
		append(PREPROARGS=-nocomment)
		help(Don't keep comments in preprocessed output)
	    )
	    suffix:suff(
		append(PREPROARGS=$if($suff,-suffix $suff))
		help(Suffix to use for makefile dependencies)
	    )
	    "":suff(
		append(PREPROARGS=$if($suff,-suffix $suff))
		help(Suffix to use for makefile dependencies)
	    )
	    include:file(
		append(PREPROARGS=-include $file)
		help(Include file before processing source file)
	    )
	    b(
		append(PREPROARGS=-b)
		hide help(Support the C++/c99 comment indicator '//')
	    )
	    c89(
		append(PREPROARGS=-c89)
		help(Use the C89 language)
	    )
	    c99(
		append(PREPROARGS=-c99)
		help(Use the C99 language)
	    )
	)
	nokeyword()
	set(DEFKEEPPREPRO=YES)
	set(PREPROCONLY=YES)
	set(NOASM=YES)
	stopafter(Preproconly)
	enable(Preproconly)
	set(COMPILEONLY=YES);

replace switch -Qdir compdir is hide #not
	hide
	help(Change compiler directory)
	helpgroup(overall)
	set(CCOMPDIR=$compdir);

replace switch -Qpath comppath is hide #not
	hide
	help(Change compiler path)
	helpgroup(overall)
	set(CCOMPDIR=$comppath);

replace switch --version is hide
	early
	help(Display compiler version)
	helpgroup(overall)
  set(VERSION=$if($LOCALRC,1,0));

replace switch -W0,arg is hide
	help(Pass argument to compiler)
	helpgroup(overall)
	append(CGARGS=$replace($arg,",", ));

replace switch -Wll,arg is hide
	help(Pass argument to linker)
	helpgroup(linker)
	disable(NoFiles)
	set(LINKALWAYS=1)
	replace($arg)
	positional(linker);

replace switch -Wa,arg is
	help(Pass argument to assembler)
	helpgroup(asm)
	append(ASARGS=$replace($arg,",", ));

replace switch -Y0,compdir is hide
	help(Change compiler directory)
	helpgroup(overall)
	set(CCOMPDIR=$path($compdir));

replace switch -Ya,asdir is hide
	help(Change assembler directory)
	helpgroup(asm)
	set(ASDIR=$path($asdir));

replace switch -Yc,compdir is hide
	help(Change C++ compiler directory)
	helpgroup(overall)
	set(CPPCOMPDIR=$path($compdir));

replace switch -YC,complibdir is hide
	help(Change compiler library directory)
	helpgroup(linker)
	set(COMPLIB=$foreach(dd,$replace($complibdir,",", ),$path($dd) ));

replace switch -Yh,compdir is hide
	help(Change F90 front end directory)
	helpgroup(overall)
	set(HCOMPDIR=$path($compdir));

replace switch -YI,incdir is hide
	help(Change standard include directory)
	helpgroup(prepro)
	set(STDINC=$incdir);

replace switch -YII,incdir is hide
	help(Append to standard include directory list)
	helpgroup(prepro)
	append(USRSTDINC=$incdir);

replace switch -Yl,linkdir is hide
	help(Change linker directory)
	helpgroup(linker)
	set(LDDIR=$path($linkdir));

replace switch -YL,stdlibdir is hide
	help(Change standard library directory)
	helpgroup(linker)
	set(LIBDIR=$path($stdlibdir))
	append(LDARGS=-YL$stdlibdir);

replace switch -Yp,preprodir is hide
	helpgroup(prepro)
	help(Change preprocessor directory)
	set(PREPRODIR=$path($preprodir));

replace switch -YS,startupdir is hide
	help(Change startup object directory)
	helpgroup(linker)
	set(STDOBJDIR=$path($startupdir));

replace switch -YU,libdir is hide
	help(Change linker library area)
	helpgroup(linker)
	append(LDARGS=-YU$path($libdir));

replace switch -csuffix=suff is hide early
	help(Define a C suffix)
	helpgroup(language)
	append(USERCSUFFIX=$suff);

replace switch -cppsuffix=suff is hide early
	help(Define a C++ suffix)
	helpgroup(language)
	append(USERCPPSUFFIX=$suff);

replace switch -asmsuffix=suff is hide early
	help(Define a assembler language suffix)
	helpgroup(language)
	append(USERASMSUFFIX=$suff);

replace switch -Mobjsuffix=suff is hide early
	help(Define a object file suffix)
	helpgroup(language)
	append(USEROBJSUFFIX=$suff);

replace switch -Mlibsuffix=suff is hide early
	help(Define a library file suffix)
	helpgroup(language)
	append(USERLIBSUFFIX=$suff);

replace switch -Mnodbgstub is hide
	hide
	append(CGARGS=-x 50 0x100);

replace switch -versions is hide
	help(Print the available compiler versions)
	helpgroup(overall)
	disable(NoFiles)
	disable(OtherChecks)
	enable(Versions)
	stopafter(Versions);

replace switch -Mnosgimp is hide;

switch -Mnonewatomic is hide
	help(Do not use new atomic)
	set(OMPATMFLAGS=-x 69 0x1000);

variable KTRAP is default(0);
replace switch -Ktrap is
	help(Control IEEE floating point exception trapping)
	helpgroup(target)
       	set(trapval=0)
	set(notrapval=0)
	keyword(
	    divz(
		or(trapval=32) andnot(notrapval=32) #not
		help(Divide by zero))
	    denorm(
		or(trapval=16) andnot(notrapval=16)
	        error($if($notequal($X86_64,1), Switch  -Ktrap=denorm only supported on x86_64 targets))
		help(Denormalized (x86_64 only))) 
	    fp(
		or(trapval=1) andnot(notrapval=1)
		help(Shorthand for -Ktrap=inv,divz,ovf))
	    inexact(
		or(trapval=256) andnot(notrapval=256) #not
		help(Inexact))
	    inv(
		or(trapval=8) andnot(notrapval=8) #not
		help(Invalid))
	    none(
		and(trapval=0) or(notrapval=511)
		help(Clear exceptions E.g. -Ktrap=inv,none,ovf implies -Ktrap=ovf))
	    ovf(
		or(trapval=64) andnot(notrapval=64) #not
		help(Overflow))
	    unf(
		or(trapval=128) andnot(notrapval=128) #not
		help(Underflow))
	)
    set(KTRAP=$trapval)
	append(CGARGS=-x 24 0x80000000 $if($trapval,-x 24 $trapval) $if($notrapval,-y 24 $notrapval))
	set(LLVMOPTMCPU=);

switch	-ffpe-trap is
	help(Control IEEE floating point exception trapping)
	helpgroup(target)
	set(trapval=0)
	set(notrapval=0)
	keyword(
		invalid(
			help(Invalid)
			or(trapval=8) andnot(notrapval=8) #not
		)
		zero(
			help(Divide by zero)
			or(trapval=32) andnot(notrapval=32) #not
		)
		overflow(
			help(Overflow)
			or(trapval=64) andnot(notrapval=64) #not
		)
		underflow(
			help(Underflow)
			or(trapval=128) andnot(notrapval=128) #not
		)
		inexact(
			help(Inexact)
			or(trapval=256) andnot(notrapval=256) #not
		)
	)
	set(KTRAP=$trapval)
	append(CGARGS=-x 24 0x80000000 $if($trapval,-x 24 $trapval) $if($notrapval,-y 24 $notrapval))
;

switch -static-nvidia is
    help(Use to link static NVIDIA runtime libraries with dynamic system libraries; implies -Mnorpath)
    helpgroup(linker)
    set(PGISTATICX=-Bstatic)
    set(PGIUNSTATICX=$ifn($STATICLIB,-Bdynamic))
    set(PGISTATIC=-Bstatic)
    set(PGIUNSTATIC=$ifn($STATICLIB,-Bdynamic))
    set(ISSTATIC=1)
    set(STDRPATH=$if($equal($NOPGIRPATH,YES),,-rpath $COMPBASE/$COMPSYS/$COMPVER/$COMPLIBSUBDIR));

switch -static == -Bstatic;
switch -Bstatic_pgi is hide shorthand(-static-nvidia);
switch -Bstatic-nvidia is hide shorthand(-static-nvidia);

switch -Mvlv is hide;

### Floating point options

variable CX_LIMITED_RANGE is default(0);
append CGARGS=$if($CX_LIMITED_RANGE, -x 15 0x2000000);

switch -fcx-limited-range is
    help (Complex divide does not need range reduction)
    helpgroup(opt)
    set(CX_LIMITED_RANGE=1)
    ;

switch -fno-cx-limited-range is
    help (Complex divide does need range reduction)
    helpgroup(opt)
    set(CX_LIMITED_RANGE=0)
    ;

variable NONAN is default(0);
append CGARGS=$if($NONAN, -x 77 0x01);

switch -Mnan is
    help (Assume arguments and results can be NaN for optimizations)
    helpgroup(opt)
    set(NONAN=0);

switch -Mno-nan is
    help (Assume arguments and results are never NaN for optimizations)
    helpgroup(opt)
    set(NONAN=1);

variable NOINF is default(0);
append CGARGS=$if($NOINF, -x 77 0x02);

switch -Minf is
    help (Assume arguments and results can be Inf for optimizations)
    helpgroup(opt)
    set(NOINF=0);

switch -Mno-inf is
    help (Assume arguments and results are never Inf for optimizations)
    helpgroup(opt)
    set(NOINF=1);

variable NOSIGNEDZEROS is default(0);
append CGARGS=$if($NOSIGNEDZEROS, -x 77 0x04);

switch -Msigned-zeros is
    help (Do not ignore signed zeros for optimization purposes)
    helpgroup(opt)
    set(NOSIGNEDZEROS=0);

switch -Mno-signed-zeros is
    help (Ignore signed zeros for optimization purposes)
    helpgroup(opt)
    set(NOSIGNEDZEROS=1);

# Unimplemented
variable AFN is default(0x0);
variable REASSOC is default(0x0);

switch -ffinite-math-only is
    help(Assume arguments and results are never NaN or Inf for optimizations)
    helpgroup(opt)
    shorthand(-Mno-nan)
    shorthand(-Mno-inf)
    ;
switch -fno-finite-math-only is
    help(Assume arguments and results can be NaN or Inf for optimizations)
    helpgroup(opt)
    shorthand(-Mnan)
    shorthand(-Minf)
    ;

switch -fsigned-zeros is
    help(Do not ignore signed zeros for optimization purposes)
    helpgroup(opt)
    shorthand(-Msigned-zeros)
    ;
switch -fno-signed-zeros is
    help(Ignore signed zeros for optimization purposes)
    helpgroup(opt)
    shorthand(-Mno-signed-zeros)
    ;

variable LLVMFAST is default($or(0x0,
                                 $if($NONAN, 0x1, 0x0),
                                 $if($NOINF, 0x2, 0x0),
                                 $if($NOSIGNEDZEROS, 0x4, 0x0),
                                 $if($RECIPDIV, 0x8, 0x0),
                                 $if($LLVMFMA, 0x10, 0x0),
                                 $if($AFN, 0x20, 0x0),
                                 $if($REASSOC, 0x40, 0x0),
                                )
                            );

append CGARGS=$if($LLVMFAST, -x 207 $LLVMFAST);
switch -Mllvm-fast is hide
    help (Add 'fast' attributes to LLVM IR)
    helpgroup(opt)
    set(NONAN=1)
    set(NOINF=1)
    set(NOSIGNEDZEROS=1)
    set(RECIPDIV=1)
    set(LLVMFMA=1)
    set(AFN=1)
    set(REASSOC=1)
    ;

switch -Mno-llvm-fast is hide
    help (Do not add 'fast' attributes to LLVM IR)
    helpgroup(opt)
    set(NONAN=0)
    set(NOINF=0)
    set(NOSIGNEDZEROS=0)
    set(RECIPDIV=0)
    #set(LLVMFMA=0) # Don't shut down FMAs with -Mno-llvm-fast.
    set(AFN=0)
    set(REASSOC=0)
    ;

# Just an alias of -Mfma
switch -fma is hide
        helpgroup(opt)
        helpname(-[no]fma)
        help(Enable (disable) generation of FMA instructions for the CPU and GPU (alias for -Mfma))
        shorthand(-Mfma);

# Just an alias of -Mnofma
switch -nofma is hide
        helpgroup(opt)
        help(Disable generation of FMA instructions for the CPU and GPU (alias for -Mnofma))
        shorthand(-Mnofma);

switch -Mnv-fma is hide
        helpgroup(opt)
        helpname(-M[no]nv-fma)
        help(Enable (disable) NVIDIA generation of FMA instructions on the CPU)
        append(CGARGS=-x 172 0x40000000 -x 179 1);

switch -Mnonv-fma is hide
        helpgroup(opt)
        help(Disable NVIDIA generation of FMA instructions on the CPU)
        append(CGARGS=-x 171 0x40000000 -x 178 1);

switch -Mllvm-fma is hide
        helpgroup(opt)
        helpname(-M[no]llvm-fma)
        help(Enable (disable) LLVM generation of FMA instructions on the CPU)
        set(LLVMFMA=1);

switch -Mnollvm-fma is hide
        helpgroup(opt)
        help(Disable LLVM generation of FMA instructions on the CPU)
        set(LLVMFMA=0);

variable RECIPDIV is default(0);
append CGARGS=$if($RECIPDIV, -x 15 $RECIPDIV);

switch -Mrecip-div is
    help (Rewrite x/y => x*1/y if profitable)
    helpgroup(opt)
    set(RECIPDIV=$if($KTRAP, 0x0, 0x4));

switch -Mno-recip-div is
    help (Disable x/y => x*1/y rewrite)
    helpgroup(opt)
    set(RECIPDIV=0x0);

variable FACTORIZE is default(0x2);
switch -Mfactorize is
    help (Enable factorization)
    helpgroup (opt)
    set(FACTORIZE=0x2)
    append(CGARGS=$if($FACTORIZE, -x 56 $FACTORIZE));

switch -Mno-factorize is
    help (Disable factorization)
    helpgroup (opt)
    set(FACTORIZE=0x0);

variable INITLOCAL is default(0);
append CGARGS=$if($INITLOCAL, -x 33 $INITLOCAL);

# type    init value  bit
# ----    ----------  ---
# reals    0.0        0x1
# reals    snan       0x2
#
# int      0          0x100
# int      <n>        0x200
#
# logical  .false.    0x1000
# logical  .true.     0x2000
#
# ------------------------
# Other  (-Minfo msg) 0x80000000

switch -Minit-local-zero is
    help(Initialize local {integer, real, logical} variables and arrays to 0)
    helpgroup(opt)
    or(INITLOCAL=0x1101); 

switch -Minit-real is
    help(Initialize local real variables and arrays to a specific value below:)
    helpgroup(opt)
    onekeyword
    keyword(
      zero(help(0.0)
           or(INITLOCAL=0x1))
      snan(help(signaling NaNs)
           or(INITLOCAL=0x2))
    );

switch -Minit-integer=n is
    help(Initialize local integer*4 and integer*8 variables and arrays to <n>)
    helpgroup(opt)
    or(INITLOCAL=0x200)
    append(CGARGS=-x 243 $n);

switch -Minit-logical is
    help(Initilize local logical*4 and logical*8 variables and arrays to true or false)
    helpgroup(opt)
    onekeyword
    keyword(
      true(help(initialize to .true.)
           or(INITLOCAL=0x2000))
      false(help(initialize to .false.)
           or(INITLOCAL=0x1000))
    );
    
switch -Minit-msg is
    help(Issue a compiler message via -Minfo for initialized variables and arrays)
    helpgroup(opt)
    or(INITLOCAL=0x80000000);


variable LLVM_NOLV is default(0);
append LLVMOPTUSERARGS=$if($LLVM_NOLV, -force-vector-width=1 -force-vector-interleave=1);
switch -Mllvm-nolv is hide
    help (Disable LoopVectorize in LLVM)
    helpgroup(opt)
    set(LLVM_NOLV=1);

append LLVMOPTUSERARGS=$if($LLVM_NOSLP, -vectorize-slp=false);
switch -Mllvm-noslp is hide
    help (Disable SLP in LLVM)
    helpgroup(opt)
    set(LLVM_NOSLP=1);

switch -Mllvm-novect is hide
    help (Disable SLP and LoopVectorize in LLVM)
    helpgroup(opt)
    shorthand(-Mllvm-nolv)
    shorthand(-Mllvm-noslp);

switch -Mnovect is
    help(Disable loop restructuring relating to SIMD code generation)
    helpgroup(opt)
    shorthand(-Mllvm-novect)
    set(VECT=0)
    set(MVECT=);

variable LLVMUNROLL is default(1);
append LLVMOPTUSERARGS=$ifn($LLVMUNROLL,-unroll-count=0);

switch -Mllvm-nounroll is hide
    help (Disable LLVM unrolling)
    helpgroup(opt)
    set(LLVMUNROLL=0);

switch -Mllvm-noinline is hide
    help (Add 'noinline' to function attributes to disable LLVM's inliner)
    helpgroup(opt)
    append(CGARGS=-x 183 0x80);

variable LLVM_FUNCSPEC is default(0);
append LLVMOPTUSERARGS=$if($LLVM_FUNCSPEC,
  # LLVM 16.0.
  $if($expr($LLVMVERINT < 170),
    $if($USECLANG,-mllvm) -function-specialization-for-literal-constant $if($USECLANG,-mllvm) -func-specialization-max-iters=8)
  # LLVM 17.0 and 18.0.
  $if($and($expr($LLVMVERINT >= 170), $expr($LLVMVERINT < 190)),
    $if($USECLANG,-mllvm) -funcspec-for-literal-constant $if($USECLANG,-mllvm) -funcspec-max-iters=8)
  # LLVM 19.0 and on.
  $if($expr($LLVMVERINT >= 190),
    $if($USECLANG,-mllvm) -funcspec-for-literal-constant $if($USECLANG,-mllvm) -funcspec-max-iters=8
    $if($USECLANG,-mllvm) -funcspec-max-codesize-growth=5 $if($USECLANG,-mllvm) -funcspec-min-codesize-savings=9));

switch -Mllvm-nofuncspec is hide
    help (Disable ipsccp and function specialisation in LLVM)
    helpgroup(opt)
    set(LLVM_FUNCSPEC=0);

switch -Mllvm-funcspec is hide
    help (Enable ipsccp and function specialisation in LLVM)
    helpgroup(opt)
    set(LLVM_FUNCSPEC=1);


switch -pgf77libs is 
       help(Deprecated; see -fortranlib)
       shorthand(-fortranlibs);
switch -pgf90libs is 
       help(Deprecated; see -fortranlibs)
       shorthand(-fortranlibs);

switch -fortranlibs is
	help(Append Fortran libraries to the link line)
	helpgroup(linker)
	set(LRTLIB=$LRTLIBNAME)
	set(NOSTDFTNLIBS=)
	append(USRFTNRTL=$PGF90LIB);

switch -nvflanglibs is hide
	help(Append Fortran libraries to the link line)
	helpgroup(linker)
	set(LRTLIB=$LRTLIBNAME)
	set(NOSTDFTNLIBS=)
	set(NEEDFLANGLIBS=1)
	append(USRFTNRTL=$PGF90LIB $FLANGLIBS);

variable DOFPIC is
  default();
variable DOFPIE is
  default();
variable FPICVAL is
  default();
variable FPIC is
  default();

append USRDDEF=$if($DOFPIC,-D__PIC__=$FPICVAL);
append USRDDEF=$if($DOFPIE,-D__PIE__=$FPICVAL);
append USRDDEF=$if($DOFPIC,-D__pic__=$FPICVAL);
append USRDDEF=$if($DOFPIE,-D__pie__=$FPICVAL);
append USRDEFDEF=$if($DOFPIC,-def __PIC__=$FPICVAL);
append USRDEFDEF=$if($DOFPIE,-def __PIE__=$FPICVAL);
append USRDEFDEF=$if($DOFPIC,-def __pic__=$FPICVAL);
append USRDEFDEF=$if($DOFPIE,-def __pie__=$FPICVAL);

append CGARGS=$if($DOFPIC,-x 62 8);
switch -fpic is
  help(Generate position independent code)
  helpgroup(opt)
  helpname(-f[no-]pic)
  set(DOFPIC=1)
  set(FPICVAL=1)
  set(FPIC=-fpic);
switch -fno-pic is hide
  help(Generate position independent code)
  helpgroup(opt)
  set(DOFPIC=)
  set(FPIC=);

switch -fPIC is
  help(Generate position independent code)
  helpgroup(opt)
  helpname(-f[no-]PIC)
  set(DOFPIC=1)
  set(FPICVAL=2)
  set(FPIC=-fPIC);
switch -fno-PIC is hide
  help(Generate position independent code)
  helpgroup(opt)
  set(DOFPIC=0)
  set(FPIC=);

switch -fPIE is
  help(Generates position independent executable.)
  helpname(-f[no-]PIE)
  helpgroup(opt)
  set(DOFPIC=1)
  set(DOFPIE=1)
  set(PASSPIE=1)
  set(FPICVAL=2)
  set(FPIC=-fPIE)
  set(LCRT1=$STDOBJDIR/Scrt1.o)
  set(LCRTB=$GCCDIR/crtbeginS.o)
  set(LCRTE=$GCCDIR/crtendS.o);
switch -fno-PIE is hide
  helpgroup(opt)
  set(DOFPIC=0)
  set(DOFPIE=0)
  set(PASSPIE=0)
  set(FPIC=)
  set(LCRT1=$STDOBJDIR/crt1.o)
  set(LCRTB=$GCCDIR/crtbegin.o)
  set(LCRTE=$GCCDIR/crtend.o);

switch -fpie is
  help(Generates position independent executable.)
  helpname(-f[no-]pie)
  helpgroup(opt)
  set(DOFPIC=1)
  set(DOFPIE=1)
  set(PASSPIE=1)
  set(FPICVAL=1)
  set(FPIC=-fpie)
  set(LCRT1=$STDOBJDIR/Scrt1.o)
  set(LCRTB=$GCCDIR/crtbeginS.o)
  set(LCRTE=$GCCDIR/crtendS.o);
switch -fno-pie is hide
  helpgroup(opt)
  set(DOFPIC=0)
  set(DOFPIE=0)
  set(PASSPIE=0)
  set(FPIC=)
  set(LCRT1=$STDOBJDIR/crt1.o)
  set(LCRTB=$GCCDIR/crtbegin.o)
  set(LCRTE=$GCCDIR/crtend.o);

switch -pie is
  help(Passes -pie to linker. -fPIE also implies -pie)
  helpname(-[no-]pie)
  helpgroup(opt)
  set(PASSPIE=1);
switch -no-pie is hide
  help(Do not pass -pie to linker)
  helpgroup(opt)
  set(PASSPIE=0);
