In their previous form, the non-`_f` variants of these entry points were unused, and IRGen
lowered the `createAsyncTask` builtins to use the `_f` variants with a large amount of caller-side
codegen to manually unpack closure values. Amid all this, it also failed to make anyone responsible
for releasing the closure context after the task completed, causing every task creation to leak.
Redo the `swift_task_create_*` entry points to accept the two words of an async closure value
directly, and unpack the closure to get its invocation entry point and initial context size
inside the runtime. (Also get rid of the non-future `swift_task_create` variant, since it's unused
and it's subtly different in a lot of hairy ways from the future forms. Better to add it later
when it's needed than to have a broken unexercised version now.)
`Builtin.createAsyncTask` takes flags, an optional parent task, and an
async/throwing function to execute, and passes it along to the
`swift_task_create_f` entry point to create a new (potentially child)
task, returning the new task and its initial context.
Add a private scratch context to the ASTContext and allow IntrinsicInfo sole access to it so it can allocate attributes into it. This removes the final dependency on the global context.
This will ensure that if an expert user is using this feature and makes a
mistake as a result of tweaking their code, they get an error. This will ensure
they do not ship and look into why this is happening.
This is not intended to be used by anyone except for expert stdlib users.
TLDR: This patch introduces a new kind of builtin, "a polymorphic builtin". One
calls it like any other builtin, e.x.:
```
Builtin.generic_add(x, y)
```
but it has a contract: it must be specialized to a concrete builtin by the time
we hit Lowered SIL. In this commit, I add support for the following generic
operations:
Type | Op
------------------------
FloatOrVector |FAdd
FloatOrVector |FDiv
FloatOrVector |FMul
FloatOrVector |FRem
FloatOrVector |FSub
IntegerOrVector|AShr
IntegerOrVector|Add
IntegerOrVector|And
IntegerOrVector|ExactSDiv
IntegerOrVector|ExactUDiv
IntegerOrVector|LShr
IntegerOrVector|Mul
IntegerOrVector|Or
IntegerOrVector|SDiv
IntegerOrVector|SRem
IntegerOrVector|Shl
IntegerOrVector|Sub
IntegerOrVector|UDiv
IntegerOrVector|Xor
Integer |URem
NOTE: I only implemented support for the builtins in SIL and in SILGen. I am
going to implement the optimizer parts of this in a separate series of commits.
DISCUSSION
----------
Today there are polymorphic like instructions in LLVM-IR. Yet, at the
swift and SIL level we represent these operations instead as Builtins whose
names are resolved by splatting the builtin into the name. For example, adding
two things in LLVM:
```
%2 = add i64 %0, %1
%2 = add <2 x i64> %0, %1
%2 = add <4 x i64> %0, %1
%2 = add <8 x i64> %0, %1
```
Each of the add operations are done by the same polymorphic instruction. In
constrast, we splat out these Builtins in swift today, i.e.:
```
let x, y: Builtin.Int32
Builtin.add_Int32(x, y)
let x, y: Builtin.Vec4xInt32
Builtin.add_Vec4xInt32(x, y)
...
```
In SIL, we translate these verbatim and then IRGen just lowers them to the
appropriate polymorphic instruction. Beyond being verbose, these prevent these
Builtins (which need static types) from being used in polymorphic contexts where
we can guarantee that eventually a static type will be provided.
In contrast, the polymorphic builtins introduced in this commit can be passed
any type, with the proviso that the expert user using this feature can guarantee
that before we reach Lowered SIL, the generic_add has been eliminated. This is
enforced by IRGen asserting if passed such a builtin and by the SILVerifier
checking that the underlying builtin is never called once the module is in
Lowered SIL.
In forthcoming commits, I am going to add two optimizations that give the stdlib
tool writer the tools needed to use this builtin:
1. I am going to add an optimization to constant propagation that changes a
"generic_*" op to the type of its argument if the argument is a type that is
valid for the builtin (i.e. integer or vector).
2. I am going to teach the SILCloner how to specialize these as it inlines. This
ensures that when we transparent inline, we specialize the builtin automatically
and can then form SSA at -Onone using predictable memory access operations.
The main implication around these polymorphic builtins are that if an author is
not able to specialize the builtin, they need to ensure that after constant
propagation, the generic builtin has been DCEed. The general rules are that the
-Onone optimizer will constant fold branches with constant integer operands. So
if one can use a bool of some sort to trigger the operation, one can be
guaranteed that the code will not codegen. I am considering putting in some sort
of diagnostic to ensure that the stdlib writer has a good experience (e.x. get
an error instead of crashing the compiler).
I am going to use this to refactor some code in ASTPrinter onto BuiltinType
wherein I use an exhaustive switch to print things as appropriate. Exhaustive
switching over all builtin types just seems like a useful thing to have as well.
We've been running doxygen with the autobrief option for a couple of
years now. This makes the \brief markers into our comments
redundant. Since they are a visual distraction and we don't want to
encourage more \brief markers in new code either, this patch removes
them all.
Patch produced by
for i in $(git grep -l '\\brief'); do perl -pi -e 's/\\brief //g' $i & done
Looking these up is slow because the attribute lists get rebuilt and
reuniqued in the LLVM context each time. Saving them is a single
pointer per IntrinsicInfo and IntrinsicInfos are already cached in
each SILModule.
This shaves about 4s off optimizing the standard library (72s out of a
3:00+ build), and probably has much less effect anywhere else. That
is, it's not /really/ important after all, but it was an easy bit of
the profile to hammer down.
The introduction of `llvm.memcpy.element.atomic` would cause an
ambiguity when we did the lookup with the trailing `.` for the type
parameters. The intrinsic itself is not necessarily suffixed with the
type in the identifier. Look up the identifier by explicit name.
This builtin returns true for types that might be ObjC class types. We want to use this builtin to optimize away NSArray handling for non-object Array types, so it needs to persist in SIL long enough for specialization to do its thing, but we never actually want to pay a runtime cost for this check, so always lower it to a constant value at IRGen time. Handle this by having canBeObjCClass return a tri-state "yes/maybe/no" result. In SILGen, we only fold away obviously "yes" or "no" cases, and in IRGen, we fold away "maybe" cases as "yes".
The optimizer will need to learn about this builtin too, but that part isn't done yet.
Swift SVN r13980
(This only fails under -DSWIFT_OPTIMIZED=NO; most likely due to an llvm bug.)
We've decided that it's best to specialize each arithmetic builtin that could overflow, instead of calling a separate generic "staticReport" builtin and passing it enough info to produce the message. The main advantage of this approach is that it would be possible for the compiler to customize the message and better link it to the builtin that overflows. For example, the constants that participated in the computation could be printed. In addition, less code will be generated and the compiler could, in the future, automatically emit the overflow diagnostics/trap at runtime.
This patch introduces new versions of op_with_overflow swift builtins. Which are lowered to llvm.op_with_overflow builtins in IRGen after the static diagnostics. If the last argument to the builtins evaluates to true, the overflow is unintentional. CCP uses the builtins to diagnose the overflow detectable at compile time. FixedPoint is changed to rely on these in implementation of primitive arithmetic operations.
Swift SVN r9328
This was causing massive failures at run-time.
This reverts commit 80081db973ccb7100741fea19ce8e8c116fc410f.
Conflicts:
lib/SILPasses/ConstantPropagation.cpp
test/SILPasses/constant_propagation.swift
test/SILPasses/constant_propagation2.sil
Swift SVN r9050
After talking to John, Joe, and Dave Z, we've decided that it's best to
specialize each arithmetic builtin that could overflow, instead of calling
a separate generic "staticReport" builtin and passing it enough info to
produce the message. The main advantage of this approach is that it
would be possible for the compiler to customize the message and better
link it to the builtin that overflows. For example, the constants that
participated in the computation could be printed. In addition, less code
will be generated and the compiler could, in the future, automatically
emit the overflow diagnostics/trap at runtime.
This patch introduces new versions of op_with_overflow swift builtins.
Which are lowered to llvm.op_with_overflow builtins in IRGen after the
static diagnostics. If the last argument to the builtins evaluates to true,
the overflow is unintentional. CCP uses the builtins to diagnose the overflow
detectable at compile time. FixedPoint is changed to rely on these in
implementation of primitive arithmetic operations.
Swift SVN r9034
And use them to decide if an llvm intrinsic apply instruction can be considered dead.
(This is a hack because it uses LLVM Global context. However, we already use
this approach elsewhere.)
Swift SVN r7404
Make the functions support a wider range of builtins and store types to make
it possible.
This is an optimization - the cached ID will be used for builtin identification,
instead of retrieval of the string name and using it as the key.
Swift SVN r7390
This adds builtin types Builtin.VecNxT, where N is a natural number
and T is a builtin type, which map down to the LLVM type <N x T>.
Update varous builtins to support vector arguments, e.g., binary
operations, comparisons, negation. Add InsertElement and
ExtractElement builtins for vectors.
On top of these builtins, add Vec4f and Vec4b structs to the standard
library, which provide 4xFloat and 4xBool vectors, respectively, with
basic support for arithmetic. These are mostly straw men, to be burned
down at our leisure.
Some issues as yet unresolved:
- Comparisons of Vec4f'ss are producing bogus Vec4b's, which I
haven't tracked down yet.
- We still don't support the shuffle builtin, although it should be
easy
- More testing!
Swift SVN r5820
allows access to any LLVM IR intrinsic that has types that can be mapped
to swift types. Notably, this excludes vector stuff, but there is a lot
of other goodness that can now be poked at.
Swift SVN r1890