# 
#     Copyright (c) 2017-2024, NVIDIA CORPORATION.  All rights reserved.
#     , 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.
# 

# llc command take files with suffixes .ll, .llvm 

# llopt commands takes .ll .llvm and output .bc

suffix ll is
        help(LLVM Intermediate Representation file)
        string(ll);

suffix bc is
        help(LLVM Intermediate Representation file)
        string(bc);

suffix llvm is
        help(LLVM Intermediate Representation file)
        string(llvm);

# variable LLCARCH  -march=
# variable LLCMCPU  -mcpu=X, passed to llc
# variable LLVMOPTMCPU -mcpu=X, passed to opt
# variable LLCMATTR -mattr=
# variable LLCFLOATABI -mabi-float=
# variable LLCARGS  any other flags to llc, can be passed by -Wl,llc
# variable LLCPIC   -relocation-model=pic

variable LLC is default(llc);
variable LLVMAS is default("llvm-as");
variable LLVMLINK is default("llvm-link");
variable LLVMDIR is default($COMPBASE/$COMPSYS/$COMPVER/$COMPBSHARE/llvm);
variable LLCARCH is default();

# Allow -Wllc to override the default -mcpu. (There can only be one)
variable DEFLLCMCPU is default($if($LLCSKIPNATIVE,,-mcpu=native));
variable LLCMCPU is default($ifn($contains($LLCARGS,-mcpu=),$DEFLLCMCPU));

# Allow -Wllc to override the default -fast-isel. (There can only be one)
variable DEFLLCFASTISEL is default();
variable LLCFASTISEL is default($ifn($contains($LLCARGS,-fast-isel),$DEFLLCFASTISEL));

# Allow -Wopt to override the default -mcpu. (There can only be one)
variable DEFLLVMOPTMCPU is default($if($LLVMOPTSKIPNATIVE,,-mcpu=native));
variable LLVMOPTMCPU is default($ifn($contains($LLVMOPTARGS,-mcpu=),$DEFLLVMOPTMCPU));

variable LLCMATTR is default();
variable LLCFLOATABI is default();
variable LLCX86CMOV is default(0);
variable LLFASTMATH is default(0);
variable LLCPIC is default();
variable LLCOPT is default();
variable LLCISEL is default();
variable LLCOPTMAX is default($if($TARGETLLCOPTMAX,$TARGETLLCOPTMAX,3));
variable LLCSUFFIX is default(ll llvm);
variable LLVMASSUFFIX is default(ll llvm);
variable LLVMLINKSUFFIX is default(bc);
variable LLOPTSUFFIX is default(ll llvm);
variable LLVMOPTLEVEL is default(2);
variable LLVMOPTLEVELOVERRIDE is default();
variable LLVMLLCLEVEL is default($if($expr($OPTLEVEL>$LLCOPTMAX),$LLCOPTMAX,$OPTLEVEL));
variable LLVMLLCLEVELOVERRIDE is default();
variable LLVMOPTARGS1 is default(-tbaa -targetlibinfo -basicaa -domtree -verify -simplifycfg -domtree -sroa -early-cse -lower-expect);
variable LLVMOPTARGS2 is default(-targetlibinfo -tbaa -basicaa -domtree -verify -globalopt -ipsccp -deadargelim -instcombine -simplifycfg -basiccg -prune-eh -inline -functionattrs -argpromotion -sroa -domtree -early-cse -lazy-value-info -jump-threading -correlated-propagation -simplifycfg -instcombine -tailcallelim -simplifycfg -reassociate -domtree -loops -loop-simplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loop-simplify -lcssa -indvars -loop-idiom -loop-deletion -loop-unroll -memdep -gvn -memdep -memcpyopt -sccp -instcombine -lazy-value-info -jump-threading -correlated-propagation -domtree -memdep -dse -adce -simplifycfg -instcombine -strip-dead-prototypes -globaldce -constmerge -globalopt -ipsccp -deadargelim -instcombine -simplifycfg -basiccg -prune-eh -inline -functionattrs -sroa -domtree -early-cse -lazy-value-info -jump-threading -correlated-propagation -simplifycfg -instcombine -tailcallelim -simplifycfg -reassociate -domtree -loops -loop-simplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loop-simplify -lcssa -indvars -loop-idiom -loop-deletion -loop-unroll -memdep -gvn -memdep -memcpyopt -sccp -instcombine -lazy-value-info -jump-threading -correlated-propagation -domtree -memdep -dse -adce -simplifycfg -instcombine -strip-dead-prototypes -globaldce -constmerge -domtree -verify);
variable LLVMOPT2PASS is default(NO);
variable LLCMODEL is default();

# We shouldn't need these if all of our IR instructions are properly decorated
# with the FMF attributes.
variable LLUNSAFEMATH is default(
				 $if($LLFASTMATH, --enable-unsafe-fp-math)
				 $if($NONAN, --enable-no-nans-fp-math) 
				 $if($NOINF, --enable-no-infs-fp-math)
				 # Guard nsz with $LLFASTMATH. Signed zeros at default is too aggressive.
				 $if($and($LLFASTMATH,$NOSIGNEDZEROS), --enable-no-signed-zeros-fp-math)
				);

