1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
/**********************************************
To provide access to features that would be otherwise counterproductive or
difficult to implement, compilers provide an interface consisting of a set
of builtins (also called intrinsics) which can be called like normal functions.
This module exposes builtins both common to all D compilers
(those provided by the frontend) and specific to the host compiler i.e. those
specific to either LLVM or GCC (`ldc.intrinsics` and `gcc.builtins` are publicly imported, respectively).
Host-specific intrinsics cannot be reliably listed here, however listings can be found
at the documentation for the relevant backends, i.e.
$(LINK2 https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html, GCC) and
$(LINK2 https://llvm.org/docs/LangRef.html, LLVM). It should be noted that not all
builtins listed are necessarily supported by the host compiler, please file a bug
if this is the case for your workload.
Use of this module reduces the amount of conditional compilation needed
to use a given builtin. For example, to write a target independent function
that uses prefetching we can write the following:
---
float usePrefetch(float[] x)
{
// There is only one import statement required rather than two (versioned) imports
import core.builtins;
version (GNU)
__builtin_prefetch(x.ptr);
version (LDC)
/+
For the curious: 0, 3, 1 mean `x` will only be read-from (0), it will be used
very often (3), and it should be fetched to the data-cache (1).
+/
llvm_prefetch(x.ptr, 0, 3, 1);
const doMath = blahBlahBlah;
return doMath;
}
---
Copyright: Copyright © 2021, The D Language Foundation
License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
Authors: Walter Bright
Source: $(DRUNTIMESRC core/builtins.d)
*/
module core.builtins;
version (GNU)
public import gcc.builtins;
version (LDC)
public import ldc.intrinsics;
/// Writes `s` to `stderr` during CTFE (does nothing at runtime).
void __ctfeWrite(scope const(char)[] s) @nogc @safe pure nothrow {}
version (GNU)
{
/// https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html#index-_005f_005fbuiltin_005fexpect
alias expect = __builtin_expect;
/// https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html#index-_005f_005fbuiltin_005ftrap
alias trap = __builtin_trap;
}
else version (LDC)
{
/// https://llvm.org/docs/LangRef.html#llvm-expect-intrinsic
alias expect = llvm_expect;
debug
/// https://llvm.org/docs/LangRef.html#llvm-debugtrap-intrinsic
alias trap = llvm_debugtrap;
else
/// https://llvm.org/docs/LangRef.html#llvm-trap-intrinsic
alias trap = llvm_trap;
}
else version (DigitalMars)
{
pragma(inline, true)
T expect(T)(T val, T expected) if (__traits(isIntegral, T))
{
return val;
}
/// Execute target dependent trap instruction, if supported.
/// Otherwise, abort execution.
pragma(inline, true)
void trap()
{
debug
{
version(D_InlineAsm_X86)
asm nothrow @nogc pure @trusted { int 3; }
}
assert(0);
}
}
/// Provide static branch and value hints for the LDC/GDC compilers.
/// DMD ignores these hints.
pragma(inline, true) bool likely()(bool b) { return !!expect(b, true); }
/// ditto
pragma(inline, true) bool unlikely()(bool b) { return !!expect(b, false); }
///
@nogc nothrow pure @safe unittest
{
int x = 12;
expect(x, 12);
if (likely(x > 0))
{
// ...
}
else if (unlikely(x == int.min))
{
// ...
}
}
|