Skip to content

Commit c354f90

Browse files
committed
[Performance diagnostics] Enable checking of throw instructions
When performance diagnostics were introduced, typed throws didn't exist so it was not generally possible to have throws anywhere without triggering performance diagnostics. As a short term hack, we disabled checking of `throw` instructions and the basic blocks that terminate in a `throw`. Now that typed throws is available and can be used to eliminate allocations with error handling, remove all of the hacks. We'll now diagnose attempts to throw or catch existential values (e.g., the `any Error` used for untyped throws), but typed throws are fine.
1 parent 9655803 commit c354f90

File tree

2 files changed

+12
-18
lines changed

2 files changed

+12
-18
lines changed

lib/SILOptimizer/Mandatory/PerformanceDiagnostics.cpp

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -290,21 +290,6 @@ bool PerformanceDiagnostics::visitFunction(SILFunction *function,
290290
if (isa<UnreachableInst>(block.getTerminator()))
291291
continue;
292292

293-
// TODO: it's not yet clear how to deal with error existentials.
294-
// Ignore them for now. If we have typed throws we could ban error existentials
295-
// because typed throws would provide and alternative.
296-
if (isa<ThrowInst>(block.getTerminator()))
297-
continue;
298-
299-
// If a function has multiple throws, all throw-path branch to the single throw-block.
300-
if (SILBasicBlock *succ = block.getSingleSuccessorBlock()) {
301-
if (isa<ThrowInst>(succ->getTerminator()))
302-
continue;
303-
}
304-
305-
if (!neBlocks.isNonErrorHandling(&block))
306-
continue;
307-
308293
for (SILInstruction &inst : block) {
309294
if (visitInst(&inst, perfConstr, parentLoc)) {
310295
if (inst.getLoc().getSourceLoc().isInvalid()) {

test/SILOptimizer/performance-annotations.swift

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,13 +101,22 @@ func errorExistential(_ b: Bool) throws -> Int {
101101
if b {
102102
return 28
103103
}
104-
throw MyError()
104+
throw MyError() // expected-error{{Using type 'MyError' can cause metadata allocation or locks}}
105+
}
106+
107+
@_noLocks
108+
func concreteThrowsExistential(_ b: Bool) throws -> Int {
109+
if b {
110+
return 28
111+
}
112+
113+
throw ErrorEnum.tryAgain // expected-error{{Using type 'any Error' can cause metadata allocation or locks}}
105114
}
106115

107116
@_noLocks
108117
func multipleThrows(_ b1: Bool, _ b2: Bool) throws -> Int {
109118
if b1 {
110-
throw MyError()
119+
throw MyError() // expected-error{{Using type 'MyError' can cause metadata allocation or locks}}
111120
}
112121
if b2 {
113122
throw MyError2()
@@ -119,7 +128,7 @@ func multipleThrows(_ b1: Bool, _ b2: Bool) throws -> Int {
119128
func testCatch(_ b: Bool) throws -> Int? {
120129
do {
121130
return try errorExistential(true)
122-
} catch let e as MyError {
131+
} catch let e as MyError { // expected-error{{this code performs reference counting operations which can cause locking}}
123132
print(e)
124133
return nil
125134
}

0 commit comments

Comments
 (0)