variable LLCFRAMEPOINTER is default($if($REALNOFRAME,--frame-pointer=none,--frame-pointer=non-leaf));
variable LLVMENABLEOLDPM is default();

# FMA options
# We only enable FMAs for -O3 right now so that CPU FMA generation does not
# diverge too much from GPU FMA generation.  
variable LLVMFMA is default($if($ARM,1,0));
variable FPCONTRACT is default();
set FPCONTRACT=$if($LLVMFMA ,$if($USECLANG,-f,--)fp-contract=$if($expr($OPTLEVEL>2),fast,on),);

# Give flexibility to control the value of -passes= to LLVM
# The format of the value is default<O2> pass1 pass2...
# Later whitespace will be replaced by comma.
variable LLVMPASSESVAL is default();
append LLVMPASSESVAL= $ifn($LLVMOPTLEVELOVERRIDE, default<O$LLVMOPTLEVEL>);

# Universal Clang and LLVM opt arguments.
# Make sure to update when changing LLVM versions.
variable OPTOLEVEL is default($ifn($LLVMOPTLEVELOVERRIDE, $if($LLVMENABLEOLDPM, -O$LLVMOPTLEVEL, -passes=$replace($LLVMPASSESVAL, ,","))));

# Default LLVM opt arguments.
variable CLANGOPTARGS is default($LLVM19_OPTARGS_LLVM);
variable LLVMOPTARGS is default($LLVM19_OPTARGS_NV);
# Additional arguments to LLVM opt.
variable LLVMOPTAPPENDARGS is default();

# Default LLVM llc arguments.
variable LLCARGS is default($LLVM19_LLCARGS_NV);
# Additional arguments to LLVM llc.
variable LLCAPPENDARGS is default();

# LLVM 16.0 opt and llc arguments.
variable LLVM16_OPTARGS_LLVM is default($OPTOLEVEL $FPCONTRACT $LLVMOPTUSERARGS $OPT160ARGS $OPTTARGET160ARGS);
variable LLVM16_OPTARGS_NV is default($LLVM16_OPTARGS_LLVM $LLVMOPTAPPENDARGS
                                      $LLVMSTALECHECK $NVOPTTARGET160ARGS
                                      $ifn($OVERRIDE_AA_FOR_TBAA, -override-aa-for-tbaa=false));
variable LLVM16_LLCARGS_LLVM is default($LLCTARGET160ARGS $LLVMLLCUSERARGS $FPCONTRACT
                                        -non-global-value-max-name-size=4294967295
                                        --align-all-functions=$if($equal($TARGET,linuxpower),7,6));
variable LLVM16_LLCARGS_NV is default($LLVM16_LLCARGS_LLVM $LLC160ARGS
                                      $LLCAPPENDARGS $NVLLCTARGET160ARGS
                                      $ifn($OVERRIDE_AA_FOR_TBAA, -override-aa-for-tbaa=false));

# LLVM 17.0 opt and llc arguments.
variable LLVM17_OPTARGS_LLVM is default($OPTOLEVEL $FPCONTRACT $LLVMOPTUSERARGS $OPT170ARGS $OPTTARGET170ARGS);
variable LLVM17_OPTARGS_NV is default($LLVM17_OPTARGS_LLVM $LLVMOPTAPPENDARGS
                                      $LLVMSTALECHECK $NVOPTTARGET170ARGS
                                      $ifn($OVERRIDE_AA_FOR_TBAA, -override-aa-for-tbaa=false));
variable LLVM17_LLCARGS_LLVM is default($LLCTARGET170ARGS $LLVMLLCUSERARGS $FPCONTRACT
                                        -non-global-value-max-name-size=4294967295
                                        --align-all-functions=$if($equal($TARGET,linuxpower),7,6));
variable LLVM17_LLCARGS_NV is default($LLVM17_LLCARGS_LLVM $LLC170ARGS
                                      $LLCAPPENDARGS $NVLLCTARGET170ARGS
                                      $ifn($OVERRIDE_AA_FOR_TBAA, -override-aa-for-tbaa=false)
                                      $if($NVMEMCPY, -nvhpc-memcpy)
                                      $if($NVMEMZERO, -nvhpc-memzero));

# LLVM 18.0 opt and llc arguments.
# FIXME: Update to LLVM 18.0
variable LLVM18_OPTARGS_LLVM is default($OPTOLEVEL $FPCONTRACT $LLVMOPTUSERARGS $OPT180ARGS $OPTTARGET180ARGS);
variable LLVM18_OPTARGS_NV is default($LLVM18_OPTARGS_LLVM $LLVMOPTAPPENDARGS
                                      $LLVMSTALECHECK $NVOPTTARGET180ARGS
                                      $ifn($OVERRIDE_AA_FOR_TBAA, -override-aa-for-tbaa=false)
                                      -nvhpc-unswitch-loops-with-trip-count=2);
