| // GNU D Compiler attribute support declarations. | |
| // Copyright (C) 2021-2025 Free Software Foundation, Inc. | |
| // GCC is free software; you can redistribute it and/or modify it under | |
| // the terms of the GNU General Public License as published by the Free | |
| // Software Foundation; either version 3, or (at your option) any later | |
| // version. | |
| // GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
| // WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| // for more details. | |
| // Under Section 7 of GPL version 3, you are granted additional | |
| // permissions described in the GCC Runtime Library Exception, version | |
| // 3.1, as published by the Free Software Foundation. | |
| // You should have received a copy of the GNU General Public License and | |
| // a copy of the GCC Runtime Library Exception along with this program; | |
| // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
| // <http://www.gnu.org/licenses/>. | |
| module gcc.attributes; | |
| // Private helper templates. | |
| private struct Attribute(A...) | |
| { | |
| A arguments; | |
| } | |
| private enum bool isStringValue(alias T) = is(typeof(T) == string); | |
| private enum bool isStringOrIntValue(alias T) | |
| = is(typeof(T) == string) || is(typeof(T) == int); | |
| private template allSatisfy(alias F, T...) | |
| { | |
| static if (T.length == 0) | |
| enum allSatisfy = true; | |
| else static if (T.length == 1) | |
| enum allSatisfy = F!(T[0]); | |
| else | |
| { | |
| enum allSatisfy = allSatisfy!(F, T[ 0 .. $/2]) | |
| && allSatisfy!(F, T[$/2 .. $ ]); | |
| } | |
| } | |
| /** | |
| * Generic entrypoint for applying GCC attributes to a function or type. | |
| * There is no type checking done, as well as no deprecation path for | |
| * attributes removed from the compiler. So the recommendation is to use any | |
| , of the other UDAs available unless it is a target-specific attribute. | |
| * | |
| * Function attributes introduced by the @attribute UDA are used in the | |
| * declaration of a function, followed by an attribute name string and | |
| * any arguments separated by commas enclosed in parentheses. | |
| * | |
| * Example: | |
| * --- | |
| * import gcc.attributes; | |
| * | |
| * @attribute("regparm", 1) int func(int size); | |
| * --- | |
| */ | |
| @system | |
| auto attribute(A...)(A arguments) | |
| if (A.length > 0 && is(A[0] == string)) | |
| { | |
| return Attribute!A(arguments); | |
| } | |
| /////////////////////////////////////////////////////////////////////////////// | |
| // | |
| // Supported common attributes exposed by GDC. | |
| // | |
| /////////////////////////////////////////////////////////////////////////////// | |
| /** | |
| * The `@alloc_size` attribute may be applied to a function that returns a | |
| * pointer and takes at least one argument of an integer or enumerated type. | |
| * It indicates that the returned pointer points to memory whose size is given | |
| * by the function argument at `sizeArgIdx`, or by the product of the arguments | |
| * at `sizeArgIdx` and `numArgIdx`. Meaningful sizes are positive values less | |
| * than `ptrdiff_t.max`. Unless `zeroBasedNumbering` is true, argument | |
| * numbering starts at one for ordinary functions, and at two for non-static | |
| * member functions. | |
| * | |
| * If `numArgIdx` is less than `0`, it is taken to mean there is no argument | |
| * specifying the element count. | |
| * | |
| * Example: | |
| * --- | |
| * import gcc.attributes; | |
| * | |
| * @alloc_size(1) extern(C) void* malloc(size_t size); | |
| * @alloc_size(3,2) extern(C) void* reallocarray(void *ptr, size_t nmemb, | |
| * size_t size); | |
| * @alloc_size(1,2) void* my_calloc(size_t element_size, size_t count, | |
| * bool irrelevant); | |
| * --- | |
| */ | |
| auto alloc_size(int sizeArgIdx) | |
| { | |
| return attribute("alloc_size", sizeArgIdx); | |
| } | |
| /// ditto | |
| auto alloc_size(int sizeArgIdx, int numArgIdx) | |
| { | |
| return attribute("alloc_size", sizeArgIdx, numArgIdx); | |
| } | |
| /// ditto | |
| auto alloc_size(int sizeArgIdx, int numArgIdx, bool zeroBasedNumbering) | |
| { | |
| return attribute("alloc_size", sizeArgIdx, numArgIdx, zeroBasedNumbering); | |
| } | |
| auto alloc_size(A...)(A arguments) | |
| { | |
| assert(false, "alloc_size attribute argument value is not an integer constant"); | |
| } | |
| /** | |
| * The `@always_inline` attribute inlines the function independent of any | |
| * restrictions that otherwise apply to inlining. Failure to inline such a | |
| * function is diagnosed as an error. | |
| * | |
| * Example: | |
| * --- | |
| * import gcc.attributes; | |
| * | |
| * @always_inline int func(); | |
| * --- | |
| */ | |
| enum always_inline = attribute("always_inline"); | |
| /** | |
| * The `@cold` attribute on functions is used to inform the compiler that the | |
| * function is unlikely to be executed. The function is optimized for size | |
| * rather than speed and on many targets it is placed into a special subsection | |
| * of the text section so all cold functions appear close together, improving | |
| * code locality of non-cold parts of program. The paths leading to calls of | |
| * cold functions within code are considered to be cold too. | |
| * | |
| * Example: | |
| * --- | |
| * import gcc.attributes; | |
| * | |
| * @cold int func(); | |
| * --- | |
| */ | |
| enum cold = attribute("cold"); | |
| /** | |
| * The `@flatten` attribute is used to inform the compiler that every call | |
| * inside this function should be inlined, if possible. Functions declared with | |
| * attribute `@noinline` and similar are not inlined. | |
| * | |
| * Example: | |
| * --- | |
| * import gcc.attributes; | |
| * | |
| * @flatten int func(); | |
| * --- | |
| */ | |
| enum flatten = attribute("flatten"); | |
| /** | |
| * The `@no_icf` attribute prevents a functions from being merged with another | |
| * semantically equivalent function. | |
| * | |
| * Example: | |
| * --- | |
| * import gcc.attributes; | |
| * | |
| * @no_icf int func(); | |
| * --- | |
| */ | |
| enum no_icf = attribute("no_icf"); | |
| /** | |
| * The `@no_sanitize` attribute on functions is used to inform the compiler | |
| * that it should not do sanitization of any option mentioned in | |
| * sanitize_option. A list of values acceptable by the `-fsanitize` option | |
| * can be provided. | |
| * | |
| * Example: | |
| * --- | |
| * import gcc.attributes; | |
| * | |
| * @no_sanitize("alignment", "object-size") void func1() { } | |
| * @no_sanitize("alignment,object-size") void func2() { } | |
| * --- | |
| */ | |
| auto no_sanitize(A...)(A arguments) | |
| if (allSatisfy!(isStringValue, arguments)) | |
| { | |
| return attribute("no_sanitize", arguments); | |
| } | |
| auto no_sanitize(A...)(A arguments) | |
| if (!allSatisfy!(isStringValue, arguments)) | |
| { | |
| assert(false, "no_sanitize attribute argument not a string constant"); | |
| } | |
| /** | |
| * The `@noclone` attribute prevents a function from being considered for | |
| * cloning - a mechanism that produces specialized copies of functions and | |
| * which is (currently) performed by interprocedural constant propagation. | |
| * | |
| * Example: | |
| * --- | |
| * import gcc.attributes; | |
| * | |
| * @noclone int func(); | |
| * --- | |
| */ | |
| enum noclone = attribute("noclone"); | |
| /** | |
| * The `@noinline` attribute prevents a function from being considered for | |
| * inlining. If the function does not have side effects, there are | |
| * optimizations other than inlining that cause function calls to be optimized | |
| * away, although the function call is live. To keep such calls from being | |
| * optimized away, put `asm { ""; }` in the called function, to serve as a | |
| * special side effect. | |
| * | |
| * Example: | |
| * --- | |
| * import gcc.attributes; | |
| * | |
| * @noinline int func(); | |
| * --- | |
| */ | |
| enum noinline = attribute("noinline"); | |
| /** | |
| * The `@noipa` attribute disables interprocedural optimizations between the | |
| * function with this attribute and its callers, as if the body of the function | |
| * is not available when optimizing callers and the callers are unavailable when | |
| * optimizing the body. This attribute implies `@noinline`, `@noclone`, and | |
| * `@no_icf` attributes. However, this attribute is not equivalent to a | |
| * combination of other attributes, because its purpose is to suppress existing | |
| * and future optimizations employing interprocedural analysis, including those | |
| * that do not have an attribute suitable for disabling them individually. | |
| * | |
| * This attribute is supported mainly for the purpose of testing the compiler. | |
| * | |
| * Example: | |
| * --- | |
| * import gcc.attributes; | |
| * | |
| * @noipa int func(); | |
| * --- | |
| */ | |
| enum noipa = attribute("noipa"); | |
| /** | |
| * The `@optimize` attribute is used to specify that a function is to be | |
| * compiled with different optimization options than specified on the command | |
| * line. Valid `arguments` are constant non-negative integers and strings. | |
| * Multiple arguments can be provided, separated by commas to specify multiple | |
| * options. Each numeric argument specifies an optimization level. Each string | |
| * argument that begins with the letter O refers to an optimization option such | |
| * as `-O0` or `-Os`. Other options are taken as suffixes to the `-f` prefix | |
| * jointly forming the name of an optimization option. | |
| * | |
| * Not every optimization option that starts with the `-f` prefix specified by | |
| * the attribute necessarily has an effect on the function. The `@optimize` | |
| * attribute should be used for debugging purposes only. It is not suitable in | |
| * production code. | |
| * | |
| * Example: | |
| * --- | |
| * import gcc.attributes; | |
| * | |
| * @optimize(2) double fn0(double x); | |
| * @optimize("2") double fn1(double x); | |
| * @optimize("s") double fn2(double x); | |
| * @optimize("Ofast") double fn3(double x); | |
| * @optimize("-O2") double fn4(double x); | |
| * @optimize("tree-vectorize") double fn5(double x); | |
| * @optimize("-ftree-vectorize") double fn6(double x); | |
| * @optimize("no-finite-math-only", 3) double fn7(double x); | |
| * --- | |
| */ | |
| auto optimize(A...)(A arguments) | |
| if (allSatisfy!(isStringOrIntValue, arguments)) | |
| { | |
| return attribute("optimize", arguments); | |
| } | |
| auto optimize(A...)(A arguments) | |
| if (!allSatisfy!(isStringOrIntValue, arguments)) | |
| { | |
| assert(false, "optimize attribute argument not a string or integer constant"); | |
| } | |
| /** | |
| * The `@register` attribute specifies that a local or `__gshared` variable | |
| * is to be given a register storage-class in the C99 sense of the term, and | |
| * will be placed into a register named `registerName`. | |
| * | |
| * The variable needs to boiled down to a data type that fits the target | |
| * register. It also cannot have either thread-local or `extern` storage. | |
| * It is an error to take the address of a register variable. | |
| * | |
| * Example: | |
| * --- | |
| * import gcc.attributes; | |
| * | |
| * @register("ebx") __gshared int ebx = void; | |
| * | |
| * void func() { @register("r10") long r10 = 0x2a; } | |
| * --- | |
| */ | |
| auto register(string registerName) | |
| { | |
| return attribute("register", registerName); | |
| } | |
| auto register(A...)(A arguments) | |
| { | |
| assert(false, "register attribute argument not a string constant"); | |
| } | |
| /** | |
| * The `@restrict` attribute specifies that a function parameter is to be | |
| * restrict-qualified in the C99 sense of the term. The parameter needs to | |
| * boil down to either a pointer or reference type, such as a D pointer, | |
| * class reference, or a `ref` parameter. | |
| * | |
| * Example: | |
| * --- | |
| * import gcc.attributes; | |
| * | |
| * void func(@restrict ref const float[16] array); | |
| * --- | |
| */ | |
| enum restrict = attribute("restrict"); | |
| /** | |
| * The `@section` attribute specifies that a function lives in a particular | |
| * section. For when you need certain particular functions to appear in | |
| * special sections. | |
| * | |
| * Some file formats do not support arbitrary sections so the section attribute | |
| * is not available on all platforms. If you need to map the entire contents | |
| * of a module to a particular section, consider using the facilities of the | |
| * linker instead. | |
| * | |
| * Example: | |
| * --- | |
| * import gcc.attributes; | |
| * | |
| * @section("bar") extern void func(); | |
| * --- | |
| */ | |
| auto section(string sectionName) | |
| { | |
| return attribute("section", sectionName); | |
| } | |
| auto section(A...)(A arguments) | |
| { | |
| assert(false, "section attribute argument not a string constant"); | |
| } | |
| /** | |
| * The `@simd` attribute enables creation of one or more function versions that | |
| * can process multiple arguments using SIMD instructions from a single | |
| * invocation. Specifying this attribute allows compiler to assume that such | |
| * versions are available at link time (provided in the same or another module). | |
| * Generated versions are target-dependent and described in the corresponding | |
| * Vector ABI document. For x86_64 target this document can be found here. | |
| * https://sourceware.org/glibc/wiki/libmvec?action=AttachFile&do=view&target=VectorABI.txt | |
| * | |
| * The `@simd_clones` attribute is the same as `@simd`, but also includes a | |
| * `mask` argument. Valid masks values are `notinbranch` or `inbranch`, and | |
| * instructs the compiler to generate non-masked or masked clones | |
| * correspondingly. | |
| * | |
| * Example: | |
| * --- | |
| * import gcc.attributes; | |
| * | |
| * @simd double sqrt(double x); | |
| * @simd("notinbranch") double atan2(double y, double x); | |
| * --- | |
| */ | |
| enum simd = attribute("simd"); | |
| auto simd_clones(string mask) | |
| { | |
| if (mask == "notinbranch" || mask == "inbranch") | |
| return attribute("simd", mask); | |
| else | |
| { | |
| assert(false, "unrecognized parameter `" ~ mask | |
| ~ "` for `gcc.attribute.simd_clones`"); | |
| } | |
| } | |
| auto simd_clones(A...)(A arguments) | |
| { | |
| assert(false, "simd_clones attribute argument not a string constant"); | |
| } | |
| /** | |
| * The `@symver` attribute creates a symbol version on ELF targets. The syntax | |
| * of the string parameter is `name@nodename`. The `name` part of the parameter | |
| * is the actual name of the symbol by which it will be externally referenced. | |
| * The `nodename` portion should be the name of a node specified in the version | |
| * script supplied to the linker when building a shared library. Versioned | |
| * symbol must be defined and must be exported with default visibility. | |
| * | |
| * Finally if the parameter is `name@@nodename` then in addition to creating a | |
| * symbol version (as if `name@nodename` was used) the version will be also used | |
| * to resolve `name` by the linker. | |
| * | |
| * Example: | |
| * --- | |
| * import gcc.attributes; | |
| * | |
| * @symver("foo@VERS_1") int foo_v1(); | |
| * --- | |
| */ | |
| auto symver(A...)(A arguments) | |
| if (allSatisfy!(isStringValue, arguments)) | |
| { | |
| return attribute("symver", arguments); | |
| } | |
| auto symver(A...)(A arguments) | |
| if (!allSatisfy!(isStringValue, arguments)) | |
| { | |
| assert(false, "symver attribute argument not a string constant"); | |
| } | |
| /** | |
| * The `@target` attribute is used to specify that a function is to be | |
| * compiled with different target options than specified on the command line. | |
| * One or more strings can be provided as arguments, separated by commas to | |
| * specify multiple options. Each string consists of one or more | |
| * comma-separated suffixes to the `-m` prefix jointly forming the name of a | |
| * machine-dependent option. | |
| * | |
| * The target attribute can be used for instance to have a function compiled | |
| * with a different ISA (instruction set architecture) than the default. | |
| * | |
| * The options supported are specific to each target. | |
| * | |
| * Example: | |
| * --- | |
| * import gcc.attributes; | |
| * | |
| * @target("arch=core2") void core2_func(); | |
| * @target("sse3") void sse3_func(); | |
| * --- | |
| */ | |
| auto target(A...)(A arguments) | |
| if (allSatisfy!(isStringValue, arguments)) | |
| { | |
| return attribute("target", arguments); | |
| } | |
| auto target(A...)(A arguments) | |
| if (!allSatisfy!(isStringValue, arguments)) | |
| { | |
| assert(false, "target attribute argument not a string constant"); | |
| } | |
| /** | |
| * The `@target_clones` attribute is used to specify that a function be cloned | |
| * into multiple versions compiled with different target `options` than | |
| * specified on the command line. The supported options and restrictions are | |
| * the same as for `@target` attribute. | |
| * | |
| * It also creates a resolver function that dynamically selects a clone suitable | |
| * for current architecture. The resolver is created only if there is a usage | |
| * of a function with `@target_clones` attribute. | |
| * | |
| * Example: | |
| * --- | |
| * import gcc.attributes; | |
| * | |
| * @target_clones("sse4.1,avx,default") double func(double x); | |
| * --- | |
| */ | |
| auto target_clones(A...)(A arguments) | |
| if (allSatisfy!(isStringValue, arguments)) | |
| { | |
| return attribute("target_clones", arguments); | |
| } | |
| auto target_clones(A...)(A arguments) | |
| if (!allSatisfy!(isStringValue, arguments)) | |
| { | |
| assert(false, "target attribute argument not a string constant"); | |
| } | |
| /** | |
| * The `@used` attribute, annotated to a function, means that code must be | |
| * emitted for the function even if it appears that the function is not | |
| * referenced. This is useful, for example, when the function is referenced | |
| * only in inline assembly. | |
| * | |
| * Example: | |
| * --- | |
| * import gcc.attributes; | |
| * | |
| * @used __gshared int var = 0x1000; | |
| * --- | |
| */ | |
| enum used = attribute("used"); | |
| /** | |
| * The `@visibility` attribute affects the linkage of the declaration to which | |
| * it is attached. It can be applied to variables, types, and functions. | |
| * | |
| * There are four supported visibility_type values: `default`, `hidden`, | |
| * `protected`, or `internal` visibility. | |
| * | |
| * Example: | |
| * --- | |
| * import gcc.attributes; | |
| * | |
| * @visibility("protected") void func() { } | |
| * --- | |
| */ | |
| auto visibility(string visibilityName) | |
| { | |
| return attribute("visibility", visibilityName); | |
| } | |
| auto visibility(A...)(A arguments) | |
| { | |
| assert(false, "visibility attribute argument not a string constant"); | |
| } | |
| /** | |
| * The `@weak` attribute causes a declaration of an external symbol to be | |
| * emitted as a weak symbol rather than a global. This is primarily useful in | |
| * defining library functions that can be overridden in user code, though it can | |
| * also be used with non-function declarations. The overriding symbol must have | |
| * the same type as the weak symbol. In addition, if it designates a variable | |
| * it must also have the same size and alignment as the weak symbol. | |
| * | |
| * Weak symbols are supported for ELF targets, and also for a.out targets when | |
| * using the GNU assembler and linker. | |
| * | |
| * Example: | |
| * --- | |
| * import gcc.attributes; | |
| * | |
| * @weak int func() { return 1; } | |
| * --- | |
| */ | |
| enum weak = attribute("weak"); | |
| /** | |
| * The `@noplt` attribute is the counterpart to option `-fno-plt`. Calls to | |
| * functions marked with this attribute in position-independent code do not use | |
| * the PLT in position-independent code. | |
| * | |
| * In position-dependant code, a few targets also convert call to functions | |
| * that are marked to not use the PLT to use the GOT instead. | |
| * | |
| * Example: | |
| * --- | |
| * import gcc.attributes; | |
| * | |
| * @noplt int func(); | |
| * | |
| * --- | |
| */ | |
| enum noplt = attribute("noplt"); | |
| /////////////////////////////////////////////////////////////////////////////// | |
| // | |
| // Attributes defined for compatibility with LDC. | |
| // | |
| /////////////////////////////////////////////////////////////////////////////// | |
| /** | |
| * Specifies that the function returns `null` or a pointer to at least a | |
| * certain number of allocated bytes. `sizeArgIdx` and `numArgIdx` specify | |
| * the 0-based index of the function arguments that should be used to calculate | |
| * the number of bytes returned. | |
| * | |
| * Example: | |
| * --- | |
| * import gcc.attributes; | |
| * | |
| * @allocSize(0) extern(C) void* malloc(size_t size); | |
| * @allocSize(2,1) extern(C) void* reallocarray(void *ptr, size_t nmemb, | |
| * size_t size); | |
| * @allocSize(0,1) void* my_calloc(size_t element_size, size_t count, | |
| * bool irrelevant); | |
| * --- | |
| */ | |
| auto allocSize(int sizeArgIdx, int numArgIdx = int.min) | |
| { | |
| return alloc_size(sizeArgIdx, numArgIdx, true); | |
| } | |
| auto allocSize(A...)(A arguments) | |
| { | |
| assert(false, "allocSize attribute argument value is not an integer constant"); | |
| } | |
| /** | |
| * When applied to a global symbol, the compiler, assembler, and linker are | |
| * required to treat the symbol as if there is a reference to the symbol that | |
| * it cannot see (which is why they have to be named). For example, it | |
| * prevents the deletion by the linker of an unreferenced symbol. | |
| * | |
| * Example: | |
| * --- | |
| * import gcc.attributes; | |
| * | |
| * @assumeUsed __gshared int var = 0x1000; | |
| * --- | |
| */ | |
| alias assumeUsed = used; | |
| /// This attribute has no effect. | |
| enum dynamicCompile = false; | |
| /// ditto | |
| enum dynamicCompileConst = false; | |
| /// ditto | |
| enum dynamicCompileEmit = false; | |
| /** | |
| * Explicitly sets "fast-math" for a function, enabling aggressive math | |
| * optimizations. These optimizations may dramatically change the outcome of | |
| * floating point calculations (e.g. because of reassociation). | |
| * | |
| * Example: | |
| * --- | |
| * import gcc.attributes; | |
| * | |
| * @fastmath | |
| * double dot(double[] a, double[] b) { | |
| * double s = 0; | |
| * foreach(size_t i; 0..a.length) | |
| * { | |
| * // will result in vectorized fused-multiply-add instructions | |
| * s += a * b; | |
| * } | |
| * return s; | |
| * } | |
| * --- | |
| */ | |
| enum fastmath = optimize("Ofast"); | |
| /** | |
| * Sets the visibility of a function or global variable to "hidden". | |
| * Such symbols aren't directly accessible from outside the DSO | |
| * (executable or DLL/.so/.dylib) and are resolved inside the DSO | |
| * during linking. If unreferenced within the DSO, the linker can | |
| * strip a hidden symbol. | |
| * An `export` visibility overrides this attribute. | |
| */ | |
| enum hidden = visibility("hidden"); | |
| /** | |
| * Adds GCC's "naked" attribute to a function, disabling function prologue / | |
| * epilogue emission. | |
| * Intended to be used in combination with basic `asm` statement. While using | |
| * extended `asm` or a mixture of basic `asm` and D code may appear to work, | |
| * they cannot be depended upon to work reliably and are not supported. | |
| * | |
| * Example: | |
| * --- | |
| * import gcc.attributes; | |
| * | |
| * @naked void abort() { | |
| * asm { "ud2"; } | |
| * } | |
| * --- | |
| */ | |
| enum naked = attribute("naked"); | |
| /** | |
| * Disables a particular sanitizer for this function. | |
| * Valid sanitizer names are all names accepted by `-fsanitize=` commandline option. | |
| * Multiple sanitizers can be disabled by applying this UDA multiple times, e.g. | |
| * `@noSanitize("address") `@noSanitize("thread")` to disable both ASan and TSan. | |
| */ | |
| alias noSanitize = no_sanitize; | |
| /** | |
| * Sets the optimization strategy for a function. | |
| * Valid strategies are "none", "optsize", "minsize". The strategies are | |
| * mutually exclusive. | |
| * | |
| * Example: | |
| * --- | |
| * import gcc.attributes; | |
| * | |
| * @optStrategy("none") | |
| * int func() { | |
| * return call(); | |
| * } | |
| * --- | |
| */ | |
| auto optStrategy(string strategy) | |
| { | |
| if (strategy == "none") | |
| return optimize("O0"); | |
| else if (strategy == "optsize" || strategy == "minsize") | |
| return optimize("Os"); | |
| else | |
| { | |
| assert(false, "unrecognized parameter `" ~ strategy | |
| ~ "` for `gcc.attribute.optStrategy`"); | |
| } | |
| } | |
| auto optStrategy(A...)(A arguments) | |
| { | |
| assert(false, "optStrategy attribute argument value is not a string constant"); | |
| } | |
| /** | |
| * When applied to a function, specifies that the function should be optimzed | |
| * by Graphite, GCC's polyhedral optimizer. Useful for optimizing loops for | |
| * data locality, vectorization and parallelism. | |
| * | |
| * Experimental! | |
| * | |
| * Only effective when GDC was built with ISL included. | |
| */ | |
| enum polly = optimize("loop-parallelize-all", "loop-nest-optimize"); |