From d4730e02ce218d8ac16491e913a46d4acc299a77 Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Tue, 9 Jan 2024 13:50:29 +0100 Subject: [PATCH 1/2] stdlib: add a semantic attribute to `Bool.init(_builtinBooleanLiteral:)` This is required for being able to constant fold boolean literals before the DefiniteInitialization pass --- stdlib/public/core/Bool.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/stdlib/public/core/Bool.swift b/stdlib/public/core/Bool.swift index 13b32b4297842..67d3b9364370d 100644 --- a/stdlib/public/core/Bool.swift +++ b/stdlib/public/core/Bool.swift @@ -143,6 +143,7 @@ public struct Bool: Sendable { extension Bool: _ExpressibleByBuiltinBooleanLiteral, ExpressibleByBooleanLiteral { @_transparent + @_semantics("bool.literal_init") public init(_builtinBooleanLiteral value: Builtin.Int1) { self._value = value } From c89df9ec985244ff5109b0a7852c086e39d8e5eb Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Tue, 9 Jan 2024 13:53:03 +0100 Subject: [PATCH 2/2] Mandatory optimizations: constant fold boolean literals before the DefiniteInitialization pass Add a new mandatory BooleanLiteralFolding pass which constant folds conditional branches with boolean literals as operands. ``` %1 = integer_literal -1 %2 = apply %bool_init(%1) // Bool.init(_builtinBooleanLiteral:) %3 = struct_extract %2, #Bool._value cond_br %3, bb1, bb2 ``` -> ``` ... br bb1 ``` This pass is intended to run before DefiniteInitialization, where mandatory inlining and constant folding didn't run, yet (which would perform this kind of optimization). This optimization is required to let DefiniteInitialization handle boolean literals correctly. For example in infinite loops: ``` init() { while true { // DI need to know that there is no loop exit from this while-statement if some_condition { member_field = init_value break } } } ``` --- .../BooleanLiteralFolding.swift | 70 +++++++++ .../Optimizer/FunctionPasses/CMakeLists.txt | 1 + .../PassManager/PassRegistration.swift | 1 + .../swift/SILOptimizer/PassManager/Passes.def | 2 + lib/SILOptimizer/PassManager/PassPipeline.cpp | 1 + .../SILOptimizer/activity_analysis.swift | 3 +- ...8660-conflicting-debug-info-inlining.swift | 3 +- ...mutating-functions-with-control-flow.swift | 3 +- .../address_only_tangentvector.swift | 3 +- .../validation-test/control_flow.swift | 22 +-- .../Inputs/syntax_macro_definitions.swift | 2 +- test/Macros/macro_expand_codeitems.swift | 2 - test/SILGen/availability_query.swift | 6 +- test/SILOptimizer/boolean-literal-folding.sil | 136 ++++++++++++++++++ .../definite_init_value_types.swift | 15 ++ test/SILOptimizer/diagnose_unreachable.swift | 10 +- test/SILOptimizer/discard_checking.swift | 12 +- test/SILOptimizer/infinite_recursion.swift | 6 +- test/SILOptimizer/pound_assert.swift | 3 +- test/SILOptimizer/return.swift | 2 +- test/decl/init/default-initialization.swift | 8 +- 21 files changed, 280 insertions(+), 31 deletions(-) create mode 100644 SwiftCompilerSources/Sources/Optimizer/FunctionPasses/BooleanLiteralFolding.swift create mode 100644 test/SILOptimizer/boolean-literal-folding.sil diff --git a/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/BooleanLiteralFolding.swift b/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/BooleanLiteralFolding.swift new file mode 100644 index 0000000000000..948566c37d80f --- /dev/null +++ b/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/BooleanLiteralFolding.swift @@ -0,0 +1,70 @@ +//===--- BooleanLiteralFolding.swift ---------------------------------------==// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +import SIL + +/// Constant folds conditional branches with boolean literals as operands. +/// +/// ``` +/// %1 = integer_literal -1 +/// %2 = apply %bool_init(%1) // Bool.init(_builtinBooleanLiteral:) +/// %3 = struct_extract %2, #Bool._value +/// cond_br %3, bb1, bb2 +/// ``` +/// -> +/// ``` +/// ... +/// br bb1 +/// ``` +/// +/// This pass is intended to run before DefiniteInitialization, where mandatory inlining and +/// constant folding didn't run, yet (which would perform this kind of optimization). +/// +/// This optimization is required to let DefiniteInitialization handle boolean literals correctly. +/// For example in infinite loops: +/// +/// ``` +/// init() { +/// while true { // DI need to know that there is no loop exit from this while-statement +/// if some_condition { +/// member_field = init_value +/// break +/// } +/// } +/// } +/// ``` +/// +let booleanLiteralFolding = FunctionPass(name: "boolean-literal-folding") { + (function: Function, context: FunctionPassContext) in + + for block in function.blocks { + if let condBr = block.terminator as? CondBranchInst { + fold(condBranch: condBr, context) + } + } +} + +private func fold(condBranch: CondBranchInst, _ context: FunctionPassContext) { + guard let structExtract = condBranch.condition as? StructExtractInst, + let initApply = structExtract.struct as? ApplyInst, + initApply.hasSemanticsAttribute("bool.literal_init"), + initApply.arguments.count == 2, + let literal = initApply.arguments[0] as? IntegerLiteralInst, + let literalValue = literal.value else + { + return + } + + let builder = Builder(before: condBranch, context) + builder.createBranch(to: literalValue == 0 ? condBranch.falseBlock : condBranch.trueBlock) + context.erase(instruction: condBranch) +} diff --git a/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/CMakeLists.txt b/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/CMakeLists.txt index 3f76931a78485..2da1ae0dc6b69 100644 --- a/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/CMakeLists.txt +++ b/SwiftCompilerSources/Sources/Optimizer/FunctionPasses/CMakeLists.txt @@ -10,6 +10,7 @@ swift_compiler_sources(Optimizer AllocVectorLowering.swift AssumeSingleThreaded.swift AsyncDemotion.swift + BooleanLiteralFolding.swift CleanupDebugSteps.swift ComputeEscapeEffects.swift ComputeSideEffects.swift diff --git a/SwiftCompilerSources/Sources/Optimizer/PassManager/PassRegistration.swift b/SwiftCompilerSources/Sources/Optimizer/PassManager/PassRegistration.swift index cd70a399331b8..f4759c02a9e1a 100644 --- a/SwiftCompilerSources/Sources/Optimizer/PassManager/PassRegistration.swift +++ b/SwiftCompilerSources/Sources/Optimizer/PassManager/PassRegistration.swift @@ -67,6 +67,7 @@ private func registerSwiftPasses() { // Function passes registerPass(allocVectorLowering, { allocVectorLowering.run($0) }) registerPass(asyncDemotion, { asyncDemotion.run($0) }) + registerPass(booleanLiteralFolding, { booleanLiteralFolding.run($0) }) registerPass(letPropertyLowering, { letPropertyLowering.run($0) }) registerPass(mergeCondFailsPass, { mergeCondFailsPass.run($0) }) registerPass(computeEscapeEffects, { computeEscapeEffects.run($0) }) diff --git a/include/swift/SILOptimizer/PassManager/Passes.def b/include/swift/SILOptimizer/PassManager/Passes.def index a3026f389a830..d23a689011bdb 100644 --- a/include/swift/SILOptimizer/PassManager/Passes.def +++ b/include/swift/SILOptimizer/PassManager/Passes.def @@ -128,6 +128,8 @@ PASS(BasicInstructionPropertyDumper, "basic-instruction-property-dump", "Print SIL Instruction MemBehavior and ReleaseBehavior Information") PASS(BasicCalleePrinter, "basic-callee-printer", "Print Basic Callee Analysis for Testing") +SWIFT_FUNCTION_PASS(BooleanLiteralFolding, "boolean-literal-folding", + "Constant folds initializers of boolean literals") PASS(CFGPrinter, "view-cfg", "View Function CFGs") PASS(COWArrayOpts, "cowarray-opt", diff --git a/lib/SILOptimizer/PassManager/PassPipeline.cpp b/lib/SILOptimizer/PassManager/PassPipeline.cpp index 199b043e8a24d..bd177ac3ff230 100644 --- a/lib/SILOptimizer/PassManager/PassPipeline.cpp +++ b/lib/SILOptimizer/PassManager/PassPipeline.cpp @@ -133,6 +133,7 @@ static void addMandatoryDiagnosticOptPipeline(SILPassPipelinePlan &P) { P.addAllocBoxToStack(); P.addNoReturnFolding(); + P.addBooleanLiteralFolding(); addDefiniteInitialization(P); P.addAddressLowering(); diff --git a/test/AutoDiff/SILOptimizer/activity_analysis.swift b/test/AutoDiff/SILOptimizer/activity_analysis.swift index bcb27af3cdf6f..e4447735d4967 100644 --- a/test/AutoDiff/SILOptimizer/activity_analysis.swift +++ b/test/AutoDiff/SILOptimizer/activity_analysis.swift @@ -1,4 +1,5 @@ -// RUN: %target-swift-emit-sil -verify -Xllvm -debug-only=differentiation %s 2>&1 | %FileCheck %s +// TODO: re-enable the boolean-literal-folding pass and fix the test accordingly +// RUN: %target-swift-emit-sil -Xllvm -sil-disable-pass=boolean-literal-folding -verify -Xllvm -debug-only=differentiation %s 2>&1 | %FileCheck %s // REQUIRES: asserts import _Differentiation diff --git a/test/AutoDiff/compiler_crashers_fixed/58660-conflicting-debug-info-inlining.swift b/test/AutoDiff/compiler_crashers_fixed/58660-conflicting-debug-info-inlining.swift index 0447065069cfd..5b84d2e935142 100644 --- a/test/AutoDiff/compiler_crashers_fixed/58660-conflicting-debug-info-inlining.swift +++ b/test/AutoDiff/compiler_crashers_fixed/58660-conflicting-debug-info-inlining.swift @@ -55,7 +55,8 @@ struct MyModel: Differentiable { property2 = localVar // `false` may instead be any expression that returns a `Bool`. - if false { + // TODO: cannot use literal `false` because it crashes + if 1 == 0 { localVar = member3 } } diff --git a/test/AutoDiff/compiler_crashers_fixed/issue-58123-mutating-functions-with-control-flow.swift b/test/AutoDiff/compiler_crashers_fixed/issue-58123-mutating-functions-with-control-flow.swift index 98ee93a59acf6..bc7f6f5050594 100644 --- a/test/AutoDiff/compiler_crashers_fixed/issue-58123-mutating-functions-with-control-flow.swift +++ b/test/AutoDiff/compiler_crashers_fixed/issue-58123-mutating-functions-with-control-flow.swift @@ -62,7 +62,8 @@ struct BatchNorm: Layer { // Crash requires conformance to `Layer` @differentiable(reverse) func callAsFunction(_ input: Tensor) -> Tensor { var offset = self.offset - if true { // Crash requires `if true` + // TODO: cannot use literal `true` because it crashes + if 1 == 1 { // Crash requires `if true` offset += offset // Using `offset = offset + offset` stops the crash } return offset diff --git a/test/AutoDiff/validation-test/address_only_tangentvector.swift b/test/AutoDiff/validation-test/address_only_tangentvector.swift index e62570ade1ff5..e7c6ad1f60cf6 100644 --- a/test/AutoDiff/validation-test/address_only_tangentvector.swift +++ b/test/AutoDiff/validation-test/address_only_tangentvector.swift @@ -43,7 +43,8 @@ AddressOnlyTangentVectorTests.test("LoadableClassAddressOnlyTangentVector") { @differentiable(reverse) func conditional(_ s: LoadableClass) -> T { var tuple = (s, (s, s)) - if false {} + // TODO: cannot use literal `false` because it crashes + if 1 == 0 {} return tuple.1.0.stored } expectEqual(.init(stored: 1), gradient(at: LoadableClass(10), of: conditional)) diff --git a/test/AutoDiff/validation-test/control_flow.swift b/test/AutoDiff/validation-test/control_flow.swift index e4a13f00481c4..915049b0a5236 100644 --- a/test/AutoDiff/validation-test/control_flow.swift +++ b/test/AutoDiff/validation-test/control_flow.swift @@ -66,10 +66,12 @@ ControlFlowTests.test("Conditionals") { func cond4_var(_ x: Float) -> Float { var outer = x - outerIf: if true { + // TODO: cannot use literal `true` because it crashes + outerIf: if 1 == 1 { var inner = outer inner = inner * x - if false { + // TODO: cannot use literal `false` because it crashes + if 1 == 0 { break outerIf } outer = inner @@ -386,8 +388,9 @@ ControlFlowTests.test("NestedConditionals") { @differentiable(reverse, wrt: self) // wrt only self is important func callAsFunction(_ input: Float) -> Float { var x = input - if true { - if true { + // TODO: cannot use literal `true` because it crashes + if 1 == 1 { + if 1 == 1 { // Function application below should make `self` have non-zero // derivative. x = x * w @@ -405,8 +408,9 @@ ControlFlowTests.test("NestedConditionals") { @differentiable(reverse, wrt: x) func TF_781(_ x: Float, _ y: Float) -> Float { var result = y - if true { - if true { + // TODO: cannot use literal `true` because it crashes + if 1 == 1 { + if 1 == 1 { result = result * x } } @@ -791,7 +795,8 @@ ControlFlowTests.test("ThrowingCalls") { func testComplexControlFlow(_ x: Float) -> Float { rethrowing({}) for _ in 0..(_ x: T) -> T { rethrowing({}) for _ in 0..<10 { - if true { + // TODO: cannot use literal `true` because it crashes + if 1 == 1 { rethrowing({}) } rethrowing({}) // non-active `try_apply` diff --git a/test/Macros/Inputs/syntax_macro_definitions.swift b/test/Macros/Inputs/syntax_macro_definitions.swift index 8082317610948..2d153af811ba9 100644 --- a/test/Macros/Inputs/syntax_macro_definitions.swift +++ b/test/Macros/Inputs/syntax_macro_definitions.swift @@ -1772,7 +1772,7 @@ public struct SimpleCodeItemMacro: CodeItemMacro { } """)), .init(item: .stmt(""" - if false { + if 1 == 0 { print("impossible") } """)), diff --git a/test/Macros/macro_expand_codeitems.swift b/test/Macros/macro_expand_codeitems.swift index b262c644bdf81..1229197a25e92 100644 --- a/test/Macros/macro_expand_codeitems.swift +++ b/test/Macros/macro_expand_codeitems.swift @@ -21,8 +21,6 @@ func testFreestandingMacroExpansion() { // CHECK: from stmt // CHECK: from usedInExpandedStmt // CHECK: from expr - // CHECK-DIAGS: note: condition always evaluates to false - // CHECK-DIAGS: CONTENTS OF FILE @__swiftmacro_9MacroUser016testFreestandingA9ExpansionyyF9codeItemsfMf0_.swift: // CHECK-DIAGS: struct $s9MacroUser016testFreestandingA9ExpansionyyF9codeItemsfMf0_3foofMu_ { // CHECK-DIAGS: END CONTENTS OF FILE #codeItems diff --git a/test/SILGen/availability_query.swift b/test/SILGen/availability_query.swift index 2e165c6099475..105c85ca5d594 100644 --- a/test/SILGen/availability_query.swift +++ b/test/SILGen/availability_query.swift @@ -121,7 +121,7 @@ func testUnreachableVersionAvailable(condition: Bool) { if true { doThing() // no-warning } - if false { // expected-note {{condition always evaluates to false}} + if 1 == 0 { // expected-note {{condition always evaluates to false}} doThing() // expected-warning {{will never be executed}} } } @@ -144,8 +144,8 @@ func testUnreachablePlatformAvailable(condition: Bool) { if true { doThing() // no-warning } - if false { // expected-note {{condition always evaluates to false}} - doThing() // expected-warning {{will never be executed}} + if false { + doThing() } } diff --git a/test/SILOptimizer/boolean-literal-folding.sil b/test/SILOptimizer/boolean-literal-folding.sil new file mode 100644 index 0000000000000..3b0baa7979914 --- /dev/null +++ b/test/SILOptimizer/boolean-literal-folding.sil @@ -0,0 +1,136 @@ +// RUN: %target-sil-opt -enable-sil-verify-all %s -boolean-literal-folding | %FileCheck %s + +// REQUIRES: swift_in_compiler + +sil_stage canonical + +import Builtin +import Swift + +sil public_external [_semantics "bool.literal_init"] @bool_literal_init : $@convention(method) (Builtin.Int1, @thin Bool.Type) -> Bool +sil public_external @no_bool_literal_init : $@convention(method) (Builtin.Int1, @thin Bool.Type) -> Bool +sil public_external [_semantics "bool.literal_init"] @wrong_bool_literal_init : $@convention(thin) () -> Bool + +// CHECK-LABEL: sil [ossa] @replace_true : +// CHECK: struct_extract +// CHECK-NEXT: br bb1 +// CHECK: bb1: +// CHECK: } // end sil function 'replace_true' +sil [ossa] @replace_true : $@convention(thin) () -> () { +bb0: + %0 = integer_literal $Builtin.Int1, -1 + %1 = metatype $@thin Bool.Type + %2 = function_ref @bool_literal_init : $@convention(method) (Builtin.Int1, @thin Bool.Type) -> Bool + %3 = apply %2(%0, %1) : $@convention(method) (Builtin.Int1, @thin Bool.Type) -> Bool + %4 = struct_extract %3 : $Bool, #Bool._value + cond_br %4, bb1, bb2 +bb1: + br bb3 +bb2: + br bb3 +bb3: + %r = tuple () + return %r : $() +} + +// CHECK-LABEL: sil [ossa] @replace_false : +// CHECK: struct_extract +// CHECK-NEXT: br bb2 +// CHECK: bb1: +// CHECK: } // end sil function 'replace_false' +sil [ossa] @replace_false : $@convention(thin) () -> () { +bb0: + %0 = integer_literal $Builtin.Int1, 0 + %1 = metatype $@thin Bool.Type + %2 = function_ref @bool_literal_init : $@convention(method) (Builtin.Int1, @thin Bool.Type) -> Bool + %3 = apply %2(%0, %1) : $@convention(method) (Builtin.Int1, @thin Bool.Type) -> Bool + %4 = struct_extract %3 : $Bool, #Bool._value + cond_br %4, bb1, bb2 +bb1: + br bb3 +bb2: + br bb3 +bb3: + %r = tuple () + return %r : $() +} + +// CHECK-LABEL: sil [ossa] @dont_replace_non_literal : +// CHECK: cond_br %0, bb1, bb2 +// CHECK: bb1: +// CHECK: } // end sil function 'dont_replace_non_literal' +sil [ossa] @dont_replace_non_literal : $@convention(thin) (Builtin.Int1) -> () { +bb0(%0 : $Builtin.Int1): + cond_br %0, bb1, bb2 +bb1: + br bb3 +bb2: + br bb3 +bb3: + %r = tuple () + return %r : $() +} + +// CHECK-LABEL: sil [ossa] @dont_replace_non_init_func : +// CHECK: [[B:%.*]] = struct_extract +// CHECK: cond_br [[B]], bb1, bb2 +// CHECK: bb1: +// CHECK: } // end sil function 'dont_replace_non_init_func' +sil [ossa] @dont_replace_non_init_func : $@convention(thin) () -> () { +bb0: + %0 = integer_literal $Builtin.Int1, -1 + %1 = metatype $@thin Bool.Type + %2 = function_ref @no_bool_literal_init : $@convention(method) (Builtin.Int1, @thin Bool.Type) -> Bool + %3 = apply %2(%0, %1) : $@convention(method) (Builtin.Int1, @thin Bool.Type) -> Bool + %4 = struct_extract %3 : $Bool, #Bool._value + cond_br %4, bb1, bb2 +bb1: + br bb3 +bb2: + br bb3 +bb3: + %r = tuple () + return %r : $() +} + +// CHECK-LABEL: sil [ossa] @dont_replace_wrong_init_func : +// CHECK: [[B:%.*]] = struct_extract +// CHECK: cond_br [[B]], bb1, bb2 +// CHECK: bb1: +// CHECK: } // end sil function 'dont_replace_wrong_init_func' +sil [ossa] @dont_replace_wrong_init_func : $@convention(thin) () -> () { +bb0: + %2 = function_ref @wrong_bool_literal_init : $@convention(thin) () -> Bool + %3 = apply %2() : $@convention(thin) () -> Bool + %4 = struct_extract %3 : $Bool, #Bool._value + cond_br %4, bb1, bb2 +bb1: + br bb3 +bb2: + br bb3 +bb3: + %r = tuple () + return %r : $() +} + +// CHECK-LABEL: sil [ossa] @dont_replace_non_literal_init : +// CHECK: [[B:%.*]] = struct_extract +// CHECK: cond_br [[B]], bb1, bb2 +// CHECK: bb1: +// CHECK: } // end sil function 'dont_replace_non_literal_init' +sil [ossa] @dont_replace_non_literal_init : $@convention(thin) (Builtin.Int1) -> () { +bb0(%0 : $Builtin.Int1): + %1 = metatype $@thin Bool.Type + %2 = function_ref @bool_literal_init : $@convention(method) (Builtin.Int1, @thin Bool.Type) -> Bool + %3 = apply %2(%0, %1) : $@convention(method) (Builtin.Int1, @thin Bool.Type) -> Bool + %4 = struct_extract %3 : $Bool, #Bool._value + cond_br %4, bb1, bb2 +bb1: + br bb3 +bb2: + br bb3 +bb3: + %r = tuple () + return %r : $() +} + diff --git a/test/SILOptimizer/definite_init_value_types.swift b/test/SILOptimizer/definite_init_value_types.swift index 3d035bc369edc..fd7351be34ced 100644 --- a/test/SILOptimizer/definite_init_value_types.swift +++ b/test/SILOptimizer/definite_init_value_types.swift @@ -115,6 +115,16 @@ struct ValueStruct { self = ValueStruct() } } + + // Test control statements with boolean literals, like while-true loops + init(es: EmptyStruct) { + while true { + if cond() { + ivar = es + break + } + } + } } struct AddressStruct { @@ -131,3 +141,8 @@ struct AddressStruct { } } } + +func cond() -> Bool { + return true +} + diff --git a/test/SILOptimizer/diagnose_unreachable.swift b/test/SILOptimizer/diagnose_unreachable.swift index 614a2ef251f92..ee8cbd9fe24c9 100644 --- a/test/SILOptimizer/diagnose_unreachable.swift +++ b/test/SILOptimizer/diagnose_unreachable.swift @@ -4,7 +4,7 @@ // RUN: %target-swift-frontend -O -emit-sil -primary-file %s -o /dev/null -verify func ifFalse() -> Int { - if false { // expected-note {{always evaluates to false}} + if 1 == 0 { // expected-note {{always evaluates to false}} return 0 // expected-warning {{will never be executed}} } else { return 1 @@ -13,7 +13,7 @@ func ifFalse() -> Int { func ifTrue() -> Int { _ = 0 - if true { // expected-note {{always evaluates to true}} + if 1 == 1 { // expected-note {{always evaluates to true}} return 1 } return 0 // expected-warning {{will never be executed}} @@ -68,7 +68,7 @@ func userCode() {} func whileTrue() { var x = 0 - while true { // expected-note {{always evaluates to true}} + while 1 == 1 { // expected-note {{always evaluates to true}} x += 1 } userCode() // expected-warning {{will never be executed}} @@ -92,7 +92,7 @@ func whileTrueReachable(_ v: Int) -> () { func whileTrueTwoPredecessorsEliminated() -> () { var x = 0 - while (true) { // expected-note {{always evaluates to true}} + while (1 == 1) { // expected-note {{always evaluates to true}} if false { break } @@ -102,7 +102,7 @@ func whileTrueTwoPredecessorsEliminated() -> () { } func unreachableBranch() -> Int { - if false { // expected-note {{always evaluates to false}} + if 1 == 0 { // expected-note {{always evaluates to false}} // FIXME: It'd be nice if the warning were on 'if true' instead of the // body. if true { diff --git a/test/SILOptimizer/discard_checking.swift b/test/SILOptimizer/discard_checking.swift index 98589911a7383..0134227813102 100644 --- a/test/SILOptimizer/discard_checking.swift +++ b/test/SILOptimizer/discard_checking.swift @@ -1,6 +1,7 @@ // RUN: %target-swift-emit-sil -sil-verify-all -verify %s -disable-availability-checking // REQUIRES: concurrency +// REQUIRES: swift_in_compiler enum Color { case red, green, blue, none @@ -476,10 +477,17 @@ struct Basics: ~Copyable { repeat { self = Basics() // expected-error {{cannot reinitialize 'self' after 'discard self'}} discard self // expected-note 2{{discarded self here}} - } while false + } while 1 == 0 } // expected-error {{must consume 'self' before exiting method that discards self}} - consuming func reinitAfterDiscard3_ok(_ c: Color) throws { + consuming func reinitAfterDiscard3_ok1(_ c: Color) throws { + repeat { + self = Basics() + discard self + } while false + } + + consuming func reinitAfterDiscard3_ok2(_ c: Color) throws { self = Basics() discard self } diff --git a/test/SILOptimizer/infinite_recursion.swift b/test/SILOptimizer/infinite_recursion.swift index d3ba28a31ce12..ee9f7dd86e282 100644 --- a/test/SILOptimizer/infinite_recursion.swift +++ b/test/SILOptimizer/infinite_recursion.swift @@ -1,5 +1,7 @@ // RUN: %target-swift-frontend -emit-sil %s -o /dev/null -verify +// REQUIRES: swift_in_compiler + func a() { a() // expected-warning {{function call causes an infinite recursion}} } @@ -152,11 +154,11 @@ func e() { f() } func f() { e() } func g() { - while true { // expected-note {{condition always evaluates to true}} + while true { g() // expected-warning {{function call causes an infinite recursion}} } - g() // expected-warning {{will never be executed}} + g() } func h(_ x : Int) { diff --git a/test/SILOptimizer/pound_assert.swift b/test/SILOptimizer/pound_assert.swift index 182daaf5f5444..16718e3fd1b5e 100644 --- a/test/SILOptimizer/pound_assert.swift +++ b/test/SILOptimizer/pound_assert.swift @@ -1,5 +1,6 @@ // RUN: %target-swift-frontend -enable-experimental-static-assert -emit-sil %s -verify // REQUIRES: asserts +// REQUIRES: swift_in_compiler //===----------------------------------------------------------------------===// // Basic function calls and control flow @@ -43,10 +44,8 @@ func loops2(a: Int) -> Int { } func infiniteLoop() -> Int { - // expected-note @+2 {{condition always evaluates to true}} // expected-note @+1 {{found loop here}} while true {} - // expected-warning @+1 {{will never be executed}} return 1 } diff --git a/test/SILOptimizer/return.swift b/test/SILOptimizer/return.swift index 6a43598205243..84147017d6506 100644 --- a/test/SILOptimizer/return.swift +++ b/test/SILOptimizer/return.swift @@ -117,7 +117,7 @@ func testUnreachableAfterNoReturn(x: Int) -> Int { func testUnreachableAfterNoReturnInADifferentBlock() -> Int { let x:Int = 5 - if true { // expected-note {{condition always evaluates to true}} + if 1 == 1 { // expected-note {{condition always evaluates to true}} exit(); } return x; // expected-warning {{will never be executed}} diff --git a/test/decl/init/default-initialization.swift b/test/decl/init/default-initialization.swift index 009faee2a21e0..428b229f73416 100644 --- a/test/decl/init/default-initialization.swift +++ b/test/decl/init/default-initialization.swift @@ -1,5 +1,7 @@ // RUN: %target-swift-frontend -emit-sil -verify %s +// REQUIRES: swift_in_compiler + struct A { var i : Int init(i : Int) { self.i = i } @@ -50,9 +52,13 @@ extension B { } init(j : Int, x : Bool) { - if true { a = A(i: j) } + if 1 == 1 { a = A(i: j) } } // expected-error {{return from initializer without initializing all stored properties}} + init(j : Int, x2 : Bool) { + if true { a = A(i: j) } + } + init(i : Int, x : Bool, y : Bool) { a = A(i: a.i) // expected-error {{'self' used before all stored properties are initialized}} }