variable LLVM18_LLCARGS_LLVM is default($LLCTARGET180ARGS $LLVMLLCUSERARGS $FPCONTRACT
                                        -non-global-value-max-name-size=4294967295
                                        --align-all-functions=$if($equal($TARGET,linuxpower),7,6));
variable LLVM18_LLCARGS_NV is default($LLVM18_LLCARGS_LLVM $LLC180ARGS
                                      $LLCAPPENDARGS $NVLLCTARGET180ARGS
                                      $ifn($OVERRIDE_AA_FOR_TBAA, -override-aa-for-tbaa=false)
                                      $if($NVMEMCPY, -nvhpc-memcpy)
                                      $if($NVMEMZERO, -nvhpc-memzero));

# LLVM 19.0 opt and llc arguments.
# FIXME: Update to LLVM 19.0
variable LLVM19_OPTARGS_LLVM is default($OPTOLEVEL $FPCONTRACT $LLVMOPTUSERARGS $OPT190ARGS $OPTTARGET190ARGS);
variable LLVM19_OPTARGS_NV is default($LLVM19_OPTARGS_LLVM $LLVMOPTAPPENDARGS
                                      $LLVMSTALECHECK $NVOPTTARGET190ARGS
                                      $ifn($OVERRIDE_AA_FOR_TBAA, -override-aa-for-tbaa=false)
                                      -nvhpc-finite-opts=false
                                      -nvhpc-unswitch-loops-with-trip-count=2
                                      -enable-infer-alignment-pass=false);
variable LLVM19_LLCARGS_LLVM is default($LLCTARGET190ARGS $LLVMLLCUSERARGS $FPCONTRACT
                                        -non-global-value-max-name-size=-1
                                        --align-all-functions=$if($equal($TARGET,linuxpower),7,6));
variable LLVM19_LLCARGS_NV is default($LLVM19_LLCARGS_LLVM $LLC190ARGS
                                      $LLCAPPENDARGS $NVLLCTARGET190ARGS
                                      $ifn($OVERRIDE_AA_FOR_TBAA, -override-aa-for-tbaa=false)
                                      $if($NVMEMCPY, -nvhpc-memcpy)
                                      $if($NVMEMZERO, -nvhpc-memzero)
                                      -nvhpc-dso-opt);

# LLVM 20.0 opt and llc arguments.
# FIXME: Update to LLVM 20.0
variable LLVM20_OPTARGS_LLVM is default($OPTOLEVEL $FPCONTRACT $LLVMOPTUSERARGS $OPT200ARGS $OPTTARGET200ARGS);
variable LLVM20_OPTARGS_NV is default($LLVM20_OPTARGS_LLVM $LLVMOPTAPPENDARGS
                                      $LLVMSTALECHECK $NVOPTTARGET200ARGS
                                      $ifn($OVERRIDE_AA_FOR_TBAA, -override-aa-for-tbaa=false)
                                      -nvhpc-unswitch-loops-with-trip-count=2);
variable LLVM20_LLCARGS_LLVM is default($LLCTARGET200ARGS $LLVMLLCUSERARGS $FPCONTRACT
                                        -non-global-value-max-name-size=-1
                                        --align-all-functions=$if($equal($TARGET,linuxpower),7,6));
variable LLVM20_LLCARGS_NV is default($LLVM20_LLCARGS_LLVM $LLC200ARGS
                                      $LLCAPPENDARGS $NVLLCTARGET200ARGS
                                      $ifn($OVERRIDE_AA_FOR_TBAA, -override-aa-for-tbaa=false)
                                      $if($NVMEMCPY, -nvhpc-memcpy)
                                      $if($NVMEMZERO, -nvhpc-memzero));

# Clang arguments.
variable CLANGUSERARGS is default();
variable CLANGARGS is default($CLANGOPTARGS $CLANGUSERARGS);
variable CLANGPIC is default();

# Global (all target) LLVM Version Options
variable OPTCOMMONARGS is default();
set OPTCOMMONARGS=$if($LLVMENABLEOLDPM, -enable-new-pm=0)
                  $if($USECLANG,-mllvm) -slp-vectorize-hor=$if($SLPVECTORIZEHOR,true,false);
variable OPT160ARGS is default($OPTCOMMONARGS);
variable OPT170ARGS is default($OPTCOMMONARGS);
variable OPT180ARGS is default($OPTCOMMONARGS);
variable OPT190ARGS is default($OPTCOMMONARGS);

variable LLCCOMMONARGS is default();
variable LLC160ARGS is default($LLCCOMMONARGS);
variable LLC170ARGS is default($LLCCOMMONARGS);
variable LLC180ARGS is default($LLCCOMMONARGS);
variable LLC190ARGS is default($LLCCOMMONARGS);

