Commit Graph

25 Commits

Author SHA1 Message Date
Tim Kientzle
1d961ba22d Add #include "swift/Basic/Assertions.h" to a lot of source files
Although I don't plan to bring over new assertions wholesale
into the current qualification branch, it's entirely possible
that various minor changes in main will use the new assertions;
having this basic support in the release branch will simplify that.
(This is why I'm adding the includes as a separate pass from
rewriting the individual assertions)
2024-06-05 19:37:30 -07:00
Erik Eckstein
e80fedc52a move CalleeCache from SILOptimizer to SIL
Extract the CalleeCache from BasicCalleeAnalysis so that it can be used in SIL without BasicCalleeAnalysis
2023-12-01 19:20:18 +01:00
Kuba Mracek
afced311f9 [embedded] Fix class_method devirtualizer to consider specialized VTables 2023-11-06 17:08:12 -08:00
Evan Wilde
309aed4925 Add SmallSetVector replacement
llvm::SmallSetVector changed semantics
(https://reviews.llvm.org/D152497) resulting in build failures in Swift.
The old semantics allowed usage of types that did not have an
`operator==` because `SmallDenseSet` uses `DenseSetInfo<T>::isEqual` to
determine equality. The new implementation switched to using
`std::find`, which internally uses `operator==`. This type is used
pretty frequently with `swift::Type`, which intentionally deletes
`operator==` as it is not the canonical type and therefore cannot be
compared in normal circumstances.

This patch adds a new type-alias to the Swift namespace that provides
the old semantic behavior for `SmallSetVector`. I've also gone through
and replaced usages of `llvm::SmallSetVector` with the
`Swift::SmallSetVector` in places where we're storing a type that
doesn't implement or explicitly deletes `operator==`. The changes to
`llvm::SmallSetVector` should improve compile-time performance, so I
left the `llvm::SmallSetVector` where possible.
2023-07-25 12:28:27 -07:00
Josh Soref
730b16c569 Spelling siloptimizer
* access
* accessed
* accesses
* accessor
* acquiring
* across
* activated
* additive
* address
* addresses'
* aggregated
* analysis
* and
* appropriately
* archetype
* argument
* associated
* availability
* barriers
* because
* been
* beginning
* belongs
* beneficial
* blocks
* borrow
* builtin
* cannot
* canonical
* canonicalize
* clazz
* cleanup
* coalesceable
* coalesced
* comparisons
* completely
* component
* computed
* concrete
* conjunction
* conservatively
* constituent
* construct
* consuming
* containing
* covered
* creates
* critical
* dataflow
* declaration
* defined
* defining
* definition
* deinitialization
* deliberately
* dependencies
* dependent
* deserialized
* destroy
* deterministic
* deterministically
* devirtualizes
* diagnostic
* diagnostics
* differentiation
* disable
* discipline
* dominate
* dominates
* don't
* element
* eliminate
* eliminating
* elimination
* embedded
* encounter
* epilogue
* epsilon
* escape
* escaping
* essential
* evaluating
* evaluation
* evaluator
* executing
* existential
* existentials
* explicit
* expression
* extended
* extension
* extract
* for
* from
* function
* generic
* guarantee
* guaranteed
* happened
* heuristic
* however
* identifiable
* immediately
* implementation
* improper
* include
* infinite
* initialize
* initialized
* initializer
* inside
* instruction
* interference
* interferes
* interleaved
* internal
* intersection
* intractable
* intrinsic
* invalidates
* irreducible
* irrelevant
* language
* lifetime
* literal
* looks
* materialize
* meaning
* mergeable
* might
* mimics
* modification
* modifies
* multiple
* mutating
* necessarily
* necessary
* needsmultiplecopies
* nonetheless
* nothing
* occurred
* occurs
* optimization
* optimizing
* original
* outside
* overflow
* overlapping
* overridden
* owned
* ownership
* parallel
* parameter
* paths
* patterns
* pipeline
* plottable
* possible
* potentially
* practically
* preamble
* precede
* preceding
* predecessor
* preferable
* preparation
* probably
* projection
* properties
* property
* protocol
* reabstraction
* reachable
* recognized
* recursive
* recursively
* redundant
* reentrancy
* referenced
* registry
* reinitialization
* reload
* represent
* requires
* response
* responsible
* retrieving
* returned
* returning
* returns
* rewriting
* rewritten
* sample
* scenarios
* scope
* should
* sideeffects
* similar
* simplify
* simplifycfg
* somewhat
* spaghetti
* specialization
* specializations
* specialized
* specially
* statistically
* substitute
* substitution
* succeeds
* successful
* successfully
* successor
* superfluous
* surprisingly
* suspension
* swift
* targeted
* that
* that our
* the
* therefore
* this
* those
* threshold
* through
* transform
* transformation
* truncated
* ultimate
* unchecked
* uninitialized
* unlikely
* unmanaged
* unoptimized key
* updataflow
* usefulness
* utilities
* villain
* whenever
* writes

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>
2022-10-03 18:31:33 -04:00
Erik Eckstein
777b42180d SILOptimizer: use the new set data structures in various optimizations 2022-07-13 14:27:50 +02:00
Erik Eckstein
3e1cc7e683 DiagnoseInfiniteRecursion: improve detection in (potentially) overridden class methods.
Even if a class method is (or could be) overridden, it's a recursive call if it's called on the self argument:

```
class X {
  // Even if foo() is overridden in a derived class, it'll end up in an
  // infinite recursion if initially called on an instance of `X`.
  func foo() { foo() }
}
```

rdar://89076581
2022-06-09 11:05:30 +02:00
Andrew Trick
2fd4de411e [SIL-opaque] Removed [Unconditional]CheckedCastValue 2022-03-22 17:04:13 -07:00
Erik Eckstein
6a020f8f15 Stabilize and simplify SIL linkage and serialization
The main point of this change is to make sure that a shared function always has a body: both, in the optimizer pipeline and in the swiftmodule file.
This is important because the compiler always needs to emit code for a shared function. Shared functions cannot be referenced from outside the module.
In several corner cases we missed to maintain this invariant which resulted in unresolved-symbol linker errors.

As side-effect of this change we can drop the shared_external SIL linkage and the IsSerializable flag, which simplifies the serialization and linkage concept.
2022-03-09 15:28:05 +01:00
Erik Eckstein
14e7e4a855 DiagnoseInfiniteRecursion: fix a false warning caused by dead-end blocks
The algorithm needs to take care of dead-end blocks.
This is done by propagating two flags instead of one: `reachesRecursiveCall` and `reachesFunctionExit`.
Dead-end blocks have none of both flags set.

rdar://80645083
2021-08-17 16:48:07 +02:00
Erik Eckstein
2ef06dbefc DiagnoseInfiniteRecursion: correctly handle multi-result instructions when checking for invariant arguments.
Use `getDefiningInstruction` instead of casting a a SILValue to SingleValueInstruction.
2021-01-27 16:40:14 +01:00
Eric Miotto
8e7f9c9cbd Revert "SIL: let SingleValueInstruction only inherit from a single SILNode." 2021-01-26 10:02:24 -08:00
Erik Eckstein
ee599d84d2 DiagnoseInfiniteRecursion: correctly handle multi-result instructions when checking for invariant arguments.
Use `getDefiningInstruction` instead of casting a a SILValue to SingleValueInstruction.
2021-01-25 09:30:04 +01:00
Erik Eckstein
0287a1ec94 SILOptimizer: Use BasicBlockData in the InfiniteRecursionAnalysis 2021-01-20 16:09:01 +01:00
Erik Eckstein
d824fd3440 DiagnoseInfiniteRecursion: handle invariant conditions and improve the warning message
The main change is to detect infinite recursive calls under invariant conditions. For example:

  func f() {
    if #available(macOS 10.4.4, *) {
      f()
    }
  }

