Preparation to fix <rdar://problem/18151694> Add Builtin.checkUnique
to avoid lost Array copies.
This adds the following new builtins:
isUnique : <T> (inout T[?]) -> Int1
isUniqueOrPinned : <T> (inout T[?]) -> Int1
These builtins take an inout object reference and return a
boolean. Passing the reference inout forces the optimizer to preserve
a retain distinct from what’s required to maintain lifetime for any of
the reference's source-level copies, because the called function is
allowed to replace the reference, thereby releasing the referent.
Before this change, the API entry points for uniqueness checking
already took an inout reference. However, after full inlining, it was
possible for two source-level variables that reference the same object
to appear to be the same variable from the optimizer's perspective
because an address to the variable was longer taken at the point of
checking uniqueness. Consequently the optimizer could remove
"redundant" copies which were actually needed to implement
copy-on-write semantics. With a builtin, the variable whose reference
is being checked for uniqueness appears mutable at the level of an
individual SIL instruction.
The kind of reference count checking that Builtin.isUnique performs
depends on the argument type:
- Native object types are directly checked by reading the
strong reference count:
(Builtin.NativeObject, known native class reference)
- Objective-C object types require an additional check that the
dynamic object type uses native swift reference counting:
(Builtin.UnknownObject, unknown class reference, class existential)
- Bridged object types allow the dymanic object type check to be
bypassed based on the pointer encoding:
(Builtin.BridgeObject)
Any of the above types may also be wrapped in an optional. If the
static argument type is optional, then a null check is also performed.
Thus, isUnique only returns true for non-null, native swift object
references with a strong reference count of one.
isUniqueOrPinned has the same semantics as isUnique except that it
also returns true if the object is marked pinned regardless of the
reference count. This allows for simultaneous non-structural
modification of multiple subobjects.
In some cases, the standard library can dynamically determine that it
has a native reference even though the static type is a bridge or
unknown object. Unsafe variants of the builtin are available to allow
the additional pointer bit mask and dynamic class lookup to be
bypassed in these cases:
isUnique_native : <T> (inout T[?]) -> Int1
isUniqueOrPinned_native : <T> (inout T[?]) -> Int1
These builtins perform an implicit cast to NativeObject before
checking uniqueness. There’s no way at SIL level to cast the address
of a reference, so we need to encapsulate this operation as part of
the builtin.
Swift SVN r27887
Calls to willThrow are marked as read-none so that the optimizer can remove
them. The willThrow builtin is still generated for all throw/rethrow sites,
but I plan to look at this next.
rdar://20356658
Swift SVN r27877
Using the intrinsics is obnoxious because I needed them
to return Builtin.NativeObject?, but there's no reasonable
way to safely generate optional types from Builtins.cpp.
Ugh.
Dave and I also decided that there's no need for
swift_tryPin to allow a null object.
Swift SVN r23824
If an imported C struct has no __nonnull pointer fields, then we can give a default initializer that zeroes all of its fields. This becomes a requirement when working with partially-imported types like NSDecimal. NSDecimal has bitfields Swift can't see yet, so it's impossible to DI, but the Foundation functions that work with NSDecimal all emit their result by out parameter, and without access to its fields it is impossible to initialize an NSDecimal for use with one of these functions. Implement the initializer using a builtin that gets lowered by IRGen; this is also made necessary by the fact that Swift has only a partial view of the struct, so we can't form a complete zero initializer until we have the definitive type layout from Clang.
Swift SVN r23727
It returns the argument and specifies that the value is not negative.
It has only an effect if the argument is a load or call.
The effect of this builtin is that for the load/call argument a positive range metadata is created in llvm ir.
I also added a public function _assumeNonNegative(x: Int) -> Int in the stdlib.
To be on the save side, I prefixed it with an underscore. But maybe it makes sense to make it available for all users.
Swift SVN r23582
CmpXChg builtins now return (T, Bool) to match the LLVM return value.
Turn the tests back on and check extractvalue / inttoptr instructions.
<rdar://problem/17309776> Update modeling of cmpxchg builtin to handle weak-ness and separate success bit
Swift SVN r23104
This is a type that has ownership of a reference while allowing access to the
spare bits inside the pointer, but which can also safely hold an ObjC tagged pointer
reference (with no spare bits of course). It additionally blesses one
Foundation-coordinated bit with the meaning of "has swift refcounting" in order
to get a faster short-circuit to native refcounting. It supports the following
builtin operations:
- Builtin.castToBridgeObject<T>(ref: T, bits: Builtin.Word) ->
Builtin.BridgeObject
Creates a BridgeObject that contains the bitwise-OR of the bit patterns of
"ref" and "bits". It is the user's responsibility to ensure "bits" doesn't
interfere with the reference identity of the resulting value. In other words,
it is undefined behavior unless:
castReferenceFromBridgeObject(castToBridgeObject(ref, bits)) === ref
This means "bits" must be zero if "ref" is a tagged pointer. If "ref" is a real
object pointer, "bits" must not have any non-spare bits set (unless they're
already set in the pointer value). The native discriminator bit may only be set
if the object is Swift-refcounted.
- Builtin.castReferenceFromBridgeObject<T>(bo: Builtin.BridgeObject) -> T
Extracts the reference from a BridgeObject.
- Builtin.castBitPatternFromBridgeObject(bo: Builtin.BridgeObject) -> Builtin.Word
Presents the bit pattern of a BridgeObject as a Word.
BridgeObject's bits are set up as follows on the various platforms:
i386, armv7:
No ObjC tagged pointers
Swift native refcounting flag bit: 0x0000_0001
Other available spare bits: 0x0000_0002
x86_64:
Reserved for ObjC tagged pointers: 0x8000_0000_0000_0001
Swift native refcounting flag bit: 0x0000_0000_0000_0002
Other available spare bits: 0x7F00_0000_0000_0004
arm64:
Reserved for ObjC tagged pointers: 0x8000_0000_0000_0000
Swift native refcounting flag bit: 0x4000_0000_0000_0000
Other available spare bits: 0x3F00_0000_0000_0007
TODO: BridgeObject doesn't present any extra inhabitants. It ought to at least provide null as an extra inhabitant for Optional.
Swift SVN r22880
Replace the true/maybe state that Builtin.canBeClass was returning by a
tri-state (yes, no, maybe) allowing the optimizer to use the definite no
answer. This removes the need of the sizeof check that we had in
isClassOrObjCExistential. It also removes the need to CSE this function since
in most cases we will be able to instantiate canBeClass to yes or no (vs maybe)
at compile time.
benchmark``````````````,``baserun0``,``optrun2``,``delta,``speedup
ClassArrayGetter```````,``988.00````,``337.00```,``644.00``,````````191.7%
DeltaBlue``````````````,``2429.00```,``1927.00``,``460.00``,````````23.9%
Dictionary`````````````,``1374.00```,``1231.00``,``129.00``,````````10.9%
Havlak`````````````````,``1079.00```,``911.00```,``124.00``,````````13.7%
Rectangles`````````````,``924.00````,``541.00```,``379.00``,````````70.1%
radar://16823238
Swift SVN r21331
- Change the parser to accept "objc" without an @ sign as a contextual
keyword, including the dance to handle the general parenthesized case.
- Update all comments to refer to "objc" instead of "@objc".
- Update all diagnostics accordingly.
- Update all tests that fail due to the diagnostics change.
- Switch the stdlib to use the new syntax.
This does not switch all tests to use the new syntax, nor does it warn about
the old syntax yet. That will be forthcoming. Also, this needs a bit of
refactoring, which will be coming up.
Swift SVN r19555
SILGen lowers this to unchecked_trivial_bit_cast or unchecked_ref_bit_cast based on the semantics of the input and output types, raising an unsupported error if one of the types are address-only.
Swift SVN r19058
This builtin only becomes unreachable when assert_configuration calls have been folded, allowing library-level checks to become unreachable based on the assert level.
Swift SVN r17322
Add Builtin.destroyArray, .copyArray, .takeArrayFrontToBack, and .takeArrayBackToFront, which perform bulk destroy/copy/take operations using memcpy/memmove, a loop, or a generic value witness.
Swift SVN r17009
This will allow stdlib code to explicitly mark branches it knows to be unreachable. Make this work with SIL diagnostics by lowering the builtin to a normal builtin_function_ref/apply in SILGen, and special-case handling the builtin in DCE by removing the apply along with the following dead instructions when we recognize an unreachable block.
Swift SVN r16745
This patch adds support for a builtin function assert_configuration that is
replaced by constant progpagation by an appropriate value dependent on a compile
time setting. This replacement can also be disabled when serializing sil for a
library.
Using this mechanism we implement assertions that can be disabled (or whose
behavior changes) depending on compile time build settings (Debug, Release,
DisableReplacement).
In the standard library we can now write one assert function that uses this
builtin function to provide different compile time selectable runtime behavior.
Example
Assert.swift:
@transparent
func assert<T : LogicValue>(
condition: @auto_closure () -> T, message: StaticString = StaticString(),
// Do not supply these parameters explicitly; they will be filled in
// by the compiler and aren't even present when asserts are disabled
file: StaticString = __FILE__, line: UWord = __LINE__
) {
// Only in debug mode.
if _isDebug() {
assert(condition().getLogicValue(), message, file, line)
}
}
AssertCommon.swift:
@transparent
func _isDebug() -> Bool {
return Int32(Builtin.assert_configuration()) == 0;
}
rdar://16458612
Swift SVN r16472
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
In the long term we want more detailed configurability of runtime checks, but for our short-term performance work we just want a blanket on/off switch. Add a StripRuntimeChecks SIL pass that, as a start, converts invocations of checked overflow builtins to the equivalent unchecked builtins and kills cond_fails. Expose it through the compiler with a -disable-all-runtime-checks switch.
NB: I haven't tested building the stdlib or running the tests with the switch thrown yet.
Swift SVN r12379
This lowers to a call to a to-be-written swift_once runtime function and will be used for lazy global initialization. Having this be a builtin seemed appropriate to me given that:
- references to it will be implicitly emitted by SILGen for global initializers.
- there are restrictions on its correct use that are currently impossible to express in the language outside of the stdlib.
Swift SVN r10508
Add new builtins(by generalizing, renaming, and extending the builtins used for compile time integer literal checking). These new builtins truncate integers and check for overflow/truncation errors at runtime. Use these for FixedPoint conversion constructors.
Fix a routine in stdlib's String implementation and a test that relied on bitwise behavior of the constructors (and triggered overflows).
TODO:
- Teach CCP about these to get static checking.
- Add special builtins for same size signed <-> unsigned conversions.
Swift SVN r10432
(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
- Added 2 new builtins strunc_with_overflow and utrunc_with_overflow
that perform truncation and produce a compile time error when truncation
overflows.
- Used these builtins instead of trunc to implement "_convertFromBuiltinIntegerLiteral".
- Currently, the builtins are converted to trunc in IRGen, but we should
not be IRGenning code that uses them, since all uses of
"_convertFromBuiltinIntegerLiteral" should be inlined and the arguments
constant folded.
- I had to change a test and the implementation of operator '~' in the standard library
because they assumed that '0xFF' is a valid signed Int8. It is questionable if we should
allow this and if we should treat signed and unsigned integers differently depending on
how they are spelled (decimal or hexadecimal).
* This patch will be further improved (Ex: will start finding overflows on Int64, better
deal with '-128' after the negative integer literal patch is committed.)
Swift SVN r9226
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
- Introduces the Builtin
- If the first parameter evaluates to '1', the dataflow diagnostics pass produces a diagnostic.
- The Builtin gets cleaned up before IRGen, but not before SIL serialization.
This patch also removes the current, overflow warning and XFAILs one of the tests. The other test is switched to use Builtin.staticReport.
TODO:
- Utilize the other parameters to the builtin - the Message and IsError flag.
- Use this Builtin within the stdlib.
Swift SVN r8939