Merge remote-tracking branch 'origin/main' into rebranch

This commit is contained in:
swift-ci
2025-09-19 22:17:53 -07:00
11 changed files with 184 additions and 74 deletions

View File

@@ -49,10 +49,14 @@ enum class CopyPropagationOption : uint8_t {
// just -enable-ossa-modules. // just -enable-ossa-modules.
RequestedPassesOnly, RequestedPassesOnly,
// Add all relevant copy propagation passes. If a setting, e.g. // Run copy propagation during optimized builds only.
// -enable-ossa-modules, requests to add copy propagation to the pipeline, do //
// so. // If a setting, e.g. -enable-ossa-modules, requests to add copy propagation
On // to the performance pipeline, do so.
Optimizing,
// Run copy propagation during all builds and whenever requested.
Always
}; };
enum class DestroyHoistingOption : uint8_t { enum class DestroyHoistingOption : uint8_t {
@@ -90,11 +94,8 @@ public:
/// observable end of lexical scope. /// observable end of lexical scope.
LexicalLifetimesOption LexicalLifetimes = LexicalLifetimesOption::On; LexicalLifetimesOption LexicalLifetimes = LexicalLifetimesOption::On;
/// Whether to run SIL copy propagation to shorten object lifetime in whatever /// Controls when to run SIL copy propagation, which shortens object lifetimes
/// optimization pipeline is currently used. CopyPropagationOption CopyPropagation = CopyPropagationOption::Optimizing;
///
/// When this is 'On' the pipeline has default behavior.
CopyPropagationOption CopyPropagation = CopyPropagationOption::On;
/// Whether to run the DestroyAddrHoisting pass. /// Whether to run the DestroyAddrHoisting pass.
/// ///

View File

@@ -282,12 +282,12 @@ def no_parallel_scan : Flag<["-"], "no-parallel-scan">,
HelpText<"Perform dependency scanning in a single-threaded fashion.">; HelpText<"Perform dependency scanning in a single-threaded fashion.">;
def enable_copy_propagation : Flag<["-"], "enable-copy-propagation">, def enable_copy_propagation : Flag<["-"], "enable-copy-propagation">,
HelpText<"Run SIL copy propagation with lexical lifetimes to shorten object " HelpText<"Always run SIL copy propagation with lexical lifetimes to shorten object "
"lifetimes while preserving variable lifetimes.">; "lifetimes while preserving variable lifetimes.">;
def copy_propagation_state_EQ : def copy_propagation_state_EQ :
Joined<["-"], "enable-copy-propagation=">, Joined<["-"], "enable-copy-propagation=">,
HelpText<"Whether to enable copy propagation">, HelpText<"Whether to enable copy propagation">,
MetaVarName<"true|requested-passes-only|false">; MetaVarName<"always|optimizing|requested-passes-only|false">;
def disable_infer_public_concurrent_value : Flag<["-"], "disable-infer-public-sendable">, def disable_infer_public_concurrent_value : Flag<["-"], "disable-infer-public-sendable">,
HelpText<"Disable inference of Sendable conformances for public structs and enums">; HelpText<"Disable inference of Sendable conformances for public structs and enums">;

View File

@@ -115,8 +115,11 @@ operator<<(raw_ostream &os, const std::optional<CopyPropagationOption> option) {
case CopyPropagationOption::RequestedPassesOnly: case CopyPropagationOption::RequestedPassesOnly:
os << "requested-passes-only"; os << "requested-passes-only";
break; break;
case CopyPropagationOption::On: case CopyPropagationOption::Optimizing:
os << "on"; os << "optimizing";
break;
case CopyPropagationOption::Always:
os << "always";
break; break;
} }
} else { } else {
@@ -135,24 +138,27 @@ public:
// parse - Return true on error. // parse - Return true on error.
bool parse(Option &O, StringRef ArgName, StringRef Arg, bool parse(Option &O, StringRef ArgName, StringRef Arg,
std::optional<CopyPropagationOption> &Value) { std::optional<CopyPropagationOption> &Value) {
if (Arg == "" || Arg == "true" || Arg == "TRUE" || Arg == "True" || if (Arg.compare_insensitive("always")) {
Arg == "1") { Value = CopyPropagationOption::Always;
Value = CopyPropagationOption::On;
return false; return false;
} }
if (Arg == "false" || Arg == "FALSE" || Arg == "False" || Arg == "0") { if (Arg.compare_insensitive("optimizing")) {
Value = CopyPropagationOption::Optimizing;
return false;
}
if (Arg.compare_insensitive("false") || Arg.compare_insensitive("off") ||
Arg == "0") {
Value = CopyPropagationOption::Off; Value = CopyPropagationOption::Off;
return false; return false;
} }
if (Arg == "requested-passes-only" || Arg == "REQUESTED-PASSES-ONLY" || if (Arg.compare_insensitive("requested-passes-only")) {
Arg == "Requested-Passes-Only") {
Value = CopyPropagationOption::RequestedPassesOnly; Value = CopyPropagationOption::RequestedPassesOnly;
return false; return false;
} }
return O.error("'" + Arg + return O.error("'" + Arg +
"' is invalid for CopyPropagationOption! Try true, false, " "' is invalid for CopyPropagationOption!"
"or requested-passes-only."); " Try always, optimizing, or requested-passes-only.");
} }
void initialize() {} void initialize() {}
@@ -907,7 +913,7 @@ int sil_opt_main(ArrayRef<const char *> argv, void *MainAddr) {
// Unless overridden below, enabling copy propagation means enabling lexical // Unless overridden below, enabling copy propagation means enabling lexical
// lifetimes. // lifetimes.
if (SILOpts.CopyPropagation == CopyPropagationOption::On) if (SILOpts.CopyPropagation >= CopyPropagationOption::Optimizing)
SILOpts.LexicalLifetimes = LexicalLifetimesOption::On; SILOpts.LexicalLifetimes = LexicalLifetimesOption::On;
// Unless overridden below, disable copy propagation means disabling lexical // Unless overridden below, disable copy propagation means disabling lexical

View File

@@ -2908,33 +2908,22 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
if (Arg *A = Args.getLastArg(OPT_copy_propagation_state_EQ)) { if (Arg *A = Args.getLastArg(OPT_copy_propagation_state_EQ)) {
specifiedCopyPropagationOption = specifiedCopyPropagationOption =
llvm::StringSwitch<std::optional<CopyPropagationOption>>(A->getValue()) llvm::StringSwitch<std::optional<CopyPropagationOption>>(A->getValue())
.Case("true", CopyPropagationOption::On) .Case("always", CopyPropagationOption::Always)
.Case("optimizing", CopyPropagationOption::Optimizing)
.Case("false", CopyPropagationOption::Off) .Case("false", CopyPropagationOption::Off)
.Case("requested-passes-only", .Case("requested-passes-only",
CopyPropagationOption::RequestedPassesOnly) CopyPropagationOption::RequestedPassesOnly)
.Default(std::nullopt); .Default(std::nullopt);
// Error if copy propagation has been set via the flag at the same time.
if (auto *Flag = Args.getLastArg(OPT_enable_copy_propagation)) {
Diags.diagnose(SourceLoc(), diag::error_invalid_arg_combination,
Flag->getAsString(Args),
A->getAsString(Args));
}
} }
if (Args.hasArg(OPT_enable_copy_propagation)) { if (Args.hasArg(OPT_enable_copy_propagation)) {
if (specifiedCopyPropagationOption) { specifiedCopyPropagationOption = CopyPropagationOption::Always;
if (*specifiedCopyPropagationOption == CopyPropagationOption::Off) {
// Error if copy propagation has been set to ::Off via the meta-var form
// and enabled via the flag.
Diags.diagnose(SourceLoc(), diag::error_invalid_arg_combination,
"enable-copy-propagation",
"enable-copy-propagation=false");
return true;
} else if (*specifiedCopyPropagationOption ==
CopyPropagationOption::RequestedPassesOnly) {
// Error if copy propagation has been set to ::RequestedPassesOnly via
// the meta-var form and enabled via the flag.
Diags.diagnose(SourceLoc(), diag::error_invalid_arg_combination,
"enable-copy-propagation",
"enable-copy-propagation=requested-passes-only");
return true;
}
} else {
specifiedCopyPropagationOption = CopyPropagationOption::On;
}
} }
if (specifiedCopyPropagationOption) { if (specifiedCopyPropagationOption) {
Opts.CopyPropagation = *specifiedCopyPropagationOption; Opts.CopyPropagation = *specifiedCopyPropagationOption;
@@ -2966,7 +2955,7 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
// Unless overridden below, enabling copy propagation means enabling lexical // Unless overridden below, enabling copy propagation means enabling lexical
// lifetimes. // lifetimes.
if (Opts.CopyPropagation == CopyPropagationOption::On) { if (Opts.CopyPropagation >= CopyPropagationOption::Optimizing) {
Opts.LexicalLifetimes = LexicalLifetimesOption::On; Opts.LexicalLifetimes = LexicalLifetimesOption::On;
Opts.DestroyHoisting = DestroyHoistingOption::On; Opts.DestroyHoisting = DestroyHoistingOption::On;
} }

View File

@@ -255,7 +255,7 @@ static void addMandatoryDiagnosticOptPipeline(SILPassPipelinePlan &P) {
// Only issue weak lifetime warnings for users who select object lifetime // Only issue weak lifetime warnings for users who select object lifetime
// optimization. The risk of spurious warnings outweighs the benefits. // optimization. The risk of spurious warnings outweighs the benefits.
if (P.getOptions().CopyPropagation == CopyPropagationOption::On) { if (P.getOptions().CopyPropagation >= CopyPropagationOption::Optimizing) {
P.addDiagnoseLifetimeIssues(); P.addDiagnoseLifetimeIssues();
} }
@@ -278,6 +278,23 @@ static void addMandatoryDiagnosticOptPipeline(SILPassPipelinePlan &P) {
P.addDiagnoseUnknownConstValues(); P.addDiagnoseUnknownConstValues();
P.addEmbeddedSwiftDiagnostics(); P.addEmbeddedSwiftDiagnostics();
/// FIXME: Ideally, we'd have this relative order:
/// 1. DiagnoseLifetimeIssues
/// 2. CopyPropagation
/// 3. AddressLowering
/// to get the maximum benefits of CopyPropagation + OpaqueValues in -Onone.
if (P.getOptions().CopyPropagation == CopyPropagationOption::Always) {
// FIXME: ComputeSideEffects helps CopyPropagation simplify across
// call-sites, but PerformanceDiagnostics is sensitive to the # of copies.
// If ManualOwnership is used in the compiler itself, we wouldn't be able
// to bootstrap the compiler on different platforms with same diagnostics.
#ifdef SWIFT_ENABLE_SWIFT_IN_SWIFT
P.addComputeSideEffects();
#endif
P.addMandatoryCopyPropagation();
}
P.addPerformanceDiagnostics(); P.addPerformanceDiagnostics();
} }
@@ -655,7 +672,7 @@ static void addPerfEarlyModulePassPipeline(SILPassPipelinePlan &P) {
// Cleanup after SILGen: remove trivial copies to temporaries. // Cleanup after SILGen: remove trivial copies to temporaries.
P.addTempRValueElimination(); P.addTempRValueElimination();
// Cleanup after SILGen: remove unneeded borrows/copies. // Cleanup after SILGen: remove unneeded borrows/copies.
if (P.getOptions().CopyPropagation == CopyPropagationOption::On) { if (P.getOptions().CopyPropagation >= CopyPropagationOption::Optimizing) {
P.addComputeSideEffects(); P.addComputeSideEffects();
P.addCopyPropagation(); P.addCopyPropagation();
} }

View File

@@ -668,7 +668,7 @@ class SILCombine : public SILFunctionTransform {
/// The entry point to the transformation. /// The entry point to the transformation.
void run() override { void run() override {
bool enableCopyPropagation = bool enableCopyPropagation =
getOptions().CopyPropagation == CopyPropagationOption::On; getOptions().CopyPropagation >= CopyPropagationOption::Optimizing;
if (getOptions().EnableOSSAModules) { if (getOptions().EnableOSSAModules) {
enableCopyPropagation = enableCopyPropagation =
getOptions().CopyPropagation != CopyPropagationOption::Off; getOptions().CopyPropagation != CopyPropagationOption::Off;

View File

@@ -688,10 +688,10 @@ void CopyPropagation::verifyOwnership() {
: deBlocksAnalysis->get(f)); : deBlocksAnalysis->get(f));
} }
// MandatoryCopyPropagation is not currently enabled in the -Onone pipeline // MandatoryCopyPropagation runs in the -Onone pipeline and needs to be more
// because it may negatively affect the debugging experience. // conservative, preserving debug information.
SILTransform *swift::createMandatoryCopyPropagation() { SILTransform *swift::createMandatoryCopyPropagation() {
return new CopyPropagation(PruneDebugInsts, /*canonicalizeAll*/ true, return new CopyPropagation(DontPruneDebugInsts, /*canonicalizeAll*/ true,
/*canonicalizeBorrows*/ false); /*canonicalizeBorrows*/ false);
} }

View File

@@ -1,4 +1,6 @@
// RUN: %target-swift-frontend %s -emit-sil -verify -enable-experimental-feature ManualOwnership // RUN: %target-swift-frontend %s -emit-sil -verify \
// RUN: -enable-experimental-feature ManualOwnership \
// RUN: -enable-copy-propagation=always
// REQUIRES: swift_feature_ManualOwnership // REQUIRES: swift_feature_ManualOwnership
@@ -12,6 +14,7 @@ public struct Pair {
var x: Int var x: Int
var y: Int var y: Int
@_manualOwnership
consuming func midpoint(_ other: borrowing Pair) -> Pair { consuming func midpoint(_ other: borrowing Pair) -> Pair {
return Pair(x: (x + other.x) / 2, y: (y + other.y) / 2) return Pair(x: (x + other.x) / 2, y: (y + other.y) / 2)
} }
@@ -24,7 +27,10 @@ public class Triangle {
var nontrivial = Whatever() var nontrivial = Whatever()
@_manualOwnership
consuming func consuming() {} consuming func consuming() {}
@_manualOwnership
borrowing func borrowing() {} borrowing func borrowing() {}
} }
@@ -33,14 +39,8 @@ public class Triangle {
@_manualOwnership @_manualOwnership
public func basic_return1() -> Triangle { public func basic_return1() -> Triangle {
let x = Triangle() let x = Triangle()
return x // expected-error {{explicit 'copy' required here}} return x
} }
@_manualOwnership
public func basic_return1_fixed() -> Triangle {
let x = Triangle()
return copy x
}
@_manualOwnership @_manualOwnership
public func basic_return2(t: Triangle) -> Triangle { public func basic_return2(t: Triangle) -> Triangle {
@@ -56,24 +56,39 @@ public func basic_return3() -> Triangle {
return Triangle() return Triangle()
} }
// FIXME: we need copy propagation in -Onone to eliminate all these copies
@_manualOwnership @_manualOwnership
func reassign_with_lets() -> Triangle { func reassign_with_lets() -> Triangle {
let x = Triangle() let x = Triangle()
let y = x // expected-error {{explicit 'copy' required here}} let y = x
let z = y // expected-error {{explicit 'copy' required here}} let z = y
return z // expected-error {{explicit 'copy' required here}} return z
} }
// FIXME: we need copy propagation in -Onone to eliminate all but the copies for returning
@_manualOwnership @_manualOwnership
func renamed_return(_ cond: Bool, _ a: Triangle) -> Triangle { func renamed_return(_ cond: Bool, _ a: Triangle) -> Triangle {
let b = a // expected-error {{explicit 'copy' required here}} let b = a
let c = b // expected-error {{explicit 'copy' required here}} let c = b
if cond { return b } // expected-error {{explicit 'copy' required here}} if cond { return b } // expected-error {{explicit 'copy' required here}}
return c // expected-error {{explicit 'copy' required here}} return c // expected-error {{explicit 'copy' required here}}
} }
@_manualOwnership
func renamed_return_fix1(_ cond: Bool, _ a: Triangle) -> Triangle {
let b = copy a
let c = copy b // FIXME: not needed! Is explicit_copy_value is blocking propagation?
if cond { return b }
return c
}
// FIXME: this crashes CopyPropagation!
//@_manualOwnership
//func renamed_return_fix2(_ cond: Bool, _ a: Triangle) -> Triangle {
// let b = a
// let c = b
// if cond { return copy b }
// return copy c
//}
/// MARK: method calls /// MARK: method calls
@_manualOwnership @_manualOwnership
@@ -87,7 +102,7 @@ func basic_methods_borrowing(_ t1: Triangle) {
func basic_methods_consuming(_ t1: Triangle) { func basic_methods_consuming(_ t1: Triangle) {
let t2 = Triangle() let t2 = Triangle()
t1.consuming() // expected-error {{explicit 'copy' required here}} t1.consuming() // expected-error {{explicit 'copy' required here}}
t2.consuming() // expected-error {{explicit 'copy' required here}} t2.consuming()
} }
@_manualOwnership @_manualOwnership
func basic_methods_consuming_fixed(_ t1: Triangle) { func basic_methods_consuming_fixed(_ t1: Triangle) {
@@ -96,7 +111,7 @@ func basic_methods_consuming_fixed(_ t1: Triangle) {
t3 = Triangle() t3 = Triangle()
(copy t1).consuming() (copy t1).consuming()
(copy t2).consuming() (copy t2).consuming() // FIXME: why is this not propagated?
(copy t3).consuming() (copy t3).consuming()
} }
@@ -113,12 +128,12 @@ func basic_function_call(_ t1: Triangle) {
/// MARK: control-flow /// MARK: control-flow
// FIXME: var's and assignments are a little busted // FIXME: var assignments are somtimes impossible to satisfy with 'copy'
// @_manualOwnership // @_manualOwnership
// func reassignments_1() { // func reassignments_1() {
// var t3 = Triangle() // var t3 = Triangle()
// t3 = Triangle() // t3 = copy Triangle() // FIXME: should not be needed
// t3.borrowing() // t3.borrowing()
// } // }
// @_manualOwnership // @_manualOwnership

View File

@@ -1,4 +1,8 @@
// RUN: %target-swift-frontend -primary-file %s -O -sil-verify-all -module-name=test -emit-sil | %FileCheck %s // RUN: %target-swift-frontend -primary-file %s -O \
// RUN: -sil-verify-all -module-name=test -emit-sil | %FileCheck %s
// RUN: %target-swift-frontend -primary-file %s -Onone -enable-copy-propagation \
// RUN: -sil-verify-all -module-name=test -emit-sil | %FileCheck %s --check-prefix ONONE
// REQUIRES: swift_in_compiler // REQUIRES: swift_in_compiler
@@ -21,6 +25,20 @@ func borrow(_ c: C)
// CHECK: [[NON_BARRIER:%[^,]+]] = function_ref @non_barrier // CHECK: [[NON_BARRIER:%[^,]+]] = function_ref @non_barrier
// CHECK: apply [[NON_BARRIER]]() // CHECK: apply [[NON_BARRIER]]()
// CHECK-LABEL: } // end sil function 'test_hoist_over_non_barrier' // CHECK-LABEL: } // end sil function 'test_hoist_over_non_barrier'
/////
// NOTE: in -Onone, the release is NOT hoisted, to preserve debugging.
// ONONE-LABEL: sil {{.*}}@test_hoist_over_non_barrier : {{.*}} {
// ONONE: [[INSTANCE:%[^,]+]] = apply {{.*}} -> @owned C
// ONONE: debug_value [[INSTANCE]], let, name "c"
// ONONE: [[BORROW:%[^,]+]] = function_ref @borrow
// ONONE: apply [[BORROW]]([[INSTANCE]])
// ONONE: [[NON_BARRIER:%[^,]+]] = function_ref @non_barrier
// ONONE: apply [[NON_BARRIER]]()
// ONONE: strong_release [[INSTANCE]]
// ONONE-LABEL: } // end sil function 'test_hoist_over_non_barrier'
@_silgen_name("test_hoist_over_non_barrier") @_silgen_name("test_hoist_over_non_barrier")
func test_hoist_over_non_barrier() { func test_hoist_over_non_barrier() {
let c = C() let c = C()
@@ -28,3 +46,67 @@ func test_hoist_over_non_barrier() {
non_barrier() non_barrier()
} }
// CHECK-LABEL: sil {{.*}}@reassign_with_lets : {{.*}} {
// CHECK: [[INSTANCE:%[^,]+]] = alloc_ref $C
// CHECK: [[EI:%.*]] = end_init_let_ref [[INSTANCE]]
// CHECK-NEXT: debug_value [[EI]], let, name "x"
// CHECK-NEXT: debug_value [[EI]], let, name "y"
// CHECK-NEXT: debug_value [[EI]], let, name "z"
// CHECK-NEXT: return [[EI]]
// CHECK-LABEL: } // end sil function 'reassign_with_lets'
// ONONE-LABEL: sil {{.*}}@reassign_with_lets : {{.*}} {
// ONONE: [[INSTANCE:%[^,]+]] = apply {{.*}} -> @owned C
// ONONE-NEXT: debug_value [[INSTANCE]], let, name "x"
// ONONE-NEXT: debug_value [[INSTANCE]], let, name "y"
// ONONE-NEXT: debug_value [[INSTANCE]], let, name "z"
// ONONE-NEXT: return [[INSTANCE]]
// ONONE-LABEL: } // end sil function 'reassign_with_lets'
@_silgen_name("reassign_with_lets")
func reassign_with_lets() -> C {
let x = C()
let y = x
let z = y
return z
}
// CHECK-LABEL: sil {{.*}}@renamed_return : {{.*}} {
// CHECK-NOT: strong_retain
// CHECK: debug_value %1, let, name "a"
// CHECK-NEXT: debug_value %1, let, name "b"
// CHECK-NEXT: debug_value %1, let, name "c"
// CHECK-NEXT: strong_retain %1
// CHECK-NEXT: return %1
// CHECK-LABEL: } // end sil function 'renamed_return'
/////
// Slightly different control-flow in -Onone, but still one
// retain dynamically executed on the object.
// ONONE-LABEL: sil {{.*}}@renamed_return : {{.*}} {
// ONONE-NOT: strong_retain
// ONONE: debug_value %1, let, name "a"
// ONONE-NEXT: debug_value %1, let, name "b"
// ONONE-NEXT: debug_value %1, let, name "c"
// ONONE: cond_br {{.*}} bb1, bb2
// ONONE: bb1
// ONONE: strong_retain %1
// ONONE: br bb3
// ONONE: bb2
// ONONE: strong_retain %1
// ONONE: br bb3
// ONONE: bb3
// ONONE-NEXT: return
// ONONE-LABEL: } // end sil function 'renamed_return'
@_silgen_name("renamed_return")
func renamed_return(_ cond: Bool, _ a: C) -> C {
let b = a
let c = b
if cond { return b }
return c
}

View File

@@ -49,7 +49,7 @@
// RUN: %target-swift-frontend %s \ // RUN: %target-swift-frontend %s \
// RUN: -O \ // RUN: -O \
// RUN: -enable-copy-propagation=true \ // RUN: -enable-copy-propagation=optimizing \
// RUN: -Xllvm -sil-print-pass-name \ // RUN: -Xllvm -sil-print-pass-name \
// RUN: -emit-ir \ // RUN: -emit-ir \
// RUN: -o /dev/null \ // RUN: -o /dev/null \
@@ -57,7 +57,7 @@
// RUN: %target-swift-frontend %s \ // RUN: %target-swift-frontend %s \
// RUN: -O \ // RUN: -O \
// RUN: -enable-copy-propagation=true \ // RUN: -enable-copy-propagation=optimizing \
// RUN: -enable-destroy-hoisting=false \ // RUN: -enable-destroy-hoisting=false \
// RUN: -Xllvm -sil-print-pass-name \ // RUN: -Xllvm -sil-print-pass-name \
// RUN: -emit-ir \ // RUN: -emit-ir \
@@ -66,7 +66,7 @@
// RUN: %target-swift-frontend %s \ // RUN: %target-swift-frontend %s \
// RUN: -O \ // RUN: -O \
// RUN: -enable-copy-propagation=true \ // RUN: -enable-copy-propagation=optimizing \
// RUN: -enable-destroy-hoisting=true \ // RUN: -enable-destroy-hoisting=true \
// RUN: -Xllvm -sil-print-pass-name \ // RUN: -Xllvm -sil-print-pass-name \
// RUN: -emit-ir \ // RUN: -emit-ir \

View File

@@ -1,4 +1,4 @@
// RUN: %target-swift-frontend -c -O -enable-copy-propagation=true -enable-lexical-lifetimes=true -sil-verify-all -Xllvm -sil-print-final-ossa-module %s | %FileCheck %s // RUN: %target-swift-frontend -c -O -enable-copy-propagation=optimizing -enable-lexical-lifetimes=true -sil-verify-all -Xllvm -sil-print-final-ossa-module %s | %FileCheck %s
// ============================================================================= // =============================================================================
// = DECLARATIONS {{ // = DECLARATIONS {{