or invariant conditions due to forwarded arguments:

  func f(_ x: Int) {
    if x > 0 {
      f(x)
    }
  }

Also, improve the warning message. Instead of giving a warning at the function location

  warning: all paths through this function will call itself

give a warning at the call location:

  warning: function call causes an infinite recursion

Especially in case of multiple recursive calls, it makes it easier to locate the problem.

https://bugs.swift.org/browse/SR-11842
rdar://57460599
2021-01-13 14:35:03 +01:00
Erik Eckstein
5e374b6f1e DiagnoseInfiniteRecursion: refactoring, NFC
Extract isRecursiveCall() into a separate function.
2021-01-13 13:23:15 +01:00
Erik Eckstein
7cec26ca85 DiagnoseInfiniteRecursion: handle throwing functions.
Means: handle try_apply

https://bugs.swift.org/browse/SR-13568
rdar://69235604
2021-01-13 13:23:15 +01:00
Robert Widmann
baa45a1167 [Gardening] Pull Out Callee Variable 2020-10-17 16:17:14 -07:00
Robert Widmann
f730ff1d54 Disregard Overridden Candidates in Infinite Recursion Check
Disregard candidates that have known override points because those
points are possible targets for dynamic dispatch. This removes a class
of false positives involving classes with known override points in
the module, as is this case in many node-based data structures.