# Set LLVM Default Version Options
variable LLVMVERSION is default(19.0);
variable LLVMVERINT is default(190);
# End LLVM Default Version Options

variable DEFCLANGMCPU is default(
	$if($equal($TARGET,linux86-64),
		# If linux86-64 set -march=<same-val-as-mcpu>
		# Don't use $LLCARCH
		# strip leading "-mcpu" (keep from "=" onwards)
		-march$substr($LLCMCPU,5,),
		# else use setting from LLCARCH (if any)
		$LLCARCH
	)
	$LLCMCPU);

variable CLANGMCPU is default($ifn($contains($CLANGUSERARGS,-mcpu=),$DEFCLANGMCPU));
variable CLANGMODEL is default($replace($LLCMODEL,-code-model,-mcmodel));

variable LLVMCOMPBIN is
        help(LLVM Utils directory )
        default($LLVMDIR/bin);

variable CLANGCOMPBIN is
        help(Clang directory )
        default($LLVMDIR/bin);

variable CLANGCMD is
        default(clang);

variable CLANG is
        default(clang);

variable NVBE is
        default(nvbe);

variable LLVMVERFLAGS is
        default(-x 249 $LLVMVERINT);

variable LLVMASCMD is
        default("llvm-as");

variable LLVMLINKCMD is
        default("llvm-link");

variable LLCCMD is
        default(llc);

variable LLVMOPTCMD is
        default(llvmopt);

variable LLCDONE is
        default();

variable LLOPT is
        default(opt);

variable LLVMMC is
        default("llvm-mc");

variable LLVMMCARGS is default();
variable DEFLLVMMCMCPU is default($if($AVX512VL,-mcpu=skylake-avx512,$LLCMCPU));
variable LLVMMCMCPU is default($ifn($contains($LLVMMCARGS,-mcpu=),$DEFLLVMMCMCPU));
variable LLVMMCATTR is default($LLCMATTR);
variable LLVMMCARCH is default($replace($LLCARCH,-march=,-arch=)); # Substitute -march with -arch

# Contains list of extra bitcode files (e.g. runtime in .bc format) to
# be passed to llc at compile time
variable BITCODERT is default(
    $NVOMPBCLIB
);
variable USEBITCODERT is default($if($BITCODERT,1,0));

# set to YES of user specify -Mllvmopt
variable LLVMOPT is             # set by -ll
        help(Go through LLVM opt tool)
        default();

variable KEEPLL is              # set by -ll
        help(Keeps the intermediate llvm assembly description file)
        default();

variable KEEPLLVM is            # set by -ll
        help(Keeps llvm file after the optimization)
        default();

variable LLVMASMONLY is         # set by -ll
        help(Keeps llvm file after the optimization)
        default();

variable KEEPBC is
        help(Keep byte-code file)
        default();

variable PGLLVMVFP is
        default($if($equal($ARM32, linuxarm-hf), -x 184 1,));

variable USELLVMAS is
        help(Using either the LLVM integrated assembler or llvm-mc)
        default(1);

