/************************************************************************* * * * Extension for YAP Prolog * * * * Copyright G.S.Oliveira, A.F.Silva and Universidade Estadual de Maringá * * * * Yap Prolog was developed at NCCUP - Universidade do Porto * * Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 * * * ************************************************************************** * * * File: jit_transformpreds.c * * comments: JIT Compiler Optimizations predicates * * * * Last rev: 2013-10-18 * *************************************************************************/ #define JIT_CODE 1 #include "jit_predicates.hpp" #define N_TRANSFORM_PASSES 69 // Disable one (passed by argument) LLVM transform pass static Int p_disable_transform_pass( USES_REGS1 ); // Enable one (passed by argument) LLVM transform pass static Int p_transform_pass( USES_REGS1 ); // Enable one (passed by argument) LLVM transform pass static Int p_enable_transform_pass( USES_REGS1 ); // Enable a list (passed by argument) of LLVM transform passes static Int p_transform_passes( USES_REGS1 ); // Enable all available LLVM transform passes static Int p_enable_all_transform_passes( USES_REGS1 ); // Disable all available LLVM transform passes static Int p_disable_all_transform_passes( USES_REGS1 ); // Enable n LLVM transform passes (randomly) static Int p_n_transform_passes( USES_REGS1 ); // Enable a transform level static Int p_transform_level( USES_REGS1 ); // Max element of Argument Promotion Pass static Int p_argument_promotion_max_elements( USES_REGS1 ); // Threshold of Scalar Repl Aggregates Pass static Int p_scalar_replace_aggregates_threshold( USES_REGS1 ); // Threshold of Loop Unroll Pass static Int p_loop_unroll_threshold( USES_REGS1 ); // Threshold of Function Inlining Pass static Int p_inline_threshold( USES_REGS1 ); // Eliminates (or not) only debugging information on Strip Symbols Pass static Int p_strip_symbols_pass_type( USES_REGS1 ); // Optimizes (or not) for size on Loop Unswitch Pass static Int p_loop_unswitch_optimize_for_size( USES_REGS1 ); /* * Default value of 'max elements on Argument Promotion Pass * * 'threshold of Scalar Repl Aggregates Pass * * 'threshold of Loop Unroll Pass * * 'threshold of Function Inlining Pass * * 'Strip Symbols Pass * * 'Loop Unswitch Pass * */ static Int p_default_optimization_args( USES_REGS1 ); // Same as 'p_default_optimization_args' static Int p_reset_optimization_args( USES_REGS1 ); // Enable IPO by LLVM static Int p_enable_unit_at_time( USES_REGS1 ); // Enable libcalls simplification by LLVM static Int p_enable_simplify_libcalls( USES_REGS1 ); // Disable IPO by LLVM static Int p_disable_unit_at_time( USES_REGS1 ); // Disable libcalls simplification by LLVM static Int p_disable_simplify_libcalls( USES_REGS1 ); // Enable (or not) link-time optimization static Int p_link_time_opt1( USES_REGS1 ); /* * Same as 'p_link_time_opt1', but accepts 3 arguments: * * 1 -- Should I apply this opt? * * 2 -- Should I run internalize? * * 3 -- Should I run inliner? * */ static Int p_link_time_opt3( USES_REGS1 ); // Enable link-time optimization. Same as 'link_time_opt(true)' static Int p_enable_link_time_opt( USES_REGS1 ); /* * Same as 'p_enable_link_time_opt', but accepts 2 arguments: * * 1 -- Should I run internalize? * * 2 -- Should I run inliner? * */ static Int p_enable_link_time_opt2( USES_REGS1 ); // Disable link-time optimization. static Int p_disable_link_time_opt( USES_REGS1 ); #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wimplicit-function-declaration" static Int p_disable_transform_pass( USES_REGS1 ) { // First: stores what transform pass should be disabled Term t = Deref(ARG1); enumTransformPasses f; // valid values for ARG1 are 'integer' and 'atom' if (IsIntTerm(t)) { // ARG1 is integer Int v = IntOfTerm(t); if (v < 0 || v >= N_TRANSFORM_PASSES) { // value passed by argument is out of known range Yap_Error(OUT_OF_KNOWNRANGE_ERROR,t,""); return FALSE; } f = (enumTransformPasses)v; } else if (IsAtomTerm(t)) { // ARG1 is atom int i = 0, j = 0; char *tmp; // gets string from atom and stores it on 'str' char *str = (char*)malloc(YAP_AtomNameLength(AtomOfTerm(t))*sizeof(char)); strcpy(str, AtomName(AtomOfTerm(t))); // Makes upper characters of 'str' (for comparison) UPPER_ENTRY(str); if (strcmp(str, "ALL") == 0) { // atom is 'all' -- this will disable all passes if (ExpEnv.transform_struc.act_tr) free(ExpEnv.transform_struc.act_tr); ExpEnv.transform_struc.act_tr = NULL; ExpEnv.transform_struc.n = 0; return TRUE; } // Detects one pass according to 'str' -- store it if (strcmp(str, "AGGRESSIVEDCE") == 0 || strcmp(str, "ADCE") == 0) f = t_createAggressiveDCEPass; else if (strcmp(str, "ARGUMENTPROMOTION") == 0 || strcmp(str, "ARGPROMOTION") == 0) f = t_createArgumentPromotionPass; else if (strcmp(str, "BBVECTORIZE") == 0) f = t_createBBVectorizePass; else if (strcmp(str, "BLOCKEXTRACTOR") == 0 || strcmp(str, "EXTRACTBLOCKS") == 0) f = t_createBlockExtractorPass; else if (strcmp(str, "BLOCKPLACEMENT") == 0) f = t_createBlockPlacementPass; else if (strcmp(str, "BREAKCRITICALEDGES") == 0 || strcmp(str, "BREAKCRITEDGES") == 0) f = t_createBreakCriticalEdgesPass; else if (strcmp(str, "CFGSIMPLIFICATION") == 0 || strcmp(str, "SIMPLIFYCFG") == 0) f = t_createCFGSimplificationPass; else if (strcmp(str, "CODEGENPREPARE") == 0) f = t_createCodeGenPreparePass; else if (strcmp(str, "CONSTANTMERGE") == 0 || strcmp(str, "CONSTMERGE") == 0) f = t_createConstantMergePass; else if (strcmp(str, "CONSTANTPROPAGATION") == 0 || strcmp(str, "CONSTPROP") == 0) f = t_createConstantPropagationPass; else if (strcmp(str, "CORRELATEDVALUEPROPAGATION") == 0 || strcmp(str, "CORRELATEDPROPAGATION") == 0) f = t_createCorrelatedValuePropagationPass; else if (strcmp(str, "DEADARGELIMINATION") == 0 || strcmp(str, "DEADARGELIM") == 0) f = t_createDeadArgEliminationPass; else if (strcmp(str, "DEADARGHACKING") == 0 || strcmp(str, "DEADARGHAX0R") == 0) f = t_createDeadArgHackingPass; else if (strcmp(str, "DEADCODEELIMINATION") == 0 || strcmp(str, "DCE") == 0) f = t_createDeadCodeEliminationPass; else if (strcmp(str, "DEADINSTELIMINATION") == 0 || strcmp(str, "DIE") == 0) f = t_createDeadInstEliminationPass; else if (strcmp(str, "DEADSTOREELIMINATION") == 0 || strcmp(str, "DSE") == 0) f = t_createDeadStoreEliminationPass; else if (strcmp(str, "DEMOTEREGISTERTOMEMORY") == 0 || strcmp(str, "REG2MEM") == 0) f = t_createDemoteRegisterToMemoryPass; else if (strcmp(str, "EARLYCSE") == 0) f = t_createEarlyCSEPass; else if (strcmp(str, "FUNCTIONATTRS") == 0) f = t_createFunctionAttrsPass; else if (strcmp(str, "FUNCTIONINLINING") == 0 || strcmp(str, "INLINE") == 0) f = t_createFunctionInliningPass; else if (strcmp(str, "GLOBALDCE") == 0) f = t_createGlobalDCEPass; else if (strcmp(str, "GLOBALOPTIMIZER") == 0 || strcmp(str, "GLOBALOPT") == 0) f = t_createGlobalOptimizerPass; else if (strcmp(str, "GVEXTRACTION") == 0) f = t_createGVExtractionPass; else if (strcmp(str, "GVN") == 0) f = t_createGVNPass; else if (strcmp(str, "INDVARSIMPLIFY") == 0 || strcmp(str, "INDVARS") == 0) f = t_createIndVarSimplifyPass; else if (strcmp(str, "INSTRUCTIONCOMBINING") == 0 || strcmp(str, "INSTCOMBINE") == 0) f = t_createInstructionCombiningPass; else if (strcmp(str, "INSTRUCTIONNAMER") == 0 || strcmp(str, "INSTNAMER") == 0) f = t_createInstructionNamerPass; else if (strcmp(str, "INSTRUCTIONSIMPLIFIER") == 0 || strcmp(str, "INSTSIMPLIFY") == 0) f = t_createInstructionSimplifierPass; else if (strcmp(str, "INTERNALIZE") == 0) f = t_createInternalizePass; else if (strcmp(str, "IPCONSTANTPROPAGATION") == 0 || strcmp(str, "IPCONSTPROP") == 0) f = t_createIPConstantPropagationPass; else if (strcmp(str, "IPSCCP") == 0) f = t_createIPSCCPPass; else if (strcmp(str, "JUMPTHREADING") == 0) f = t_createJumpThreadingPass; else if (strcmp(str, "LCSSA") == 0) f = t_createLCSSAPass; else if (strcmp(str, "LICM") == 0) f = t_createLICMPass; else if (strcmp(str, "LOOPDELETION") == 0) f = t_createLoopDeletionPass; else if (strcmp(str, "LOOPEXTRACTOR") == 0 || strcmp(str, "LOOPEXTRACT") == 0) f = t_createLoopExtractorPass; else if (strcmp(str, "LOOPIDIOM") == 0) f = t_createLoopIdiomPass; else if (strcmp(str, "LOOPINSTSIMPLIFY") == 0) f = t_createLoopInstSimplifyPass; else if (strcmp(str, "LOOPROTATE") == 0) f = t_createLoopRotatePass; else if (strcmp(str, "LOOPSIMPLIFY") == 0) f = t_createLoopSimplifyPass; else if (strcmp(str, "LOOPSTRENGTHREDUCE") == 0 || strcmp(str, "LOOPREDUCE") == 0) f = t_createLoopStrengthReducePass; else if (strcmp(str, "LOOPUNROLL") == 0) f = t_createLoopUnrollPass; else if (strcmp(str, "LOOPUNSWITCH") == 0) f = t_createLoopUnswitchPass; else if (strcmp(str, "LOWERATOMIC") == 0) f = t_createLowerAtomicPass; else if (strcmp(str, "LOWEREXPECTINTRINSIC") == 0 || strcmp(str, "LOWEREXPECT") == 0) f = t_createLowerExpectIntrinsicPass; else if (strcmp(str, "LOWERINVOKE") == 0) f = t_createLowerInvokePass; else if (strcmp(str, "LOWERSWITCH") == 0) f = t_createLowerSwitchPass; else if (strcmp(str, "MEMCPYOPT") == 0) f = t_createMemCpyOptPass; else if (strcmp(str, "MERGEFUNCTIONS") == 0 || strcmp(str, "MERGEFUNC") == 0) f = t_createMergeFunctionsPass; else if (strcmp(str, "OBJCARCAPELIM") == 0) f = t_createObjCARCAPElimPass; else if (strcmp(str, "OBJCARCCONTRACT") == 0) f = t_createObjCARCContractPass; else if (strcmp(str, "OBJCARCEXPAND") == 0) f = t_createObjCARCExpandPass; else if (strcmp(str, "OBJCARCOPT") == 0 || strcmp(str, "OBJCARC") == 0) f = t_createObjCARCOptPass; else if (strcmp(str, "PARTIALINLINING") == 0 || strcmp(str, "PARTIALINLINER") == 0) f = t_createPartialInliningPass; else if (strcmp(str, "PROMOTEMEMORYTOREGISTER") == 0 || strcmp(str, "MEM2REG") == 0) f = t_createPromoteMemoryToRegisterPass; else if (strcmp(str, "PRUNEEH") == 0) f = t_createPruneEHPass; else if (strcmp(str, "REASSOCIATE") == 0) f = t_createReassociatePass; else if (strcmp(str, "SCALARREPLAGGREGATES") == 0 || strcmp(str, "SCALARREPL") == 0) f = t_createScalarReplAggregatesPass; else if (strcmp(str, "SCCP") == 0) f = t_createSCCPPass; else if (strcmp(str, "SIMPLIFYLIBCALLS") == 0) f = t_createSimplifyLibCallsPass; else if (strcmp(str, "SINGLELOOPEXTRACTOR") == 0 || strcmp(str, "LOOPEXTRACTSINGLE") == 0) f = t_createSingleLoopExtractorPass; else if (strcmp(str, "SINKING") == 0 || strcmp(str, "SINK") == 0) f = t_createSinkingPass; else if (strcmp(str, "STRIPDEADDEBUGINFO") == 0) f = t_createStripDeadDebugInfoPass; else if (strcmp(str, "STRIPDEADPROTOTYPES") == 0) f = t_createStripDeadPrototypesPass; else if (strcmp(str, "STRIPDEBUGDECLARE") == 0) f = t_createStripDebugDeclarePass; else if (strcmp(str, "STRIPNONDEBUGSYMBOLS") == 0) f = t_createStripNonDebugSymbolsPass; else if (strcmp(str, "STRIPSYMBOLS") == 0 || strcmp(str, "STRIP") == 0) f = t_createStripSymbolsPass; else if (strcmp(str, "TAILCALLELIMINATION") == 0 || strcmp(str, "TAILCALLELIM") == 0) f = t_createTailCallEliminationPass; else { // value passed by argument is out of known range Yap_Error(OUT_OF_KNOWNRANGE_ERROR,t,""); return FALSE; } } else { // ARG1 is not an integer or atom Yap_NilError(INVALID_PARAMETER_TYPE_ERROR,"Transform pass"); return FALSE; } // Second: creates a new list with all transform on 'ExpEnv.analysis_struc.act_tr' but that transform stored on first step enumTransformPasses *tmplist = NULL; COUNT tmpn = 0; int i = 0; while (i < ExpEnv.transform_struc.n) { if (ExpEnv.transform_struc.act_tr[i] != f) { tmpn += 1; tmplist = (enumTransformPasses*)realloc(tmplist, tmpn*sizeof(enumTransformPasses)); tmplist[tmpn-1] = ExpEnv.transform_struc.act_tr[i]; } i += 1; } // Third: makes 'ExpEnv.analysis_struc.act_tr' to point to new list created on second step free(ExpEnv.transform_struc.act_tr); ExpEnv.transform_struc.n = tmpn; ExpEnv.transform_struc.act_tr = tmplist; return TRUE; } static Int p_transform_pass( USES_REGS1 ) { // First: disables analysis pass (if be active) p_disable_transform_pass( PASS_REGS1 ); // Second: valids argument and inserts new transform pass // valid values for ARG1 are 'integer' and 'atom' Term t = Deref(ARG1); Int v; if (IsIntTerm(t)) { // ARG1 is integer v = IntOfTerm(t); if (v < 0 || v >= N_TRANSFORM_PASSES) { // value passed by argument is out of known range Yap_Error(OUT_OF_KNOWNRANGE_ERROR,t,""); return FALSE; } // creates a new slot in 'ExpEnv.analysis_struc.act_tr' and appends the pass in it ExpEnv.transform_struc.n += 1; ExpEnv.transform_struc.act_tr = (enumTransformPasses*) realloc(ExpEnv.transform_struc.act_tr, ExpEnv.transform_struc.n * sizeof(enumTransformPasses)); ExpEnv.transform_struc.act_tr[ExpEnv.transform_struc.n-1] = (enumTransformPasses)v; return TRUE; } else if (IsAtomTerm(t)) { // ARG1 is atom int i = 0, j = 0; char *tmp; // gets string from atom and stores it on 'str' char *str = (char*)malloc(YAP_AtomNameLength(AtomOfTerm(t))*sizeof(char)); strcpy(str, AtomName(AtomOfTerm(t))); // Makes upper characters of 'str' (for comparison) UPPER_ENTRY(str); // Detects one pass according to 'str' if (strcmp(str, "AGGRESSIVEDCE") == 0 || strcmp(str, "ADCE") == 0) v = t_createAggressiveDCEPass; else if (strcmp(str, "ARGUMENTPROMOTION") == 0 || strcmp(str, "ARGPROMOTION") == 0) v = t_createArgumentPromotionPass; else if (strcmp(str, "BBVECTORIZE") == 0) v = t_createBBVectorizePass; else if (strcmp(str, "BLOCKEXTRACTOR") == 0 || strcmp(str, "EXTRACTBLOCKS") == 0) v = t_createBlockExtractorPass; else if (strcmp(str, "BLOCKPLACEMENT") == 0) v = t_createBlockPlacementPass; else if (strcmp(str, "BREAKCRITICALEDGES") == 0 || strcmp(str, "BREAKCRITEDGES") == 0) v = t_createBreakCriticalEdgesPass; else if (strcmp(str, "CFGSIMPLIFICATION") == 0 || strcmp(str, "SIMPLIFYCFG") == 0) v = t_createCFGSimplificationPass; else if (strcmp(str, "CODEGENPREPARE") == 0) v = t_createCodeGenPreparePass; else if (strcmp(str, "CONSTANTMERGE") == 0 || strcmp(str, "CONSTMERGE") == 0) v = t_createConstantMergePass; else if (strcmp(str, "CONSTANTPROPAGATION") == 0 || strcmp(str, "CONSTPROP") == 0) v = t_createConstantPropagationPass; else if (strcmp(str, "CORRELATEDVALUEPROPAGATION") == 0 || strcmp(str, "CORRELATEDPROPAGATION") == 0) v = t_createCorrelatedValuePropagationPass; else if (strcmp(str, "DEADARGELIMINATION") == 0 || strcmp(str, "DEADARGELIM") == 0) v = t_createDeadArgEliminationPass; else if (strcmp(str, "DEADARGHACKING") == 0 || strcmp(str, "DEADARGHAX0R") == 0) v = t_createDeadArgHackingPass; else if (strcmp(str, "DEADCODEELIMINATION") == 0 || strcmp(str, "DCE") == 0) v = t_createDeadCodeEliminationPass; else if (strcmp(str, "DEADINSTELIMINATION") == 0 || strcmp(str, "DIE") == 0) v = t_createDeadInstEliminationPass; else if (strcmp(str, "DEADSTOREELIMINATION") == 0 || strcmp(str, "DSE") == 0) v = t_createDeadStoreEliminationPass; else if (strcmp(str, "DEMOTEREGISTERTOMEMORY") == 0 || strcmp(str, "REG2MEM") == 0) v = t_createDemoteRegisterToMemoryPass; else if (strcmp(str, "EARLYCSE") == 0) v = t_createEarlyCSEPass; else if (strcmp(str, "FUNCTIONATTRS") == 0) v = t_createFunctionAttrsPass; else if (strcmp(str, "FUNCTIONINLINING") == 0 || strcmp(str, "INLINE") == 0) v = t_createFunctionInliningPass; else if (strcmp(str, "GLOBALDCE") == 0) v = t_createGlobalDCEPass; else if (strcmp(str, "GLOBALOPTIMIZER") == 0 || strcmp(str, "GLOBALOPT") == 0) v = t_createGlobalOptimizerPass; else if (strcmp(str, "GVEXTRACTION") == 0) v = t_createGVExtractionPass; else if (strcmp(str, "GVN") == 0) v = t_createGVNPass; else if (strcmp(str, "INDVARSIMPLIFY") == 0 || strcmp(str, "INDVARS") == 0) v = t_createIndVarSimplifyPass; else if (strcmp(str, "INSTRUCTIONCOMBINING") == 0 || strcmp(str, "INSTCOMBINE") == 0) v = t_createInstructionCombiningPass; else if (strcmp(str, "INSTRUCTIONNAMER") == 0 || strcmp(str, "INSTNAMER") == 0) v = t_createInstructionNamerPass; else if (strcmp(str, "INSTRUCTIONSIMPLIFIER") == 0 || strcmp(str, "INSTSIMPLIFY") == 0) v = t_createInstructionSimplifierPass; else if (strcmp(str, "INTERNALIZE") == 0) v = t_createInternalizePass; else if (strcmp(str, "IPCONSTANTPROPAGATION") == 0 || strcmp(str, "IPCONSTPROP") == 0) v = t_createIPConstantPropagationPass; else if (strcmp(str, "IPSCCP") == 0) v = t_createIPSCCPPass; else if (strcmp(str, "JUMPTHREADING") == 0) v = t_createJumpThreadingPass; else if (strcmp(str, "LCSSA") == 0) v = t_createLCSSAPass; else if (strcmp(str, "LICM") == 0) v = t_createLICMPass; else if (strcmp(str, "LOOPDELETION") == 0) v = t_createLoopDeletionPass; else if (strcmp(str, "LOOPEXTRACTOR") == 0 || strcmp(str, "LOOPEXTRACT") == 0) v = t_createLoopExtractorPass; else if (strcmp(str, "LOOPIDIOM") == 0) v = t_createLoopIdiomPass; else if (strcmp(str, "LOOPINSTSIMPLIFY") == 0) v = t_createLoopInstSimplifyPass; else if (strcmp(str, "LOOPROTATE") == 0) v = t_createLoopRotatePass; else if (strcmp(str, "LOOPSIMPLIFY") == 0) v = t_createLoopSimplifyPass; else if (strcmp(str, "LOOPSTRENGTHREDUCE") == 0 || strcmp(str, "LOOPREDUCE") == 0) v = t_createLoopStrengthReducePass; else if (strcmp(str, "LOOPUNROLL") == 0) v = t_createLoopUnrollPass; else if (strcmp(str, "LOOPUNSWITCH") == 0) v = t_createLoopUnswitchPass; else if (strcmp(str, "LOWERATOMIC") == 0) v = t_createLowerAtomicPass; else if (strcmp(str, "LOWEREXPECTINTRINSIC") == 0 || strcmp(str, "LOWEREXPECT") == 0) v = t_createLowerExpectIntrinsicPass; else if (strcmp(str, "LOWERINVOKE") == 0) v = t_createLowerInvokePass; else if (strcmp(str, "LOWERSWITCH") == 0) v = t_createLowerSwitchPass; else if (strcmp(str, "MEMCPYOPT") == 0) v = t_createMemCpyOptPass; else if (strcmp(str, "MERGEFUNCTIONS") == 0 || strcmp(str, "MERGEFUNC") == 0) v = t_createMergeFunctionsPass; else if (strcmp(str, "OBJCARCAPELIM") == 0) v = t_createObjCARCAPElimPass; else if (strcmp(str, "OBJCARCCONTRACT") == 0) v = t_createObjCARCContractPass; else if (strcmp(str, "OBJCARCEXPAND") == 0) v = t_createObjCARCExpandPass; else if (strcmp(str, "OBJCARCOPT") == 0 || strcmp(str, "OBJCARC") == 0) v = t_createObjCARCOptPass; else if (strcmp(str, "PARTIALINLINING") == 0 || strcmp(str, "PARTIALINLINER") == 0) v = t_createPartialInliningPass; else if (strcmp(str, "PROMOTEMEMORYTOREGISTER") == 0 || strcmp(str, "MEM2REG") == 0) v = t_createPromoteMemoryToRegisterPass; else if (strcmp(str, "PRUNEEH") == 0) v = t_createPruneEHPass; else if (strcmp(str, "REASSOCIATE") == 0) v = t_createReassociatePass; else if (strcmp(str, "SCALARREPLAGGREGATES") == 0 || strcmp(str, "SCALARREPL") == 0) v = t_createScalarReplAggregatesPass; else if (strcmp(str, "SCCP") == 0) v = t_createSCCPPass; else if (strcmp(str, "SIMPLIFYLIBCALLS") == 0) v = t_createSimplifyLibCallsPass; else if (strcmp(str, "SINGLELOOPEXTRACTOR") == 0 || strcmp(str, "LOOPEXTRACTSINGLE") == 0) v = t_createSingleLoopExtractorPass; else if (strcmp(str, "SINKING") == 0 || strcmp(str, "SINK") == 0) v = t_createSinkingPass; else if (strcmp(str, "STRIPDEADDEBUGINFO") == 0) v = t_createStripDeadDebugInfoPass; else if (strcmp(str, "STRIPDEADPROTOTYPES") == 0) v = t_createStripDeadPrototypesPass; else if (strcmp(str, "STRIPDEBUGDECLARE") == 0) v = t_createStripDebugDeclarePass; else if (strcmp(str, "STRIPNONDEBUGSYMBOLS") == 0) v = t_createStripNonDebugSymbolsPass; else if (strcmp(str, "STRIPSYMBOLS") == 0 || strcmp(str, "STRIP") == 0) v = t_createStripSymbolsPass; else if (strcmp(str, "TAILCALLELIMINATION") == 0 || strcmp(str, "TAILCALLELIM") == 0) v = t_createTailCallEliminationPass; else { // value passed by argument is out of known range Yap_Error(OUT_OF_KNOWNRANGE_ERROR,t,""); return FALSE; } // creates a new slot in 'ExpEnv.analysis_struc.act_tr' and appends the pass in it ExpEnv.transform_struc.n += 1; ExpEnv.transform_struc.act_tr = (enumTransformPasses*) realloc(ExpEnv.transform_struc.act_tr, ExpEnv.transform_struc.n * sizeof(enumTransformPasses)); ExpEnv.transform_struc.act_tr[ExpEnv.transform_struc.n-1] = v; ExpEnv.transform_struc.optlevel = -1; // using this, optlevel won't be used return TRUE; } else { // ARG1 is not an integer or atom Yap_NilError(INVALID_PARAMETER_TYPE_ERROR,"Transform pass"); return FALSE; } } static Int p_enable_transform_pass( USES_REGS1 ) { return p_transform_pass( PASS_REGS1 ); } static Int p_transform_passes( USES_REGS1 ) { int i = 0, j = 0; char *tmp; // valid values for ARG1 are 'atom' and 'list (pair)' Term t = Deref(ARG1); if (IsAtomTerm(t)) { // ARG1 is atom // gets string from atom and stores it on 'str' char *str = (char*)malloc(YAP_AtomNameLength(AtomOfTerm(t))*sizeof(char)); strcpy(str, AtomName(AtomOfTerm(t))); // Makes upper characters of 'str' (for comparison) UPPER_ENTRY(str); // If ARG1 is atom, 'all' is the only valid value if (strcmp(str, "ALL") == 0) { // First: disables all transform passes free(ExpEnv.transform_struc.act_tr); ExpEnv.transform_struc.act_tr = NULL; ExpEnv.transform_struc.n = 0; // Second, insert all transform passes on 'ExpEnv.analysis_struc.act_tr' int i; for (i = 0; i < N_TRANSFORM_PASSES; i++) { ExpEnv.transform_struc.n += 1; ExpEnv.transform_struc.act_tr = (enumTransformPasses*)realloc(ExpEnv.transform_struc.act_tr, ExpEnv.transform_struc.n * sizeof(enumTransformPasses)); ExpEnv.transform_struc.act_tr[ExpEnv.transform_struc.n-1] = i; } return TRUE; } // value passed by argument is out of known range (ARG1 differs of 'all') Yap_Error(OUT_OF_KNOWNRANGE_ERROR,t,""); return FALSE; } else if (IsPairTerm(t)) { // ARG1 is list // First: disables all transform passes if (ExpEnv.transform_struc.act_tr) free(ExpEnv.transform_struc.act_tr); ExpEnv.transform_struc.act_tr = NULL; ExpEnv.transform_struc.n = 0; // Second: scrolls over the list treating each element individually Term u = HeadOfTermCell(t); // get head of list 't' u = Deref(u); while (1) { Int v; enumTransformPasses w; // valid values for head are 'integer' and 'atom' (the list can contain both) if (IsIntTerm(u)) { // head is integer v = IntOfTerm(u); if (v < 0 || v >= N_TRANSFORM_PASSES) { // head's value is out of known range Yap_Error(OUT_OF_KNOWNRANGE_ERROR,u,""); return FALSE; } // insert transform pass defined by 'head' on 'ExpEnv.analysis_struc.act_tr' ExpEnv.transform_struc.n += 1; ExpEnv.transform_struc.act_tr = (enumTransformPasses*)realloc(ExpEnv.transform_struc.act_tr, ExpEnv.transform_struc.n * sizeof(enumTransformPasses)); ExpEnv.transform_struc.act_tr[ExpEnv.transform_struc.n-1] = (enumTransformPasses)v; } else if (IsAtomTerm(u)) { // head is atom int i = 0, j = 0; // gets string from atom and stores it on 'str' char *str = (char*)malloc(YAP_AtomNameLength(AtomOfTerm(u))*sizeof(char)); strcpy(str, AtomName(AtomOfTerm(u))); // Makes upper characters of 'str' (for comparison) UPPER_ENTRY(str); // Detects one pass according to 'str' if (strcmp(str, "AGGRESSIVEDCE") == 0 || strcmp(str, "ADCE") == 0) w = t_createAggressiveDCEPass; else if (strcmp(str, "ARGUMENTPROMOTION") == 0 || strcmp(str, "ARGPROMOTION") == 0) w = t_createArgumentPromotionPass; else if (strcmp(str, "BBVECTORIZE") == 0) w = t_createBBVectorizePass; else if (strcmp(str, "BLOCKEXTRACTOR") == 0 || strcmp(str, "EXTRACTBLOCKS") == 0) w = t_createBlockExtractorPass; else if (strcmp(str, "BLOCKPLACEMENT") == 0) w = t_createBlockPlacementPass; else if (strcmp(str, "BREAKCRITICALEDGES") == 0 || strcmp(str, "BREAKCRITEDGES") == 0) w = t_createBreakCriticalEdgesPass; else if (strcmp(str, "CFGSIMPLIFICATION") == 0 || strcmp(str, "SIMPLIFYCFG") == 0) w = t_createCFGSimplificationPass; else if (strcmp(str, "CODEGENPREPARE") == 0) w = t_createCodeGenPreparePass; else if (strcmp(str, "CONSTANTMERGE") == 0 || strcmp(str, "CONSTMERGE") == 0) w = t_createConstantMergePass; else if (strcmp(str, "CONSTANTPROPAGATION") == 0 || strcmp(str, "CONSTPROP") == 0) w = t_createConstantPropagationPass; else if (strcmp(str, "CORRELATEDVALUEPROPAGATION") == 0 || strcmp(str, "CORRELATEDPROPAGATION") == 0) w = t_createCorrelatedValuePropagationPass; else if (strcmp(str, "DEADARGELIMINATION") == 0 || strcmp(str, "DEADARGELIM") == 0) w = t_createDeadArgEliminationPass; else if (strcmp(str, "DEADARGHACKING") == 0 || strcmp(str, "DEADARGHAX0R") == 0) w = t_createDeadArgHackingPass; else if (strcmp(str, "DEADCODEELIMINATION") == 0 || strcmp(str, "DCE") == 0) w = t_createDeadCodeEliminationPass; else if (strcmp(str, "DEADINSTELIMINATION") == 0 || strcmp(str, "DIE") == 0) w = t_createDeadInstEliminationPass; else if (strcmp(str, "DEADSTOREELIMINATION") == 0 || strcmp(str, "DSE") == 0) w = t_createDeadStoreEliminationPass; else if (strcmp(str, "DEMOTEREGISTERTOMEMORY") == 0 || strcmp(str, "REG2MEM") == 0) w = t_createDemoteRegisterToMemoryPass; else if (strcmp(str, "EARLYCSE") == 0) w = t_createEarlyCSEPass; else if (strcmp(str, "FUNCTIONATTRS") == 0) w = t_createFunctionAttrsPass; else if (strcmp(str, "FUNCTIONINLINING") == 0 || strcmp(str, "INLINE") == 0) w = t_createFunctionInliningPass; else if (strcmp(str, "GLOBALDCE") == 0) w = t_createGlobalDCEPass; else if (strcmp(str, "GLOBALOPTIMIZER") == 0 || strcmp(str, "GLOBALOPT") == 0) w = t_createGlobalOptimizerPass; else if (strcmp(str, "GVEXTRACTION") == 0) w = t_createGVExtractionPass; else if (strcmp(str, "GVN") == 0) w = t_createGVNPass; else if (strcmp(str, "INDVARSIMPLIFY") == 0 || strcmp(str, "INDVARS") == 0) w = t_createIndVarSimplifyPass; else if (strcmp(str, "INSTRUCTIONCOMBINING") == 0 || strcmp(str, "INSTCOMBINE") == 0) w = t_createInstructionCombiningPass; else if (strcmp(str, "INSTRUCTIONNAMER") == 0 || strcmp(str, "INSTNAMER") == 0) w = t_createInstructionNamerPass; else if (strcmp(str, "INSTRUCTIONSIMPLIFIER") == 0 || strcmp(str, "INSTSIMPLIFY") == 0) w = t_createInstructionSimplifierPass; else if (strcmp(str, "INTERNALIZE") == 0) w = t_createInternalizePass; else if (strcmp(str, "IPCONSTANTPROPAGATION") == 0 || strcmp(str, "IPCONSTPROP") == 0) w = t_createIPConstantPropagationPass; else if (strcmp(str, "IPSCCP") == 0) w = t_createIPSCCPPass; else if (strcmp(str, "JUMPTHREADING") == 0) w = t_createJumpThreadingPass; else if (strcmp(str, "LCSSA") == 0) w = t_createLCSSAPass; else if (strcmp(str, "LICM") == 0) w = t_createLICMPass; else if (strcmp(str, "LOOPDELETION") == 0) w = t_createLoopDeletionPass; else if (strcmp(str, "LOOPEXTRACTOR") == 0 || strcmp(str, "LOOPEXTRACT") == 0) w = t_createLoopExtractorPass; else if (strcmp(str, "LOOPIDIOM") == 0) w = t_createLoopIdiomPass; else if (strcmp(str, "LOOPINSTSIMPLIFY") == 0) w = t_createLoopInstSimplifyPass; else if (strcmp(str, "LOOPROTATE") == 0) w = t_createLoopRotatePass; else if (strcmp(str, "LOOPSIMPLIFY") == 0) w = t_createLoopSimplifyPass; else if (strcmp(str, "LOOPSTRENGTHREDUCE") == 0 || strcmp(str, "LOOPREDUCE") == 0) w = t_createLoopStrengthReducePass; else if (strcmp(str, "LOOPUNROLL") == 0) w = t_createLoopUnrollPass; else if (strcmp(str, "LOOPUNSWITCH") == 0) w = t_createLoopUnswitchPass; else if (strcmp(str, "LOWERATOMIC") == 0) w = t_createLowerAtomicPass; else if (strcmp(str, "LOWEREXPECTINTRINSIC") == 0 || strcmp(str, "LOWEREXPECT") == 0) w = t_createLowerExpectIntrinsicPass; else if (strcmp(str, "LOWERINVOKE") == 0) w = t_createLowerInvokePass; else if (strcmp(str, "LOWERSWITCH") == 0) w = t_createLowerSwitchPass; else if (strcmp(str, "MEMCPYOPT") == 0) w = t_createMemCpyOptPass; else if (strcmp(str, "MERGEFUNCTIONS") == 0 || strcmp(str, "MERGEFUNC") == 0) w = t_createMergeFunctionsPass; else if (strcmp(str, "OBJCARCAPELIM") == 0) w = t_createObjCARCAPElimPass; else if (strcmp(str, "OBJCARCCONTRACT") == 0) w = t_createObjCARCContractPass; else if (strcmp(str, "OBJCARCEXPAND") == 0) w = t_createObjCARCExpandPass; else if (strcmp(str, "OBJCARCOPT") == 0 || strcmp(str, "OBJCARC") == 0) w = t_createObjCARCOptPass; else if (strcmp(str, "PARTIALINLINING") == 0 || strcmp(str, "PARTIALINLINER") == 0) w = t_createPartialInliningPass; else if (strcmp(str, "PROMOTEMEMORYTOREGISTER") == 0 || strcmp(str, "MEM2REG") == 0) w = t_createPromoteMemoryToRegisterPass; else if (strcmp(str, "PRUNEEH") == 0) w = t_createPruneEHPass; else if (strcmp(str, "REASSOCIATE") == 0) w = t_createReassociatePass; else if (strcmp(str, "SCALARREPLAGGREGATES") == 0 || strcmp(str, "SCALARREPL") == 0) w = t_createScalarReplAggregatesPass; else if (strcmp(str, "SCCP") == 0) w = t_createSCCPPass; else if (strcmp(str, "SIMPLIFYLIBCALLS") == 0) w = t_createSimplifyLibCallsPass; else if (strcmp(str, "SINGLELOOPEXTRACTOR") == 0 || strcmp(str, "LOOPEXTRACTSINGLE") == 0) w = t_createSingleLoopExtractorPass; else if (strcmp(str, "SINKING") == 0 || strcmp(str, "SINK") == 0) w = t_createSinkingPass; else if (strcmp(str, "STRIPDEADDEBUGINFO") == 0) w = t_createStripDeadDebugInfoPass; else if (strcmp(str, "STRIPDEADPROTOTYPES") == 0) w = t_createStripDeadPrototypesPass; else if (strcmp(str, "STRIPDEBUGDECLARE") == 0) w = t_createStripDebugDeclarePass; else if (strcmp(str, "STRIPNONDEBUGSYMBOLS") == 0) w = t_createStripNonDebugSymbolsPass; else if (strcmp(str, "STRIPSYMBOLS") == 0 || strcmp(str, "STRIP") == 0) w = t_createStripSymbolsPass; else if (strcmp(str, "TAILCALLELIMINATION") == 0 || strcmp(str, "TAILCALLELIM") == 0) w = t_createTailCallEliminationPass; else { // head's value is out of known range Yap_Error(OUT_OF_KNOWNRANGE_ERROR,u,""); return FALSE; } // insert transform pass defined by 'head' on 'ExpEnv.analysis_struc.act_tr' ExpEnv.transform_struc.n += 1; ExpEnv.transform_struc.act_tr = (enumTransformPasses*)realloc(ExpEnv.transform_struc.act_tr, ExpEnv.transform_struc.n * sizeof(enumTransformPasses)); ExpEnv.transform_struc.act_tr[ExpEnv.transform_struc.n-1] = w; } else { // head's value is not an integer or atom Yap_NilError(INVALID_PARAMETER_TYPE_ERROR,"Transform pass"); return FALSE; } // here, 'u' is the current head of list (just been treated) and 't' is our list itself t = TailOfTermCell(t); // 't' is now our list without 'u' (tail of 't') t = Deref(t); if (IsAtomTerm(t)) break; // if 't' is an empty list (which is treated as atom by Prolog), we finish the loop u = HeadOfTermCell(t); // else, 'u' is now next head which will be treated u = Deref(u); } ExpEnv.transform_struc.optlevel = -1; // using this, optlevel won't be used return TRUE; } else { // ARG1 is not an integer or atom Yap_NilError(INVALID_PARAMETER_TYPE_ERROR,"Transform pass"); return FALSE; } } static Int p_enable_all_transform_passes( USES_REGS1 ) { // Same as 'transform_passes(all)' // First, disable all analysis passes if (ExpEnv.transform_struc.act_tr) free(ExpEnv.transform_struc.act_tr); ExpEnv.transform_struc.act_tr = NULL; ExpEnv.transform_struc.n = 0; // Second, insert all transform passes int i; for (i = 0; i < N_TRANSFORM_PASSES; i++) { ExpEnv.transform_struc.n += 1; ExpEnv.transform_struc.act_tr = (enumTransformPasses*) realloc(ExpEnv.transform_struc.act_tr, ExpEnv.transform_struc.n * sizeof(enumTransformPasses)); ExpEnv.transform_struc.act_tr[ExpEnv.transform_struc.n-1] = (enumTransformPasses)i; } ExpEnv.transform_struc.optlevel = -1; // using this, optlevel won't be used return TRUE; } static Int p_disable_all_transform_passes( USES_REGS1 ) { // Just empty 'ExpEnv.analysis_struc.act_tr' if (ExpEnv.transform_struc.act_tr) free(ExpEnv.transform_struc.act_tr); ExpEnv.transform_struc.act_tr = NULL; ExpEnv.transform_struc.n = 0; return TRUE; } static Int p_n_transform_passes( USES_REGS1 ) { // valid value for ARG1 is just 'integer' (number of transform passes added randomly) Term t = Deref(ARG1); if (IsIntTerm(t)) { // ARG1 is integer Int n = IntOfTerm(t); if (n < 0 || n >= N_TRANSFORM_PASSES) { // value passed by argument is out of known range Yap_Error(OUT_OF_KNOWNRANGE_ERROR,t,""); return FALSE; } // First: disables all transform passes free(ExpEnv.transform_struc.act_tr); ExpEnv.transform_struc.act_tr = NULL; ExpEnv.transform_struc.n = 0; /* Second: adds n transform passes randomly */ srand (time(NULL)); while (ExpEnv.transform_struc.n < n) { CELL v = rand() % (n); if ( ((enumTransformPasses)v == t_createBlockExtractorPass) || ((enumTransformPasses)v == t_createDeadArgHackingPass) || ((enumTransformPasses)v == t_createGVExtractionPass) || ((enumTransformPasses)v == t_createLoopExtractorPass) || ((enumTransformPasses)v == t_createStripDeadDebugInfoPass) || ((enumTransformPasses)v == t_createStripDeadPrototypesPass) || ((enumTransformPasses)v == t_createStripDebugDeclarePass) || ((enumTransformPasses)v == t_createStripNonDebugSymbolsPass) || ((enumTransformPasses)v == t_createStripSymbolsPass) ) { // I can't add these passes (they are used just for debugging) n -= 1; continue; } COUNT i = 0; /* I must ensure all steps are different from one another */ while (i < ExpEnv.transform_struc.n) { if (ExpEnv.transform_struc.act_tr[i] == (enumTransformPasses)v) break; i++; } if (i == ExpEnv.transform_struc.n) { /***/ // If pass is not specific for debugging and not yet added so I add it */ ExpEnv.transform_struc.n += 1; ExpEnv.transform_struc.act_tr = (enumTransformPasses*) realloc(ExpEnv.transform_struc.act_tr, ExpEnv.transform_struc.n*sizeof(enumTransformPasses)); ExpEnv.transform_struc.act_tr[ExpEnv.transform_struc.n-1] = (enumTransformPasses)v; } } ExpEnv.transform_struc.optlevel = -1; // using this, optlevel won't be used return TRUE; } else { // ARG1 is not an integer Yap_NilError(INVALID_PARAMETER_TYPE_ERROR,"N transform passes"); return FALSE; } } static Int p_transform_level( USES_REGS1 ) { Term t = Deref(ARG1); // valid value for ARG1 is just 'integer' if (IsIntTerm(t)) { // ARG1 is integer Int lvl = IntOfTerm(t); if (lvl < -1 || lvl > 3) { // value passed by argument is out of known range (valid values are: 0, 1, 2, and 3) Yap_Error(OUT_OF_KNOWNRANGE_ERROR,t,""); return FALSE; } ExpEnv.transform_struc.optlevel = lvl; // if 'transform_pass' or similars are used before, they won't be considered /* Setting function inlining threshold (for createFunctionInliningPass) -- level 0 does not apply this */ if (ExpEnv.transform_struc.optlevel == 3) ExpEnv.transform_struc.opt_args.inline_threshold = 225; else if (ExpEnv.transform_struc.optlevel == 2) ExpEnv.transform_struc.opt_args.inline_threshold = 100; else ExpEnv.transform_struc.opt_args.inline_threshold = 40; return TRUE; } else { // ARG1 is not an integer Yap_NilError(INVALID_PARAMETER_TYPE_ERROR,"Transform level"); return FALSE; } } static Int p_argument_promotion_max_elements( USES_REGS1 ) { Term t = Deref(ARG1); // valid value for ARG1 is just 'integer' if (IsIntTerm(t)) { // ARG1 is integer Int v = IntOfTerm(t); #if SIZEOF_INT_P==4 if (v < 0 || v > 0xffffffff) { // 32 bits #else /* SIZEOF_INT_P==8 */ if (v < 0 || v > 0x1999999999999999) { // 64 bits #endif // value passed by argument is out of known range (max value is machine-dependent) Yap_Error(OUT_OF_KNOWNRANGE_ERROR,t,""); return FALSE; } // Setting max elements for Argument Promotion Pass ExpEnv.transform_struc.opt_args.arg_promotion_max_elements = v; return TRUE; } else { // ARG1 is not an integer Yap_NilError(INVALID_PARAMETER_TYPE_ERROR,"Argument Promotion Max Elements"); return FALSE; } } static Int p_scalar_replace_aggregates_threshold( USES_REGS1 ) { Term t = Deref(ARG1); // valid value for ARG1 is just 'integer' if (IsIntTerm(t)) { // ARG1 is integer Int v = IntOfTerm(t); if (v < -1 || v > 0xffff) { // value passed by argument is out of known range (max value is 65535) Yap_Error(OUT_OF_KNOWNRANGE_ERROR,t,""); return FALSE; } // Setting threshold for Scalar Repl Aggregates Pass ExpEnv.transform_struc.opt_args.scalar_replace_aggregates_threshold = v; return TRUE; } else { // ARG1 is not an integer Yap_NilError(INVALID_PARAMETER_TYPE_ERROR,"Scalar Replace Aggregates Threshold"); return FALSE; } } static Int p_loop_unroll_threshold( USES_REGS1 ) { Term t = Deref(ARG1); // valid value for ARG1 is just 'integer' if (IsIntTerm(t)) { // ARG1 is integer Int v = IntOfTerm(t); if (v < -1 || v > 0xffff) { // value passed by argument is out of known range (max value is 65535) Yap_Error(OUT_OF_KNOWNRANGE_ERROR,t,""); return FALSE; } // Setting threshold for Loop Unroll Pass ExpEnv.transform_struc.opt_args.loop_unroll_threshold = v; return TRUE; } else { // ARG1 is not an integer Yap_NilError(INVALID_PARAMETER_TYPE_ERROR,"Loop Unroll Threshold"); return FALSE; } } static Int p_inline_threshold( USES_REGS1 ) { Term t = Deref(ARG1); // valid value for ARG1 is just 'integer' if (IsIntTerm(t)) { // ARG1 is integer Int v = IntOfTerm(t); if (v < -1 || v > 0xffff) { // value passed by argument is out of known range (max value is 65535) Yap_Error(OUT_OF_KNOWNRANGE_ERROR,t,""); return FALSE; } // Setting threshold for Function Inlining Pass ExpEnv.transform_struc.opt_args.inline_threshold = v; return TRUE; } else { // ARG1 is not an integer Yap_NilError(INVALID_PARAMETER_TYPE_ERROR,"Inline Threshold"); return FALSE; } } static Int p_strip_symbols_pass_type( USES_REGS1 ) { Term t = Deref(ARG1); // valid values for ARG1 are 'integer' and 'atom' if (IsIntTerm(t)) { // ARG1 is integer // Setting Strip Symbols Pass condition. '0' is false; Any other value is true ExpEnv.transform_struc.opt_args.strip_symbols_pass_type = IntOfTerm(t); return TRUE; } else if (IsAtomTerm(t)) { // ARG1 is atom int i = 0, j = 0; char *tmp; // gets string from atom and stores it on 'str' char *str = (char*)malloc(YAP_AtomNameLength(AtomOfTerm(t))*sizeof(char)); strcpy(str, AtomName(AtomOfTerm(t))); // Makes upper characters of 'str' (for comparison) UPPER_ENTRY(str); // Detecting value according to 'str' if (strcmp(str, "FALSE") == 0) ExpEnv.transform_struc.opt_args.strip_symbols_pass_type = 0; else if (strcmp(str, "TRUE") == 0) ExpEnv.transform_struc.opt_args.strip_symbols_pass_type = 1; else { // value passed by argument is out of known range (only 'true' or 'false' are allowed) Yap_Error(OUT_OF_KNOWNRANGE_ERROR,t,""); return FALSE; } return TRUE; } else { // ARG1 is not an integer or atom Yap_NilError(INVALID_PARAMETER_TYPE_ERROR,"Strip Symbols Pass Type"); return FALSE; } } static Int p_loop_unswitch_optimize_for_size( USES_REGS1 ) { Term t = Deref(ARG1); // valid values for ARG1 are 'integer' and 'atom' if (IsIntTerm(t)) { // ARG1 is integer // Setting Loop Unswitch Pass condition. '0' is false; Any other value is true ExpEnv.transform_struc.opt_args.loop_unswitch_optimize_for_size = IntOfTerm(t); return TRUE; } else if (IsAtomTerm(t)) { // ARG1 is atom int i = 0, j = 0; char *tmp; // gets string from atom and stores it on 'str' char *str = (char*)malloc(YAP_AtomNameLength(AtomOfTerm(t))*sizeof(char)); strcpy(str, AtomName(AtomOfTerm(t))); // Makes upper characters of 'str' (for comparison) UPPER_ENTRY(str); // Detecting value according to 'str' if (strcmp(str, "FALSE") == 0) ExpEnv.transform_struc.opt_args.loop_unswitch_optimize_for_size = 0; else if (strcmp(str, "TRUE") == 0) ExpEnv.transform_struc.opt_args.loop_unswitch_optimize_for_size = 1; else { // value passed by argument is out of known range (only 'true' or 'false' are allowed) Yap_Error(OUT_OF_KNOWNRANGE_ERROR,t,""); return FALSE; } return TRUE; } else { // ARG1 is not an integer or atom Yap_NilError(INVALID_PARAMETER_TYPE_ERROR,"Loop Unswitch Optimize for Size"); return FALSE; } } static Int p_default_optimization_args( USES_REGS1 ) { /* resetting arguments used in some passes */ ExpEnv.transform_struc.opt_args.arg_promotion_max_elements = 3; // Argument Promotion Pass ExpEnv.transform_struc.opt_args.strip_symbols_pass_type = 0; // Strip Symbols Pass ExpEnv.transform_struc.opt_args.scalar_replace_aggregates_threshold = -1; // Scalar Repl Aggregates Pass ExpEnv.transform_struc.opt_args.loop_unswitch_optimize_for_size = 0; // Loop Unswitch Pass ExpEnv.transform_struc.opt_args.loop_unroll_threshold = -1; // Loop Unroll Pass // Function Inlining Pass (according current 'optlevel') if (ExpEnv.transform_struc.optlevel == 3) ExpEnv.transform_struc.opt_args.inline_threshold = 225; else if (ExpEnv.transform_struc.optlevel == 2) ExpEnv.transform_struc.opt_args.inline_threshold = 100; else if (ExpEnv.transform_struc.optlevel == 1) ExpEnv.transform_struc.opt_args.inline_threshold = 40; else // 0 ExpEnv.transform_struc.opt_args.inline_threshold = 0; /***/ // Link-time optimization ExpEnv.transform_struc.link_time_opt.enabled = 0; ExpEnv.transform_struc.link_time_opt.internalize = 0; ExpEnv.transform_struc.link_time_opt.runinliner = 0; return TRUE; } static Int p_reset_optimization_args( USES_REGS1 ) { // Same as 'p_default_optimization_args' p_default_optimization_args( PASS_REGS1 ); return TRUE; } static Int p_enable_unit_at_time( USES_REGS1 ) { // Enable IPO ExpEnv.transform_struc.unit_at_time_enabled = 1; return TRUE; } static Int p_enable_simplify_libcalls( USES_REGS1 ) { // Enable libcalls simplification ExpEnv.transform_struc.simplify_libcalls_enabled = 1; return TRUE; } static Int p_disable_unit_at_time( USES_REGS1 ) { // Disable IPO ExpEnv.transform_struc.unit_at_time_enabled = 0; return TRUE; } static Int p_disable_simplify_libcalls( USES_REGS1 ) { // Disable libcalls simplification ExpEnv.transform_struc.simplify_libcalls_enabled = 0; return TRUE; } static Int p_link_time_opt1( USES_REGS1 ) { Term t = Deref(ARG1); // valid value for ARG1 are 'integer' and 'atom' if (IsIntTerm(t)) { // 'ARG1' is integer // enabling link-time optimization ('internalize' = 1 and 'runinliner' = 0 are default) ExpEnv.transform_struc.link_time_opt.enabled = IntOfTerm(t); ExpEnv.transform_struc.link_time_opt.internalize = 1; ExpEnv.transform_struc.link_time_opt.runinliner = 0; return TRUE; } else if (IsAtomTerm(t)) { // 'ARG1' is atom int i = 0, j = 0; char *tmp; // gets string from atom and stores it on 'str' char *str = (char*)malloc(YAP_AtomNameLength(AtomOfTerm(t))*sizeof(char)); strcpy(str, AtomName(AtomOfTerm(t))); // Makes upper characters of 'str' (for comparison) UPPER_ENTRY(str); // Detecting value according to 'str' if (strcmp(str, "FALSE") == 0) { // disabling link-time optimization ('internalize' and 'runinliner' does not work if 'enabled' = 0) ExpEnv.transform_struc.link_time_opt.enabled = 0; ExpEnv.transform_struc.link_time_opt.internalize = 0; ExpEnv.transform_struc.link_time_opt.runinliner = 0; } else if (strcmp(str, "TRUE") == 0) { // enabling link-time optimization ('internalize' = 1 and 'runinliner' = 0 are default) ExpEnv.transform_struc.link_time_opt.enabled = 1; ExpEnv.transform_struc.link_time_opt.internalize = 1; ExpEnv.transform_struc.link_time_opt.runinliner = 0; } else { // value passed by argument is out of known range (only 'true' or 'false' are allowed) Yap_Error(OUT_OF_KNOWNRANGE_ERROR,t,""); return FALSE; } return TRUE; } else { // ARG1 is not an integer or atom Yap_NilError(INVALID_PARAMETER_TYPE_ERROR,"Link-time optimization"); return FALSE; } } static Int p_link_time_opt3( USES_REGS1 ) { Term t = Deref(ARG1); // valid value for ARG1 are 'integer' and 'atom' if (IsIntTerm(t) || IsAtomTerm(t)) { Term u = Deref(ARG2); // valid value for ARG2 are 'integer' and 'atom' if (IsIntTerm(u) || IsAtomTerm(u)) { Term v = Deref(ARG3); // valid value for ARG3 are 'integer' and 'atom' if (IsIntTerm(v) || IsAtomTerm(v)) { /* setting 1st argument (link-time optimization itself) */ if (IsIntTerm(t)) { // ARG1 is integer ExpEnv.transform_struc.link_time_opt.enabled = IntOfTerm(t); } else /* atom */ { // ARG1 is atom int i = 0, j = 0; char *tmp; // gets string from atom and stores it on 'str' char *str = (char*)malloc(YAP_AtomNameLength(AtomOfTerm(t))*sizeof(char)); strcpy(str, AtomName(AtomOfTerm(t))); // Makes upper characters of 'str' (for comparison) UPPER_ENTRY(str); // Detecting value according to 'str' if (strcmp(str, "FALSE") == 0) ExpEnv.transform_struc.link_time_opt.enabled = 0; // disabling link-time opt else if (strcmp(str, "TRUE") == 0) ExpEnv.transform_struc.link_time_opt.enabled = 1; // enabling link-time opt else { // value passed by argument is out of known range (only 'true' or 'false' are allowed) Yap_Error(OUT_OF_KNOWNRANGE_ERROR,t,""); return FALSE; } } /* setting 2nd argument (internalize) */ if (IsIntTerm(u)) { // ARG2 is integer ExpEnv.transform_struc.link_time_opt.internalize = IntOfTerm(u); } else /* atom */ { // ARG2 is atom int i = 0, j = 0; char *tmp; // gets string from atom and stores it on 'str' char *str = (char*)malloc(YAP_AtomNameLength(AtomOfTerm(u))*sizeof(char)); strcpy(str, AtomName(AtomOfTerm(u))); // Makes upper characters of 'str' (for comparison) UPPER_ENTRY(str); // Detecting value according to 'str' if (strcmp(str, "FALSE") == 0) ExpEnv.transform_struc.link_time_opt.internalize = 0; // disabling internalize else if (strcmp(str, "TRUE") == 0) ExpEnv.transform_struc.link_time_opt.internalize = 1; // enabling internalize else { // value passed by argument is out of known range (only 'true' or 'false' are allowed) Yap_Error(OUT_OF_KNOWNRANGE_ERROR,u,""); return FALSE; } } /* setting 3rd argument (runinliner) */ if (IsIntTerm(v)) { // ARG3 is integer ExpEnv.transform_struc.link_time_opt.runinliner = IntOfTerm(v); return TRUE; } else /* atom */ { // ARG3 is atom int i = 0, j = 0; char *tmp; // gets string from atom and stores it on 'str' char *str = (char*)malloc(YAP_AtomNameLength(AtomOfTerm(v))*sizeof(char)); strcpy(str, AtomName(AtomOfTerm(v))); // Makes upper characters of 'str' (for comparison) UPPER_ENTRY(str); // Detecting value according to 'str' if (strcmp(str, "FALSE") == 0) ExpEnv.transform_struc.link_time_opt.runinliner = 0; // disabling runinliner else if (strcmp(str, "TRUE") == 0) ExpEnv.transform_struc.link_time_opt.runinliner = 1; // enabling runinliner else { // value passed by argument is out of known range (only 'true' or 'false' are allowed) Yap_Error(OUT_OF_KNOWNRANGE_ERROR,v,""); return FALSE; } return TRUE; } } else { // ARG3 is not an integer or atom Yap_NilError(INVALID_PARAMETER_TYPE_ERROR,"Link-time optimization (3rd arg)"); return FALSE; } } else { // ARG2 is not an integer or atom Yap_NilError(INVALID_PARAMETER_TYPE_ERROR,"Link-time optimization (2nd arg)"); return FALSE; } } else { // ARG1 is not an integer or atom Yap_NilError(INVALID_PARAMETER_TYPE_ERROR,"Link-time optimization (1st arg)"); return FALSE; } } static Int p_enable_link_time_opt( USES_REGS1 ) { // Same as 'link_time_opt(true)' ExpEnv.transform_struc.link_time_opt.enabled = 1; ExpEnv.transform_struc.link_time_opt.internalize = 1; ExpEnv.transform_struc.link_time_opt.runinliner = 0; return TRUE; } static Int p_enable_link_time_opt2( USES_REGS1 ) { Term t = Deref(ARG1); // valid value for ARG1 are 'integer' and 'atom' if (IsIntTerm(t) || IsAtomTerm(t)) { // valid value for ARG2 are 'integer' and 'atom' Term u = Deref(ARG2); if (IsIntTerm(u) || IsAtomTerm(u)) { /* setting 1st argument (internalize) */ if (IsIntTerm(t)) { // ARG1 is integer ExpEnv.transform_struc.link_time_opt.internalize = IntOfTerm(t); } else /* atom */ { // ARG1 is atom int i = 0, j = 0; char *tmp; // gets string from atom and stores it on 'str' char *str = (char*)malloc(YAP_AtomNameLength(AtomOfTerm(t))*sizeof(char)); strcpy(str, AtomName(AtomOfTerm(t))); // Makes upper characters of 'str' (for comparison) UPPER_ENTRY(str); // Detecting value according to 'str' if (strcmp(str, "FALSE") == 0) ExpEnv.transform_struc.link_time_opt.internalize = 0; // disabling internalize else if (strcmp(str, "TRUE") == 0) ExpEnv.transform_struc.link_time_opt.internalize = 1; // enabling internalize else { // value passed by argument is out of known range (only 'true' or 'false' are allowed) Yap_Error(OUT_OF_KNOWNRANGE_ERROR,t,""); return FALSE; } } /* setting 2nd argument (runinliner) */ if (IsIntTerm(u)) { // ARG2 is integer ExpEnv.transform_struc.link_time_opt.runinliner = IntOfTerm(u); ExpEnv.transform_struc.link_time_opt.enabled = 1; return TRUE; } else /* atom */ { // ARG2 is atom int i = 0, j = 0; char *tmp; // gets string from atom and stores it on 'str' char *str = (char*)malloc(YAP_AtomNameLength(AtomOfTerm(u))*sizeof(char)); strcpy(str, AtomName(AtomOfTerm(u))); // Makes upper characters of 'str' (for comparison) UPPER_ENTRY(str); // Detecting value according to 'str' if (strcmp(str, "FALSE") == 0) ExpEnv.transform_struc.link_time_opt.runinliner = 0; // disabling runinliner else if (strcmp(str, "TRUE") == 0) ExpEnv.transform_struc.link_time_opt.runinliner = 1; // enabling runinliner else { // value passed by argument is out of known range (only 'true' or 'false' are allowed) Yap_Error(OUT_OF_KNOWNRANGE_ERROR,u,""); return FALSE; } ExpEnv.transform_struc.link_time_opt.enabled = 1; // enabling link-time opt return TRUE; } } else { // ARG2 is not an integer or atom Yap_NilError(INVALID_PARAMETER_TYPE_ERROR,"Link-time optimization (2nd arg)"); return FALSE; } } else { // ARG1 is not an integer or atom Yap_NilError(INVALID_PARAMETER_TYPE_ERROR,"Link-time optimization (1st arg)"); return FALSE; } } static Int p_disable_link_time_opt( USES_REGS1 ) { ExpEnv.transform_struc.link_time_opt.enabled = 0; ExpEnv.transform_struc.link_time_opt.internalize = 0; ExpEnv.transform_struc.link_time_opt.runinliner = 0; return TRUE; } #pragma GCC diagnostic pop void Yap_InitJitTransformPreds( void ) { Yap_InitCPred("disable_transform_pass", 1, p_disable_transform_pass, SafePredFlag); Yap_InitCPred("transform_pass", 1, p_transform_pass, SafePredFlag); Yap_InitCPred("enable_transform_pass", 1, p_enable_transform_pass, SafePredFlag); Yap_InitCPred("transform_passes", 1, p_transform_passes, SafePredFlag); Yap_InitCPred("enable_all_transform_passes", 0, p_enable_all_transform_passes, SafePredFlag); Yap_InitCPred("disable_all_transform_passes", 1, p_disable_all_transform_passes, SafePredFlag); Yap_InitCPred("n_transform_passes", 1, p_n_transform_passes, SafePredFlag); Yap_InitCPred("transform_level", 1, p_transform_level, SafePredFlag); Yap_InitCPred("argument_promotion_max_elements", 1, p_argument_promotion_max_elements, SafePredFlag); Yap_InitCPred("scalar_replace_aggregates_threshold", 1, p_scalar_replace_aggregates_threshold, SafePredFlag); Yap_InitCPred("loop_unroll_threshold", 1, p_loop_unroll_threshold, SafePredFlag); Yap_InitCPred("inline_threshold", 1, p_inline_threshold, SafePredFlag); Yap_InitCPred("strip_symbols_pass_type", 1, p_strip_symbols_pass_type, SafePredFlag); Yap_InitCPred("loop_unswitch_optimize_for_size", 1, p_loop_unswitch_optimize_for_size, SafePredFlag); Yap_InitCPred("default_optimization_args", 0, p_default_optimization_args, SafePredFlag); Yap_InitCPred("reset_optimization_args", 0, p_reset_optimization_args, SafePredFlag); Yap_InitCPred("enable_unit_at_time", 0, p_enable_unit_at_time, SafePredFlag); Yap_InitCPred("enable_simplify_libcalls", 0, p_enable_simplify_libcalls, SafePredFlag); Yap_InitCPred("disable_unit_at_time", 0, p_disable_unit_at_time, SafePredFlag); Yap_InitCPred("disable_simplify_libcalls", 0, p_disable_simplify_libcalls, SafePredFlag); Yap_InitCPred("link_time_opt", 1, p_link_time_opt1, SafePredFlag); Yap_InitCPred("link_time_opt", 3, p_link_time_opt3, SafePredFlag); Yap_InitCPred("enable_link_time_opt", 0, p_enable_link_time_opt, SafePredFlag); Yap_InitCPred("enable_link_time_opt", 2, p_enable_link_time_opt2, SafePredFlag); Yap_InitCPred("disable_link_time_opt", 0, p_disable_link_time_opt, SafePredFlag); }