rdar://70410948
2020-10-17 16:15:27 -07:00
Slava Pestov
112d1bd561 SILOptimizer: Small cleanups for devirtualizer
Where possible, pass around a ClassDecl or a CanType instead of a
SILType that might wrap a metatype; the unwrapping logic was
repeated in several places.

Also add a FIXME for a bug I found by inspection.
2019-02-28 22:40:54 -05:00
Harlan
00cc011621 [SILOptimizer] Don't diagnose infinite recursion if a branch terminates the program (#19781)
* [SILOptimizer] Don't diagnose infinite recursion if a branch terminates the program

This patch augments the infinite recursion checker to not warn if a
branch terminates, but still warns if a branch calls into something with
@_semantics("programtermination_point"). This way, calling fatalError
doesn't disqualify you for the diagnostic, but calling exit does.

This also removes the warning workaround in the standard library, and
annotates the internal _assertionFailure functions as
programtermination_points, so they get this treatment too.

* Fix formatting in SILInstructions.cpp

* Re-add missing test
2018-10-09 09:46:37 -07:00
Graydon Hoare
cc16ddfd13 Revert "[SILOptimizer] Don't diagnose infinite recursion if a branch terminates (#19724)"
This reverts commit e94450e840.

rdar://45080912
2018-10-07 23:54:33 -07:00
Harlan
e94450e840 [SILOptimizer] Don't diagnose infinite recursion if a branch terminates (#19724)
This patch augments the infinite recursion checker to not warn if a
branch terminates, but still warns if a branch calls into something with
`@_semantics("arc.programtermination_point")`. This way, calling `fatalError`
doesn't disqualify you for the diagnostic, but calling `exit` does.

This also removes the warning workaround in the standard library, and
annotates the internal _assertionFailure functions as
`programtermination_point`s, so they get this treatment too.
2018-10-05 19:15:26 -07:00
Harlan
b08a3b772e [SILOptimizer] Clean up infinite recursion diagnostic pass (#19710)
* [SILOptimizer] Clean up infinite recursion diagnostic pass

NFC. This cleans up the pass to avoid the extra lambda and to clear up
the ordering of what check is supposed to come before what.

* Address review comments
2018-10-04 15:10:01 -07:00
Robert Widmann
5c7b79072b Detect and diagnose infinitely-recursive code
Add a new warning that detects when a function will call itself
recursively on all code paths.  Attempts to invoke functions like this
may cause unbounded stack growth at least or undefined behavior in the
worst cases.

The detection code is implemented as DFS for a reachable exit path in
a given SILFunction.
2018-02-26 16:27:32 -05:00