switch -Masm is hide
        help(Override the assembler)
        helpgroup(overall)
        keyword(
          "gnu"(
              help(Use GNU's assembler)
              set(USELLVMAS=0)
             )
          "llvm"(
              help(Use LLVM's assembler)
              set(USELLVMAS=1)
             )
         )
         ;

variable LLNASM is
        default($if($USELLVMAS,"llvm-mc",Nasm));

set ASMCOMMAND=$if($USELLVMAS,$LLVMMC,asm);
variable LLVMDO is
        default($if($USELLVMAS,$ifn($COMPILEONLY$KEEPASM,YES)));

variable LLCDO is
        default();

tool "llvm-as" is
        help(llvm .ll -> .bc assembler)
        program($LLVMAS) directory($LLVMCOMPBIN);
tool "llvm-link" is
        help(llvm linker)
        program($LLVMLINK) directory($LLVMCOMPBIN);
tool llc is
        help(llvm object compiler)
        program($LLC) directory($LLVMCOMPBIN);
tool llopt is
        help(llvm optimizer)
        program($LLOPT) directory($LLVMCOMPBIN);
tool llvmmc is
        help(llvm assembler)
        program($LLVMMC) directory($LLVMCOMPBIN);
tool clang is
        help(clang compiler to llvm files to objects files)
        program($CLANG) directory($CLANGCOMPBIN);
tool nvbe is
        help(llvm optimizer + object compiler)
        program($NVBE) directory($LLVMCOMPBIN);

# LLVM 12.0 and newer should disable loop idiom recognition if -Mvect=noidiom
# is specified.
variable LLVMOPTNOIDIOM is
	help(llvm optimizer - disable loop idiom recognition)
	default($if($and($MVECTIDIOM,$expr($LLVMVERINT >= 120)), -disable-loop-idiom-all));

replace command "llvm-mc" is
        help(LLVM assembler)
        tool(llvmmc)
        suffix($ASMSUFFIX)
        set(objfile=$if($and($KEEPOBJ,$equal($POSTASM,)),$if($and($ASMONLY,$notequal($OUTFILE,)),$OUTFILE,$if($notequal($OBJDIR,),$OBJDIR/)$basename($file).$OBJSUFFIX),$tempfile($OBJSUFFIX)))
        append(linkfiles=$if($equal($POSTASM,),$objfile))
        append(objfiles=$if($equal($POSTASM,),$objfile))
        arguments($input -o $objfile -filetype=obj $LLVMMCMCPU $LLVMMCATTR $LLVMMCARCH $LLVMMCARGS)
        execute(
            condition($notequal($POSTASM,))
            input($objfile)
            command($POSTASM)
        )
        execute(
            condition($and($doappend,$equal($POSTASM,)))
            input($objfile)
            command(append)
        )
        ;

replace command llvmopt is
        help(LLVM OPT)
        tool(llopt)
        suffix($if($USEBITCODERT,$LLVMLINKSUFFIX,$LLOPTSUFFIX))
        set(llvmbcfile=$ifn($NOASM,$if($and($COMPILEONLY,$notequal($OUTFILE,)),$OUTFILE,$ifn($KEEPTEMP$KEEPLL,$tempfile(llvm),$if($and($ASMONLY,$notequal($OUTFILE,)),$dirname($OUTFILE)/$basename($OUTFILE).llvm,$basename($file).llvm)))))
        set(OPTFASTMATH=$if($equal($IEEE,), $LLUNSAFEMATH))
        arguments($LLVMOPTPARGS $LLVMOPTMCPU $OPTFASTMATH $LLVMOPTNOIDIOM $if($equal($substr($input,0,0),-),./$input,$input) -S -o $llvmbcfile)
        set(LLVMOPT=YES)
        ;

command "llvm-as" is
        help(llvm .ll -> .bc assembler)
        tool("llvm-as")
        suffix($LLVMASSUFFIX)
        set(outsuffix=$LLVMLINKSUFFIX)
        set(objkeep=$if($LLVMDO,$KEEPOBJ))
        set(inputfile=$if($equal($substr($input,0,0),-),./$input,$input))
        set(outputfile=$dirname($inputfile)/$basename($inputfile).$outsuffix)
        arguments($inputfile -o $outputfile)
        execute(
	        condition($USEBITCODERT)
	        input($outputfile)
	        command($LLVMLINK)
        );

command "llvm-link" is
        help(llvm linker)
        tool("llvm-link")
        suffix($LLVMLINKSUFFIX)
        set(outsuffix=$LLVMLINKSUFFIX)
        set(objkeep=$if($LLVMDO,$KEEPOBJ))
        set(inputfile=$if($equal($substr($input,0,0),-),./$input,$input))
        set(outputfile=$dirname($inputfile)/$basename($inputfile).link.$outsuffix)
        arguments($inputfile $BITCODERT -o $outputfile)
        execute(
            input($outputfile)
            command($LLCCMD)
        );

replace command llc is
        help(LLVM assembler)
        tool(llc)
        suffix($if($USEBITCODERT,$LLVMLINKSUFFIX,$LLCSUFFIX))
        set(LLCDO=$if($LLVMDO,-filetype=obj))
        set(outsuffix=$if($LLVMDO,$if($equal($TARGET,win64-llvm),obj,o),s))
        set(objkeep=$if($LLVMDO,$KEEPOBJ))
        set(asmfile=$ifn($NOASM,$if($and($COMPILEONLY,$notequal($OUTFILE,)),$OUTFILE,$ifn($KEEPTEMP$KEEPASM$KEEPLL$objkeep,$tempfile($outsuffix),$if($and($ASMONLY,$notequal($OUTFILE,)),$if($LLVMDO,$OUTFILE,$dirname($OUTFILE)/$basename($OUTFILE).$outsuffix),$basename($file).$outsuffix)))))
        append(linkfiles=$if($LLVMDO,$if($equal($POSTASM,),$asmfile)))
        append(objfiles=$if($LLVMDO,$if($equal($POSTASM,),$asmfile)))
        set(llcinputfile=$if($equal($substr($input,0,0),-),./$input,$input))
        set(LLCPIC=$if($DOFPIC,-relocation-model=pic))
        set(LLCOPT=$ifn($LLVMLLCLEVELOVERRIDE, -O$LLVMLLCLEVEL))
        set(LLCISEL=$LLCFASTISEL)
        set(LLCDONE=YES)
        set(LLCFASTMATH=$if($equal($IEEE,), $LLUNSAFEMATH))
        execute(
               input($input)
               condition($equal($COROUTINES,1))
               set(LLVMOPTPARGS=-passes=module(coro-early),cgscc(coro-split,coro-elide),module(coro-cleanup))
               set(LLVMSUFFIX=llvm)
               command(llvmopt)
               set(llcinputfile=$llvmbcfile)
               set(LLVMOPT=NO)
               )
        execute( 
               input($input)
               condition($notequal($LLVMOPT,NO))
               condition($equal($LLVMOPT2PASS,NO))
               condition($or($equal($LLVMOPT,YES),$or($expr($OPTLEVEL > 1),$expr($OPTLEVELMIN > 1))))
               set(LLVMOPTPARGS=$LLVMOPTARGS)
               set(LLVMSUFFIX=llvm)
               command(llvmopt)
               set(llcinputfile=$llvmbcfile)
               )
        execute( 
               input($input)
               condition($notequal($LLVMOPT,NO))
               condition($equal($LLVMOPT2PASS,YES))
               condition($or($equal($LLVMOPT,YES),$or($expr($OPTLEVEL > 1),$expr($OPTLEVELMIN > 1))))
               set(LLVMSUFFIX=tmp.ll)
               set(LLVMOPTPARGS=$LLVMOPTARGS1)
               command(llvmopt)
               set(input=$llvmbcfile)
               set(LLVMSUFFIX=llvm)
               set(LLVMOPTPARGS=$LLVMOPTARGS2)
               command(llvmopt)
               set(llcinputfile=$llvmbcfile)
               )
        set(llvmbcfile=$ifn($or($NOASM,$notequal($llvmbcfile,) ),$if($and($COMPILEONLY,$notequal($OUTFILE,)),$OUTFILE,$ifn($KEEPTEMP$KEEPLL,$tempfile(llvm),$if($and($ASMONLY,$notequal($OUTFILE,)),$dirname($OUTFILE)/$basename($OUTFILE).llvm,$basename($file).llvm)))))
        arguments($llcinputfile $LLCARCH $LLCMCPU $LLCMATTR $LLCFLOATABI $LLCOPT $LLCFASTMATH $LLCISEL $LLCARGS $LLCPIC $LLCMODEL $LLCDO $LLCFRAMEPOINTER -o $asmfile)
        execute(
            condition($equal($NOASM$COMPILEONLY$LLVMDO,))
            input($asmfile)
            command($LLNASM)
        )
        execute(
            condition($and($notequal($POSTASM,), 
                           $and($LLVMDO, $equal($NOASM$COMPILEONLY,))))
            input($asmfile)
            command($POSTASM)
        )
        execute(
            condition($and($doappend,
                           $and($equal($POSTASM,),
                                $and($LLVMDO, $equal($NOASM$COMPILEONLY,)))))
            input($asmfile)
            command(append)
        )
        ;

command clang is
        help(LLVM assembler)
        tool(clang)
        suffix($LLCSUFFIX)
        set(LLCDO=$ifn($LLVMDO,-S -fno-integrated-as))
        set(outsuffix=$if($LLVMDO,o,s))
	set(objkeep=$if($LLVMDO,$KEEPOBJ))
        set(asmfile=$ifn($NOASM,$if($and($COMPILEONLY,$notequal($OUTFILE,)),$OUTFILE,$ifn($KEEPTEMP$KEEPASM$KEEPLL$objkeep,$tempfile($outsuffix),$if($and($ASMONLY,$notequal($OUTFILE,)),$if($LLVMDO,$OUTFILE,$dirname($OUTFILE)/$basename($OUTFILE).$outsuffix),$basename($file).$outsuffix)))))
        append(linkfiles=$if($LLVMDO,$if($equal($POSTASM,),$asmfile)))
        append(objfiles=$if($LLVMDO,$if($equal($POSTASM,),$asmfile)))
        set(clanginputfile=$input)
        set(CLANGPIC=$if($DOFPIC,-fpic -fPIC))
        set(LLCOPT=-O$if($expr($OPTLEVEL>$LLCOPTMAX),$LLCOPTMAX,$OPTLEVEL))
        set(LLCDONE=YES)
        arguments(-c $clanginputfile $CLANGMCPU $LLCOPT $CLANGARGS $CLANGPIC $CLANGMODEL $LLCDO -o $asmfile -Wno-override-module -Wno-unused-command-line-argument )
        execute(
            condition($equal($NOASM$COMPILEONLY$LLVMDO,))
            input($asmfile)
            command($LLNASM)
        )
        execute(
            condition($and($notequal($POSTASM,), 
                           $and($LLVMDO, $equal($NOASM$COMPILEONLY,))))
            input($asmfile)
            command($POSTASM)
        )
        execute(
            condition($and($doappend,
                           $and($equal($POSTASM,),
                                $and($LLVMDO, $equal($NOASM$COMPILEONLY,)))))
            input($asmfile)
            command(append)
        )
        ;

command nvbe is
        help(LLVM assembler)
        tool(nvbe)
        suffix($LLCSUFFIX)
        set(LLCDO=$ifn($LLVMDO,-S, -filetype=obj))
        set(outsuffix=$if($LLVMDO,o,s))
        set(objkeep=$if($LLVMDO,$KEEPOBJ))
        set(asmfile=$ifn($NOASM,$if($and($COMPILEONLY,$notequal($OUTFILE,)),$OUTFILE,$ifn($KEEPTEMP$KEEPASM$KEEPLL$objkeep,$tempfile($outsuffix),$if($and($ASMONLY,$notequal($OUTFILE,)),$if($LLVMDO,$OUTFILE,$dirname($OUTFILE)/$basename($OUTFILE).$outsuffix),$basename($file).$outsuffix)))))
        set(LLCPIC=$if($DOFPIC,-relocation-model=pic))
        append(linkfiles=$if($LLVMDO,$if($equal($POSTASM,),$asmfile)))
        append(objfiles=$if($LLVMDO,$if($equal($POSTASM,),$asmfile)))
        set(nvbeinputfile=$input)
        set(LLCOPT=-O$if($expr($OPTLEVEL>$LLCOPTMAX),$LLCOPTMAX,$OPTLEVEL))
        set(LLCDONE=YES)
        set(LLCISEL=$LLCFASTISEL)
        set(NVBEFASTMATH=$if($equal($IEEE,), $LLUNSAFEMATH))
        arguments( $nvbeinputfile $LLCMCPU $LLCARCH $LLCPIC $LLCFLOATABI $NVBEFASTMATH $LLCISEL $LLCOPT $LLCARGS $LLCDO -o $asmfile )
        execute(
            condition($equal($NOASM$COMPILEONLY$LLVMDO,))
            input($asmfile)
            command($LLNASM)
        )
        execute(
            condition($and($notequal($POSTASM,),
                           $and($LLVMDO, $equal($NOASM$COMPILEONLY,))))
            input($asmfile)
            command($POSTASM)
        )
        execute(
            condition($and($doappend,
                           $and($equal($POSTASM,),
                                $and($LLVMDO, $equal($NOASM$COMPILEONLY,)))))
            input($asmfile)
            command(append)
        )
        ;

# This may not be the right file but it is quick/convenient for now.
switch -Mandroid is hide
        help(Android tool chain version)
        early
        helpgroup(overall)
        keyword(
          "r5b"(
              help(Use Android Tool Chains version r5b)
              set(ANDROIDBASEDIR=$dirname($ANDROIDBASE)/r5b)
             )
          "r7b"(
              help(Use Android Tool Chains version r7b)
              set(ANDROIDBASEDIR=$dirname($ANDROIDBASE)/r7b)
             )
          "r8c"(
              help(Use Android Tool Chains version r8c)
              set(ANDROIDBASEDIR=$dirname($ANDROIDBASE)/r8c)
        )
        ;

# Enable data-layout and IL_GARG for all llvm compilers.
append CARGS=-x 183 4 -x 121 0x800;
append FCGARGS=-x 183 4 -x 121 0x800;

switch -MllvmO0 is hide
        help(Override LLVM's optimization level to -O0)
        helpgroup(overall)
        set(LLVMOPTLEVEL=0)
        set(LLVMLLCLEVEL=0);

switch -MllvmO1 is hide
        help(Override LLVM's optimization level to -O1)
        helpgroup(overall)
        set(LLVMOPTLEVEL=1)
        set(LLVMLLCLEVEL=1);

switch -MllvmO2 is hide
        help(Override LLVM's optimization level to -O2)
        helpgroup(overall)
        set(LLVMOPTLEVEL=2)
        set(LLVMLLCLEVEL=2);

switch -MllvmO3 is hide
        help(Override LLVM's optimization level to -O3)
        helpgroup(overall)
        set(LLVMOPTLEVEL=3)
        set(LLVMLLCLEVEL=3);

switch -Mllvmopt2pass is hide
        help(Enable 2 Passes for LLVM OPT)
        helpgroup(overall)
        set(LLVMOPT2PASS=YES);

switch -Mllvmopt is hide
        help(Pass through LLVM OPT)
        helpgroup(overall)
        set(LLVMOPT=YES);

switch -Mnollvmopt is hide
        help(Pass through LLVM OPT)
        helpgroup(overall)
        set(LLVMOPT=NO);

variable LLVERBOSE is default (1);
append CGARGS=$if($LLVERBOSE, -x 120 0x1000000);

switch -Mkeepllvm is hide
        help(Preserve LLVM IR files)
        helpgroup(overall)
        nokeyword()
        keyword(less(help(Generate less verbose ouput in .ll files)
                     set(LLVERBOSE=0)))
        set(KEEPLL=YES)
        set(KEEPBC=YES);

switch -emit-llvm is hide shorthand(-Mkeepllvm);

switch -Mkeepll is hide
        # Remove in/after 23A
        help(Preserve LLVM intermediate assembly language file)
        helpgroup(overall)
        append(F901ARGS=-x 50 0x10)
        set(KEEPLL=YES)
        echo(-Mkeepll has been deprecated and will be removed in a future release; use -Mkeepllvm);

switch -Monlyll is hide
        # Remove in/after 23A
        help(Preserve LLVM intermediate assembly language file)
        helpgroup(overall)
        set(KEEPLL=YES)
        set(DEFOUTFILE=)
        set(LLONLY=YES)
        echo(-Monlyll has been deprecated and will be removed in a future release; use -Mkeepllvm);

switch -Mkeepbc is hide
        # Remove in/after 23A
        help(Preserve byte-code LLVM file)
        helpgroup(overall)
        set(KEEPLL=YES)
        set(KEEPBC=YES)
        echo(-Mkeepbc has been deprecated and will be removed in a future release; use -Mkeepllvm);

switch -Memit-dwarf-inlined is
        help(Enable generation of DWARF for inlined functions)
        helpgroup(debug)
        append(CGARGS=-x 183 0x80000000 -x 2 0x100000);

switch -Mnometadata is hide
        help(Strip off all metadata)
        helpgroup(debug)
        append(CGARGS=-x 120 0x40000000);

switch -Mfullmetadata is hide
        help(Force output the full metadata, ignore mdnode check and show artificial variables name)
        helpgroup(debug)
        append(CGARGS=-x 120 0x8000000);

# extra argument to llc
switch -Wllc,arg is hide
        help(Pass argument to llc)
        helpgroup(llc)
        disable(NoFiles)
        # Note we'll match any -O* here.
        set(LLVMLLCLEVELOVERRIDE=$if($contains($arg, -O$.), 1))
        append(LLVMLLCUSERARGS=$replace($arg,",", ));

# extra argument to llc
switch -Wllvmmc,arg is hide
        help(Pass argument to llvm-mc)
        helpgroup(llvmmc)
        disable(NoFiles)
        append(LLVMMCARGS=$replace($arg,",", ));

# extra argument to clang
switch -Wclang,arg is hide
        help(Pass argument to clang)
        helpgroup(clang)
        disable(NoFiles)
        append(CLANGUSERARGS=$replace($arg,",", ));

# extra argument to nvbe
switch -Wnvbe,arg is hide
        help(Pass argument to nvbe)
        helpgroup(nvbe)
        disable(NoFiles)
        append(LLCARGS=$replace($arg,",", ));

# extra argument to opt
switch -Wlopt,arg is hide
        help(Pass argument to llvm opt)
        helpgroup(opt)
        disable(NoFiles)
        # Note we'll match any -O* here.
        set(LLVMOPTLEVELOVERRIDE=$if($or($contains($arg, -O$.), $contains($arg, default<O$.)), 1, ))
        set(LLVMENABLEOLDPM=$if($contains($arg, -enable-new-pm=0), 1, ))
        append(LLVMOPTUSERARGS=$replace($replace($arg,",", ), "-enable-new-pm=0", ));

switch -Wlopt1,arg is hide
        help(Pass argument to llvm opt pass 1)
        helpgroup(opt)
        disable(NoFiles)
        append(LLVMOPTARGS1=$replace($arg,",", ));

switch -Wlopt2,arg is hide
        help(Pass argument to llvm opt pass 2)
        helpgroup(opt)
        disable(NoFiles)
        append(LLVMOPTARGS2=$replace($arg,",", ));

variable OPAQUEPTR is default(1);
append CGARGS=$if($OPAQUEPTR, -x 73 0x04);
append OPTCOMMONARGS=$if($and($OPAQUEPTR,$expr($LLVMVERINT == 160)), -opaque-pointers);
append LLCCOMMONARGS=$if($and($OPAQUEPTR,$expr($LLVMVERINT == 160)), -opaque-pointers);

variable NVMEMZERO is default($if($LLVMVERINT >= 170,1,0));
append CGARGS=$if($NVMEMZERO, -x 231 0x800);

switch -Mllvm-slp-vectorize-hor is hide set(SLPVECTORIZEHOR=1);
switch -Mllvm-no-slp-vectorize-hor is hide set(SLPVECTORIZEHOR=0);

variable FUNCSECTIONS is default(0);
append LLCAPPENDARGS=$if($FUNCSECTIONS,-function-sections=1);

switch -ffunction-sections is
    help (Place each function in its own section)
    helpgroup(llc)
    set(FUNCSECTIONS=1);

switch -fno-function-sections is
   set(FUNCSECTIONS=0);

variable DATASECTIONS is default(0);
append LLCAPPENDARGS=$if($DATASECTIONS,-data-sections=1);

switch -fdata-sections is
    help (Place each data in its own section)
    helpgroup(llc)
    set(DATASECTIONS=1);

switch -fno-data-sections is
   set(DATASECTIONS=0);

switch -MfortranO0 is hide
  help(Force fort1 opt level to -O0)
  append(F901ARGS=-x 68 0x400);

switch -Mrestart is hide
  help(Informs fort1 that it was restarted and it should not attempt another restart on the current source file)
  append(F901ARGS=-x 68 0x800);

switch -Mnorestart is
  help(Instructs fort1 not to restart at a lower optimization level when subprogram is too large to compile at -O2 or higher)
  append(F901ARGS=-x 68 0x1000);


