Skip to content

Commit 370db70

Browse files
committed
Disable parallel compilation if an optimization flag in the -O group is being used.
Unless cross-module-optimization is disabled (which we don't really support at this time), the driver in this case will create a single frontend invocation that emits both the module and performs codegen. Cherry-pick of upstream: 29f0ec2
1 parent 2895800 commit 370db70

File tree

7 files changed

+125
-79
lines changed

7 files changed

+125
-79
lines changed

swift/internal/BUILD

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,9 @@ bzl_library(
9999
":feature_names",
100100
":features",
101101
":module_maps",
102+
":optimization",
102103
":utils",
103104
":vfsoverlay",
104-
":wmo",
105105
"//swift:providers",
106106
"@bazel_skylib//lib:paths",
107107
"@bazel_skylib//lib:sets",
@@ -314,9 +314,8 @@ bzl_library(
314314
)
315315

316316
bzl_library(
317-
name = "wmo",
318-
srcs = ["wmo.bzl"],
319-
visibility = ["//swift:__subpackages__"],
317+
name = "optimization",
318+
srcs = ["optimization.bzl"],
320319
deps = [
321320
":feature_names",
322321
],

swift/internal/compiling.bzl

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,12 @@ load(
7272
"upcoming_and_experimental_features",
7373
)
7474
load(":module_maps.bzl", "write_module_map")
75+
load(
76+
":optimization.bzl",
77+
"find_num_threads_flag_value",
78+
"is_optimization_manually_requested",
79+
"is_wmo_manually_requested",
80+
)
7581
load(":toolchain_utils.bzl", "SWIFT_TOOLCHAIN_TYPE")
7682
load(
7783
":utils.bzl",
@@ -84,7 +90,6 @@ load(
8490
"struct_fields",
8591
)
8692
load(":vfsoverlay.bzl", "write_vfsoverlay")
87-
load(":wmo.bzl", "find_num_threads_flag_value", "is_wmo_manually_requested")
8893

8994
# VFS root where all .swiftmodule files will be placed when
9095
# SWIFT_FEATURE_VFSOVERLAY is enabled.
@@ -631,9 +636,9 @@ to use swift_common.compile(include_dev_srch_paths = ...) instead.\
631636
"workspace_name": workspace_name,
632637
} | struct_fields(compile_outputs)
633638

634-
if is_feature_enabled(
639+
if _should_plan_parallel_compilation(
635640
feature_configuration = feature_configuration,
636-
feature_name = SWIFT_FEATURE_COMPILE_IN_PARALLEL,
641+
user_compile_flags = copts,
637642
):
638643
_execute_compile_plan(
639644
actions = actions,
@@ -756,6 +761,23 @@ to use swift_common.compile(include_dev_srch_paths = ...) instead.\
756761
),
757762
)
758763

764+
def _should_plan_parallel_compilation(
765+
feature_configuration,
766+
user_compile_flags):
767+
"""Returns `True` if the compilation should be done in parallel."""
768+
parallel_requested = is_feature_enabled(
769+
feature_configuration = feature_configuration,
770+
feature_name = SWIFT_FEATURE_COMPILE_IN_PARALLEL,
771+
)
772+
773+
# The Swift driver will not emit separate jobs to compile the module and to
774+
# perform codegen if optimization is requested. See
775+
# https://github.com/swiftlang/swift-driver/blob/c647e91574122f2b104d294ab1ec5baadaa1aa95/Sources/SwiftDriver/Jobs/EmitModuleJob.swift#L156-L181.
776+
opt_requested = is_optimization_manually_requested(
777+
user_compile_flags = user_compile_flags,
778+
)
779+
return parallel_requested and not opt_requested
780+
759781
def _execute_compile_plan(
760782
actions,
761783
compile_plan,

swift/internal/features.bzl

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ load(
2020
":feature_names.bzl",
2121
"SWIFT_FEATURE_CACHEABLE_SWIFTMODULES",
2222
"SWIFT_FEATURE_CHECKED_EXCLUSIVITY",
23+
"SWIFT_FEATURE_COMPILE_IN_PARALLEL",
2324
"SWIFT_FEATURE_COVERAGE",
2425
"SWIFT_FEATURE_COVERAGE_PREFIX_MAP",
2526
"SWIFT_FEATURE_DEBUG_PREFIX_MAP",
@@ -169,27 +170,43 @@ def configure_features(
169170
)
170171

171172
def features_for_build_modes(ctx, cpp_fragment = None):
172-
"""Returns a list of Swift toolchain features for current build modes.
173+
"""Returns features to request and disable for current build modes.
173174
174175
This function explicitly breaks the "don't pass `ctx` as an argument"
175176
rule-of-thumb because it is internal and only called from the toolchain
176177
rules, so there is no concern about supporting differing call sites.
177178
178179
Args:
179180
ctx: The current rule context.
180-
cpp_fragment: The Cpp configuration fragment, if available.
181+
cpp_fragment: The `cpp` configuration fragment, if available.
181182
182183
Returns:
183-
A list of Swift toolchain features to enable.
184+
A tuple containing two lists:
185+
186+
1. A list of Swift toolchain features to requested (enable).
187+
2. A list of Swift toolchain features that are unsupported (disabled).
184188
"""
189+
requested_features = []
190+
unsupported_features = []
191+
185192
compilation_mode = ctx.var["COMPILATION_MODE"]
186-
features = []
187-
features.append("swift.{}".format(compilation_mode))
193+
requested_features.append("swift.{}".format(compilation_mode))
188194
if compilation_mode in ("dbg", "fastbuild"):
189-
features.append(SWIFT_FEATURE_ENABLE_TESTING)
195+
requested_features.append(SWIFT_FEATURE_ENABLE_TESTING)
196+
elif compilation_mode == "opt":
197+
# Disable parallel compilation early if we know we're going to be doing
198+
# an optimized compile, because the driver will not emit separate jobs
199+
# unless we also explicitly disable cross-module optimization. See
200+
# https://github.com/swiftlang/swift-driver/blob/c647e91574122f2b104d294ab1ec5baadaa1aa95/Sources/SwiftDriver/Jobs/EmitModuleJob.swift#L156-L181.
201+
unsupported_features.append(SWIFT_FEATURE_COMPILE_IN_PARALLEL)
202+
203+
if ctx.configuration.coverage_enabled:
204+
requested_features.append(SWIFT_FEATURE_COVERAGE)
205+
190206
if cpp_fragment and cpp_fragment.apple_generate_dsym:
191-
features.append(SWIFT_FEATURE_FULL_DEBUG_INFO)
192-
return features
207+
requested_features.append(SWIFT_FEATURE_FULL_DEBUG_INFO)
208+
209+
return requested_features, unsupported_features
193210

194211
def get_cc_feature_configuration(feature_configuration):
195212
"""Returns the C++ feature configuration in a Swift feature configuration.

swift/internal/wmo.bzl renamed to swift/internal/optimization.bzl

Lines changed: 46 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
"""Functionality releated to detecting whole-module optimization."""
15+
"""Detection of various optimization settings."""
1616

1717
load(
1818
":feature_names.bzl",
19+
"SWIFT_FEATURE_COMPILE_IN_PARALLEL",
1920
"SWIFT_FEATURE__NUM_THREADS_0_IN_SWIFTCOPTS",
2021
"SWIFT_FEATURE__WMO_IN_SWIFTCOPTS",
2122
)
@@ -28,29 +29,14 @@ _WMO_FLAGS = {
2829
"-force-single-frontend-invocation": True,
2930
}
3031

31-
def features_from_swiftcopts(swiftcopts):
32-
"""Returns a list of features to enable based on `--swiftcopt` flags.
33-
34-
Since `--swiftcopt` flags are hooked into the action configuration when the
35-
toolchain is configured, it's not possible for individual actions to query
36-
them easily if those flags may determine the nature of outputs (for example,
37-
single- vs. multi-threaded WMO). The toolchain can call this function to map
38-
those flags to private features that can be queried instead.
39-
40-
Args:
41-
swiftcopts: The list of command line flags that were passed using
42-
`--swiftcopt`.
43-
44-
Returns:
45-
A list (possibly empty) of strings denoting feature names that should be
46-
enabled on the toolchain.
47-
"""
48-
features = []
49-
if is_wmo_manually_requested(user_compile_flags = swiftcopts):
50-
features.append(SWIFT_FEATURE__WMO_IN_SWIFTCOPTS)
51-
if find_num_threads_flag_value(user_compile_flags = swiftcopts) == 0:
52-
features.append(SWIFT_FEATURE__NUM_THREADS_0_IN_SWIFTCOPTS)
53-
return features
32+
# Swift command line flags in the `O` group that enable some kind of
33+
# optimization. This explicitly excludes `-Onone`.
34+
_OPT_FLAGS = {
35+
"-O": True,
36+
"-Oplayground": True,
37+
"-Osize": True,
38+
"-Ounchecked": True,
39+
}
5440

5541
def find_num_threads_flag_value(user_compile_flags):
5642
"""Finds the value of the `-num-threads` flag.
@@ -75,6 +61,20 @@ def find_num_threads_flag_value(user_compile_flags):
7561
saw_num_threads = True
7662
return num_threads
7763

64+
def is_optimization_manually_requested(user_compile_flags):
65+
"""Returns `True` if some optimization flag is in the given list of flags.
66+
67+
Args:
68+
user_compile_flags: A list of compiler flags to scan for optimization.
69+
70+
Returns:
71+
True if some optimization is enabled in the given list of flags.
72+
"""
73+
for copt in user_compile_flags:
74+
if copt in _OPT_FLAGS:
75+
return True
76+
return False
77+
7878
def is_wmo_manually_requested(user_compile_flags):
7979
"""Returns `True` if a WMO flag is in the given list of compiler flags.
8080
@@ -89,8 +89,8 @@ def is_wmo_manually_requested(user_compile_flags):
8989
return True
9090
return False
9191

92-
def wmo_features_from_swiftcopts(swiftcopts):
93-
"""Returns a list of features to enable based on `--swiftcopt` flags.
92+
def optimization_features_from_swiftcopts(swiftcopts):
93+
"""Returns features to enable or disable based on `--swiftcopt` flags.
9494
9595
Since `--swiftcopt` flags are hooked into the action configuration when the
9696
toolchain is configured, it's not possible for individual actions to query
@@ -103,15 +103,29 @@ def wmo_features_from_swiftcopts(swiftcopts):
103103
`--swiftcopt`.
104104
105105
Returns:
106-
A list (possibly empty) of strings denoting feature names that should be
107-
enabled on the toolchain.
106+
A tuple containing two lists:
107+
108+
1. A list (possibly empty) of strings denoting feature names that
109+
should be enabled on the toolchain.
110+
2. A list (possibly empty) of strings denoting feature names that
111+
should be disabled on the toolchain.
108112
"""
109-
features = []
113+
requested_features = []
114+
unsupported_features = []
115+
116+
if is_optimization_manually_requested(user_compile_flags = swiftcopts):
117+
# Disable parallel compilation early if we know we're going to be doing
118+
# an optimized compile, because the driver will not emit separate jobs
119+
# unless we also explicitly disable cross-module optimization. See
120+
# https://github.com/swiftlang/swift-driver/blob/c647e91574122f2b104d294ab1ec5baadaa1aa95/Sources/SwiftDriver/Jobs/EmitModuleJob.swift#L156-L181.
121+
unsupported_features.append(SWIFT_FEATURE_COMPILE_IN_PARALLEL)
122+
110123
if is_wmo_manually_requested(user_compile_flags = swiftcopts):
111-
features.append(SWIFT_FEATURE__WMO_IN_SWIFTCOPTS)
124+
requested_features.append(SWIFT_FEATURE__WMO_IN_SWIFTCOPTS)
112125
if find_num_threads_flag_value(user_compile_flags = swiftcopts) == 1:
113-
features.append(SWIFT_FEATURE__NUM_THREADS_0_IN_SWIFTCOPTS)
114-
return features
126+
requested_features.append(SWIFT_FEATURE__NUM_THREADS_0_IN_SWIFTCOPTS)
127+
128+
return requested_features, unsupported_features
115129

116130
def _safe_int(s):
117131
"""Returns the base-10 integer value of `s` or `None` if it is invalid.

swift/toolchains/config/compile_config.bzl

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ load(
9191
"SWIFT_FEATURE__SUPPORTS_V6",
9292
"SWIFT_FEATURE__WMO_IN_SWIFTCOPTS",
9393
)
94+
load(
95+
"//swift/internal:optimization.bzl",
96+
"is_wmo_manually_requested",
97+
)
9498
load(":action_config.bzl", "ActionConfigInfo", "ConfigResultInfo", "add_arg")
9599

96100
# The number of threads to use for WMO builds, using the same number of cores
@@ -99,14 +103,6 @@ load(":action_config.bzl", "ActionConfigInfo", "ConfigResultInfo", "add_arg")
99103
# when an API to obtain this is available.
100104
_DEFAULT_WMO_THREAD_COUNT = 12
101105

102-
# Swift command line flags that enable whole module optimization. (This
103-
# dictionary is used as a set for quick lookup; the values are irrelevant.)
104-
_WMO_FLAGS = {
105-
"-wmo": True,
106-
"-whole-module-optimization": True,
107-
"-force-single-frontend-invocation": True,
108-
}
109-
110106
def compile_action_configs(
111107
*,
112108
additional_objc_copts = [],
@@ -1494,7 +1490,7 @@ def _pcm_developer_framework_paths_configurator(prerequisites, args):
14941490

14951491
def _batch_mode_configurator(prerequisites, args):
14961492
"""Adds flags to enable batch compilation mode."""
1497-
if not _is_wmo_manually_requested(prerequisites.user_compile_flags):
1493+
if not is_wmo_manually_requested(prerequisites.user_compile_flags):
14981494
args.add("-enable-batch-mode")
14991495

15001496
def _c_layering_check_configurator(prerequisites, args):
@@ -2082,25 +2078,11 @@ def _make_wmo_thread_count_configurator(should_check_flags):
20822078
return lambda _prerequisites, args: _add_num_threads(args)
20832079

20842080
def _flag_checking_wmo_thread_count_configurator(prerequisites, args):
2085-
if _is_wmo_manually_requested(prerequisites.user_compile_flags):
2081+
if is_wmo_manually_requested(prerequisites.user_compile_flags):
20862082
_add_num_threads(args)
20872083

20882084
return _flag_checking_wmo_thread_count_configurator
20892085

2090-
def _is_wmo_manually_requested(user_compile_flags):
2091-
"""Returns `True` if a WMO flag is in the given list of compiler flags.
2092-
2093-
Args:
2094-
user_compile_flags: A list of compiler flags to scan for WMO usage.
2095-
2096-
Returns:
2097-
True if WMO is enabled in the given list of flags.
2098-
"""
2099-
for copt in user_compile_flags:
2100-
if copt in _WMO_FLAGS:
2101-
return True
2102-
return False
2103-
21042086
def _exclude_swift_incompatible_define(define):
21052087
"""A `map_each` helper that excludes a define if it is not Swift-compatible.
21062088

swift/toolchains/swift_toolchain.bzl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ load(
6060
"default_features_for_toolchain",
6161
"features_for_build_modes",
6262
)
63+
load("//swift/internal:optimization.bzl", "optimization_features_from_swiftcopts")
6364
load(
6465
"//swift/internal:providers.bzl",
6566
"SwiftCrossImportOverlayInfo",
@@ -71,7 +72,6 @@ load(
7172
"collect_implicit_deps_providers",
7273
"get_swift_executable_for_toolchain",
7374
)
74-
load("//swift/internal:wmo.bzl", "features_from_swiftcopts")
7575
load(
7676
"//swift/toolchains/config:action_config.bzl",
7777
"ActionConfigInfo",
@@ -453,9 +453,9 @@ def _swift_toolchain_impl(ctx):
453453

454454
# Combine build mode features, autoconfigured features, and required
455455
# features.
456+
features_from_swiftcopts, _ = optimization_features_from_swiftcopts(swiftcopts = swiftcopts)
456457
requested_features = (
457-
features_for_build_modes(ctx) +
458-
features_from_swiftcopts(swiftcopts = swiftcopts)
458+
features_for_build_modes(ctx) + features_from_swiftcopts
459459
)
460460
requested_features.extend(default_features_for_toolchain(
461461
target_triple = target_triple,

0 commit comments

Comments
 (0)