Merge pull request #11465 from KingOfBrian/bugfix/SR-964
Warn if the getter is used, but the setter argument is not used
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 22fb3fb..cf1242a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -66,7 +66,11 @@
endif()
option(SWIFT_BUILD_PERF_TESTSUITE
- "Create targets for swift performance benchmarks."
+ "Create in-tree targets for building swift performance benchmarks."
+ FALSE)
+
+option(SWIFT_BUILD_EXTERNAL_PERF_TESTSUITE
+ "Create out-of-tree targets for building swift performance benchmarks."
FALSE)
option(SWIFT_INCLUDE_TESTS "Create targets for building/running tests." TRUE)
@@ -869,22 +873,54 @@
endif()
# Add all of the subdirectories, where we actually do work.
+
+###############
+# PLEASE READ #
+###############
+#
+# We have to include stdlib/ before tools/.
+# Do not move add_subdirectory(stdlib) after add_subdirectory(tools)!
+#
+# We must include stdlib/ before tools/ because stdlib/CMakeLists.txt
+# declares the swift-stdlib-* set of targets. These targets will then
+# implicitly depend on any targets declared with IS_STDLIB or
+# TARGET_LIBRARY.
+#
+# One such library that declares IS_STDLIB is SwiftSyntax, living in
+# tools/SwiftSyntax. If we include stdlib/ after tools/,
+# the swift-stdlib-* set of targets will not have been generated yet,
+# causing the implicit dependency for SwiftSyntax to silently not be
+# created. This then will cause SwiftSyntax to fail to build.
+#
+# https://bugs.swift.org/browse/SR-5975
+add_subdirectory(stdlib)
+
if(SWIFT_INCLUDE_TOOLS)
add_subdirectory(include)
add_subdirectory(lib)
+
+ # Always include this after including stdlib/!
+ # Refer to the large comment above the add_subdirectory(stdlib) call.
+ # https://bugs.swift.org/browse/SR-5975
add_subdirectory(tools)
endif()
add_subdirectory(utils)
-add_subdirectory(stdlib)
if(SWIFT_BUILD_DYNAMIC_STDLIB AND SWIFT_INCLUDE_TESTS)
add_subdirectory(tools/swift-reflection-test)
endif()
-if(SWIFT_BUILD_PERF_TESTSUITE AND "${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
- add_subdirectory(benchmark)
+if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
+ if(SWIFT_BUILD_PERF_TESTSUITE)
+ add_subdirectory(benchmark)
+ endif()
+ if(SWIFT_BUILD_EXTERNAL_PERF_TESTSUITE)
+ include(SwiftExternalBenchmarkBuild)
+ add_external_benchmark_suite()
+ endif()
endif()
+
if(SWIFT_INCLUDE_TESTS)
add_subdirectory(test)
add_subdirectory(unittests)
diff --git a/benchmark/CMakeLists.txt b/benchmark/CMakeLists.txt
index 8012413..fe92ab2 100644
--- a/benchmark/CMakeLists.txt
+++ b/benchmark/CMakeLists.txt
@@ -125,9 +125,16 @@
single-source/XorLoop
)
-set(SWIFT_MULTISOURCE_BENCHES
+set(SWIFT_MULTISOURCE_SWIFT3_BENCHES
+ multi-source/PrimsSplit
)
+set(PrimsSplit_sources
+ multi-source/PrimsSplit/Prims.swift
+ multi-source/PrimsSplit/main.swift)
+
+set(SWIFT_MULTISOURCE_SWIFT4_BENCHES
+)
set(BENCH_DRIVER_LIBRARY_FLAGS)
if (SWIFT_RUNTIME_ENABLE_LEAK_CHECKER)
@@ -231,6 +238,7 @@
message("--")
message("-- Swift Benchmark Suite:")
+message("-- SWIFT_BENCHMARK_BUILT_STANDALONE = ${SWIFT_BENCHMARK_BUILT_STANDALONE}")
message("-- SWIFT_EXEC = ${SWIFT_EXEC}")
message("-- SWIFT_LIBRARY_PATH = ${SWIFT_LIBRARY_PATH}")
message("-- CLANG_EXEC = ${CLANG_EXEC}")
diff --git a/benchmark/cmake/modules/AddSwiftBenchmarkSuite.cmake b/benchmark/cmake/modules/AddSwiftBenchmarkSuite.cmake
index 3a0c547..e56b583 100644
--- a/benchmark/cmake/modules/AddSwiftBenchmarkSuite.cmake
+++ b/benchmark/cmake/modules/AddSwiftBenchmarkSuite.cmake
@@ -1,5 +1,6 @@
include(CMakeParseArguments)
+include(SwiftBenchmarkUtils)
# Run a shell command and assign output to a variable or fail with an error.
# Example usage:
@@ -20,7 +21,7 @@
endfunction(runcmd)
function (add_swift_benchmark_library objfile_out sibfile_out)
- cmake_parse_arguments(BENCHLIB "" "MODULE_PATH;SOURCE_DIR;OBJECT_DIR" "SOURCES;LIBRARY_FLAGS" ${ARGN})
+ cmake_parse_arguments(BENCHLIB "" "MODULE_PATH;SOURCE_DIR;OBJECT_DIR" "SOURCES;LIBRARY_FLAGS;DEPENDS" ${ARGN})
precondition(BENCHLIB_MODULE_PATH)
precondition(BENCHLIB_SOURCE_DIR)
@@ -39,7 +40,7 @@
precondition(objfile_out)
add_custom_command(
OUTPUT "${objfile}"
- DEPENDS ${stdlib_dependencies} ${sources}
+ DEPENDS ${stdlib_dependencies} ${sources} ${BENCHLIB_DEPENDS}
COMMAND "${SWIFT_EXEC}"
${BENCHLIB_LIBRARY_FLAGS}
"-force-single-frontend-invocation"
@@ -58,7 +59,7 @@
add_custom_command(
OUTPUT "${sibfile}"
DEPENDS
- ${stdlib_dependencies} ${sources}
+ ${stdlib_dependencies} ${sources} ${BENCHLIB_DEPENDS}
COMMAND "${SWIFT_EXEC}"
${BENCHLIB_LIBRARY_FLAGS}
"-force-single-frontend-invocation"
@@ -72,6 +73,104 @@
endif()
endfunction()
+function(_construct_sources_for_multibench sources_out objfile_out)
+ cmake_parse_arguments(SOURCEJSONLIST "" "" "SOURCES" ${ARGN})
+
+ set(sources)
+ set(objfiles)
+
+ foreach(source ${SOURCEJSONLIST_SOURCES})
+ list(APPEND sources "${srcdir}/${source}")
+
+ get_filename_component(basename "${source}" NAME_WE)
+ set(objfile "${objdir}/${module_name}/${basename}.o")
+
+ string(CONCAT json "${json}"
+ " \"${srcdir}/${source}\": { \"object\": \"${objfile}\" },\n")
+
+ list(APPEND objfiles "${objfile}")
+ endforeach()
+ string(CONCAT json "${json}" "}")
+ file(WRITE "${objdir}/${module_name}/outputmap.json" ${json})
+ set(${sources_out} ${sources} PARENT_SCOPE)
+ set(${objfile_out} ${objfiles} PARENT_SCOPE)
+endfunction()
+
+# Regular whole-module-compilation: only a single object file is
+# generated.
+function (add_swift_multisource_wmo_benchmark_library objfile_out)
+ cmake_parse_arguments(BENCHLIB "" "MODULE_PATH;SOURCE_DIR;OBJECT_DIR" "SOURCES;LIBRARY_FLAGS;DEPENDS" ${ARGN})
+
+ precondition(BENCHLIB_MODULE_PATH)
+ precondition(BENCHLIB_SOURCE_DIR)
+ precondition(BENCHLIB_OBJECT_DIR)
+ precondition(BENCHLIB_SOURCES)
+
+ set(module_name_path "${BENCHLIB_MODULE_PATH}")
+ get_filename_component(module_name "${module_name_path}" NAME)
+ set(srcdir "${BENCHLIB_SOURCE_DIR}")
+ set(objdir "${BENCHLIB_OBJECT_DIR}")
+
+ set(objfile "${objdir}/${module_name}.o")
+
+ set(sources)
+ foreach(source ${BENCHLIB_SOURCES})
+ list(APPEND sources "${srcdir}/${source}")
+ endforeach()
+
+ add_custom_command(
+ OUTPUT "${objfile}"
+ DEPENDS
+ ${sources} ${BENCHLIB_DEPENDS}
+ COMMAND "${SWIFT_EXEC}"
+ ${BENCHLIB_LIBRARY_FLAGS}
+ "-parse-as-library"
+ "-emit-module" "-module-name" "${module_name}"
+ "-I" "${objdir}"
+ "-o" "${objfile}"
+ ${sources})
+
+ set(${objfile_out} "${objfile}" PARENT_SCOPE)
+endfunction()
+
+function(add_swift_multisource_nonwmo_benchmark_library objfiles_out)
+ cmake_parse_arguments(BENCHLIB "" "MODULE_PATH;SOURCE_DIR;OBJECT_DIR" "SOURCES;LIBRARY_FLAGS;DEPENDS" ${ARGN})
+
+ precondition(BENCHLIB_MODULE_PATH)
+ precondition(BENCHLIB_SOURCE_DIR)
+ precondition(BENCHLIB_OBJECT_DIR)
+ precondition(BENCHLIB_SOURCES)
+
+ set(module_name_path "${BENCHLIB_MODULE_PATH}")
+ get_filename_component(module_name "${module_name_path}" NAME)
+ set(srcdir "${BENCHLIB_SOURCE_DIR}")
+ set(objdir "${BENCHLIB_OBJECT_DIR}")
+
+ set(objfile "${objdir}/${module_name}.o")
+
+ # No whole-module-compilation or multi-threaded compilation.
+ # There is an output object file for each input file. We have to write
+ # an output-map-file to specify the output object file names.
+ set(sources)
+ set(objfiles)
+ _construct_sources_for_multibench(sources objfiles
+ SOURCES ${BENCHLIB_SOURCES})
+
+ add_custom_command(
+ OUTPUT ${objfiles}
+ DEPENDS ${sources} ${BENCHLIB_DEPENDS}
+ COMMAND "${SWIFT_EXEC}"
+ ${BENCHLIB_LIBRARY_FLAGS}
+ "-parse-as-library"
+ "-emit-module-path" "${objdir}/${module_name}.swiftmodule"
+ "-module-name" "${module_name}"
+ "-I" "${objdir}"
+ "-output-file-map" "${objdir}/${module_name}/outputmap.json"
+ ${sources})
+
+ set(${objfiles_out} ${objfiles} PARENT_SCOPE)
+endfunction()
+
function (swift_benchmark_compile_archopts)
cmake_parse_arguments(BENCH_COMPILE_ARCHOPTS "" "PLATFORM;ARCH;OPT" "" ${ARGN})
set(sdk ${${BENCH_COMPILE_ARCHOPTS_PLATFORM}_sdk})
@@ -94,7 +193,6 @@
set(bench_flags "${${benchvar}}")
set(common_options
- "-swift-version" "3" # FIXME: Force Swift 3 version compatibility.
"-c"
"-sdk" "${sdk}"
"-target" "${target}"
@@ -102,6 +200,8 @@
"-${BENCH_COMPILE_ARCHOPTS_OPT}"
"-no-link-objc-runtime"
"-I" "${srcdir}/utils/ObjectiveCTests")
+ set(common_swift3_options ${common_options} "-swift-version" "3")
+ set(common_swift4_options ${common_options} "-swift-version" "4")
# Always optimize the driver modules.
# Note that we compile the driver for Ounchecked also with -Ounchecked
@@ -120,89 +220,47 @@
set(bench_library_sibfiles)
# Build libraries used by the driver and benchmarks.
foreach(module_name_path ${BENCH_LIBRARY_MODULES})
- get_filename_component(module_name "${module_name_path}" NAME)
+ set(sources "${srcdir}/${module_name_path}.swift")
- set(objfile "${objdir}/${module_name}.o")
- set(swiftmodule "${objdir}/${module_name}.swiftmodule")
- set(source "${srcdir}/${module_name_path}.swift")
- list(APPEND bench_library_objects "${objfile}")
- add_custom_command(
- OUTPUT "${objfile}"
- DEPENDS
- ${stdlib_dependencies} "${source}" ${extra_sources}
- COMMAND "${SWIFT_EXEC}"
- ${common_options}
- "-force-single-frontend-invocation"
- "-parse-as-library"
- "-module-name" "${module_name}"
- "-emit-module" "-emit-module-path" "${swiftmodule}"
- "-o" "${objfile}"
- "${source}" ${extra_sources})
+ add_swift_benchmark_library(objfile_out sibfile_out
+ MODULE_PATH "${module_name_path}"
+ SOURCE_DIR "${srcdir}"
+ OBJECT_DIR "${objdir}"
+ SOURCES ${sources}
+ LIBRARY_FLAGS ${common_swift3_options})
+ precondition(objfile_out)
+ list(APPEND bench_library_objects "${objfile_out}")
if (SWIFT_BENCHMARK_EMIT_SIB)
- set(sibfile "${objdir}/${module_name}.sib")
- list(APPEND bench_library_sibfiles "${sibfile}")
- add_custom_command(
- OUTPUT "${sibfile}"
- DEPENDS
- ${stdlib_dependencies} "${srcdir}/${module_name_path}.swift"
- ${extra_sources}
- COMMAND "${SWIFT_EXEC}"
- ${common_options}
- "-force-single-frontend-invocation"
- "-parse-as-library"
- "-module-name" "${module_name}"
- "-emit-sib"
- "-o" "${sibfile}"
- "${source}" ${extra_sources})
+ precondition(sibfile_out)
+ list(APPEND bench_library_sibfiles "${sibfile_out}")
endif()
endforeach()
+ precondition(bench_library_objects)
set(bench_driver_objects)
set(bench_driver_sibfiles)
foreach(module_name_path ${BENCH_DRIVER_LIBRARY_MODULES})
- get_filename_component(module_name "${module_name_path}" NAME)
+ set(sources "${srcdir}/${module_name_path}.swift")
+ get_filename_component(module_name "${module_name_path}" NAME)
if("${module_name}" STREQUAL "DriverUtils")
- set(extra_sources "${srcdir}/utils/ArgParse.swift")
+ list(APPEND sources "${srcdir}/utils/ArgParse.swift")
endif()
- set(objfile "${objdir}/${module_name}.o")
- set(swiftmodule "${objdir}/${module_name}.swiftmodule")
- list(APPEND bench_driver_objects "${objfile}")
- set(source "${srcdir}/${module_name_path}.swift")
- add_custom_command(
- OUTPUT "${objfile}"
- DEPENDS
- ${stdlib_dependencies} ${bench_library_objects} ${source}
- ${extra_sources}
- COMMAND "${SWIFT_EXEC}"
- ${common_options_driver}
- ${BENCH_DRIVER_LIBRARY_FLAGS}
- "-force-single-frontend-invocation"
- "-parse-as-library"
- "-module-name" "${module_name}"
- "-emit-module" "-emit-module-path" "${swiftmodule}"
- "-I" "${objdir}"
- "-o" "${objfile}"
- "${source}" ${extra_sources})
- if(SWIFT_BENCHMARK_EMIT_SIB)
- set(sibfile "${objdir}/${module_name}.sib")
- list(APPEND bench_driver_sibfiles "${sibfile}")
- add_custom_command(
- OUTPUT "${sibfile}"
- DEPENDS
- ${stdlib_dependencies} ${bench_library_objects} ${source}
- ${extra_sources}
- COMMAND "${SWIFT_EXEC}"
- ${common_options_driver}
- ${BENCH_DRIVER_LIBRARY_FLAGS}
- "-force-single-frontend-invocation"
- "-parse-as-library"
- "-module-name" "${module_name}"
- "-emit-sib"
- "-I" "${objdir}"
- "-o" "${sibfile}"
- "${source}" ${extra_sources})
+ set(objfile_out)
+ set(sibfile_out)
+ add_swift_benchmark_library(objfile_out sibfile_out
+ MODULE_PATH "${module_name_path}"
+ SOURCE_DIR "${srcdir}"
+ OBJECT_DIR "${objdir}"
+ SOURCES ${sources}
+ LIBRARY_FLAGS ${common_options_driver} ${BENCH_DRIVER_LIBRARY_FLAGS}
+ DEPENDS ${bench_library_objects})
+ precondition(objfile_out)
+ list(APPEND bench_driver_objects "${objfile_out}")
+ if (SWIFT_BENCHMARK_EMIT_SIB)
+ precondition(sibfile_out)
+ list(APPEND bench_driver_sibfiles "${sibfile_out}")
endif()
endforeach()
@@ -238,7 +296,7 @@
${stdlib_dependencies} ${bench_library_objects}
"${srcdir}/${module_name_path}.swift"
COMMAND "${SWIFT_EXEC}"
- ${common_options}
+ ${common_swift3_options}
${extra_options}
"-parse-as-library"
${bench_flags}
@@ -256,7 +314,7 @@
${stdlib_dependencies} ${bench_library_sibfiles}
"${srcdir}/${module_name_path}.swift"
COMMAND "${SWIFT_EXEC}"
- ${common_options}
+ ${common_swift3_options}
"-parse-as-library"
${bench_flags}
"-module-name" "${module_name}"
@@ -268,67 +326,61 @@
endif()
endforeach()
- foreach(module_name_path ${SWIFT_MULTISOURCE_BENCHES})
+ foreach(module_name_path ${SWIFT_MULTISOURCE_SWIFT3_BENCHES})
get_filename_component(module_name "${module_name_path}" NAME)
if ("${bench_flags}" MATCHES "-whole-module.*" AND
NOT "${bench_flags}" MATCHES "-num-threads.*")
- # Regular whole-module-compilation: only a single object file is
- # generated.
- set(objfile "${objdir}/${module_name}.o")
- list(APPEND SWIFT_BENCH_OBJFILES "${objfile}")
- set(sources)
- foreach(source ${${module_name}_sources})
- list(APPEND sources "${srcdir}/${source}")
- endforeach()
- add_custom_command(
- OUTPUT "${objfile}"
- DEPENDS
- ${stdlib_dependencies} ${bench_library_objects} ${sources}
- COMMAND "${SWIFT_EXEC}"
- ${common_options}
- ${bench_flags}
- "-parse-as-library"
- "-emit-module" "-module-name" "${module_name}"
- "-I" "${objdir}"
- "-o" "${objfile}"
- ${sources})
+ set(objfile_out)
+ add_swift_multisource_wmo_benchmark_library(objfile_out
+ MODULE_PATH "${module_name_path}"
+ SOURCE_DIR "${srcdir}"
+ OBJECT_DIR "${objdir}"
+ SOURCES ${${module_name}_sources}
+ LIBRARY_FLAGS ${common_swift3_options} ${bench_flags}
+ DEPENDS ${bench_library_objects} ${stdlib_dependencies})
+ precondition(objfile_out)
+ list(APPEND SWIFT_BENCH_OBJFILES "${objfile_out}")
else()
+ set(objfiles_out)
+ add_swift_multisource_nonwmo_benchmark_library(objfiles_out
+ MODULE_PATH "${module_name_path}"
+ SOURCE_DIR "${srcdir}"
+ OBJECT_DIR "${objdir}"
+ SOURCES ${${module_name}_sources}
+ LIBRARY_FLAGS ${common_swift3_options} ${bench_flags}
+ DEPENDS ${bench_library_objects} ${stdlib_dependencies})
+ precondition(objfiles_out)
+ list(APPEND SWIFT_BENCH_OBJFILES ${objfiles_out})
+ endif()
+ endforeach()
- # No whole-module-compilation or multi-threaded compilation.
- # There is an output object file for each input file. We have to write
- # an output-map-file to specify the output object file names.
- set(sources)
- set(objfiles)
- set(json "{\n")
- foreach(source ${${module_name}_sources})
- list(APPEND sources "${srcdir}/${source}")
+ foreach(module_name_path ${SWIFT_MULTISOURCE_SWIFT4_BENCHES})
+ get_filename_component(module_name "${module_name_path}" NAME)
- get_filename_component(basename "${source}" NAME_WE)
- set(objfile "${objdir}/${module_name}/${basename}.o")
-
- string(CONCAT json "${json}"
- " \"${srcdir}/${source}\": { \"object\": \"${objfile}\" },\n")
-
- list(APPEND objfiles "${objfile}")
- list(APPEND SWIFT_BENCH_OBJFILES "${objfile}")
- endforeach()
- string(CONCAT json "${json}" "}")
- file(WRITE "${objdir}/${module_name}/outputmap.json" ${json})
-
- add_custom_command(
- OUTPUT ${objfiles}
- DEPENDS
- ${stdlib_dependencies} ${bench_library_objects} ${sources}
- COMMAND "${SWIFT_EXEC}"
- ${common_options}
- ${bench_flags}
- "-parse-as-library"
- "-emit-module-path" "${objdir}/${module_name}.swiftmodule"
- "-module-name" "${module_name}"
- "-I" "${objdir}"
- "-output-file-map" "${objdir}/${module_name}/outputmap.json"
- ${sources})
+ if ("${bench_flags}" MATCHES "-whole-module.*" AND
+ NOT "${bench_flags}" MATCHES "-num-threads.*")
+ set(objfile_out)
+ add_swift_multisource_wmo_benchmark_library(objfile_out
+ MODULE_PATH "${module_name_path}"
+ SOURCE_DIR "${srcdir}"
+ OBJECT_DIR "${objdir}"
+ SOURCES ${${module_name}_sources}
+ LIBRARY_FLAGS ${common_swift4_options} ${bench_flags}
+ DEPENDS ${bench_library_objects} ${stdlib_dependencies})
+ precondition(objfile_out)
+ list(APPEND SWIFT_BENCH_OBJFILES "${objfile_out}")
+ else()
+ set(objfiles_out)
+ add_swift_multisource_nonwmo_benchmark_library(objfiles_out
+ MODULE_PATH "${module_name_path}"
+ SOURCE_DIR "${srcdir}"
+ OBJECT_DIR "${objdir}"
+ SOURCES ${${module_name}_sources}
+ LIBRARY_FLAGS ${common_swift4_options} ${bench_flags}
+ DEPENDS ${bench_library_objects} ${stdlib_dependencies})
+ precondition(objfiles_out)
+ list(APPEND SWIFT_BENCH_OBJFILES ${objfiles_out})
endif()
endforeach()
@@ -342,7 +394,7 @@
${bench_library_sibfiles} ${bench_driver_sibfiles}
${SWIFT_BENCH_SIBFILES} "${source}"
COMMAND "${SWIFT_EXEC}"
- ${common_options}
+ ${common_swift3_options}
"-force-single-frontend-invocation"
"-emit-module" "-module-name" "${module_name}"
"-I" "${objdir}"
@@ -436,7 +488,16 @@
list(APPEND platform_executables ${new_output_exec})
endforeach()
- set(executable_target "swift-benchmark-${SWIFT_BENCHMARK_COMPILE_PLATFORM}-${arch}")
+ # If we are building standalone, we add the -external suffix to all of our
+ # cmake target names. This enables the main swift build to simple create
+ # -external targets and forward them via AddExternalProject to the
+ # standalone benchmark project. The reason why this is necessary is that we
+ # want to be able to support in-tree and out-of-tree benchmark builds at the
+ # same time implying that we need some sort of way to distinguish the
+ # in-tree (which don't have the suffix) from the out of tree target (which
+ # do).
+ translate_flag(SWIFT_BENCHMARK_BUILT_STANDALONE "-external" external)
+ set(executable_target "swift-benchmark-${SWIFT_BENCHMARK_COMPILE_PLATFORM}-${arch}${external}")
add_custom_target("${executable_target}"
DEPENDS ${platform_executables})
diff --git a/benchmark/cmake/modules/SwiftBenchmarkUtils.cmake b/benchmark/cmake/modules/SwiftBenchmarkUtils.cmake
new file mode 100644
index 0000000..9c5e6a0
--- /dev/null
+++ b/benchmark/cmake/modules/SwiftBenchmarkUtils.cmake
@@ -0,0 +1,45 @@
+
+include(CMakeParseArguments)
+
+function(precondition var)
+ cmake_parse_arguments(
+ PRECONDITION # prefix
+ "NEGATE" # options
+ "MESSAGE" # single-value args
+ "" # multi-value args
+ ${ARGN})
+
+ if (PRECONDITION_NEGATE)
+ if (${var})
+ if (PRECONDITION_MESSAGE)
+ message(FATAL_ERROR "Error! ${PRECONDITION_MESSAGE}")
+ else()
+ message(FATAL_ERROR "Error! Variable ${var} is true or not empty. The value of ${var} is ${${var}}.")
+ endif()
+ endif()
+ else()
+ if (NOT ${var})
+ if (PRECONDITION_MESSAGE)
+ message(FATAL_ERROR "Error! ${PRECONDITION_MESSAGE}")
+ else()
+ message(FATAL_ERROR "Error! Variable ${var} is false, empty or not set.")
+ endif()
+ endif()
+ endif()
+endfunction()
+
+# Translate a yes/no variable to the presence of a given string in a
+# variable.
+#
+# Usage:
+# translate_flag(is_set flag_name var_name)
+#
+# If is_set is true, sets ${var_name} to ${flag_name}. Otherwise,
+# unsets ${var_name}.
+function(translate_flag is_set flag_name var_name)
+ if(${is_set})
+ set("${var_name}" "${flag_name}" PARENT_SCOPE)
+ else()
+ set("${var_name}" "" PARENT_SCOPE)
+ endif()
+endfunction()
diff --git a/benchmark/multi-source/PrimsSplit/Prims.swift b/benchmark/multi-source/PrimsSplit/Prims.swift
new file mode 100644
index 0000000..57d1f6d
--- /dev/null
+++ b/benchmark/multi-source/PrimsSplit/Prims.swift
@@ -0,0 +1,214 @@
+//===--- Prims.swift ------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 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
+//
+//===----------------------------------------------------------------------===//
+
+// The test implements Prim's algorithm for minimum spanning tree building.
+// http://en.wikipedia.org/wiki/Prim%27s_algorithm
+
+// This class implements array-based heap (priority queue).
+// It is used to store edges from nodes in spanning tree to nodes outside of it.
+// We are interested only in the edges with the smallest costs, so if there are
+// several edges pointing to the same node, we keep only one from them. Thus,
+// it is enough to record this node instead.
+// We maintain a map (node index in graph)->(node index in heap) to be able to
+// update the heap fast when we add a new node to the tree.
+import TestsUtils
+
+class PriorityQueue {
+ final var heap: Array<EdgeCost>
+ final var graphIndexToHeapIndexMap: Array<Int?>
+
+ // Create heap for graph with NUM nodes.
+ init(Num: Int) {
+ heap = Array<EdgeCost>()
+ graphIndexToHeapIndexMap = Array<Int?>(repeating:nil, count: Num)
+ }
+
+ func isEmpty() -> Bool {
+ return heap.isEmpty
+ }
+
+ // Insert element N to heap, maintaining the heap property.
+ func insert(_ n: EdgeCost) {
+ let ind: Int = heap.count
+ heap.append(n)
+ graphIndexToHeapIndexMap[n.to] = heap.count - 1
+ bubbleUp(ind)
+ }
+
+ // Insert element N if in's not in the heap, or update its cost if the new
+ // value is less than the existing one.
+ func insertOrUpdate(_ n: EdgeCost) {
+ let id = n.to
+ let c = n.cost
+ if let ind = graphIndexToHeapIndexMap[id] {
+ if heap[ind].cost <= c {
+ // We don't need an edge with a bigger cost
+ return
+ }
+ heap[ind].cost = c
+ heap[ind].from = n.from
+ bubbleUp(ind)
+ } else {
+ insert(n)
+ }
+ }
+
+ // Restore heap property by moving element at index IND up.
+ // This is needed after insertion, and after decreasing an element's cost.
+ func bubbleUp(_ ind: Int) {
+ var ind = ind
+ let c = heap[ind].cost
+ while (ind != 0) {
+ let p = getParentIndex(ind)
+ if heap[p].cost > c {
+ Swap(p, with: ind)
+ ind = p
+ } else {
+ break
+ }
+ }
+ }
+
+ // Pop minimum element from heap and restore the heap property after that.
+ func pop() -> EdgeCost? {
+ if (heap.isEmpty) {
+ return nil
+ }
+ Swap(0, with:heap.count-1)
+ let r = heap.removeLast()
+ graphIndexToHeapIndexMap[r.to] = nil
+ bubbleDown(0)
+ return r
+ }
+
+ // Restore heap property by moving element at index IND down.
+ // This is needed after removing an element, and after increasing an
+ // element's cost.
+ func bubbleDown(_ ind: Int) {
+ var ind = ind
+ let n = heap.count
+ while (ind < n) {
+ let l = getLeftChildIndex(ind)
+ let r = getRightChildIndex(ind)
+ if (l >= n) {
+ break
+ }
+ var min: Int
+ if (r < n && heap[r].cost < heap[l].cost) {
+ min = r
+ } else {
+ min = l
+ }
+ if (heap[ind].cost <= heap[min].cost) {
+ break
+ }
+ Swap(ind, with: min)
+ ind = min
+ }
+ }
+
+ // Swaps elements I and J in the heap and correspondingly updates
+ // graphIndexToHeapIndexMap.
+ func Swap(_ i: Int, with j : Int) {
+ if (i == j) {
+ return
+ }
+ (heap[i], heap[j]) = (heap[j], heap[i])
+ let (I, J) = (heap[i].to, heap[j].to)
+ (graphIndexToHeapIndexMap[I], graphIndexToHeapIndexMap[J]) =
+ (graphIndexToHeapIndexMap[J], graphIndexToHeapIndexMap[I])
+ }
+
+ // Dumps the heap.
+ func dump() {
+ print("QUEUE")
+ for nodeCost in heap {
+ let to: Int = nodeCost.to
+ let from: Int = nodeCost.from
+ let cost: Double = nodeCost.cost
+ print("(\(from)->\(to), \(cost))")
+ }
+ }
+
+ func getLeftChildIndex(_ index : Int) -> Int {
+ return index*2 + 1
+ }
+ func getRightChildIndex(_ index : Int) -> Int {
+ return (index + 1)*2
+ }
+ func getParentIndex(_ childIndex : Int) -> Int {
+ return (childIndex - 1)/2
+ }
+}
+
+struct GraphNode {
+ var id: Int
+ var adjList: Array<Int>
+
+ init(i : Int) {
+ id = i
+ adjList = Array<Int>()
+ }
+}
+
+struct EdgeCost {
+ var to: Int
+ var cost: Double
+ var from: Int
+}
+
+struct Edge : Equatable {
+ var start: Int
+ var end: Int
+}
+
+func ==(lhs: Edge, rhs: Edge) -> Bool {
+ return lhs.start == rhs.start && lhs.end == rhs.end
+}
+
+extension Edge : Hashable {
+ var hashValue: Int {
+ get {
+ return start.hashValue ^ end.hashValue
+ }
+ }
+}
+
+func Prims(_ graph : Array<GraphNode>, _ fun : (Int, Int) -> Double) -> Array<Int?> {
+ var treeEdges = Array<Int?>(repeating:nil, count:graph.count)
+
+ let queue = PriorityQueue(Num:graph.count)
+ // Make the minimum spanning tree root its own parent for simplicity.
+ queue.insert(EdgeCost(to: 0, cost: 0.0, from: 0))
+
+ // Take an element with the smallest cost from the queue and add its
+ // neighbors to the queue if their cost was updated
+ while !queue.isEmpty() {
+ // Add an edge with minimum cost to the spanning tree
+ let e = queue.pop()!
+ let newnode = e.to
+ // Add record about the edge newnode->e.from to treeEdges
+ treeEdges[newnode] = e.from
+
+ // Check all adjacent nodes and add edges, ending outside the tree, to the
+ // queue. If the queue already contains an edge to an adjacent node, we
+ // replace existing one with the new one in case the new one costs less.
+ for adjNodeIndex in graph[newnode].adjList {
+ if treeEdges[adjNodeIndex] != nil {
+ continue
+ }
+ let newcost = fun(newnode, graph[adjNodeIndex].id)
+ queue.insertOrUpdate(EdgeCost(to: adjNodeIndex, cost: newcost, from: newnode))
+ }
+ }
+ return treeEdges
+}
diff --git a/benchmark/multi-source/PrimsSplit/README.md b/benchmark/multi-source/PrimsSplit/README.md
new file mode 100644
index 0000000..9987e9c
--- /dev/null
+++ b/benchmark/multi-source/PrimsSplit/README.md
@@ -0,0 +1,4 @@
+
+This test is just a split version of Prims.swift. The reason why this is here is
+to provide at least 1 multi-source benchmark for the purpose of validating that
+the multi-source benchmarks can build successfully.
diff --git a/benchmark/multi-source/PrimsSplit/main.swift b/benchmark/multi-source/PrimsSplit/main.swift
new file mode 100644
index 0000000..0609e92
--- /dev/null
+++ b/benchmark/multi-source/PrimsSplit/main.swift
@@ -0,0 +1,555 @@
+//===--- main.swift -------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 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 TestsUtils
+
+@inline(never)
+public func run_PrimsSplit(_ N: Int) {
+ for _ in 1...5*N {
+ let nodes : [Int] = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+ 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
+ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
+ 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
+ 93, 94, 95, 96, 97, 98, 99 ]
+
+ // Prim's algorithm is designed for undirected graphs.
+ // Due to that, in our set all the edges are paired, i.e. for any
+ // edge (start, end, C) there is also an edge (end, start, C).
+ let edges : [(Int, Int, Double)] = [
+ (26, 47, 921),
+ (20, 25, 971),
+ (92, 59, 250),
+ (33, 55, 1391),
+ (78, 39, 313),
+ (7, 25, 637),
+ (18, 19, 1817),
+ (33, 41, 993),
+ (64, 41, 926),
+ (88, 86, 574),
+ (93, 15, 1462),
+ (86, 33, 1649),
+ (37, 35, 841),
+ (98, 51, 1160),
+ (15, 30, 1125),
+ (65, 78, 1052),
+ (58, 12, 1273),
+ (12, 17, 285),
+ (45, 61, 1608),
+ (75, 53, 545),
+ (99, 48, 410),
+ (97, 0, 1303),
+ (48, 17, 1807),
+ (1, 54, 1491),
+ (15, 34, 807),
+ (94, 98, 646),
+ (12, 69, 136),
+ (65, 11, 983),
+ (63, 83, 1604),
+ (78, 89, 1828),
+ (61, 63, 845),
+ (18, 36, 1626),
+ (68, 52, 1324),
+ (14, 50, 690),
+ (3, 11, 943),
+ (21, 68, 914),
+ (19, 44, 1762),
+ (85, 80, 270),
+ (59, 92, 250),
+ (86, 84, 1431),
+ (19, 18, 1817),
+ (52, 68, 1324),
+ (16, 29, 1108),
+ (36, 80, 395),
+ (67, 18, 803),
+ (63, 88, 1717),
+ (68, 21, 914),
+ (75, 82, 306),
+ (49, 82, 1292),
+ (73, 45, 1876),
+ (89, 82, 409),
+ (45, 47, 272),
+ (22, 83, 597),
+ (61, 12, 1791),
+ (44, 68, 1229),
+ (50, 51, 917),
+ (14, 53, 355),
+ (77, 41, 138),
+ (54, 21, 1870),
+ (93, 70, 1582),
+ (76, 2, 1658),
+ (83, 73, 1162),
+ (6, 1, 482),
+ (11, 65, 983),
+ (81, 90, 1024),
+ (19, 1, 970),
+ (8, 58, 1131),
+ (60, 42, 477),
+ (86, 29, 258),
+ (69, 59, 903),
+ (34, 15, 807),
+ (37, 2, 1451),
+ (7, 73, 754),
+ (47, 86, 184),
+ (67, 17, 449),
+ (18, 67, 803),
+ (25, 4, 595),
+ (3, 31, 1337),
+ (64, 31, 1928),
+ (9, 43, 237),
+ (83, 63, 1604),
+ (47, 45, 272),
+ (86, 88, 574),
+ (87, 74, 934),
+ (98, 94, 646),
+ (20, 1, 642),
+ (26, 92, 1344),
+ (18, 17, 565),
+ (47, 11, 595),
+ (10, 59, 1558),
+ (2, 76, 1658),
+ (77, 74, 1277),
+ (42, 60, 477),
+ (80, 36, 395),
+ (35, 23, 589),
+ (50, 37, 203),
+ (6, 96, 481),
+ (78, 65, 1052),
+ (1, 52, 127),
+ (65, 23, 1932),
+ (46, 51, 213),
+ (59, 89, 89),
+ (15, 93, 1462),
+ (69, 3, 1305),
+ (17, 37, 1177),
+ (30, 3, 193),
+ (9, 15, 818),
+ (75, 95, 977),
+ (86, 47, 184),
+ (10, 12, 1736),
+ (80, 27, 1010),
+ (12, 10, 1736),
+ (86, 1, 1958),
+ (60, 12, 1240),
+ (43, 71, 683),
+ (91, 65, 1519),
+ (33, 86, 1649),
+ (62, 26, 1773),
+ (1, 13, 1187),
+ (2, 10, 1018),
+ (91, 29, 351),
+ (69, 12, 136),
+ (43, 9, 237),
+ (29, 86, 258),
+ (17, 48, 1807),
+ (31, 64, 1928),
+ (68, 61, 1936),
+ (76, 38, 1724),
+ (1, 6, 482),
+ (53, 14, 355),
+ (51, 50, 917),
+ (54, 13, 815),
+ (19, 29, 883),
+ (35, 87, 974),
+ (70, 96, 511),
+ (23, 35, 589),
+ (39, 69, 1588),
+ (93, 73, 1093),
+ (13, 73, 435),
+ (5, 60, 1619),
+ (42, 41, 1523),
+ (66, 58, 1596),
+ (1, 67, 431),
+ (17, 67, 449),
+ (30, 95, 906),
+ (71, 43, 683),
+ (5, 87, 190),
+ (12, 78, 891),
+ (30, 97, 402),
+ (28, 17, 1131),
+ (7, 97, 1356),
+ (58, 66, 1596),
+ (20, 37, 1294),
+ (73, 76, 514),
+ (54, 8, 613),
+ (68, 35, 1252),
+ (92, 32, 701),
+ (3, 90, 652),
+ (99, 46, 1576),
+ (13, 54, 815),
+ (20, 87, 1390),
+ (36, 18, 1626),
+ (51, 26, 1146),
+ (2, 23, 581),
+ (29, 7, 1558),
+ (88, 59, 173),
+ (17, 1, 1071),
+ (37, 49, 1011),
+ (18, 6, 696),
+ (88, 33, 225),
+ (58, 38, 802),
+ (87, 50, 1744),
+ (29, 91, 351),
+ (6, 71, 1053),
+ (45, 24, 1720),
+ (65, 91, 1519),
+ (37, 50, 203),
+ (11, 3, 943),
+ (72, 65, 1330),
+ (45, 50, 339),
+ (25, 20, 971),
+ (15, 9, 818),
+ (14, 54, 1353),
+ (69, 95, 393),
+ (8, 66, 1213),
+ (52, 2, 1608),
+ (50, 14, 690),
+ (50, 45, 339),
+ (1, 37, 1273),
+ (45, 93, 1650),
+ (39, 78, 313),
+ (1, 86, 1958),
+ (17, 28, 1131),
+ (35, 33, 1667),
+ (23, 2, 581),
+ (51, 66, 245),
+ (17, 54, 924),
+ (41, 49, 1629),
+ (60, 5, 1619),
+ (56, 93, 1110),
+ (96, 13, 461),
+ (25, 7, 637),
+ (11, 69, 370),
+ (90, 3, 652),
+ (39, 71, 1485),
+ (65, 51, 1529),
+ (20, 6, 1414),
+ (80, 85, 270),
+ (73, 83, 1162),
+ (0, 97, 1303),
+ (13, 33, 826),
+ (29, 71, 1788),
+ (33, 12, 461),
+ (12, 58, 1273),
+ (69, 39, 1588),
+ (67, 75, 1504),
+ (87, 20, 1390),
+ (88, 97, 526),
+ (33, 88, 225),
+ (95, 69, 393),
+ (2, 52, 1608),
+ (5, 25, 719),
+ (34, 78, 510),
+ (53, 99, 1074),
+ (33, 35, 1667),
+ (57, 30, 361),
+ (87, 58, 1574),
+ (13, 90, 1030),
+ (79, 74, 91),
+ (4, 86, 1107),
+ (64, 94, 1609),
+ (11, 12, 167),
+ (30, 45, 272),
+ (47, 91, 561),
+ (37, 17, 1177),
+ (77, 49, 883),
+ (88, 23, 1747),
+ (70, 80, 995),
+ (62, 77, 907),
+ (18, 4, 371),
+ (73, 93, 1093),
+ (11, 47, 595),
+ (44, 23, 1990),
+ (20, 0, 512),
+ (3, 69, 1305),
+ (82, 3, 1815),
+ (20, 88, 368),
+ (44, 45, 364),
+ (26, 51, 1146),
+ (7, 65, 349),
+ (71, 39, 1485),
+ (56, 88, 1954),
+ (94, 69, 1397),
+ (12, 28, 544),
+ (95, 75, 977),
+ (32, 90, 789),
+ (53, 1, 772),
+ (54, 14, 1353),
+ (49, 77, 883),
+ (92, 26, 1344),
+ (17, 18, 565),
+ (97, 88, 526),
+ (48, 80, 1203),
+ (90, 32, 789),
+ (71, 6, 1053),
+ (87, 35, 974),
+ (55, 90, 1808),
+ (12, 61, 1791),
+ (1, 96, 328),
+ (63, 10, 1681),
+ (76, 34, 871),
+ (41, 64, 926),
+ (42, 97, 482),
+ (25, 5, 719),
+ (23, 65, 1932),
+ (54, 1, 1491),
+ (28, 12, 544),
+ (89, 10, 108),
+ (27, 33, 143),
+ (67, 1, 431),
+ (32, 45, 52),
+ (79, 33, 1871),
+ (6, 55, 717),
+ (10, 58, 459),
+ (67, 39, 393),
+ (10, 4, 1808),
+ (96, 6, 481),
+ (1, 19, 970),
+ (97, 7, 1356),
+ (29, 16, 1108),
+ (1, 53, 772),
+ (30, 15, 1125),
+ (4, 6, 634),
+ (6, 20, 1414),
+ (88, 56, 1954),
+ (87, 64, 1950),
+ (34, 76, 871),
+ (17, 12, 285),
+ (55, 59, 321),
+ (61, 68, 1936),
+ (50, 87, 1744),
+ (84, 44, 952),
+ (41, 33, 993),
+ (59, 18, 1352),
+ (33, 27, 143),
+ (38, 32, 1210),
+ (55, 70, 1264),
+ (38, 58, 802),
+ (1, 20, 642),
+ (73, 13, 435),
+ (80, 48, 1203),
+ (94, 64, 1609),
+ (38, 28, 414),
+ (73, 23, 1113),
+ (78, 12, 891),
+ (26, 62, 1773),
+ (87, 43, 579),
+ (53, 6, 95),
+ (59, 95, 285),
+ (88, 63, 1717),
+ (17, 5, 633),
+ (66, 8, 1213),
+ (41, 42, 1523),
+ (83, 22, 597),
+ (95, 30, 906),
+ (51, 65, 1529),
+ (17, 49, 1727),
+ (64, 87, 1950),
+ (86, 4, 1107),
+ (37, 98, 1102),
+ (32, 92, 701),
+ (60, 94, 198),
+ (73, 98, 1749),
+ (4, 18, 371),
+ (96, 70, 511),
+ (7, 29, 1558),
+ (35, 37, 841),
+ (27, 64, 384),
+ (12, 33, 461),
+ (36, 38, 529),
+ (69, 16, 1183),
+ (91, 47, 561),
+ (85, 29, 1676),
+ (3, 82, 1815),
+ (69, 58, 1579),
+ (93, 45, 1650),
+ (97, 42, 482),
+ (37, 1, 1273),
+ (61, 4, 543),
+ (96, 1, 328),
+ (26, 0, 1993),
+ (70, 64, 878),
+ (3, 30, 193),
+ (58, 69, 1579),
+ (4, 25, 595),
+ (31, 3, 1337),
+ (55, 6, 717),
+ (39, 67, 393),
+ (78, 34, 510),
+ (75, 67, 1504),
+ (6, 53, 95),
+ (51, 79, 175),
+ (28, 91, 1040),
+ (89, 78, 1828),
+ (74, 93, 1587),
+ (45, 32, 52),
+ (10, 2, 1018),
+ (49, 37, 1011),
+ (63, 61, 845),
+ (0, 20, 512),
+ (1, 17, 1071),
+ (99, 53, 1074),
+ (37, 20, 1294),
+ (10, 89, 108),
+ (33, 92, 946),
+ (23, 73, 1113),
+ (23, 88, 1747),
+ (49, 17, 1727),
+ (88, 20, 368),
+ (21, 54, 1870),
+ (70, 93, 1582),
+ (59, 88, 173),
+ (32, 38, 1210),
+ (89, 59, 89),
+ (23, 44, 1990),
+ (38, 76, 1724),
+ (30, 57, 361),
+ (94, 60, 198),
+ (59, 10, 1558),
+ (55, 64, 1996),
+ (12, 11, 167),
+ (36, 24, 1801),
+ (97, 30, 402),
+ (52, 1, 127),
+ (58, 87, 1574),
+ (54, 17, 924),
+ (93, 74, 1587),
+ (24, 36, 1801),
+ (2, 37, 1451),
+ (91, 28, 1040),
+ (59, 55, 321),
+ (69, 11, 370),
+ (8, 54, 613),
+ (29, 85, 1676),
+ (44, 19, 1762),
+ (74, 79, 91),
+ (93, 56, 1110),
+ (58, 10, 459),
+ (41, 50, 1559),
+ (66, 51, 245),
+ (80, 19, 1838),
+ (33, 79, 1871),
+ (76, 73, 514),
+ (98, 37, 1102),
+ (45, 44, 364),
+ (16, 69, 1183),
+ (49, 41, 1629),
+ (19, 80, 1838),
+ (71, 57, 500),
+ (6, 4, 634),
+ (64, 27, 384),
+ (84, 86, 1431),
+ (5, 17, 633),
+ (96, 88, 334),
+ (87, 5, 190),
+ (70, 21, 1619),
+ (55, 33, 1391),
+ (10, 63, 1681),
+ (11, 62, 1339),
+ (33, 13, 826),
+ (64, 70, 878),
+ (65, 72, 1330),
+ (70, 55, 1264),
+ (64, 55, 1996),
+ (50, 41, 1559),
+ (46, 99, 1576),
+ (88, 96, 334),
+ (51, 20, 868),
+ (73, 7, 754),
+ (80, 70, 995),
+ (44, 84, 952),
+ (29, 19, 883),
+ (59, 69, 903),
+ (57, 53, 1575),
+ (90, 13, 1030),
+ (28, 38, 414),
+ (12, 60, 1240),
+ (85, 58, 573),
+ (90, 55, 1808),
+ (4, 10, 1808),
+ (68, 44, 1229),
+ (92, 33, 946),
+ (90, 81, 1024),
+ (53, 75, 545),
+ (45, 30, 272),
+ (41, 77, 138),
+ (21, 70, 1619),
+ (45, 73, 1876),
+ (35, 68, 1252),
+ (13, 96, 461),
+ (53, 57, 1575),
+ (82, 89, 409),
+ (28, 61, 449),
+ (58, 61, 78),
+ (27, 80, 1010),
+ (61, 58, 78),
+ (38, 36, 529),
+ (80, 30, 397),
+ (18, 59, 1352),
+ (62, 11, 1339),
+ (95, 59, 285),
+ (51, 98, 1160),
+ (6, 18, 696),
+ (30, 80, 397),
+ (69, 94, 1397),
+ (58, 85, 573),
+ (48, 99, 410),
+ (51, 46, 213),
+ (57, 71, 500),
+ (91, 30, 104),
+ (65, 7, 349),
+ (79, 51, 175),
+ (47, 26, 921),
+ (4, 61, 543),
+ (98, 73, 1749),
+ (74, 77, 1277),
+ (61, 28, 449),
+ (58, 8, 1131),
+ (61, 45, 1608),
+ (74, 87, 934),
+ (71, 29, 1788),
+ (30, 91, 104),
+ (13, 1, 1187),
+ (0, 26, 1993),
+ (82, 49, 1292),
+ (43, 87, 579),
+ (24, 45, 1720),
+ (20, 51, 868),
+ (77, 62, 907),
+ (82, 75, 306),
+ ]
+
+ // Prepare graph and edge->cost map
+ var graph = Array<GraphNode>()
+ for n in nodes {
+ graph.append(GraphNode(i: n))
+ }
+ var map = Dictionary<Edge, Double>()
+ for tup in edges {
+ map[Edge(start: tup.0, end: tup.1)] = tup.2
+ graph[tup.0].adjList.append(tup.1)
+ }
+
+ // Find spanning tree
+ let treeEdges = Prims(graph, { (start: Int, end: Int) in
+ return map[Edge(start: start, end: end)]!
+ })
+
+ // Compute its cost in order to check results
+ var cost = 0.0
+ for i in 1..<treeEdges.count {
+ if let n = treeEdges[i] { cost += map[Edge(start: n, end: i)]! }
+ }
+ CheckResults(Int(cost) == 49324)
+ }
+}
diff --git a/benchmark/utils/DriverUtils.swift b/benchmark/utils/DriverUtils.swift
index 103529b..f0eba2d 100644
--- a/benchmark/utils/DriverUtils.swift
+++ b/benchmark/utils/DriverUtils.swift
@@ -26,7 +26,9 @@
var mean: UInt64 = 0
var sd: UInt64 = 0
var median: UInt64 = 0
+
init() {}
+
init(delim: String, sampleCount: UInt64, min: UInt64, max: UInt64, mean: UInt64, sd: UInt64, median: UInt64) {
self.delim = delim
self.sampleCount = sampleCount
@@ -56,21 +58,21 @@
let index: Int
let f: (Int) -> ()
let run: Bool
- let tags: [BenchmarkCategories]
+ let tags: [BenchmarkCategory]
}
// Legacy test dictionaries.
-public var precommitTests: [String : ((Int) -> (), [BenchmarkCategories])] = [:]
-public var otherTests: [String : ((Int) -> (), [BenchmarkCategories])] = [:]
-public var stringTests: [String : ((Int) -> (), [BenchmarkCategories])] = [:]
+public var precommitTests: [String : ((Int) -> (), [BenchmarkCategory])] = [:]
+public var otherTests: [String : ((Int) -> (), [BenchmarkCategory])] = [:]
+public var stringTests: [String : ((Int) -> (), [BenchmarkCategory])] = [:]
// We should migrate to a collection of BenchmarkInfo.
public var registeredBenchmarks = [TestsUtils.BenchmarkInfo]()
enum TestAction {
- case Run
- case ListTests
- case Fail(String)
+ case run
+ case listTests
+ case fail(String)
}
struct TestConfig {
@@ -81,7 +83,7 @@
var filters = [String]()
/// The tag that we want to run
- var tags = Set<BenchmarkCategories>()
+ var tags = Set<BenchmarkCategory>()
/// The scalar multiple of the amount of times a test should be run. This
/// enables one to cause tests to run for N iterations longer than they
@@ -123,24 +125,24 @@
]
let maybeBenchArgs: Arguments? = parseArgs(validOptions)
if maybeBenchArgs == nil {
- return .Fail("Failed to parse arguments")
+ return .fail("Failed to parse arguments")
}
let benchArgs = maybeBenchArgs!
filters = benchArgs.positionalArgs
if let x = benchArgs.optionalArgsMap["--iter-scale"] {
- if x.isEmpty { return .Fail("--iter-scale requires a value") }
+ if x.isEmpty { return .fail("--iter-scale requires a value") }
iterationScale = Int(x)!
}
if let x = benchArgs.optionalArgsMap["--num-iters"] {
- if x.isEmpty { return .Fail("--num-iters requires a value") }
+ if x.isEmpty { return .fail("--num-iters requires a value") }
fixedNumIters = numericCast(Int(x)!)
}
if let x = benchArgs.optionalArgsMap["--num-samples"] {
- if x.isEmpty { return .Fail("--num-samples requires a value") }
+ if x.isEmpty { return .fail("--num-samples requires a value") }
numSamples = Int(x)!
}
@@ -150,75 +152,16 @@
}
if let x = benchArgs.optionalArgsMap["--delim"] {
- if x.isEmpty { return .Fail("--delim requires a value") }
+ if x.isEmpty { return .fail("--delim requires a value") }
delim = x
}
if let x = benchArgs.optionalArgsMap["--tags"] {
- if x.isEmpty { return .Fail("--tags requires a value") }
- if x.contains("cpubench") {
- tags.insert(BenchmarkCategories.cpubench)
+ if x.isEmpty { return .fail("--tags requires a value") }
+ guard let cat = BenchmarkCategory(rawValue: x) else {
+ return .fail("Unknown benchmark category: '\(x)'")
}
- if x.contains("unstable") {
- tags.insert(BenchmarkCategories.unstable)
- }
- if x.contains("validation") {
- tags.insert(BenchmarkCategories.validation)
- }
- if x.contains("api") {
- tags.insert(BenchmarkCategories.api)
- }
- if x.contains("Array") {
- tags.insert(BenchmarkCategories.Array)
- }
- if x.contains("String") {
- tags.insert(BenchmarkCategories.String)
- }
- if x.contains("Dictionary") {
- tags.insert(BenchmarkCategories.Dictionary)
- }
- if x.contains("Codable") {
- tags.insert(BenchmarkCategories.Codable)
- }
- if x.contains("Set") {
- tags.insert(BenchmarkCategories.Set)
- }
- if x.contains("sdk") {
- tags.insert(BenchmarkCategories.sdk)
- }
- if x.contains("runtime") {
- tags.insert(BenchmarkCategories.runtime)
- }
- if x.contains("refcount") {
- tags.insert(BenchmarkCategories.refcount)
- }
- if x.contains("metadata") {
- tags.insert(BenchmarkCategories.metadata)
- }
- if x.contains("abstraction") {
- tags.insert(BenchmarkCategories.abstraction)
- }
- if x.contains("safetychecks") {
- tags.insert(BenchmarkCategories.safetychecks)
- }
- if x.contains("exceptions") {
- tags.insert(BenchmarkCategories.exceptions)
- }
- if x.contains("bridging") {
- tags.insert(BenchmarkCategories.bridging)
- }
- if x.contains("concurrency") {
- tags.insert(BenchmarkCategories.concurrency)
- }
- if x.contains("algorithm") {
- tags.insert(BenchmarkCategories.algorithm)
- }
- if x.contains("miniapplication") {
- tags.insert(BenchmarkCategories.miniapplication)
- }
- if x.contains("regression") {
- tags.insert(BenchmarkCategories.regression)
- }
+ tags.insert(cat)
}
if let _ = benchArgs.optionalArgsMap["--run-all"] {
@@ -227,32 +170,32 @@
if let x = benchArgs.optionalArgsMap["--sleep"] {
if x.isEmpty {
- return .Fail("--sleep requires a non-empty integer value")
+ return .fail("--sleep requires a non-empty integer value")
}
let v: Int? = Int(x)
if v == nil {
- return .Fail("--sleep requires a non-empty integer value")
+ return .fail("--sleep requires a non-empty integer value")
}
afterRunSleep = v!
}
if let _ = benchArgs.optionalArgsMap["--list"] {
- return .ListTests
+ return .listTests
}
if let _ = benchArgs.optionalArgsMap["--registered"] {
onlyRegistered = true
}
- return .Run
+ return .run
}
mutating func findTestsToRun() {
- var allTests: [(key: String, value: ((Int) -> (), [BenchmarkCategories]))]
+ var allTests: [(key: String, value: ((Int) -> (), [BenchmarkCategory]))]
if onlyRegistered {
allTests = registeredBenchmarks.map {
- bench -> (key: String, value: ((Int) -> (), [BenchmarkCategories])) in
+ bench -> (key: String, value: ((Int) -> (), [BenchmarkCategory])) in
(bench.name, (bench.runFunction, bench.tags))
}
// FIXME: for now unstable/extra benchmarks are not registered at all, but
@@ -261,7 +204,7 @@
}
else {
allTests = [precommitTests, otherTests, stringTests]
- .map { dictionary -> [(key: String, value: ((Int) -> (), [BenchmarkCategories]))] in
+ .map { dictionary -> [(key: String, value: ((Int) -> (), [BenchmarkCategory]))] in
Array(dictionary).sorted { $0.key < $1.key } } // by name
.flatMap { $0 }
}
@@ -466,48 +409,48 @@
func runBenchmarks(_ c: TestConfig) {
let units = "us"
print("#\(c.delim)TEST\(c.delim)SAMPLES\(c.delim)MIN(\(units))\(c.delim)MAX(\(units))\(c.delim)MEAN(\(units))\(c.delim)SD(\(units))\(c.delim)MEDIAN(\(units))")
- var SumBenchResults = BenchResults()
- SumBenchResults.sampleCount = 0
+ var sumBenchResults = BenchResults()
+ sumBenchResults.sampleCount = 0
for t in c.tests {
if !t.run {
continue
}
- let BenchIndex = t.index
- let BenchName = t.name
- let BenchFunc = t.f
- let results = runBench(BenchName, BenchFunc, c)
- print("\(BenchIndex)\(c.delim)\(BenchName)\(c.delim)\(results.description)")
+ let benchIndex = t.index
+ let benchName = t.name
+ let benchFunc = t.f
+ let results = runBench(benchName, benchFunc, c)
+ print("\(benchIndex)\(c.delim)\(benchName)\(c.delim)\(results.description)")
fflush(stdout)
- SumBenchResults.min += results.min
- SumBenchResults.max += results.max
- SumBenchResults.mean += results.mean
- SumBenchResults.sampleCount += 1
+ sumBenchResults.min += results.min
+ sumBenchResults.max += results.max
+ sumBenchResults.mean += results.mean
+ sumBenchResults.sampleCount += 1
// Don't accumulate SD and Median, as simple sum isn't valid for them.
// TODO: Compute SD and Median for total results as well.
- // SumBenchResults.sd += results.sd
- // SumBenchResults.median += results.median
+ // sumBenchResults.sd += results.sd
+ // sumBenchResults.median += results.median
}
print("")
- print("Totals\(c.delim)\(SumBenchResults.description)")
+ print("Totals\(c.delim)\(sumBenchResults.description)")
}
public func main() {
var config = TestConfig()
switch (config.processArguments()) {
- case let .Fail(msg):
+ case let .fail(msg):
// We do this since we need an autoclosure...
fatalError("\(msg)")
- case .ListTests:
+ case .listTests:
config.findTestsToRun()
print("Enabled Tests\(config.delim)Tags")
for t in config.tests where t.run == true {
print("\(t.name)\(config.delim)\(t.tags)")
}
- case .Run:
+ case .run:
config.findTestsToRun()
printRunInfo(config)
runBenchmarks(config)
diff --git a/benchmark/utils/TestsUtils.swift b/benchmark/utils/TestsUtils.swift
index fd9ab99..107260e 100644
--- a/benchmark/utils/TestsUtils.swift
+++ b/benchmark/utils/TestsUtils.swift
@@ -16,7 +16,7 @@
import Darwin
#endif
-public enum BenchmarkCategories : CustomStringConvertible {
+public enum BenchmarkCategory : String {
// Validation "micro" benchmarks test a specific operation or critical path that
// we know is important to measure.
case validation
@@ -65,40 +65,21 @@
// reimplementing or call into code paths that have known opportunities for
// significant optimization.
case cpubench
-
- public var description : String {
- switch self {
- case .cpubench: return "cpubench"
- case .unstable: return "unstable"
- case .validation: return "validation"
- case .api: return "api"
- case .Array: return "Array"
- case .String: return "String"
- case .Dictionary: return "Dictionary"
- case .Codable: return "Codable"
- case .Set: return "Set"
- case .sdk: return "sdk"
- case .runtime: return "runtime"
- case .refcount: return "refcount"
- case .metadata: return "metadata"
- case .abstraction: return "abstraction"
- case .safetychecks: return "safetychecks"
- case .exceptions: return "exceptions"
- case .bridging: return "bridging"
- case .concurrency: return "concurrency"
- case .algorithm: return "algorithm"
- case .miniapplication: return "miniapplication"
- case .regression: return "regression"
- }
- }
}
public struct BenchmarkInfo {
+ /// The name of the benchmark that should be displayed by the harness.
public var name: String
- public var runFunction: (Int) -> ()
- public var tags: [BenchmarkCategories]
- public init(name: String, runFunction: @escaping (Int) -> (), tags: [BenchmarkCategories]) {
+ /// A function that invokes the specific benchmark routine.
+ public var runFunction: (Int) -> ()
+
+ /// A set of category tags that describe this benchmark. This is used by the
+ /// harness to allow for easy slicing of the set of benchmarks along tag
+ /// boundaries, e.x.: run all string benchmarks or ref count benchmarks, etc.
+ public var tags: [BenchmarkCategory]
+
+ public init(name: String, runFunction: @escaping (Int) -> (), tags: [BenchmarkCategory]) {
self.name = name
self.runFunction = runFunction
self.tags = tags
diff --git a/benchmark/utils/main.swift b/benchmark/utils/main.swift
index 88b7326..2c6287e 100644
--- a/benchmark/utils/main.swift
+++ b/benchmark/utils/main.swift
@@ -90,6 +90,7 @@
import Prefix
import PrefixWhile
import Prims
+import PrimsSplit
import ProtocolDispatch
import ProtocolDispatch2
import RC4
@@ -141,10 +142,10 @@
@inline(__always)
private func addTo(
- _ testSuite: inout [String : ((Int) -> (), [BenchmarkCategories])],
+ _ testSuite: inout [String : ((Int) -> (), [BenchmarkCategory])],
_ name: String,
_ function: @escaping (Int) -> (),
- _ tags: [BenchmarkCategories] = []
+ _ tags: [BenchmarkCategory] = []
) {
testSuite[name] = (function, tags)
}
@@ -402,6 +403,7 @@
addTo(&precommitTests, "PrefixWhileSequence", run_PrefixWhileSequence, [.validation, .api, .abstraction])
addTo(&precommitTests, "PrefixWhileSequenceLazy", run_PrefixWhileSequenceLazy, [.validation, .api, .abstraction])
addTo(&precommitTests, "Prims", run_Prims, [.validation, .algorithm])
+addTo(&precommitTests, "PrimsSplit", run_PrimsSplit, [.validation, .algorithm])
addTo(&precommitTests, "ProtocolDispatch", run_ProtocolDispatch, [.validation, .abstraction])
addTo(&precommitTests, "ProtocolDispatch2", run_ProtocolDispatch2, [.validation, .abstraction])
addTo(&precommitTests, "RC4", run_RC4, [.validation, .algorithm])
diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake
index 9741821..5145017 100644
--- a/cmake/modules/AddSwift.cmake
+++ b/cmake/modules/AddSwift.cmake
@@ -1,5 +1,6 @@
include(SwiftList)
include(SwiftXcodeSupport)
+include(SwiftWindowsSupport)
# SWIFTLIB_DIR is the directory in the build tree where Swift resource files
# should be placed. Note that $CMAKE_CFG_INTDIR expands to "." for
@@ -240,6 +241,9 @@
list(APPEND result "-D_CRT_USE_BUILTIN_OFFSETOF")
# TODO(compnerd) permit building for different families
list(APPEND result "-D_CRT_USE_WINAPI_FAMILY_DESKTOP_APP")
+ if("${CFLAGS_ARCH}" MATCHES arm)
+ list(APPEND result "-D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE")
+ endif()
# TODO(compnerd) handle /MT
list(APPEND result "-D_DLL")
# NOTE: We assume that we are using VS 2015 U2+
@@ -354,6 +358,8 @@
# options. This causes conflicts.
list(APPEND result "-nostdlib")
endif()
+ swift_windows_lib_for_arch(${LFLAGS_ARCH} ${LFLAGS_ARCH}_LIB)
+ list(APPEND library_search_directories ${${LFLAGS_ARCH}_LIB})
elseif("${LFLAGS_SDK}" STREQUAL "HAIKU")
list(APPEND result "-lbsd" "-latomic" "-Wl,-Bsymbolic")
elseif("${LFLAGS_SDK}" STREQUAL "ANDROID")
@@ -723,6 +729,13 @@
endif()
if("${SWIFTLIB_SINGLE_SDK}" STREQUAL "WINDOWS")
+ swift_windows_include_for_arch(${SWIFTLIB_SINGLE_ARCHITECTURE} SWIFTLIB_INCLUDE)
+ foreach(directory ${SWIFTLIB_INCLUDE})
+ list(APPEND SWIFTLIB_SINGLE_SWIFT_COMPILE_FLAGS -Xfrontend;-I${directory})
+ endforeach()
+ if("${SWIFTLIB_SINGLE_ARCHITECTURE}" MATCHES arm)
+ list(APPEND SWIFTLIB_SINGLE_SWIFT_COMPILE_FLAGS -Xcc;-D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE)
+ endif()
list(APPEND SWIFTLIB_SINGLE_SWIFT_COMPILE_FLAGS -Xfrontend;-autolink-library;-Xfrontend;oldnames)
# TODO(compnerd) handle /MT and /MTd
if("${CMAKE_BUILD_TYPE}" STREQUAL "RELEASE")
@@ -833,6 +846,11 @@
endif()
endif()
+ if("${SWIFTLIB_SINGLE_SDK}" STREQUAL "WINDOWS")
+ swift_windows_include_for_arch(${SWIFTLIB_SINGLE_ARCHITECTURE} SWIFTLIB_INCLUDE)
+ target_include_directories("${target}" SYSTEM PRIVATE ${SWIFTLIB_INCLUDE})
+ endif()
+
if("${SWIFTLIB_SINGLE_SDK}" STREQUAL "WINDOWS" AND NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
if("${libkind}" STREQUAL "SHARED")
# Each dll has an associated .lib (import library); since we may be
diff --git a/cmake/modules/SwiftConfigureSDK.cmake b/cmake/modules/SwiftConfigureSDK.cmake
index 12ccac7..a69c8e7 100644
--- a/cmake/modules/SwiftConfigureSDK.cmake
+++ b/cmake/modules/SwiftConfigureSDK.cmake
@@ -5,12 +5,22 @@
# built for each variant.
set(SWIFT_CONFIGURED_SDKS)
+include(SwiftWindowsSupport)
+
# Report the given SDK to the user.
function(_report_sdk prefix)
message(STATUS "${SWIFT_SDK_${prefix}_NAME} SDK:")
if("${prefix}" STREQUAL "WINDOWS")
- message(STATUS " INCLUDE: $ENV{INCLUDE}")
- message(STATUS " LIB: $ENV{LIB}")
+ message(STATUS " UCRT Version: $ENV{UCRTVersion}")
+ message(STATUS " UCRT SDK Dir: $ENV{UniversalCRTSdkDir}")
+ message(STATUS " VC Dir: $ENV{VCToolsInstallDir}")
+
+ foreach(arch ${SWIFT_SDK_${prefix}_ARCHITECTURES})
+ swift_windows_include_for_arch(${arch} ${arch}_INCLUDE)
+ swift_windows_lib_for_arch(${arch} ${arch}_LIB)
+ message(STATUS " ${arch} INCLUDE: ${${arch}_INCLUDE}")
+ message(STATUS " ${arch} LIB: ${${arch}_LIB}")
+ endforeach()
else()
message(STATUS " Path: ${SWIFT_SDK_${prefix}_PATH}")
endif()
diff --git a/cmake/modules/SwiftExternalBenchmarkBuild.cmake b/cmake/modules/SwiftExternalBenchmarkBuild.cmake
new file mode 100644
index 0000000..64db306
--- /dev/null
+++ b/cmake/modules/SwiftExternalBenchmarkBuild.cmake
@@ -0,0 +1,89 @@
+
+include(CMakeParseArguments)
+include(LLVMExternalProjectUtils)
+include(SwiftUtils)
+
+# This is the name of the target on the parent cmake side that is associated
+# with an external project target.
+#
+# If LLVMExternalProjectUtils refactors its external target code, so we can
+# easily add individual forwarded targets with different dependencies, this can
+# be removed.
+function(compute_external_target_name target_name_out target)
+ string(REPLACE ":" ";" target_list ${target})
+ list(GET target_list 0 target)
+ list(LENGTH target_list target_list_len)
+ if(${target_list_len} GREATER 1)
+ list(GET target_list 1 target_name)
+ else()
+ set(target_name "${target}")
+ endif()
+
+ set(${target_name_out} "${target_name}" PARENT_SCOPE)
+endfunction()
+
+function(compute_stdlib_dependencies stdlib_dependencies_out platform)
+ foreach(stdlib_dependency ${UNIVERSAL_LIBRARY_NAMES_${platform}})
+ string(FIND "${stdlib_dependency}" "Unittest" find_output)
+ if("${find_output}" STREQUAL "-1")
+ list(APPEND stdlib_dependencies "${stdlib_dependency}")
+ endif()
+ endforeach()
+ set(${stdlib_dependencies_out} "${stdlib_dependencies}" PARENT_SCOPE)
+endfunction()
+
+set(ONLY_PLATFORMS "macosx" "iphoneos" "appletvos" "watchos")
+
+function (get_platform_from_target target_platform_out target)
+ foreach (platform ${ONLY_PLATFORMS})
+ string(FIND "${target}" "${platform}" FOUND_TARGET_PLATFORM)
+ if (NOT FOUND_TARGET_PLATFORM)
+ continue()
+ endif()
+
+ set(${target_platform_out} "${platform}" PARENT_SCOPE)
+ break()
+ endforeach()
+endfunction()
+
+function (compute_target_stdlib_dependencies dependencies_out target)
+ get_platform_from_target(target_platform ${target})
+ precondition(target_platform
+ MESSAGE "Failed to find a platform for ${target_platform}")
+ compute_stdlib_dependencies(stdlib_dependencies ${target_platform})
+ set(${dependencies_out} ${stdlib_dependencies} PARENT_SCOPE)
+endfunction()
+
+function (add_external_benchmark_suite)
+ set(name swift-benchmark)
+ set(src_dir ${SWIFT_SOURCE_DIR}/benchmark)
+ set(bin_dir ${SWIFT_BINARY_DIR}/external-benchmark/binary)
+ set(stamp_dir ${SWIFT_BINARY_DIR}/external-benchmark/stamps)
+ set(prefix_dir ${SWIFT_BINARY_DIR}/external-benchmark/prefix)
+
+ set(bench_targets Benchmark_O Benchmark_Onone Benchmark_Ounchecked)
+ set(library_targets swift-benchmark-macosx-x86_64-external)
+
+ set(all_stdlib_dependencies)
+ foreach (target ${library_targets})
+ compute_target_stdlib_dependencies(stdlib_dependencies ${target})
+ precondition(stdlib_dependencies)
+ # Add dependencies from all of our stdlib dependencies to
+ # swift-bench-configure. This will ensure the stdlib is ready to be poked at
+ # in the configure script if we ever want to do so.
+ list(APPEND all_stdlib_dependencies ${stdlib_dependencies})
+ endforeach()
+
+ llvm_ExternalProject_add(swift-bench ${src_dir}
+ SOURCE_DIR ${src_dir}
+ EXCLUDE_FROM_ALL
+ DEPENDS swift ${all_stdlib_dependencies}
+ EXTRA_TARGETS ${bench_targets} ${library_targets}
+ CMAKE_ARGS
+ -DSWIFT_EXEC=${SWIFT_BINARY_DIR}/bin/swiftc
+ -DSWIFT_LIBRARY_PATH=${SWIFT_BINARY_DIR}/lib/swift
+ -DCMAKE_C_COMPILER=${PATH_TO_CLANG_BUILD}/bin/clang
+ -DCMAKE_CXX_COMPILER=${PATH_TO_CLANG_BUILD}/bin/clang++
+ PASSTHROUGH_PREFIXES SWIFT_BENCHMARK
+ )
+endfunction()
diff --git a/cmake/modules/SwiftWindowsSupport.cmake b/cmake/modules/SwiftWindowsSupport.cmake
new file mode 100644
index 0000000..8fd49b4
--- /dev/null
+++ b/cmake/modules/SwiftWindowsSupport.cmake
@@ -0,0 +1,60 @@
+
+include(SwiftUtils)
+
+function(swift_windows_arch_spelling arch var)
+ if(${arch} STREQUAL i686)
+ set(${var} x86 PARENT_SCOPE)
+ elseif(${arch} STREQUAL x86_64)
+ set(${var} x64 PARENT_SCOPE)
+ elseif(${arch} STREQUAL armv7)
+ set(${var} arm PARENT_SCOPE)
+ elseif(${arch} STREQUAL aarch64)
+ set(${var} arm64 PARENT_SCOPE)
+ else()
+ message(FATAL_ERROR "do not know MSVC spelling for ARCH: `${arch}`")
+ endif()
+endfunction()
+
+function(swift_verify_windows_environment_variables)
+ set(VCToolsInstallDir $ENV{VCToolsInstallDir})
+ set(UniversalCRTSdkDir $ENV{UniversalCRTSdkDir})
+ set(UCRTVersion $ENV{UCRTVersion})
+
+ precondition(VCToolsInstallDir
+ MESSAGE
+ "VCToolsInstallDir environment variable must be set")
+ precondition(UniversalCRTSdkDir
+ MESSAGE
+ "UniversalCRTSdkDir environment variable must be set")
+ precondition(UCRTVersion
+ MESSAGE
+ "UCRTVersion environment variable must be set")
+endfunction()
+
+function(swift_windows_include_for_arch arch var)
+ swift_verify_windows_environment_variables()
+
+ set(paths
+ "$ENV{VCToolsInstallDir}/include"
+ "$ENV{UniversalCRTSdkDir}/Include/$ENV{UCRTVersion}/ucrt"
+ "$ENV{UniversalCRTSdkDir}/Include/$ENV{UCRTVersion}/um"
+ "$ENV{UniversalCRTSdkDir}/Include/$ENV{UCRTVersion}/shared")
+ set(${var} ${paths} PARENT_SCOPE)
+endfunction()
+
+function(swift_windows_lib_for_arch arch var)
+ swift_verify_windows_environment_variables()
+ swift_windows_arch_spelling(${arch} ARCH)
+
+ set(paths)
+ if(${ARCH} STREQUAL x86)
+ list(APPEND paths "$ENV{VCToolsInstallDir}/Lib")
+ else()
+ list(APPEND paths "$ENV{VCToolsInstallDir}/Lib/${ARCH}")
+ endif()
+ list(APPEND paths
+ "$ENV{UniversalCRTSdkDir}/Lib/$ENV{UCRTVersion}/ucrt/${ARCH}"
+ "$ENV{UniversalCRTSdkDir}/Lib/$ENV{UCRTVersion}/um/${ARCH}")
+ set(${var} ${paths} PARENT_SCOPE)
+endfunction()
+
diff --git a/docs/SIL.rst b/docs/SIL.rst
index 7d71939..3cd82a8 100644
--- a/docs/SIL.rst
+++ b/docs/SIL.rst
@@ -167,7 +167,7 @@
%2 = struct_extract %0 : $Point, #Point.x
%3 = struct_extract %0 : $Point, #Point.y
%4 = apply %1(%2, %3) : $(Double, Double) -> Double
- %5 = return %4 : Double
+ return %4 : Double
}
// Define a SIL vtable. This matches dynamically-dispatched method
@@ -4625,7 +4625,7 @@
sil-type 'in' sil-operand 'to'
sil-type 'in' sil-operand
- %1 = unconditional_checked_cast_addr $A in %0 : $*@thick A to $B in $*@thick B
+ unconditional_checked_cast_addr $A in %0 : $*@thick A to $B in $*@thick B
// $A and $B must be both addresses
// %1 will be of type $*B
// $A is destroyed during the conversion. There is no implicit copy.
diff --git a/docs/Windows.md b/docs/Windows.md
index 8b65abf..387dc71 100644
--- a/docs/Windows.md
+++ b/docs/Windows.md
@@ -11,18 +11,18 @@
Windows 10 SDK at revision 10.10.586.
```
-export WINKIT_ROOT=".../Windows Kits/10"
-export VC_ROOT=".../Microsoft Visual Studio 14.0/VC"
-export INCLUDE='${VC_ROOT}/include;${WINKIT_ROOT}/Include/10.0.10586.0/ucrt;${WINKIT_ROOT}/Include/10.0.10586.0/um;${WINKIT_ROOT}/Include/10.0.10586.0/shared'
-export LIB='${VC_ROOT}/lib;${WINKIT_ROOT}/Lib/10.0.10586.0/ucrt/x86;${WINKIT_ROOT}/Lib/10.0.10586.0/um/x86'
+# Visual Studio 2015 does not have VCToolsInstallDir, use VCINSTALLDIR's value
+export UCRTVersion=10.0.10586.0
+export UniversalCRTSdkDir=".../Windows Kits/10"
+export VCToolsInstallDir=".../Microsoft Visual Studio/2017/Community"
```
### 2. Setup `visualc` and `ucrt` modules
The `visualc.modulemap` located at
`swift/stdlib/public/Platform/visualc.modulemap` needs to be copied into
-`${VC_ROOT}/include`. The `ucrt.modulemap` located at
+`${VCToolsInstallDir}/include`. The `ucrt.modulemap` located at
`swift/stdlib/public/Platform/ucrt.modulemap` needs to be copied into
-`${WINKIT_ROOT}/Include/10.0.10586.0/ucrt`.
+`${UniversalCRTSdkDir}/Include/${UCRTVersion}/ucrt`.
### 3. Configure the runtime to be built with the just built clang
Ensure that we use the tools from the just built LLVM and clang tools to build
diff --git a/include/swift/ABI/MetadataValues.h b/include/swift/ABI/MetadataValues.h
index 1d53b34..0259ba7 100644
--- a/include/swift/ABI/MetadataValues.h
+++ b/include/swift/ABI/MetadataValues.h
@@ -305,11 +305,9 @@
/// Flags in a generic nominal type descriptor.
class GenericParameterDescriptorFlags {
- typedef uint32_t int_type;
+ typedef uint16_t int_type;
enum : int_type {
- HasParent = 0x01,
- HasGenericParent = 0x02,
- HasVTable = 0x04,
+ HasVTable = 0x0004,
};
int_type Data;
@@ -317,38 +315,11 @@
public:
constexpr GenericParameterDescriptorFlags() : Data(0) {}
- constexpr GenericParameterDescriptorFlags withHasParent(bool b) const {
- return GenericParameterDescriptorFlags(b ? (Data | HasParent)
- : (Data & ~HasParent));
- }
-
- constexpr GenericParameterDescriptorFlags withHasGenericParent(bool b) const {
- return GenericParameterDescriptorFlags(b ? (Data | HasGenericParent)
- : (Data & ~HasGenericParent));
- }
-
constexpr GenericParameterDescriptorFlags withHasVTable(bool b) const {
return GenericParameterDescriptorFlags(b ? (Data | HasVTable)
: (Data & ~HasVTable));
}
- /// Does this type have a lexical parent type?
- ///
- /// For class metadata, if this is true, the storage for the parent type
- /// appears immediately prior to the first generic argument. Other
- /// metadata always have a slot for their parent type.
- bool hasParent() const {
- return Data & HasParent;
- }
-
- /// Given that this type has a parent type, is that type generic? If so,
- /// it forms part of the key distinguishing this metadata from other
- /// metadata, and the parent metadata will be the first argument to
- /// the generic metadata access function.
- bool hasGenericParent() const {
- return Data & HasGenericParent;
- }
-
/// If this type is a class, does it have a vtable? If so, the number
/// of vtable entries immediately follows the generic requirement
/// descriptor.
diff --git a/include/swift/AST/Attr.def b/include/swift/AST/Attr.def
index 359a7bd..19937a3 100644
--- a/include/swift/AST/Attr.def
+++ b/include/swift/AST/Attr.def
@@ -259,8 +259,8 @@
// FIXME: Replace with improved @available attribute.
SIMPLE_DECL_ATTR(_versioned, Versioned,
OnFunc | OnVar | OnSubscript | OnConstructor |
- OnStruct | OnEnum | OnClass | OnProtocol |
- LongAttribute | UserInaccessible,
+ OnDestructor | OnStruct | OnEnum | OnClass |
+ OnProtocol | LongAttribute | UserInaccessible,
64)
SIMPLE_DECL_ATTR(discardableResult, DiscardableResult,
diff --git a/include/swift/AST/DiagnosticsCommon.def b/include/swift/AST/DiagnosticsCommon.def
index fb17f8c..70fd091 100644
--- a/include/swift/AST/DiagnosticsCommon.def
+++ b/include/swift/AST/DiagnosticsCommon.def
@@ -82,6 +82,9 @@
NOTE(note_typo_candidate,none,
"did you mean '%0'?", (StringRef))
+NOTE(profile_read_error,none,
+ "failed to load profile data '%0': '%1'", (StringRef, StringRef))
+
#ifndef DIAG_NO_UNDEF
# if defined(DIAG)
# undef DIAG
diff --git a/include/swift/AST/DiagnosticsDriver.def b/include/swift/AST/DiagnosticsDriver.def
index 8fea22f..a589010 100644
--- a/include/swift/AST/DiagnosticsDriver.def
+++ b/include/swift/AST/DiagnosticsDriver.def
@@ -133,6 +133,9 @@
WARNING(verify_debug_info_requires_debug_option,none,
"ignoring '-verify-debug-info'; no debug info is being generated", ())
+ERROR(error_profile_missing,none,
+ "no profdata file exists at '%0'", (StringRef))
+
#ifndef DIAG_NO_UNDEF
# if defined(DIAG)
# undef DIAG
diff --git a/include/swift/AST/DiagnosticsParse.def b/include/swift/AST/DiagnosticsParse.def
index b6260cf..aab6948 100644
--- a/include/swift/AST/DiagnosticsParse.def
+++ b/include/swift/AST/DiagnosticsParse.def
@@ -511,6 +511,8 @@
"SIL instructions must be at the start of a line", ())
ERROR(expected_equal_in_sil_instr,none,
"expected '=' in SIL instruction", ())
+ERROR(wrong_result_count_in_sil_instr,none,
+ "wrong number of results for SIL instruction, expected %0", (unsigned))
ERROR(expected_sil_instr_opcode,none,
"expected SIL instruction opcode", ())
ERROR(expected_tok_in_sil_instr,none,
diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def
index 736c72f..c8af8d0 100644
--- a/include/swift/AST/DiagnosticsSema.def
+++ b/include/swift/AST/DiagnosticsSema.def
@@ -333,7 +333,7 @@
ERROR(cannot_convert_default_arg_value_protocol,none,
"default argument value of type %0 does not conform to %1", (Type,Type))
ERROR(cannot_convert_default_arg_value_nil,none,
- "nil default argument value of cannot be converted to type %0", (Type))
+ "nil default argument value cannot be converted to type %0", (Type))
ERROR(cannot_convert_argument_value,none,
"cannot convert value of type %0 to expected argument type %1",
diff --git a/include/swift/AST/GenericSignatureBuilder.h b/include/swift/AST/GenericSignatureBuilder.h
index ddf8ebe..94dafa3 100644
--- a/include/swift/AST/GenericSignatureBuilder.h
+++ b/include/swift/AST/GenericSignatureBuilder.h
@@ -769,16 +769,6 @@
/// \c TypeRepr.
Inferred,
- /// A requirement inferred from part of the signature of a declaration
- /// but for which we don't want to produce warnings, e.g., the result
- /// type of a generic function:
- ///
- /// func f<T>() -> Set<T> { ... } // infers T: Hashable, but don't warn
- ///
- /// This is a root requirement source, which can be described by a
- /// \c TypeRepr.
- QuietlyInferred,
-
/// A requirement for the creation of the requirement signature of a
/// protocol.
///
@@ -889,7 +879,6 @@
case Explicit:
case Inferred:
- case QuietlyInferred:
case NestedTypeNameMatch:
case ConcreteTypeBinding:
case Superclass:
@@ -930,7 +919,6 @@
switch (kind) {
case Explicit:
case Inferred:
- case QuietlyInferred:
case RequirementSignatureSelf:
case NestedTypeNameMatch:
case ConcreteTypeBinding:
@@ -1052,8 +1040,7 @@
/// inferred from some part of a generic declaration's signature, e.g., the
/// parameter or result type of a generic function.
static const RequirementSource *forInferred(PotentialArchetype *root,
- const TypeRepr *typeRepr,
- bool quietly);
+ const TypeRepr *typeRepr);
/// Retrieve a requirement source representing the requirement signature
/// computation for a protocol.
@@ -1150,7 +1137,7 @@
/// Whether the requirement is inferred or derived from an inferred
/// requirement.
- bool isInferredRequirement(bool includeQuietInferred) const;
+ bool isInferredRequirement() const;
/// Classify the kind of this source for diagnostic purposes.
unsigned classifyDiagKind() const;
@@ -1272,8 +1259,6 @@
Explicit,
/// An inferred requirement source lacking a root.
Inferred,
- /// A quietly inferred requirement source lacking a root.
- QuietlyInferred,
/// A requirement source augmented by an abstract protocol requirement
AbstractProtocol,
/// A requirement source for a nested-type-name match introduced by
@@ -1319,9 +1304,8 @@
return { Explicit, requirementRepr };
}
- static FloatingRequirementSource forInferred(const TypeRepr *typeRepr,
- bool quietly) {
- return { quietly? QuietlyInferred : Inferred, typeRepr };
+ static FloatingRequirementSource forInferred(const TypeRepr *typeRepr) {
+ return { Inferred, typeRepr };
}
static FloatingRequirementSource viaProtocolRequirement(
diff --git a/include/swift/AST/IRGenOptions.h b/include/swift/AST/IRGenOptions.h
index 4c9c6b1..a72fbc5 100644
--- a/include/swift/AST/IRGenOptions.h
+++ b/include/swift/AST/IRGenOptions.h
@@ -139,9 +139,6 @@
/// Frameworks that we should not autolink against.
SmallVector<std::string, 1> DisableAutolinkFrameworks;
- /// Instrument code to generate profiling information.
- unsigned GenerateProfile : 1;
-
/// Print the LLVM inline tree at the end of the LLVM pass pipeline.
unsigned PrintInlineTree : 1;
@@ -168,6 +165,12 @@
/// Enable use of the swiftcall calling convention.
unsigned UseSwiftCall : 1;
+ /// Instrument code to generate profiling information.
+ unsigned GenerateProfile : 1;
+
+ /// Path to the profdata file to be used for PGO, or the empty string.
+ std::string UseProfile = "";
+
/// List of backend command-line options for -embed-bitcode.
std::vector<uint8_t> CmdArgs;
@@ -181,11 +184,11 @@
DebugInfoKind(IRGenDebugInfoKind::None), UseJIT(false),
DisableLLVMOptzns(false), DisableLLVMARCOpts(false),
DisableLLVMSLPVectorizer(false), DisableFPElim(true), Playground(false),
- EmitStackPromotionChecks(false), GenerateProfile(false),
- PrintInlineTree(false), EmbedMode(IRGenEmbedMode::None),
- HasValueNamesSetting(false), ValueNames(false),
- EnableReflectionMetadata(true), EnableReflectionNames(true),
- UseIncrementalLLVMCodeGen(true), UseSwiftCall(false), CmdArgs(),
+ EmitStackPromotionChecks(false), PrintInlineTree(false),
+ EmbedMode(IRGenEmbedMode::None), HasValueNamesSetting(false),
+ ValueNames(false), EnableReflectionMetadata(true),
+ EnableReflectionNames(true), UseIncrementalLLVMCodeGen(true),
+ UseSwiftCall(false), GenerateProfile(false), CmdArgs(),
SanitizeCoverage(llvm::SanitizerCoverageOptions()) {}
/// Gets the name of the specified output filename.
diff --git a/include/swift/AST/SILOptions.h b/include/swift/AST/SILOptions.h
index 3dd247c..1b6eb44 100644
--- a/include/swift/AST/SILOptions.h
+++ b/include/swift/AST/SILOptions.h
@@ -107,6 +107,9 @@
/// Instrument code to generate profiling information.
bool GenerateProfile = false;
+ /// Path to the profdata file to be used for PGO, or the empty string.
+ std::string UseProfile = "";
+
/// Emit a mapping of profile counters for use in coverage.
bool EmitProfileCoverageMapping = false;
diff --git a/include/swift/AST/Type.h b/include/swift/AST/Type.h
index 453fab4..f0408a7 100644
--- a/include/swift/AST/Type.h
+++ b/include/swift/AST/Type.h
@@ -356,11 +356,11 @@
/// join of D and A (or D and B, or D and C) because there is no common
/// superclass. One would have to jump to an existential (e.g., \c AnyObject)
/// to find a common type.
- ///
- /// \returns the join of the two types, if there is a concrete type that can
- /// express the join, or a null type if the only join would be a more-general
- /// existential type (e.g., \c Any).
- static Type join(Type type1, Type type2);
+ ///
+ /// \returns the join of the two types, if there is a concrete type
+ /// that can express the join, or Any if the only join would be a
+ /// more-general existential type
+ static Type join(Type first, Type second);
private:
// Direct comparison is disabled for types, because they may not be canonical.
diff --git a/include/swift/Basic/ArrayRefView.h b/include/swift/Basic/ArrayRefView.h
index ad27232..89edd8d 100644
--- a/include/swift/Basic/ArrayRefView.h
+++ b/include/swift/Basic/ArrayRefView.h
@@ -29,6 +29,7 @@
class ArrayRefView {
llvm::ArrayRef<Orig> Array;
public:
+ ArrayRefView() {}
ArrayRefView(llvm::ArrayRef<Orig> array) : Array(array) {}
class iterator {
@@ -111,6 +112,41 @@
"original array access not enabled for this view");
return Array;
}
+
+ friend bool operator==(ArrayRefView lhs, ArrayRefView rhs) {
+ if (lhs.size() != rhs.size())
+ return false;
+ for (auto i : indices(lhs))
+ if (lhs[i] != rhs[i])
+ return false;
+ return true;
+ }
+ friend bool operator==(llvm::ArrayRef<Projected> lhs, ArrayRefView rhs) {
+ if (lhs.size() != rhs.size())
+ return false;
+ for (auto i : indices(lhs))
+ if (lhs[i] != rhs[i])
+ return false;
+ return true;
+ }
+ friend bool operator==(ArrayRefView lhs, llvm::ArrayRef<Projected> rhs) {
+ if (lhs.size() != rhs.size())
+ return false;
+ for (auto i : indices(lhs))
+ if (lhs[i] != rhs[i])
+ return false;
+ return true;
+ }
+
+ friend bool operator!=(ArrayRefView lhs, ArrayRefView rhs) {
+ return !(lhs == rhs);
+ }
+ friend bool operator!=(llvm::ArrayRef<Projected> lhs, ArrayRefView rhs) {
+ return !(lhs == rhs);
+ }
+ friend bool operator!=(ArrayRefView lhs, llvm::ArrayRef<Projected> rhs) {
+ return !(lhs == rhs);
+ }
};
} // end namespace swift
diff --git a/include/swift/Basic/ProfileCounter.h b/include/swift/Basic/ProfileCounter.h
new file mode 100644
index 0000000..b01c274
--- /dev/null
+++ b/include/swift/Basic/ProfileCounter.h
@@ -0,0 +1,46 @@
+//===------------ ProfileCounter.h - PGO Propfile counter -------*- C++ -*-===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 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
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file Declares ProfileCounter, a convenient type for PGO
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_BASIC_PROFILECOUNTER_H
+#define SWIFT_BASIC_PROFILECOUNTER_H
+
+#include <cassert>
+#include <cstdint>
+
+namespace swift {
+/// A class designed to be smaller than using Optional<uint64_t> for PGO
+class ProfileCounter {
+private:
+ uint64_t count;
+
+public:
+ explicit ProfileCounter() : count(UINT64_MAX) {}
+ ProfileCounter(uint64_t Count) : count(Count) {
+ if (Count == UINT64_MAX) {
+ count = UINT64_MAX - 1;
+ }
+ }
+
+ bool hasValue() const { return count != UINT64_MAX; }
+ uint64_t getValue() const {
+ assert(hasValue());
+ return count;
+ }
+ explicit operator bool() const { return hasValue(); }
+};
+} // end namespace swift
+
+#endif // SWIFT_BASIC_PROFILECOUNTER_H
diff --git a/include/swift/Basic/Range.h b/include/swift/Basic/Range.h
index d9b6a7f..3e23aea 100644
--- a/include/swift/Basic/Range.h
+++ b/include/swift/Basic/Range.h
@@ -63,11 +63,47 @@
return result;
}
-/// A range of integers. This type behaves roughly like an ArrayRef.
-template <class T=unsigned> class IntRange {
- static_assert(std::is_integral<T>::value, "T must be an integer type");
+template <class T, bool IsEnum = std::is_enum<T>::value>
+struct IntRangeTraits;
+
+template <class T>
+struct IntRangeTraits<T, /*is enum*/ false> {
+ static_assert(std::is_integral<T>::value,
+ "argument type of IntRange is either an integer nor an enum");
+ using int_type = T;
+ using difference_type = typename std::make_signed<int_type>::type;
+
+ static T addOffset(T value, difference_type quantity) {
+ return T(difference_type(value) + quantity);
+ }
+ static difference_type distance(T begin, T end) {
+ return difference_type(end) - difference_type(begin);
+ }
+};
+
+template <class T>
+struct IntRangeTraits<T, /*is enum*/ true> {
+ using int_type = typename std::underlying_type<T>::type;
+ using difference_type = typename std::make_signed<int_type>::type;
+
+ static T addOffset(T value, difference_type quantity) {
+ return T(difference_type(value) + quantity);
+ }
+ static difference_type distance(T begin, T end) {
+ return difference_type(end) - difference_type(begin);
+ }
+};
+
+/// A range of integers or enum values. This type behaves roughly
+/// like an ArrayRef.
+template <class T = unsigned, class Traits = IntRangeTraits<T>>
+class IntRange {
T Begin;
T End;
+
+ using int_type = typename Traits::int_type;
+ using difference_type = typename Traits::difference_type;
+
public:
IntRange() : Begin(0), End(0) {}
IntRange(T end) : Begin(0), End(end) {}
@@ -87,37 +123,48 @@
typedef std::random_access_iterator_tag iterator_category;
T operator*() const { return Value; }
- iterator &operator++() { Value++; return *this; }
- iterator operator++(int) { return iterator(Value++); }
- iterator &operator--() {
- Value--;
- return *this;
+ iterator &operator++() {
+ return *this += 1;
}
- iterator operator--(int) { return iterator(Value--); }
+ iterator operator++(int) {
+ auto copy = *this;
+ *this += 1;
+ return copy;
+ }
+ iterator &operator--() {
+ return *this -= 1;
+ }
+ iterator operator--(int) {
+ auto copy = *this;
+ *this -= 1;
+ return copy;
+ }
bool operator==(iterator rhs) { return Value == rhs.Value; }
bool operator!=(iterator rhs) { return Value != rhs.Value; }
iterator &operator+=(difference_type i) {
- Value += T(i);
+ Value = Traits::addOffset(Value, i);
return *this;
}
iterator operator+(difference_type i) const {
- return iterator(Value + T(i));
+ return iterator(Traits::adddOfset(Value, i));
}
friend iterator operator+(difference_type i, iterator base) {
- return iterator(base.Value + T(i));
+ return iterator(Traits::addOffset(base.Value, i));
}
iterator &operator-=(difference_type i) {
- Value -= T(i);
+ Value = Traits::addOffset(Value, -i);
return *this;
}
iterator operator-(difference_type i) const {
- return iterator(Value - T(i));
+ return iterator(Traits::addOffset(Value, -i));
}
difference_type operator-(iterator rhs) const {
- return difference_type(Value - rhs.Value);
+ return Traits::distance(rhs.Value, Value);
}
- T operator[](difference_type i) const { return Value + T(i); }
+ T operator[](difference_type i) const {
+ return Traits::addOffset(Value, i);
+ }
bool operator<(iterator rhs) const { return Value < rhs.Value; }
bool operator<=(iterator rhs) const { return Value <= rhs.Value; }
bool operator>(iterator rhs) const { return Value > rhs.Value; }
@@ -134,26 +181,27 @@
}
bool empty() const { return Begin == End; }
- size_t size() const { return End - Begin; }
+ size_t size() const { return size_t(Traits::distance(Begin, End)); }
T operator[](size_t i) const {
assert(i < size());
- return Begin + i;
+ return Traits::addOffset(Begin, i);
}
T front() const { assert(!empty()); return Begin; }
- T back() const { assert(!empty()); return End - 1; }
+ T back() const { assert(!empty()); return Traits::addOffset(End, -1); }
IntRange drop_back(size_t length = 1) const {
assert(length <= size());
- return IntRange(Begin, End - length);
+ return IntRange(Begin, Traits::addOffset(End, -length));
}
IntRange slice(size_t start) const {
assert(start <= size());
- return IntRange(Begin + start, End);
+ return IntRange(Traits::addOffset(Begin, start), End);
}
IntRange slice(size_t start, size_t length) const {
assert(start <= size());
- return IntRange(Begin + start,
- Begin + start + std::min(length, End - (Begin + start)));
+ auto newBegin = Traits::addOffset(Begin, start);
+ auto newSize = std::min(length, size_t(Traits::distance(newBegin, End)));
+ return IntRange(newBegin, Traits::addOffset(newBegin, newSize));
}
bool operator==(IntRange other) const {
diff --git a/include/swift/IDE/SyntaxModel.h b/include/swift/IDE/SyntaxModel.h
index 138ce92..6e223c4 100644
--- a/include/swift/IDE/SyntaxModel.h
+++ b/include/swift/IDE/SyntaxModel.h
@@ -111,6 +111,7 @@
ArrayExpression,
DictionaryExpression,
ObjectLiteralExpression,
+ TupleExpression
};
enum class SyntaxStructureElementKind : uint8_t {
diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td
index 33d80e9..88bca35 100644
--- a/include/swift/Option/Options.td
+++ b/include/swift/Option/Options.td
@@ -641,6 +641,10 @@
Flags<[FrontendOption, NoInteractiveOption]>,
HelpText<"Generate instrumented code to collect execution counts">;
+def profile_use : CommaJoined<["-"], "profile-use=">,
+ Flags<[FrontendOption, NoInteractiveOption]>, MetaVarName<"<profdata>">,
+ HelpText<"Supply a profdata file to enable profile-guided optimization">;
+
def profile_coverage_mapping : Flag<["-"], "profile-coverage-mapping">,
Flags<[FrontendOption, NoInteractiveOption]>,
HelpText<"Generate coverage data for use with profiled execution counts">;
diff --git a/include/swift/Reflection/MetadataSource.h b/include/swift/Reflection/MetadataSource.h
index 7b234b0..5fa9706 100644
--- a/include/swift/Reflection/MetadataSource.h
+++ b/include/swift/Reflection/MetadataSource.h
@@ -147,25 +147,6 @@
}
template <typename Allocator>
- static const MetadataSource*
- decodeParent(Allocator &A,
- std::string::const_iterator &it,
- const std::string::const_iterator &end) {
- if (it == end || *it != 'P')
- return nullptr;
-
- ++it;
- auto Child = decode(A, it, end);
- if (!Child)
- return nullptr;
-
- if (it == end || *it != '_')
- return nullptr;
-
- return A.createParent(Child);
- }
-
- template <typename Allocator>
static const MetadataSource *decode(Allocator &A,
std::string::const_iterator &it,
const std::string::const_iterator &end) {
@@ -180,8 +161,6 @@
return decodeMetadataCapture(A, it, end);
case 'G':
return decodeGenericArgument(A, it, end);
- case 'P':
- return decodeParent(A, it, end);
case 'S':
++it;
return A.createSelf();
@@ -318,29 +297,6 @@
}
};
-/// Metadata gotten through the parent of a nominal type's metadata.
-class ParentMetadataSource final : public MetadataSource {
- const MetadataSource *Child;
-public:
- ParentMetadataSource(const MetadataSource *Child)
- : MetadataSource(MetadataSourceKind::Parent),
- Child(Child) {}
-
- template <typename Allocator>
- static const ParentMetadataSource*
- create(Allocator &A, const MetadataSource *Child) {
- return A.template make_source<ParentMetadataSource>(Child);
- }
-
- const MetadataSource *getChild() const {
- return Child;
- }
-
- static bool classof(const MetadataSource *MS) {
- return MS->getKind() == MetadataSourceKind::Parent;
- }
-};
-
/// A source of metadata from the Self metadata parameter passed via
/// a witness_method convention function.
class SelfMetadataSource final : public MetadataSource {
diff --git a/include/swift/Reflection/MetadataSourceBuilder.h b/include/swift/Reflection/MetadataSourceBuilder.h
index 2df9d85..3117b10 100644
--- a/include/swift/Reflection/MetadataSourceBuilder.h
+++ b/include/swift/Reflection/MetadataSourceBuilder.h
@@ -59,11 +59,6 @@
return ClosureBindingMetadataSource::create(*this, Index);
}
- const ParentMetadataSource *
- createParent(const MetadataSource *Child) {
- return ParentMetadataSource::create(*this, Child);
- }
-
const SelfMetadataSource *
createSelf() {
return SelfMetadataSource::create(*this);
diff --git a/include/swift/Reflection/MetadataSources.def b/include/swift/Reflection/MetadataSources.def
index 60fe4ef..b4dfe28 100644
--- a/include/swift/Reflection/MetadataSources.def
+++ b/include/swift/Reflection/MetadataSources.def
@@ -20,6 +20,5 @@
METADATA_SOURCE(ReferenceCapture, MetadataSource)
METADATA_SOURCE(MetadataCapture, MetadataSource)
METADATA_SOURCE(GenericArgument, MetadataSource)
-METADATA_SOURCE(Parent, MetadataSource)
METADATA_SOURCE(Self, MetadataSource)
METADATA_SOURCE(SelfWitnessTable, MetadataSource)
diff --git a/include/swift/Reflection/ReflectionContext.h b/include/swift/Reflection/ReflectionContext.h
index bc7a5c3..920c1d2 100644
--- a/include/swift/Reflection/ReflectionContext.h
+++ b/include/swift/Reflection/ReflectionContext.h
@@ -50,7 +50,6 @@
using super::getBuilder;
using super::readIsaMask;
using super::readTypeFromMetadata;
- using super::readParentFromMetadata;
using super::readGenericArgFromMetadata;
using super::readMetadataFromInstance;
using typename super::StoredPointer;
@@ -460,10 +459,6 @@
auto Base = cast<GenericArgumentMetadataSource>(MS)->getSource();
return isMetadataSourceReady(Base, Builder);
}
- case MetadataSourceKind::Parent: {
- auto Base = cast<ParentMetadataSource>(MS)->getChild();
- return isMetadataSourceReady(Base, Builder);
- }
case MetadataSourceKind::Self:
case MetadataSourceKind::SelfWitnessTable:
return true;
@@ -548,19 +543,6 @@
return Arg;
}
- case MetadataSourceKind::Parent: {
- auto Base = readMetadataSource(Context,
- cast<ParentMetadataSource>(MS)->getChild(),
- Builder);
- if (!Base.first)
- break;
-
- auto Parent = readParentFromMetadata(Base.second);
- if (!Parent.first)
- break;
-
- return Parent;
- }
case MetadataSourceKind::Self:
case MetadataSourceKind::SelfWitnessTable:
break;
diff --git a/include/swift/Reflection/TypeRefBuilder.h b/include/swift/Reflection/TypeRefBuilder.h
index 2be00c3..b339432 100644
--- a/include/swift/Reflection/TypeRefBuilder.h
+++ b/include/swift/Reflection/TypeRefBuilder.h
@@ -178,6 +178,11 @@
}
const NominalTypeRef *createNominalType(
+ const Optional<std::string> &mangledName) {
+ return NominalTypeRef::create(*this, *mangledName, nullptr);
+ }
+
+ const NominalTypeRef *createNominalType(
const Optional<std::string> &mangledName,
const TypeRef *parent) {
return NominalTypeRef::create(*this, *mangledName, parent);
@@ -185,6 +190,12 @@
const BoundGenericTypeRef *
createBoundGenericType(const Optional<std::string> &mangledName,
+ const std::vector<const TypeRef *> &args) {
+ return BoundGenericTypeRef::create(*this, *mangledName, args, nullptr);
+ }
+
+ const BoundGenericTypeRef *
+ createBoundGenericType(const Optional<std::string> &mangledName,
const std::vector<const TypeRef *> &args,
const TypeRef *parent) {
return BoundGenericTypeRef::create(*this, *mangledName, args, parent);
diff --git a/include/swift/Remote/MetadataReader.h b/include/swift/Remote/MetadataReader.h
index 396e964..d26bc9f 100644
--- a/include/swift/Remote/MetadataReader.h
+++ b/include/swift/Remote/MetadataReader.h
@@ -934,33 +934,6 @@
swift_runtime_unreachable("Unhandled IsaEncodingKind in switch.");
}
- /// Read the parent type metadata from a nested nominal type metadata.
- std::pair<bool, StoredPointer>
- readParentFromMetadata(StoredPointer metadata) {
- auto Meta = readMetadata(metadata);
- if (!Meta)
- return std::make_pair(false, 0);
-
- auto descriptorAddress = readAddressOfNominalTypeDescriptor(Meta);
- if (!descriptorAddress)
- return std::make_pair(false, 0);
-
- // Read the nominal type descriptor.
- auto descriptor = readNominalTypeDescriptor(descriptorAddress);
- if (!descriptor)
- return std::make_pair(false, 0);
-
- // Read the parent type if the type has one.
- if (descriptor->GenericParams.Flags.hasParent()) {
- StoredPointer parentAddress = getNominalParent(Meta, descriptor);
- if (!parentAddress)
- return std::make_pair(false, 0);
- return std::make_pair(true, parentAddress);
- }
-
- return std::make_pair(false, 0);
- }
-
/// Read a single generic type argument from a bound generic type
/// metadata.
std::pair<bool, StoredPointer>
@@ -1308,32 +1281,6 @@
return OwnedProtocolDescriptorRef(Casted);
}
- StoredPointer getNominalParent(MetadataRef metadata,
- NominalTypeDescriptorRef descriptor) {
- // If this is metadata for some sort of value type, the parent type
- // is at a fixed offset.
- if (auto valueMetadata = dyn_cast<TargetValueMetadata<Runtime>>(metadata)) {
- return valueMetadata->Parent;
- }
-
- // If this is metadata for a class type, the parent type for the
- // most-derived class is at an offset stored in the most-derived
- // nominal type descriptor.
- if (auto classMetadata = dyn_cast<TargetClassMetadata<Runtime>>(metadata)) {
- // If it does, it's immediately before the generic parameters.
- auto offsetToParent
- = sizeof(StoredPointer) * (descriptor->GenericParams.Offset - 1);
- RemoteAddress addressOfParent(metadata.getAddress() + offsetToParent);
- StoredPointer parentAddress;
- if (!Reader->readInteger(addressOfParent, &parentAddress))
- return StoredPointer();
- return parentAddress;
- }
-
- // Otherwise, we don't know how to access its parent. This is a failure.
- return StoredPointer();
- }
-
std::vector<BuiltType>
getGenericSubst(MetadataRef metadata, NominalTypeDescriptorRef descriptor) {
std::vector<BuiltType> substitutions;
@@ -1387,23 +1334,13 @@
if (!typeDecl)
return BuiltType();
- // Read the parent type if the type has one.
- BuiltType parent = BuiltType();
- if (descriptor->GenericParams.Flags.hasParent()) {
- StoredPointer parentAddress = getNominalParent(metadata, descriptor);
- if (!parentAddress)
- return BuiltType();
- parent = readTypeFromMetadata(parentAddress);
- if (!parent) return BuiltType();
- }
-
BuiltType nominal;
if (descriptor->GenericParams.NumPrimaryParams) {
auto args = getGenericSubst(metadata, descriptor);
if (args.empty()) return BuiltType();
- nominal = Builder.createBoundGenericType(typeDecl, args, parent);
+ nominal = Builder.createBoundGenericType(typeDecl, args);
} else {
- nominal = Builder.createNominalType(typeDecl, parent);
+ nominal = Builder.createNominalType(typeDecl);
}
if (!nominal) return BuiltType();
diff --git a/include/swift/Runtime/Metadata.h b/include/swift/Runtime/Metadata.h
index 87ccf64..5207f0c 100644
--- a/include/swift/Runtime/Metadata.h
+++ b/include/swift/Runtime/Metadata.h
@@ -1102,6 +1102,13 @@
};
using HeapMetadata = TargetHeapMetadata<InProcess>;
+struct GenericContextDescriptor {
+ /// The number of primary type parameters. This is always less than or equal
+ /// to NumGenericRequirements; it counts only the type parameters
+ /// and not any required witness tables.
+ uint32_t NumPrimaryParams;
+};
+
/// Header for a generic parameter descriptor. This is a variable-sized
/// structure that describes how to find and parse a generic parameter vector
/// within the type metadata for an instance of a nominal type.
@@ -1109,8 +1116,7 @@
/// The offset to the first generic argument from the start of
/// metadata record.
///
- /// This is meaningful if either NumGenericRequirements is nonzero or
- /// (for classes) if Flags.hasParent() is true.
+ /// This is meaningful if NumGenericRequirements is nonzero.
uint32_t Offset;
/// The amount of generic requirement data in the metadata record, in
@@ -1126,6 +1132,10 @@
/// and not any required witness tables.
uint32_t NumPrimaryParams;
+ /// The number of types that this type is nested inside of, including itself
+ /// (so this value is at least 1).
+ uint16_t NestingDepth;
+
/// Flags for this generic parameter descriptor.
GenericParameterDescriptorFlags Flags;
@@ -1135,7 +1145,12 @@
/// True if the nominal type is generic in any way.
bool isGeneric() const {
- return hasGenericRequirements() || Flags.hasGenericParent();
+ return hasGenericRequirements();
+ }
+
+ GenericContextDescriptor getContext(unsigned depth) const {
+ assert(depth < NestingDepth);
+ return ((const GenericContextDescriptor *)(this + 1))[depth];
}
// TODO: add meaningful descriptions of the generic requirements.
@@ -1316,12 +1331,13 @@
!GenericParams.Flags.hasVTable())
return nullptr;
- auto asWords = reinterpret_cast<const void * const*>(this + 1);
+ auto asWords = reinterpret_cast<const uint32_t *>(this + 1);
// TODO: Once we emit reflective descriptions of generic requirements,
// skip the right number of words here.
- return reinterpret_cast<const VTableDescriptor *>(asWords);
+ return reinterpret_cast<const VTableDescriptor *>(asWords
+ + GenericParams.NestingDepth);
}
/// The generic parameter descriptor header. This describes how to find and
@@ -1567,17 +1583,6 @@
return getter(this);
}
- /// Return the parent type for a given level in the class hierarchy, or
- /// null if that level does not have a parent type.
- const TargetMetadata<Runtime> *
- getParentType(const TargetNominalTypeDescriptor<Runtime> *theClass) const {
- if (!theClass->GenericParams.Flags.hasParent())
- return nullptr;
-
- auto metadataAsWords = reinterpret_cast<const Metadata * const *>(this);
- return metadataAsWords[theClass->GenericParams.Offset - 1];
- }
-
StoredPointer offsetToDescriptorOffset() const {
return offsetof(TargetClassMetadata<Runtime>, Description);
}
@@ -1745,22 +1750,15 @@
using StoredPointer = typename Runtime::StoredPointer;
TargetValueMetadata(MetadataKind Kind,
ConstTargetMetadataPointer<Runtime, TargetNominalTypeDescriptor>
- description,
- ConstTargetMetadataPointer<Runtime, swift::TargetMetadata> parent)
+ description)
: TargetMetadata<Runtime>(Kind),
- Description(description),
- Parent(parent)
+ Description(description)
{}
/// An out-of-line description of the type.
ConstTargetFarRelativeDirectPointer<Runtime, TargetNominalTypeDescriptor>
Description;
- /// The parent type of this member type, or null if this is not a
- /// member type. It's acceptable to make this a direct pointer because
- /// parent types are relatively uncommon.
- TargetPointer<Runtime, const TargetMetadata<Runtime>> Parent;
-
static bool classof(const TargetMetadata<Runtime> *metadata) {
return metadata->getKind() == MetadataKind::Struct
|| metadata->getKind() == MetadataKind::Enum
@@ -1785,11 +1783,6 @@
StoredPointer offsetToDescriptorOffset() const {
return offsetof(TargetValueMetadata<Runtime>, Description);
}
-
- StoredPointer offsetToParentOffset() const {
- return offsetof(TargetValueMetadata<Runtime>, Parent);
- }
-
};
using ValueMetadata = TargetValueMetadata<InProcess>;
diff --git a/include/swift/SIL/DebugUtils.h b/include/swift/SIL/DebugUtils.h
index b8cbb76..3df6dd5 100644
--- a/include/swift/SIL/DebugUtils.h
+++ b/include/swift/SIL/DebugUtils.h
@@ -143,6 +143,16 @@
return NonDebugUses.begin() == NonDebugUses.end();
}
+/// Return true if all of the results of the given instruction have no uses
+/// except debug instructions.
+inline bool onlyHaveDebugUsesOfAllResults(SILInstruction *I) {
+ for (auto result : I->getResults()) {
+ if (!onlyHaveDebugUses(result))
+ return false;
+ }
+ return true;
+}
+
/// Returns true if a value (e.g. SILInstruction) has exactly one use which is
/// not a debug instruction.
inline bool hasOneNonDebugUse(SILValue V) {
@@ -169,16 +179,26 @@
/// incremented.
inline void eraseFromParentWithDebugInsts(SILInstruction *I,
SILBasicBlock::iterator &InstIter) {
- while (!I->use_empty()) {
- auto *User = I->use_begin()->getUser();
- assert(isDebugInst(User));
- if (InstIter != SILBasicBlock::iterator() &&
- InstIter != I->getParent()->end() &&
- &*InstIter == User) {
- InstIter++;
+ auto results = I->getResults();
+
+ bool foundAny;
+ do {
+ foundAny = false;
+ for (auto result : results) {
+ while (!result->use_empty()) {
+ foundAny = true;
+ auto *User = result->use_begin()->getUser();
+ assert(isDebugInst(User));
+ if (InstIter != SILBasicBlock::iterator() &&
+ InstIter != I->getParent()->end() &&
+ &*InstIter == User) {
+ InstIter++;
+ }
+ User->eraseFromParent();
+ }
}
- User->eraseFromParent();
- }
+ } while (foundAny);
+
I->eraseFromParent();
}
diff --git a/include/swift/SIL/DynamicCasts.h b/include/swift/SIL/DynamicCasts.h
index 8f33fd7..aa46086 100644
--- a/include/swift/SIL/DynamicCasts.h
+++ b/include/swift/SIL/DynamicCasts.h
@@ -18,6 +18,8 @@
#ifndef SWIFT_SIL_DYNAMICCASTS_H
#define SWIFT_SIL_DYNAMICCASTS_H
+#include "swift/Basic/ProfileCounter.h"
+
namespace swift {
class CanType;
@@ -78,10 +80,10 @@
/// using a scalar cast operation.
void emitIndirectConditionalCastWithScalar(
SILBuilder &B, ModuleDecl *M, SILLocation loc,
- CastConsumptionKind consumption,
- SILValue src, CanType sourceType,
- SILValue dest, CanType targetType,
- SILBasicBlock *trueBB, SILBasicBlock *falseBB);
+ CastConsumptionKind consumption, SILValue src, CanType sourceType,
+ SILValue dest, CanType targetType, SILBasicBlock *trueBB,
+ SILBasicBlock *falseBB, ProfileCounter TrueCount = ProfileCounter(),
+ ProfileCounter FalseCount = ProfileCounter());
/// \brief Does the type conform to the _ObjectiveCBridgeable protocol.
bool isObjectiveCBridgeable(ModuleDecl *M, CanType Ty);
diff --git a/include/swift/SIL/Notifications.h b/include/swift/SIL/Notifications.h
index 49f9980..e51c208 100644
--- a/include/swift/SIL/Notifications.h
+++ b/include/swift/SIL/Notifications.h
@@ -15,7 +15,7 @@
namespace swift {
-class ValueBase;
+class SILNode;
/// A protocol (or interface) for handling value deletion notifications.
///
@@ -29,7 +29,7 @@
virtual ~DeleteNotificationHandler() {}
/// Handle the invalidation message for the value \p Value.
- virtual void handleDeleteNotification(swift::ValueBase *Value) { }
+ virtual void handleDeleteNotification(SILNode *value) { }
/// Returns True if the pass, analysis or other entity wants to receive
/// notifications. This callback is called once when the class is being
diff --git a/include/swift/SIL/PatternMatch.h b/include/swift/SIL/PatternMatch.h
index 85624de..bf4f912 100644
--- a/include/swift/SIL/PatternMatch.h
+++ b/include/swift/SIL/PatternMatch.h
@@ -296,19 +296,24 @@
// Unary Instructions
//===----------------------------------------------------------------------===//
-template<typename OpMatchTy, ValueKind Kind>
+template<typename OpMatchTy, SILInstructionKind Kind>
struct UnaryOp_match {
OpMatchTy OpMatch;
UnaryOp_match(const OpMatchTy &Op) : OpMatch(Op) { }
- template<typename OpTy>
- bool match(OpTy *V) {
- if (V->getKind() != Kind)
+ bool match(SILNode *node) {
+ if (node->getKind() != SILNodeKind(Kind))
return false;
- auto *I = dyn_cast<SILInstruction>(V);
- if (!I || I->getNumOperands() != 1)
+ return match(cast<SILInstruction>(node));
+ }
+
+ bool match(SILInstruction *I) {
+ if (I->getKind() != Kind)
+ return false;
+
+ if (I->getNumOperands() != 1)
return false;
return OpMatch.match(I->getOperand(0));
@@ -319,7 +324,7 @@
// further matchers to the operands of the unary operation.
#define UNARY_OP_MATCH_WITH_ARG_MATCHER(Class) \
template <typename Ty> \
- UnaryOp_match<Ty, ValueKind::Class> \
+ UnaryOp_match<Ty, SILInstructionKind::Class> \
m_##Class(const Ty &T) { \
return T; \
}
@@ -393,20 +398,25 @@
// Binary Instructions
//===----------------------------------------------------------------------===//
-template<typename LHSTy, typename RHSTy, ValueKind Kind>
+template<typename LHSTy, typename RHSTy, SILInstructionKind Kind>
struct BinaryOp_match {
LHSTy L;
RHSTy R;
BinaryOp_match(const LHSTy &LHS, const RHSTy &RHS) : L(LHS), R(RHS) {}
- template<typename OpTy>
- bool match(OpTy *V) {
- if (V->getKind() != Kind)
+ bool match(SILNode *node) {
+ if (node->getKind() != SILNodeKind(Kind))
return false;
- auto *I = dyn_cast<SILInstruction>(V);
- if (!I || I->getNumOperands() != 2)
+ return match(cast<SILInstruction>(node));
+ }
+
+ bool match(SILInstruction *I) {
+ if (I->getKind() != Kind)
+ return false;
+
+ if (I->getNumOperands() != 2)
return false;
return L.match((ValueBase *)I->getOperand(0)) &&
@@ -415,7 +425,7 @@
};
template <typename LTy, typename RTy>
-BinaryOp_match<LTy, RTy, ValueKind::IndexRawPointerInst>
+BinaryOp_match<LTy, RTy, SILInstructionKind::IndexRawPointerInst>
m_IndexRawPointerInst(const LTy &Left, const RTy &Right) {
return {Left, Right};
}
diff --git a/include/swift/SIL/Projection.h b/include/swift/SIL/Projection.h
index c42274d..2371cb7 100644
--- a/include/swift/SIL/Projection.h
+++ b/include/swift/SIL/Projection.h
@@ -228,8 +228,10 @@
Projection() = delete;
explicit Projection(SILValue V)
- : Projection(dyn_cast<SILInstruction>(V)) {}
- explicit Projection(SILInstruction *I);
+ : Projection(dyn_cast<SingleValueInstruction>(V)) {}
+ explicit Projection(SILInstruction *I)
+ : Projection(dyn_cast<SingleValueInstruction>(I)) {}
+ explicit Projection(SingleValueInstruction *I);
Projection(ProjectionKind Kind, unsigned NewIndex)
: Value(Kind, NewIndex) {}
@@ -255,7 +257,7 @@
/// Determine if I is a value projection instruction whose corresponding
/// projection equals this projection.
- bool matchesObjectProjection(SILInstruction *I) const {
+ bool matchesObjectProjection(SingleValueInstruction *I) const {
Projection P(I);
return P.isValid() && P == *this;
}
@@ -264,17 +266,17 @@
/// type differences and this Projection is representable as a value
/// projection, create the relevant value projection and return it. Otherwise,
/// return nullptr.
- NullablePtr<SILInstruction>
+ NullablePtr<SingleValueInstruction>
createObjectProjection(SILBuilder &B, SILLocation Loc, SILValue Base) const;
/// If Base's type matches this Projections type ignoring Address vs Object
/// type differences and this projection is representable as an address
/// projection, create the relevant address projection and return
/// it. Otherwise, return nullptr.
- NullablePtr<SILInstruction>
+ NullablePtr<SingleValueInstruction>
createAddressProjection(SILBuilder &B, SILLocation Loc, SILValue Base) const;
- NullablePtr<SILInstruction>
+ NullablePtr<SingleValueInstruction>
createProjection(SILBuilder &B, SILLocation Loc, SILValue Base) const {
if (Base->getType().isAddress()) {
return createAddressProjection(B, Loc, Base);
@@ -370,13 +372,16 @@
/// Returns true if this instruction projects from an address type to an
/// address subtype.
- static bool isAddressProjection(SILValue V) {
+ static SingleValueInstruction *isAddressProjection(SILValue V) {
switch (V->getKind()) {
default:
- return false;
+ return nullptr;
case ValueKind::IndexAddrInst: {
+ auto I = cast<IndexAddrInst>(V);
unsigned Scalar;
- return getIntegerIndex(cast<IndexAddrInst>(V)->getIndex(), Scalar);
+ if (getIntegerIndex(I->getIndex(), Scalar))
+ return I;
+ return nullptr;
}
case ValueKind::StructElementAddrInst:
case ValueKind::RefElementAddrInst:
@@ -384,20 +389,20 @@
case ValueKind::ProjectBoxInst:
case ValueKind::TupleElementAddrInst:
case ValueKind::UncheckedTakeEnumDataAddrInst:
- return true;
+ return cast<SingleValueInstruction>(V);
}
}
/// Returns true if this instruction projects from an object type to an object
/// subtype.
- static bool isObjectProjection(SILValue V) {
+ static SingleValueInstruction *isObjectProjection(SILValue V) {
switch (V->getKind()) {
default:
- return false;
+ return nullptr;
case ValueKind::StructExtractInst:
case ValueKind::TupleExtractInst:
case ValueKind::UncheckedEnumDataInst:
- return true;
+ return cast<SingleValueInstruction>(V);
}
}
@@ -465,7 +470,7 @@
/// This can be used with getFirstLevelProjections to project out/reform
/// values. We do not need to use the original projections here since to build
/// aggregate instructions the order is the only important thing.
- static NullablePtr<SILInstruction>
+ static NullablePtr<SingleValueInstruction>
createAggFromFirstLevelProjections(SILBuilder &B, SILLocation Loc,
SILType BaseType,
llvm::SmallVectorImpl<SILValue> &Values);
@@ -788,10 +793,10 @@
ProjectionTreeNode *getChildForProjection(ProjectionTree &Tree,
const Projection &P);
- NullablePtr<SILInstruction> createProjection(SILBuilder &B, SILLocation Loc,
- SILValue Arg) const;
+ NullablePtr<SingleValueInstruction>
+ createProjection(SILBuilder &B, SILLocation Loc, SILValue Arg) const;
- SILInstruction *
+ SingleValueInstruction *
createAggregate(SILBuilder &B, SILLocation Loc,
ArrayRef<SILValue> Args) const;
diff --git a/include/swift/SIL/SILArgument.h b/include/swift/SIL/SILArgument.h
index c7ec76e..34764b4 100644
--- a/include/swift/SIL/SILArgument.h
+++ b/include/swift/SIL/SILArgument.h
@@ -22,6 +22,7 @@
class SILBasicBlock;
class SILModule;
+class SILUndef;
// Map an argument index onto a SILArgumentConvention.
inline SILArgumentConvention
@@ -58,9 +59,11 @@
const ValueDecl *getDecl() const { return Decl; }
- static bool classof(const ValueBase *V) {
- return V->getKind() >= ValueKind::First_SILArgument &&
- V->getKind() <= ValueKind::Last_SILArgument;
+ static bool classof(const SILInstruction *) = delete;
+ static bool classof(const SILUndef *) = delete;
+ static bool classof(const SILNode *node) {
+ return node->getKind() >= SILNodeKind::First_SILArgument &&
+ node->getKind() <= SILNodeKind::Last_SILArgument;
}
unsigned getIndex() const {
@@ -165,8 +168,10 @@
/// payload argument is the enum itself (the operand of the switch_enum).
SILValue getSingleIncomingValue() const;
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::SILPHIArgument;
+ static bool classof(const SILInstruction *) = delete;
+ static bool classof(const SILUndef *) = delete;
+ static bool classof(const SILNode *node) {
+ return node->getKind() == SILNodeKind::SILPHIArgument;
}
private:
@@ -216,8 +221,10 @@
return getArgumentConvention() == P;
}
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::SILFunctionArgument;
+ static bool classof(const SILInstruction *) = delete;
+ static bool classof(const SILUndef *) = delete;
+ static bool classof(const SILNode *node) {
+ return node->getKind() == SILNodeKind::SILFunctionArgument;
}
private:
diff --git a/include/swift/SIL/SILBasicBlock.h b/include/swift/SIL/SILBasicBlock.h
index 6f861e3..ae02555 100644
--- a/include/swift/SIL/SILBasicBlock.h
+++ b/include/swift/SIL/SILBasicBlock.h
@@ -389,13 +389,7 @@
I.dropAllReferences();
}
- void eraseInstructions() {
- for (auto It = begin(); It != end();) {
- auto *Inst = &*It++;
- Inst->replaceAllUsesWithUndef();
- Inst->eraseFromParent();
- }
- }
+ void eraseInstructions();
private:
friend class SILArgument;
diff --git a/include/swift/SIL/SILBuilder.h b/include/swift/SIL/SILBuilder.h
index 58c86d9..b075883 100644
--- a/include/swift/SIL/SILBuilder.h
+++ b/include/swift/SIL/SILBuilder.h
@@ -13,6 +13,7 @@
#ifndef SWIFT_SIL_SILBUILDER_H
#define SWIFT_SIL_SILBUILDER_H
+#include "swift/Basic/ProfileCounter.h"
#include "swift/SIL/SILArgument.h"
#include "swift/SIL/SILDebugScope.h"
#include "swift/SIL/SILFunction.h"
@@ -1084,27 +1085,33 @@
getSILDebugLocation(Loc), Operand, Element));
}
- SelectEnumInst *createSelectEnum(
- SILLocation Loc, SILValue Operand, SILType Ty, SILValue DefaultValue,
- ArrayRef<std::pair<EnumElementDecl *, SILValue>> CaseValues) {
- return insert(SelectEnumInst::create(getSILDebugLocation(Loc), Operand,
- Ty, DefaultValue, CaseValues, getFunction()));
+ SelectEnumInst *
+ createSelectEnum(SILLocation Loc, SILValue Operand, SILType Ty,
+ SILValue DefaultValue,
+ ArrayRef<std::pair<EnumElementDecl *, SILValue>> CaseValues,
+ Optional<ArrayRef<ProfileCounter>> CaseCounts = None,
+ ProfileCounter DefaultCount = ProfileCounter()) {
+ return insert(SelectEnumInst::create(
+ getSILDebugLocation(Loc), Operand, Ty, DefaultValue, CaseValues,
+ getFunction(), CaseCounts, DefaultCount));
}
SelectEnumAddrInst *createSelectEnumAddr(
SILLocation Loc, SILValue Operand, SILType Ty, SILValue DefaultValue,
- ArrayRef<std::pair<EnumElementDecl *, SILValue>> CaseValues) {
+ ArrayRef<std::pair<EnumElementDecl *, SILValue>> CaseValues,
+ Optional<ArrayRef<ProfileCounter>> CaseCounts = None,
+ ProfileCounter DefaultCount = ProfileCounter()) {
return insert(SelectEnumAddrInst::create(
getSILDebugLocation(Loc), Operand, Ty, DefaultValue, CaseValues,
- getFunction()));
+ getFunction(), CaseCounts, DefaultCount));
}
SelectValueInst *createSelectValue(
SILLocation Loc, SILValue Operand, SILType Ty, SILValue DefaultResult,
ArrayRef<std::pair<SILValue, SILValue>> CaseValuesAndResults) {
- return insert(SelectValueInst::create(getSILDebugLocation(Loc), Operand,
- Ty, DefaultResult,
- CaseValuesAndResults, getFunction()));
+ return insert(SelectValueInst::create(getSILDebugLocation(Loc), Operand, Ty,
+ DefaultResult, CaseValuesAndResults,
+ getFunction()));
}
TupleExtractInst *createTupleExtract(SILLocation Loc, SILValue Operand,
@@ -1525,12 +1532,12 @@
// Create an UncheckedRefCast if the source and dest types are legal,
// otherwise return null.
// Unwrap or wrap optional types as needed.
- SILInstruction *tryCreateUncheckedRefCast(SILLocation Loc, SILValue Op,
- SILType ResultTy);
+ SingleValueInstruction *tryCreateUncheckedRefCast(SILLocation Loc, SILValue Op,
+ SILType ResultTy);
// Create the appropriate cast instruction based on result type.
- SILInstruction *createUncheckedBitCast(SILLocation Loc, SILValue Op,
- SILType Ty);
+ SingleValueInstruction *createUncheckedBitCast(SILLocation Loc, SILValue Op,
+ SILType Ty);
//===--------------------------------------------------------------------===//
// Runtime failure
@@ -1589,28 +1596,33 @@
new (getModule()) ThrowInst(getSILDebugLocation(Loc), errorValue));
}
- CondBranchInst *createCondBranch(SILLocation Loc, SILValue Cond,
- SILBasicBlock *Target1,
- SILBasicBlock *Target2) {
- return insertTerminator(CondBranchInst::create(getSILDebugLocation(Loc),
- Cond, Target1, Target2, getFunction()));
+ CondBranchInst *
+ createCondBranch(SILLocation Loc, SILValue Cond, SILBasicBlock *Target1,
+ SILBasicBlock *Target2,
+ ProfileCounter Target1Count = ProfileCounter(),
+ ProfileCounter Target2Count = ProfileCounter()) {
+ return insertTerminator(
+ CondBranchInst::create(getSILDebugLocation(Loc), Cond, Target1, Target2,
+ Target1Count, Target2Count, getFunction()));
}
- CondBranchInst *createCondBranch(SILLocation Loc, SILValue Cond,
- SILBasicBlock *Target1,
- ArrayRef<SILValue> Args1,
- SILBasicBlock *Target2,
- ArrayRef<SILValue> Args2) {
- return insertTerminator(CondBranchInst::create(
- getSILDebugLocation(Loc), Cond, Target1, Args1, Target2, Args2,
- getFunction()));
+ CondBranchInst *
+ createCondBranch(SILLocation Loc, SILValue Cond, SILBasicBlock *Target1,
+ ArrayRef<SILValue> Args1, SILBasicBlock *Target2,
+ ArrayRef<SILValue> Args2,
+ ProfileCounter Target1Count = ProfileCounter(),
+ ProfileCounter Target2Count = ProfileCounter()) {
+ return insertTerminator(
+ CondBranchInst::create(getSILDebugLocation(Loc), Cond, Target1, Args1,
+ Target2, Args2, Target1Count, Target2Count, getFunction()));
}
- CondBranchInst *createCondBranch(SILLocation Loc, SILValue Cond,
- SILBasicBlock *Target1,
- OperandValueArrayRef Args1,
- SILBasicBlock *Target2,
- OperandValueArrayRef Args2) {
+ CondBranchInst *
+ createCondBranch(SILLocation Loc, SILValue Cond, SILBasicBlock *Target1,
+ OperandValueArrayRef Args1, SILBasicBlock *Target2,
+ OperandValueArrayRef Args2,
+ ProfileCounter Target1Count = ProfileCounter(),
+ ProfileCounter Target2Count = ProfileCounter()) {
SmallVector<SILValue, 6> ArgsCopy1;
SmallVector<SILValue, 6> ArgsCopy2;
@@ -1622,10 +1634,9 @@
for (auto I = Args2.begin(), E = Args2.end(); I != E; ++I)
ArgsCopy2.push_back(*I);
- return insertTerminator(CondBranchInst::create(getSILDebugLocation(Loc),
- Cond, Target1, ArgsCopy1,
- Target2, ArgsCopy2,
- getFunction()));
+ return insertTerminator(CondBranchInst::create(
+ getSILDebugLocation(Loc), Cond, Target1, ArgsCopy1, Target2, ArgsCopy2,
+ Target1Count, Target2Count, getFunction()));
}
BranchInst *createBranch(SILLocation Loc, SILBasicBlock *TargetBlock) {
@@ -1652,16 +1663,22 @@
SwitchEnumInst *createSwitchEnum(
SILLocation Loc, SILValue Operand, SILBasicBlock *DefaultBB,
- ArrayRef<std::pair<EnumElementDecl *, SILBasicBlock *>> CaseBBs) {
+ ArrayRef<std::pair<EnumElementDecl *, SILBasicBlock *>> CaseBBs,
+ Optional<ArrayRef<ProfileCounter>> CaseCounts = None,
+ ProfileCounter DefaultCount = ProfileCounter()) {
return insertTerminator(SwitchEnumInst::create(
- getSILDebugLocation(Loc), Operand, DefaultBB, CaseBBs, getFunction()));
+ getSILDebugLocation(Loc), Operand, DefaultBB, CaseBBs, getFunction(),
+ CaseCounts, DefaultCount));
}
SwitchEnumAddrInst *createSwitchEnumAddr(
SILLocation Loc, SILValue Operand, SILBasicBlock *DefaultBB,
- ArrayRef<std::pair<EnumElementDecl *, SILBasicBlock *>> CaseBBs) {
+ ArrayRef<std::pair<EnumElementDecl *, SILBasicBlock *>> CaseBBs,
+ Optional<ArrayRef<ProfileCounter>> CaseCounts = None,
+ ProfileCounter DefaultCount = ProfileCounter()) {
return insertTerminator(SwitchEnumAddrInst::create(
- getSILDebugLocation(Loc), Operand, DefaultBB, CaseBBs, getFunction()));
+ getSILDebugLocation(Loc), Operand, DefaultBB, CaseBBs, getFunction(),
+ CaseCounts, DefaultCount));
}
DynamicMethodBranchInst *
@@ -1673,13 +1690,15 @@
Member, HasMethodBB, NoMethodBB, getFunction()));
}
- CheckedCastBranchInst *createCheckedCastBranch(SILLocation Loc, bool isExact,
- SILValue op, SILType destTy,
- SILBasicBlock *successBB,
- SILBasicBlock *failureBB) {
+ CheckedCastBranchInst *
+ createCheckedCastBranch(SILLocation Loc, bool isExact, SILValue op,
+ SILType destTy, SILBasicBlock *successBB,
+ SILBasicBlock *failureBB,
+ ProfileCounter Target1Count = ProfileCounter(),
+ ProfileCounter Target2Count = ProfileCounter()) {
return insertTerminator(CheckedCastBranchInst::create(
getSILDebugLocation(Loc), isExact, op, destTy, successBB, failureBB,
- getFunction(), OpenedArchetypes));
+ getFunction(), OpenedArchetypes, Target1Count, Target2Count));
}
CheckedCastValueBranchInst *
@@ -1695,10 +1714,12 @@
createCheckedCastAddrBranch(SILLocation Loc, CastConsumptionKind consumption,
SILValue src, CanType sourceType, SILValue dest,
CanType targetType, SILBasicBlock *successBB,
- SILBasicBlock *failureBB) {
+ SILBasicBlock *failureBB,
+ ProfileCounter Target1Count = ProfileCounter(),
+ ProfileCounter Target2Count = ProfileCounter()) {
return insertTerminator(new (getModule()) CheckedCastAddrBranchInst(
getSILDebugLocation(Loc), consumption, src, sourceType, dest,
- targetType, successBB, failureBB));
+ targetType, successBB, failureBB, Target1Count, Target2Count));
}
//===--------------------------------------------------------------------===//
diff --git a/include/swift/SIL/SILCloner.h b/include/swift/SIL/SILCloner.h
index 6e05444..a3f2bfa 100644
--- a/include/swift/SIL/SILCloner.h
+++ b/include/swift/SIL/SILCloner.h
@@ -35,11 +35,12 @@
/// basic block, or function; subclasses that want to handle those should
/// implement the appropriate visit functions and/or provide other entry points.
template<typename ImplClass>
-class SILCloner : protected SILVisitor<ImplClass> {
- friend class SILVisitor<ImplClass, SILValue>;
+class SILCloner : protected SILInstructionVisitor<ImplClass> {
+ friend class SILVisitorBase<ImplClass>;
+ friend class SILInstructionVisitor<ImplClass>;
public:
- using SILVisitor<ImplClass>::asImpl;
+ using SILInstructionVisitor<ImplClass>::asImpl;
explicit SILCloner(SILFunction &F,
SILOpenedArchetypesTracker &OpenedArchetypesTracker)
@@ -70,19 +71,13 @@
SILBuilder &getBuilder() { return Builder; }
protected:
- void beforeVisit(ValueBase *V) {
- if (auto I = dyn_cast<SILInstruction>(V)) {
- // Update the set of available opened archetypes with the opened
- // archetypes used by the current instruction.
- doPreProcess(I);
- }
+ void beforeVisit(SILInstruction *I) {
+ // Update the set of available opened archetypes with the opened
+ // archetypes used by the current instruction.
+ doPreProcess(I);
}
-#define VALUE(CLASS, PARENT) \
- void visit##CLASS(CLASS *I) { \
- llvm_unreachable("SILCloner visiting non-instruction?"); \
- }
-#define INST(CLASS, PARENT, TEXTUALNAME, MEMBEHAVIOR, RELEASINGBEHAVIOR) \
+#define INST(CLASS, PARENT) \
void visit##CLASS(CLASS *I);
#include "swift/SIL/SILNodes.def"
@@ -250,7 +245,6 @@
SILBuilder Builder;
SILBasicBlock *InsertBeforeBB;
llvm::DenseMap<SILValue, SILValue> ValueMap;
- llvm::DenseMap<SILInstruction*, SILInstruction*> InstructionMap;
// Use MapVector to ensure that the order of block predecessors is
// deterministic.
@@ -352,13 +346,6 @@
if (VI != ValueMap.end())
return VI->second;
- if (auto *I = dyn_cast<SILInstruction>(Value)) {
- auto II = InstructionMap.find(I);
- if (II != InstructionMap.end())
- return SILValue(II->second);
- llvm_unreachable("Unmapped instruction while cloning?");
- }
-
// If we have undef, just remap the type.
if (auto *U = dyn_cast<SILUndef>(Value)) {
auto type = getOpType(U->getType());
@@ -380,15 +367,26 @@
template<typename ImplClass>
void
-SILCloner<ImplClass>::postProcess(SILInstruction *Orig,
- SILInstruction *Cloned) {
- assert((Orig->getDebugScope() ? Cloned->getDebugScope()!=nullptr : true) &&
+SILCloner<ImplClass>::postProcess(SILInstruction *orig,
+ SILInstruction *cloned) {
+ assert((orig->getDebugScope() ? cloned->getDebugScope()!=nullptr : true) &&
"cloned function dropped debug scope");
- // Remove any previous mappings for the Orig instruction.
- // If this is not done and there is a mapping for Orig in the map already,
- // then this new mapping will be silently ignored.
- InstructionMap.erase(Orig);
- InstructionMap.insert(std::make_pair(Orig, Cloned));
+
+ // It sometimes happens that an instruction with no results gets mapped
+ // to an instruction with results, e.g. when specializing a cast.
+ // Just ignore this.
+ auto origResults = orig->getResults();
+ if (origResults.empty()) return;
+
+ // Otherwise, map the results over one-by-one.
+ auto clonedResults = cloned->getResults();
+ assert(origResults.size() == clonedResults.size());
+ for (auto i : indices(origResults)) {
+ SILValue origResult = origResults[i], clonedResult = clonedResults[i];
+ auto insertion = ValueMap.insert(std::make_pair(origResult, clonedResult));
+ if (!insertion.second)
+ insertion.first->second = clonedResult;
+ }
}
/// \brief Recursively visit a callee's BBs in depth-first preorder (only
@@ -454,7 +452,7 @@
for (auto *Inst : ToRemove) {
// Replace any non-dead results with SILUndef values
- Inst->replaceAllUsesWithUndef();
+ Inst->replaceAllUsesOfAllResultsWithUndef();
Inst->eraseFromParent();
}
}
@@ -2121,7 +2119,8 @@
getOpValue(Inst->getCondition()),
getOpBasicBlock(Inst->getTrueBB()), TrueArgs,
getOpBasicBlock(Inst->getFalseBB()),
- FalseArgs));
+ FalseArgs, Inst->getTrueBBCount(),
+ Inst->getFalseBBCount()));
}
template<typename ImplClass>
@@ -2129,13 +2128,15 @@
SILCloner<ImplClass>::visitCheckedCastBranchInst(CheckedCastBranchInst *Inst) {
SILBasicBlock *OpSuccBB = getOpBasicBlock(Inst->getSuccessBB());
SILBasicBlock *OpFailBB = getOpBasicBlock(Inst->getFailureBB());
+ auto TrueCount = Inst->getTrueBBCount();
+ auto FalseCount = Inst->getFalseBBCount();
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
doPostProcess(Inst,
- getBuilder().createCheckedCastBranch(getOpLocation(Inst->getLoc()),
- Inst->isExact(),
- getOpValue(Inst->getOperand()),
- getOpType(Inst->getCastType()),
- OpSuccBB, OpFailBB));
+ getBuilder().createCheckedCastBranch(
+ getOpLocation(Inst->getLoc()), Inst->isExact(),
+ getOpValue(Inst->getOperand()),
+ getOpType(Inst->getCastType()), OpSuccBB, OpFailBB,
+ TrueCount, FalseCount));
}
template <typename ImplClass>
@@ -2160,12 +2161,13 @@
CanType SrcType = getOpASTType(Inst->getSourceType());
CanType TargetType = getOpASTType(Inst->getTargetType());
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
+ auto TrueCount = Inst->getTrueBBCount();
+ auto FalseCount = Inst->getFalseBBCount();
doPostProcess(Inst,
- getBuilder().createCheckedCastAddrBranch(getOpLocation(Inst->getLoc()),
- Inst->getConsumptionKind(),
- SrcValue, SrcType,
- DestValue, TargetType,
- OpSuccBB, OpFailBB));
+ getBuilder().createCheckedCastAddrBranch(
+ getOpLocation(Inst->getLoc()), Inst->getConsumptionKind(),
+ SrcValue, SrcType, DestValue, TargetType, OpSuccBB,
+ OpFailBB, TrueCount, FalseCount));
}
template<typename ImplClass>
diff --git a/include/swift/SIL/SILFunction.h b/include/swift/SIL/SILFunction.h
index 60e14dd..fe27083 100644
--- a/include/swift/SIL/SILFunction.h
+++ b/include/swift/SIL/SILFunction.h
@@ -17,6 +17,7 @@
#ifndef SWIFT_SIL_SILFUNCTION_H
#define SWIFT_SIL_SILFUNCTION_H
+#include "swift/Basic/ProfileCounter.h"
#include "swift/SIL/SILBasicBlock.h"
#include "swift/SIL/SILDebugScope.h"
#include "swift/SIL/SILLinkage.h"
@@ -180,6 +181,10 @@
/// The function's effects attribute.
EffectsKind EffectsKindAttr;
+ /// Has value if there's a profile for this function
+ /// Contains Function Entry Count
+ ProfileCounter EntryCount;
+
/// True if this function is inlined at least once. This means that the
/// debug info keeps a pointer to this function.
bool Inlined = false;
@@ -204,9 +209,9 @@
CanSILFunctionType loweredType, GenericEnvironment *genericEnv,
Optional<SILLocation> loc, IsBare_t isBareSILFunction,
IsTransparent_t isTrans, IsSerialized_t isSerialized,
- IsThunk_t isThunk, SubclassScope classSubclassScope,
- Inline_t inlineStrategy, EffectsKind E,
- SILFunction *insertBefore,
+ ProfileCounter entryCount, IsThunk_t isThunk,
+ SubclassScope classSubclassScope, Inline_t inlineStrategy,
+ EffectsKind E, SILFunction *insertBefore,
const SILDebugScope *debugScope);
static SILFunction *
@@ -214,7 +219,7 @@
CanSILFunctionType loweredType, GenericEnvironment *genericEnv,
Optional<SILLocation> loc, IsBare_t isBareSILFunction,
IsTransparent_t isTrans, IsSerialized_t isSerialized,
- IsThunk_t isThunk = IsNotThunk,
+ ProfileCounter entryCount, IsThunk_t isThunk = IsNotThunk,
SubclassScope classSubclassScope = SubclassScope::NotApplicable,
Inline_t inlineStrategy = InlineDefault,
EffectsKind EffectsKindAttr = EffectsKind::Unspecified,
@@ -236,6 +241,8 @@
return SILFunctionConventions(LoweredType, getModule());
}
+ ProfileCounter getEntryCount() const { return EntryCount; }
+
bool isNoReturnFunction() const;
/// Unsafely rewrite the lowered type of this function.
@@ -776,9 +783,12 @@
/// '@function_mangled_name'.
void printName(raw_ostream &OS) const;
- /// Assigns consecutive numbers to all SILValues in the function.
- void numberValues(llvm::DenseMap<const ValueBase*,
- unsigned> &ValueToNumberMap) const;
+ /// Assigns consecutive numbers to all the SILNodes in the function.
+ /// For instructions, both the instruction node and the value nodes of
+ /// any results will be assigned numbers; the instruction node will
+ /// be numbered the same as the first result, if there are any results.
+ void numberValues(llvm::DenseMap<const SILNode*, unsigned> &nodeToNumberMap)
+ const;
ASTContext &getASTContext() const;
diff --git a/include/swift/SIL/SILInstruction.h b/include/swift/SIL/SILInstruction.h
index 288bf2b..3efedff 100644
--- a/include/swift/SIL/SILInstruction.h
+++ b/include/swift/SIL/SILInstruction.h
@@ -23,10 +23,12 @@
#include "swift/AST/TypeAlignments.h"
#include "swift/Basic/Compiler.h"
#include "swift/Basic/NullablePtr.h"
+#include "swift/Basic/ProfileCounter.h"
+#include "swift/Basic/Range.h"
#include "swift/SIL/Consumption.h"
#include "swift/SIL/SILAllocated.h"
-#include "swift/SIL/SILFunctionConventions.h"
#include "swift/SIL/SILDeclRef.h"
+#include "swift/SIL/SILFunctionConventions.h"
#include "swift/SIL/SILLocation.h"
#include "swift/SIL/SILSuccessor.h"
#include "swift/SIL/SILValue.h"
@@ -62,21 +64,45 @@
// An enum class for SILInstructions that enables exhaustive switches over
// instructions.
-enum class SILInstructionKind : std::underlying_type<ValueKind>::type {
-#define INST(Id, Parent, TextualName, MemoryBehavior, ReleasingBehavior) \
- Id = static_cast<std::underlying_type<ValueKind>::type>(ValueKind::Id),
+enum class SILInstructionKind : std::underlying_type<SILNodeKind>::type {
+#define INST(ID, PARENT) \
+ ID = unsigned(SILNodeKind::ID),
+#define INST_RANGE(ID, FIRST, LAST) \
+ First_##ID = unsigned(SILNodeKind::First_##ID), \
+ Last_##ID = unsigned(SILNodeKind::Last_##ID),
#include "SILNodes.def"
};
+/// Return a range which can be used to easily iterate over all
+/// SILInstructionKinds.
+inline IntRange<SILInstructionKind> allSILInstructionKinds() {
+ return IntRange<SILInstructionKind>(
+ SILInstructionKind(SILNodeKind::First_SILInstruction),
+ SILInstructionKind(unsigned(SILNodeKind::Last_SILInstruction) + 1));
+}
+
/// Map SILInstruction's mnemonic name to its SILInstructionKind.
SILInstructionKind getSILInstructionKind(StringRef InstName);
/// Map SILInstructionKind to a corresponding SILInstruction name.
StringRef getSILInstructionName(SILInstructionKind Kind);
-/// This is the root class for all instructions that can be used as the contents
-/// of a Swift SILBasicBlock.
-class SILInstruction : public ValueBase,public llvm::ilist_node<SILInstruction>{
+/// This is the root class for all instructions that can be used as the
+/// contents of a Swift SILBasicBlock.
+///
+/// Most instructions are defined in terms of two basic kinds of
+/// structure: a list of operand values upon which the instruction depends
+/// and a list of result values upon which other instructions can depend.
+///
+/// The operands can be divided into two sets:
+/// - the formal operands of the instruction, which reflect its
+/// direct value dependencies, and
+/// - the type-dependent operands, which reflect dependencies that are
+/// not captured by the formal operands; currently, these dependencies
+/// only arise due to certain instructions (e.g. open_existential_addr)
+/// that bind new archetypes in the local context.
+class SILInstruction
+ : public SILNode, public llvm::ilist_node<SILInstruction> {
friend llvm::ilist_traits<SILInstruction>;
friend llvm::ilist_traits<SILBasicBlock>;
friend SILBasicBlock;
@@ -107,10 +133,22 @@
static int NumCreatedInstructions;
static int NumDeletedInstructions;
+ // Helper functions used by the ArrayRefViews below.
+ static SILValue projectValueBaseAsSILValue(const ValueBase &value) {
+ return &value;
+ }
+ static SILType projectValueBaseType(const ValueBase &value) {
+ return value.getType();
+ }
+
+ /// An internal method which retrieves the result values of the
+ /// instruction as an array of ValueBase objects.
+ ArrayRef<ValueBase> getResultsImpl() const;
+
protected:
- SILInstruction(ValueKind Kind, SILDebugLocation DebugLoc,
- SILType Ty = SILType())
- : ValueBase(Kind, Ty), ParentBB(0), Location(DebugLoc) {
+ SILInstruction(SILInstructionKind kind, SILDebugLocation DebugLoc)
+ : SILNode(SILNodeKind(kind), SILNodeStorageLocation::Instruction),
+ ParentBB(nullptr), Location(DebugLoc) {
NumCreatedInstructions++;
}
@@ -150,6 +188,22 @@
MayRelease,
};
+ LLVM_ATTRIBUTE_ALWAYS_INLINE
+ SILInstructionKind getKind() const {
+ return SILInstructionKind(SILNode::getKind());
+ }
+
+ SILNode *getCanonicalSILNodeInObject() {
+ assert(isCanonicalSILNodeInObject() &&
+ "the SILInstruction subobject is always canonical");
+ return this;
+ }
+ const SILNode *getCanonicalSILNodeInObject() const {
+ assert(isCanonicalSILNodeInObject() &&
+ "the SILInstruction subobject is always canonical");
+ return this;
+ }
+
const SILBasicBlock *getParent() const { return ParentBB; }
SILBasicBlock *getParent() { return ParentBB; }
@@ -189,6 +243,22 @@
/// \brief Drops all uses that belong to this instruction.
void dropAllReferences();
+ /// \brief Replace all uses of all results of this instruction with undef.
+ void replaceAllUsesOfAllResultsWithUndef();
+
+ /// \brief Replace all uses of all results of this instruction
+ /// with the parwise-corresponding results of the given instruction.
+ void replaceAllUsesPairwiseWith(SILInstruction *other);
+
+ /// \brief Are there uses of any of the results of this instruction?
+ bool hasUsesOfAnyResult() const {
+ for (auto result : getResults()) {
+ if (!result->use_empty())
+ return true;
+ }
+ return false;
+ }
+
/// Return the array of operands for this instruction.
ArrayRef<Operand> getAllOperands() const;
@@ -248,6 +318,20 @@
getAllOperands()[Num1].swap(getAllOperands()[Num2]);
}
+ using ResultArrayRef =
+ ArrayRefView<ValueBase,SILValue,projectValueBaseAsSILValue>;
+
+ /// Return the list of results produced by this instruction.
+ ResultArrayRef getResults() const { return getResultsImpl(); }
+
+ using ResultTypeArrayRef =
+ ArrayRefView<ValueBase,SILType,projectValueBaseType>;
+
+ /// Return the types of the results produced by this instruction.
+ ResultTypeArrayRef getResultTypes() const {
+ return getResultsImpl();
+ }
+
MemoryBehavior getMemoryBehavior() const;
ReleasingBehavior getReleasingBehavior() const;
@@ -272,14 +356,16 @@
/// using \p opEqual to compare operands.
///
template <typename OpCmp>
- bool isIdenticalTo(const SILInstruction *RHS, OpCmp opEqual) const {
+ bool isIdenticalTo(const SILInstruction *RHS, OpCmp &&opEqual) const {
// Quick check if both instructions have the same kind, number of operands,
// and types. This should filter out most cases.
if (getKind() != RHS->getKind() ||
- getNumOperands() != RHS->getNumOperands() ||
- getType() != RHS->getType()) {
+ getNumOperands() != RHS->getNumOperands()) {
return false;
}
+
+ if (getResultTypes() != RHS->getResultTypes())
+ return false;
// Check operands.
for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
@@ -328,11 +414,6 @@
/// The first operand must be the allocating instruction.
bool isDeallocatingStack() const;
- static bool classof(const ValueBase *V) {
- return V->getKind() >= ValueKind::First_SILInstruction &&
- V->getKind() <= ValueKind::Last_SILInstruction;
- }
-
/// Create a new copy of this instruction, which retains all of the operands
/// and other information of this one. If an insertion point is specified,
/// then the new instruction is inserted before the specified point, otherwise
@@ -362,8 +443,33 @@
static int getNumDeletedInstructions() {
return NumDeletedInstructions;
}
+
+ /// Pretty-print the value.
+ void dump() const;
+ void print(raw_ostream &OS) const;
+
+ /// Pretty-print the value in context, preceded by its operands (if the
+ /// value represents the result of an instruction) and followed by its
+ /// users.
+ void dumpInContext() const;
+ void printInContext(raw_ostream &OS) const;
+
+ static bool classof(const SILNode *N) {
+ return N->getKind() >= SILNodeKind::First_SILInstruction &&
+ N->getKind() <= SILNodeKind::Last_SILInstruction;
+ }
+ static bool classof(const SILInstruction *I) { return true; }
+
+ /// This is supportable but usually suggests a logic mistake.
+ static bool classof(const ValueBase *) = delete;
};
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+ const SILInstruction &I) {
+ I.print(OS);
+ return OS;
+}
+
/// Returns the combined behavior of \p B1 and \p B2.
inline SILInstruction::MemoryBehavior
combineMemoryBehavior(SILInstruction::MemoryBehavior B1,
@@ -386,48 +492,187 @@
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
SILInstruction::ReleasingBehavior B);
+/// An instruction which always produces a single value.
+///
+/// Because this instruction is both a SILInstruction and a ValueBase,
+/// both of which inherit from SILNode, it introduces the need for
+/// some care when working with SILNodes. See the comment on SILNode.
+class SingleValueInstruction : public SILInstruction, public ValueBase {
+ static bool isSingleValueInstKind(SILNodeKind kind) {
+ return kind >= SILNodeKind::First_SingleValueInstruction &&
+ kind <= SILNodeKind::Last_SingleValueInstruction;
+ }
+
+ friend class SILInstruction;
+ ArrayRef<ValueBase> getResultsImpl() const {
+ return ArrayRef<ValueBase>(this, 1);
+ }
+public:
+ SingleValueInstruction(SILInstructionKind kind, SILDebugLocation loc,
+ SILType type)
+ : SILInstruction(kind, loc),
+ ValueBase(ValueKind(kind), type) {
+ }
+
+ using SILInstruction::getFunction;
+ using SILInstruction::getModule;
+ using SILInstruction::getKind;
+ using SILInstruction::operator new;
+ using SILInstruction::dumpInContext;
+ using SILInstruction::print;
+ using SILInstruction::printInContext;
+
+ // Redeclare because lldb currently doesn't know about using-declarations
+ void dump() const;
+
+ void operator delete(void *Ptr, size_t) SWIFT_DELETE_OPERATOR_DELETED
+
+ ValueKind getValueKind() const {
+ return ValueBase::getKind();
+ }
+
+ SILNode *getCanonicalSILNodeInObject() {
+ assert(SILInstruction::isCanonicalSILNodeInObject() &&
+ "the SILInstruction subobject is always canonical");
+ return static_cast<SILInstruction*>(this);
+ }
+ const SILNode *getCanonicalSILNodeInObject() const {
+ assert(SILInstruction::isCanonicalSILNodeInObject() &&
+ "the SILInstruction subobject is always canonical");
+ return static_cast<const SILInstruction*>(this);
+ }
+
+ SingleValueInstruction *clone(SILInstruction *insertPt = nullptr) {
+ return cast<SingleValueInstruction>(SILInstruction::clone(insertPt));
+ }
+
+ /// Override this to reflect the more efficient access pattern.
+ ResultArrayRef getResults() const {
+ return getResultsImpl();
+ }
+
+ static bool classof(const SILNode *node) {
+ return isSingleValueInstKind(node->getKind());
+ }
+};
+
+// Resolve ambiguities.
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+ const SingleValueInstruction &I) {
+ I.print(OS);
+ return OS;
+}
+
+inline SingleValueInstruction *SILNode::castToSingleValueInstruction() {
+ assert(isa<SingleValueInstruction>(this));
+
+ // We do reference static_casts to convince the host compiler to do
+ // null-unchecked conversions.
+
+ // If we're in the value slot, cast through ValueBase.
+ if (getStorageLoc() == SILNodeStorageLocation::Value) {
+ return &static_cast<SingleValueInstruction&>(
+ static_cast<ValueBase&>(*this));
+
+ // Otherwise, cast through SILInstruction.
+ } else {
+ return &static_cast<SingleValueInstruction&>(
+ static_cast<SILInstruction&>(*this));
+ }
+}
+
+#define DEFINE_ABSTRACT_SINGLE_VALUE_INST_BOILERPLATE(ID) \
+ static bool classof(const SILNode *node) { \
+ return node->getKind() >= SILNodeKind::First_##ID && \
+ node->getKind() <= SILNodeKind::Last_##ID; \
+ } \
+ static bool classof(const SingleValueInstruction *inst) { \
+ return inst->getKind() >= SILInstructionKind::First_##ID && \
+ inst->getKind() <= SILInstructionKind::Last_##ID; \
+ }
+
+/// A subclass of SILInstruction which does not produce any values.
+class NonValueInstruction : public SILInstruction {
+public:
+ NonValueInstruction(SILInstructionKind kind, SILDebugLocation loc)
+ : SILInstruction(kind, loc) {}
+
+ /// Doesn't produce any results.
+ SILType getType() const = delete;
+ ResultArrayRef getResults() const = delete;
+};
+#define DEFINE_ABSTRACT_NON_VALUE_INST_BOILERPLATE(ID) \
+ static bool classof(const ValueBase *value) = delete; \
+ static bool classof(const SILNode *node) { \
+ return node->getKind() >= SILNodeKind::First_##ID && \
+ node->getKind() <= SILNodeKind::Last_##ID; \
+ }
+
+/// A helper class for defining some basic boilerplate.
+template <SILInstructionKind Kind, typename Base,
+ bool IsSingleResult =
+ std::is_base_of<SingleValueInstruction, Base>::value>
+class InstructionBase;
+
+template <SILInstructionKind Kind, typename Base>
+class InstructionBase<Kind, Base, /*HasResult*/ true> : public Base {
+protected:
+ template <typename... As>
+ InstructionBase(As &&...args)
+ : Base(Kind, std::forward<As>(args)...) {}
+
+public:
+ /// Override to statically return the kind.
+ static constexpr SILInstructionKind getKind() {
+ return Kind;
+ }
+
+ static bool classof(const SILNode *node) {
+ return node->getKind() == SILNodeKind(Kind);
+ }
+ static bool classof(const SingleValueInstruction *I) { // resolve ambiguities
+ return I->getKind() == Kind;
+ }
+};
+
+template <SILInstructionKind Kind, typename Base>
+class InstructionBase<Kind, Base, /*HasResult*/ false> : public Base {
+protected:
+ template <typename... As>
+ InstructionBase(As &&...args)
+ : Base(Kind, std::forward<As>(args)...) {}
+
+public:
+ static constexpr SILInstructionKind getKind() {
+ return Kind;
+ }
+
+ /// Can never dynamically succeed.
+ static bool classof(const ValueBase *value) = delete;
+
+ static bool classof(const SILNode *node) {
+ return node->getKind() == SILNodeKind(Kind);
+ }
+};
+
/// A template base class for instructions that take a single SILValue operand
/// and has no result or a single value result.
-template<ValueKind KIND, typename BASE = SILInstruction, bool HAS_RESULT = true>
-class UnaryInstructionBase : public BASE {
+template<SILInstructionKind Kind, typename Base>
+class UnaryInstructionBase : public InstructionBase<Kind, Base> {
// Space for 1 operand.
FixedOperandList<1> Operands;
- /// Check HAS_RESULT in enable_if predicates by injecting a dependency on
- /// a template argument.
- template<typename X>
- struct has_result {
- enum { value = HAS_RESULT };
- };
-
public:
- UnaryInstructionBase(SILDebugLocation DebugLoc, SILValue Operand)
- : BASE(KIND, DebugLoc), Operands(this, Operand) {}
-
- template <typename X = void>
- UnaryInstructionBase(
- SILDebugLocation DebugLoc, SILValue Operand,
- typename std::enable_if<has_result<X>::value, SILType>::type Ty)
- : BASE(KIND, DebugLoc, Ty), Operands(this, Operand) {}
-
- template <typename X = void, typename... A>
- UnaryInstructionBase(
- SILDebugLocation DebugLoc, SILValue Operand,
- typename std::enable_if<has_result<X>::value, SILType>::type Ty,
- A &&... args)
- : BASE(KIND, DebugLoc, Ty, std::forward<A>(args)...),
- Operands(this, Operand) {}
+ template <typename... A>
+ UnaryInstructionBase(SILDebugLocation loc, SILValue op, A &&... args)
+ : InstructionBase<Kind, Base>(loc, std::forward<A>(args)...),
+ Operands(this, op) {}
SILValue getOperand() const { return Operands[0].get(); }
void setOperand(SILValue V) { Operands[0].set(V); }
Operand &getOperandRef() { return Operands[0]; }
- /// getType() is ok if this is known to only have one type.
- template<typename X = void>
- typename std::enable_if<has_result<X>::value, SILType>::type
- getType() const { return ValueBase::getType(); }
-
ArrayRef<Operand> getAllOperands() const { return Operands.asArray(); }
MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
@@ -438,10 +683,6 @@
MutableArrayRef<Operand> getTypeDependentOperands() {
return {};
}
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == KIND;
- }
};
/// A template base class for instructions that take a single regular SILValue
@@ -449,24 +690,18 @@
/// or a single value result. The operands are tail allocated after the
/// instruction. Further trailing data can be allocated as well if
/// TRAILING_TYPES are provided.
-template<ValueKind KIND, typename DERIVED,
- typename BASE, bool HAS_RESULT,
- typename... TRAILING_TYPES>
-class UnaryInstructionWithTypeDependentOperandsBase :
- public BASE,
- protected llvm::TrailingObjects<DERIVED, Operand, TRAILING_TYPES...> {
-
- /// Check HAS_RESULT in enable_if predicates by injecting a dependency on
- /// a template argument.
- template<typename X>
- struct has_result {
- enum { value = HAS_RESULT };
- };
+template<SILInstructionKind Kind,
+ typename Derived,
+ typename Base,
+ typename... OtherTrailingTypes>
+class UnaryInstructionWithTypeDependentOperandsBase
+ : public InstructionBase<Kind, Base>,
+ protected llvm::TrailingObjects<Derived, Operand, OtherTrailingTypes...> {
protected:
- friend llvm::TrailingObjects<DERIVED, Operand, TRAILING_TYPES...>;
+ friend llvm::TrailingObjects<Derived, Operand, OtherTrailingTypes...>;
- typedef llvm::TrailingObjects<DERIVED, Operand, TRAILING_TYPES...>
+ typedef llvm::TrailingObjects<Derived, Operand, OtherTrailingTypes...>
TrailingObjects;
using TrailingObjects::totalSizeToAlloc;
@@ -476,6 +711,17 @@
unsigned NumOperands;
public:
+ template <typename... Args>
+ UnaryInstructionWithTypeDependentOperandsBase(
+ SILDebugLocation debugLoc, SILValue operand,
+ ArrayRef<SILValue> typeDependentOperands,
+ Args &&...args)
+ : InstructionBase<Kind, Base>(debugLoc, std::forward<Args>(args)...),
+ NumOperands(1 + typeDependentOperands.size()) {
+ TrailingOperandsList::InitOperandsList(getAllOperands().begin(), this,
+ operand, typeDependentOperands);
+ }
+
// Destruct tail allocated objects.
~UnaryInstructionWithTypeDependentOperandsBase() {
Operand *Operands = &getAllOperands()[0];
@@ -489,39 +735,6 @@
return NumOperands;
}
- UnaryInstructionWithTypeDependentOperandsBase(
- SILDebugLocation DebugLoc, SILValue Operand,
- ArrayRef<SILValue> TypeDependentOperands)
- : BASE(KIND, DebugLoc), NumOperands(1 + TypeDependentOperands.size()) {
- TrailingOperandsList::InitOperandsList(getAllOperands().begin(), this,
- Operand, TypeDependentOperands);
- }
-
- template <typename X = void>
- UnaryInstructionWithTypeDependentOperandsBase(
- SILDebugLocation DebugLoc, SILValue Operand,
- ArrayRef<SILValue> TypeDependentOperands,
- typename std::enable_if<has_result<X>::value, SILType>::type Ty)
- : BASE(KIND, DebugLoc, Ty),
- NumOperands(1 + TypeDependentOperands.size())
- {
- TrailingOperandsList::InitOperandsList(getAllOperands().begin(), this,
- Operand, TypeDependentOperands);
- }
-
- template <typename X = void, typename... A>
- UnaryInstructionWithTypeDependentOperandsBase(
- SILDebugLocation DebugLoc, SILValue Operand,
- ArrayRef<SILValue> TypeDependentOperands,
- typename std::enable_if<has_result<X>::value, SILType>::type Ty,
- A &&... args)
- : BASE(KIND, DebugLoc, Ty, std::forward<A>(args)...),
- NumOperands(1 + TypeDependentOperands.size())
- {
- TrailingOperandsList::InitOperandsList(getAllOperands().begin(), this,
- Operand, TypeDependentOperands);
- }
-
unsigned getNumTypeDependentOperands() const {
return NumOperands - 1;
}
@@ -531,11 +744,6 @@
Operand &getOperandRef() { return getAllOperands()[0]; }
- /// getType() is ok if this is known to only have one type.
- template<typename X = void>
- typename std::enable_if<has_result<X>::value, SILType>::type
- getType() const { return ValueBase::getType(); }
-
ArrayRef<Operand> getAllOperands() const {
return {TrailingObjects::template getTrailingObjects<Operand>(),
static_cast<size_t>(NumOperands)};
@@ -553,10 +761,6 @@
MutableArrayRef<Operand> getTypeDependentOperands() {
return getAllOperands().slice(1);
}
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == KIND;
- }
};
/// Holds common debug information about local variables and function
@@ -609,17 +813,13 @@
/// Abstract base class for allocation instructions, like alloc_stack, alloc_box
/// and alloc_ref, etc.
-class AllocationInst : public SILInstruction {
+class AllocationInst : public SingleValueInstruction {
protected:
- AllocationInst(ValueKind Kind, SILDebugLocation DebugLoc, SILType Ty)
- : SILInstruction(Kind, DebugLoc, Ty) {}
+ AllocationInst(SILInstructionKind Kind, SILDebugLocation DebugLoc, SILType Ty)
+ : SingleValueInstruction(Kind, DebugLoc, Ty) {}
public:
-
- static bool classof(const ValueBase *V) {
- return V->getKind() >= ValueKind::First_AllocationInst &&
- V->getKind() <= ValueKind::Last_AllocationInst;
- }
+ DEFINE_ABSTRACT_SINGLE_VALUE_INST_BOILERPLATE(AllocationInst)
};
/// Base class for allocation/deallocation instructions where the allocation
@@ -643,7 +843,8 @@
/// AllocStackInst - This represents the allocation of an unboxed (i.e., no
/// reference count) stack memory. The memory is provided uninitialized.
class AllocStackInst final
- : public AllocationInst,
+ : public InstructionBase<SILInstructionKind::AllocStackInst,
+ AllocationInst>,
private llvm::TrailingObjects<AllocStackInst, Operand, char> {
friend TrailingObjects;
friend SILBuilder;
@@ -704,10 +905,6 @@
MutableArrayRef<Operand> getTypeDependentOperands() {
return getAllOperands();
}
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::AllocStackInst;
- }
};
/// The base class for AllocRefInst and AllocRefDynamicInst.
@@ -716,7 +913,7 @@
public StackPromotable {
protected:
- AllocRefInstBase(ValueKind Kind,
+ AllocRefInstBase(SILInstructionKind Kind,
SILDebugLocation DebugLoc,
SILType ObjectType,
bool objc, bool canBeOnStack,
@@ -774,7 +971,9 @@
/// returned uninitialized.
/// Optionally, the allocated instance contains space for one or more tail-
/// allocated arrays.
-class AllocRefInst final : public AllocRefInstBase {
+class AllocRefInst final
+ : public InstructionBase<SILInstructionKind::AllocRefInst,
+ AllocRefInstBase> {
friend SILBuilder;
AllocRefInst(SILDebugLocation DebugLoc, SILFunction &F,
@@ -782,8 +981,8 @@
bool objc, bool canBeOnStack,
ArrayRef<SILType> ElementTypes,
ArrayRef<SILValue> AllOperands)
- : AllocRefInstBase(ValueKind::AllocRefInst, DebugLoc, ObjectType, objc,
- canBeOnStack, ElementTypes, AllOperands) {
+ : InstructionBase(DebugLoc, ObjectType, objc,
+ canBeOnStack, ElementTypes, AllOperands) {
static_assert(sizeof(AllocRefInst) == sizeof(AllocRefInstBase),
"subclass has extra storage");
}
@@ -803,10 +1002,6 @@
MutableArrayRef<Operand> getTypeDependentOperands() {
return getAllOperands().slice(NumTailTypes);
}
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::AllocRefInst;
- }
};
/// AllocRefDynamicInst - This represents the primitive allocation of
@@ -815,7 +1010,9 @@
/// instance is returned uninitialized.
/// Optionally, the allocated instance contains space for one or more tail-
/// allocated arrays.
-class AllocRefDynamicInst final : public AllocRefInstBase {
+class AllocRefDynamicInst final
+ : public InstructionBase<SILInstructionKind::AllocRefDynamicInst,
+ AllocRefInstBase> {
friend SILBuilder;
AllocRefDynamicInst(SILDebugLocation DebugLoc,
@@ -823,9 +1020,7 @@
bool objc,
ArrayRef<SILType> ElementTypes,
ArrayRef<SILValue> AllOperands)
- : AllocRefInstBase(ValueKind::AllocRefDynamicInst, DebugLoc,
- ty, objc, false,
- ElementTypes, AllOperands) {
+ : InstructionBase(DebugLoc, ty, objc, false, ElementTypes, AllOperands) {
static_assert(sizeof(AllocRefInst) == sizeof(AllocRefInstBase),
"subclass has extra storage");
}
@@ -849,19 +1044,14 @@
MutableArrayRef<Operand> getTypeDependentOperands() {
return getAllOperands().slice(NumTailTypes + 1);
}
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::AllocRefDynamicInst;
- }
};
/// AllocValueBufferInst - Allocate memory in a value buffer.
class AllocValueBufferInst final
: public UnaryInstructionWithTypeDependentOperandsBase<
- ValueKind::AllocValueBufferInst,
+ SILInstructionKind::AllocValueBufferInst,
AllocValueBufferInst,
- AllocationInst,
- true> {
+ AllocationInst> {
friend SILBuilder;
AllocValueBufferInst(SILDebugLocation DebugLoc, SILType valueType,
@@ -883,7 +1073,8 @@
/// is an address pointing to the contained element. The contained
/// element is uninitialized.
class AllocBoxInst final
- : public AllocationInst,
+ : public InstructionBase<SILInstructionKind::AllocBoxInst,
+ AllocationInst>,
private llvm::TrailingObjects<AllocBoxInst, Operand, char> {
friend TrailingObjects;
friend SILBuilder;
@@ -946,10 +1137,6 @@
MutableArrayRef<Operand> getTypeDependentOperands() {
return getAllOperands();
}
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::AllocBoxInst;
- }
};
/// This represents the allocation of a heap box for an existential container.
@@ -958,7 +1145,8 @@
/// is an address pointing to the contained element. The contained
/// value is uninitialized.
class AllocExistentialBoxInst final
- : public AllocationInst,
+ : public InstructionBase<SILInstructionKind::AllocExistentialBoxInst,
+ AllocationInst>,
private llvm::TrailingObjects<AllocExistentialBoxInst, Operand> {
friend TrailingObjects;
friend SILBuilder;
@@ -1008,10 +1196,6 @@
MutableArrayRef<Operand> getTypeDependentOperands() {
return getAllOperands();
}
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::AllocExistentialBoxInst;
- }
};
/// GenericSpecializationInformation - provides information about a generic
@@ -1088,7 +1272,7 @@
protected:
template <class... As>
- ApplyInstBase(ValueKind kind, SILDebugLocation DebugLoc, SILValue callee,
+ ApplyInstBase(SILInstructionKind kind, SILDebugLocation DebugLoc, SILValue callee,
SILType substCalleeType, SubstitutionList substitutions,
ArrayRef<SILValue> args,
ArrayRef<SILValue> TypeDependentOperands,
@@ -1344,7 +1528,9 @@
};
/// ApplyInst - Represents the full application of a function value.
-class ApplyInst : public ApplyInstBase<ApplyInst, SILInstruction> {
+class ApplyInst
+ : public InstructionBase<SILInstructionKind::ApplyInst,
+ ApplyInstBase<ApplyInst, SingleValueInstruction>> {
friend SILBuilder;
ApplyInst(SILDebugLocation DebugLoc, SILValue Callee,
@@ -1363,10 +1549,6 @@
const GenericSpecializationInformation *SpecializationInfo);
public:
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::ApplyInst;
- }
-
/// Returns true if the called function has an error result but is not actually
/// throwing an error.
bool isNonThrowing() const {
@@ -1377,7 +1559,9 @@
/// PartialApplyInst - Represents the creation of a closure object by partial
/// application of a function value.
class PartialApplyInst
- : public ApplyInstBase<PartialApplyInst, SILInstruction> {
+ : public InstructionBase<SILInstructionKind::PartialApplyInst,
+ ApplyInstBase<PartialApplyInst,
+ SingleValueInstruction>> {
friend SILBuilder;
PartialApplyInst(SILDebugLocation DebugLoc, SILValue Callee,
@@ -1399,10 +1583,6 @@
CanSILFunctionType getFunctionType() const {
return getType().castTo<SILFunctionType>();
}
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::PartialApplyInst;
- }
};
//===----------------------------------------------------------------------===//
@@ -1410,21 +1590,20 @@
//===----------------------------------------------------------------------===//
/// Abstract base class for literal instructions.
-class LiteralInst : public SILInstruction {
+class LiteralInst : public SingleValueInstruction {
protected:
- LiteralInst(ValueKind Kind, SILDebugLocation DebugLoc, SILType Ty)
- : SILInstruction(Kind, DebugLoc, Ty) {}
+ LiteralInst(SILInstructionKind Kind, SILDebugLocation DebugLoc, SILType Ty)
+ : SingleValueInstruction(Kind, DebugLoc, Ty) {}
public:
- static bool classof(const ValueBase *V) {
- return V->getKind() >= ValueKind::First_LiteralInst &&
- V->getKind() <= ValueKind::Last_LiteralInst;
- }
+ DEFINE_ABSTRACT_SINGLE_VALUE_INST_BOILERPLATE(LiteralInst)
};
/// FunctionRefInst - Represents a reference to a SIL function.
-class FunctionRefInst : public LiteralInst {
+class FunctionRefInst
+ : public InstructionBase<SILInstructionKind::FunctionRefInst,
+ LiteralInst> {
friend SILBuilder;
SILFunction *Function;
@@ -1451,10 +1630,6 @@
ArrayRef<Operand> getAllOperands() const { return {}; }
MutableArrayRef<Operand> getAllOperands() { return {}; }
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::FunctionRefInst;
- }
};
/// Component of a KeyPathInst.
@@ -1821,9 +1996,9 @@
/// Instantiates a key path object.
class KeyPathInst final
- : public SILInstruction,
- private llvm::TrailingObjects<KeyPathInst, Substitution, Operand>
-{
+ : public InstructionBase<SILInstructionKind::KeyPathInst,
+ SingleValueInstruction>,
+ private llvm::TrailingObjects<KeyPathInst, Substitution, Operand> {
friend SILBuilder;
friend TrailingObjects;
@@ -1864,10 +2039,6 @@
return const_cast<KeyPathInst*>(this)->getSubstitutions();
}
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::KeyPathInst;
- }
-
void dropReferencedPattern();
~KeyPathInst();
@@ -1875,7 +2046,9 @@
/// Represents an invocation of builtin functionality provided by the code
/// generator.
-class BuiltinInst : public SILInstruction {
+class BuiltinInst
+ : public InstructionBase<SILInstructionKind::BuiltinInst,
+ SingleValueInstruction> {
friend SILBuilder;
/// The name of the builtin to invoke.
@@ -1963,15 +2136,13 @@
OperandValueArrayRef getArguments() const {
return Operands.asValueArray();
}
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::BuiltinInst;
- }
};
/// Initializes a SIL global variable. Only valid once, before any
/// usages of the global via GlobalAddrInst.
-class AllocGlobalInst : public SILInstruction {
+class AllocGlobalInst
+ : public InstructionBase<SILInstructionKind::AllocGlobalInst,
+ SILInstruction> {
friend SILBuilder;
SILGlobalVariable *Global;
@@ -1979,12 +2150,6 @@
AllocGlobalInst(SILDebugLocation DebugLoc, SILGlobalVariable *Global);
public:
- // FIXME: This constructor should be private but is currently used
- // in the SILParser.
-
- /// Create a placeholder instruction with an unset global reference.
- AllocGlobalInst(SILDebugLocation DebugLoc);
-
/// Return the referenced global variable.
SILGlobalVariable *getReferencedGlobal() const { return Global; }
@@ -1992,10 +2157,6 @@
ArrayRef<Operand> getAllOperands() const { return {}; }
MutableArrayRef<Operand> getAllOperands() { return {}; }
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::AllocGlobalInst;
- }
};
/// The base class for global_addr and global_value.
@@ -2003,9 +2164,9 @@
SILGlobalVariable *Global;
protected:
- GlobalAccessInst(ValueKind valueKind, SILDebugLocation DebugLoc,
- SILGlobalVariable *Global, SILType Ty)
- : LiteralInst(valueKind, DebugLoc, Ty), Global(Global) { }
+ GlobalAccessInst(SILInstructionKind kind, SILDebugLocation loc,
+ SILType ty, SILGlobalVariable *global)
+ : LiteralInst(kind, loc, ty), Global(global) { }
public:
/// Return the referenced global variable.
@@ -2019,7 +2180,9 @@
/// Gives the address of a SIL global variable. Only valid after an
/// AllocGlobalInst.
-class GlobalAddrInst : public GlobalAccessInst {
+class GlobalAddrInst
+ : public InstructionBase<SILInstructionKind::GlobalAddrInst,
+ GlobalAccessInst> {
friend SILBuilder;
GlobalAddrInst(SILDebugLocation DebugLoc, SILGlobalVariable *Global);
@@ -2029,31 +2192,27 @@
/// Create a placeholder instruction with an unset global reference.
GlobalAddrInst(SILDebugLocation DebugLoc, SILType Ty)
- : GlobalAccessInst(ValueKind::GlobalAddrInst, DebugLoc, nullptr, Ty) { }
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::GlobalAddrInst;
- }
+ : InstructionBase(DebugLoc, Ty, nullptr) { }
};
/// Gives the value of a global variable.
///
/// The referenced global variable must be a statically initialized object.
/// TODO: in future we might support global variables in general.
-class GlobalValueInst : public GlobalAccessInst {
+class GlobalValueInst
+ : public InstructionBase<SILInstructionKind::GlobalValueInst,
+ GlobalAccessInst> {
friend SILBuilder;
GlobalValueInst(SILDebugLocation DebugLoc, SILGlobalVariable *Global);
-public:
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::GlobalValueInst;
- }
};
/// IntegerLiteralInst - Encapsulates an integer constant, as defined originally
/// by an IntegerLiteralExpr.
-class IntegerLiteralInst final : public LiteralInst,
- private llvm::TrailingObjects<IntegerLiteralInst, llvm::APInt::WordType> {
+class IntegerLiteralInst final
+ : public InstructionBase<SILInstructionKind::IntegerLiteralInst,
+ LiteralInst>,
+ private llvm::TrailingObjects<IntegerLiteralInst, llvm::APInt::WordType> {
friend TrailingObjects;
friend SILBuilder;
@@ -2074,16 +2233,14 @@
ArrayRef<Operand> getAllOperands() const { return {}; }
MutableArrayRef<Operand> getAllOperands() { return {}; }
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::IntegerLiteralInst;
- }
};
/// FloatLiteralInst - Encapsulates a floating point constant, as defined
/// originally by a FloatLiteralExpr.
-class FloatLiteralInst final : public LiteralInst,
- private llvm::TrailingObjects<FloatLiteralInst, llvm::APInt::WordType> {
+class FloatLiteralInst final
+ : public InstructionBase<SILInstructionKind::FloatLiteralInst,
+ LiteralInst>,
+ private llvm::TrailingObjects<FloatLiteralInst, llvm::APInt::WordType> {
friend TrailingObjects;
friend SILBuilder;
@@ -2105,17 +2262,15 @@
ArrayRef<Operand> getAllOperands() const { return {}; }
MutableArrayRef<Operand> getAllOperands() { return {}; }
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::FloatLiteralInst;
- }
};
/// StringLiteralInst - Encapsulates a string constant, as defined originally by
/// a StringLiteralExpr. This produces the address of the string data as a
/// Builtin.RawPointer.
-class StringLiteralInst final : public LiteralInst,
- private llvm::TrailingObjects<StringLiteralInst, char> {
+class StringLiteralInst final
+ : public InstructionBase<SILInstructionKind::StringLiteralInst,
+ LiteralInst>,
+ private llvm::TrailingObjects<StringLiteralInst, char> {
friend TrailingObjects;
friend SILBuilder;
@@ -2152,10 +2307,6 @@
ArrayRef<Operand> getAllOperands() const { return {}; }
MutableArrayRef<Operand> getAllOperands() { return {}; }
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::StringLiteralInst;
- }
};
/// ConstStringLiteralInst - Encapsulates a string constant, as defined
@@ -2163,7 +2314,8 @@
/// a StringLiteralExpr. This produces the address of the string data as a
/// Builtin.RawPointer.
class ConstStringLiteralInst final
- : public LiteralInst,
+ : public InstructionBase<SILInstructionKind::ConstStringLiteralInst,
+ LiteralInst>,
private llvm::TrailingObjects<ConstStringLiteralInst, char> {
friend TrailingObjects;
friend SILBuilder;
@@ -2198,11 +2350,8 @@
ArrayRef<Operand> getAllOperands() const { return {}; }
MutableArrayRef<Operand> getAllOperands() { return {}; }
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::ConstStringLiteralInst;
- }
};
+
//===----------------------------------------------------------------------===//
// Memory instructions.
//===----------------------------------------------------------------------===//
@@ -2220,7 +2369,8 @@
/// LoadInst - Represents a load from a memory location.
class LoadInst
- : public UnaryInstructionBase<ValueKind::LoadInst>
+ : public UnaryInstructionBase<SILInstructionKind::LoadInst,
+ SingleValueInstruction>
{
friend SILBuilder;
@@ -2251,7 +2401,9 @@
};
/// StoreInst - Represents a store from a memory location.
-class StoreInst : public SILInstruction {
+class StoreInst
+ : public InstructionBase<SILInstructionKind::StoreInst,
+ NonValueInstruction> {
friend SILBuilder;
private:
@@ -2275,10 +2427,6 @@
ArrayRef<Operand> getAllOperands() const { return Operands.asArray(); }
MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::StoreInst;
- }
-
StoreOwnershipQualifier getOwnershipQualifier() const {
return OwnershipQualifier;
}
@@ -2286,7 +2434,9 @@
/// Represents a load of a borrowed value. Must be paired with an end_borrow
/// instruction in its use-def list.
-class LoadBorrowInst : public UnaryInstructionBase<ValueKind::LoadBorrowInst> {
+class LoadBorrowInst :
+ public UnaryInstructionBase<SILInstructionKind::LoadBorrowInst,
+ SingleValueInstruction> {
friend class SILBuilder;
LoadBorrowInst(SILDebugLocation DebugLoc, SILValue LValue)
@@ -2297,7 +2447,8 @@
/// Represents the begin scope of a borrowed value. Must be paired with an
/// end_borrow instruction in its use-def list.
class BeginBorrowInst
- : public UnaryInstructionBase<ValueKind::BeginBorrowInst> {
+ : public UnaryInstructionBase<SILInstructionKind::BeginBorrowInst,
+ SingleValueInstruction> {
friend class SILBuilder;
BeginBorrowInst(SILDebugLocation DebugLoc, SILValue LValue)
@@ -2307,7 +2458,9 @@
/// Represents a store of a borrowed value into an address. Returns the borrowed
/// address. Must be paired with an end_borrow in its use-def list.
-class StoreBorrowInst : public SILInstruction {
+class StoreBorrowInst
+ : public InstructionBase<SILInstructionKind::StoreBorrowInst,
+ SingleValueInstruction> {
friend class SILBuilder;
public:
@@ -2328,10 +2481,6 @@
ArrayRef<Operand> getAllOperands() const { return Operands.asArray(); }
MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::StoreBorrowInst;
- }
};
/// Represents the end of a borrow scope for a value or address from another
@@ -2340,7 +2489,9 @@
/// The semantics of the instruction here is that the "dest" SILValue can not be
/// used after this instruction and the "src" SILValue must stay alive up to
/// EndBorrowInst.
-class EndBorrowInst : public SILInstruction {
+class EndBorrowInst
+ : public InstructionBase<SILInstructionKind::EndBorrowInst,
+ NonValueInstruction> {
friend class SILBuilder;
public:
@@ -2363,10 +2514,6 @@
ArrayRef<Operand> getAllOperands() const { return Operands.asArray(); }
MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::EndBorrowInst;
- }
};
/// Represents the end of a borrow scope for an argument. The reason why this is
@@ -2374,7 +2521,8 @@
/// specific SSA value. Instead it is borrowed from potentially many different
/// incoming values.
class EndBorrowArgumentInst
- : public UnaryInstructionBase<ValueKind::EndBorrowArgumentInst> {
+ : public UnaryInstructionBase<SILInstructionKind::EndBorrowArgumentInst,
+ NonValueInstruction> {
friend class SILBuilder;
EndBorrowArgumentInst(SILDebugLocation DebugLoc, SILArgument *Arg);
@@ -2429,7 +2577,8 @@
/// Begins an access scope. Must be paired with an end_access instruction
/// along every path.
class BeginAccessInst
- : public UnaryInstructionBase<ValueKind::BeginAccessInst> {
+ : public UnaryInstructionBase<SILInstructionKind::BeginAccessInst,
+ SingleValueInstruction> {
friend class SILBuilder;
SILAccessKind AccessKind;
@@ -2478,7 +2627,9 @@
};
/// Represents the end of an access scope.
-class EndAccessInst : public UnaryInstructionBase<ValueKind::EndAccessInst> {
+class EndAccessInst
+ : public UnaryInstructionBase<SILInstructionKind::EndAccessInst,
+ NonValueInstruction> {
friend class SILBuilder;
bool Aborting;
@@ -2531,7 +2682,9 @@
///
/// This should only be used in materializeForSet, and eventually it should
/// be removed entirely.
-class BeginUnpairedAccessInst : public SILInstruction {
+class BeginUnpairedAccessInst
+ : public InstructionBase<SILInstructionKind::BeginUnpairedAccessInst,
+ NonValueInstruction> {
friend class SILBuilder;
FixedOperandList<2> Operands;
@@ -2542,8 +2695,7 @@
BeginUnpairedAccessInst(SILDebugLocation loc, SILValue addr, SILValue buffer,
SILAccessKind accessKind,
SILAccessEnforcement enforcement)
- : SILInstruction(ValueKind::BeginUnpairedAccessInst,
- loc, addr->getType()),
+ : InstructionBase(loc),
Operands(this, addr, buffer),
AccessKind(accessKind), Enforcement(enforcement) {
}
@@ -2581,15 +2733,12 @@
MutableArrayRef<Operand> getTypeDependentOperands() {
return {};
}
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::BeginUnpairedAccessInst;
- }
};
/// Ends an unpaired access.
class EndUnpairedAccessInst
- : public UnaryInstructionBase<ValueKind::EndUnpairedAccessInst> {
+ : public UnaryInstructionBase<SILInstructionKind::EndUnpairedAccessInst,
+ NonValueInstruction> {
friend class SILBuilder;
SILAccessEnforcement Enforcement;
@@ -2632,7 +2781,9 @@
/// AssignInst - Represents an abstract assignment to a memory location, which
/// may either be an initialization or a store sequence. This is only valid in
/// Raw SIL.
-class AssignInst : public SILInstruction {
+class AssignInst
+ : public InstructionBase<SILInstructionKind::AssignInst,
+ NonValueInstruction> {
friend SILBuilder;
enum {
@@ -2656,10 +2807,6 @@
ArrayRef<Operand> getAllOperands() const { return Operands.asArray(); }
MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::AssignInst;
- }
};
/// Abstract base class for instructions that mark storage as uninitialized.
@@ -2668,7 +2815,8 @@
/// this point and needs to be initialized by the end of the function and before
/// any escape point for this instruction. This is only valid in Raw SIL.
class MarkUninitializedInst
- : public UnaryInstructionBase<ValueKind::MarkUninitializedInst> {
+ : public UnaryInstructionBase<SILInstructionKind::MarkUninitializedInst,
+ SingleValueInstruction> {
friend SILBuilder;
public:
@@ -2724,7 +2872,9 @@
/// the logical initialization state of the property.
///
/// This is only valid in Raw SIL.
-class MarkUninitializedBehaviorInst final : public SILInstruction,
+class MarkUninitializedBehaviorInst final
+ : public InstructionBase<SILInstructionKind::MarkUninitializedBehaviorInst,
+ SingleValueInstruction>,
private llvm::TrailingObjects<MarkUninitializedBehaviorInst, Substitution>
{
friend SILBuilder;
@@ -2791,16 +2941,14 @@
ArrayRef<Operand> getAllOperands() const { return Operands.asArray(); }
MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::MarkUninitializedBehaviorInst;
- }
};
/// MarkFunctionEscape - Represents the escape point of set of variables due to
/// a function definition which uses the variables. This is only valid in Raw
/// SIL.
-class MarkFunctionEscapeInst : public SILInstruction {
+class MarkFunctionEscapeInst
+ : public InstructionBase<SILInstructionKind::MarkFunctionEscapeInst,
+ NonValueInstruction> {
friend SILBuilder;
TailAllocatedOperandList<0> Operands;
@@ -2828,17 +2976,14 @@
ArrayRef<Operand> getAllOperands() const { return Operands.asArray(); }
MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::MarkFunctionEscapeInst;
- }
};
/// Define the start or update to a symbolic variable value (for loadable
/// types).
class DebugValueInst final
- : public UnaryInstructionBase<ValueKind::DebugValueInst>,
- private llvm::TrailingObjects<DebugValueInst, char> {
+ : public UnaryInstructionBase<SILInstructionKind::DebugValueInst,
+ NonValueInstruction>,
+ private llvm::TrailingObjects<DebugValueInst, char> {
friend TrailingObjects;
friend SILBuilder;
TailAllocatedDebugVariable VarInfo;
@@ -2863,7 +3008,8 @@
/// Define the start or update to a symbolic variable value (for address-only
/// types) .
class DebugValueAddrInst final
- : public UnaryInstructionBase<ValueKind::DebugValueAddrInst>,
+ : public UnaryInstructionBase<SILInstructionKind::DebugValueAddrInst,
+ NonValueInstruction>,
private llvm::TrailingObjects<DebugValueAddrInst, char> {
friend TrailingObjects;
friend SILBuilder;
@@ -2887,8 +3033,9 @@
/// An abstract class representing a load from some kind of reference storage.
-template <ValueKind K>
-class LoadReferenceInstBase : public UnaryInstructionBase<K> {
+template <SILInstructionKind K>
+class LoadReferenceInstBase
+ : public UnaryInstructionBase<K, SingleValueInstruction> {
static SILType getResultType(SILType operandTy) {
assert(operandTy.isAddress() && "loading from non-address operand?");
auto refType = cast<ReferenceStorageType>(operandTy.getSwiftRValueType());
@@ -2899,7 +3046,8 @@
protected:
LoadReferenceInstBase(SILDebugLocation loc, SILValue lvalue, IsTake_t isTake)
- : UnaryInstructionBase<K>(loc, lvalue, getResultType(lvalue->getType())),
+ : UnaryInstructionBase<K, SingleValueInstruction>(loc, lvalue,
+ getResultType(lvalue->getType())),
IsTake(unsigned(isTake)) {
}
@@ -2908,15 +3056,16 @@
};
/// An abstract class representing a store to some kind of reference storage.
-template <ValueKind K>
-class StoreReferenceInstBase : public SILInstruction {
+template <SILInstructionKind K>
+class StoreReferenceInstBase : public InstructionBase<K, NonValueInstruction> {
enum { Src, Dest };
FixedOperandList<2> Operands;
unsigned IsInitializationOfDest : 1; // FIXME: pack this somewhere
protected:
StoreReferenceInstBase(SILDebugLocation loc, SILValue src, SILValue dest,
IsInitialization_t isInit)
- : SILInstruction(K, loc), Operands(this, src, dest),
+ : InstructionBase<K, NonValueInstruction>(loc),
+ Operands(this, src, dest),
IsInitializationOfDest(unsigned(isInit)) {
}
@@ -2933,15 +3082,11 @@
ArrayRef<Operand> getAllOperands() const { return Operands.asArray(); }
MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == K;
- }
};
/// Represents a load from a @weak memory location.
class LoadWeakInst
- : public LoadReferenceInstBase<ValueKind::LoadWeakInst>
+ : public LoadReferenceInstBase<SILInstructionKind::LoadWeakInst>
{
friend SILBuilder;
@@ -2954,7 +3099,7 @@
/// Represents a store to a @weak memory location.
class StoreWeakInst
- : public StoreReferenceInstBase<ValueKind::StoreWeakInst>
+ : public StoreReferenceInstBase<SILInstructionKind::StoreWeakInst>
{
friend SILBuilder;
@@ -2968,7 +3113,7 @@
/// This is only required for address-only unowned references; for loadable
/// unowned references, it's better to use a load and a strong_retain_unowned.
class LoadUnownedInst
- : public LoadReferenceInstBase<ValueKind::LoadUnownedInst>
+ : public LoadReferenceInstBase<SILInstructionKind::LoadUnownedInst>
{
friend SILBuilder;
@@ -2984,7 +3129,7 @@
/// This is only required for address-only unowned references; for loadable
/// unowned references, it's better to use a ref_to_unowned and a store.
class StoreUnownedInst
- : public StoreReferenceInstBase<ValueKind::StoreUnownedInst>
+ : public StoreReferenceInstBase<SILInstructionKind::StoreUnownedInst>
{
friend SILBuilder;
@@ -2998,7 +3143,9 @@
/// %1 = load %src
/// store %1 to %dest
/// but a copy instruction must be used for address-only types.
-class CopyAddrInst : public SILInstruction {
+class CopyAddrInst
+ : public InstructionBase<SILInstructionKind::CopyAddrInst,
+ NonValueInstruction> {
friend SILBuilder;
public:
@@ -3047,10 +3194,6 @@
ArrayRef<Operand> getAllOperands() const { return Operands.asArray(); }
MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::CopyAddrInst;
- }
};
/// BindMemoryInst -
@@ -3058,7 +3201,8 @@
/// Binds memory at the raw pointer %0 to type $T with enough capacity
/// to hold $1 values.
class BindMemoryInst final :
- public SILInstruction,
+ public InstructionBase<SILInstructionKind::BindMemoryInst,
+ NonValueInstruction>,
protected llvm::TrailingObjects<BindMemoryInst, Operand> {
typedef llvm::TrailingObjects<BindMemoryInst, Operand> TrailingObjects;
@@ -3120,10 +3264,6 @@
MutableArrayRef<Operand> getTypeDependentOperands() {
return getAllOperands().slice(2);
}
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::BindMemoryInst;
- }
};
//===----------------------------------------------------------------------===//
@@ -3133,10 +3273,10 @@
/// ConversionInst - Abstract class representing instructions that convert
/// values.
///
-class ConversionInst : public SILInstruction {
+class ConversionInst : public SingleValueInstruction {
protected:
- ConversionInst(ValueKind Kind, SILDebugLocation DebugLoc, SILType Ty)
- : SILInstruction(Kind, DebugLoc, Ty) {}
+ ConversionInst(SILInstructionKind Kind, SILDebugLocation DebugLoc, SILType Ty)
+ : SingleValueInstruction(Kind, DebugLoc, Ty) {}
public:
/// All conversion instructions take the converted value, whose reference
@@ -3145,18 +3285,15 @@
/// affect the reference identity.
SILValue getConverted() const { return getOperand(0); }
- static bool classof(const ValueBase *V) {
- return V->getKind() >= ValueKind::First_ConversionInst &&
- V->getKind() <= ValueKind::Last_ConversionInst;
- }
+ DEFINE_ABSTRACT_SINGLE_VALUE_INST_BOILERPLATE(ConversionInst)
};
/// ConvertFunctionInst - Change the type of a function value without
/// affecting how it will codegen.
class ConvertFunctionInst final
: public UnaryInstructionWithTypeDependentOperandsBase<
- ValueKind::ConvertFunctionInst, ConvertFunctionInst, ConversionInst,
- /* HAS_RESULT */ true> {
+ SILInstructionKind::ConvertFunctionInst,
+ ConvertFunctionInst, ConversionInst> {
friend SILBuilder;
ConvertFunctionInst(SILDebugLocation DebugLoc, SILValue Operand,
@@ -3172,7 +3309,7 @@
/// ThinFunctionToPointerInst - Convert a thin function pointer to a
/// Builtin.RawPointer.
class ThinFunctionToPointerInst
- : public UnaryInstructionBase<ValueKind::ThinFunctionToPointerInst,
+ : public UnaryInstructionBase<SILInstructionKind::ThinFunctionToPointerInst,
ConversionInst>
{
friend SILBuilder;
@@ -3186,8 +3323,9 @@
/// function pointer.
class PointerToThinFunctionInst final
: public UnaryInstructionWithTypeDependentOperandsBase<
- ValueKind::PointerToThinFunctionInst, PointerToThinFunctionInst,
- ConversionInst, /* HAS_RESULT */ true> {
+ SILInstructionKind::PointerToThinFunctionInst,
+ PointerToThinFunctionInst,
+ ConversionInst> {
friend SILBuilder;
PointerToThinFunctionInst(SILDebugLocation DebugLoc, SILValue operand,
@@ -3202,9 +3340,10 @@
};
/// UpcastInst - Perform a conversion of a class instance to a supertype.
-class UpcastInst final : public UnaryInstructionWithTypeDependentOperandsBase<
- ValueKind::UpcastInst, UpcastInst, ConversionInst,
- /* HAS_RESULT */ true>
+class UpcastInst final
+ : public UnaryInstructionWithTypeDependentOperandsBase<
+ SILInstructionKind::UpcastInst,
+ UpcastInst, ConversionInst>
{
friend SILBuilder;
@@ -3221,7 +3360,8 @@
/// AddressToPointerInst - Convert a SIL address to a Builtin.RawPointer value.
class AddressToPointerInst
- : public UnaryInstructionBase<ValueKind::AddressToPointerInst, ConversionInst>
+ : public UnaryInstructionBase<SILInstructionKind::AddressToPointerInst,
+ ConversionInst>
{
friend SILBuilder;
@@ -3231,7 +3371,8 @@
/// PointerToAddressInst - Convert a Builtin.RawPointer value to a SIL address.
class PointerToAddressInst
- : public UnaryInstructionBase<ValueKind::PointerToAddressInst, ConversionInst>
+ : public UnaryInstructionBase<SILInstructionKind::PointerToAddressInst,
+ ConversionInst>
{
friend SILBuilder;
@@ -3257,10 +3398,9 @@
/// checks.
class UncheckedRefCastInst final
: public UnaryInstructionWithTypeDependentOperandsBase<
- ValueKind::UncheckedRefCastInst,
+ SILInstructionKind::UncheckedRefCastInst,
UncheckedRefCastInst,
- ConversionInst,
- /* HAS_RESULT */ true>
+ ConversionInst>
{
friend SILBuilder;
@@ -3277,7 +3417,9 @@
/// checks. This is a variant of UncheckedRefCast that works on address types,
/// thus encapsulates an implicit load and take of the reference followed by a
/// store and initialization of a new reference.
-class UncheckedRefCastAddrInst : public SILInstruction {
+class UncheckedRefCastAddrInst
+ : public InstructionBase<SILInstructionKind::UncheckedRefCastAddrInst,
+ NonValueInstruction> {
public:
enum {
/// the value being stored
@@ -3305,18 +3447,13 @@
ArrayRef<Operand> getAllOperands() const { return Operands.asArray(); }
MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::UncheckedRefCastAddrInst;
- }
};
class UncheckedAddrCastInst final
: public UnaryInstructionWithTypeDependentOperandsBase<
- ValueKind::UncheckedAddrCastInst,
+ SILInstructionKind::UncheckedAddrCastInst,
UncheckedAddrCastInst,
- ConversionInst,
- true>
+ ConversionInst>
{
friend SILBuilder;
@@ -3332,10 +3469,9 @@
/// Convert a value's binary representation to a trivial type of the same size.
class UncheckedTrivialBitCastInst final
: public UnaryInstructionWithTypeDependentOperandsBase<
- ValueKind::UncheckedTrivialBitCastInst,
+ SILInstructionKind::UncheckedTrivialBitCastInst,
UncheckedTrivialBitCastInst,
- ConversionInst,
- true>
+ ConversionInst>
{
friend SILBuilder;
@@ -3353,10 +3489,9 @@
/// Bitwise copy a value into another value of the same size or smaller.
class UncheckedBitwiseCastInst final
: public UnaryInstructionWithTypeDependentOperandsBase<
- ValueKind::UncheckedBitwiseCastInst,
+ SILInstructionKind::UncheckedBitwiseCastInst,
UncheckedBitwiseCastInst,
- ConversionInst,
- true>
+ ConversionInst>
{
friend SILBuilder;
@@ -3372,31 +3507,27 @@
/// Build a Builtin.BridgeObject from a heap object reference by bitwise-or-ing
/// in bits from a word.
-class RefToBridgeObjectInst : public ConversionInst {
+class RefToBridgeObjectInst
+ : public InstructionBase<SILInstructionKind::RefToBridgeObjectInst,
+ ConversionInst> {
friend SILBuilder;
FixedOperandList<2> Operands;
RefToBridgeObjectInst(SILDebugLocation DebugLoc, SILValue ConvertedValue,
SILValue MaskValue, SILType BridgeObjectTy)
- : ConversionInst(ValueKind::RefToBridgeObjectInst, DebugLoc,
- BridgeObjectTy),
+ : InstructionBase(DebugLoc, BridgeObjectTy),
Operands(this, ConvertedValue, MaskValue) {}
public:
-
SILValue getBitsOperand() const { return Operands[1].get(); }
ArrayRef<Operand> getAllOperands() const { return Operands.asArray(); }
MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::RefToBridgeObjectInst;
- }
};
/// Extract the heap object reference from a BridgeObject.
class BridgeObjectToRefInst
- : public UnaryInstructionBase<ValueKind::BridgeObjectToRefInst,
+ : public UnaryInstructionBase<SILInstructionKind::BridgeObjectToRefInst,
ConversionInst>
{
friend SILBuilder;
@@ -3408,7 +3539,7 @@
/// Retrieve the bit pattern of a BridgeObject.
class BridgeObjectToWordInst
- : public UnaryInstructionBase<ValueKind::BridgeObjectToWordInst,
+ : public UnaryInstructionBase<SILInstructionKind::BridgeObjectToWordInst,
ConversionInst>
{
friend SILBuilder;
@@ -3420,7 +3551,8 @@
/// RefToRawPointer - Convert a reference type to a Builtin.RawPointer.
class RefToRawPointerInst
- : public UnaryInstructionBase<ValueKind::RefToRawPointerInst, ConversionInst>
+ : public UnaryInstructionBase<SILInstructionKind::RefToRawPointerInst,
+ ConversionInst>
{
friend SILBuilder;
@@ -3430,7 +3562,8 @@
/// RawPointerToRefInst - Convert a Builtin.RawPointer to a reference type.
class RawPointerToRefInst
- : public UnaryInstructionBase<ValueKind::RawPointerToRefInst, ConversionInst>
+ : public UnaryInstructionBase<SILInstructionKind::RawPointerToRefInst,
+ ConversionInst>
{
friend SILBuilder;
@@ -3443,7 +3576,8 @@
///
/// This does nothing at runtime; it just changes the formal type.
class RefToUnownedInst
- : public UnaryInstructionBase<ValueKind::RefToUnownedInst, ConversionInst>
+ : public UnaryInstructionBase<SILInstructionKind::RefToUnownedInst,
+ ConversionInst>
{
friend SILBuilder;
@@ -3456,7 +3590,8 @@
///
/// This does nothing at runtime; it just changes the formal type.
class UnownedToRefInst
- : public UnaryInstructionBase<ValueKind::UnownedToRefInst, ConversionInst>
+ : public UnaryInstructionBase<SILInstructionKind::UnownedToRefInst,
+ ConversionInst>
{
friend SILBuilder;
@@ -3469,7 +3604,8 @@
///
/// This does nothing at runtime; it just changes the formal type.
class RefToUnmanagedInst
- : public UnaryInstructionBase<ValueKind::RefToUnmanagedInst, ConversionInst>
+ : public UnaryInstructionBase<SILInstructionKind::RefToUnmanagedInst,
+ ConversionInst>
{
friend SILBuilder;
@@ -3482,7 +3618,8 @@
///
/// This does nothing at runtime; it just changes the formal type.
class UnmanagedToRefInst
- : public UnaryInstructionBase<ValueKind::UnmanagedToRefInst, ConversionInst>
+ : public UnaryInstructionBase<SILInstructionKind::UnmanagedToRefInst,
+ ConversionInst>
{
friend SILBuilder;
@@ -3494,8 +3631,8 @@
/// context to convert the value to a thick function type.
class ThinToThickFunctionInst final
: public UnaryInstructionWithTypeDependentOperandsBase<
- ValueKind::ThinToThickFunctionInst, ThinToThickFunctionInst,
- ConversionInst, /* HAS_RESULT */ true> {
+ SILInstructionKind::ThinToThickFunctionInst, ThinToThickFunctionInst,
+ ConversionInst> {
friend SILBuilder;
ThinToThickFunctionInst(SILDebugLocation DebugLoc, SILValue Operand,
@@ -3519,7 +3656,7 @@
/// Given a thick metatype value, produces an Objective-C metatype
/// value.
class ThickToObjCMetatypeInst
- : public UnaryInstructionBase<ValueKind::ThickToObjCMetatypeInst,
+ : public UnaryInstructionBase<SILInstructionKind::ThickToObjCMetatypeInst,
ConversionInst>
{
friend SILBuilder;
@@ -3532,7 +3669,7 @@
/// Given an Objective-C metatype value, produces a thick metatype
/// value.
class ObjCToThickMetatypeInst
- : public UnaryInstructionBase<ValueKind::ObjCToThickMetatypeInst,
+ : public UnaryInstructionBase<SILInstructionKind::ObjCToThickMetatypeInst,
ConversionInst>
{
friend SILBuilder;
@@ -3544,7 +3681,7 @@
/// Given an Objective-C metatype value, convert it to an AnyObject value.
class ObjCMetatypeToObjectInst
- : public UnaryInstructionBase<ValueKind::ObjCMetatypeToObjectInst,
+ : public UnaryInstructionBase<SILInstructionKind::ObjCMetatypeToObjectInst,
ConversionInst>
{
friend SILBuilder;
@@ -3557,7 +3694,7 @@
/// Given an Objective-C existential metatype value, convert it to an AnyObject
/// value.
class ObjCExistentialMetatypeToObjectInst
- : public UnaryInstructionBase<ValueKind::ObjCExistentialMetatypeToObjectInst,
+ : public UnaryInstructionBase<SILInstructionKind::ObjCExistentialMetatypeToObjectInst,
ConversionInst>
{
friend SILBuilder;
@@ -3568,13 +3705,14 @@
};
/// Return the Objective-C Protocol class instance for a protocol.
-class ObjCProtocolInst : public SILInstruction
-{
+class ObjCProtocolInst
+ : public InstructionBase<SILInstructionKind::ObjCProtocolInst,
+ SingleValueInstruction> {
friend SILBuilder;
ProtocolDecl *Proto;
ObjCProtocolInst(SILDebugLocation DebugLoc, ProtocolDecl *Proto, SILType Ty)
- : SILInstruction(ValueKind::ObjCProtocolInst, DebugLoc, Ty),
+ : InstructionBase(DebugLoc, Ty),
Proto(Proto) {}
public:
@@ -3582,14 +3720,12 @@
ArrayRef<Operand> getAllOperands() const { return {}; }
MutableArrayRef<Operand> getAllOperands() { return {}; }
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::ObjCProtocolInst;
- }
};
/// Test that an address or reference type is not null.
-class IsNonnullInst : public UnaryInstructionBase<ValueKind::IsNonnullInst> {
+class IsNonnullInst
+ : public UnaryInstructionBase<SILInstructionKind::IsNonnullInst,
+ SingleValueInstruction> {
friend SILBuilder;
IsNonnullInst(SILDebugLocation DebugLoc, SILValue Operand, SILType BoolTy)
@@ -3600,10 +3736,9 @@
/// Perform an unconditional checked cast that aborts if the cast fails.
class UnconditionalCheckedCastInst final
: public UnaryInstructionWithTypeDependentOperandsBase<
- ValueKind::UnconditionalCheckedCastInst,
+ SILInstructionKind::UnconditionalCheckedCastInst,
UnconditionalCheckedCastInst,
- ConversionInst,
- true>
+ ConversionInst>
{
friend SILBuilder;
@@ -3634,8 +3769,9 @@
/// Perform an unconditional checked cast that aborts if the cast fails.
/// The result of the checked cast is left in the destination address.
-class UnconditionalCheckedCastAddrInst : public SILInstruction
-{
+class UnconditionalCheckedCastAddrInst
+ : public InstructionBase<SILInstructionKind::UnconditionalCheckedCastAddrInst,
+ NonValueInstruction> {
friend SILBuilder;
enum {
@@ -3664,18 +3800,14 @@
ArrayRef<Operand> getAllOperands() const { return Operands.asArray(); }
MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::UnconditionalCheckedCastAddrInst;
- }
};
/// Perform an unconditional checked cast that aborts if the cast fails.
/// The result of the checked cast is left in the destination.
class UnconditionalCheckedCastValueInst final
: public UnaryInstructionWithTypeDependentOperandsBase<
- ValueKind::UnconditionalCheckedCastValueInst,
- UnconditionalCheckedCastValueInst, ConversionInst, true> {
+ SILInstructionKind::UnconditionalCheckedCastValueInst,
+ UnconditionalCheckedCastValueInst, ConversionInst> {
friend SILBuilder;
UnconditionalCheckedCastValueInst(SILDebugLocation DebugLoc, SILValue Operand,
@@ -3690,7 +3822,9 @@
};
/// StructInst - Represents a constructed loadable struct.
-class StructInst : public SILInstruction {
+class StructInst
+ : public InstructionBase<SILInstructionKind::StructInst,
+ SingleValueInstruction> {
friend SILBuilder;
TailAllocatedOperandList<0> Operands;
@@ -3779,15 +3913,11 @@
assert(s && "A struct should always have a StructDecl associated with it");
return s;
}
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::StructInst;
- }
};
/// RefCountingInst - An abstract class of instructions which
/// manipulate the reference count of their object operand.
-class RefCountingInst : public SILInstruction {
+class RefCountingInst : public NonValueInstruction {
public:
/// The atomicity of a reference counting operation to be used.
enum class Atomicity : bool {
@@ -3799,30 +3929,24 @@
protected:
Atomicity atomicity;
protected:
- RefCountingInst(ValueKind Kind, SILDebugLocation DebugLoc)
- : SILInstruction(Kind, DebugLoc), atomicity(Atomicity::Atomic) {}
-
- RefCountingInst(ValueKind Kind, SILDebugLocation DebugLoc, SILType Type)
- : SILInstruction(Kind, DebugLoc, Type), atomicity(Atomicity::Atomic) {}
+ RefCountingInst(SILInstructionKind Kind, SILDebugLocation DebugLoc)
+ : NonValueInstruction(Kind, DebugLoc), atomicity(Atomicity::Atomic) {}
public:
- static bool classof(const ValueBase *V) {
- return V->getKind() >= ValueKind::First_RefCountingInst &&
- V->getKind() <= ValueKind::Last_RefCountingInst;
- }
-
void setAtomicity(Atomicity flag) { atomicity = flag; }
void setNonAtomic() { atomicity = Atomicity::NonAtomic; }
void setAtomic() { atomicity = Atomicity::Atomic; }
Atomicity getAtomicity() const { return atomicity; }
bool isNonAtomic() const { return atomicity == Atomicity::NonAtomic; }
bool isAtomic() const { return atomicity == Atomicity::Atomic; }
+
+ DEFINE_ABSTRACT_NON_VALUE_INST_BOILERPLATE(RefCountingInst)
};
/// RetainValueInst - Copies a loadable value.
-class RetainValueInst : public UnaryInstructionBase<ValueKind::RetainValueInst,
- RefCountingInst,
- /*HasValue*/ false> {
+class RetainValueInst
+ : public UnaryInstructionBase<SILInstructionKind::RetainValueInst,
+ RefCountingInst> {
friend SILBuilder;
RetainValueInst(SILDebugLocation DebugLoc, SILValue operand,
@@ -3834,8 +3958,8 @@
/// RetainValueAddrInst - Copies a loadable value by address.
class RetainValueAddrInst
- : public UnaryInstructionBase<ValueKind::RetainValueAddrInst,
- RefCountingInst, /*HasValue*/ false> {
+ : public UnaryInstructionBase<SILInstructionKind::RetainValueAddrInst,
+ RefCountingInst> {
friend SILBuilder;
RetainValueAddrInst(SILDebugLocation DebugLoc, SILValue operand,
@@ -3846,9 +3970,9 @@
};
/// ReleaseValueInst - Destroys a loadable value.
-class ReleaseValueInst : public UnaryInstructionBase<ValueKind::ReleaseValueInst,
- RefCountingInst,
- /*HasValue*/ false> {
+class ReleaseValueInst
+ : public UnaryInstructionBase<SILInstructionKind::ReleaseValueInst,
+ RefCountingInst> {
friend SILBuilder;
ReleaseValueInst(SILDebugLocation DebugLoc, SILValue operand,
@@ -3860,8 +3984,8 @@
/// ReleaseValueInst - Destroys a loadable value by address.
class ReleaseValueAddrInst
- : public UnaryInstructionBase<ValueKind::ReleaseValueAddrInst,
- RefCountingInst, /*HasValue*/ false> {
+ : public UnaryInstructionBase<SILInstructionKind::ReleaseValueAddrInst,
+ RefCountingInst> {
friend SILBuilder;
ReleaseValueAddrInst(SILDebugLocation DebugLoc, SILValue operand,
@@ -3875,9 +3999,8 @@
/// in ownership qualified SIL. Please do not use this EVER unless you are
/// implementing a part of the stdlib called Unmanaged.
class UnmanagedRetainValueInst
- : public UnaryInstructionBase<ValueKind::UnmanagedRetainValueInst,
- RefCountingInst,
- /*HasValue*/ false> {
+ : public UnaryInstructionBase<SILInstructionKind::UnmanagedRetainValueInst,
+ RefCountingInst> {
friend SILBuilder;
UnmanagedRetainValueInst(SILDebugLocation DebugLoc, SILValue operand,
@@ -3891,9 +4014,8 @@
/// use in ownership qualified SIL. Please do not use this EVER unless you are
/// implementing a part of the stdlib called Unmanaged.
class UnmanagedReleaseValueInst
- : public UnaryInstructionBase<ValueKind::UnmanagedReleaseValueInst,
- RefCountingInst,
- /*HasValue*/ false> {
+ : public UnaryInstructionBase<SILInstructionKind::UnmanagedReleaseValueInst,
+ RefCountingInst> {
friend SILBuilder;
UnmanagedReleaseValueInst(SILDebugLocation DebugLoc, SILValue operand,
@@ -3906,9 +4028,8 @@
/// Transfers ownership of a loadable value to the current autorelease
/// pool. Unmanaged, so it is ignored from an ownership balancing perspective.
class UnmanagedAutoreleaseValueInst
- : public UnaryInstructionBase<ValueKind::UnmanagedAutoreleaseValueInst,
- RefCountingInst,
- /*HasValue*/ false> {
+ : public UnaryInstructionBase<SILInstructionKind::UnmanagedAutoreleaseValueInst,
+ RefCountingInst> {
friend SILBuilder;
UnmanagedAutoreleaseValueInst(SILDebugLocation DebugLoc, SILValue operand,
@@ -3920,9 +4041,8 @@
/// Transfers ownership of a loadable value to the current autorelease pool.
class AutoreleaseValueInst
- : public UnaryInstructionBase<ValueKind::AutoreleaseValueInst,
- RefCountingInst,
- /*HasValue*/ false> {
+ : public UnaryInstructionBase<SILInstructionKind::AutoreleaseValueInst,
+ RefCountingInst> {
friend SILBuilder;
AutoreleaseValueInst(SILDebugLocation DebugLoc, SILValue operand,
@@ -3937,9 +4057,8 @@
/// This is the same operation what's done by a strong_release immediately
/// before it calls the deallocator of the object.
class SetDeallocatingInst
- : public UnaryInstructionBase<ValueKind::SetDeallocatingInst,
- RefCountingInst,
- /*HasValue*/ false> {
+ : public UnaryInstructionBase<SILInstructionKind::SetDeallocatingInst,
+ RefCountingInst> {
friend SILBuilder;
SetDeallocatingInst(SILDebugLocation DebugLoc, SILValue operand,
@@ -3956,21 +4075,36 @@
/// operations. (This should generally be straightforward, as pin and
/// unpin may be conservatively assumed to have arbitrary
/// side-effects.)
+///
+/// This can't be a RefCountingInst because it returns a value.
class StrongPinInst
- : public UnaryInstructionBase<ValueKind::StrongPinInst, RefCountingInst,
- /*HasResult*/ true>
+ : public UnaryInstructionBase<SILInstructionKind::StrongPinInst,
+ SingleValueInstruction>
{
+public:
+ using Atomicity = RefCountingInst::Atomicity;
+
+private:
friend SILBuilder;
+ Atomicity atomicity;
StrongPinInst(SILDebugLocation DebugLoc, SILValue operand,
Atomicity atomicity);
+
+public:
+ void setAtomicity(Atomicity flag) { atomicity = flag; }
+ void setNonAtomic() { atomicity = Atomicity::NonAtomic; }
+ void setAtomic() { atomicity = Atomicity::Atomic; }
+ Atomicity getAtomicity() const { return atomicity; }
+ bool isNonAtomic() const { return atomicity == Atomicity::NonAtomic; }
+ bool isAtomic() const { return atomicity == Atomicity::Atomic; }
};
/// StrongUnpinInst - Given that the operand is the result of a
/// strong_pin instruction, unpin it.
class StrongUnpinInst
- : public UnaryInstructionBase<ValueKind::StrongUnpinInst, RefCountingInst,
- /*HasResult*/ false>
+ : public UnaryInstructionBase<SILInstructionKind::StrongUnpinInst,
+ RefCountingInst>
{
friend SILBuilder;
@@ -3985,7 +4119,9 @@
///
/// This instruction can only appear at the end of a gobal variable's
/// static initializer list.
-class ObjectInst : public SILInstruction {
+class ObjectInst
+ : public InstructionBase<SILInstructionKind::ObjectInst,
+ SingleValueInstruction> {
friend SILBuilder;
unsigned NumBaseElements;
@@ -4025,15 +4161,13 @@
ArrayRef<Operand> getAllOperands() const { return Operands.asArray(); }
MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::ObjectInst;
- }
};
/// TupleInst - Represents a constructed loadable tuple.
-class TupleInst : public SILInstruction {
+class TupleInst
+ : public InstructionBase<SILInstructionKind::TupleInst,
+ SingleValueInstruction> {
friend SILBuilder;
TailAllocatedOperandList<0> Operands;
@@ -4071,10 +4205,6 @@
ArrayRef<Operand> getAllOperands() const { return Operands.asArray(); }
MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::TupleInst;
- }
-
TupleType *getTupleType() const {
return getType().getSwiftRValueType()->castTo<TupleType>();
}
@@ -4112,7 +4242,9 @@
/// Represents a loadable enum constructed from one of its
/// elements.
-class EnumInst : public SILInstruction {
+class EnumInst
+ : public InstructionBase<SILInstructionKind::EnumInst,
+ SingleValueInstruction> {
friend SILBuilder;
Optional<FixedOperandList<1>> OptionalOperand;
@@ -4120,7 +4252,7 @@
EnumInst(SILDebugLocation DebugLoc, SILValue Operand,
EnumElementDecl *Element, SILType ResultTy)
- : SILInstruction(ValueKind::EnumInst, DebugLoc, ResultTy),
+ : InstructionBase(DebugLoc, ResultTy),
Element(Element) {
if (Operand) {
OptionalOperand.emplace(this, Operand);
@@ -4143,16 +4275,13 @@
return OptionalOperand
? OptionalOperand->asArray() : MutableArrayRef<Operand>{};
}
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::EnumInst;
- }
};
/// Unsafely project the data for an enum case out of an enum without checking
/// the tag.
class UncheckedEnumDataInst
- : public UnaryInstructionBase<ValueKind::UncheckedEnumDataInst>
+ : public UnaryInstructionBase<SILInstructionKind::UncheckedEnumDataInst,
+ SingleValueInstruction>
{
friend SILBuilder;
@@ -4186,7 +4315,8 @@
/// Projects the address of the data for a case inside an uninitialized enum in
/// order to initialize the payload for that case.
class InitEnumDataAddrInst
- : public UnaryInstructionBase<ValueKind::InitEnumDataAddrInst>
+ : public UnaryInstructionBase<SILInstructionKind::InitEnumDataAddrInst,
+ SingleValueInstruction>
{
friend SILBuilder;
@@ -4203,9 +4333,8 @@
/// InjectEnumAddrInst - Tags an enum as containing a case. The data for
/// that case, if any, must have been written into the enum first.
class InjectEnumAddrInst
- : public UnaryInstructionBase<ValueKind::InjectEnumAddrInst,
- SILInstruction,
- /*HAS_RESULT*/ false>
+ : public UnaryInstructionBase<SILInstructionKind::InjectEnumAddrInst,
+ NonValueInstruction>
{
friend SILBuilder;
@@ -4222,7 +4351,8 @@
/// Invalidate an enum value and take ownership of its payload data
/// without moving it in memory.
class UncheckedTakeEnumDataAddrInst
- : public UnaryInstructionBase<ValueKind::UncheckedTakeEnumDataAddrInst>
+ : public UnaryInstructionBase<SILInstructionKind::UncheckedTakeEnumDataAddrInst,
+ SingleValueInstruction>
{
friend SILBuilder;
@@ -4259,7 +4389,7 @@
// The template parameter represents a type of case values to be compared
// with the operand of a select instruction.
template <class Derived, class T>
-class SelectInstBase : public SILInstruction {
+class SelectInstBase : public SingleValueInstruction {
protected:
unsigned NumCases : 31;
unsigned HasDefault : 1;
@@ -4269,10 +4399,10 @@
TailAllocatedOperandList<1> Operands;
public:
- SelectInstBase(ValueKind kind, SILDebugLocation DebugLoc, SILType type,
- unsigned numCases, bool hasDefault,
+ SelectInstBase(SILInstructionKind kind, SILDebugLocation DebugLoc,
+ SILType type, unsigned numCases, bool hasDefault,
ArrayRef<SILValue> operands, SILValue operand)
- : SILInstruction(kind, DebugLoc, type), NumCases(numCases),
+ : SingleValueInstruction(kind, DebugLoc, type), NumCases(numCases),
HasDefault(hasDefault), Operands(this, operands, operand) {}
SILValue getOperand() const { return Operands[0].get(); }
@@ -4309,17 +4439,19 @@
}
protected:
- SelectEnumInstBase(
- ValueKind Kind, SILDebugLocation DebugLoc, SILValue Enum, SILType Type,
- SILValue DefaultValue,
- ArrayRef<std::pair<EnumElementDecl *, SILValue>> CaseValues);
-
+ SelectEnumInstBase(SILInstructionKind kind, SILDebugLocation debugLoc,
+ SILType type, SILValue enumValue, SILValue defaultValue,
+ ArrayRef<std::pair<EnumElementDecl *, SILValue>> cases,
+ Optional<ArrayRef<ProfileCounter>> CaseCounts,
+ ProfileCounter DefaultCount);
template <typename SELECT_ENUM_INST>
static SELECT_ENUM_INST *
createSelectEnum(SILDebugLocation DebugLoc, SILValue Enum, SILType Type,
SILValue DefaultValue,
ArrayRef<std::pair<EnumElementDecl *, SILValue>> CaseValues,
- SILFunction &F);
+ SILFunction &F,
+ Optional<ArrayRef<ProfileCounter>> CaseCounts,
+ ProfileCounter DefaultCount);
public:
SILValue getEnumOperand() const { return getOperand(); }
@@ -4360,7 +4492,9 @@
};
/// Select one of a set of values based on the case of an enum.
-class SelectEnumInst : public SelectEnumInstBase {
+class SelectEnumInst
+ : public InstructionBase<SILInstructionKind::SelectEnumInst,
+ SelectEnumInstBase> {
friend SILBuilder;
private:
@@ -4368,48 +4502,46 @@
SelectEnumInst(SILDebugLocation DebugLoc, SILValue Operand, SILType Type,
SILValue DefaultValue,
- ArrayRef<std::pair<EnumElementDecl *, SILValue>> CaseValues)
- : SelectEnumInstBase(ValueKind::SelectEnumInst, DebugLoc, Operand, Type,
- DefaultValue, CaseValues) {}
-
+ ArrayRef<std::pair<EnumElementDecl *, SILValue>> CaseValues,
+ Optional<ArrayRef<ProfileCounter>> CaseCounts,
+ ProfileCounter DefaultCount)
+ : InstructionBase(DebugLoc, Type, Operand, DefaultValue, CaseValues,
+ CaseCounts, DefaultCount) {}
static SelectEnumInst *
create(SILDebugLocation DebugLoc, SILValue Operand, SILType Type,
SILValue DefaultValue,
ArrayRef<std::pair<EnumElementDecl *, SILValue>> CaseValues,
- SILFunction &F);
-
-public:
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::SelectEnumInst;
- }
+ SILFunction &F, Optional<ArrayRef<ProfileCounter>> CaseCounts,
+ ProfileCounter DefaultCount);
};
/// Select one of a set of values based on the case of an enum.
-class SelectEnumAddrInst : public SelectEnumInstBase {
+class SelectEnumAddrInst
+ : public InstructionBase<SILInstructionKind::SelectEnumAddrInst,
+ SelectEnumInstBase> {
friend SILBuilder;
friend SelectEnumInstBase;
SelectEnumAddrInst(
SILDebugLocation DebugLoc, SILValue Operand, SILType Type,
SILValue DefaultValue,
- ArrayRef<std::pair<EnumElementDecl *, SILValue>> CaseValues)
- : SelectEnumInstBase(ValueKind::SelectEnumAddrInst, DebugLoc, Operand,
- Type, DefaultValue, CaseValues) {}
-
+ ArrayRef<std::pair<EnumElementDecl *, SILValue>> CaseValues,
+ Optional<ArrayRef<ProfileCounter>> CaseCounts,
+ ProfileCounter DefaultCount)
+ : InstructionBase(DebugLoc, Type, Operand, DefaultValue, CaseValues,
+ CaseCounts, DefaultCount) {}
static SelectEnumAddrInst *
create(SILDebugLocation DebugLoc, SILValue Operand, SILType Type,
SILValue DefaultValue,
ArrayRef<std::pair<EnumElementDecl *, SILValue>> CaseValues,
- SILFunction &F);
-
-public:
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::SelectEnumAddrInst;
- }
+ SILFunction &F, Optional<ArrayRef<ProfileCounter>> CaseCounts,
+ ProfileCounter DefaultCount);
};
/// Select on a value of a builtin integer type.
-class SelectValueInst : public SelectInstBase<SelectValueInst, SILValue> {
+class SelectValueInst
+ : public InstructionBase<SILInstructionKind::SelectValueInst,
+ SelectInstBase<SelectValueInst, SILValue>> {
friend SILBuilder;
SelectValueInst(SILDebugLocation DebugLoc, SILValue Operand, SILType Type,
@@ -4438,16 +4570,13 @@
assert(HasDefault && "doesn't have a default");
return getCaseBuf()[NumCases*2];
}
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::SelectValueInst;
- }
};
/// MetatypeInst - Represents the production of an instance of a given metatype
/// named statically.
class MetatypeInst final
- : public SILInstruction,
+ : public InstructionBase<SILInstructionKind::MetatypeInst,
+ SingleValueInstruction>,
private llvm::TrailingObjects<MetatypeInst, Operand> {
friend TrailingObjects;
friend SILBuilder;
@@ -4485,15 +4614,12 @@
MutableArrayRef<Operand> getTypeDependentOperands() {
return { getTrailingObjects<Operand>(), NumOperands };
}
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::MetatypeInst;
- }
};
/// Represents loading a dynamic metatype from a value.
class ValueMetatypeInst
- : public UnaryInstructionBase<ValueKind::ValueMetatypeInst>
+ : public UnaryInstructionBase<SILInstructionKind::ValueMetatypeInst,
+ SingleValueInstruction>
{
friend SILBuilder;
@@ -4504,7 +4630,8 @@
/// ExistentialMetatype - Represents loading a dynamic metatype from an
/// existential container.
class ExistentialMetatypeInst
- : public UnaryInstructionBase<ValueKind::ExistentialMetatypeInst>
+ : public UnaryInstructionBase<SILInstructionKind::ExistentialMetatypeInst,
+ SingleValueInstruction>
{
friend SILBuilder;
@@ -4515,7 +4642,8 @@
/// Extract a numbered element out of a value of tuple type.
class TupleExtractInst
- : public UnaryInstructionBase<ValueKind::TupleExtractInst>
+ : public UnaryInstructionBase<SILInstructionKind::TupleExtractInst,
+ SingleValueInstruction>
{
friend SILBuilder;
@@ -4544,7 +4672,8 @@
/// Derive the address of a numbered element from the address of a tuple.
class TupleElementAddrInst
- : public UnaryInstructionBase<ValueKind::TupleElementAddrInst>
+ : public UnaryInstructionBase<SILInstructionKind::TupleElementAddrInst,
+ SingleValueInstruction>
{
friend SILBuilder;
@@ -4565,7 +4694,8 @@
/// Extract a physical, fragile field out of a value of struct type.
class StructExtractInst
- : public UnaryInstructionBase<ValueKind::StructExtractInst>
+ : public UnaryInstructionBase<SILInstructionKind::StructExtractInst,
+ SingleValueInstruction>
{
friend SILBuilder;
@@ -4607,7 +4737,8 @@
/// Derive the address of a physical field from the address of a struct.
class StructElementAddrInst
- : public UnaryInstructionBase<ValueKind::StructElementAddrInst>
+ : public UnaryInstructionBase<SILInstructionKind::StructElementAddrInst,
+ SingleValueInstruction>
{
friend SILBuilder;
@@ -4641,7 +4772,8 @@
/// RefElementAddrInst - Derive the address of a named element in a reference
/// type instance.
class RefElementAddrInst
- : public UnaryInstructionBase<ValueKind::RefElementAddrInst>
+ : public UnaryInstructionBase<SILInstructionKind::RefElementAddrInst,
+ SingleValueInstruction>
{
friend SILBuilder;
@@ -4675,7 +4807,8 @@
/// RefTailAddrInst - Derive the address of the first element of the first
/// tail-allocated array in a reference type instance.
class RefTailAddrInst
- : public UnaryInstructionBase<ValueKind::RefTailAddrInst>
+ : public UnaryInstructionBase<SILInstructionKind::RefTailAddrInst,
+ SingleValueInstruction>
{
friend SILBuilder;
@@ -4694,13 +4827,13 @@
/// MethodInst - Abstract base for instructions that implement dynamic
/// method lookup.
-class MethodInst : public SILInstruction {
+class MethodInst : public SingleValueInstruction {
SILDeclRef Member;
bool Volatile;
public:
- MethodInst(ValueKind Kind, SILDebugLocation DebugLoc, SILType Ty,
+ MethodInst(SILInstructionKind Kind, SILDebugLocation DebugLoc, SILType Ty,
SILDeclRef Member, bool Volatile = false)
- : SILInstruction(Kind, DebugLoc, Ty), Member(Member), Volatile(Volatile) {
+ : SingleValueInstruction(Kind, DebugLoc, Ty), Member(Member), Volatile(Volatile) {
}
SILDeclRef getMember() const { return Member; }
@@ -4708,17 +4841,15 @@
/// True if this dynamic dispatch is semantically required.
bool isVolatile() const { return Volatile; }
- static bool classof(const ValueBase *V) {
- return V->getKind() >= ValueKind::First_MethodInst &&
- V->getKind() <= ValueKind::Last_MethodInst;
- }
+ DEFINE_ABSTRACT_SINGLE_VALUE_INST_BOILERPLATE(MethodInst)
};
/// ClassMethodInst - Given the address of a value of class type and a method
/// constant, extracts the implementation of that method for the dynamic
/// instance type of the class.
class ClassMethodInst
- : public UnaryInstructionBase<ValueKind::ClassMethodInst, MethodInst>
+ : public UnaryInstructionBase<SILInstructionKind::ClassMethodInst,
+ MethodInst>
{
friend SILBuilder;
@@ -4731,7 +4862,7 @@
/// constant, extracts the implementation of that method for the superclass of
/// the static type of the class.
class SuperMethodInst
- : public UnaryInstructionBase<ValueKind::SuperMethodInst, MethodInst>
+ : public UnaryInstructionBase<SILInstructionKind::SuperMethodInst, MethodInst>
{
friend SILBuilder;
@@ -4744,7 +4875,8 @@
/// and a protocol method constant, extracts the implementation of that method
/// for the type.
class WitnessMethodInst final
- : public MethodInst,
+ : public InstructionBase<SILInstructionKind::WitnessMethodInst,
+ MethodInst>,
llvm::TrailingObjects<WitnessMethodInst, Operand> {
friend TrailingObjects;
friend SILBuilder;
@@ -4757,8 +4889,7 @@
ProtocolConformanceRef Conformance, SILDeclRef Member,
SILType Ty, ArrayRef<SILValue> TypeDependentOperands,
bool Volatile = false)
- : MethodInst(ValueKind::WitnessMethodInst, DebugLoc, Ty, Member,
- Volatile),
+ : InstructionBase(DebugLoc, Ty, Member, Volatile),
LookupType(LookupType), Conformance(Conformance),
NumOperands(TypeDependentOperands.size()) {
TrailingOperandsList::InitOperandsList(getAllOperands().begin(), this,
@@ -4802,10 +4933,6 @@
MutableArrayRef<Operand> getTypeDependentOperands() {
return { getTrailingObjects<Operand>(), NumOperands };
}
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::WitnessMethodInst;
- }
};
/// Given the address of a value of AnyObject protocol type and a method
@@ -4814,10 +4941,9 @@
/// can fail at run-time
class DynamicMethodInst final
: public UnaryInstructionWithTypeDependentOperandsBase<
- ValueKind::DynamicMethodInst,
+ SILInstructionKind::DynamicMethodInst,
DynamicMethodInst,
- MethodInst,
- true>
+ MethodInst>
{
friend SILBuilder;
@@ -4844,7 +4970,8 @@
/// existential by returning a pointer to a fresh archetype T, which also
/// captures the (dynamic) conformances.
class OpenExistentialAddrInst
- : public UnaryInstructionBase<ValueKind::OpenExistentialAddrInst>
+ : public UnaryInstructionBase<SILInstructionKind::OpenExistentialAddrInst,
+ SingleValueInstruction>
{
friend SILBuilder;
OpenedExistentialAccess ForAccess;
@@ -4860,7 +4987,8 @@
/// existential by returning a pointer to a fresh archetype T, which also
/// captures the (dynamic) conformances.
class OpenExistentialValueInst
- : public UnaryInstructionBase<ValueKind::OpenExistentialValueInst> {
+ : public UnaryInstructionBase<SILInstructionKind::OpenExistentialValueInst,
+ SingleValueInstruction> {
friend SILBuilder;
OpenExistentialValueInst(SILDebugLocation DebugLoc, SILValue Operand,
@@ -4871,7 +4999,8 @@
/// existential by returning a pointer to a fresh archetype T, which also
/// captures the (dynamic) conformances.
class OpenExistentialRefInst
- : public UnaryInstructionBase<ValueKind::OpenExistentialRefInst>
+ : public UnaryInstructionBase<SILInstructionKind::OpenExistentialRefInst,
+ SingleValueInstruction>
{
friend SILBuilder;
@@ -4884,7 +5013,8 @@
/// archetype metatype T.Type, which also captures the (dynamic)
/// conformances.
class OpenExistentialMetatypeInst
- : public UnaryInstructionBase<ValueKind::OpenExistentialMetatypeInst>
+ : public UnaryInstructionBase<SILInstructionKind::OpenExistentialMetatypeInst,
+ SingleValueInstruction>
{
friend SILBuilder;
@@ -4896,7 +5026,8 @@
/// "opens" the existential by returning a pointer to a fresh
/// archetype T, which also captures the (dynamic) conformances.
class OpenExistentialBoxInst
- : public UnaryInstructionBase<ValueKind::OpenExistentialBoxInst>
+ : public UnaryInstructionBase<SILInstructionKind::OpenExistentialBoxInst,
+ SingleValueInstruction>
{
friend SILBuilder;
@@ -4907,7 +5038,8 @@
/// Given a boxed existential container, "opens" the existential by returning a
/// fresh archetype T, which also captures the (dynamic) conformances.
class OpenExistentialBoxValueInst
- : public UnaryInstructionBase<ValueKind::OpenExistentialBoxValueInst>
+ : public UnaryInstructionBase<SILInstructionKind::OpenExistentialBoxValueInst,
+ SingleValueInstruction>
{
friend SILBuilder;
@@ -4921,10 +5053,9 @@
/// concrete value inside the existential container.
class InitExistentialAddrInst final
: public UnaryInstructionWithTypeDependentOperandsBase<
- ValueKind::InitExistentialAddrInst,
+ SILInstructionKind::InitExistentialAddrInst,
InitExistentialAddrInst,
- SILInstruction,
- true>
+ SingleValueInstruction>
{
friend SILBuilder;
@@ -4966,8 +5097,8 @@
/// concrete value inside the existential container.
class InitExistentialValueInst final
: public UnaryInstructionWithTypeDependentOperandsBase<
- ValueKind::InitExistentialValueInst, InitExistentialValueInst,
- SILInstruction, true> {
+ SILInstructionKind::InitExistentialValueInst, InitExistentialValueInst,
+ SingleValueInstruction> {
friend SILBuilder;
CanType ConcreteType;
@@ -5000,10 +5131,9 @@
/// class instance.
class InitExistentialRefInst final
: public UnaryInstructionWithTypeDependentOperandsBase<
- ValueKind::InitExistentialRefInst,
+ SILInstructionKind::InitExistentialRefInst,
InitExistentialRefInst,
- SILInstruction,
- true>
+ SingleValueInstruction>
{
friend SILBuilder;
@@ -5042,10 +5172,9 @@
/// the metatype.
class InitExistentialMetatypeInst final
: public UnaryInstructionWithTypeDependentOperandsBase<
- ValueKind::InitExistentialMetatypeInst,
+ SILInstructionKind::InitExistentialMetatypeInst,
InitExistentialMetatypeInst,
- SILInstruction,
- true,
+ SingleValueInstruction,
ProtocolConformanceRef>
{
friend SILBuilder;
@@ -5088,9 +5217,8 @@
/// existentials; a fully-initialized existential can be destroyed with
/// DestroyAddrInst and deallocated with DeallocStackInst.
class DeinitExistentialAddrInst
- : public UnaryInstructionBase<ValueKind::DeinitExistentialAddrInst,
- SILInstruction,
- /*HAS_RESULT*/ false>
+ : public UnaryInstructionBase<SILInstructionKind::DeinitExistentialAddrInst,
+ NonValueInstruction>
{
friend SILBuilder;
@@ -5099,8 +5227,8 @@
};
class DeinitExistentialValueInst
- : public UnaryInstructionBase<ValueKind::DeinitExistentialValueInst,
- SILInstruction, /*HAS_RESULT*/ false> {
+ : public UnaryInstructionBase<SILInstructionKind::DeinitExistentialValueInst,
+ NonValueInstruction> {
friend SILBuilder;
DeinitExistentialValueInst(SILDebugLocation DebugLoc, SILValue Existential)
@@ -5109,8 +5237,8 @@
/// Projects the capture storage address from a @block_storage address.
class ProjectBlockStorageInst
- : public UnaryInstructionBase<ValueKind::ProjectBlockStorageInst,
- SILInstruction>
+ : public UnaryInstructionBase<SILInstructionKind::ProjectBlockStorageInst,
+ SingleValueInstruction>
{
friend SILBuilder;
@@ -5122,7 +5250,9 @@
/// Initializes a block header, creating a block that
/// invokes a given thin cdecl function.
-class InitBlockStorageHeaderInst : public SILInstruction {
+class InitBlockStorageHeaderInst
+ : public InstructionBase<SILInstructionKind::InitBlockStorageHeaderInst,
+ SingleValueInstruction> {
friend SILBuilder;
enum { BlockStorage, InvokeFunction };
@@ -5139,8 +5269,7 @@
InitBlockStorageHeaderInst(SILDebugLocation DebugLoc, SILValue BlockStorage,
SILValue InvokeFunction, SILType BlockType,
SubstitutionList Subs)
- : SILInstruction(ValueKind::InitBlockStorageHeaderInst, DebugLoc,
- BlockType),
+ : InstructionBase(DebugLoc, BlockType),
NumSubstitutions(Subs.size()),
Operands(this, BlockStorage, InvokeFunction) {
memcpy(getSubstitutionsStorage(), Subs.begin(),
@@ -5163,17 +5292,12 @@
ArrayRef<Operand> getAllOperands() const { return Operands.asArray(); }
MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::InitBlockStorageHeaderInst;
- }
};
/// StrongRetainInst - Increase the strong reference count of an object.
class StrongRetainInst
- : public UnaryInstructionBase<ValueKind::StrongRetainInst,
- RefCountingInst,
- /*HAS_RESULT*/ false>
+ : public UnaryInstructionBase<SILInstructionKind::StrongRetainInst,
+ RefCountingInst>
{
friend SILBuilder;
@@ -5190,8 +5314,8 @@
/// zero. It can be deallocated when both its strong reference and
/// weak reference counts reach zero.
class StrongReleaseInst
- : public UnaryInstructionBase<ValueKind::StrongReleaseInst,
- RefCountingInst, /*HAS_RESULT*/ false>
+ : public UnaryInstructionBase<SILInstructionKind::StrongReleaseInst,
+ RefCountingInst>
{
friend SILBuilder;
@@ -5207,8 +5331,8 @@
///
/// The operand must be an @unowned type.
class StrongRetainUnownedInst :
- public UnaryInstructionBase<ValueKind::StrongRetainUnownedInst,
- RefCountingInst, /*HAS_RESULT*/ false>
+ public UnaryInstructionBase<SILInstructionKind::StrongRetainUnownedInst,
+ RefCountingInst>
{
friend SILBuilder;
@@ -5221,8 +5345,8 @@
/// UnownedRetainInst - Increase the unowned reference count of an object.
class UnownedRetainInst :
- public UnaryInstructionBase<ValueKind::UnownedRetainInst,
- RefCountingInst, /*HAS_RESULT*/ false>
+ public UnaryInstructionBase<SILInstructionKind::UnownedRetainInst,
+ RefCountingInst>
{
friend SILBuilder;
@@ -5235,8 +5359,8 @@
/// UnownedReleaseInst - Decrease the unowned reference count of an object.
class UnownedReleaseInst :
- public UnaryInstructionBase<ValueKind::UnownedReleaseInst,
- RefCountingInst, /*HAS_RESULT*/ false>
+ public UnaryInstructionBase<SILInstructionKind::UnownedReleaseInst,
+ RefCountingInst>
{
friend SILBuilder;
@@ -5250,8 +5374,8 @@
/// FixLifetimeInst - An artificial use of a value for the purposes of ARC or
/// RVO optimizations.
class FixLifetimeInst :
- public UnaryInstructionBase<ValueKind::FixLifetimeInst,
- SILInstruction, /*HAS_RESULT*/ false>
+ public UnaryInstructionBase<SILInstructionKind::FixLifetimeInst,
+ NonValueInstruction>
{
friend SILBuilder;
@@ -5273,8 +5397,8 @@
/// destroyers, without an actual release being emitted (avoiding the runtime
/// assert).
class EndLifetimeInst
- : public UnaryInstructionBase<ValueKind::EndLifetimeInst, SILInstruction,
- /*HAS_RESULT*/ false> {
+ : public UnaryInstructionBase<SILInstructionKind::EndLifetimeInst,
+ NonValueInstruction> {
friend SILBuilder;
EndLifetimeInst(SILDebugLocation DebugLoc, SILValue Operand)
@@ -5287,7 +5411,8 @@
/// constraints, we need to be able to convert a guaranteed parameter to an owned
/// parameter.
class UncheckedOwnershipConversionInst
- : public UnaryInstructionBase<ValueKind::UncheckedOwnershipConversionInst> {
+ : public UnaryInstructionBase<SILInstructionKind::UncheckedOwnershipConversionInst,
+ SingleValueInstruction> {
friend SILBuilder;
ValueOwnershipKind Kind;
@@ -5303,15 +5428,16 @@
/// MarkDependenceInst - Marks that one value depends on another for
/// validity in a non-obvious way.
-class MarkDependenceInst : public SILInstruction {
+class MarkDependenceInst
+ : public InstructionBase<SILInstructionKind::MarkDependenceInst,
+ SingleValueInstruction> {
friend SILBuilder;
enum { Value, Base };
FixedOperandList<2> Operands;
MarkDependenceInst(SILDebugLocation DebugLoc, SILValue value, SILValue base)
- : SILInstruction(ValueKind::MarkDependenceInst, DebugLoc,
- value->getType()),
+ : InstructionBase(DebugLoc, value->getType()),
Operands{this, value, base} {}
public:
@@ -5320,17 +5446,13 @@
ArrayRef<Operand> getAllOperands() const { return Operands.asArray(); }
MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::MarkDependenceInst;
- }
};
/// Promote an Objective-C block that is on the stack to the heap, or simply
/// retain a block that is already on the heap.
-class CopyBlockInst :
- public UnaryInstructionBase<ValueKind::CopyBlockInst,
- SILInstruction, /*HAS_RESULT*/ true>
+class CopyBlockInst
+ : public UnaryInstructionBase<SILInstructionKind::CopyBlockInst,
+ SingleValueInstruction>
{
friend SILBuilder;
@@ -5338,7 +5460,9 @@
: UnaryInstructionBase(DebugLoc, operand, operand->getType()) {}
};
-class CopyValueInst : public UnaryInstructionBase<ValueKind::CopyValueInst> {
+class CopyValueInst
+ : public UnaryInstructionBase<SILInstructionKind::CopyValueInst,
+ SingleValueInstruction> {
friend class SILBuilder;
CopyValueInst(SILDebugLocation DebugLoc, SILValue operand)
@@ -5346,7 +5470,8 @@
};
class CopyUnownedValueInst
- : public UnaryInstructionBase<ValueKind::CopyUnownedValueInst> {
+ : public UnaryInstructionBase<SILInstructionKind::CopyUnownedValueInst,
+ SingleValueInstruction> {
friend class SILBuilder;
CopyUnownedValueInst(SILDebugLocation DebugLoc, SILValue operand,
@@ -5356,7 +5481,8 @@
};
class DestroyValueInst
- : public UnaryInstructionBase<ValueKind::DestroyValueInst> {
+ : public UnaryInstructionBase<SILInstructionKind::DestroyValueInst,
+ NonValueInstruction> {
friend class SILBuilder;
DestroyValueInst(SILDebugLocation DebugLoc, SILValue operand)
@@ -5365,7 +5491,9 @@
/// Given an object reference, return true iff it is non-nil and refers
/// to a native swift object with strong reference count of 1.
-class IsUniqueInst : public UnaryInstructionBase<ValueKind::IsUniqueInst>
+class IsUniqueInst
+ : public UnaryInstructionBase<SILInstructionKind::IsUniqueInst,
+ SingleValueInstruction>
{
friend SILBuilder;
@@ -5376,8 +5504,9 @@
/// Given an object reference, return true iff it is non-nil and either refers
/// to a native swift object with strong reference count of 1 or refers to a
/// pinned object (for simultaneous access to multiple subobjects).
-class IsUniqueOrPinnedInst :
- public UnaryInstructionBase<ValueKind::IsUniqueOrPinnedInst> {
+class IsUniqueOrPinnedInst
+ : public UnaryInstructionBase<SILInstructionKind::IsUniqueOrPinnedInst,
+ SingleValueInstruction> {
friend SILBuilder;
IsUniqueOrPinnedInst(SILDebugLocation DebugLoc, SILValue Operand,
@@ -5390,22 +5519,19 @@
//===----------------------------------------------------------------------===//
/// DeallocationInst - An abstract parent class for Dealloc{Stack, Box, Ref}.
-class DeallocationInst : public SILInstruction {
+class DeallocationInst : public NonValueInstruction {
protected:
- DeallocationInst(ValueKind Kind, SILDebugLocation DebugLoc)
- : SILInstruction(Kind, DebugLoc) {}
+ DeallocationInst(SILInstructionKind Kind, SILDebugLocation DebugLoc)
+ : NonValueInstruction(Kind, DebugLoc) {}
public:
- static bool classof(const ValueBase *V) {
- return V->getKind() >= ValueKind::First_DeallocationInst &&
- V->getKind() <= ValueKind::Last_DeallocationInst;
- }
+ DEFINE_ABSTRACT_NON_VALUE_INST_BOILERPLATE(DeallocationInst)
};
/// DeallocStackInst - Deallocate stack memory allocated by alloc_stack.
class DeallocStackInst :
- public UnaryInstructionBase<ValueKind::DeallocStackInst, DeallocationInst,
- /*HAS_RESULT*/ false> {
+ public UnaryInstructionBase<SILInstructionKind::DeallocStackInst,
+ DeallocationInst> {
friend SILBuilder;
DeallocStackInst(SILDebugLocation DebugLoc, SILValue operand)
@@ -5421,8 +5547,8 @@
/// It is undefined behavior if the type of the operand does not match the
/// most derived type of the allocated instance.
class DeallocRefInst :
- public UnaryInstructionBase<ValueKind::DeallocRefInst, DeallocationInst,
- /*HAS_RESULT*/ false>,
+ public UnaryInstructionBase<SILInstructionKind::DeallocRefInst,
+ DeallocationInst>,
public StackPromotable {
friend SILBuilder;
@@ -5442,7 +5568,9 @@
///
/// The metatype value can either be the static self type (in a designated
/// initializer) or a dynamic self type (in a convenience initializer).
-class DeallocPartialRefInst : public DeallocationInst {
+class DeallocPartialRefInst
+ : public InstructionBase<SILInstructionKind::DeallocPartialRefInst,
+ DeallocationInst> {
friend SILBuilder;
private:
@@ -5450,7 +5578,7 @@
DeallocPartialRefInst(SILDebugLocation DebugLoc, SILValue Operand,
SILValue Metatype)
- : DeallocationInst(ValueKind::DeallocPartialRefInst, DebugLoc),
+ : InstructionBase(DebugLoc),
Operands(this, Operand, Metatype) {}
public:
@@ -5459,16 +5587,12 @@
SILValue getInstance() const { return getOperand(0); }
SILValue getMetatype() const { return getOperand(1); }
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::DeallocPartialRefInst;
- }
};
/// Deallocate memory allocated for an unsafe value buffer.
-class DeallocValueBufferInst :
- public UnaryInstructionBase<ValueKind::DeallocValueBufferInst,
- DeallocationInst, /*HAS_RESULT*/ true> {
+class DeallocValueBufferInst
+ : public UnaryInstructionBase<SILInstructionKind::DeallocValueBufferInst,
+ DeallocationInst> {
friend SILBuilder;
SILType ValueType;
@@ -5487,9 +5611,9 @@
///
/// This does not destroy the boxed value instance; it must either be
/// uninitialized or have been manually destroyed.
-class DeallocBoxInst :
- public UnaryInstructionBase<ValueKind::DeallocBoxInst, DeallocationInst,
- /*HAS_RESULT*/ false>
+class DeallocBoxInst
+ : public UnaryInstructionBase<SILInstructionKind::DeallocBoxInst,
+ DeallocationInst>
{
friend SILBuilder;
@@ -5503,10 +5627,9 @@
///
/// This does not destroy the boxed value instance; it must either be
/// uninitialized or have been manually destroyed.
-class DeallocExistentialBoxInst :
- public UnaryInstructionBase<ValueKind::DeallocExistentialBoxInst,
- DeallocationInst,
- /*HAS_RESULT*/ false>
+class DeallocExistentialBoxInst
+ : public UnaryInstructionBase<SILInstructionKind::DeallocExistentialBoxInst,
+ DeallocationInst>
{
friend SILBuilder;
@@ -5526,9 +5649,9 @@
/// release_value %1
/// but a destroy instruction can be used for types that cannot be loaded,
/// such as resilient value types.
-class DestroyAddrInst : public UnaryInstructionBase<ValueKind::DestroyAddrInst,
- SILInstruction,
- /*HAS_RESULT*/ false>
+class DestroyAddrInst
+ : public UnaryInstructionBase<SILInstructionKind::DestroyAddrInst,
+ NonValueInstruction>
{
friend SILBuilder;
@@ -5538,9 +5661,9 @@
/// Project out the address of the value
/// stored in the given Builtin.UnsafeValueBuffer.
-class ProjectValueBufferInst :
- public UnaryInstructionBase<ValueKind::ProjectValueBufferInst,
- SILInstruction, /*HasResult*/ true> {
+class ProjectValueBufferInst
+ : public UnaryInstructionBase<SILInstructionKind::ProjectValueBufferInst,
+ SingleValueInstruction> {
friend SILBuilder;
ProjectValueBufferInst(SILDebugLocation DebugLoc, SILType valueType,
@@ -5552,9 +5675,9 @@
};
/// Project out the address of the value in a box.
-class ProjectBoxInst :
- public UnaryInstructionBase<ValueKind::ProjectBoxInst,
- SILInstruction, /*HasResult*/ true> {
+class ProjectBoxInst
+ : public UnaryInstructionBase<SILInstructionKind::ProjectBoxInst,
+ SingleValueInstruction> {
friend SILBuilder;
unsigned Index;
@@ -5572,9 +5695,9 @@
};
/// Project out the address of the value in an existential box.
-class ProjectExistentialBoxInst :
- public UnaryInstructionBase<ValueKind::ProjectExistentialBoxInst,
- SILInstruction, /*HasResult*/ true> {
+class ProjectExistentialBoxInst
+ : public UnaryInstructionBase<SILInstructionKind::ProjectExistentialBoxInst,
+ SingleValueInstruction> {
friend SILBuilder;
ProjectExistentialBoxInst(SILDebugLocation DebugLoc, SILType valueType,
@@ -5587,9 +5710,9 @@
//===----------------------------------------------------------------------===//
/// Trigger a runtime failure if the given Int1 value is true.
-class CondFailInst : public UnaryInstructionBase<ValueKind::CondFailInst,
- SILInstruction,
- /*HAS_RESULT*/ false>
+class CondFailInst
+ : public UnaryInstructionBase<SILInstructionKind::CondFailInst,
+ NonValueInstruction>
{
friend SILBuilder;
@@ -5602,18 +5725,13 @@
//===----------------------------------------------------------------------===//
/// Abstract base class for indexing instructions.
-class IndexingInst : public SILInstruction {
+class IndexingInst : public SingleValueInstruction {
enum { Base, Index };
FixedOperandList<2> Operands;
public:
- IndexingInst(ValueKind Kind, SILDebugLocation DebugLoc, SILValue Operand,
- SILValue Index)
- : SILInstruction(Kind, DebugLoc, Operand->getType()),
- Operands{this, Operand, Index} {}
-
- IndexingInst(ValueKind Kind, SILDebugLocation DebugLoc, SILValue Operand,
- SILValue Index, SILType ResultTy)
- : SILInstruction(Kind, DebugLoc, ResultTy),
+ IndexingInst(SILInstructionKind Kind, SILDebugLocation DebugLoc,
+ SILType ResultTy, SILValue Operand, SILValue Index)
+ : SingleValueInstruction(Kind, DebugLoc, ResultTy),
Operands{this, Operand, Index} {}
SILValue getBase() const { return Operands[Base].get(); }
@@ -5622,44 +5740,35 @@
ArrayRef<Operand> getAllOperands() const { return Operands.asArray(); }
MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
- static bool classof(const ValueBase *V) {
- return V->getKind() >= ValueKind::First_IndexingInst
- && V->getKind() <= ValueKind::Last_IndexingInst;
- }
+ DEFINE_ABSTRACT_SINGLE_VALUE_INST_BOILERPLATE(IndexingInst)
};
/// IndexAddrInst - "%2 : $*T = index_addr %0 : $*T, %1 : $Builtin.Word"
/// This takes an address and indexes it, striding by the pointed-
/// to type. This is used to index into arrays of uniform elements.
-class IndexAddrInst : public IndexingInst {
+class IndexAddrInst
+ : public InstructionBase<SILInstructionKind::IndexAddrInst,
+ IndexingInst> {
friend SILBuilder;
enum { Base, Index };
IndexAddrInst(SILDebugLocation DebugLoc, SILValue Operand, SILValue Index)
- : IndexingInst(ValueKind::IndexAddrInst, DebugLoc, Operand, Index) {}
-
-public:
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::IndexAddrInst;
- }
+ : InstructionBase(DebugLoc, Operand->getType(), Operand, Index) {}
};
/// TailAddrInst - like IndexingInst, but aligns-up the resulting address to a
/// tail-allocated element type.
-class TailAddrInst : public IndexingInst {
+class TailAddrInst
+ : public InstructionBase<SILInstructionKind::TailAddrInst,
+ IndexingInst> {
friend SILBuilder;
TailAddrInst(SILDebugLocation DebugLoc, SILValue Operand, SILValue Count,
SILType ResultTy)
- : IndexingInst(ValueKind::TailAddrInst, DebugLoc, Operand, Count,
- ResultTy) {}
+ : InstructionBase(DebugLoc, ResultTy, Operand, Count) {}
public:
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::TailAddrInst;
- }
-
SILType getTailType() const { return getType().getObjectType(); }
};
@@ -5668,19 +5777,16 @@
/// = index_raw_pointer %0 : $Builtin.RawPointer, %1 : $Builtin.Word
/// This takes an address and indexes it, striding by the pointed-
/// to type. This is used to index into arrays of uniform elements.
-class IndexRawPointerInst : public IndexingInst {
+class IndexRawPointerInst
+ : public InstructionBase<SILInstructionKind::IndexRawPointerInst,
+ IndexingInst> {
friend SILBuilder;
enum { Base, Index };
IndexRawPointerInst(SILDebugLocation DebugLoc, SILValue Operand,
SILValue Index)
- : IndexingInst(ValueKind::IndexRawPointerInst, DebugLoc, Operand, Index) {
- }
-
-public:
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::IndexRawPointerInst;
+ : InstructionBase(DebugLoc, Operand->getType(), Operand, Index) {
}
};
@@ -5689,33 +5795,16 @@
//===----------------------------------------------------------------------===//
enum class TermKind {
-#define TERMINATOR(Id, Parent, TextualName, MemBehavior, MayRelease) Id,
+#define TERMINATOR(Id, TextualName, Parent, MemBehavior, MayRelease) \
+ Id = unsigned(SILInstructionKind::Id),
#include "SILNodes.def"
};
-struct ValueKindAsTermKind {
- TermKind K;
-
- ValueKindAsTermKind(ValueKind V) {
- switch (V) {
-#define TERMINATOR(Id, Parent, TextualName, MemBehavior, MayRelease) \
- case ValueKind::Id: \
- K = TermKind::Id; \
- break;
-#include "SILNodes.def"
- default:
- llvm_unreachable("Not a terminator kind?!");
- }
- }
-
- operator TermKind() const { return K; }
-};
-
/// This class defines a "terminating instruction" for a SILBasicBlock.
-class TermInst : public SILInstruction {
+class TermInst : public NonValueInstruction {
protected:
- TermInst(ValueKind K, SILDebugLocation DebugLoc)
- : SILInstruction(K, DebugLoc) {}
+ TermInst(SILInstructionKind K, SILDebugLocation DebugLoc)
+ : NonValueInstruction(K, DebugLoc) {}
public:
@@ -5728,27 +5817,26 @@
return const_cast<TermInst*>(this)->getSuccessors();
}
- static bool classof(const ValueBase *V) {
- return V->getKind() >= ValueKind::First_TermInst &&
- V->getKind() <= ValueKind::Last_TermInst;
- }
+ DEFINE_ABSTRACT_NON_VALUE_INST_BOILERPLATE(TermInst)
bool isBranch() const { return !getSuccessors().empty(); }
/// Returns true if this terminator exits the function.
bool isFunctionExiting() const;
- TermKind getTermKind() const { return ValueKindAsTermKind(getKind()); }
+ TermKind getTermKind() const { return TermKind(getKind()); }
};
/// UnreachableInst - Position in the code which would be undefined to reach.
/// These are always implicitly generated, e.g. when falling off the end of a
/// function or after a no-return function call.
-class UnreachableInst : public TermInst {
+class UnreachableInst
+ : public InstructionBase<SILInstructionKind::UnreachableInst,
+ TermInst> {
friend SILBuilder;
UnreachableInst(SILDebugLocation DebugLoc)
- : TermInst(ValueKind::UnreachableInst, DebugLoc) {}
+ : InstructionBase(DebugLoc) {}
public:
SuccessorListTy getSuccessors() {
@@ -5758,16 +5846,11 @@
ArrayRef<Operand> getAllOperands() const { return {}; }
MutableArrayRef<Operand> getAllOperands() { return {}; }
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::UnreachableInst;
- }
};
/// ReturnInst - Representation of a ReturnStmt.
class ReturnInst
- : public UnaryInstructionBase<ValueKind::ReturnInst, TermInst,
- /*HAS_RESULT*/ false>
+ : public UnaryInstructionBase<SILInstructionKind::ReturnInst, TermInst>
{
friend SILBuilder;
@@ -5790,8 +5873,7 @@
/// ThrowInst - Throw a typed error (which, in our system, is
/// essentially just a funny kind of return).
class ThrowInst
- : public UnaryInstructionBase<ValueKind::ThrowInst, TermInst,
- /*HAS_RESULT*/ false>
+ : public UnaryInstructionBase<SILInstructionKind::ThrowInst, TermInst>
{
friend SILBuilder;
@@ -5811,7 +5893,9 @@
};
/// BranchInst - An unconditional branch.
-class BranchInst : public TermInst {
+class BranchInst
+ : public InstructionBase<SILInstructionKind::BranchInst,
+ TermInst> {
friend SILBuilder;
SILSuccessor DestBB;
@@ -5847,14 +5931,12 @@
ArrayRef<Operand> getAllOperands() const { return Operands.asArray(); }
MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::BranchInst;
- }
};
/// A conditional branch.
-class CondBranchInst : public TermInst {
+class CondBranchInst
+ : public InstructionBase<SILInstructionKind::CondBranchInst,
+ TermInst> {
friend SILBuilder;
public:
@@ -5878,22 +5960,24 @@
TailAllocatedOperandList<1> Operands;
CondBranchInst(SILDebugLocation DebugLoc, SILValue Condition,
SILBasicBlock *TrueBB, SILBasicBlock *FalseBB,
- ArrayRef<SILValue> Args, unsigned NumTrue, unsigned NumFalse);
+ ArrayRef<SILValue> Args, unsigned NumTrue, unsigned NumFalse,
+ ProfileCounter TrueBBCount, ProfileCounter FalseBBCount);
/// Construct a CondBranchInst that will branch to TrueBB or FalseBB based on
/// the Condition value. Both blocks must not take any arguments.
static CondBranchInst *create(SILDebugLocation DebugLoc, SILValue Condition,
SILBasicBlock *TrueBB, SILBasicBlock *FalseBB,
- SILFunction &F);
+ ProfileCounter TrueBBCount,
+ ProfileCounter FalseBBCount, SILFunction &F);
/// Construct a CondBranchInst that will either branch to TrueBB and pass
/// TrueArgs or branch to FalseBB and pass FalseArgs based on the Condition
/// value.
- static CondBranchInst *create(SILDebugLocation DebugLoc, SILValue Condition,
- SILBasicBlock *TrueBB,
- ArrayRef<SILValue> TrueArgs,
- SILBasicBlock *FalseBB,
- ArrayRef<SILValue> FalseArgs, SILFunction &F);
+ static CondBranchInst *
+ create(SILDebugLocation DebugLoc, SILValue Condition, SILBasicBlock *TrueBB,
+ ArrayRef<SILValue> TrueArgs, SILBasicBlock *FalseBB,
+ ArrayRef<SILValue> FalseArgs, ProfileCounter TrueBBCount,
+ ProfileCounter FalseBBCount, SILFunction &F);
public:
SILValue getCondition() const { return Operands[ConditionIdx].get(); }
@@ -5910,6 +5994,11 @@
SILBasicBlock *getFalseBB() { return DestBBs[1]; }
const SILBasicBlock *getFalseBB() const { return DestBBs[1]; }
+ /// The number of times the True branch was executed.
+ ProfileCounter getTrueBBCount() const { return DestBBs[0].getCount(); }
+ /// The number of times the False branch was executed.
+ ProfileCounter getFalseBBCount() const { return DestBBs[1].getCount(); }
+
/// Get the arguments to the true BB.
OperandValueArrayRef getTrueArgs() const;
/// Get the arguments to the false BB.
@@ -5967,14 +6056,12 @@
ArrayRef<Operand> getAllOperands() const { return Operands.asArray(); }
MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::CondBranchInst;
- }
};
/// A switch on a value of a builtin type.
-class SwitchValueInst : public TermInst {
+class SwitchValueInst
+ : public InstructionBase<SILInstructionKind::SwitchValueInst,
+ TermInst> {
friend SILBuilder;
unsigned NumCases : 31;
@@ -6035,10 +6122,6 @@
assert(HasDefault && "doesn't have a default");
return getSuccessorBuf()[NumCases];
}
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::SwitchValueInst;
- }
};
/// Common implementation for the switch_enum and
@@ -6075,15 +6158,17 @@
protected:
SwitchEnumInstBase(
- ValueKind Kind, SILDebugLocation DebugLoc, SILValue Operand,
+ SILInstructionKind Kind, SILDebugLocation DebugLoc, SILValue Operand,
SILBasicBlock *DefaultBB,
- ArrayRef<std::pair<EnumElementDecl *, SILBasicBlock *>> CaseBBs);
+ ArrayRef<std::pair<EnumElementDecl *, SILBasicBlock *>> CaseBBs,
+ Optional<ArrayRef<ProfileCounter>> Counts, ProfileCounter DefaultCount);
template <typename SWITCH_ENUM_INST>
static SWITCH_ENUM_INST *createSwitchEnum(
SILDebugLocation DebugLoc, SILValue Operand, SILBasicBlock *DefaultBB,
ArrayRef<std::pair<EnumElementDecl *, SILBasicBlock *>> CaseBBs,
- SILFunction &F);
+ SILFunction &F, Optional<ArrayRef<ProfileCounter>> Counts,
+ ProfileCounter DefaultCount);
public:
/// Clean up tail-allocated successor records for the switch cases.
@@ -6105,6 +6190,10 @@
assert(i < NumCases && "case out of bounds");
return {getCaseBuf()[i], getSuccessorBuf()[i].getBB()};
}
+ ProfileCounter getCaseCount(unsigned i) const {
+ assert(i < NumCases && "case out of bounds");
+ return getSuccessorBuf()[i].getCount();
+ }
// Swap the cases at indices \p i and \p j.
void swapCase(unsigned i, unsigned j);
@@ -6133,16 +6222,22 @@
assert(HasDefault && "doesn't have a default");
return getSuccessorBuf()[NumCases];
}
+ ProfileCounter getDefaultCount() const {
+ assert(HasDefault && "doesn't have a default");
+ return getSuccessorBuf()[NumCases].getCount();
+ }
- static bool classof(const ValueBase *V) {
- return V->getKind() >= ValueKind::SwitchEnumInst &&
- V->getKind() <= ValueKind::SwitchEnumAddrInst;
+ static bool classof(const SILInstruction *I) {
+ return I->getKind() >= SILInstructionKind::SwitchEnumInst &&
+ I->getKind() <= SILInstructionKind::SwitchEnumAddrInst;
}
};
/// A switch on a loadable enum's discriminator. The data for each case is
/// passed into the corresponding destination block as an argument.
-class SwitchEnumInst : public SwitchEnumInstBase {
+class SwitchEnumInst
+ : public InstructionBase<SILInstructionKind::SwitchEnumInst,
+ SwitchEnumInstBase> {
friend SILBuilder;
private:
@@ -6150,23 +6245,22 @@
SwitchEnumInst(
SILDebugLocation DebugLoc, SILValue Operand, SILBasicBlock *DefaultBB,
- ArrayRef<std::pair<EnumElementDecl *, SILBasicBlock *>> CaseBBs)
- : SwitchEnumInstBase(ValueKind::SwitchEnumInst, DebugLoc, Operand,
- DefaultBB, CaseBBs) {}
-
+ ArrayRef<std::pair<EnumElementDecl *, SILBasicBlock *>> CaseBBs,
+ Optional<ArrayRef<ProfileCounter>> CaseCounts,
+ ProfileCounter DefaultCount)
+ : InstructionBase(DebugLoc, Operand, DefaultBB, CaseBBs, CaseCounts,
+ DefaultCount) {}
static SwitchEnumInst *
create(SILDebugLocation DebugLoc, SILValue Operand, SILBasicBlock *DefaultBB,
ArrayRef<std::pair<EnumElementDecl *, SILBasicBlock *>> CaseBBs,
- SILFunction &F);
-
-public:
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::SwitchEnumInst;
- }
+ SILFunction &F, Optional<ArrayRef<ProfileCounter>> CaseCounts,
+ ProfileCounter DefaultCount);
};
/// A switch on an enum's discriminator in memory.
-class SwitchEnumAddrInst : public SwitchEnumInstBase {
+class SwitchEnumAddrInst
+ : public InstructionBase<SILInstructionKind::SwitchEnumAddrInst,
+ SwitchEnumInstBase> {
friend SILBuilder;
private:
@@ -6174,19 +6268,16 @@
SwitchEnumAddrInst(
SILDebugLocation DebugLoc, SILValue Operand, SILBasicBlock *DefaultBB,
- ArrayRef<std::pair<EnumElementDecl *, SILBasicBlock *>> CaseBBs)
- : SwitchEnumInstBase(ValueKind::SwitchEnumAddrInst, DebugLoc, Operand,
- DefaultBB, CaseBBs) {}
-
+ ArrayRef<std::pair<EnumElementDecl *, SILBasicBlock *>> CaseBBs,
+ Optional<ArrayRef<ProfileCounter>> CaseCounts,
+ ProfileCounter DefaultCount)
+ : InstructionBase(DebugLoc, Operand, DefaultBB, CaseBBs, CaseCounts,
+ DefaultCount) {}
static SwitchEnumAddrInst *
create(SILDebugLocation DebugLoc, SILValue Operand, SILBasicBlock *DefaultBB,
ArrayRef<std::pair<EnumElementDecl *, SILBasicBlock *>> CaseBBs,
- SILFunction &F);
-
-public:
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::SwitchEnumAddrInst;
- }
+ SILFunction &F, Optional<ArrayRef<ProfileCounter>> CaseCounts,
+ ProfileCounter DefaultCount);
};
/// Branch on the existence of an Objective-C method in the dynamic type of
@@ -6194,7 +6285,9 @@
///
/// If the method exists, branches to the first BB, providing it with the
/// method reference; otherwise, branches to the second BB.
-class DynamicMethodBranchInst : public TermInst {
+class DynamicMethodBranchInst
+ : public InstructionBase<SILInstructionKind::DynamicMethodBranchInst,
+ TermInst> {
friend SILBuilder;
SILDeclRef Member;
@@ -6231,10 +6324,6 @@
ArrayRef<Operand> getAllOperands() const { return Operands.asArray(); }
MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::DynamicMethodBranchInst;
- }
};
/// Perform a checked cast operation and branch on whether the cast succeeds.
@@ -6242,10 +6331,9 @@
/// argument.
class CheckedCastBranchInst final:
public UnaryInstructionWithTypeDependentOperandsBase<
- ValueKind::CheckedCastBranchInst,
+ SILInstructionKind::CheckedCastBranchInst,
CheckedCastBranchInst,
- TermInst,
- false> {
+ TermInst> {
friend SILBuilder;
SILType DestTy;
@@ -6256,17 +6344,20 @@
CheckedCastBranchInst(SILDebugLocation DebugLoc, bool IsExact,
SILValue Operand,
ArrayRef<SILValue> TypeDependentOperands,
- SILType DestTy,
- SILBasicBlock *SuccessBB, SILBasicBlock *FailureBB)
+ SILType DestTy, SILBasicBlock *SuccessBB,
+ SILBasicBlock *FailureBB, ProfileCounter Target1Count,
+ ProfileCounter Target2Count)
: UnaryInstructionWithTypeDependentOperandsBase(DebugLoc, Operand,
- TypeDependentOperands),
- DestTy(DestTy), IsExact(IsExact),
- DestBBs{{this, SuccessBB}, {this, FailureBB}} {}
+ TypeDependentOperands),
+ DestTy(DestTy),
+ IsExact(IsExact), DestBBs{{this, SuccessBB, Target1Count},
+ {this, FailureBB, Target2Count}} {}
static CheckedCastBranchInst *
create(SILDebugLocation DebugLoc, bool IsExact, SILValue Operand,
SILType DestTy, SILBasicBlock *SuccessBB, SILBasicBlock *FailureBB,
- SILFunction &F, SILOpenedArchetypesState &OpenedArchetypes);
+ SILFunction &F, SILOpenedArchetypesState &OpenedArchetypes,
+ ProfileCounter Target1Count, ProfileCounter Target2Count);
public:
bool isExact() const { return IsExact; }
@@ -6294,9 +6385,10 @@
SILBasicBlock *getFailureBB() { return DestBBs[1]; }
const SILBasicBlock *getFailureBB() const { return DestBBs[1]; }
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::CheckedCastBranchInst;
- }
+ /// The number of times the True branch was executed
+ ProfileCounter getTrueBBCount() const { return DestBBs[0].getCount(); }
+ /// The number of times the False branch was executed
+ ProfileCounter getFalseBBCount() const { return DestBBs[1].getCount(); }
};
/// Perform a checked cast operation and branch on whether the cast succeeds.
@@ -6304,8 +6396,9 @@
/// argument.
class CheckedCastValueBranchInst final
: public UnaryInstructionWithTypeDependentOperandsBase<
- ValueKind::CheckedCastValueBranchInst, CheckedCastValueBranchInst,
- TermInst, false> {
+ SILInstructionKind::CheckedCastValueBranchInst,
+ CheckedCastValueBranchInst,
+ TermInst> {
friend SILBuilder;
SILType DestTy;
@@ -6346,15 +6439,13 @@
const SILBasicBlock *getSuccessBB() const { return DestBBs[0]; }
SILBasicBlock *getFailureBB() { return DestBBs[1]; }
const SILBasicBlock *getFailureBB() const { return DestBBs[1]; }
-
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::CheckedCastValueBranchInst;
- }
};
/// Perform a checked cast operation and branch on whether the cast succeeds.
/// The result of the checked cast is left in the destination address.
-class CheckedCastAddrBranchInst : public TermInst {
+class CheckedCastAddrBranchInst
+ : public InstructionBase<SILInstructionKind::CheckedCastAddrBranchInst,
+ TermInst> {
friend SILBuilder;
CastConsumptionKind ConsumptionKind;
@@ -6374,11 +6465,13 @@
CheckedCastAddrBranchInst(SILDebugLocation DebugLoc,
CastConsumptionKind consumptionKind, SILValue src,
CanType srcType, SILValue dest, CanType targetType,
- SILBasicBlock *successBB, SILBasicBlock *failureBB)
- : TermInst(ValueKind::CheckedCastAddrBranchInst, DebugLoc),
- ConsumptionKind(consumptionKind), Operands{this, src, dest},
- DestBBs{{this, successBB}, {this, failureBB}}, SourceType(srcType),
- TargetType(targetType) {}
+ SILBasicBlock *successBB, SILBasicBlock *failureBB,
+ ProfileCounter Target1Count,
+ ProfileCounter Target2Count)
+ : InstructionBase(DebugLoc), ConsumptionKind(consumptionKind),
+ Operands{this, src, dest}, DestBBs{{this, successBB, Target1Count},
+ {this, failureBB, Target2Count}},
+ SourceType(srcType), TargetType(targetType) {}
public:
CastConsumptionKind getConsumptionKind() const { return ConsumptionKind; }
@@ -6404,9 +6497,10 @@
SILBasicBlock *getFailureBB() { return DestBBs[1]; }
const SILBasicBlock *getFailureBB() const { return DestBBs[1]; }
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::CheckedCastAddrBranchInst;
- }
+ /// The number of times the True branch was executed.
+ ProfileCounter getTrueBBCount() const { return DestBBs[0].getCount(); }
+ /// The number of times the False branch was executed.
+ ProfileCounter getFalseBBCount() const { return DestBBs[1].getCount(); }
};
/// A private abstract class to store the destinations of a TryApplyInst.
@@ -6421,7 +6515,7 @@
SILSuccessor DestBBs[2];
protected:
- TryApplyInstBase(ValueKind valueKind, SILDebugLocation Loc,
+ TryApplyInstBase(SILInstructionKind valueKind, SILDebugLocation Loc,
SILBasicBlock *normalBB, SILBasicBlock *errorBB);
public:
@@ -6447,7 +6541,8 @@
/// TryApplyInst - Represents the full application of a function that
/// can produce an error.
class TryApplyInst
- : public ApplyInstBase<TryApplyInst, TryApplyInstBase> {
+ : public InstructionBase<SILInstructionKind::TryApplyInst,
+ ApplyInstBase<TryApplyInst, TryApplyInstBase>> {
friend SILBuilder;
TryApplyInst(SILDebugLocation DebugLoc, SILValue callee,
@@ -6463,11 +6558,6 @@
SILBasicBlock *normalBB, SILBasicBlock *errorBB, SILFunction &F,
SILOpenedArchetypesState &OpenedArchetypes,
const GenericSpecializationInformation *SpecializationInfo);
-
-public:
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::TryApplyInst;
- }
};
/// An apply instruction.
@@ -6479,7 +6569,7 @@
public:
ApplySite() : Inst(nullptr) {}
- explicit ApplySite(ValueBase *inst)
+ explicit ApplySite(SILInstruction *inst)
: Inst(static_cast<SILInstruction*>(inst)) {
assert(classof(inst) && "not an apply instruction?");
}
@@ -6491,8 +6581,17 @@
return Inst->getModule();
}
- static ApplySite isa(ValueBase *inst) {
- return (classof(inst) ? ApplySite(inst) : ApplySite());
+ static ApplySite isa(SILNode *node) {
+ switch (node->getKind()) {
+ case SILNodeKind::ApplyInst:
+ return ApplySite(cast<ApplyInst>(node));
+ case SILNodeKind::TryApplyInst:
+ return ApplySite(cast<TryApplyInst>(node));
+ case SILNodeKind::PartialApplyInst:
+ return ApplySite(cast<PartialApplyInst>(node));
+ default:
+ return ApplySite();
+ }
}
explicit operator bool() const {
@@ -6507,11 +6606,11 @@
#define FOREACH_IMPL_RETURN(OPERATION) do { \
switch (Inst->getKind()) { \
- case ValueKind::ApplyInst: \
+ case SILInstructionKind::ApplyInst: \
return cast<ApplyInst>(Inst)->OPERATION; \
- case ValueKind::PartialApplyInst: \
+ case SILInstructionKind::PartialApplyInst: \
return cast<PartialApplyInst>(Inst)->OPERATION; \
- case ValueKind::TryApplyInst: \
+ case SILInstructionKind::TryApplyInst: \
return cast<TryApplyInst>(Inst)->OPERATION; \
default: \
llvm_unreachable("not an apply instruction!"); \
@@ -6627,9 +6726,9 @@
/// The arguments passed to this instruction, without self.
OperandValueArrayRef getArgumentsWithoutSelf() const {
switch (Inst->getKind()) {
- case ValueKind::ApplyInst:
+ case SILInstructionKind::ApplyInst:
return cast<ApplyInst>(Inst)->getArgumentsWithoutSelf();
- case ValueKind::TryApplyInst:
+ case SILInstructionKind::TryApplyInst:
return cast<TryApplyInst>(Inst)->getArgumentsWithoutSelf();
default:
llvm_unreachable("not implemented for this instruction!");
@@ -6643,10 +6742,10 @@
// argument. Returns 0 for full applies. May return > 0 for partial applies.
unsigned getCalleeArgIndexOfFirstAppliedArg() const {
switch (Inst->getKind()) {
- case ValueKind::ApplyInst:
- case ValueKind::TryApplyInst:
+ case SILInstructionKind::ApplyInst:
+ case SILInstructionKind::TryApplyInst:
return 0;
- case ValueKind::PartialApplyInst:
+ case SILInstructionKind::PartialApplyInst:
// The arguments to partial_apply are a suffix of the arguments to the
// the actually-called function.
return getSubstCalleeConv().getNumSILArguments() - getNumArguments();
@@ -6680,9 +6779,9 @@
/// Return the self argument passed to this instruction.
bool hasSelfArgument() const {
switch (Inst->getKind()) {
- case ValueKind::ApplyInst:
+ case SILInstructionKind::ApplyInst:
return cast<ApplyInst>(Inst)->hasSelfArgument();
- case ValueKind::TryApplyInst:
+ case SILInstructionKind::TryApplyInst:
return cast<TryApplyInst>(Inst)->hasSelfArgument();
default:
llvm_unreachable("not implemented for this instruction!");
@@ -6692,9 +6791,9 @@
/// Return the self argument passed to this instruction.
SILValue getSelfArgument() const {
switch (Inst->getKind()) {
- case ValueKind::ApplyInst:
+ case SILInstructionKind::ApplyInst:
return cast<ApplyInst>(Inst)->getSelfArgument();
- case ValueKind::TryApplyInst:
+ case SILInstructionKind::TryApplyInst:
return cast<TryApplyInst>(Inst)->getSelfArgument();
default:
llvm_unreachable("not implemented for this instruction!");
@@ -6704,9 +6803,9 @@
/// Return the self operand passed to this instruction.
Operand &getSelfArgumentOperand() {
switch (Inst->getKind()) {
- case ValueKind::ApplyInst:
+ case SILInstructionKind::ApplyInst:
return cast<ApplyInst>(Inst)->getSelfArgumentOperand();
- case ValueKind::TryApplyInst:
+ case SILInstructionKind::TryApplyInst:
return cast<TryApplyInst>(Inst)->getSelfArgumentOperand();
default:
llvm_unreachable("not implemented for this instruction!");
@@ -6728,10 +6827,10 @@
return lhs.getInstruction() != rhs.getInstruction();
}
- static bool classof(const ValueBase *inst) {
- return (inst->getKind() == ValueKind::ApplyInst ||
- inst->getKind() == ValueKind::PartialApplyInst ||
- inst->getKind() == ValueKind::TryApplyInst);
+ static bool classof(const SILInstruction *inst) {
+ return (inst->getKind() == SILInstructionKind::ApplyInst ||
+ inst->getKind() == SILInstructionKind::PartialApplyInst ||
+ inst->getKind() == SILInstructionKind::TryApplyInst);
}
};
@@ -6741,14 +6840,21 @@
public:
FullApplySite() : ApplySite() {}
- explicit FullApplySite(ValueBase *inst) : ApplySite(inst) {
+ explicit FullApplySite(SILInstruction *inst) : ApplySite(inst) {
assert(classof(inst) && "not an apply instruction?");
}
FullApplySite(ApplyInst *inst) : ApplySite(inst) {}
FullApplySite(TryApplyInst *inst) : ApplySite(inst) {}
- static FullApplySite isa(ValueBase *inst) {
- return (classof(inst) ? FullApplySite(inst) : FullApplySite());
+ static FullApplySite isa(SILNode *node) {
+ switch (node->getKind()) {
+ case SILNodeKind::ApplyInst:
+ return FullApplySite(cast<ApplyInst>(node));
+ case SILNodeKind::TryApplyInst:
+ return FullApplySite(cast<TryApplyInst>(node));
+ default:
+ return FullApplySite();
+ }
}
bool hasIndirectSILResults() const {
@@ -6771,9 +6877,9 @@
return FullApplySite(p);
}
- static bool classof(const ValueBase *inst) {
- return (inst->getKind() == ValueKind::ApplyInst ||
- inst->getKind() == ValueKind::TryApplyInst);
+ static bool classof(const SILInstruction *inst) {
+ return (inst->getKind() == SILInstructionKind::ApplyInst ||
+ inst->getKind() == SILInstructionKind::TryApplyInst);
}
};
diff --git a/include/swift/SIL/SILModule.h b/include/swift/SIL/SILModule.h
index f9dc6ed..dc6c399 100644
--- a/include/swift/SIL/SILModule.h
+++ b/include/swift/SIL/SILModule.h
@@ -20,21 +20,22 @@
#include "swift/AST/ASTContext.h"
#include "swift/AST/Builtins.h"
#include "swift/AST/Module.h"
-#include "swift/AST/SILOptions.h"
#include "swift/AST/SILLayout.h"
+#include "swift/AST/SILOptions.h"
#include "swift/Basic/LangOptions.h"
+#include "swift/Basic/ProfileCounter.h"
#include "swift/Basic/Range.h"
+#include "swift/SIL/Notifications.h"
#include "swift/SIL/SILCoverageMap.h"
#include "swift/SIL/SILDeclRef.h"
#include "swift/SIL/SILDefaultWitnessTable.h"
#include "swift/SIL/SILFunction.h"
#include "swift/SIL/SILGlobalVariable.h"
-#include "swift/SIL/Notifications.h"
+#include "swift/SIL/SILPrintContext.h"
#include "swift/SIL/SILType.h"
#include "swift/SIL/SILVTable.h"
#include "swift/SIL/SILWitnessTable.h"
#include "swift/SIL/TypeLowering.h"
-#include "swift/SIL/SILPrintContext.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/Optional.h"
@@ -248,7 +249,7 @@
/// Send the invalidation message that \p V is being deleted to all
/// registered handlers. The order of handlers is deterministic but arbitrary.
- void notifyDeleteHandlers(ValueBase *V);
+ void notifyDeleteHandlers(SILNode *node);
/// \brief This converts Swift types to SILTypes.
mutable Lowering::TypeConverter Types;
@@ -483,12 +484,12 @@
/// \brief Return the declaration of a utility function that can,
/// but needn't, be shared between modules.
- SILFunction *getOrCreateSharedFunction(SILLocation loc,
- StringRef name,
+ SILFunction *getOrCreateSharedFunction(SILLocation loc, StringRef name,
CanSILFunctionType type,
IsBare_t isBareSILFunction,
IsTransparent_t isTransparent,
IsSerialized_t isSerialized,
+ ProfileCounter entryCount,
IsThunk_t isThunk);
/// \brief Return the declaration of a function, or create it if it doesn't
@@ -497,30 +498,34 @@
SILLocation loc, StringRef name, SILLinkage linkage,
CanSILFunctionType type, IsBare_t isBareSILFunction,
IsTransparent_t isTransparent, IsSerialized_t isSerialized,
+ ProfileCounter entryCount = ProfileCounter(),
IsThunk_t isThunk = IsNotThunk,
SubclassScope subclassScope = SubclassScope::NotApplicable);
/// \brief Return the declaration of a function, or create it if it doesn't
/// exist.
- SILFunction *getOrCreateFunction(SILLocation loc,
- SILDeclRef constant,
- ForDefinition_t forDefinition);
+ SILFunction *
+ getOrCreateFunction(SILLocation loc, SILDeclRef constant,
+ ForDefinition_t forDefinition,
+ ProfileCounter entryCount = ProfileCounter());
/// \brief Create a function declaration.
///
/// This signature is a direct copy of the signature of SILFunction::create()
/// in order to simplify refactoring all SILFunction creation use-sites to use
/// SILModule. Eventually the uses should probably be refactored.
- SILFunction *createFunction(
- SILLinkage linkage, StringRef name, CanSILFunctionType loweredType,
- GenericEnvironment *genericEnv, Optional<SILLocation> loc,
- IsBare_t isBareSILFunction, IsTransparent_t isTrans,
- IsSerialized_t isSerialized, IsThunk_t isThunk = IsNotThunk,
- SubclassScope subclassScope = SubclassScope::NotApplicable,
- Inline_t inlineStrategy = InlineDefault,
- EffectsKind EK = EffectsKind::Unspecified,
- SILFunction *InsertBefore = nullptr,
- const SILDebugScope *DebugScope = nullptr);
+ SILFunction *
+ createFunction(SILLinkage linkage, StringRef name,
+ CanSILFunctionType loweredType, GenericEnvironment *genericEnv,
+ Optional<SILLocation> loc, IsBare_t isBareSILFunction,
+ IsTransparent_t isTrans, IsSerialized_t isSerialized,
+ ProfileCounter entryCount = ProfileCounter(),
+ IsThunk_t isThunk = IsNotThunk,
+ SubclassScope subclassScope = SubclassScope::NotApplicable,
+ Inline_t inlineStrategy = InlineDefault,
+ EffectsKind EK = EffectsKind::Unspecified,
+ SILFunction *InsertBefore = nullptr,
+ const SILDebugScope *DebugScope = nullptr);
/// Look up the SILWitnessTable representing the lowering of a protocol
/// conformance, and collect the substitutions to apply to the referenced
diff --git a/include/swift/SIL/SILNode.h b/include/swift/SIL/SILNode.h
new file mode 100644
index 0000000..4da965e
--- /dev/null
+++ b/include/swift/SIL/SILNode.h
@@ -0,0 +1,301 @@
+//===--- SILNode.h - Node base class for SIL --------------------*- C++ -*-===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the SILNode class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_SIL_SILNODE_H
+#define SWIFT_SIL_SILNODE_H
+
+#include "llvm/Support/Compiler.h"
+#include "llvm/ADT/DenseMapInfo.h"
+#include "swift/Basic/LLVM.h"
+#include <type_traits>
+
+namespace swift {
+
+class SILBasicBlock;
+class SILFunction;
+class SILInstruction;
+class SILModule;
+class SingleValueInstruction;
+class ValueBase;
+
+/// An enumeration which contains values for all the nodes in SILNodes.def.
+/// Other enumerators, like ValueKind and SILInstructionind, ultimately
+/// take their values from this enumerator.
+enum class SILNodeKind {
+#define NODE(ID, PARENT) \
+ ID,
+#define NODE_RANGE(ID, FIRST, LAST) \
+ First_##ID = FIRST, \
+ Last_##ID = LAST,
+#include "swift/SIL/SILNodes.def"
+};
+
+enum {
+ NumSILNodeKindBits = 8
+};
+static_assert(unsigned(SILNodeKind::Last_SILNode) < (1 << NumSILNodeKindBits),
+ "SILNodeKind fits in NumSILNodeKindBits bits");
+
+/// A SILNode is a node in the use-def graph of a SILFunction. It is
+/// either an instruction or a defined value which can be used by an
+/// instruction. A defined value may be an instruction result, a basic
+/// block argument, or the special 'undef' value.
+///
+/// The 'node' intuition is slightly imprecise because a single instruction
+/// may be composed of multiple SILNodes: one for the instruction itself
+/// and one for each value it produces. When an instruction kind always
+/// produces exactly one value, the cast machinery (isa, cast, and dyn_cast)
+/// works to make both nodes appear to be the same object: there is a value
+/// kind exactly equal to the instruction kind and the value node can be
+/// directly cast to the instruction's class. When an instruction kind
+/// never produces values, it has no corresponding value kind, and it is
+/// a compile-time error to attempt to cast a value node to the instruction
+/// class. When an instruction kind can have multiple values (not yet
+/// implemented), its value nodes have a different kind from the
+/// instruction kind and it is a static error to attempt to cast a value
+/// node to the instruction kind.
+///
+/// Another way of interpreting SILNode is that there is a SILNode for
+/// everything that can be numbered in SIL assembly (plus 'undef', which
+/// is not conventionally numbered). Instructions without results are
+/// still numbered in SIL in order to describe the users lists of an
+/// instruction or argument. Instructions with multiple results are
+/// numbered using their first result.
+///
+/// SILNode is a base class of both SILInstruction and ValueBase.
+/// Because there can be multiple SILNodes within a single instruction
+/// object, some care must be taken when working with SILNode pointers.
+/// These precautions only apply to SILNode* and not its subclasses.
+///
+/// - There may have multiple SILNode* values that refer to the same
+/// instruction. Data structures and algorithms that rely on
+/// uniqueness of a SILNode* should generally make sure that they're
+/// working with the canonical SILNode*; see getCanonicalSILNodeInObject().
+///
+/// - Do not use builtin C++ casts to downcast a SILNode*. A static_cast
+/// from SILNode* to SILInstruction* only works if the referenced
+/// SILNode is the base subobject of the object's SILInstruction
+/// subobject. If the SILNode is actually the base subobject of a
+/// ValueBase subobject, the cast will yield a corrupted value.
+/// Always use the LLVM casts (cast<>, dyn_cast<>, etc.) instead.
+class alignas(8) SILNode {
+protected:
+ enum class SILNodeStorageLocation {
+ Value,
+ Instruction
+ };
+
+private:
+ const unsigned Kind : NumSILNodeKindBits;
+ const unsigned StorageLoc : 1;
+ const unsigned IsCanonical : 1;
+
+ // TODO: Pack other things in here.
+
+ SILNodeStorageLocation getStorageLoc() const {
+ return SILNodeStorageLocation(StorageLoc);
+ }
+
+ const SILNode *getCanonicalSILNodeSlowPath() const;
+
+protected:
+ SILNode(SILNodeKind kind, SILNodeStorageLocation storageLoc)
+ : Kind(unsigned(kind)),
+ StorageLoc(unsigned(storageLoc)),
+ IsCanonical(storageLoc == SILNodeStorageLocation::Instruction ||
+ !hasMultipleSILNodes(kind)) {}
+
+public:
+
+ /// Does the given kind of node have multiple SILNode bases?
+ static bool hasMultipleSILNodes(SILNodeKind kind) {
+ // Currently only SingleValueInstructions. Note that multi-result
+ // instructions shouldn't return true for this.
+ return kind >= SILNodeKind::First_SingleValueInstruction &&
+ kind <= SILNodeKind::Last_SingleValueInstruction;
+ }
+
+ /// Is this SILNode the canonical SILNode subobject in this object?
+ bool isCanonicalSILNodeInObject() const {
+ return IsCanonical;
+ }
+
+ /// Return a pointer to the canonical SILNode subobject in this object.
+ SILNode *getCanonicalSILNodeInObject() {
+ if (IsCanonical) return this;
+ return const_cast<SILNode*>(getCanonicalSILNodeSlowPath());
+ }
+ const SILNode *getCanonicalSILNodeInObject() const {
+ if (IsCanonical) return this;
+ return getCanonicalSILNodeSlowPath();
+ }
+
+ LLVM_ATTRIBUTE_ALWAYS_INLINE
+ SILNodeKind getKind() const {
+ return SILNodeKind(Kind);
+ }
+
+ /// If this is a SILArgument or a SILInstruction get its parent basic block,
+ /// otherwise return null.
+ SILBasicBlock *getParentBlock() const;
+
+ /// If this is a SILArgument or a SILInstruction get its parent function,
+ /// otherwise return null.
+ SILFunction *getFunction() const;
+
+ /// If this is a SILArgument or a SILInstruction get its parent module,
+ /// otherwise return null.
+ SILModule *getModule() const;
+
+ /// Pretty-print the node. If the node is an instruction, the output
+ /// will be valid SIL assembly; otherwise, it will be an arbitrary
+ /// format suitable for debugging.
+ void print(raw_ostream &OS) const;
+ void dump() const;
+
+ /// Pretty-print the node in context, preceded by its operands (if the
+ /// value represents the result of an instruction) and followed by its
+ /// users.
+ void printInContext(raw_ostream &OS) const;
+ void dumpInContext() const;
+
+ // Cast to SingleValueInstruction. This is an implementation detail
+ // of the cast machinery. At a high level, all you need to know is to
+ // never use static_cast to downcast a SILNode.
+ SingleValueInstruction *castToSingleValueInstruction();
+ const SingleValueInstruction *castToSingleValueInstruction() const {
+ return const_cast<SILNode*>(this)->castToSingleValueInstruction();
+ }
+
+ static bool classof(const SILNode *node) {
+ return true;
+ }
+};
+
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+ const SILNode &node) {
+ node.print(OS);
+ return OS;
+}
+
+template <class To> struct cast_sil_node_is_unambiguous {
+ // The only ambiguity right now is between the value and instruction
+ // nodes on a SingleValueInstruction.
+ static constexpr bool value =
+ // If the destination type isn't a subclass of ValueBase or
+ // SILInstruction, there's no ambiguity.
+ (!std::is_base_of<SILInstruction, To>::value &&
+ !std::is_base_of<ValueBase, To>::value)
+
+ // If the destination type is a proper subclass of ValueBase
+ // that isn't a subclass of SILInstruction, there's no ambiguity.
+ || (std::is_base_of<ValueBase, To>::value &&
+ !std::is_same<ValueBase, To>::value &&
+ !std::is_base_of<SILInstruction, To>::value)
+
+ // If the destination type is a proper subclass of SILInstruction
+ // that isn't a subclass of ValueBase, there's no ambiguity.
+ || (std::is_base_of<SILInstruction, To>::value &&
+ !std::is_same<SILInstruction, To>::value &&
+ !std::is_base_of<ValueBase, To>::value);
+};
+
+template <class To,
+ bool IsSingleValueInstruction =
+ std::is_base_of<SingleValueInstruction, To>::value,
+ bool IsKnownUnambiguous =
+ cast_sil_node_is_unambiguous<To>::value>
+struct cast_sil_node;
+
+// If all complete objects of the destination type are known to only
+// contain a single node, we can just use a static_cast.
+template <class To>
+struct cast_sil_node<To, /*single value*/ false, /*unambiguous*/ true> {
+ static To *doit(SILNode *node) {
+ return &static_cast<To&>(*node);
+ }
+};
+
+// If we're casting to a subclass of SingleValueInstruction, we don't
+// need to dynamically check whether the node is an SVI. In fact,
+// we can't, because the static_cast will be ambiguous.
+template <class To>
+struct cast_sil_node<To, /*single value*/ true, /*unambiguous*/ false> {
+ static To *doit(SILNode *node) {
+ auto svi = node->castToSingleValueInstruction();
+ return &static_cast<To&>(*svi);
+ }
+};
+
+// Otherwise, we need to dynamically check which case we're in.
+template <class To>
+struct cast_sil_node<To, /*single value*/ false, /*unambiguous*/ false> {
+ static To *doit(SILNode *node) {
+ // If the node isn't dynamically a SingleValueInstruction, then this
+ // is indeed the SILNode subobject that's statically observable in To.
+ if (!SILNode::hasMultipleSILNodes(node->getKind())) {
+ return &static_cast<To&>(*node);
+ }
+
+ auto svi = node->castToSingleValueInstruction();
+ return &static_cast<To&>(*svi);
+ }
+};
+
+} // end namespace swift
+
+namespace llvm {
+
+/// Completely take over cast<>'ing from SILNode*. A static_cast to
+/// ValueBase* or SILInstruction* can be quite wrong.
+template <class To>
+struct cast_convert_val<To, swift::SILNode*, swift::SILNode*> {
+ using ret_type = typename cast_retty<To, swift::SILNode*>::ret_type;
+ static ret_type doit(swift::SILNode *node) {
+ return swift::cast_sil_node<To>::doit(node);
+ }
+};
+template <class To>
+struct cast_convert_val<To, const swift::SILNode *, const swift::SILNode *> {
+ using ret_type = typename cast_retty<To, const swift::SILNode*>::ret_type;
+ static ret_type doit(const swift::SILNode *node) {
+ return swift::cast_sil_node<To>::doit(const_cast<swift::SILNode*>(node));
+ }
+};
+
+// We don't support casting from SILNode references yet.
+template <class To, class From>
+struct cast_convert_val<To, swift::SILNode, From>;
+template <class To, class From>
+struct cast_convert_val<To, const swift::SILNode, From>;
+
+/// ValueBase * is always at least eight-byte aligned; make the three tag bits
+/// available through PointerLikeTypeTraits.
+template<>
+class PointerLikeTypeTraits<swift::SILNode *> {
+public:
+ static inline void *getAsVoidPointer(swift::SILNode *I) {
+ return (void*)I;
+ }
+ static inline swift::SILNode *getFromVoidPointer(void *P) {
+ return (swift::SILNode *)P;
+ }
+ enum { NumLowBitsAvailable = 3 };
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/include/swift/SIL/SILNodes.def b/include/swift/SIL/SILNodes.def
index 2894d6b..4cf2af4 100644
--- a/include/swift/SIL/SILNodes.def
+++ b/include/swift/SIL/SILNodes.def
@@ -14,60 +14,182 @@
//
//===----------------------------------------------------------------------===//
-/// VALUE(Id, Parent)
-/// The expression enumerator value is a ValueKind. The node's class name is
+/// NODE(ID, PARENT)
+///
+/// A concrete subclass of SILNode. ID is the name of the class as well
+/// as a member of SILNodeKind. PARENT is the name of its abstract
+/// superclass.
+#ifndef NODE
+#define NODE(ID, PARENT)
+#endif
+
+/// SINGLE_VALUE_INST(Id, Parent, TextualName, MemBehavior, MayRelease)
+///
+/// A concrete subclass of SingleValueInstruction, which inherits from
+/// both ValueBase and SILInstruction. ID is a member of both ValueKind
+/// and SILInstructionKind.
+#ifndef SINGLE_VALUE_INST
+#ifdef VALUE
+#define SINGLE_VALUE_INST(ID, NAME, PARENT, MEMBEHAVIOR, MAYRELEASE) \
+ VALUE(ID, PARENT)
+#else
+#define SINGLE_VALUE_INST(ID, NAME, PARENT, MEMBEHAVIOR, MAYRELEASE) \
+ FULL_INST(ID, NAME, PARENT, MEMBEHAVIOR, MAYRELEASE)
+#endif
+#endif
+
+/// VALUE(ID, PARENT)
+///
+/// A concrete subclass of ValueBase. ID is a member of ValueKind.
+/// ID is a member of ValueKind. The node's class name is
/// Id, and the name of its base class (in the SILValue hierarchy) is Parent.
#ifndef VALUE
-#define VALUE(Id, Parent)
+#define VALUE(ID, PARENT) NODE(ID, PARENT)
#endif
-/// ARGUMENT(Id, Parent)
-/// The expression enumerator value is a ValueKind. The node's class name is
-/// Id and the name of its base class (in the SILValue hierarchy) is Parent.
+/// ARGUMENT(ID, PARENT)
+///
+/// A concrete subclass of SILArgument, which is a subclass of ValueBase.
#ifndef ARGUMENT
-#define ARGUMENT(Id, Parent) VALUE(Id, Parent)
+#define ARGUMENT(ID, PARENT) VALUE(ID, PARENT)
#endif
-/// INST(Id, Parent, TextualName, MemBehavior, MayRelease)
+/// INST(ID, PARENT)
///
-/// The expression enumerator value is a ValueKind. The node's class name is
-/// Id, and the name of its base class (in the SILInstruction hierarchy) is
-/// Parent. TextualName is the textual name of the instruction. MemBehavior is
-/// an enum value that reflects the memory behavior of the
-/// instruction. MayRelease indicates whether the execution of the instruction
-/// may result in memory being released.
+/// A concrete subclass of SILInstruction. ID is a member of
+/// SILInstructionKind.
#ifndef INST
-#define INST(Id, Parent, TextualName, MemBehavior, MayRelease) VALUE(Id, Parent)
+#define INST(ID, PARENT) NODE(ID, PARENT)
#endif
-/// TERMINATOR(Id, Parent, TextualName, MemBehavior, MayRelease)
-/// Expands for terminator instructions. The expression enumerator value is a
-/// ValueKind. The node's class name is Id, and the name of its base class
-/// (in the SILInstruction hierarchy) is Parent. TextualName is the name of
-/// the instruction in textual SIL. MemBehavior is an enum value that
-/// reflects the memory behavior of the instruction. MayRelease indicates
-/// whether the execution of the instruction may result in memory being
-/// released.
-#ifndef TERMINATOR
-#define TERMINATOR(Id, Parent, TextualName, MemBehavior, MayRelease) \
- INST(Id, Parent, TextualName, MemBehavior, MayRelease)
-#endif
-
-/// An abstract value base is an abstract base class in the hierarchy; it is
-/// never a most-derived type, and it does not have an enumerator in ValueKind.
+/// FULL_INST(ID, NAME, PARENT, MEMBEHAVIOR, MAYRELEASE)
///
-/// Most metaprograms do not care about abstract expressions, so the default
-/// is to ignore them.
-#ifndef ABSTRACT_VALUE
-#define ABSTRACT_VALUE(Id, Parent)
+/// A macro which includes a bunch of secondary information about
+/// an instruction. In addition to the information from INST:
+///
+/// NAME is the name of the instruction in SIL assembly.
+/// The argument will be a bare identifier, not a string literal.
+///
+/// MEMBEHAVIOR is an enum value that reflects the memory behavior of
+/// the instruction.
+///
+/// MAYRELEASE indicates whether the execution of the
+/// instruction may result in memory being released.
+#ifndef FULL_INST
+#define FULL_INST(ID, NAME, PARENT, MEMBEHAVIOR, MAYRELEASE) INST(ID, PARENT)
#endif
-/// A convenience for determining the range of values. These will always
-/// appear immediately after the last member.
-#ifndef VALUE_RANGE
-#define VALUE_RANGE(Id, First, Last)
+/// NON_VALUE_INST(ID, NAME, PARENT, MEMBEHAVIOR, MAYRELEASE)
+///
+/// ID is a SILInstructionKind and the name of a subclass of SILInstruction
+/// that does not inherit from ValueBase.
+#ifndef NON_VALUE_INST
+#define NON_VALUE_INST(ID, NAME, PARENT, MEMBEHAVIOR, MAYRELEASE) \
+ FULL_INST(ID, NAME, PARENT, MEMBEHAVIOR, MAYRELEASE)
#endif
+/// TERMINATOR(ID, NAME, PARENT, MEMBEHAVIOR, MAYRELEASE)
+///
+/// ID is a member of TerminatorKind and the name of a subclass of TermInst.
+#ifndef TERMINATOR
+#define TERMINATOR(ID, NAME, PARENT, MEMBEHAVIOR, MAYRELEASE) \
+ NON_VALUE_INST(ID, NAME, PARENT, MEMBEHAVIOR, MAYRELEASE)
+#endif
+
+/// ABSTRACT_NODE(ID, PARENT)
+///
+/// An abstract class in the SILNode hierarchy. It does not have an
+/// enumerator in SILNodeKind and is never the most-derived type of a
+/// node. ID is the name of the class.
+///
+/// PARENT is the name of its abstract superclass in the node
+/// hierarchy, which will be either a subject of an ABSTRACT_NODE
+/// entry or SILNode. SingleValueInstruction considers its superclass
+/// to be SILInstruction for the purposes of the node hierarchy.
+#ifndef ABSTRACT_NODE
+#define ABSTRACT_NODE(ID, PARENT)
+#endif
+
+// Handle SingleValueInstruction.
+#ifdef ABSTRACT_VALUE
+#define ABSTRACT_VALUE_AND_INST(ID, VALUE_PARENT, INST_PARENT) \
+ ABSTRACT_VALUE(ID, VALUE_PARENT)
+#else
+#define ABSTRACT_VALUE_AND_INST(ID, VALUE_PARENT, INST_PARENT) \
+ ABSTRACT_INST(ID, INST_PARENT)
+#endif
+
+/// ABSTRACT_SINGLE_VALUE_INST(ID, PARENT)
+///
+/// An abstract subclass of SingleValueInstruction, which is therefore
+/// in both the ValueBase and SILInstruction hierarchies.
+#ifndef ABSTRACT_SINGLE_VALUE_INST
+#ifdef ABSTRACT_VALUE
+#define ABSTRACT_SINGLE_VALUE_INST(ID, PARENT) ABSTRACT_VALUE(ID, PARENT)
+#else
+#define ABSTRACT_SINGLE_VALUE_INST(ID, PARENT) ABSTRACT_INST(ID, PARENT)
+#endif
+#endif
+
+/// ABSTRACT_VALUE(ID, PARENT)
+///
+/// An abstract class in the ValueBase hierarchy. It does not have an
+/// enumerator in ValueKind and is never the most-derived type of a
+/// node. ID is the name of the class.
+///
+/// PARENT is the name of its abstract superclass in the ValueBase
+/// hierarchy, which be either a subject of an ABSTRACT_VALUE
+/// entry or ValueBase.
+#ifndef ABSTRACT_VALUE
+#define ABSTRACT_VALUE(ID, PARENT) ABSTRACT_NODE(ID, PARENT)
+#endif
+
+/// ABSTRACT_INST(ID, PARENT)
+///
+/// An abstract class in the SILInstruction hierarchy. It does not
+/// enumerator in SILInstructionKind and is never the most-derived type
+/// of a node. ID is the name of the class.
+///
+/// PARENT is the name of its abstract superclass in the SILInstruction
+/// hierarchy, which be either a subject of an ABSTRACT_INST
+/// entry or SILInstruction.
+#ifndef ABSTRACT_INST
+#define ABSTRACT_INST(ID, PARENT) ABSTRACT_NODE(ID, PARENT)
+#endif
+
+/// NODE_RANGE(ID, PARENT)
+///
+/// The enumerator range of an abstract class in the SILNode hierarchy.
+/// This will always appear right after the last member of the class.
+#ifndef NODE_RANGE
+#define NODE_RANGE(ID, FIRST, LAST)
+#endif
+
+#ifndef SINGLE_VALUE_INST_RANGE
+#ifdef VALUE_RANGE
+#define SINGLE_VALUE_INST_RANGE(ID, FIRST, LAST) VALUE_RANGE(ID, FIRST, LAST)
+#else
+#define SINGLE_VALUE_INST_RANGE(ID, FIRST, LAST) INST_RANGE(ID, FIRST, LAST)
+#endif
+#endif
+
+/// VALUE_RANGE(ID, PARENT)
+///
+/// The enumerator range of an abstract class in the ValueBase hierarchy.
+#ifndef VALUE_RANGE
+#define VALUE_RANGE(ID, FIRST, LAST) NODE_RANGE(ID, FIRST, LAST)
+#endif
+
+/// INST_RANGE(ID, PARENT)
+///
+/// The enumerator range of an abstract class in the SILInstruction
+/// hierarchy.
+#ifndef INST_RANGE
+#define INST_RANGE(ID, FIRST, LAST) NODE_RANGE(ID, FIRST, LAST)
+#endif
+
+ABSTRACT_NODE(ValueBase, SILNode)
+
ABSTRACT_VALUE(SILArgument, ValueBase)
ARGUMENT(SILPHIArgument, SILArgument)
ARGUMENT(SILFunctionArgument, SILArgument)
@@ -75,219 +197,118 @@
VALUE(SILUndef, ValueBase)
-// Please keep the order of instructions consistent with the order of their
-// descriptions in the SIL reference in docs/SIL.rst.
+ABSTRACT_NODE(SILInstruction, SILNode)
-ABSTRACT_VALUE(SILInstruction, ValueBase)
+ABSTRACT_VALUE_AND_INST(SingleValueInstruction, ValueBase, SILInstruction)
// Allocation instructions.
- ABSTRACT_VALUE(AllocationInst, SILInstruction)
- INST(AllocStackInst, AllocationInst, alloc_stack, None, DoesNotRelease)
- INST(AllocRefInst, AllocationInst, alloc_ref, None, DoesNotRelease)
- INST(AllocRefDynamicInst, AllocationInst, alloc_ref_dynamic, None, DoesNotRelease)
- INST(AllocValueBufferInst, AllocationInst, alloc_value_buffer, None, DoesNotRelease)
- INST(AllocBoxInst, AllocationInst, alloc_box, None, DoesNotRelease)
- INST(AllocExistentialBoxInst, AllocationInst, alloc_existential_box, MayWrite, DoesNotRelease)
- VALUE_RANGE(AllocationInst, AllocStackInst, AllocExistentialBoxInst)
+ ABSTRACT_SINGLE_VALUE_INST(AllocationInst, SingleValueInstruction)
+ SINGLE_VALUE_INST(AllocStackInst, alloc_stack,
+ AllocationInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(AllocRefInst, alloc_ref,
+ AllocationInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(AllocRefDynamicInst, alloc_ref_dynamic,
+ AllocationInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(AllocValueBufferInst, alloc_value_buffer,
+ AllocationInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(AllocBoxInst, alloc_box,
+ AllocationInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(AllocExistentialBoxInst, alloc_existential_box,
+ AllocationInst, MayWrite, DoesNotRelease)
+ SINGLE_VALUE_INST_RANGE(AllocationInst, AllocStackInst, AllocExistentialBoxInst)
- // Deallocation instructions.
- ABSTRACT_VALUE(DeallocationInst, SILInstruction)
- INST(DeallocStackInst, DeallocationInst, dealloc_stack, MayHaveSideEffects, DoesNotRelease)
- INST(DeallocRefInst, DeallocationInst, dealloc_ref, MayHaveSideEffects, DoesNotRelease)
- INST(DeallocPartialRefInst, DeallocationInst, dealloc_partial_ref, MayHaveSideEffects,
- DoesNotRelease)
- INST(DeallocValueBufferInst, DeallocationInst, dealloc_value_buffer, MayHaveSideEffects,
- DoesNotRelease)
- INST(DeallocBoxInst, DeallocationInst, dealloc_box, MayHaveSideEffects, DoesNotRelease)
- INST(DeallocExistentialBoxInst, DeallocationInst, dealloc_existential_box, MayHaveSideEffects,
- DoesNotRelease)
- VALUE_RANGE(DeallocationInst, DeallocStackInst, DeallocExistentialBoxInst)
-
- // Accessing memory
- INST(LoadInst, SILInstruction, load, MayRead, DoesNotRelease)
- INST(LoadBorrowInst, SILInstruction, load_borrow, MayRead, DoesNotRelease)
- INST(BeginBorrowInst, SILInstruction, begin_borrow, MayHaveSideEffects, DoesNotRelease)
- INST(EndBorrowInst, SILInstruction, end_borrow, MayHaveSideEffects, DoesNotRelease)
- INST(EndBorrowArgumentInst, SILInstruction, end_borrow_argument, MayHaveSideEffects, DoesNotRelease)
- INST(BeginAccessInst, SILInstruction, begin_access, MayHaveSideEffects, DoesNotRelease)
- INST(EndAccessInst, SILInstruction, end_access, MayHaveSideEffects, DoesNotRelease)
- INST(BeginUnpairedAccessInst, SILInstruction, begin_unpaired_access, MayHaveSideEffects, DoesNotRelease)
- INST(EndUnpairedAccessInst, SILInstruction, end_unpaired_access, MayHaveSideEffects, DoesNotRelease)
- INST(LoadUnownedInst, SILInstruction, load_unowned, MayRead, DoesNotRelease)
- INST(LoadWeakInst, SILInstruction, load_weak, MayRead, DoesNotRelease)
- INST(StoreInst, SILInstruction, store, MayWrite, DoesNotRelease)
- INST(StoreBorrowInst, SILInstruction, store_borrow, MayWrite, DoesNotRelease)
- INST(AssignInst, SILInstruction, assign, MayWrite, DoesNotRelease)
- INST(MarkUninitializedInst, SILInstruction, mark_uninitialized, None, DoesNotRelease)
- INST(MarkUninitializedBehaviorInst, SILInstruction, mark_uninitialized_behavior, None, DoesNotRelease)
- INST(MarkFunctionEscapeInst, SILInstruction, mark_function_escape, None, DoesNotRelease)
- INST(DebugValueInst, SILInstruction, debug_value, None, DoesNotRelease)
- INST(DebugValueAddrInst, SILInstruction, debug_value_addr, None, DoesNotRelease)
- INST(StoreUnownedInst, SILInstruction, store_unowned, MayWrite, DoesNotRelease)
- INST(StoreWeakInst, SILInstruction, store_weak, MayWrite, DoesNotRelease)
- INST(CopyAddrInst, SILInstruction, copy_addr, MayHaveSideEffects, MayRelease)
- INST(DestroyAddrInst, SILInstruction, destroy_addr, MayHaveSideEffects, MayRelease)
- INST(ProjectValueBufferInst, SILInstruction, project_value_buffer, MayRead, DoesNotRelease)
- INST(ProjectBoxInst, SILInstruction, project_box, None, DoesNotRelease)
- INST(ProjectExistentialBoxInst, SILInstruction, project_existential_box, None, DoesNotRelease)
- ABSTRACT_VALUE(IndexingInst, SILInstruction)
- INST(IndexAddrInst, IndexingInst, index_addr, None, DoesNotRelease)
- INST(TailAddrInst, IndexingInst, tail_addr, None, DoesNotRelease)
- INST(IndexRawPointerInst, IndexingInst, index_raw_pointer, None, DoesNotRelease)
- VALUE_RANGE(IndexingInst, IndexAddrInst, IndexRawPointerInst)
-
- // BindMemory has no physical side effect. Semantically it writes to
- // its affected memory region because any reads or writes accessing
- // that memory must be dependent on the bind operation.
- INST(BindMemoryInst, SILInstruction, bind_memory, MayWrite, DoesNotRelease)
-
- // Reference Counting
- ABSTRACT_VALUE(RefCountingInst, SILInstruction)
- INST(StrongRetainInst, RefCountingInst, strong_retain, MayHaveSideEffects, DoesNotRelease)
- INST(StrongReleaseInst, RefCountingInst, strong_release, MayHaveSideEffects, MayRelease)
- INST(StrongRetainUnownedInst, RefCountingInst, strong_retain_unowned, MayHaveSideEffects,
- DoesNotRelease)
- INST(StrongPinInst, RefCountingInst, strong_pin, MayHaveSideEffects, DoesNotRelease)
- INST(StrongUnpinInst, RefCountingInst, strong_unpin, MayHaveSideEffects, DoesNotRelease)
- INST(UnownedRetainInst, RefCountingInst, unowned_retain, MayHaveSideEffects, DoesNotRelease)
- INST(UnownedReleaseInst, RefCountingInst, unowned_release, MayHaveSideEffects,
- MayRelease)
- INST(UnmanagedRetainValueInst, RefCountingInst, unmanaged_retain_value, MayHaveSideEffects, DoesNotRelease)
- INST(UnmanagedReleaseValueInst, RefCountingInst, unmanaged_release_value, MayHaveSideEffects, MayRelease)
- INST(UnmanagedAutoreleaseValueInst, RefCountingInst, unmanaged_autorelease_value, MayHaveSideEffects, DoesNotRelease)
- INST(RetainValueInst, RefCountingInst, retain_value, MayHaveSideEffects, DoesNotRelease)
- INST(RetainValueAddrInst, RefCountingInst, retain_value_addr, MayHaveSideEffects, DoesNotRelease)
- INST(ReleaseValueInst, RefCountingInst, release_value, MayHaveSideEffects, MayRelease)
- INST(ReleaseValueAddrInst, RefCountingInst, release_value_addr, MayHaveSideEffects, MayRelease)
- INST(SetDeallocatingInst, RefCountingInst, set_deallocating, MayHaveSideEffects,
- DoesNotRelease)
- INST(AutoreleaseValueInst, RefCountingInst, autorelease_value, MayHaveSideEffects,
- DoesNotRelease)
- VALUE_RANGE(RefCountingInst, StrongRetainInst, AutoreleaseValueInst)
- // FIXME: Is MayHaveSideEffects appropriate?
- INST(FixLifetimeInst, SILInstruction, fix_lifetime, MayHaveSideEffects, DoesNotRelease)
- INST(MarkDependenceInst, SILInstruction, mark_dependence, None, DoesNotRelease)
- INST(CopyBlockInst, SILInstruction, copy_block, MayHaveSideEffects, DoesNotRelease)
- INST(CopyValueInst, SILInstruction, copy_value, MayHaveSideEffects, DoesNotRelease)
- INST(CopyUnownedValueInst, SILInstruction, copy_unowned_value, MayHaveSideEffects, DoesNotRelease)
- INST(DestroyValueInst, SILInstruction, destroy_value, MayHaveSideEffects, MayRelease)
- INST(EndLifetimeInst, SILInstruction, end_lifetime, MayHaveSideEffects, MayRelease)
- INST(UncheckedOwnershipConversionInst, SILInstruction, unchecked_ownership_conversion, MayHaveSideEffects, MayRelease)
-
- // IsUnique does not actually write to memory but should be modeled
- // as such. Its operand is a pointer to an object reference. The
- // optimizer should not assume that the same object is pointed to after
- // the isUnique instruction. It appears to write a new object reference.
- INST(IsUniqueInst, SILInstruction, is_unique, MayHaveSideEffects, DoesNotRelease)
- INST(IsUniqueOrPinnedInst, SILInstruction, is_unique_or_pinned, MayHaveSideEffects, DoesNotRelease)
-
- INST(AllocGlobalInst, SILInstruction, alloc_global, MayHaveSideEffects, DoesNotRelease)
+ ABSTRACT_SINGLE_VALUE_INST(IndexingInst, SingleValueInstruction)
+ SINGLE_VALUE_INST(IndexAddrInst, index_addr,
+ IndexingInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(TailAddrInst, tail_addr,
+ IndexingInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(IndexRawPointerInst, index_raw_pointer,
+ IndexingInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST_RANGE(IndexingInst, IndexAddrInst, IndexRawPointerInst)
// Literals
- ABSTRACT_VALUE(LiteralInst, SILInstruction)
- INST(FunctionRefInst, LiteralInst, function_ref, None, DoesNotRelease)
- INST(GlobalAddrInst, LiteralInst, global_addr, None, DoesNotRelease)
- INST(GlobalValueInst, LiteralInst, global_value, None, DoesNotRelease)
- INST(IntegerLiteralInst, LiteralInst, integer_literal, None, DoesNotRelease)
- INST(FloatLiteralInst, LiteralInst, float_literal, None, DoesNotRelease)
- INST(StringLiteralInst, LiteralInst, string_literal, None, DoesNotRelease)
- INST(ConstStringLiteralInst, LiteralInst, const_string_literal, None, DoesNotRelease)
- VALUE_RANGE(LiteralInst, FunctionRefInst, ConstStringLiteralInst)
+ ABSTRACT_SINGLE_VALUE_INST(LiteralInst, SingleValueInstruction)
+ SINGLE_VALUE_INST(FunctionRefInst, function_ref,
+ LiteralInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(GlobalAddrInst, global_addr,
+ LiteralInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(GlobalValueInst, global_value,
+ LiteralInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(IntegerLiteralInst, integer_literal,
+ LiteralInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(FloatLiteralInst, float_literal,
+ LiteralInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(StringLiteralInst, string_literal,
+ LiteralInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(ConstStringLiteralInst, const_string_literal,
+ LiteralInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST_RANGE(LiteralInst, FunctionRefInst, ConstStringLiteralInst)
// Dynamic Dispatch
- ABSTRACT_VALUE(MethodInst, SILInstruction)
- INST(ClassMethodInst, MethodInst, class_method, None, DoesNotRelease)
- INST(SuperMethodInst, MethodInst, super_method, None, DoesNotRelease)
- INST(WitnessMethodInst, MethodInst, witness_method, None, DoesNotRelease)
- INST(DynamicMethodInst, MethodInst, dynamic_method, None, DoesNotRelease)
- VALUE_RANGE(MethodInst, ClassMethodInst, DynamicMethodInst)
-
- // Function Application
- INST(ApplyInst, SILInstruction, apply, MayHaveSideEffects, MayRelease)
- INST(PartialApplyInst, SILInstruction, partial_apply, MayHaveSideEffects, DoesNotRelease)
- INST(BuiltinInst, SILInstruction, builtin, MayHaveSideEffects, MayRelease)
-
- // Metatypes
- INST(MetatypeInst, SILInstruction, metatype, None, DoesNotRelease)
- INST(ValueMetatypeInst, SILInstruction, value_metatype, MayRead, DoesNotRelease)
- INST(ExistentialMetatypeInst, SILInstruction, existential_metatype, MayRead, DoesNotRelease)
- INST(ObjCProtocolInst, SILInstruction, objc_protocol, None, DoesNotRelease)
-
- // Aggregate Types
- INST(ObjectInst, SILInstruction, object, None, DoesNotRelease)
- INST(TupleInst, SILInstruction, tuple, None, DoesNotRelease)
- INST(TupleExtractInst, SILInstruction, tuple_extract, None, DoesNotRelease)
- INST(TupleElementAddrInst, SILInstruction, tuple_element_addr, None, DoesNotRelease)
- INST(StructInst, SILInstruction, struct, None, DoesNotRelease)
- INST(StructExtractInst, SILInstruction, struct_extract, None, DoesNotRelease)
- INST(StructElementAddrInst, SILInstruction, struct_element_addr, None, DoesNotRelease)
- INST(RefElementAddrInst, SILInstruction, ref_element_addr, None, DoesNotRelease)
- INST(RefTailAddrInst, SILInstruction, ref_tail_addr, None, DoesNotRelease)
-
- // Enums
- INST(EnumInst, SILInstruction, enum, None, DoesNotRelease)
- INST(UncheckedEnumDataInst, SILInstruction, unchecked_enum_data, None, DoesNotRelease)
- INST(InitEnumDataAddrInst, SILInstruction, init_enum_data_addr, None, DoesNotRelease)
- INST(UncheckedTakeEnumDataAddrInst, SILInstruction, unchecked_take_enum_data_addr, MayWrite, DoesNotRelease)
- INST(InjectEnumAddrInst, SILInstruction, inject_enum_addr, MayWrite, DoesNotRelease)
- INST(SelectEnumInst, SILInstruction, select_enum, None, DoesNotRelease)
- INST(SelectEnumAddrInst, SILInstruction, select_enum_addr, MayRead, DoesNotRelease)
- INST(SelectValueInst, SILInstruction, select_value, None, DoesNotRelease)
-
- // Protocol and Protocol Composition Types
- INST(InitExistentialAddrInst, SILInstruction, init_existential_addr, MayWrite, DoesNotRelease)
- INST(InitExistentialValueInst, SILInstruction, init_existential_value, MayWrite, DoesNotRelease)
- INST(DeinitExistentialAddrInst, SILInstruction, deinit_existential_addr, MayHaveSideEffects,
- DoesNotRelease)
- INST(DeinitExistentialValueInst, SILInstruction, deinit_existential_value, MayHaveSideEffects,
- DoesNotRelease)
- INST(OpenExistentialAddrInst, SILInstruction, open_existential_addr, MayRead, DoesNotRelease)
- INST(InitExistentialRefInst, SILInstruction, init_existential_ref, None, DoesNotRelease)
- INST(OpenExistentialRefInst, SILInstruction, open_existential_ref, None, DoesNotRelease)
- INST(InitExistentialMetatypeInst, SILInstruction, init_existential_metatype, None, DoesNotRelease)
- INST(OpenExistentialMetatypeInst, SILInstruction, open_existential_metatype, None, DoesNotRelease)
- INST(OpenExistentialBoxInst, SILInstruction, open_existential_box, MayRead, DoesNotRelease)
- INST(OpenExistentialValueInst, SILInstruction, open_existential_value, MayRead, DoesNotRelease)
- INST(OpenExistentialBoxValueInst, SILInstruction, open_existential_box_value, MayRead, DoesNotRelease)
-
- // Blocks
- INST(ProjectBlockStorageInst, SILInstruction, project_block_storage, None, DoesNotRelease)
- INST(InitBlockStorageHeaderInst, SILInstruction, init_block_storage_header, None, DoesNotRelease)
-
- // Key paths
- // TODO: The only "side effect" is potentially retaining the returned key path
- // object; is there a more specific effect?
- INST(KeyPathInst, SILInstruction, keypath, MayHaveSideEffects, DoesNotRelease)
+ ABSTRACT_SINGLE_VALUE_INST(MethodInst, SingleValueInstruction)
+ SINGLE_VALUE_INST(ClassMethodInst, class_method,
+ MethodInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(SuperMethodInst, super_method,
+ MethodInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(WitnessMethodInst, witness_method,
+ MethodInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(DynamicMethodInst, dynamic_method,
+ MethodInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST_RANGE(MethodInst, ClassMethodInst, DynamicMethodInst)
// Conversions
- ABSTRACT_VALUE(ConversionInst, SILInstruction)
- INST(UpcastInst, ConversionInst, upcast, None, DoesNotRelease)
- INST(AddressToPointerInst, ConversionInst, address_to_pointer, None, DoesNotRelease)
- INST(PointerToAddressInst, ConversionInst, pointer_to_address, None, DoesNotRelease)
- INST(UncheckedRefCastInst, ConversionInst, unchecked_ref_cast, None, DoesNotRelease)
- INST(UncheckedAddrCastInst, ConversionInst, unchecked_addr_cast, None, DoesNotRelease)
- INST(UncheckedTrivialBitCastInst, ConversionInst, unchecked_trivial_bit_cast, None, DoesNotRelease)
- INST(UncheckedBitwiseCastInst, ConversionInst, unchecked_bitwise_cast, None, DoesNotRelease)
- INST(RefToRawPointerInst, ConversionInst, ref_to_raw_pointer, None, DoesNotRelease)
- INST(RawPointerToRefInst, ConversionInst, raw_pointer_to_ref, None, DoesNotRelease)
- INST(RefToUnownedInst, ConversionInst, ref_to_unowned, None, DoesNotRelease)
- INST(UnownedToRefInst, ConversionInst, unowned_to_ref, None, DoesNotRelease)
- INST(RefToUnmanagedInst, ConversionInst, ref_to_unmanaged, None, DoesNotRelease)
- INST(UnmanagedToRefInst, ConversionInst, unmanaged_to_ref, None, DoesNotRelease)
- INST(ConvertFunctionInst, ConversionInst, convert_function, None, DoesNotRelease)
- INST(ThinFunctionToPointerInst, ConversionInst, thin_function_to_pointer, None, DoesNotRelease)
- INST(PointerToThinFunctionInst, ConversionInst, pointer_to_thin_function, None, DoesNotRelease)
- INST(RefToBridgeObjectInst, ConversionInst, ref_to_bridge_object, None, DoesNotRelease)
- INST(BridgeObjectToRefInst, ConversionInst, bridge_object_to_ref, None, DoesNotRelease)
- INST(BridgeObjectToWordInst, ConversionInst, bridge_object_to_word, None, DoesNotRelease)
- INST(ThinToThickFunctionInst, ConversionInst, thin_to_thick_function, None, DoesNotRelease)
- INST(ThickToObjCMetatypeInst, ConversionInst, thick_to_objc_metatype, None, DoesNotRelease)
- INST(ObjCToThickMetatypeInst, ConversionInst, objc_to_thick_metatype, None, DoesNotRelease)
- INST(ObjCMetatypeToObjectInst, ConversionInst, objc_metatype_to_object, None, DoesNotRelease)
- INST(ObjCExistentialMetatypeToObjectInst, ConversionInst, objc_existential_metatype_to_object, None,
- DoesNotRelease)
+ ABSTRACT_SINGLE_VALUE_INST(ConversionInst, SingleValueInstruction)
+ SINGLE_VALUE_INST(UpcastInst, upcast,
+ ConversionInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(AddressToPointerInst, address_to_pointer,
+ ConversionInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(PointerToAddressInst, pointer_to_address,
+ ConversionInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(UncheckedRefCastInst, unchecked_ref_cast,
+ ConversionInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(UncheckedAddrCastInst, unchecked_addr_cast,
+ ConversionInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(UncheckedTrivialBitCastInst, unchecked_trivial_bit_cast,
+ ConversionInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(UncheckedBitwiseCastInst, unchecked_bitwise_cast,
+ ConversionInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(RefToRawPointerInst, ref_to_raw_pointer,
+ ConversionInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(RawPointerToRefInst, raw_pointer_to_ref,
+ ConversionInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(RefToUnownedInst, ref_to_unowned,
+ ConversionInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(UnownedToRefInst, unowned_to_ref,
+ ConversionInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(RefToUnmanagedInst, ref_to_unmanaged,
+ ConversionInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(UnmanagedToRefInst, unmanaged_to_ref,
+ ConversionInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(ConvertFunctionInst, convert_function,
+ ConversionInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(ThinFunctionToPointerInst, thin_function_to_pointer,
+ ConversionInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(PointerToThinFunctionInst, pointer_to_thin_function,
+ ConversionInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(RefToBridgeObjectInst, ref_to_bridge_object,
+ ConversionInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(BridgeObjectToRefInst, bridge_object_to_ref,
+ ConversionInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(BridgeObjectToWordInst, bridge_object_to_word,
+ ConversionInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(ThinToThickFunctionInst, thin_to_thick_function,
+ ConversionInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(ThickToObjCMetatypeInst, thick_to_objc_metatype,
+ ConversionInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(ObjCToThickMetatypeInst, objc_to_thick_metatype,
+ ConversionInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(ObjCMetatypeToObjectInst, objc_metatype_to_object,
+ ConversionInst, None, DoesNotRelease)
+ SINGLE_VALUE_INST(ObjCExistentialMetatypeToObjectInst, objc_existential_metatype_to_object,
+ ConversionInst, None, DoesNotRelease)
// unconditional_checked_cast_value reads the source value and produces
// a new value with a potentially different representation.
- INST(UnconditionalCheckedCastValueInst, ConversionInst, unconditional_checked_cast_value, MayRead, MayRelease)
+ SINGLE_VALUE_INST(UnconditionalCheckedCastValueInst, unconditional_checked_cast_value,
+ ConversionInst, MayRead, MayRelease)
// unconditional_checked_cast_inst is only MayRead to prevent a subsequent
// release of the cast's source from being hoisted above the cast:
// retain X
@@ -299,41 +320,314 @@
// should never happen. Since unconditional_checked_cast is a
// scalar cast that doesn't affect the value's representation, its
// side effect can then be modeled as None.
- INST(UnconditionalCheckedCastInst, ConversionInst, unconditional_checked_cast, MayRead, DoesNotRelease)
- VALUE_RANGE(ConversionInst, UpcastInst, UnconditionalCheckedCastInst)
- INST(IsNonnullInst, SILInstruction, is_nonnull, None, DoesNotRelease)
- INST(UnconditionalCheckedCastAddrInst, SILInstruction, unconditional_checked_cast_addr, MayHaveSideEffects,
- MayRelease)
- INST(UncheckedRefCastAddrInst, SILInstruction, unchecked_ref_cast_addr, MayHaveSideEffects,
+ SINGLE_VALUE_INST(UnconditionalCheckedCastInst, unconditional_checked_cast,
+ ConversionInst, MayRead, DoesNotRelease)
+ SINGLE_VALUE_INST_RANGE(ConversionInst, UpcastInst, UnconditionalCheckedCastInst)
+
+ SINGLE_VALUE_INST(MarkDependenceInst, mark_dependence,
+ SingleValueInstruction, None, DoesNotRelease)
+ SINGLE_VALUE_INST(CopyBlockInst, copy_block,
+ SingleValueInstruction, MayHaveSideEffects, DoesNotRelease)
+ SINGLE_VALUE_INST(CopyValueInst, copy_value,
+ SingleValueInstruction, MayHaveSideEffects, DoesNotRelease)
+ SINGLE_VALUE_INST(CopyUnownedValueInst, copy_unowned_value,
+ SingleValueInstruction, MayHaveSideEffects, DoesNotRelease)
+ SINGLE_VALUE_INST(UncheckedOwnershipConversionInst, unchecked_ownership_conversion,
+ SingleValueInstruction, MayHaveSideEffects, MayRelease)
+ SINGLE_VALUE_INST(StrongPinInst, strong_pin,
+ SingleValueInstruction, MayHaveSideEffects, DoesNotRelease)
+
+ // IsUnique does not actually write to memory but should be modeled
+ // as such. Its operand is a pointer to an object reference. The
+ // optimizer should not assume that the same object is pointed to after
+ // the isUnique instruction. It appears to write a new object reference.
+ SINGLE_VALUE_INST(IsUniqueInst, is_unique,
+ SingleValueInstruction, MayHaveSideEffects, DoesNotRelease)
+ SINGLE_VALUE_INST(IsUniqueOrPinnedInst, is_unique_or_pinned,
+ SingleValueInstruction, MayHaveSideEffects, DoesNotRelease)
+
+ // Accessing memory
+ SINGLE_VALUE_INST(LoadInst, load,
+ SingleValueInstruction, MayRead, DoesNotRelease)
+ SINGLE_VALUE_INST(LoadBorrowInst, load_borrow,
+ SingleValueInstruction, MayRead, DoesNotRelease)
+ SINGLE_VALUE_INST(BeginBorrowInst, begin_borrow,
+ SingleValueInstruction, MayHaveSideEffects, DoesNotRelease)
+ SINGLE_VALUE_INST(StoreBorrowInst, store_borrow,
+ SILInstruction, MayWrite, DoesNotRelease)
+ SINGLE_VALUE_INST(BeginAccessInst, begin_access,
+ SingleValueInstruction, MayHaveSideEffects, DoesNotRelease)
+ SINGLE_VALUE_INST(LoadUnownedInst, load_unowned,
+ SingleValueInstruction, MayRead, DoesNotRelease)
+ SINGLE_VALUE_INST(LoadWeakInst, load_weak,
+ SingleValueInstruction, MayRead, DoesNotRelease)
+ SINGLE_VALUE_INST(MarkUninitializedInst, mark_uninitialized,
+ SingleValueInstruction, None, DoesNotRelease)
+ SINGLE_VALUE_INST(MarkUninitializedBehaviorInst, mark_uninitialized_behavior,
+ SingleValueInstruction, None, DoesNotRelease)
+ SINGLE_VALUE_INST(ProjectValueBufferInst, project_value_buffer,
+ SingleValueInstruction, MayRead, DoesNotRelease)
+ SINGLE_VALUE_INST(ProjectBoxInst, project_box,
+ SingleValueInstruction, None, DoesNotRelease)
+ SINGLE_VALUE_INST(ProjectExistentialBoxInst, project_existential_box,
+ SingleValueInstruction, None, DoesNotRelease)
+
+ // Function Application
+ SINGLE_VALUE_INST(ApplyInst, apply,
+ SingleValueInstruction, MayHaveSideEffects, MayRelease)
+ SINGLE_VALUE_INST(BuiltinInst, builtin,
+ SingleValueInstruction, MayHaveSideEffects, MayRelease)
+ SINGLE_VALUE_INST(PartialApplyInst, partial_apply,
+ SingleValueInstruction, MayHaveSideEffects, DoesNotRelease)
+
+ // Metatypes
+ SINGLE_VALUE_INST(MetatypeInst, metatype,
+ SingleValueInstruction, None, DoesNotRelease)
+ SINGLE_VALUE_INST(ValueMetatypeInst, value_metatype,
+ SingleValueInstruction, MayRead, DoesNotRelease)
+ SINGLE_VALUE_INST(ExistentialMetatypeInst, existential_metatype,
+ SingleValueInstruction, MayRead, DoesNotRelease)
+ SINGLE_VALUE_INST(ObjCProtocolInst, objc_protocol,
+ SingleValueInstruction, None, DoesNotRelease)
+
+ // Aggregate Types
+ SINGLE_VALUE_INST(ObjectInst, object,
+ SingleValueInstruction, None, DoesNotRelease)
+ SINGLE_VALUE_INST(TupleInst, tuple,
+ SingleValueInstruction, None, DoesNotRelease)
+ SINGLE_VALUE_INST(TupleExtractInst, tuple_extract,
+ SingleValueInstruction, None, DoesNotRelease)
+ SINGLE_VALUE_INST(TupleElementAddrInst, tuple_element_addr,
+ SingleValueInstruction, None, DoesNotRelease)
+ SINGLE_VALUE_INST(StructInst, struct,
+ SingleValueInstruction, None, DoesNotRelease)
+ SINGLE_VALUE_INST(StructExtractInst, struct_extract,
+ SingleValueInstruction, None, DoesNotRelease)
+ SINGLE_VALUE_INST(StructElementAddrInst, struct_element_addr,
+ SingleValueInstruction, None, DoesNotRelease)
+ SINGLE_VALUE_INST(RefElementAddrInst, ref_element_addr,
+ SingleValueInstruction, None, DoesNotRelease)
+ SINGLE_VALUE_INST(RefTailAddrInst, ref_tail_addr,
+ SingleValueInstruction, None, DoesNotRelease)
+
+ // Enums
+ SINGLE_VALUE_INST(EnumInst, enum,
+ SingleValueInstruction, None, DoesNotRelease)
+ SINGLE_VALUE_INST(UncheckedEnumDataInst, unchecked_enum_data,
+ SingleValueInstruction, None, DoesNotRelease)
+ SINGLE_VALUE_INST(InitEnumDataAddrInst, init_enum_data_addr,
+ SingleValueInstruction, None, DoesNotRelease)
+ SINGLE_VALUE_INST(UncheckedTakeEnumDataAddrInst, unchecked_take_enum_data_addr,
+ SingleValueInstruction, MayWrite, DoesNotRelease)
+ SINGLE_VALUE_INST(SelectEnumInst, select_enum,
+ SingleValueInstruction, None, DoesNotRelease)
+ SINGLE_VALUE_INST(SelectEnumAddrInst, select_enum_addr,
+ SingleValueInstruction, MayRead, DoesNotRelease)
+ SINGLE_VALUE_INST(SelectValueInst, select_value,
+ SingleValueInstruction, None, DoesNotRelease)
+
+ // Protocol and Protocol Composition Types
+ SINGLE_VALUE_INST(InitExistentialAddrInst, init_existential_addr,
+ SingleValueInstruction, MayWrite, DoesNotRelease)
+ SINGLE_VALUE_INST(InitExistentialValueInst, init_existential_value,
+ SingleValueInstruction, MayWrite, DoesNotRelease)
+ SINGLE_VALUE_INST(OpenExistentialAddrInst, open_existential_addr,
+ SingleValueInstruction, MayRead, DoesNotRelease)
+ SINGLE_VALUE_INST(InitExistentialRefInst, init_existential_ref,
+ SingleValueInstruction, None, DoesNotRelease)
+ SINGLE_VALUE_INST(OpenExistentialRefInst, open_existential_ref,
+ SingleValueInstruction, None, DoesNotRelease)
+ SINGLE_VALUE_INST(InitExistentialMetatypeInst, init_existential_metatype,
+ SingleValueInstruction, None, DoesNotRelease)
+ SINGLE_VALUE_INST(OpenExistentialMetatypeInst, open_existential_metatype,
+ SingleValueInstruction, None, DoesNotRelease)
+ SINGLE_VALUE_INST(OpenExistentialBoxInst, open_existential_box,
+ SingleValueInstruction, MayRead, DoesNotRelease)
+ SINGLE_VALUE_INST(OpenExistentialValueInst, open_existential_value,
+ SingleValueInstruction, MayRead, DoesNotRelease)
+ SINGLE_VALUE_INST(OpenExistentialBoxValueInst, open_existential_box_value,
+ SingleValueInstruction, MayRead, DoesNotRelease)
+
+ // Blocks
+ SINGLE_VALUE_INST(ProjectBlockStorageInst, project_block_storage,
+ SingleValueInstruction, None, DoesNotRelease)
+ SINGLE_VALUE_INST(InitBlockStorageHeaderInst, init_block_storage_header,
+ SingleValueInstruction, None, DoesNotRelease)
+
+ // Key paths
+ // TODO: The only "side effect" is potentially retaining the returned key path
+ // object; is there a more specific effect?
+ SINGLE_VALUE_INST(KeyPathInst, keypath,
+ SingleValueInstruction, MayHaveSideEffects, DoesNotRelease)
+
+ SINGLE_VALUE_INST(IsNonnullInst, is_nonnull,
+ SingleValueInstruction, None, DoesNotRelease)
+
+ SINGLE_VALUE_INST_RANGE(SingleValueInstruction, AllocStackInst, IsNonnullInst)
+
+NODE_RANGE(ValueBase, SILPHIArgument, IsNonnullInst)
+
+// Terminators
+ABSTRACT_INST(TermInst, SILInstruction)
+ TERMINATOR(UnreachableInst, unreachable,
+ TermInst, None, DoesNotRelease)
+ TERMINATOR(ReturnInst, return,
+ TermInst, None, DoesNotRelease)
+ TERMINATOR(ThrowInst, throw,
+ TermInst, None, DoesNotRelease)
+ TERMINATOR(TryApplyInst, try_apply,
+ TermInst, MayHaveSideEffects, MayRelease)
+ TERMINATOR(BranchInst, br,
+ TermInst, None, DoesNotRelease)
+ TERMINATOR(CondBranchInst, cond_br,
+ TermInst, None, DoesNotRelease)
+ TERMINATOR(SwitchValueInst, switch_value,
+ TermInst, None, DoesNotRelease)
+ TERMINATOR(SwitchEnumInst, switch_enum,
+ TermInst, None, DoesNotRelease)
+ TERMINATOR(SwitchEnumAddrInst, switch_enum_addr,
+ TermInst, MayRead, DoesNotRelease)
+ TERMINATOR(DynamicMethodBranchInst, dynamic_method_br,
+ TermInst, None, DoesNotRelease)
+ TERMINATOR(CheckedCastBranchInst, checked_cast_br,
+ TermInst, None, DoesNotRelease)
+ TERMINATOR(CheckedCastAddrBranchInst, checked_cast_addr_br,
+ TermInst, MayHaveSideEffects, MayRelease)
+ TERMINATOR(CheckedCastValueBranchInst, checked_cast_value_br,
+ TermInst, None, DoesNotRelease)
+ INST_RANGE(TermInst, UnreachableInst, CheckedCastValueBranchInst)
+
+// Deallocation instructions.
+ABSTRACT_INST(DeallocationInst, SILInstruction)
+ NON_VALUE_INST(DeallocStackInst, dealloc_stack,
+ DeallocationInst, MayHaveSideEffects, DoesNotRelease)
+ NON_VALUE_INST(DeallocRefInst, dealloc_ref,
+ DeallocationInst, MayHaveSideEffects, DoesNotRelease)
+ NON_VALUE_INST(DeallocPartialRefInst, dealloc_partial_ref,
+ DeallocationInst, MayHaveSideEffects, DoesNotRelease)
+ NON_VALUE_INST(DeallocValueBufferInst, dealloc_value_buffer,
+ DeallocationInst, MayHaveSideEffects, DoesNotRelease)
+ NON_VALUE_INST(DeallocBoxInst, dealloc_box,
+ DeallocationInst, MayHaveSideEffects, DoesNotRelease)
+ NON_VALUE_INST(DeallocExistentialBoxInst, dealloc_existential_box,
+ DeallocationInst, MayHaveSideEffects, DoesNotRelease)
+ INST_RANGE(DeallocationInst, DeallocStackInst, DeallocExistentialBoxInst)
+
+// Reference Counting
+ABSTRACT_INST(RefCountingInst, SILInstruction)
+ NON_VALUE_INST(StrongRetainInst, strong_retain,
+ RefCountingInst, MayHaveSideEffects, DoesNotRelease)
+ NON_VALUE_INST(StrongReleaseInst, strong_release,
+ RefCountingInst, MayHaveSideEffects, MayRelease)
+ NON_VALUE_INST(StrongRetainUnownedInst, strong_retain_unowned,
+ RefCountingInst, MayHaveSideEffects,
DoesNotRelease)
+ NON_VALUE_INST(StrongUnpinInst, strong_unpin,
+ RefCountingInst, MayHaveSideEffects, DoesNotRelease)
+ NON_VALUE_INST(UnownedRetainInst, unowned_retain,
+ RefCountingInst, MayHaveSideEffects, DoesNotRelease)
+ NON_VALUE_INST(UnownedReleaseInst, unowned_release,
+ RefCountingInst, MayHaveSideEffects,
+ MayRelease)
+ NON_VALUE_INST(UnmanagedRetainValueInst, unmanaged_retain_value,
+ RefCountingInst, MayHaveSideEffects, DoesNotRelease)
+ NON_VALUE_INST(UnmanagedReleaseValueInst, unmanaged_release_value,
+ RefCountingInst, MayHaveSideEffects, MayRelease)
+ NON_VALUE_INST(UnmanagedAutoreleaseValueInst, unmanaged_autorelease_value,
+ RefCountingInst, MayHaveSideEffects, DoesNotRelease)
+ NON_VALUE_INST(RetainValueInst, retain_value,
+ RefCountingInst, MayHaveSideEffects, DoesNotRelease)
+ NON_VALUE_INST(RetainValueAddrInst, retain_value_addr,
+ RefCountingInst, MayHaveSideEffects, DoesNotRelease)
+ NON_VALUE_INST(ReleaseValueInst, release_value,
+ RefCountingInst, MayHaveSideEffects, MayRelease)
+ NON_VALUE_INST(ReleaseValueAddrInst, release_value_addr,
+ RefCountingInst, MayHaveSideEffects, MayRelease)
+ NON_VALUE_INST(SetDeallocatingInst, set_deallocating,
+ RefCountingInst, MayHaveSideEffects,
+ DoesNotRelease)
+ NON_VALUE_INST(AutoreleaseValueInst, autorelease_value,
+ RefCountingInst, MayHaveSideEffects,
+ DoesNotRelease)
+ INST_RANGE(RefCountingInst, StrongRetainInst, AutoreleaseValueInst)
- // Runtime failure
- // FIXME: Special MemBehavior for runtime failure?
- INST(CondFailInst, SILInstruction, cond_fail, MayHaveSideEffects, DoesNotRelease)
+// BindMemory has no physical side effect. Semantically it writes to
+// its affected memory region because any reads or writes accessing
+// that memory must be dependent on the bind operation.
+NON_VALUE_INST(BindMemoryInst, bind_memory,
+ SILInstruction, MayWrite, DoesNotRelease)
- // Terminators
- ABSTRACT_VALUE(TermInst, SILInstruction)
- TERMINATOR(UnreachableInst, TermInst, unreachable, None, DoesNotRelease)
- TERMINATOR(ReturnInst, TermInst, return, None, DoesNotRelease)
- TERMINATOR(ThrowInst, TermInst, throw, None, DoesNotRelease)
- TERMINATOR(TryApplyInst, TermInst, try_apply, MayHaveSideEffects, MayRelease)
- TERMINATOR(BranchInst, TermInst, br, None, DoesNotRelease)
- TERMINATOR(CondBranchInst, TermInst, cond_br, None, DoesNotRelease)
- TERMINATOR(SwitchValueInst, TermInst, switch_value, None, DoesNotRelease)
- TERMINATOR(SwitchEnumInst, TermInst, switch_enum, None, DoesNotRelease)
- TERMINATOR(SwitchEnumAddrInst, TermInst, switch_enum_addr, MayRead, DoesNotRelease)
- TERMINATOR(DynamicMethodBranchInst, TermInst, dynamic_method_br, None, DoesNotRelease)
- TERMINATOR(CheckedCastBranchInst, TermInst, checked_cast_br, None, DoesNotRelease)
- TERMINATOR(CheckedCastAddrBranchInst, TermInst, checked_cast_addr_br, MayHaveSideEffects,
- MayRelease)
- TERMINATOR(CheckedCastValueBranchInst, TermInst, checked_cast_value_br, None, DoesNotRelease)
- VALUE_RANGE(TermInst, UnreachableInst, CheckedCastValueBranchInst)
+// FIXME: Is MayHaveSideEffects appropriate?
+NON_VALUE_INST(FixLifetimeInst, fix_lifetime,
+ SILInstruction, MayHaveSideEffects, DoesNotRelease)
- VALUE_RANGE(SILInstruction, AllocStackInst, CheckedCastValueBranchInst)
+NON_VALUE_INST(DestroyValueInst, destroy_value,
+ SILInstruction, MayHaveSideEffects, MayRelease)
+NON_VALUE_INST(EndBorrowInst, end_borrow,
+ SILInstruction, MayHaveSideEffects, DoesNotRelease)
+NON_VALUE_INST(EndBorrowArgumentInst, end_borrow_argument,
+ SILInstruction, MayHaveSideEffects, DoesNotRelease)
+NON_VALUE_INST(EndAccessInst, end_access,
+ SILInstruction, MayHaveSideEffects, DoesNotRelease)
+NON_VALUE_INST(BeginUnpairedAccessInst, begin_unpaired_access,
+ SILInstruction, MayHaveSideEffects, DoesNotRelease)
+NON_VALUE_INST(EndUnpairedAccessInst, end_unpaired_access,
+ SILInstruction, MayHaveSideEffects, DoesNotRelease)
+NON_VALUE_INST(StoreInst, store,
+ SILInstruction, MayWrite, DoesNotRelease)
+NON_VALUE_INST(AssignInst, assign,
+ SILInstruction, MayWrite, DoesNotRelease)
+NON_VALUE_INST(MarkFunctionEscapeInst, mark_function_escape,
+ SILInstruction, None, DoesNotRelease)
+NON_VALUE_INST(DebugValueInst, debug_value,
+ SILInstruction, None, DoesNotRelease)
+NON_VALUE_INST(DebugValueAddrInst, debug_value_addr,
+ SILInstruction, None, DoesNotRelease)
+NON_VALUE_INST(StoreUnownedInst, store_unowned,
+ SILInstruction, MayWrite, DoesNotRelease)
+NON_VALUE_INST(StoreWeakInst, store_weak,
+ SILInstruction, MayWrite, DoesNotRelease)
+NON_VALUE_INST(CopyAddrInst, copy_addr,
+ SILInstruction, MayHaveSideEffects, MayRelease)
+NON_VALUE_INST(DestroyAddrInst, destroy_addr,
+ SILInstruction, MayHaveSideEffects, MayRelease)
+NON_VALUE_INST(EndLifetimeInst, end_lifetime,
+ SILInstruction, MayHaveSideEffects, MayRelease)
+NON_VALUE_INST(InjectEnumAddrInst, inject_enum_addr,
+ SILInstruction, MayWrite, DoesNotRelease)
+NON_VALUE_INST(DeinitExistentialAddrInst, deinit_existential_addr,
+ SILInstruction, MayHaveSideEffects, DoesNotRelease)
+NON_VALUE_INST(DeinitExistentialValueInst, deinit_existential_value,
+ SILInstruction, MayHaveSideEffects, DoesNotRelease)
+NON_VALUE_INST(UnconditionalCheckedCastAddrInst, unconditional_checked_cast_addr,
+ SILInstruction, MayHaveSideEffects, MayRelease)
+NON_VALUE_INST(UncheckedRefCastAddrInst, unchecked_ref_cast_addr,
+ SILInstruction, MayHaveSideEffects, DoesNotRelease)
+NON_VALUE_INST(AllocGlobalInst, alloc_global,
+ SILInstruction, MayHaveSideEffects, DoesNotRelease)
+// Runtime failure
+// FIXME: Special MemBehavior for runtime failure?
+NON_VALUE_INST(CondFailInst, cond_fail,
+ SILInstruction, MayHaveSideEffects, DoesNotRelease)
+
+NODE_RANGE(SILInstruction, AllocStackInst, CondFailInst)
+NODE_RANGE(SILNode, SILPHIArgument, CondFailInst)
+
+#undef SINGLE_VALUE_INST_RANGE
+#undef INST_RANGE
#undef VALUE_RANGE
+#undef NODE_RANGE
+#undef ABSTRACT_SINGLE_VALUE_INST
+#undef ABSTRACT_INST
#undef ABSTRACT_VALUE
+#undef ABSTRACT_NODE
+#undef ABSTRACT_VALUE_AND_INST
#undef TERMINATOR
+#undef NON_VALUE_INST
+#undef SINGLE_VALUE_INST
+#undef FULL_INST
#undef INST
#undef ARGUMENT
#undef VALUE
+#undef NODE
diff --git a/include/swift/SIL/SILOpenedArchetypesTracker.h b/include/swift/SIL/SILOpenedArchetypesTracker.h
index f8046fd..508eb36 100644
--- a/include/swift/SIL/SILOpenedArchetypesTracker.h
+++ b/include/swift/SIL/SILOpenedArchetypesTracker.h
@@ -31,7 +31,8 @@
/// The intended clients of this class are SILGen, SIL deserializers, etc.
class SILOpenedArchetypesTracker : public DeleteNotificationHandler {
public:
- typedef llvm::DenseMap<ArchetypeType *, SILValue> OpenedArchetypeDefsMap;
+ using OpenedArchetypeDefsMap =
+ llvm::DenseMap<ArchetypeType*, SingleValueInstruction*>;
SILOpenedArchetypesTracker(SILOpenedArchetypesTracker &Tracker)
: SILOpenedArchetypesTracker(Tracker.F, Tracker) {}
@@ -57,19 +58,13 @@
}
// Register a definition of a given opened archetype.
- void addOpenedArchetypeDef(CanArchetypeType archetype, SILValue Def);
+ void addOpenedArchetypeDef(CanArchetypeType archetype,
+ SingleValueInstruction *def);
- void removeOpenedArchetypeDef(CanArchetypeType archetype, SILValue Def) {
- auto FoundDef = getOpenedArchetypeDef(archetype);
- assert(FoundDef &&
- "Opened archetype definition is not registered in SILFunction");
- if (FoundDef == Def)
- OpenedArchetypeDefs.erase(archetype);
- }
-
- // Return the SILValue defining a given archetype.
- // If the defining value is not known, return an empty SILValue.
- SILValue getOpenedArchetypeDef(CanArchetypeType archetype) const {
+ // Return the SILInstruciton* defining a given archetype.
+ // If the defining value is not known, return a null instruction.
+ SingleValueInstruction *
+ getOpenedArchetypeDef(CanArchetypeType archetype) const {
return OpenedArchetypeDefs.lookup(archetype);
}
@@ -107,7 +102,7 @@
bool needsNotifications() { return true; }
// Handle notifications about removals of instructions.
- void handleDeleteNotification(swift::ValueBase *Value);
+ void handleDeleteNotification(SILNode *node);
// Dump the contents.
void dump() const;
diff --git a/include/swift/SIL/SILPrintContext.h b/include/swift/SIL/SILPrintContext.h
index 69ff784..1ac3c3e 100644
--- a/include/swift/SIL/SILPrintContext.h
+++ b/include/swift/SIL/SILPrintContext.h
@@ -50,7 +50,7 @@
//
const void *ContextFunctionOrBlock = nullptr;
llvm::DenseMap<const SILBasicBlock *, unsigned> BlocksToIDMap;
- llvm::DenseMap<const ValueBase *, unsigned> ValueToIDMap;
+ llvm::DenseMap<const SILNode *, unsigned> ValueToIDMap;
llvm::raw_ostream &OutStream;
@@ -96,7 +96,7 @@
SILPrintContext::ID getID(const SILBasicBlock *Block);
- SILPrintContext::ID getID(SILValue V);
+ SILPrintContext::ID getID(const SILNode *node);
/// Returns true if the \p Scope has and ID assigned.
bool hasScopeID(const SILDebugScope *Scope) const {
diff --git a/include/swift/SIL/SILSuccessor.h b/include/swift/SIL/SILSuccessor.h
index 2f63aa9..6ed9390 100644
--- a/include/swift/SIL/SILSuccessor.h
+++ b/include/swift/SIL/SILSuccessor.h
@@ -13,6 +13,7 @@
#ifndef SWIFT_SIL_SILSUCCESSOR_H
#define SWIFT_SIL_SILSUCCESSOR_H
+#include "swift/Basic/ProfileCounter.h"
#include <cassert>
#include <cstddef>
#include <iterator>
@@ -40,6 +41,9 @@
/// If non-null, this is the BasicBlock that the terminator branches to.
SILBasicBlock *SuccessorBlock = nullptr;
+ /// If hasValue, this is the profiled execution count of the edge
+ ProfileCounter Count;
+
/// A pointer to the SILSuccessor that represents the previous SILSuccessor in the
/// predecessor list for SuccessorBlock.
///
@@ -53,14 +57,14 @@
SILSuccessor *Next = nullptr;
public:
- SILSuccessor() {}
+ SILSuccessor(ProfileCounter Count = ProfileCounter()) : Count(Count) {}
- SILSuccessor(TermInst *CI)
- : ContainingInst(CI) {
- }
+ SILSuccessor(TermInst *CI, ProfileCounter Count = ProfileCounter())
+ : ContainingInst(CI), Count(Count) {}
- SILSuccessor(TermInst *CI, SILBasicBlock *Succ)
- : ContainingInst(CI) {
+ SILSuccessor(TermInst *CI, SILBasicBlock *Succ,
+ ProfileCounter Count = ProfileCounter())
+ : ContainingInst(CI), Count(Count) {
*this = Succ;
}
@@ -72,7 +76,9 @@
operator SILBasicBlock*() const { return SuccessorBlock; }
SILBasicBlock *getBB() const { return SuccessorBlock; }
-
+
+ ProfileCounter getCount() const { return Count; }
+
// Do not copy or move these.
SILSuccessor(const SILSuccessor &) = delete;
SILSuccessor(SILSuccessor &&) = delete;
diff --git a/include/swift/SIL/SILUndef.h b/include/swift/SIL/SILUndef.h
index a62fe12..b1bd8c5 100644
--- a/include/swift/SIL/SILUndef.h
+++ b/include/swift/SIL/SILUndef.h
@@ -17,7 +17,9 @@
#include "swift/SIL/SILValue.h"
namespace swift {
- class SILModule;
+class SILArgument;
+class SILInstruction;
+class SILModule;
class SILUndef : public ValueBase {
void operator=(const SILArgument &) = delete;
@@ -32,8 +34,10 @@
template<class OwnerTy>
static SILUndef *getSentinelValue(SILType Ty, OwnerTy Owner) { return new (*Owner) SILUndef(Ty); }
- static bool classof(const ValueBase *V) {
- return V->getKind() == ValueKind::SILUndef;
+ static bool classof(const SILArgument *) = delete;
+ static bool classof(const SILInstruction *) = delete;
+ static bool classof(const SILNode *node) {
+ return node->getKind() == SILNodeKind::SILUndef;
}
};
diff --git a/include/swift/SIL/SILValue.h b/include/swift/SIL/SILValue.h
index 4de46f2..ce81ab5 100644
--- a/include/swift/SIL/SILValue.h
+++ b/include/swift/SIL/SILValue.h
@@ -18,6 +18,7 @@
#define SWIFT_SIL_SILVALUE_H
#include "swift/Basic/Range.h"
+#include "swift/SIL/SILNode.h"
#include "swift/SIL/SILType.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Hashing.h"
@@ -31,19 +32,20 @@
class PostOrderFunctionInfo;
class ReversePostOrderInfo;
class Operand;
-class SILBasicBlock;
-class SILFunction;
class SILInstruction;
class SILLocation;
-class SILModule;
class DeadEndBlocks;
class ValueBaseUseIterator;
class ValueUseIterator;
-enum class ValueKind {
-#define VALUE(Id, Parent) Id,
-#define VALUE_RANGE(Id, FirstId, LastId) \
- First_##Id = FirstId, Last_##Id = LastId,
+/// An enumeration which contains values for all the concrete ValueBase
+/// subclasses.
+enum class ValueKind : std::underlying_type<SILNodeKind>::type {
+#define VALUE(ID, PARENT) \
+ ID = unsigned(SILNodeKind::ID),
+#define VALUE_RANGE(ID, FIRST, LAST) \
+ First_##ID = unsigned(SILNodeKind::First_##ID), \
+ Last_##ID = unsigned(SILNodeKind::Last_##ID),
#include "swift/SIL/SILNodes.def"
};
@@ -132,31 +134,26 @@
/// This is the base class of the SIL value hierarchy, which represents a
/// runtime computed value. Things like SILInstruction derive from this.
-class alignas(8) ValueBase : public SILAllocated<ValueBase> {
+class ValueBase : public SILNode, public SILAllocated<ValueBase> {
SILType Type;
Operand *FirstUse = nullptr;
friend class Operand;
- const ValueKind Kind;
-
ValueBase(const ValueBase &) = delete;
ValueBase &operator=(const ValueBase &) = delete;
protected:
- ValueBase(ValueKind Kind, SILType Ty)
- : Type(Ty), Kind(Kind) {}
+ ValueBase(ValueKind kind, SILType type)
+ : SILNode(SILNodeKind(kind), SILNodeStorageLocation::Value),
+ Type(type) {}
public:
~ValueBase() {
assert(use_empty() && "Cannot destroy a value that still has uses!");
}
-
- ValueKind getKind() const { return Kind; }
-
- /// True if the "value" is actually a value that can be used by other
- /// instructions.
- bool hasValue() const { return !Type.isNull(); }
+ LLVM_ATTRIBUTE_ALWAYS_INLINE
+ ValueKind getKind() const { return ValueKind(SILNode::getKind()); }
SILType getType() const {
return Type;
@@ -173,6 +170,9 @@
/// same type as the result of this instruction.
void replaceAllUsesWithUndef();
+ /// Is this value a direct result of the given instruction?
+ bool isResultOf(SILInstruction *I) const;
+
/// Returns true if this value has no uses.
/// To ignore debug-info instructions use swift::onlyHaveDebugUses instead
/// (see comment in DebugUtils.h).
@@ -201,37 +201,32 @@
template <class T>
inline T *getSingleUserOfType();
- /// Pretty-print the value.
- void dump() const;
- void print(raw_ostream &OS) const;
+ /// Return the instruction that defines this value, or null if it is
+ /// not defined by an instruction.
+ const SILInstruction *getDefiningInstruction() const {
+ return const_cast<ValueBase*>(this)->getDefiningInstruction();
+ }
+ SILInstruction *getDefiningInstruction();
- /// Pretty-print the value in context, preceded by its operands (if the
- /// value represents the result of an instruction) and followed by its
- /// users.
- void dumpInContext() const;
- void printInContext(raw_ostream &OS) const;
+ struct DefiningInstructionResult {
+ SILInstruction *Instruction;
+ size_t ResultIndex;
+ };
+ /// Return the instruction that defines this value and the appropriate
+ /// result index, or None if it is not defined by an instruction.
+ Optional<DefiningInstructionResult> getDefiningInstructionResult();
+
+ static bool classof(const SILNode *N) {
+ return N->getKind() >= SILNodeKind::First_ValueBase &&
+ N->getKind() <= SILNodeKind::Last_ValueBase;
+ }
static bool classof(const ValueBase *V) { return true; }
- /// If this is a SILArgument or a SILInstruction get its parent basic block,
- /// otherwise return null.
- SILBasicBlock *getParentBlock() const;
-
- /// If this is a SILArgument or a SILInstruction get its parent function,
- /// otherwise return null.
- SILFunction *getFunction() const;
-
- /// If this is a SILArgument or a SILInstruction get its parent module,
- /// otherwise return null.
- SILModule *getModule() const;
+ /// This is supportable but usually suggests a logic mistake.
+ static bool classof(const SILInstruction *) = delete;
};
-inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
- const ValueBase &V) {
- V.print(OS);
- return OS;
-}
-
} // end namespace swift
namespace llvm {
@@ -783,12 +778,6 @@
return OS;
}
-/// Map a SILValue mnemonic name to its ValueKind.
-ValueKind getSILValueKind(StringRef Name);
-
-/// Map ValueKind to a corresponding mnemonic name.
-StringRef getSILValueName(ValueKind Kind);
-
} // end namespace swift
diff --git a/include/swift/SIL/SILVisitor.h b/include/swift/SIL/SILVisitor.h
index 439553c..86554bb 100644
--- a/include/swift/SIL/SILVisitor.h
+++ b/include/swift/SIL/SILVisitor.h
@@ -24,80 +24,136 @@
namespace swift {
-/// SILVisitor - This is a simple visitor class for Swift SIL nodes, allowing
-/// clients to walk over entire SIL functions, blocks, or instructions.
-template<typename ImplClass, typename ValueRetTy = void>
-class SILVisitor {
+/// A helper class for all the SIL visitors.
+/// You probably shouldn't use this directly.
+template <typename ImplClass, typename RetTy = void, typename... ArgTys>
+class SILVisitorBase {
public:
ImplClass &asImpl() { return static_cast<ImplClass &>(*this); }
- // Perform any required pre-processing before visiting.
- // Sub-classes can override it to provide their custom
- // pre-processing steps.
- void beforeVisit(ValueBase *V) {
+ void visitSILBasicBlock(SILBasicBlock *BB, ArgTys... args) {
+ asImpl().visitBasicBlockArguments(BB, args...);
+
+ for (auto &I : *BB)
+ asImpl().visit(&I, args...);
+ }
+ void visitSILBasicBlock(SILBasicBlock &BB, ArgTys... args) {
+ asImpl().visitSILBasicBlock(&BB, args...);
}
- ValueRetTy visit(ValueBase *V) {
- asImpl().beforeVisit(V);
+ void visitSILFunction(SILFunction *F, ArgTys... args) {
+ for (auto &BB : *F)
+ asImpl().visitSILBasicBlock(&BB, args...);
+ }
+ void visitSILFunction(SILFunction &F, ArgTys... args) {
+ asImpl().visitSILFunction(&F, args...);
+ }
+};
+/// SILValueVisitor - This is a simple visitor class for Swift SIL nodes,
+/// allowing clients to walk over entire SIL functions, blocks, or instructions.
+template <typename ImplClass, typename RetTy = void, typename... ArgTys>
+class SILValueVisitor
+ : public SILVisitorBase<ImplClass, RetTy, ArgTys...> {
+ using super = SILVisitorBase<ImplClass, RetTy, ArgTys...>;
+public:
+ using super::asImpl;
+
+ RetTy visit(ValueBase *V, ArgTys... args) {
switch (V->getKind()) {
#define VALUE(CLASS, PARENT) \
case ValueKind::CLASS: \
- return asImpl().visit##CLASS(static_cast<CLASS*>(V));
+ return asImpl().visit##CLASS(static_cast<CLASS*>(V), \
+ std::forward<ArgTys>(args)...);
#include "swift/SIL/SILNodes.def"
}
llvm_unreachable("Not reachable, all cases handled");
}
// Define default dispatcher implementations chain to parent nodes.
-#define VALUE(CLASS, PARENT) \
- ValueRetTy visit##CLASS(CLASS *I) { \
- return asImpl().visit##PARENT(I); \
+#define VALUE(CLASS, PARENT) \
+ RetTy visit##CLASS(CLASS *I, ArgTys... args) { \
+ return asImpl().visit##PARENT(I, std::forward<ArgTys>(args)...); \
}
#define ABSTRACT_VALUE(CLASS, PARENT) VALUE(CLASS, PARENT)
#include "swift/SIL/SILNodes.def"
-
- void visitSILBasicBlock(SILBasicBlock *BB) {
- asImpl().visitBasicBlockArguments(BB);
-
- for (auto &I : *BB)
- asImpl().visit(&I);
- }
- void visitSILBasicBlock(SILBasicBlock &BB) {
- asImpl().visitSILBasicBlock(&BB);
- }
-
- void visitBasicBlockArguments(SILBasicBlock *BB) {
- for (auto argI = BB->args_begin(), argEnd = BB->args_end(); argI != argEnd;
- ++argI)
- asImpl().visit(*argI);
- }
-
- void visitSILFunction(SILFunction *F) {
- for (auto &BB : *F)
- asImpl().visitSILBasicBlock(&BB);
- }
- void visitSILFunction(SILFunction &F) {
- asImpl().visitSILFunction(&F);
- }
};
-/// A simple convenience class for a visitor that should only visit
-/// SIL instructions.
-template<typename ImplClass, typename ValueRetTy = void>
-class SILInstructionVisitor : public SILVisitor<ImplClass, ValueRetTy> {
+/// A visitor that should only visit SIL instructions.
+template <typename ImplClass, typename RetTy = void, typename... ArgTys>
+class SILInstructionVisitor
+ : public SILVisitorBase<ImplClass, RetTy, ArgTys...> {
+ using super = SILVisitorBase<ImplClass, RetTy, ArgTys...>;
public:
- void visitBasicBlockArguments(SILBasicBlock *BB) {}
+ using super::asImpl;
- ValueRetTy visitSILArgument(SILArgument *A) {
- llvm_unreachable("should only be visiting instructions");
- }
- ValueRetTy visitSILUndef(SILUndef *U) {
- llvm_unreachable("should only be visiting instructions");
+ // Perform any required pre-processing before visiting.
+ // Sub-classes can override it to provide their custom
+ // pre-processing steps.
+ void beforeVisit(SILInstruction *inst) {}
+
+ RetTy visit(SILInstruction *inst, ArgTys... args) {
+ asImpl().beforeVisit(inst, args...);
+
+ switch (inst->getKind()) {
+#define INST(CLASS, PARENT) \
+ case SILInstructionKind::CLASS: \
+ return asImpl().visit##CLASS(static_cast<CLASS*>(inst), \
+ std::forward<ArgTys>(args)...);
+#include "swift/SIL/SILNodes.def"
+ }
+ llvm_unreachable("Not reachable, all cases handled");
}
- ValueRetTy visit(SILInstruction *I) {
- return SILVisitor<ImplClass, ValueRetTy>::visit(I);
+ // Define default dispatcher implementations chain to parent nodes.
+#define INST(CLASS, PARENT) \
+ RetTy visit##CLASS(CLASS *inst, ArgTys... args) { \
+ return asImpl().visit##PARENT(inst, std::forward<ArgTys>(args)...); \
+ }
+#define ABSTRACT_INST(CLASS, PARENT) INST(CLASS, PARENT)
+#include "swift/SIL/SILNodes.def"
+
+ void visitBasicBlockArguments(SILBasicBlock *BB, ArgTys... args) {}
+};
+
+/// A visitor that should visit all SIL nodes.
+template <typename ImplClass, typename RetTy = void, typename... ArgTys>
+class SILNodeVisitor
+ : public SILVisitorBase<ImplClass, RetTy, ArgTys...> {
+ using super = SILVisitorBase<ImplClass, RetTy, ArgTys...>;
+public:
+ using super::asImpl;
+
+ // Perform any required pre-processing before visiting.
+ // Sub-classes can override it to provide their custom
+ // pre-processing steps.
+ void beforeVisit(SILNode *I, ArgTys... args) {}
+
+ RetTy visit(SILNode *node, ArgTys... args) {
+ asImpl().beforeVisit(node, args...);
+
+ switch (node->getKind()) {
+#define NODE(CLASS, PARENT) \
+ case SILNodeKind::CLASS: \
+ return asImpl().visit##CLASS(cast<CLASS>(node), \
+ std::forward<ArgTys>(args)...);
+#include "swift/SIL/SILNodes.def"
+ }
+ llvm_unreachable("Not reachable, all cases handled");
+ }
+
+ // Define default dispatcher implementations chain to parent nodes.
+#define NODE(CLASS, PARENT) \
+ RetTy visit##CLASS(CLASS *node, ArgTys... args) { \
+ return asImpl().visit##PARENT(node, std::forward<ArgTys>(args)...); \
+ }
+#define ABSTRACT_NODE(CLASS, PARENT) NODE(CLASS, PARENT)
+#include "swift/SIL/SILNodes.def"
+
+ void visitBasicBlockArguments(SILBasicBlock *BB, ArgTys... args) {
+ for (auto argI = BB->args_begin(), argEnd = BB->args_end(); argI != argEnd;
+ ++argI)
+ asImpl().visit(*argI, args...);
}
};
diff --git a/include/swift/SIL/TypeSubstCloner.h b/include/swift/SIL/TypeSubstCloner.h
index 6fc7156..872f3c7 100644
--- a/include/swift/SIL/TypeSubstCloner.h
+++ b/include/swift/SIL/TypeSubstCloner.h
@@ -31,7 +31,7 @@
/// TypeSubstCloner - a utility class for cloning code while remapping types.
template<typename ImplClass>
class TypeSubstCloner : public SILClonerWithScopes<ImplClass> {
- friend class SILVisitor<ImplClass>;
+ friend class SILInstructionVisitor<ImplClass>;
friend class SILCloner<ImplClass>;
typedef SILClonerWithScopes<ImplClass> super;
@@ -185,7 +185,7 @@
}
void visitApplyInst(ApplyInst *Inst) {
- ApplySiteCloningHelper Helper(ApplySite::isa(Inst), *this);
+ ApplySiteCloningHelper Helper(ApplySite(Inst), *this);
ApplyInst *N =
getBuilder().createApply(getOpLocation(Inst->getLoc()),
Helper.getCallee(), Helper.getSubstitutions(),
@@ -196,7 +196,7 @@
}
void visitTryApplyInst(TryApplyInst *Inst) {
- ApplySiteCloningHelper Helper(ApplySite::isa(Inst), *this);
+ ApplySiteCloningHelper Helper(ApplySite(Inst), *this);
TryApplyInst *N = getBuilder().createTryApply(
getOpLocation(Inst->getLoc()), Helper.getCallee(),
Helper.getSubstitutions(), Helper.getArguments(),
@@ -208,7 +208,7 @@
}
void visitPartialApplyInst(PartialApplyInst *Inst) {
- ApplySiteCloningHelper Helper(ApplySite::isa(Inst), *this);
+ ApplySiteCloningHelper Helper(ApplySite(Inst), *this);
auto ParamConvention =
Inst->getType().getAs<SILFunctionType>()->getCalleeConvention();
PartialApplyInst *N = getBuilder().createPartialApply(
@@ -232,14 +232,15 @@
SILBuilderWithPostProcess<TypeSubstCloner, 16> B(this, inst);
B.setCurrentDebugScope(super::getOpScope(inst->getDebugScope()));
+ auto TrueCount = inst->getTrueBBCount();
+ auto FalseCount = inst->getFalseBBCount();
+
// Try to use the scalar cast instruction.
if (canUseScalarCheckedCastInstructions(B.getModule(),
sourceType, targetType)) {
- emitIndirectConditionalCastWithScalar(B, SwiftMod, loc,
- inst->getConsumptionKind(),
- src, sourceType,
- dest, targetType,
- succBB, failBB);
+ emitIndirectConditionalCastWithScalar(
+ B, SwiftMod, loc, inst->getConsumptionKind(), src, sourceType, dest,
+ targetType, succBB, failBB, TrueCount, FalseCount);
return;
}
diff --git a/include/swift/SILOptimizer/Analysis/ARCAnalysis.h b/include/swift/SILOptimizer/Analysis/ARCAnalysis.h
index 9d8c067..5cee6ef 100644
--- a/include/swift/SILOptimizer/Analysis/ARCAnalysis.h
+++ b/include/swift/SILOptimizer/Analysis/ARCAnalysis.h
@@ -376,12 +376,12 @@
/// Gets the (GuaranteedValue, Token) tuple from a call to "unsafeGuaranteed"
/// if the tuple elements are identified by a single tuple_extract use.
/// Otherwise, returns a (nullptr, nullptr) tuple.
-std::pair<SILInstruction *, SILInstruction *>
+std::pair<SingleValueInstruction *, SingleValueInstruction *>
getSingleUnsafeGuaranteedValueResult(BuiltinInst *UnsafeGuaranteedInst);
/// Get the single builtin "unsafeGuaranteedEnd" user of a builtin
/// "unsafeGuaranteed"'s token.
-BuiltinInst *getUnsafeGuaranteedEndUser(SILInstruction *UnsafeGuaranteedToken);
+BuiltinInst *getUnsafeGuaranteedEndUser(SILValue UnsafeGuaranteedToken);
/// Walk forwards from an unsafeGuaranteedEnd builtin instruction looking for a
/// release on the reference returned by the matching unsafeGuaranteed builtin
diff --git a/include/swift/SILOptimizer/Analysis/AliasAnalysis.h b/include/swift/SILOptimizer/Analysis/AliasAnalysis.h
index 2b6c7fa..c74f03c 100644
--- a/include/swift/SILOptimizer/Analysis/AliasAnalysis.h
+++ b/include/swift/SILOptimizer/Analysis/AliasAnalysis.h
@@ -125,7 +125,7 @@
/// NOTE: we do not use the same ValueEnumerator for the alias cache,
/// as when either cache is cleared, we can not clear the ValueEnumerator
/// because doing so could give rise to collisions in the other cache.
- ValueEnumerator<ValueBase*> MemoryBehaviorValueBaseToIndex;
+ ValueEnumerator<SILNode*> MemoryBehaviorNodeToIndex;
AliasResult aliasAddressProjection(SILValue V1, SILValue V2,
SILValue O1, SILValue O2);
@@ -138,12 +138,17 @@
/// Returns True if memory of type \p T1 and \p T2 may alias.
bool typesMayAlias(SILType T1, SILType T2);
- virtual void handleDeleteNotification(ValueBase *I) override {
- // The pointer I is going away. We can't scan the whole cache and remove
- // all of the occurrences of the pointer. Instead we remove the pointer
- // from the cache that translates pointers to indices.
- AliasValueBaseToIndex.invalidateValue(I);
- MemoryBehaviorValueBaseToIndex.invalidateValue(I);
+ virtual void handleDeleteNotification(SILNode *node) override {
+ assert(node->isCanonicalSILNodeInObject());
+
+ // The pointer 'node' is going away. We can't scan the whole cache
+ // and remove all of the occurrences of the pointer. Instead we remove
+ // the pointer from the cache that translates pointers to indices.
+ auto value = dyn_cast<ValueBase>(node);
+ if (!value) return;
+
+ AliasValueBaseToIndex.invalidateValue(value);
+ MemoryBehaviorNodeToIndex.invalidateValue(node);
}
virtual bool needsNotifications() override { return true; }
@@ -261,7 +266,8 @@
AliasKeyTy toAliasKey(SILValue V1, SILValue V2, SILType Type1, SILType Type2);
/// Encodes the memory behavior query as a MemBehaviorKeyTy.
- MemBehaviorKeyTy toMemoryBehaviorKey(SILValue V1, SILValue V2, RetainObserveKind K);
+ MemBehaviorKeyTy toMemoryBehaviorKey(SILInstruction *V1, SILValue V2,
+ RetainObserveKind K);
virtual void invalidate() override {
AliasCache.clear();
diff --git a/include/swift/SILOptimizer/Analysis/ArraySemantic.h b/include/swift/SILOptimizer/Analysis/ArraySemantic.h
index f4db8ae..42a96c0 100644
--- a/include/swift/SILOptimizer/Analysis/ArraySemantic.h
+++ b/include/swift/SILOptimizer/Analysis/ArraySemantic.h
@@ -49,17 +49,31 @@
class ArraySemanticsCall {
ApplyInst *SemanticsCall;
+ void initialize(ApplyInst *apply, StringRef semanticString,
+ bool matchPartialName);
+
public:
+ /// Match calls with any array semantic.
+ template <class NodeTy>
+ ArraySemanticsCall(NodeTy node)
+ : ArraySemanticsCall(node, "array.", /*allow partial*/ true) {}
+
+ /// Match calls with a specific array semantic.
+ template <class NodeTy>
+ ArraySemanticsCall(NodeTy node, StringRef semanticName)
+ : ArraySemanticsCall(node, semanticName, /*allow partial*/ false) {}
+
/// Match array semantic calls.
- ArraySemanticsCall(ValueBase *V, StringRef SemanticStr,
+ ArraySemanticsCall(ApplyInst *apply, StringRef SemanticStr,
bool MatchPartialName);
- /// Match any array semantics call.
- ArraySemanticsCall(ValueBase *V) : ArraySemanticsCall(V, "array.", true) {}
+ /// Match array semantic calls.
+ ArraySemanticsCall(SILInstruction *I, StringRef semanticName,
+ bool matchPartialName);
- /// Match a specific array semantic call.
- ArraySemanticsCall(ValueBase *V, StringRef SemanticStr)
- : ArraySemanticsCall(V, SemanticStr, false) {}
+ /// Match array semantic calls.
+ ArraySemanticsCall(SILValue V, StringRef semanticName,
+ bool matchPartialName);
/// Can we hoist this call.
bool canHoist(SILInstruction *To, DominanceInfo *DT) const;
@@ -156,6 +170,8 @@
/// Get the semantics call as an ApplyInst.
operator ApplyInst *() const { return SemanticsCall; }
+ SILValue getCallResult() const { return SemanticsCall; }
+
/// Is this a semantics call.
operator bool() const { return SemanticsCall != nullptr; }
diff --git a/include/swift/SILOptimizer/Analysis/EpilogueARCAnalysis.h b/include/swift/SILOptimizer/Analysis/EpilogueARCAnalysis.h
index 55aca7c..0c60732 100644
--- a/include/swift/SILOptimizer/Analysis/EpilogueARCAnalysis.h
+++ b/include/swift/SILOptimizer/Analysis/EpilogueARCAnalysis.h
@@ -224,7 +224,7 @@
llvm::DenseMap<SILValue, ARCInstructions> EpilogueReleaseInstCache;
public:
- void handleDeleteNotification(ValueBase *V) {
+ void handleDeleteNotification(SILNode *node) {
// Being conservative and clear everything for now.
EpilogueRetainInstCache.clear();
EpilogueReleaseInstCache.clear();
@@ -277,17 +277,17 @@
EpilogueARCAnalysis(const EpilogueARCAnalysis &) = delete;
EpilogueARCAnalysis &operator=(const EpilogueARCAnalysis &) = delete;
- virtual void handleDeleteNotification(ValueBase *V) override {
+ virtual void handleDeleteNotification(SILNode *node) override {
// If the parent function of this instruction was just turned into an
// external declaration, bail. This happens during SILFunction destruction.
- SILFunction *F = V->getFunction();
+ SILFunction *F = node->getFunction();
if (F->isExternalDeclaration()) {
return;
}
// If we do have an analysis, tell it to handle its delete notifications.
if (auto A = maybeGet(F)) {
- A.get()->handleDeleteNotification(V);
+ A.get()->handleDeleteNotification(node);
}
}
diff --git a/include/swift/SILOptimizer/Analysis/EscapeAnalysis.h b/include/swift/SILOptimizer/Analysis/EscapeAnalysis.h
index 11dd680..21549b3 100644
--- a/include/swift/SILOptimizer/Analysis/EscapeAnalysis.h
+++ b/include/swift/SILOptimizer/Analysis/EscapeAnalysis.h
@@ -378,10 +378,10 @@
CGNode *ReturnNode = nullptr;
/// The list of use points.
- llvm::SmallVector<ValueBase *, 16> UsePointTable;
+ llvm::SmallVector<SILNode *, 16> UsePointTable;
/// Mapping of use points to bit indices in CGNode::UsePoints.
- llvm::DenseMap<ValueBase *, int> UsePoints;
+ llvm::DenseMap<SILNode *, int> UsePoints;
/// The allocator for nodes.
llvm::SpecificBumpPtrAllocator<CGNode> NodeAllocator;
@@ -486,14 +486,15 @@
}
/// Adds an argument/instruction in which the node's value is used.
- int addUsePoint(CGNode *Node, ValueBase *V) {
+ int addUsePoint(CGNode *Node, SILNode *User) {
if (Node->getEscapeState() >= EscapeState::Global)
return -1;
+ User = User->getCanonicalSILNodeInObject();
int Idx = (int)UsePoints.size();
- assert(UsePoints.count(V) == 0 && "value is already a use-point");
- UsePoints[V] = Idx;
- UsePointTable.push_back(V);
+ assert(UsePoints.count(User) == 0 && "value is already a use-point");
+ UsePoints[User] = Idx;
+ UsePointTable.push_back(User);
assert(UsePoints.size() == UsePointTable.size());
Node->setUsePointBit(Idx);
return Idx;
@@ -567,15 +568,15 @@
return Node->UsePoints.count();
}
- /// Returns true if \p V is a use of \p Node, i.e. V may (indirectly)
- /// somehow refer to the Node's value.
+ /// Returns true if \p UsePoint is a use of \p Node, i.e. UsePoint may
+ /// (indirectly) somehow refer to the Node's value.
/// Use-points are only values which are relevant for lifeness computation,
/// e.g. release or apply instructions.
- bool isUsePoint(ValueBase *V, CGNode *Node);
+ bool isUsePoint(SILNode *UsePoint, CGNode *Node);
/// Returns all use points of \p Node in \p UsePoints.
void getUsePoints(CGNode *Node,
- llvm::SmallVectorImpl<ValueBase *> &UsePoints);
+ llvm::SmallVectorImpl<SILNode *> &UsePoints);
/// Computes the use point information.
void computeUsePoints();
@@ -671,9 +672,9 @@
/// See EscapeAnalysis::NodeType::Value.
bool isPointer(ValueBase *V);
- /// If V is a pointer, set it to global escaping.
- void setEscapesGlobal(ConnectionGraph *ConGraph, ValueBase *V) {
- if (CGNode *Node = ConGraph->getNode(V, this))
+ /// If \p pointer is a pointer, set it to global escaping.
+ void setEscapesGlobal(ConnectionGraph *ConGraph, ValueBase *pointer) {
+ if (CGNode *Node = ConGraph->getNode(pointer, this))
ConGraph->setEscapesGlobal(Node);
}
@@ -740,7 +741,7 @@
/// Returns true if the value \p V can escape to the \p UsePoint, where
/// \p UsePoint is either a release-instruction or a function call.
- bool canEscapeToUsePoint(SILValue V, ValueBase *UsePoint,
+ bool canEscapeToUsePoint(SILValue V, SILNode *UsePoint,
ConnectionGraph *ConGraph);
friend struct ::CGForDotView;
@@ -818,7 +819,7 @@
/// Notify the analysis about changed witness or vtables.
virtual void invalidateFunctionTables() override { }
- virtual void handleDeleteNotification(ValueBase *I) override;
+ virtual void handleDeleteNotification(SILNode *N) override;
virtual bool needsNotifications() override { return true; }
diff --git a/include/swift/SILOptimizer/Analysis/IVAnalysis.h b/include/swift/SILOptimizer/Analysis/IVAnalysis.h
index f72d93e..0ab7f82 100644
--- a/include/swift/SILOptimizer/Analysis/IVAnalysis.h
+++ b/include/swift/SILOptimizer/Analysis/IVAnalysis.h
@@ -25,7 +25,7 @@
class IVInfo : public SCCVisitor<IVInfo> {
public:
- typedef llvm::SmallVectorImpl<ValueBase *> SCCType;
+ typedef llvm::SmallVectorImpl<SILNode *> SCCType;
friend SCCVisitor;
public:
diff --git a/include/swift/SILOptimizer/Analysis/RCIdentityAnalysis.h b/include/swift/SILOptimizer/Analysis/RCIdentityAnalysis.h
index c011957..595ee73 100644
--- a/include/swift/SILOptimizer/Analysis/RCIdentityAnalysis.h
+++ b/include/swift/SILOptimizer/Analysis/RCIdentityAnalysis.h
@@ -55,11 +55,16 @@
/// unchecked_trivial_bit_cast.
void getRCUsers(SILValue V, llvm::SmallVectorImpl<SILInstruction *> &Users);
- void handleDeleteNotification(ValueBase *V) {
+ void handleDeleteNotification(SILNode *node) {
+ auto value = dyn_cast<ValueBase>(node);
+ if (!value)
+ return;
+
// Check the cache. If we don't find it, there is nothing to do.
- auto Iter = RCCache.find(SILValue(V));
+ auto Iter = RCCache.find(SILValue(value));
if (Iter == RCCache.end())
return;
+
// Then erase Iter from the cache.
RCCache.erase(Iter);
}
@@ -84,14 +89,14 @@
RCIdentityAnalysis(const RCIdentityAnalysis &) = delete;
RCIdentityAnalysis &operator=(const RCIdentityAnalysis &) = delete;
- virtual void handleDeleteNotification(ValueBase *V) override {
+ virtual void handleDeleteNotification(SILNode *node) override {
// If the parent function of this instruction was just turned into an
// external declaration, bail. This happens during SILFunction destruction.
- SILFunction *F = V->getFunction();
+ SILFunction *F = node->getFunction();
if (F->isExternalDeclaration()) {
return;
}
- get(F)->handleDeleteNotification(V);
+ get(F)->handleDeleteNotification(node);
}
virtual bool needsNotifications() override { return true; }
diff --git a/include/swift/SILOptimizer/Utils/Local.h b/include/swift/SILOptimizer/Utils/Local.h
index 817b505..267f38e 100644
--- a/include/swift/SILOptimizer/Utils/Local.h
+++ b/include/swift/SILOptimizer/Utils/Local.h
@@ -102,7 +102,7 @@
/// value itself)
void eraseUsesOfValue(SILValue V);
-FullApplySite findApplyFromDevirtualizedResult(SILInstruction *I);
+FullApplySite findApplyFromDevirtualizedResult(SILValue value);
/// Check that this is a partial apply of a reabstraction thunk and return the
/// argument of the partial apply if it is.
@@ -158,7 +158,7 @@
/// Tries to optimize a given apply instruction if it is a concatenation of
/// string literals. Returns a new instruction if optimization was possible.
-SILInstruction *tryToConcatenateStrings(ApplyInst *AI, SILBuilder &B);
+SingleValueInstruction *tryToConcatenateStrings(ApplyInst *AI, SILBuilder &B);
/// Tries to perform jump-threading on all checked_cast_br instruction in
/// function \p Fn.
@@ -193,7 +193,7 @@
///
/// In the future this should be extended to be less conservative with users.
bool
-tryDeleteDeadClosure(SILInstruction *Closure,
+tryDeleteDeadClosure(SingleValueInstruction *Closure,
InstModCallbacks Callbacks = InstModCallbacks());
/// Given a SILValue argument to a partial apply \p Arg and the associated
@@ -227,8 +227,10 @@
/// Constructor for the value \p Def considering all the value's uses.
ValueLifetimeAnalysis(SILInstruction *Def) : DefValue(Def) {
- for (Operand *Op : Def->getUses()) {
- UserSet.insert(Op->getUser());
+ for (auto result : Def->getResults()) {
+ for (Operand *op : result->getUses()) {
+ UserSet.insert(op->getUser());
+ }
}
propagateLiveness();
}
@@ -268,7 +270,7 @@
/// Returns true if the value is alive at the begin of block \p BB.
bool isAliveAtBeginOfBlock(SILBasicBlock *BB) {
- return LiveBlocks.count(BB) && BB != DefValue->getParentBlock();
+ return LiveBlocks.count(BB) && BB != DefValue->getParent();
}
/// For debug dumping.
@@ -295,7 +297,7 @@
/// Base class for BB cloners.
class BaseThreadingCloner : public SILClonerWithScopes<BaseThreadingCloner> {
- friend class SILVisitor<BaseThreadingCloner>;
+ friend class SILInstructionVisitor<BaseThreadingCloner>;
friend class SILCloner<BaseThreadingCloner>;
protected:
@@ -321,7 +323,7 @@
SILValue remapValue(SILValue Value) {
// If this is a use of an instruction in another block, then just use it.
- if (auto SI = dyn_cast<SILInstruction>(Value)) {
+ if (auto SI = Value->getDefiningInstruction()) {
if (SI->getParent() != FromBB)
return Value;
} else if (auto BBArg = dyn_cast<SILArgument>(Value)) {
@@ -340,8 +342,13 @@
SILCloner<BaseThreadingCloner>::postProcess(Orig, Cloned);
// A terminator defines no values. Keeping terminators in the AvailVals list
// is problematic because terminators get replaced during SSA update.
- if (!isa<TermInst>(Orig))
- AvailVals.push_back(std::make_pair(Orig, SILValue(Cloned)));
+ auto results = Orig->getResults();
+ assert(results.size() == Cloned->getResults().size());
+ if (!results.empty()) {
+ auto clonedResults = Cloned->getResults();
+ for (size_t i = 0, e = results.size(); i != e; ++i)
+ AvailVals.push_back(std::make_pair(results[i], clonedResults[i]));
+ }
}
};
@@ -428,7 +435,8 @@
/// \brief This is a helper class used to optimize casts.
class CastOptimizer {
// Callback to be called when uses of an instruction should be replaced.
- std::function<void (SILInstruction *I, ValueBase *V)> ReplaceInstUsesAction;
+ std::function<void (SingleValueInstruction *I, ValueBase *V)>
+ ReplaceInstUsesAction;
// Callback to call when an instruction needs to be erased.
std::function<void (SILInstruction *)> EraseInstAction;
@@ -474,7 +482,7 @@
SILInstruction *TrapInst);
public:
- CastOptimizer(std::function<void (SILInstruction *I, ValueBase *V)> ReplaceInstUsesAction,
+ CastOptimizer(std::function<void (SingleValueInstruction *I, ValueBase *V)> ReplaceInstUsesAction,
std::function<void (SILInstruction *)> EraseAction,
std::function<void ()> WillSucceedAction,
std::function<void ()> WillFailAction = [](){})
@@ -488,7 +496,7 @@
// couldn't use the single constructor version which has three default
// arguments. It seems the number of the default argument with lambda is
// limited.
- CastOptimizer(std::function<void (SILInstruction *I, ValueBase *V)> ReplaceInstUsesAction,
+ CastOptimizer(std::function<void (SingleValueInstruction *I, ValueBase *V)> ReplaceInstUsesAction,
std::function<void (SILInstruction *)> EraseAction = [](SILInstruction*){})
: CastOptimizer(ReplaceInstUsesAction, EraseAction, [](){}, [](){}) {}
@@ -581,20 +589,20 @@
ValueBaseUseIterator OrigUseChain;
ValueBaseUseIterator CurrentIter;
- static bool isExpect(Operand *Use) {
+ static BuiltinInst *isExpect(Operand *Use) {
if (auto *BI = dyn_cast<BuiltinInst>(Use->getUser()))
if (BI->getIntrinsicInfo().ID == llvm::Intrinsic::expect)
- return true;
- return false;
+ return BI;
+ return nullptr;
}
// Advance through expect users to their users until we encounter a user that
// is not an expect.
void advanceThroughExpects() {
while (CurrentIter == OrigUseChain &&
- CurrentIter != ValueBaseUseIterator(nullptr) &&
- isExpect(*CurrentIter)) {
- auto *Expect = CurrentIter->getUser();
+ CurrentIter != ValueBaseUseIterator(nullptr)) {
+ auto *Expect = isExpect(*CurrentIter);
+ if (!Expect) return;
CurrentIter = Expect->use_begin();
// Expect with no users advance to next item in original use chain.
if (CurrentIter == Expect->use_end())
@@ -663,7 +671,7 @@
/// An example of how this is useful is in cases where one is splitting up an
/// aggregate and reforming it, the reformed aggregate may have extract
/// operations from it. These can be simplified and removed.
-bool simplifyUsers(SILInstruction *I);
+bool simplifyUsers(SingleValueInstruction *I);
/// True if a type can be expanded
/// without a significant increase to code size.
@@ -687,7 +695,7 @@
/// The sequence is traversed inside out, i.e.
/// starting with the innermost struct_element_addr
void replaceLoadSequence(SILInstruction *I,
- SILInstruction *Value,
+ SILValue Value,
SILBuilder &B);
diff --git a/include/swift/SILOptimizer/Utils/SCCVisitor.h b/include/swift/SILOptimizer/Utils/SCCVisitor.h
index ffe1354..ccddb5b 100644
--- a/include/swift/SILOptimizer/Utils/SCCVisitor.h
+++ b/include/swift/SILOptimizer/Utils/SCCVisitor.h
@@ -39,13 +39,13 @@
template <typename ImplClass>
class SCCVisitor {
public:
- SCCVisitor(SILFunction &F) : F(F), CurrentNum(0) {}
+ SCCVisitor(SILFunction &F) : F(F) {}
~SCCVisitor() {
cleanup();
}
ImplClass &asImpl() { return static_cast<ImplClass &>(*this); }
- void visit(llvm::SmallVectorImpl<ValueBase *> &SCC) { }
+ void visit(llvm::SmallVectorImpl<SILNode *> &SCC) { }
void run() {
llvm::ReversePostOrderTraversal<SILFunction *> RPOT(&F);
@@ -53,8 +53,7 @@
for (auto Iter = RPOT.begin(), E = RPOT.end(); Iter != E; ++Iter) {
auto *BB = *Iter;
for (auto &I : *BB)
- if (!Visited.count(&I))
- DFS(&I);
+ maybeDFS(&I);
}
cleanup();
@@ -62,20 +61,19 @@
private:
struct DFSInfo {
- ValueBase *Value;
+ SILNode *Node;
int DFSNum;
int LowNum;
- DFSInfo(ValueBase *Value, int Num) : Value(Value), DFSNum(Num),
- LowNum(Num) {}
+ DFSInfo(SILNode *node, int num) : Node(node), DFSNum(num), LowNum(num) {}
};
SILFunction &F;
- int CurrentNum;
+ int CurrentNum = 0;
- llvm::DenseSet<ValueBase *> Visited;
- llvm::SetVector<ValueBase *> DFSStack;
- typedef llvm::DenseMap<ValueBase *, DFSInfo *> ValueInfoMapType;
+ llvm::DenseSet<SILNode *> Visited;
+ llvm::SetVector<SILNode *> DFSStack;
+ typedef llvm::DenseMap<SILNode *, DFSInfo *> ValueInfoMapType;
ValueInfoMapType ValueInfoMap;
void cleanup() {
@@ -88,25 +86,26 @@
CurrentNum = 0;
}
- DFSInfo &addDFSInfo(ValueBase *Value) {
- typename ValueInfoMapType::iterator Iter;
- bool Inserted;
+ DFSInfo &addDFSInfo(SILNode *node) {
+ assert(node->isCanonicalSILNodeInObject());
- auto MapEntry = std::make_pair(Value, new DFSInfo(Value, CurrentNum++));
- std::tie(Iter, Inserted) = ValueInfoMap.insert(MapEntry);
- assert(Inserted && "Cannot add DFS info more than once for a value!");
- return *Iter->second;
+ auto entry = std::make_pair(node, new DFSInfo(node, CurrentNum++));
+ auto insertion = ValueInfoMap.insert(entry);
+ assert(insertion.second && "Cannot add DFS info more than once!");
+ return *insertion.first->second;
}
- DFSInfo &getDFSInfo(ValueBase *Value) {
- assert(ValueInfoMap.find(Value) != ValueInfoMap.end() &&
+ DFSInfo &getDFSInfo(SILNode *node) {
+ assert(node->isCanonicalSILNodeInObject());
+ auto it = ValueInfoMap.find(node);
+ assert(it != ValueInfoMap.end() &&
"Expected to find value in DFS info map!");
- return *ValueInfoMap.find(Value)->second;
+ return *it->second;
}
void getArgsForTerminator(TermInst *Term, SILBasicBlock *SuccBB, int Index,
- llvm::SmallVectorImpl<ValueBase *> &Operands) {
+ llvm::SmallVectorImpl<SILValue> &Operands) {
switch (Term->getTermKind()) {
case TermKind::BranchInst:
return Operands.push_back(cast<BranchInst>(Term)->getArg(Index));
@@ -143,15 +142,15 @@
}
}
- void collectOperandsForUser(ValueBase *User,
- llvm::SmallVectorImpl<ValueBase *> &Operands) {
- if (auto *I = dyn_cast<SILInstruction>(User)) {
+ void collectOperandsForUser(SILNode *node,
+ llvm::SmallVectorImpl<SILValue> &Operands) {
+ if (auto *I = dyn_cast<SILInstruction>(node)) {
for (auto &O : I->getAllOperands())
Operands.push_back(O.get());
return;
}
- if (auto *A = dyn_cast<SILArgument>(User)) {
+ if (auto *A = dyn_cast<SILArgument>(node)) {
auto *BB = A->getParent();
auto Index = A->getIndex();
@@ -161,47 +160,52 @@
}
}
- // Is Value currently on our DFS stack?
- bool onStack(ValueBase *Value) {
- return DFSStack.count(Value);
+ void maybeDFS(SILInstruction *inst) {
+ (void) maybeDFSCanonicalNode(inst->getCanonicalSILNodeInObject());
}
- /// Do depth-first through the value graph, finding the strongly
- /// component that User is a part of, and call visit() with that SCC.
- void DFS(ValueBase *User) {
- assert(!Visited.count(User) &&
- "Attempting to visit a value twice in DFS search!");
+ /// Continue a DFS from the given node, finding the strongly
+ /// component that User is a part of, calling visit() with that SCC,
+ /// and returning the DFSInfo for the node.
+ /// But if we've already visited the node, just return null.
+ DFSInfo *maybeDFSCanonicalNode(SILNode *node) {
+ assert(node->isCanonicalSILNodeInObject() && "should already be canonical");
- DFSStack.insert(User);
- Visited.insert(User);
+ if (!Visited.insert(node).second)
+ return nullptr;
- auto &UserInfo = addDFSInfo(User);
+ DFSStack.insert(node);
- llvm::SmallVector<ValueBase *, 4> Operands;
- collectOperandsForUser(User, Operands);
+ auto &nodeInfo = addDFSInfo(node);
+
+ llvm::SmallVector<SILValue, 4> operands;
+ collectOperandsForUser(node, operands);
// Visit each unvisited operand, updating the lowest DFS number we've seen
// reachable in User's SCC.
- for (auto *Opnd : Operands) {
- if (!Visited.count(Opnd)) {
- DFS(Opnd);
- UserInfo.LowNum = std::min(UserInfo.LowNum, getDFSInfo(Opnd).LowNum);
- } else if (onStack(Opnd)) {
- UserInfo.LowNum = std::min(UserInfo.LowNum, getDFSInfo(Opnd).DFSNum);
+ for (SILValue operandValue : operands) {
+ SILNode *operandNode = operandValue->getCanonicalSILNodeInObject();
+ if (auto operandNodeInfo = maybeDFSCanonicalNode(operandNode)) {
+ nodeInfo.LowNum = std::min(nodeInfo.LowNum, operandNodeInfo->LowNum);
+ } else if (DFSStack.count(operandNode)) {
+ auto operandNodeInfo = &getDFSInfo(operandNode);
+ nodeInfo.LowNum = std::min(nodeInfo.LowNum, operandNodeInfo->DFSNum);
}
}
// If User is the head of its own SCC, pop that SCC off the DFS stack.
- if (UserInfo.DFSNum == UserInfo.LowNum) {
- llvm::SmallVector<ValueBase *, 4> SCC;
- ValueBase *PoppedValue;
+ if (nodeInfo.DFSNum == nodeInfo.LowNum) {
+ llvm::SmallVector<SILNode *, 4> SCC;
+ SILNode *poppedNode;
do {
- PoppedValue = DFSStack.pop_back_val();
- SCC.push_back(PoppedValue);
- } while (PoppedValue != User);
+ poppedNode = DFSStack.pop_back_val();
+ SCC.push_back(poppedNode);
+ } while (poppedNode != node);
asImpl().visit(SCC);
}
+
+ return &nodeInfo;
}
};
diff --git a/include/swift/SILOptimizer/Utils/SILInliner.h b/include/swift/SILOptimizer/Utils/SILInliner.h
index a7f5921..b059e36 100644
--- a/include/swift/SILOptimizer/Utils/SILInliner.h
+++ b/include/swift/SILOptimizer/Utils/SILInliner.h
@@ -37,7 +37,7 @@
class SILInliner : public TypeSubstCloner<SILInliner> {
public:
- friend class SILVisitor<SILInliner>;
+ friend class SILInstructionVisitor<SILInliner>;
friend class SILCloner<SILInliner>;
enum class InlineKind {
diff --git a/include/swift/SILOptimizer/Utils/SILSSAUpdater.h b/include/swift/SILOptimizer/Utils/SILSSAUpdater.h
index 7c599c3..671c0a0 100644
--- a/include/swift/SILOptimizer/Utils/SILSSAUpdater.h
+++ b/include/swift/SILOptimizer/Utils/SILSSAUpdater.h
@@ -31,7 +31,7 @@
/// Independent utility that canonicalizes BB arguments by reusing structurally
/// equivalent arguments and replacing the original arguments with casts.
-SILInstruction *replaceBBArgWithCast(SILPHIArgument *Arg);
+SILValue replaceBBArgWithCast(SILPHIArgument *Arg);
/// This class updates SSA for a set of SIL instructions defined in multiple
/// blocks.
diff --git a/include/swift/SILOptimizer/Utils/StackNesting.h b/include/swift/SILOptimizer/Utils/StackNesting.h
index 105ae28..78adaa2 100644
--- a/include/swift/SILOptimizer/Utils/StackNesting.h
+++ b/include/swift/SILOptimizer/Utils/StackNesting.h
@@ -79,10 +79,10 @@
///
/// Each stack location is allocated by a single allocation instruction.
struct StackLoc {
- StackLoc(SILInstruction *Alloc) : Alloc(Alloc) { }
+ StackLoc(AllocationInst *Alloc) : Alloc(Alloc) { }
/// Back-link to the allocation instruction.
- SILInstruction *Alloc;
+ AllocationInst *Alloc;
/// Bit-set which represents all alive locations at this allocation.
/// It obviously includes this location itself. And it includes all "outer"
@@ -91,7 +91,7 @@
};
/// Mapping from stack allocations (= locations) to bit numbers.
- llvm::DenseMap<SILInstruction *, unsigned> StackLoc2BitNumbers;
+ llvm::DenseMap<SingleValueInstruction *, unsigned> StackLoc2BitNumbers;
/// The list of stack locations. The index into this array is also the bit
/// number in the bit-sets.
diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h
index 08f2d2e..5341b09 100644
--- a/include/swift/Serialization/ModuleFormat.h
+++ b/include/swift/Serialization/ModuleFormat.h
@@ -54,7 +54,7 @@
/// in source control, you should also update the comment to briefly
/// describe what change you made. The content of this comment isn't important;
/// it just ensures a conflict if two people change the module format.
-const uint16_t VERSION_MINOR = 366; // Last change: default argument resilience expansion
+const uint16_t VERSION_MINOR = 367; // Last change: SIL values vs. instructions
using DeclID = PointerEmbeddedInt<unsigned, 31>;
using DeclIDField = BCFixed<31>;
diff --git a/lib/AST/GenericSignature.cpp b/lib/AST/GenericSignature.cpp
index 161da23..594d466 100644
--- a/lib/AST/GenericSignature.cpp
+++ b/lib/AST/GenericSignature.cpp
@@ -912,8 +912,7 @@
// We are at an explicit or inferred requirement.
assert(source->kind == RequirementSource::Explicit ||
- source->kind == RequirementSource::Inferred ||
- source->kind == RequirementSource::QuietlyInferred);
+ source->kind == RequirementSource::Inferred);
// Skip trivial path elements. These occur when querying a requirement
// signature.
diff --git a/lib/AST/GenericSignatureBuilder.cpp b/lib/AST/GenericSignatureBuilder.cpp
index f0b85ea..c8319b3 100644
--- a/lib/AST/GenericSignatureBuilder.cpp
+++ b/lib/AST/GenericSignatureBuilder.cpp
@@ -340,7 +340,6 @@
switch (kind) {
case Explicit:
case Inferred:
- case QuietlyInferred:
case RequirementSignatureSelf:
case NestedTypeNameMatch:
case ConcreteTypeBinding:
@@ -449,16 +448,13 @@
return nullptr;
}
-bool RequirementSource::isInferredRequirement(bool includeQuietInferred) const {
+bool RequirementSource::isInferredRequirement() const {
for (auto source = this; source; source = source->parent) {
switch (source->kind) {
case Inferred:
case InferredProtocolRequirement:
- return true;
-
- case QuietlyInferred:
case NestedTypeNameMatch:
- return includeQuietInferred;
+ return true;
case ConcreteTypeBinding:
case EquivalentType:
@@ -479,7 +475,7 @@
}
unsigned RequirementSource::classifyDiagKind() const {
- if (isInferredRequirement(/*includeQuietInferred=*/false)) return 2;
+ if (isInferredRequirement()) return 2;
if (isDerivedRequirement()) return 1;
return 0;
}
@@ -488,7 +484,6 @@
switch (kind) {
case Explicit:
case Inferred:
- case QuietlyInferred:
return false;
case NestedTypeNameMatch:
@@ -691,7 +686,6 @@
case Explicit:
case Inferred:
- case QuietlyInferred:
case NestedTypeNameMatch:
case ConcreteTypeBinding:
rootPA = parentPA;
@@ -779,14 +773,13 @@
const RequirementSource *RequirementSource::forInferred(
PotentialArchetype *root,
- const TypeRepr *typeRepr,
- bool quietly) {
+ const TypeRepr *typeRepr) {
WrittenRequirementLoc writtenLoc = typeRepr;
auto &builder = *root->getBuilder();
REQUIREMENT_SOURCE_FACTORY_BODY(
- (nodeID, quietly ? QuietlyInferred : Inferred, nullptr, root,
+ (nodeID, Inferred, nullptr, root,
writtenLoc.getOpaqueValue(), nullptr),
- (quietly ? QuietlyInferred : Inferred, root, nullptr, writtenLoc),
+ (Inferred, root, nullptr, writtenLoc),
0, writtenLoc);
}
@@ -916,7 +909,6 @@
switch (kind) {
case Explicit:
case Inferred:
- case QuietlyInferred:
case RequirementSignatureSelf:
case NestedTypeNameMatch:
case ConcreteTypeBinding:
@@ -999,7 +991,6 @@
case RequirementSource::ConcreteTypeBinding:
case RequirementSource::Explicit:
case RequirementSource::Inferred:
- case RequirementSource::QuietlyInferred:
case RequirementSource::RequirementSignatureSelf: {
auto rootPA = getRootPotentialArchetype();
if (visitor(rootPA, this)) return nullptr;
@@ -1175,10 +1166,6 @@
out << "Inferred";
break;
- case QuietlyInferred:
- out << "Quietly inferred";
- break;
-
case NestedTypeNameMatch:
out << "Nested type match";
break;
@@ -1292,12 +1279,7 @@
return RequirementSource::forAbstract(pa);
case Inferred:
- return RequirementSource::forInferred(pa, storage.get<const TypeRepr *>(),
- /*quietly=*/false);
-
- case QuietlyInferred:
- return RequirementSource::forInferred(pa, storage.get<const TypeRepr *>(),
- /*quietly=*/true);
+ return RequirementSource::forInferred(pa, storage.get<const TypeRepr *>());
case AbstractProtocol: {
// Derive the dependent type on which this requirement was written. It is
@@ -1350,7 +1332,6 @@
return true;
case Inferred:
- case QuietlyInferred:
case NestedTypeNameMatch:
return false;
@@ -1366,7 +1347,6 @@
case RequirementSource::Concrete:
case RequirementSource::Explicit:
case RequirementSource::Inferred:
- case RequirementSource::QuietlyInferred:
case RequirementSource::NestedTypeNameMatch:
case RequirementSource::ConcreteTypeBinding:
case RequirementSource::Parent:
@@ -1388,7 +1368,6 @@
== RequirementSource::RequirementSignatureSelf;
case RequirementSource::Inferred:
- case RequirementSource::QuietlyInferred:
case RequirementSource::InferredProtocolRequirement:
case RequirementSource::RequirementSignatureSelf:
case RequirementSource::Concrete:
@@ -1408,10 +1387,9 @@
const TypeRepr *typeRepr) const {
switch (kind) {
case Explicit:
- return forInferred(typeRepr, /*quietly=*/false);
+ return forInferred(typeRepr);
case Inferred:
- case QuietlyInferred:
case Resolved:
case NestedTypeNameMatch:
return *this;
@@ -3619,10 +3597,10 @@
assert(allNested.back() == nestedPA);
if (allNested.size() > 1) {
auto firstPA = allNested.front();
- auto quietlyInferredSource =
- FloatingRequirementSource::forInferred(nullptr, /*quietly=*/true);
+ auto inferredSource =
+ FloatingRequirementSource::forInferred(nullptr);
- addSameTypeRequirement(firstPA, nestedPA, quietlyInferredSource,
+ addSameTypeRequirement(firstPA, nestedPA, inferredSource,
UnresolvedHandlingKind::GenerateConstraints);
return;
}
@@ -3977,8 +3955,7 @@
// We are inferring requirements.
if (forInferred) {
- return FloatingRequirementSource::forInferred(typeRepr,
- /*quietly=*/false);
+ return FloatingRequirementSource::forInferred(typeRepr);
}
// Explicit requirement.
@@ -4126,10 +4103,10 @@
if (inferForModule) {
inferRequirements(*inferForModule, TypeLoc::withoutLoc(firstType),
FloatingRequirementSource::forInferred(
- nullptr, /*quietly=*/false));
+ nullptr));
inferRequirements(*inferForModule, TypeLoc::withoutLoc(secondType),
FloatingRequirementSource::forInferred(
- nullptr, /*quietly=*/false));
+ nullptr));
}
return addTypeRequirement(firstType, secondType, source,
@@ -4143,8 +4120,7 @@
if (inferForModule) {
inferRequirements(*inferForModule, TypeLoc::withoutLoc(firstType),
- FloatingRequirementSource::forInferred(
- nullptr, /*quietly=*/false));
+ FloatingRequirementSource::forInferred(nullptr));
}
return addLayoutRequirement(firstType, req.getLayoutConstraint(), source,
@@ -4160,10 +4136,10 @@
if (inferForModule) {
inferRequirements(*inferForModule, TypeLoc::withoutLoc(firstType),
FloatingRequirementSource::forInferred(
- nullptr, /*quietly=*/false));
+ nullptr));
inferRequirements(*inferForModule, TypeLoc::withoutLoc(secondType),
FloatingRequirementSource::forInferred(
- nullptr, /*quietly=*/false));
+ nullptr));
}
return addSameTypeRequirement(
@@ -4237,7 +4213,7 @@
for (auto P : *params) {
inferRequirements(module, P->getTypeLoc(),
FloatingRequirementSource::forInferred(
- P->getTypeLoc().getTypeRepr(), /*quietly=*/false));
+ P->getTypeLoc().getTypeRepr()));
}
}
@@ -4292,20 +4268,6 @@
continue;
}
- // We prefer constraints rooted at inferred requirements to ones rooted
- // on explicit requirements, because the former won't be diagnosed
- // directly.
- bool thisIsInferred = constraint.source->isInferredRequirement(
- /*includeQuietInferred=*/false);
- bool representativeIsInferred =
- representativeConstraint->source->isInferredRequirement(
- /*includeQuietInferred=*/false);
- if (thisIsInferred != representativeIsInferred) {
- if (thisIsInferred)
- representativeConstraint = constraint;
- continue;
- }
-
// We prefer derived constraints to non-derived constraints.
bool thisIsDerived = constraint.source->isDerivedRequirement();
bool representativeIsDerived =
@@ -4317,6 +4279,17 @@
continue;
}
+ // We prefer constraints that are explicit to inferred constraints.
+ bool thisIsInferred = constraint.source->isInferredRequirement();
+ bool representativeIsInferred =
+ representativeConstraint->source->isInferredRequirement();
+ if (thisIsInferred != representativeIsInferred) {
+ if (thisIsInferred)
+ representativeConstraint = constraint;
+
+ continue;
+ }
+
// We prefer constraints with locations to constraints without locations.
bool thisHasValidSourceLoc = constraint.source->getLoc().isValid();
bool representativeHasValidSourceLoc =
@@ -4873,7 +4846,8 @@
bool diagnosedConflictingRepresentative = false;
for (const auto &constraint : constraints) {
// Leave the representative alone.
- if (constraint == *representativeConstraint) continue;
+ if (representativeConstraint && constraint == *representativeConstraint)
+ continue;
switch (checkConstraint(constraint)) {
case ConstraintRelation::Unrelated:
@@ -4937,9 +4911,9 @@
// If this requirement is not derived or inferred (but has a useful
// location) complain that it is redundant.
if (!constraint.source->isDerivedRequirement() &&
- !constraint.source->isInferredRequirement(
- /*includeQuietInferred=*/true) &&
- constraint.source->getLoc().isValid()) {
+ !constraint.source->isInferredRequirement() &&
+ constraint.source->getLoc().isValid() &&
+ !representativeConstraint->source->isInferredRequirement()) {
Diags.diagnose(constraint.source->getLoc(),
redundancyDiag,
constraint.archetype->getDependentType(genericParams),
@@ -5191,12 +5165,8 @@
return lhs.target < rhs.target;
// Prefer non-inferred requirement sources.
- bool lhsIsInferred =
- lhs.constraint.source->isInferredRequirement(
- /*includeQuietInferred=*/false);
- bool rhsIsInferred =
- rhs.constraint.source->isInferredRequirement(
- /*includeQuietInferred=*/false);
+ bool lhsIsInferred = lhs.constraint.source->isInferredRequirement();
+ bool rhsIsInferred = rhs.constraint.source->isInferredRequirement();
if (lhsIsInferred != rhsIsInferred)
return rhsIsInferred;;
@@ -5615,8 +5585,7 @@
// If the source/destination are identical, complain.
if (constraint.archetype == constraint.value) {
if (!constraint.source->isDerivedRequirement() &&
- !constraint.source->isInferredRequirement(
- /*includeQuietInferred=*/true) &&
+ !constraint.source->isInferredRequirement() &&
constraint.source->getLoc().isValid()) {
Diags.diagnose(constraint.source->getLoc(),
diag::redundant_same_type_constraint,
@@ -5734,8 +5703,8 @@
return true;
// If the constraint source is inferred, don't diagnose it.
- if (lhs.constraint.source->isInferredRequirement(
- /*includeQuietInferred=*/true))
+ if (lhs.constraint.source->isInferredRequirement() ||
+ rhs.constraint.source->isInferredRequirement())
return true;
Diags.diagnose(lhs.constraint.source->getLoc(),
@@ -5765,9 +5734,9 @@
// not part of the spanning tree.
if (connected[edge.source] && connected[edge.target]) {
if (edge.constraint.source->getLoc().isValid() &&
- !edge.constraint.source->isInferredRequirement(
- /*includeQuietInferred=*/true) &&
- firstEdge.constraint.source->getLoc().isValid()) {
+ !edge.constraint.source->isInferredRequirement() &&
+ firstEdge.constraint.source->getLoc().isValid() &&
+ !firstEdge.constraint.source->isInferredRequirement()) {
Diags.diagnose(edge.constraint.source->getLoc(),
diag::redundant_same_type_constraint,
edge.constraint.archetype->getDependentType(
@@ -5926,11 +5895,13 @@
if (auto existing = equivClass->findAnyConcreteConstraintAsWritten(
representativeConstraint.archetype)) {
- Diags.diagnose(existing->source->getLoc(),
- diag::same_type_redundancy_here,
- existing->source->classifyDiagKind(),
- existing->archetype->getDependentType(genericParams),
- existing->value);
+ if (!existing->source->isInferredRequirement()) {
+ Diags.diagnose(existing->source->getLoc(),
+ diag::same_type_redundancy_here,
+ existing->source->classifyDiagKind(),
+ existing->archetype->getDependentType(genericParams),
+ existing->value);
+ }
}
}
}
@@ -6226,22 +6197,8 @@
for (auto param : sig->getGenericParams())
addGenericParameter(param);
- // Add the requirements, queuing up same-type requirements until the end.
- // FIXME: Queuing up same-type requirements is a hack that works around
- // problems when referencing associated types. These issues primarily
- // occur when building canonical generic environments
- SmallVector<Requirement, 4> sameTypeRequirements;
- for (auto &reqt : sig->getRequirements()) {
- if (reqt.getKind() == RequirementKind::SameType)
- sameTypeRequirements.push_back(reqt);
- else
- addRequirement(reqt, FloatingRequirementSource::forAbstract(), nullptr);
- }
-
- // Handle same-type requirements.
- for (auto &reqt : sameTypeRequirements) {
+ for (auto &reqt : sig->getRequirements())
addRequirement(reqt, FloatingRequirementSource::forAbstract(), nullptr);
- }
}
/// Collect the set of requirements placed on the given generic parameters and
diff --git a/lib/AST/TypeJoinMeet.cpp b/lib/AST/TypeJoinMeet.cpp
index 3620c4a..ac5284a 100644
--- a/lib/AST/TypeJoinMeet.cpp
+++ b/lib/AST/TypeJoinMeet.cpp
@@ -15,9 +15,9 @@
//
//===----------------------------------------------------------------------===//
#include "swift/AST/ASTContext.h"
+#include "swift/AST/CanTypeVisitor.h"
#include "swift/AST/Decl.h"
#include "swift/AST/Type.h"
-#include "swift/AST/TypeVisitor.h"
#include "swift/AST/Types.h"
#include "llvm/ADT/SmallPtrSet.h"
using namespace swift;
@@ -26,43 +26,33 @@
// used for optimizing away extra exploratory work in the constraint
// solver. It should eventually encompass all of the subtyping rules
// of the language.
-struct TypeJoin : TypeVisitor<TypeJoin, Type> {
- Type First;
+struct TypeJoin : CanTypeVisitor<TypeJoin, CanType> {
+ CanType First;
- TypeJoin(Type First) : First(First) {
+ TypeJoin(CanType First) : First(First) {
assert(First && "Unexpected null type!");
}
- static Type getSuperclassJoin(Type first, Type second);
+ static CanType getSuperclassJoin(CanType first, CanType second);
- Type visitClassType(Type second);
- Type visitBoundGenericClassType(Type second);
- Type visitArchetypeType(Type second);
- Type visitDynamicSelfType(Type second);
- Type visitMetatypeType(Type second);
- Type visitExistentialMetatypeType(Type second);
- Type visitBoundGenericEnumType(Type second);
+ CanType visitClassType(CanType second);
+ CanType visitBoundGenericClassType(CanType second);
+ CanType visitArchetypeType(CanType second);
+ CanType visitDynamicSelfType(CanType second);
+ CanType visitMetatypeType(CanType second);
+ CanType visitExistentialMetatypeType(CanType second);
+ CanType visitBoundGenericEnumType(CanType second);
- Type visitOptionalType(Type second);
+ CanType visitOptionalType(CanType second);
- Type visitType(Type second) {
+ CanType visitType(CanType second) {
// FIXME: Implement all the visitors.
// llvm_unreachable("Unimplemented type visitor!");
return First->getASTContext().TheAnyType;
}
public:
- static Type join(Type first, Type second) {
- if (!first || !second) {
- if (first)
- return ErrorType::get(first->getASTContext());
-
- if (second)
- return ErrorType::get(second->getASTContext());
-
- return Type();
- }
-
+ static CanType join(CanType first, CanType second) {
assert(!first->hasTypeVariable() && !second->hasTypeVariable() &&
"Cannot compute join of types involving type variables");
@@ -72,7 +62,7 @@
"Expected simple type!");
// If the types are equivalent, the join is obvious.
- if (first->isEqual(second))
+ if (first == second)
return first;
// Until we handle all the combinations of joins, we need to make
@@ -85,23 +75,19 @@
}
};
-Type TypeJoin::getSuperclassJoin(Type first, Type second) {
- if (!first || !second)
- return TypeJoin::join(first, second);
-
+CanType TypeJoin::getSuperclassJoin(CanType first, CanType second) {
if (!first->mayHaveSuperclass() || !second->mayHaveSuperclass())
return first->getASTContext().TheAnyType;
/// Walk the superclasses of `first` looking for `second`. Record them
/// for our second step.
llvm::SmallPtrSet<CanType, 8> superclassesOfFirst;
- CanType canSecond = second->getCanonicalType();
for (Type super = first; super; super = super->getSuperclass()) {
- CanType canSuper = super->getCanonicalType();
+ auto canSuper = super->getCanonicalType();
// If we have found the second type, we're done.
- if (canSuper == canSecond)
- return super;
+ if (canSuper == second)
+ return canSuper;
superclassesOfFirst.insert(canSuper);
}
@@ -109,94 +95,104 @@
// Look through the superclasses of second to determine if any were also
// superclasses of first.
for (Type super = second; super; super = super->getSuperclass()) {
- CanType canSuper = super->getCanonicalType();
+ auto canSuper = super->getCanonicalType();
// If we found the first type, we're done.
if (superclassesOfFirst.count(canSuper))
- return super;
+ return canSuper;
}
// There is no common superclass; we're done.
return first->getASTContext().TheAnyType;
}
-Type TypeJoin::visitClassType(Type second) {
+CanType TypeJoin::visitClassType(CanType second) {
return getSuperclassJoin(First, second);
}
-Type TypeJoin::visitBoundGenericClassType(Type second) {
+CanType TypeJoin::visitBoundGenericClassType(CanType second) {
return getSuperclassJoin(First, second);
}
-Type TypeJoin::visitArchetypeType(Type second) {
+CanType TypeJoin::visitArchetypeType(CanType second) {
return getSuperclassJoin(First, second);
}
-Type TypeJoin::visitDynamicSelfType(Type second) {
+CanType TypeJoin::visitDynamicSelfType(CanType second) {
return getSuperclassJoin(First, second);
}
-Type TypeJoin::visitMetatypeType(Type second) {
+CanType TypeJoin::visitMetatypeType(CanType second) {
if (First->getKind() != second->getKind())
return First->getASTContext().TheAnyType;
- auto firstInstance = First->castTo<AnyMetatypeType>()->getInstanceType();
- auto secondInstance = second->castTo<AnyMetatypeType>()->getInstanceType();
+ auto firstInstance =
+ First->castTo<AnyMetatypeType>()->getInstanceType()->getCanonicalType();
+ auto secondInstance =
+ second->castTo<AnyMetatypeType>()->getInstanceType()->getCanonicalType();
auto joinInstance = join(firstInstance, secondInstance);
if (!joinInstance)
return First->getASTContext().TheAnyType;
- return MetatypeType::get(joinInstance);
+ return MetatypeType::get(joinInstance)->getCanonicalType();
}
-Type TypeJoin::visitExistentialMetatypeType(Type second) {
+CanType TypeJoin::visitExistentialMetatypeType(CanType second) {
if (First->getKind() != second->getKind())
return First->getASTContext().TheAnyType;
- auto firstInstance = First->castTo<AnyMetatypeType>()->getInstanceType();
- auto secondInstance = second->castTo<AnyMetatypeType>()->getInstanceType();
+ auto firstInstance =
+ First->castTo<AnyMetatypeType>()->getInstanceType()->getCanonicalType();
+ auto secondInstance =
+ second->castTo<AnyMetatypeType>()->getInstanceType()->getCanonicalType();
auto joinInstance = join(firstInstance, secondInstance);
if (!joinInstance)
return First->getASTContext().TheAnyType;
- return ExistentialMetatypeType::get(joinInstance);
+ return ExistentialMetatypeType::get(joinInstance)->getCanonicalType();
}
-Type TypeJoin::visitBoundGenericEnumType(Type second) {
+CanType TypeJoin::visitBoundGenericEnumType(CanType second) {
if (First->getKind() != second->getKind())
return First->getASTContext().TheAnyType;
OptionalTypeKind otk1, otk2;
- Type objectType1 = First->getAnyOptionalObjectType(otk1);
- Type objectType2 = second->getAnyOptionalObjectType(otk2);
+ auto firstObject = First->getAnyOptionalObjectType(otk1);
+ auto secondObject = second->getAnyOptionalObjectType(otk2);
if (otk1 == OTK_Optional || otk2 == OTK_Optional) {
+ auto canFirst = firstObject->getCanonicalType();
+ auto canSecond = secondObject->getCanonicalType();
+
// Compute the join of the unwrapped type. If there is none, we're done.
- Type unwrappedJoin = join(objectType1 ? objectType1 : First,
- objectType2 ? objectType2 : second);
+ auto unwrappedJoin =
+ join(canFirst ? canFirst : First, canSecond ? canSecond : second);
// FIXME: More general joins of enums need to be handled.
if (!unwrappedJoin)
return First->getASTContext().TheAnyType;
- return OptionalType::get(unwrappedJoin);
+ return OptionalType::get(unwrappedJoin)->getCanonicalType();
}
// FIXME: More general joins of enums need to be handled.
return First->getASTContext().TheAnyType;
}
-Type TypeJoin::visitOptionalType(Type second) {
- auto canFirst = First->getCanonicalType();
- auto canSecond = second->getCanonicalType();
+Type Type::join(Type first, Type second) {
+ assert(first && second && "Unexpected null type!");
- return TypeJoin::join(canFirst, canSecond);
-}
+ if (!first || !second) {
+ if (first)
+ return Type(ErrorType::get(first->getASTContext()));
-Type Type::join(Type type1, Type type2) {
- assert(type1 && type2 && "Unexpected null type!");
+ if (second)
+ return Type(ErrorType::get(second->getASTContext()));
- return TypeJoin::join(type1, type2);
+ return Type();
+ }
+
+ return TypeJoin::join(first->getCanonicalType(), second->getCanonicalType());
}
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index ca99376..16f22e8 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -4341,9 +4341,10 @@
SmallVector<TypeLoc, 4> inheritedTypes;
Type superclassType;
if (decl->getSuperClass()) {
- auto clangSuperclassType =
- Impl.getClangASTContext().getObjCObjectPointerType(
- clang::QualType(decl->getSuperClassType(), 0));
+ clang::QualType clangSuperclassType =
+ decl->getSuperClassType()->stripObjCKindOfTypeAndQuals(clangCtx);
+ clangSuperclassType =
+ clangCtx.getObjCObjectPointerType(clangSuperclassType);
superclassType = Impl.importType(clangSuperclassType,
ImportTypeKind::Abstract,
isInSystemModule(dc),
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index c1b126c..265bbea 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -162,6 +162,18 @@
"-warnings-as-errors", "-suppress-warnings");
}
+ // Check for conflicting profiling flags
+ const Arg *ProfileGenerate = Args.getLastArg(options::OPT_profile_generate);
+ const Arg *ProfileUse = Args.getLastArg(options::OPT_profile_use);
+ if (ProfileGenerate && ProfileUse)
+ diags.diagnose(SourceLoc(), diag::error_conflicting_options,
+ "-profile-generate", "-profile-use");
+
+ // Check if the profdata is missing
+ if (ProfileUse && !llvm::sys::fs::exists(ProfileUse->getValue()))
+ diags.diagnose(SourceLoc(), diag::error_profile_missing,
+ ProfileUse->getValue());
+
// Check for missing debug option when verifying debug info.
if (Args.hasArg(options::OPT_verify_debug_info)) {
bool hasDebugOption = true;
diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp
index f0e03d0..968bf8c 100644
--- a/lib/Driver/ToolChains.cpp
+++ b/lib/Driver/ToolChains.cpp
@@ -144,6 +144,7 @@
inputArgs.AddLastArg(arguments, options::OPT_warn_swift3_objc_inference);
inputArgs.AddLastArg(arguments, options::OPT_suppress_warnings);
inputArgs.AddLastArg(arguments, options::OPT_profile_generate);
+ inputArgs.AddLastArg(arguments, options::OPT_profile_use);
inputArgs.AddLastArg(arguments, options::OPT_profile_coverage_mapping);
inputArgs.AddLastArg(arguments, options::OPT_warnings_as_errors);
inputArgs.AddLastArg(arguments, options::OPT_sanitize_EQ);
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 92ba309..19c3a9f 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -1458,6 +1458,9 @@
Opts.ExternalPassPipelineFilename = A->getValue();
Opts.GenerateProfile |= Args.hasArg(OPT_profile_generate);
+ const Arg *ProfileUse = Args.getLastArg(OPT_profile_use);
+ Opts.UseProfile = ProfileUse ? ProfileUse->getValue() : "";
+
Opts.EmitProfileCoverageMapping |= Args.hasArg(OPT_profile_coverage_mapping);
Opts.EnableGuaranteedClosureContexts |=
Args.hasArg(OPT_enable_guaranteed_closure_contexts);
@@ -1639,6 +1642,9 @@
}
Opts.GenerateProfile |= Args.hasArg(OPT_profile_generate);
+ const Arg *ProfileUse = Args.getLastArg(OPT_profile_use);
+ Opts.UseProfile = ProfileUse ? ProfileUse->getValue() : "";
+
Opts.PrintInlineTree |= Args.hasArg(OPT_print_llvm_inline_tree);
Opts.UseSwiftCall = Args.hasArg(OPT_enable_swiftcall);
diff --git a/lib/IDE/Refactoring.cpp b/lib/IDE/Refactoring.cpp
index f6bba17..3bf103b 100644
--- a/lib/IDE/Refactoring.cpp
+++ b/lib/IDE/Refactoring.cpp
@@ -619,21 +619,17 @@
class TokenBasedRefactoringAction : public RefactoringAction {
protected:
ResolvedCursorInfo CursorInfo;
- bool CanProceed;
public:
TokenBasedRefactoringAction(ModuleDecl *MD, RefactoringOptions &Opts,
SourceEditConsumer &EditConsumer,
DiagnosticConsumer &DiagConsumer) :
RefactoringAction(MD, Opts, EditConsumer, DiagConsumer) {
// We can only proceed with valid location and source file.
- CanProceed = StartLoc.isValid() && TheFile;
- if (!CanProceed)
- return;
-
- // Resolve the sema token and save it for later use.
- CursorInfoResolver Resolver(*TheFile);
- CursorInfo = Resolver.resolve(StartLoc);
- CanProceed = CursorInfo.isValid();
+ if (StartLoc.isValid() && TheFile) {
+ // Resolve the sema token and save it for later use.
+ CursorInfoResolver Resolver(*TheFile);
+ CursorInfo = Resolver.resolve(StartLoc);
+ }
}
};
@@ -644,8 +640,11 @@
SourceEditConsumer &EditConsumer, \
DiagnosticConsumer &DiagConsumer) : \
TokenBasedRefactoringAction(MD, Opts, EditConsumer, DiagConsumer) {} \
- static bool isApplicable(ResolvedCursorInfo Tok); \
bool performChange() override; \
+ static bool isApplicable(ResolvedCursorInfo Tok, DiagnosticEngine &Diag); \
+ bool isApplicable() { \
+ return RefactoringAction##KIND::isApplicable(CursorInfo, DiagEngine) ; \
+ } \
};
#include "swift/IDE/RefactoringKinds.def"
@@ -671,10 +670,14 @@
RangeBasedRefactoringAction(MD, Opts, EditConsumer, DiagConsumer) {} \
bool performChange() override; \
static bool isApplicable(ResolvedRangeInfo Info, DiagnosticEngine &Diag); \
+ bool isApplicable() { \
+ return RefactoringAction##KIND::isApplicable(RangeInfo, DiagEngine) ; \
+ } \
};
#include "swift/IDE/RefactoringKinds.def"
-bool RefactoringActionLocalRename::isApplicable(ResolvedCursorInfo CursorInfo) {
+bool RefactoringActionLocalRename::
+isApplicable(ResolvedCursorInfo CursorInfo, DiagnosticEngine &Diag) {
if (CursorInfo.Kind != CursorInfoKind::ValueRef)
return false;
auto RenameOp = getAvailableRenameForDecl(CursorInfo.ValueD);
@@ -1036,8 +1039,6 @@
}
bool RefactoringActionExtractFunction::performChange() {
- if (!isApplicable(RangeInfo, DiagEngine))
- return true;
// Check if the new name is ok.
if (!Lexer::isIdentifier(PreferredName)) {
DiagEngine.diagnose(SourceLoc(), diag::invalid_name, PreferredName);
@@ -1420,8 +1421,6 @@
}
bool RefactoringActionExtractExpr::performChange() {
- if (!isApplicable(RangeInfo, DiagEngine))
- return true;
return RefactoringActionExtractExprBase(TheFile, RangeInfo,
DiagEngine, false, PreferredName,
EditConsumer).performChange();
@@ -1442,8 +1441,6 @@
}
}
bool RefactoringActionExtractRepeatedExpr::performChange() {
- if (!isApplicable(RangeInfo, DiagEngine))
- return true;
return RefactoringActionExtractExprBase(TheFile, RangeInfo,
DiagEngine, true, PreferredName,
EditConsumer).performChange();
@@ -1523,7 +1520,8 @@
return Walker.IfInfo;
}
-bool RefactoringActionCollapseNestedIfExpr::isApplicable(ResolvedCursorInfo Tok) {
+bool RefactoringActionCollapseNestedIfExpr::
+isApplicable(ResolvedCursorInfo Tok, DiagnosticEngine &Diag) {
return findCollapseNestedIfTarget(Tok).isValid();
}
@@ -1752,22 +1750,17 @@
return NonWitnessedReqs;
}
-bool RefactoringActionFillProtocolStub::isApplicable(ResolvedCursorInfo Tok) {
+bool RefactoringActionFillProtocolStub::
+isApplicable(ResolvedCursorInfo Tok, DiagnosticEngine &Diag) {
return FillProtocolStubContext::getContextFromCursorInfo(Tok).canProceed();
};
bool RefactoringActionFillProtocolStub::performChange() {
- // If the base class says no proceeding, respect it.
- if (!CanProceed)
- return true;
-
// Get the filling protocol context from the input token.
FillProtocolStubContext Context = FillProtocolStubContext::
- getContextFromCursorInfo(CursorInfo);
+ getContextFromCursorInfo(CursorInfo);
- // If the filling context disallows continue, abort.
- if (!Context.canProceed())
- return true;
+ assert(Context.canProceed());
assert(!Context.getFillingContents().empty());
assert(Context.getFillingContext());
llvm::SmallString<128> Text;
@@ -1807,21 +1800,22 @@
return collectAvailableRefactorings(SF, Tok, Scratch, /*Exclude rename*/false);
}
-bool RefactoringActionExpandDefault::isApplicable(ResolvedCursorInfo CursorInfo) {
+bool RefactoringActionExpandDefault::
+isApplicable(ResolvedCursorInfo CursorInfo, DiagnosticEngine &Diag) {
+ auto Exit = [&](bool Applicable) {
+ if (!Applicable)
+ Diag.diagnose(SourceLoc(), diag::invalid_default_location);
+ return Applicable;
+ };
if (CursorInfo.Kind != CursorInfoKind::StmtStart)
- return false;
+ return Exit(false);
if (auto *CS = dyn_cast<CaseStmt>(CursorInfo.TrailingStmt)) {
- return CS->isDefault();
+ return Exit(CS->isDefault());
}
- return false;
+ return Exit(false);
}
bool RefactoringActionExpandDefault::performChange() {
- if (!isApplicable(CursorInfo)) {
- DiagEngine.diagnose(SourceLoc(), diag::invalid_default_location);
- return true;
- }
-
// Try to find the switch statement enclosing the default statement.
auto *CS = static_cast<CaseStmt*>(CursorInfo.TrailingStmt);
auto IsSwitch = [](ASTNode Node) {
@@ -1911,7 +1905,8 @@
return Walker.Target;
}
-bool RefactoringActionLocalizeString::isApplicable(ResolvedCursorInfo Tok) {
+bool RefactoringActionLocalizeString::
+isApplicable(ResolvedCursorInfo Tok, DiagnosticEngine &Diag) {
return findLocalizeTarget(Tok);
}
@@ -1954,7 +1949,8 @@
return ConvertToCharRange(TargetNode.getSourceRange());
}
-bool RefactoringActionConvertToDoCatch::isApplicable(ResolvedCursorInfo Tok) {
+bool RefactoringActionConvertToDoCatch::
+isApplicable(ResolvedCursorInfo Tok, DiagnosticEngine &Diag) {
if (!Tok.TrailingExpr)
return false;
return isa<ForceTryExpr>(Tok.TrailingExpr);
@@ -1962,8 +1958,7 @@
bool RefactoringActionConvertToDoCatch::performChange() {
auto *TryExpr = dyn_cast<ForceTryExpr>(CursorInfo.TrailingExpr);
- if (!TryExpr)
- return true;
+ assert(TryExpr);
auto Range = findSourceRangeToWrapInCatch(CursorInfo, TheFile, SM);
if (!Range.isValid())
return true;
@@ -1973,7 +1968,8 @@
OS << "\n} catch {\n" << getCodePlaceholder() << "\n}";
// Delete ! from try! expression
- auto ExclaimRange = CharSourceRange(TryExpr->getExclaimLoc(), 1);
+ auto ExclaimLen = getKeywordLen(tok::exclaim_postfix);
+ auto ExclaimRange = CharSourceRange(TryExpr->getExclaimLoc(), ExclaimLen);
EditConsumer.accept(SM, ExclaimRange, "");
return false;
}
@@ -2042,7 +2038,7 @@
}
bool RefactoringActionSimplifyNumberLiteral::
-isApplicable(ResolvedCursorInfo Tok) {
+isApplicable(ResolvedCursorInfo Tok, DiagnosticEngine &Diag) {
if (auto *Literal = getTrailingNumberLiteral(Tok)) {
llvm::SmallString<64> Buffer;
llvm::raw_svector_ostream OS(Buffer);
@@ -2257,8 +2253,9 @@
AllKinds.push_back(RenameOp.getValue());
}
}
+ DiagnosticEngine DiagEngine(SF->getASTContext().SourceMgr);
#define CURSOR_REFACTORING(KIND, NAME, ID) \
- if (RefactoringAction##KIND::isApplicable(CursorInfo)) \
+ if (RefactoringAction##KIND::isApplicable(CursorInfo, DiagEngine)) \
AllKinds.push_back(RefactoringKind::KIND);
#include "swift/IDE/RefactoringKinds.def"
@@ -2323,8 +2320,13 @@
switch (Opts.Kind) {
#define SEMANTIC_REFACTORING(KIND, NAME, ID) \
- case RefactoringKind::KIND: return RefactoringAction##KIND(M, Opts, \
- EditConsumer, DiagConsumer).performChange();
+case RefactoringKind::KIND: { \
+ RefactoringAction##KIND Action(M, Opts, EditConsumer, DiagConsumer); \
+ if (RefactoringKind::KIND == RefactoringKind::LocalRename || \
+ Action.isApplicable()) \
+ return Action.performChange(); \
+ return true; \
+ }
#include "swift/IDE/RefactoringKinds.def"
case RefactoringKind::GlobalRename:
case RefactoringKind::FindGlobalRenameRanges:
diff --git a/lib/IDE/SwiftSourceDocInfo.cpp b/lib/IDE/SwiftSourceDocInfo.cpp
index e2215ea..2644a9e 100644
--- a/lib/IDE/SwiftSourceDocInfo.cpp
+++ b/lib/IDE/SwiftSourceDocInfo.cpp
@@ -189,10 +189,15 @@
}
}
auto IsProperCursorLocation = E->getStartLoc() == LocToResolve;
- // Handle cursor placement between try and ! in ForceTryExpr.
+ // Handle cursor placement after `try` in ForceTry and OptionalTry Expr.
+ auto CheckLocation = [&IsProperCursorLocation, this](SourceLoc Loc) {
+ IsProperCursorLocation = Loc == LocToResolve || IsProperCursorLocation;
+ };
if (auto *FTE = dyn_cast<ForceTryExpr>(E)) {
- IsProperCursorLocation = LocToResolve == FTE->getExclaimLoc() ||
- IsProperCursorLocation;
+ CheckLocation(FTE->getExclaimLoc());
+ }
+ if (auto *OTE = dyn_cast<OptionalTryExpr>(E)) {
+ CheckLocation(OTE->getQuestionLoc());
}
// Keep track of trailing expressions.
if (!E->isImplicit() && IsProperCursorLocation)
diff --git a/lib/IDE/SyntaxModel.cpp b/lib/IDE/SyntaxModel.cpp
index d6465b0..d43c0bc 100644
--- a/lib/IDE/SyntaxModel.cpp
+++ b/lib/IDE/SyntaxModel.cpp
@@ -507,10 +507,24 @@
SN.BodyRange = innerCharSourceRangeFromSourceRange(SM, E->getSourceRange());
pushStructureNode(SN, E);
} else if (auto *Tup = dyn_cast<TupleExpr>(E)) {
- for (unsigned I = 0; I < Tup->getNumElements(); ++ I) {
- SourceLoc NameLoc = Tup->getElementNameLoc(I);
- if (NameLoc.isValid())
- passTokenNodesUntil(NameLoc, PassNodesBehavior::ExcludeNodeAtLocation);
+ if (isCurrentCallArgExpr(Tup)) {
+ for (unsigned I = 0; I < Tup->getNumElements(); ++ I) {
+ SourceLoc NameLoc = Tup->getElementNameLoc(I);
+ if (NameLoc.isValid())
+ passTokenNodesUntil(NameLoc, PassNodesBehavior::ExcludeNodeAtLocation);
+ }
+ } else {
+ SyntaxStructureNode SN;
+ SN.Kind = SyntaxStructureKind::TupleExpression;
+ SN.Range = charSourceRangeFromSourceRange(SM, Tup->getSourceRange());
+ SN.BodyRange = innerCharSourceRangeFromSourceRange(SM,
+ Tup->getSourceRange());
+
+ for (auto *Elem : Tup->getElements()) {
+ addExprElem(Elem, SN);
+ }
+
+ pushStructureNode(SN, Tup);
}
}
diff --git a/lib/IDE/TypeReconstruction.cpp b/lib/IDE/TypeReconstruction.cpp
index 78baaf1..927b5ca 100644
--- a/lib/IDE/TypeReconstruction.cpp
+++ b/lib/IDE/TypeReconstruction.cpp
@@ -694,7 +694,7 @@
// and they bear no connection to their original variable at the interface
// level
CanFunctionType swift_can_func_type =
- CanFunctionType::get(AnyFunctionType::CanParamArrayRef({}),
+ CanFunctionType::get(AnyFunctionType::CanParamArrayRef(),
ast->TheRawPointerType,
AnyFunctionType::ExtInfo());
result._types.push_back(swift_can_func_type.getPointer());
diff --git a/lib/IRGen/ClassMetadataVisitor.h b/lib/IRGen/ClassMetadataVisitor.h
index 7d70d2b..a6faa37 100644
--- a/lib/IRGen/ClassMetadataVisitor.h
+++ b/lib/IRGen/ClassMetadataVisitor.h
@@ -105,11 +105,6 @@
}
}
- // Add a reference to the parent class, if applicable.
- if (theClass->getDeclContext()->isTypeContext()) {
- asImpl().addParentMetadataRef(theClass, type);
- }
-
// Add space for the generic parameters, if applicable.
// Note that we only add references for the immediate parameters;
// parameters for the parent context are handled by the parent.
@@ -161,7 +156,6 @@
void addIVarDestroyer() { addPointer(); }
void addValueWitnessTable() { addPointer(); }
void addDestructorFunction() { addPointer(); }
- void addParentMetadataRef(ClassDecl *forClass, Type classType) {addPointer();}
void addSuperClass() { addPointer(); }
void addClassFlags() { addInt32(); }
void addInstanceAddressPoint() { addInt32(); }
diff --git a/lib/IRGen/EnumMetadataVisitor.h b/lib/IRGen/EnumMetadataVisitor.h
index 917c6ca..bc8334a 100644
--- a/lib/IRGen/EnumMetadataVisitor.h
+++ b/lib/IRGen/EnumMetadataVisitor.h
@@ -49,7 +49,6 @@
// EnumMetadata header.
asImpl().addNominalTypeDescriptor();
- asImpl().addParentMetadataRef();
// If changing this layout, you must update the magic number in
// emitParentMetadataRef.
@@ -83,7 +82,6 @@
void addMetadataFlags() { addPointer(); }
void addValueWitnessTable() { addPointer(); }
void addNominalTypeDescriptor() { addPointer(); }
- void addParentMetadataRef() { addPointer(); }
void addGenericArgument(CanType argument) { addPointer(); }
void addGenericWitnessTable(CanType argument, ProtocolConformanceRef conf) {
addPointer();
diff --git a/lib/IRGen/Fulfillment.cpp b/lib/IRGen/Fulfillment.cpp
index 449acb8..739b4f5 100644
--- a/lib/IRGen/Fulfillment.cpp
+++ b/lib/IRGen/Fulfillment.cpp
@@ -70,12 +70,12 @@
case TypeKind::Tuple:
return cast<TupleType>(type)->getNumElements() == 0;
- // Nominal types might have parents.
+ // Nominal types might have generic parents.
case TypeKind::Class:
case TypeKind::Enum:
case TypeKind::Protocol:
case TypeKind::Struct:
- return !cast<NominalType>(type)->getParent();
+ return !cast<NominalType>(type)->getDecl()->isGenericContext();
// Bound generic types have type arguments.
case TypeKind::BoundGenericClass:
@@ -125,14 +125,17 @@
return hadFulfillment;
}
+ if (keys.isInterestingType(type)) {
+ if (auto superclassTy = keys.getSuperclassBound(type)) {
+ return searchNominalTypeMetadata(IGM, superclassTy, source,
+ std::move(path), keys);
+ }
+ }
+
// Inexact metadata will be a problem if we ever try to use this
// to remember that we already have the metadata for something.
- if (auto nomTy = dyn_cast<NominalType>(type)) {
- return searchNominalTypeMetadata(IGM, nomTy, source, std::move(path), keys);
- }
- if (auto boundTy = dyn_cast<BoundGenericType>(type)) {
- return searchBoundGenericTypeMetadata(IGM, boundTy, source,
- std::move(path), keys);
+ if (isa<NominalType>(type) || isa<BoundGenericType>(type)) {
+ return searchNominalTypeMetadata(IGM, type, source, std::move(path), keys);
}
// TODO: tuples
@@ -203,47 +206,27 @@
}
-bool FulfillmentMap::searchParentTypeMetadata(IRGenModule &IGM,
- NominalTypeDecl *decl,
- CanType parent,
- unsigned source,
- MetadataPath &&path,
- const InterestingKeysCallback &keys) {
- // We might not have a parent type.
- if (!parent) return false;
-
- // If we do, it has to be nominal one way or another.
- path.addNominalParentComponent();
- return searchTypeMetadata(IGM, parent, IsExact, source, std::move(path),keys);
-}
-
bool FulfillmentMap::searchNominalTypeMetadata(IRGenModule &IGM,
- CanNominalType type,
+ CanType type,
unsigned source,
MetadataPath &&path,
const InterestingKeysCallback &keys) {
- // Nominal types add no generic arguments themselves, but they
- // may have the arguments of their parents.
- return searchParentTypeMetadata(IGM, type->getDecl(), type.getParent(),
- source, std::move(path), keys);
-}
-
-bool FulfillmentMap::searchBoundGenericTypeMetadata(IRGenModule &IGM,
- CanBoundGenericType type,
- unsigned source,
- MetadataPath &&path,
- const InterestingKeysCallback &keys) {
// Objective-C generics don't preserve their generic parameters at runtime,
// so they aren't able to fulfill type metadata requirements.
- if (type->getDecl()->hasClangNode()) {
+ if (type.getAnyNominal()->hasClangNode()) {
return false;
}
+ auto *nominal = type.getAnyNominal();
+ if (!nominal->isGenericContext() || isa<ProtocolDecl>(nominal)) {
+ return false;
+ }
+
bool hadFulfillment = false;
- GenericTypeRequirements requirements(IGM, type->getDecl());
+ GenericTypeRequirements requirements(IGM, nominal);
requirements.enumerateFulfillments(
- IGM, type->getContextSubstitutionMap(IGM.getSwiftModule(), type->getDecl()),
+ IGM, type->getContextSubstitutionMap(IGM.getSwiftModule(), nominal),
[&](unsigned reqtIndex, CanType arg,
Optional<ProtocolConformanceRef> conf) {
// Skip uninteresting type arguments.
@@ -289,11 +272,6 @@
std::move(argPath), keys, interestingConformances);
});
- // Also match against the parent. The polymorphic type
- // will start with any arguments from the parent.
- hadFulfillment |= searchParentTypeMetadata(IGM, type->getDecl(),
- type.getParent(),
- source, std::move(path), keys);
return hadFulfillment;
}
@@ -318,21 +296,6 @@
}
}
-bool FulfillmentMap::Everything::isInterestingType(CanType type) const {
- return true;
-}
-bool FulfillmentMap::Everything::hasInterestingType(CanType type) const {
- return true;
-}
-bool FulfillmentMap::Everything
- ::hasLimitedInterestingConformances(CanType type) const {
- return false;
-}
-GenericSignature::ConformsToArray
-FulfillmentMap::Everything::getInterestingConformances(CanType type) const{
- return {};
-}
-
void FulfillmentMap::dump() const {
auto &out = llvm::errs();
for (auto &entry : Fulfillments) {
diff --git a/lib/IRGen/Fulfillment.h b/lib/IRGen/Fulfillment.h
index 82b66ba..65737b6 100644
--- a/lib/IRGen/Fulfillment.h
+++ b/lib/IRGen/Fulfillment.h
@@ -66,17 +66,10 @@
virtual GenericSignature::ConformsToArray
getInterestingConformances(CanType type) const = 0;
- virtual ~InterestingKeysCallback() = default;
- };
+ /// Return the limited interesting conformances for an interesting type.
+ virtual CanType getSuperclassBound(CanType type) const = 0;
- /// An implementation of InterestingKeysCallback that returns everything
- /// fulfillable.
- struct Everything : InterestingKeysCallback {
- bool isInterestingType(CanType type) const override;
- bool hasInterestingType(CanType type) const override;
- bool hasLimitedInterestingConformances(CanType type) const override;
- GenericSignature::ConformsToArray
- getInterestingConformances(CanType type) const override;
+ virtual ~InterestingKeysCallback() = default;
};
FulfillmentMap() = default;
@@ -140,19 +133,10 @@
}
private:
- bool searchParentTypeMetadata(IRGenModule &IGM, NominalTypeDecl *typeDecl,
- CanType parent,
- unsigned source, MetadataPath &&path,
- const InterestingKeysCallback &keys);
-
- bool searchNominalTypeMetadata(IRGenModule &IGM, CanNominalType type,
+ bool searchNominalTypeMetadata(IRGenModule &IGM, CanType type,
unsigned source, MetadataPath &&path,
const InterestingKeysCallback &keys);
- bool searchBoundGenericTypeMetadata(IRGenModule &IGM, CanBoundGenericType type,
- unsigned source, MetadataPath &&path,
- const InterestingKeysCallback &keys);
-
/// Search the given witness table for useful fulfillments.
///
/// \return true if any fulfillments were added by this search.
@@ -168,5 +152,3 @@
}
#endif
-
-
diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp
index c2bea3e..fdd329d 100644
--- a/lib/IRGen/GenDecl.cpp
+++ b/lib/IRGen/GenDecl.cpp
@@ -2561,8 +2561,9 @@
NominalTypeDecl *nominal,
ArrayRef<llvm::Type *> genericArgs,
ForDefinition_t forDefinition) {
- assert(!genericArgs.empty());
assert(nominal->isGenericContext());
+ assert(!genericArgs.empty() ||
+ nominal->getGenericSignature()->areAllParamsConcrete());
IRGen.addLazyTypeMetadata(nominal);
auto type = nominal->getDeclaredType()->getCanonicalType();
diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp
index 174a627..2219b15 100644
--- a/lib/IRGen/GenMeta.cpp
+++ b/lib/IRGen/GenMeta.cpp
@@ -142,8 +142,7 @@
static unsigned getNumGenericArguments(IRGenModule &IGM,
NominalTypeDecl *nominal) {
GenericTypeRequirements requirements(IGM, nominal);
- return unsigned(requirements.hasParentType())
- + requirements.getNumTypeRequirements();
+ return requirements.getNumTypeRequirements();
}
void collectTypes(IRGenModule &IGM, NominalTypeDecl *nominal) {
@@ -153,10 +152,6 @@
void collectTypes(IRGenModule &IGM,
const GenericTypeRequirements &requirements) {
- if (requirements.hasParentType()) {
- Types.push_back(IGM.TypeMetadataPtrTy);
- }
-
for (auto &requirement : requirements.getRequirements()) {
if (requirement.Protocol) {
Types.push_back(IGM.WitnessTablePtrTy);
@@ -181,10 +176,6 @@
GenericTypeRequirements requirements(IGF.IGM, decl);
- if (requirements.hasParentType()) {
- Values.push_back(IGF.emitTypeMetadataRef(parentType));
- }
-
auto subs =
type->getContextSubstitutionMap(IGF.IGM.getSwiftModule(), decl);
requirements.enumerateFulfillments(IGF.IGM, subs,
@@ -217,14 +208,6 @@
->getCanonicalType();
};
- // If we have a parent type, it's the first parameter.
- if (requirements.hasParentType()) {
- auto parentType = getInContext(requirements.getParentType());
- llvm::Value *parentMetadata = IGF.Builder.CreateLoad(array);
- array = IGF.Builder.CreateConstArrayGEP(array, 1, IGF.IGM.getPointerSize());
- IGF.bindLocalTypeDataFromTypeMetadata(parentType, IsExact, parentMetadata);
- }
-
// Okay, bind everything else from the context.
requirements.bindFromBuffer(IGF, array, getInContext);
}
@@ -372,7 +355,9 @@
// Grab the substitutions.
GenericArguments genericArgs;
genericArgs.collect(IGF, theType);
- assert(genericArgs.Values.size() > 0 && "no generic args?!");
+ assert((genericArgs.Values.size() > 0 ||
+ theDecl->getGenericSignature()->areAllParamsConcrete())
+ && "no generic args?!");
// Call the generic metadata accessor function.
llvm::Function *accessor =
@@ -1147,7 +1132,9 @@
for (auto &arg : IGF.CurFn->args())
genericArgs.Values.push_back(&arg);
assert(genericArgs.Values.size() == genericArgs.Types.size());
- assert(genericArgs.Values.size() > 0 && "no generic args?!");
+ assert((genericArgs.Values.size() > 0 ||
+ nominal->getGenericSignature()->areAllParamsConcrete())
+ && "no generic args?!");
// Slam that information directly into the generic arguments buffer.
auto argsBufferTy =
@@ -1684,7 +1671,7 @@
// All function types look like () -> ().
// FIXME: It'd be nice not to have to call through the runtime here.
return IGF.emitTypeMetadataRef(
- CanFunctionType::get(AnyFunctionType::CanParamArrayRef({ }),
+ CanFunctionType::get(AnyFunctionType::CanParamArrayRef(),
C.TheEmptyTupleType,
AnyFunctionType::ExtInfo()));
case SILFunctionType::Representation::Block:
@@ -1866,7 +1853,7 @@
case SILFunctionType::Representation::Thick:
// All function types look like () -> ().
return emitFromValueWitnessTable(
- CanFunctionType::get(AnyFunctionType::CanParamArrayRef({}),
+ CanFunctionType::get(AnyFunctionType::CanParamArrayRef(),
C.TheEmptyTupleType,
AnyFunctionType::ExtInfo()));
case SILFunctionType::Representation::Block:
@@ -2184,23 +2171,58 @@
// GenericParameterDescriptorFlags Flags;
GenericParameterDescriptorFlags flags;
- if (ntd->getDeclContext()->isTypeContext())
- flags = flags.withHasParent(true);
- if (requirements.hasParentType())
- flags = flags.withHasGenericParent(true);
if (auto *cd = dyn_cast<ClassDecl>(ntd)) {
auto &layout = IGM.getMetadataLayout(cd);
if (layout.getVTableSize() > 0)
flags = flags.withHasVTable(true);
}
- B.addInt32(flags.getIntValue());
+
+ // Calculate the number of generic parameters at each nesting depth.
+ unsigned totalGenericParams = 0;
+ SmallVector<unsigned, 2> numPrimaryParams;
+ for (auto *outer = ntd; outer != nullptr;
+ outer = outer->getDeclContext()
+ ->getAsNominalTypeOrNominalTypeExtensionContext()) {
+ unsigned genericParamsAtDepth = 0;
+ if (auto *genericParams = outer->getGenericParams()) {
+ for (auto *paramDecl : *genericParams) {
+ auto contextTy = ntd->mapTypeIntoContext(
+ paramDecl->getDeclaredInterfaceType());
+ // Skip parameters which have been made concrete, because they do
+ // not appear in type metadata.
+ //
+ // FIXME: We should emit information about same-type constraints
+ // as well as conformance constraints, so that clients can
+ // reconstruct the full generic signature of the type, including
+ // fully-concrete parameters.
+ if (contextTy->is<ArchetypeType>()) {
+ totalGenericParams++;
+ genericParamsAtDepth++;
+ }
+ }
+ }
+ numPrimaryParams.push_back(genericParamsAtDepth);
+ }
+
+ // This assertion will fail once we have generic types nested
+ // inside generic functions or other local generic contexts.
+ assert(totalGenericParams == requirements.getNumTypeRequirements());
+
+ // Emit the nesting depth.
+ B.addInt16(numPrimaryParams.size());
+
+ // Emit the flags.
+ B.addInt16(flags.getIntValue());
+
+ // Emit the number of generic parameters at each nesting depth.
+ std::reverse(numPrimaryParams.begin(), numPrimaryParams.end());
+ for (auto count : numPrimaryParams)
+ B.addInt32(count);
// TODO: provide reflective descriptions of the type and
// conformance requirements stored here.
-
- // };
}
-
+
llvm::Constant *emit() {
asImpl().layout();
@@ -3487,7 +3509,6 @@
using super = ClassMetadataBuilderBase<ClassMetadataBuilder>;
bool HasUnfilledSuperclass = false;
- bool HasUnfilledParent = false;
Size AddressPoint;
@@ -3534,22 +3555,6 @@
}
}
- void addParentMetadataRef(ClassDecl *forClass, Type classType) {
- CanType parentType = classType->getCanonicalType().getNominalParent();
-
- if (auto metadata =
- tryEmitConstantTypeMetadataRef(IGM, parentType,
- SymbolReferenceKind::Absolute)) {
- B.add(metadata.getValue());
- } else {
- // Leave a null pointer placeholder to be filled by in-place
- // initialization.
- B.addNullPointer(IGM.TypeMetadataPtrTy);
- if (forClass == Target)
- HasUnfilledParent = true;
- }
- }
-
bool canBeConstant() {
// TODO: the metadata global can actually be constant in a very
// special case: it's not a pattern, ObjC interoperation isn't
@@ -3566,7 +3571,7 @@
[&](IRGenFunction &IGF, llvm::Constant *cacheVar) -> llvm::Value* {
// There's an interesting special case where we can do the
// initialization idempotently and thus avoid the need for a lock.
- if (!HasUnfilledSuperclass && !HasUnfilledParent &&
+ if (!HasUnfilledSuperclass &&
isFinishInitializationIdempotent()) {
auto type = Target->getDeclaredType()->getCanonicalType();
auto metadata =
@@ -3604,18 +3609,6 @@
IGF.Builder.CreateStore(superclassMetadata, superField);
}
- // Initialize the class's own parent pointer if it has one and it
- // wasn't emitted as a constant.
- if (HasUnfilledParent) {
- auto parentType = type.getParent();
- assert(parentType);
- llvm::Value *parentMetadata = IGF.emitTypeMetadataRef(parentType);
-
- auto parentSlot =
- emitAddressOfParentMetadataSlot(IGF, metadata, type->getDecl());
- IGF.Builder.CreateStore(parentMetadata, parentSlot);
- }
-
metadata = emitFinishInitializationOfClassMetadata(IGF, metadata);
return metadata;
@@ -3647,12 +3640,6 @@
HasDependentMetadata = true;
}
- void addParentMetadataRef(ClassDecl *forClass, Type classType) {
- CanType parentType = classType->getCanonicalType().getNominalParent();
- this->addFillOp(parentType, None, /*relative*/ false);
- B.addNullPointer(IGM.TypeMetadataPtrTy);
- }
-
void addSuperClass() {
// Filled in by the runtime.
B.addNullPointer(IGM.TypeMetadataPtrTy);
@@ -4362,71 +4349,13 @@
// Value types (structs and enums)
//===----------------------------------------------------------------------===//
-namespace {
- template <class Impl, class Base>
- class ValueTypeMetadataBuilderBase : public Base {
- using super = Base;
-
- protected:
- using super::asImpl;
- using super::IGM;
- using super::Target;
- ConstantStructBuilder &B;
-
- template <class DeclTy>
- ValueTypeMetadataBuilderBase(IRGenModule &IGM, DeclTy *theDecl,
- ConstantStructBuilder &B)
- : super(IGM, theDecl), B(B) {}
-
- CanType getParentType() const {
- Type type = Target->getDeclaredTypeInContext();
- Type parentType = type->getNominalParent();
- if (parentType)
- return parentType->getCanonicalType();
- return CanType();
- }
-
- public:
- void addParentMetadataRef() {
- llvm::Constant *parentMetadata = nullptr;
- if (auto parentType = getParentType()) {
- parentMetadata =
- tryEmitConstantTypeMetadataRef(IGM, parentType,
- SymbolReferenceKind::Absolute)
- .getDirectValue();
- if (!parentMetadata) {
- asImpl().flagUnfilledParent();
- }
- }
-
- if (!parentMetadata)
- parentMetadata = llvm::ConstantPointerNull::get(IGM.TypeMetadataPtrTy);
- B.add(parentMetadata);
- }
- };
-} // end anonymous namespace
-
static llvm::Value *
emitInPlaceValueTypeMetadataInitialization(IRGenFunction &IGF,
CanNominalType type,
- llvm::Value *metadata,
- bool hasUnfilledParent) {
+ llvm::Value *metadata) {
// All the value types are basically similar.
assert(isa<StructType>(type) || isa<EnumType>(type));
- // Initialize the parent-metadata field if it wasn't done statically.
- if (hasUnfilledParent) {
- CanType parentType = type.getParent();
- assert(parentType);
-
- // Value types hold the parent metadata as a far relative
- // indirectable pointer.
- llvm::Value *parentMetadata = IGF.emitTypeMetadataRef(parentType);
- Address addr =
- emitAddressOfParentMetadataSlot(IGF, metadata, type->getDecl());
- IGF.Builder.CreateStore(parentMetadata, addr);
- }
-
// Set up the value witness table if it's dependent.
SILType loweredType = IGF.IGM.getLoweredType(AbstractionPattern(type), type);
auto &ti = IGF.IGM.getTypeInfo(loweredType);
@@ -4445,8 +4374,7 @@
/// Create an access function for the type metadata of the given
/// non-generic nominal type.
static void createInPlaceValueTypeMetadataAccessFunction(IRGenModule &IGM,
- NominalTypeDecl *typeDecl,
- bool hasUnfilledParent) {
+ NominalTypeDecl *typeDecl) {
assert(!typeDecl->isGenericContext());
auto type =
cast<NominalType>(typeDecl->getDeclaredType()->getCanonicalType());
@@ -4456,8 +4384,7 @@
llvm::Constant *cacheVariable) {
return emitInPlaceTypeMetadataAccessFunctionBody(IGF, type, cacheVariable,
[&](IRGenFunction &IGF, llvm::Value *metadata) {
- return emitInPlaceValueTypeMetadataInitialization(IGF, type, metadata,
- hasUnfilledParent);
+ return emitInPlaceValueTypeMetadataInitialization(IGF, type, metadata);
});
});
}
@@ -4469,19 +4396,18 @@
namespace {
/// An adapter for laying out struct metadata.
template <class Impl>
- class StructMetadataBuilderBase
- : public ValueTypeMetadataBuilderBase<Impl,StructMetadataVisitor<Impl>>{
- using super = ValueTypeMetadataBuilderBase<Impl,StructMetadataVisitor<Impl>>;
+ class StructMetadataBuilderBase : public StructMetadataVisitor<Impl> {
+ using super = StructMetadataVisitor<Impl>;
protected:
+ ConstantStructBuilder &B;
using super::IGM;
using super::Target;
using super::asImpl;
- using super::B;
StructMetadataBuilderBase(IRGenModule &IGM, StructDecl *theStruct,
ConstantStructBuilder &B)
- : super(IGM, theStruct, B) {
+ : super(IGM, theStruct), B(B) {
}
public:
@@ -4525,23 +4451,18 @@
class StructMetadataBuilder :
public StructMetadataBuilderBase<StructMetadataBuilder> {
- bool HasUnfilledParent = false;
bool HasUnfilledFieldOffset = false;
public:
StructMetadataBuilder(IRGenModule &IGM, StructDecl *theStruct,
ConstantStructBuilder &B)
: StructMetadataBuilderBase(IGM, theStruct, B) {}
- void flagUnfilledParent() {
- HasUnfilledParent = true;
- }
-
void flagUnfilledFieldOffset() {
HasUnfilledFieldOffset = true;
}
bool canBeConstant() {
- return !HasUnfilledParent && !HasUnfilledFieldOffset;
+ return !HasUnfilledFieldOffset;
}
void addValueWitnessTable() {
@@ -4550,8 +4471,7 @@
}
void createMetadataAccessFunction() {
- createInPlaceValueTypeMetadataAccessFunction(IGM, Target,
- HasUnfilledParent);
+ createInPlaceValueTypeMetadataAccessFunction(IGM, Target);
}
};
@@ -4591,15 +4511,6 @@
{metadataPattern, arguments});
}
- void addParentMetadataRef() {
- // Override to always use a fill op instead of a relocation.
- if (CanType parentType = getParentType()) {
- addFillOp(parentType, None, /*relative*/ false);
- }
-
- B.addInt(IGM.IntPtrTy, 0);
- }
-
void flagUnfilledFieldOffset() {
// We just assume this might happen.
}
@@ -4665,19 +4576,18 @@
namespace {
template<class Impl>
-class EnumMetadataBuilderBase
- : public ValueTypeMetadataBuilderBase<Impl, EnumMetadataVisitor<Impl>> {
- using super = ValueTypeMetadataBuilderBase<Impl, EnumMetadataVisitor<Impl>>;
+class EnumMetadataBuilderBase : public EnumMetadataVisitor<Impl> {
+ using super = EnumMetadataVisitor<Impl>;
protected:
+ ConstantStructBuilder &B;
using super::IGM;
using super::Target;
- using super::B;
public:
EnumMetadataBuilderBase(IRGenModule &IGM, EnumDecl *theEnum,
ConstantStructBuilder &B)
- : super(IGM, theEnum, B) {
+ : super(IGM, theEnum), B(B) {
}
void addMetadataFlags() {
@@ -4705,7 +4615,6 @@
class EnumMetadataBuilder
: public EnumMetadataBuilderBase<EnumMetadataBuilder> {
- bool HasUnfilledParent = false;
bool HasUnfilledPayloadSize = false;
public:
@@ -4733,17 +4642,12 @@
B.addInt(IGM.IntPtrTy, strategy.getPayloadSizeForMetadata());
}
- void flagUnfilledParent() {
- HasUnfilledParent = true;
- }
-
bool canBeConstant() {
- return !HasUnfilledParent && !HasUnfilledPayloadSize;
+ return !HasUnfilledPayloadSize;
}
void createMetadataAccessFunction() {
- createInPlaceValueTypeMetadataAccessFunction(IGM, Target,
- HasUnfilledParent);
+ createInPlaceValueTypeMetadataAccessFunction(IGM, Target);
}
};
@@ -4763,15 +4667,6 @@
{metadataPattern, arguments});
}
- void addParentMetadataRef() {
- // Override to always use a fill op instead of a relocation.
- if (CanType parentType = getParentType()) {
- addFillOp(parentType, None, /*relative*/ false);
- }
-
- B.addInt(IGM.IntPtrTy, 0);
- }
-
void addValueWitnessTable() {
B.add(getValueWitnessTableForGenericValueType(IGM, Target,
HasDependentVWT));
@@ -4905,14 +4800,6 @@
Size AddressPoint = Size::invalid();
- bool computeUnfilledParent() {
- if (auto parentType = asImpl().getTargetType().getNominalParent()) {
- return !tryEmitConstantTypeMetadataRef(IGM, parentType,
- SymbolReferenceKind::Absolute);
- }
- return false;
- }
-
public:
void layout() {
if (asImpl().requiresInitializationFunction())
@@ -5027,41 +4914,25 @@
public ForeignMetadataBuilderBase<ForeignStructMetadataBuilder,
StructMetadataBuilderBase<ForeignStructMetadataBuilder>>
{
- bool HasUnfilledParent = false;
public:
ForeignStructMetadataBuilder(IRGenModule &IGM, StructDecl *target,
ConstantStructBuilder &builder)
- : ForeignMetadataBuilderBase(IGM, target, builder) {
- HasUnfilledParent = computeUnfilledParent();
- }
+ : ForeignMetadataBuilderBase(IGM, target, builder) {}
CanType getTargetType() const {
return Target->getDeclaredType()->getCanonicalType();
}
bool requiresInitializationFunction() const {
- return HasUnfilledParent;
+ return false;
}
- void emitInitialization(IRGenFunction &IGF, llvm::Value *metadata) {
- if (HasUnfilledParent) {
- auto parentType = getTargetType().getNominalParent();
- auto parentMetadata = IGF.emitTypeMetadataRef(parentType);
-
- Address slot =
- emitAddressOfParentMetadataSlot(IGF, metadata, this->Target);
- IGF.Builder.CreateStore(parentMetadata, slot);
- }
- }
+ void emitInitialization(IRGenFunction &IGF, llvm::Value *metadata) {}
void addValueWitnessTable() {
auto type = this->Target->getDeclaredType()->getCanonicalType();
B.add(emitValueWitnessTable(IGM, type));
}
- void flagUnfilledParent() {
- assert(HasUnfilledParent);
- }
-
void flagUnfilledFieldOffset() {
llvm_unreachable("foreign type with non-fixed layout?");
}
@@ -5072,31 +4943,19 @@
public ForeignMetadataBuilderBase<ForeignEnumMetadataBuilder,
EnumMetadataBuilderBase<ForeignEnumMetadataBuilder>>
{
- bool HasUnfilledParent = false;
public:
ForeignEnumMetadataBuilder(IRGenModule &IGM, EnumDecl *target,
ConstantStructBuilder &builder)
- : ForeignMetadataBuilderBase(IGM, target, builder) {
- HasUnfilledParent = computeUnfilledParent();
- }
+ : ForeignMetadataBuilderBase(IGM, target, builder) {}
CanType getTargetType() const {
return Target->getDeclaredType()->getCanonicalType();
}
bool requiresInitializationFunction() const {
- return HasUnfilledParent;
+ return false;
}
- void emitInitialization(IRGenFunction &IGF, llvm::Value *metadata) {
- if (HasUnfilledParent) {
- auto parentType = getTargetType().getNominalParent();
- auto parentMetadata = IGF.emitTypeMetadataRef(parentType);
-
- Address slot =
- emitAddressOfParentMetadataSlot(IGF, metadata, this->Target);
- IGF.Builder.CreateStore(parentMetadata, slot);
- }
- }
+ void emitInitialization(IRGenFunction &IGF, llvm::Value *metadata) {}
void addValueWitnessTable() {
auto type = this->Target->getDeclaredType()->getCanonicalType();
@@ -5106,10 +4965,6 @@
void addPayloadSize() const {
llvm_unreachable("nongeneric enums shouldn't need payload size in metadata");
}
-
- void flagUnfilledParent() {
- assert(HasUnfilledParent);
- }
};
} // end anonymous namespace
diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp
index 7ddf897..3982e34 100644
--- a/lib/IRGen/GenProto.cpp
+++ b/lib/IRGen/GenProto.cpp
@@ -95,6 +95,12 @@
return Generics->getConformsTo(t, M);
}
+ CanType getSuperclassBound(Type t) {
+ if (auto superclassTy = Generics->getSuperclassBound(t, M))
+ return superclassTy->getCanonicalType();
+ return CanType();
+ }
+
public:
PolymorphicConvention(IRGenModule &IGM, CanSILFunctionType fnType);
@@ -291,6 +297,9 @@
getInterestingConformances(CanType type) const override {
return Self.getConformsTo(type);
}
+ CanType getSuperclassBound(CanType type) const override {
+ return Self.getSuperclassBound(type);
+ }
} callbacks(*this);
return Fulfillments.searchTypeMetadata(IGM, type, isExact, sourceIndex,
std::move(path), callbacks);
@@ -367,6 +376,15 @@
return;
}
+ if (isa<GenericTypeParamType>(type)) {
+ if (auto superclassTy = getSuperclassBound(type)) {
+ considerNewTypeSource(MetadataSource::Kind::ClassPointer,
+ paramIndex, superclassTy, IsInexact);
+ return;
+
+ }
+ }
+
// Thick metatypes are sources of metadata.
if (auto metatypeTy = dyn_cast<MetatypeType>(type)) {
if (metatypeTy->getRepresentation() != MetatypeRepresentation::Thick)
@@ -1284,6 +1302,11 @@
getInterestingConformances(CanType type) const override {
llvm_unreachable("no limits");
}
+ CanType getSuperclassBound(CanType type) const override {
+ if (auto superclassTy = cast<ArchetypeType>(type)->getSuperclass())
+ return superclassTy->getCanonicalType();
+ return CanType();
+ }
} callback;
Fulfillments->searchTypeMetadata(IGM, ConcreteType, IsExact,
/*sourceIndex*/ 0, MetadataPath(),
@@ -2023,15 +2046,17 @@
case Component::Kind::NominalTypeArgument:
case Component::Kind::NominalTypeArgumentConformance: {
assert(sourceKey.Kind == LocalTypeDataKind::forTypeMetadata());
- auto generic = cast<BoundGenericType>(sourceKey.Type);
+ auto type = sourceKey.Type;
+ if (auto archetypeTy = dyn_cast<ArchetypeType>(type))
+ type = archetypeTy->getSuperclass()->getCanonicalType();
+ auto *nominal = type.getAnyNominal();
auto reqtIndex = component.getPrimaryIndex();
- GenericTypeRequirements requirements(IGF.IGM, generic->getDecl());
+ GenericTypeRequirements requirements(IGF.IGM, nominal);
auto &requirement = requirements.getRequirements()[reqtIndex];
auto module = IGF.getSwiftModule();
- auto subs = generic->getContextSubstitutionMap(module,
- generic->getDecl());
+ auto subs = sourceKey.Type->getContextSubstitutionMap(module, nominal);
auto sub = requirement.TypeParameter.subst(subs)->getCanonicalType();
// In either case, we need to change the type.
@@ -2041,7 +2066,7 @@
if (component.getKind() == Component::Kind::NominalTypeArgument) {
assert(!requirement.Protocol && "index mismatch!");
if (source) {
- source = emitArgumentMetadataRef(IGF, generic->getDecl(),
+ source = emitArgumentMetadataRef(IGF, nominal,
requirements, reqtIndex, source);
setTypeMetadataName(IGF.IGM, source, sourceKey.Type);
}
@@ -2057,7 +2082,7 @@
if (source) {
auto protocol = conformance.getRequirement();
- source = emitArgumentWitnessTableRef(IGF, generic->getDecl(),
+ source = emitArgumentWitnessTableRef(IGF, nominal,
requirements, reqtIndex, source);
setProtocolWitnessTableName(IGF.IGM, source, sourceKey.Type, protocol);
}
@@ -2066,25 +2091,6 @@
return source;
}
- case Component::Kind::NominalParent: {
- assert(sourceKey.Kind == LocalTypeDataKind::forTypeMetadata());
- NominalTypeDecl *nominalDecl;
- if (auto nominal = dyn_cast<NominalType>(sourceKey.Type)) {
- nominalDecl = nominal->getDecl();
- sourceKey.Type = nominal.getParent();
- } else {
- auto generic = cast<BoundGenericType>(sourceKey.Type);
- nominalDecl = generic->getDecl();
- sourceKey.Type = generic.getParent();
- }
-
- if (source) {
- source = emitParentMetadataRef(IGF, nominalDecl, source);
- setTypeMetadataName(IGF.IGM, source, sourceKey.Type);
- }
- return source;
- }
-
case Component::Kind::OutOfLineBaseProtocol: {
auto conformance = sourceKey.Kind.getProtocolConformance();
auto protocol = conformance.getRequirement();
@@ -2184,9 +2190,6 @@
out << "nominal_type_argument_conformance["
<< component.getPrimaryIndex() << "]";
break;
- case Component::Kind::NominalParent:
- out << "nominal_parent";
- break;
case Component::Kind::Impossible:
out << "impossible";
break;
@@ -2573,28 +2576,9 @@
// Construct a representative function type.
auto generics = ncGenerics->getCanonicalSignature();
CanSILFunctionType fnType = [&]() -> CanSILFunctionType {
- CanType type = typeDecl->getDeclaredInterfaceType()->getCanonicalType();
- if (auto nominal = dyn_cast<NominalType>(type)) {
- ParentType = nominal.getParent();
- } else {
- ParentType = cast<BoundGenericType>(type).getParent();
- }
-
- // Ignore the existence of the parent type if it has no type parameters.
- if (ParentType && !ParentType->hasTypeParameter())
- ParentType = CanType();
-
- SmallVector<SILParameterInfo, 1> params;
- if (ParentType) {
- auto parentMetatype =
- CanMetatypeType::get(ParentType, MetatypeRepresentation::Thick);
- params.push_back(SILParameterInfo(parentMetatype,
- ParameterConvention::Direct_Unowned));
- }
-
return SILFunctionType::get(generics, SILFunctionType::ExtInfo(),
/*callee*/ ParameterConvention::Direct_Unowned,
- params, /*results*/ {}, /*error*/ None,
+ /*params*/ {}, /*results*/ {}, /*error*/ None,
IGM.Context);
}();
diff --git a/lib/IRGen/GenReflection.cpp b/lib/IRGen/GenReflection.cpp
index 5e4d832..f282d27 100644
--- a/lib/IRGen/GenReflection.cpp
+++ b/lib/IRGen/GenReflection.cpp
@@ -71,12 +71,6 @@
OS << '_';
}
- void visitParentMetadataSource(const ParentMetadataSource *P) {
- OS << 'P';
- visit(P->getChild());
- OS << '_';
- }
-
void visitSelfMetadataSource(const SelfMetadataSource *S) {
OS << 'S';
}
@@ -158,13 +152,6 @@
}
void
- visitParentMetadataSource(const ParentMetadataSource *P) {
- printHeader("parent-of");
- printRec(P->getChild());
- closeForm();
- }
-
- void
visitSelfMetadataSource(const SelfMetadataSource *S) {
printHeader("self");
closeForm();
@@ -928,7 +915,7 @@
// extra inhabitants as these. But maybe it's best not to codify
// that in the ABI anyway.
CanType thinFunction = CanFunctionType::get(
- AnyFunctionType::CanParamArrayRef({}), Context.TheEmptyTupleType,
+ AnyFunctionType::CanParamArrayRef(), Context.TheEmptyTupleType,
AnyFunctionType::ExtInfo().withRepresentation(
FunctionTypeRepresentation::Thin));
BuiltinTypes.insert(thinFunction);
diff --git a/lib/IRGen/GenericRequirement.h b/lib/IRGen/GenericRequirement.h
index 9839224..48cdccd 100644
--- a/lib/IRGen/GenericRequirement.h
+++ b/lib/IRGen/GenericRequirement.h
@@ -97,7 +97,6 @@
/// anything fulfillable from its parent type metadata).
class GenericTypeRequirements {
NominalTypeDecl *TheDecl;
- CanType ParentType;
llvm::SmallVector<GenericRequirement, 4> Requirements;
public:
@@ -108,15 +107,6 @@
return Requirements;
}
- /// Does this generic type have
- bool hasParentType() const {
- return bool(ParentType);
- }
-
- CanType getParentType() const {
- return ParentType;
- }
-
/// Return the number of entries required in order to store this data.
unsigned getStorageSizeInWords() const {
return Requirements.size();
diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp
index 707c3b5f..15a9c9f 100644
--- a/lib/IRGen/IRGenModule.cpp
+++ b/lib/IRGen/IRGenModule.cpp
@@ -39,6 +39,7 @@
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/ADT/PointerUnion.h"
@@ -1126,6 +1127,16 @@
emitLazyObjCProtocolDefinitions();
}
+llvm::MDNode *IRGenModule::createProfileWeights(uint64_t TrueCount,
+ uint64_t FalseCount) const {
+ uint64_t MaxWeight = std::max(TrueCount, FalseCount);
+ uint64_t Scale = (MaxWeight > UINT32_MAX) ? UINT32_MAX : 1;
+ uint32_t ScaledTrueCount = (TrueCount / Scale) + 1;
+ uint32_t ScaledFalseCount = (FalseCount / Scale) + 1;
+ llvm::MDBuilder MDHelper(getLLVMContext());
+ return MDHelper.createBranchWeights(ScaledTrueCount, ScaledFalseCount);
+}
+
void IRGenModule::unimplemented(SourceLoc loc, StringRef message) {
Context.Diags.diagnose(loc, diag::irgen_unimplemented, message);
}
diff --git a/lib/IRGen/IRGenModule.h b/lib/IRGen/IRGenModule.h
index a474122..a9ac937 100644
--- a/lib/IRGen/IRGenModule.h
+++ b/lib/IRGen/IRGenModule.h
@@ -1089,6 +1089,12 @@
void emitRuntimeRegistration();
void emitVTableStubs();
void emitTypeVerifier();
+
+ /// Create llvm metadata which encodes the branch weights given by
+ /// \p TrueCount and \p FalseCount.
+ llvm::MDNode *createProfileWeights(uint64_t TrueCount,
+ uint64_t FalseCount) const;
+
private:
void emitGlobalDecl(Decl *D);
};
diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp
index 9252938..a4c0580 100644
--- a/lib/IRGen/IRGenSIL.cpp
+++ b/lib/IRGen/IRGenSIL.cpp
@@ -2179,8 +2179,8 @@
Explosion result;
emission.emitToExplosion(result);
- if (isa<ApplyInst>(i)) {
- setLoweredExplosion(i, result);
+ if (auto apply = dyn_cast<ApplyInst>(i)) {
+ setLoweredExplosion(apply, result);
} else {
auto tryApplyInst = cast<TryApplyInst>(i);
@@ -3062,7 +3062,14 @@
addIncomingSILArgumentsToPHINodes(*this, trueBB, i->getTrueArgs());
addIncomingSILArgumentsToPHINodes(*this, falseBB, i->getFalseArgs());
- Builder.CreateCondBr(condValue, trueBB.bb, falseBB.bb);
+ llvm::MDNode *Weights = nullptr;
+ auto TrueBBCount = i->getTrueBBCount();
+ auto FalseBBCount = i->getFalseBBCount();
+ if (TrueBBCount || FalseBBCount)
+ Weights = IGM.createProfileWeights(TrueBBCount ? TrueBBCount.getValue() : 0,
+ FalseBBCount ? FalseBBCount.getValue() : 0);
+
+ Builder.CreateCondBr(condValue, trueBB.bb, falseBB.bb, Weights);
}
void IRGenSILFunction::visitRetainValueInst(swift::RetainValueInst *i) {
@@ -3456,7 +3463,7 @@
unsigned ArgNo = i->getVarInfo().ArgNo;
emitDebugVariableDeclaration(
emitShadowCopy(Addr, i->getDebugScope(), Name, ArgNo), DbgTy,
- i->getType(), i->getDebugScope(), Decl, Name, ArgNo,
+ SILType(), i->getDebugScope(), Decl, Name, ArgNo,
DbgTy.isImplicitlyIndirect() ? DirectValue : IndirectValue);
}
@@ -3692,8 +3699,7 @@
(void) Decl;
- bool isEntryBlock =
- i->getParentBlock() == i->getFunction()->getEntryBlock();
+ bool isEntryBlock = (i->getParent() == i->getFunction()->getEntryBlock());
auto addr =
type.allocateStack(*this, i->getElementType(), isEntryBlock, dbgname);
diff --git a/lib/IRGen/LoadableByAddress.cpp b/lib/IRGen/LoadableByAddress.cpp
index b338777..181012b 100644
--- a/lib/IRGen/LoadableByAddress.cpp
+++ b/lib/IRGen/LoadableByAddress.cpp
@@ -41,7 +41,7 @@
///
/// TODO: This should be a common utility.
static SILLocation getLocForValue(SILValue value) {
- if (auto *instr = dyn_cast<SILInstruction>(value)) {
+ if (auto *instr = value->getDefiningInstruction()) {
return instr->getLoc();
}
if (auto *arg = dyn_cast<SILArgument>(value)) {
@@ -377,9 +377,9 @@
// All args for which we did a load
llvm::DenseMap<SILValue, SILValue> argsToLoadedValueMap;
// All applies for which we did an alloc
- llvm::DenseMap<SILValue, SILValue> applyRetToAllocMap;
+ llvm::DenseMap<SILInstruction *, SILValue> applyRetToAllocMap;
// recerse map of the one above
- llvm::DenseMap<SILInstruction *, SILValue> allocToApplyRetMap;
+ llvm::DenseMap<SILInstruction *, SILInstruction*> allocToApplyRetMap;
// All call sites with SILArgument that needs to be re-written
// Calls are removed from the set when rewritten.
SmallVector<SILInstruction *, 16> applies;
@@ -392,7 +392,7 @@
// All struct_extract instrs that should be converted to struct_element_addr
SmallVector<StructExtractInst *, 16> structExtractInstsToMod;
// All tuple instructions for which the return type is a function type
- SmallVector<SILInstruction *, 8> tupleInstsToMod;
+ SmallVector<SingleValueInstruction *, 8> tupleInstsToMod;
// All allock stack instructions to modify
SmallVector<AllocStackInst *, 8> allocStackInstsToMod;
// All pointer to address instructions to modify
@@ -401,7 +401,7 @@
SmallVector<RetainValueInst *, 16> retainInstsToMod;
SmallVector<ReleaseValueInst *, 16> releaseInstsToMod;
// All result types instrs for which we need to convert the ResultTy
- llvm::SetVector<SILInstruction *> resultTyInstsToMod;
+ llvm::SetVector<SingleValueInstruction *> resultTyInstsToMod;
// All instructions that use the large struct that are not covered above
SmallVector<SILInstruction *, 16> instsToMod;
// All function-exiting terminators (return or throw instructions).
@@ -443,10 +443,10 @@
void visitStructExtractInst(StructExtractInst *instr);
void visitRetainInst(RetainValueInst *instr);
void visitReleaseInst(ReleaseValueInst *instr);
- void visitResultTyInst(SILInstruction *instr);
+ void visitResultTyInst(SingleValueInstruction *instr);
void visitDebugValueInst(DebugValueInst *instr);
void visitDestroyValueInst(DestroyValueInst *instr);
- void visitTupleInst(SILInstruction *instr);
+ void visitTupleInst(SingleValueInstruction *instr);
void visitAllocStackInst(AllocStackInst *instr);
void visitPointerToAddressInst(PointerToAddressInst *instr);
void visitReturnInst(ReturnInst *instr);
@@ -467,82 +467,82 @@
for (auto &II : *BB) {
SILInstruction *currIns = &II;
switch (currIns->getKind()) {
- case ValueKind::ApplyInst:
- case ValueKind::TryApplyInst:
- case ValueKind::PartialApplyInst: {
+ case SILInstructionKind::ApplyInst:
+ case SILInstructionKind::TryApplyInst:
+ case SILInstructionKind::PartialApplyInst: {
visitApply(ApplySite(currIns));
break;
}
- case ValueKind::ClassMethodInst:
- case ValueKind::SuperMethodInst:
- case ValueKind::DynamicMethodInst:
- case ValueKind::WitnessMethodInst: {
+ case SILInstructionKind::ClassMethodInst:
+ case SILInstructionKind::SuperMethodInst:
+ case SILInstructionKind::DynamicMethodInst:
+ case SILInstructionKind::WitnessMethodInst: {
// TODO Any more instructions to add here?
auto *MI = dyn_cast<MethodInst>(currIns);
visitMethodInst(MI);
break;
}
- case ValueKind::StructExtractInst:
- case ValueKind::StructElementAddrInst:
- case ValueKind::RefTailAddrInst:
- case ValueKind::RefElementAddrInst:
- case ValueKind::BeginAccessInst:
- case ValueKind::EnumInst: {
+ case SILInstructionKind::StructExtractInst:
+ case SILInstructionKind::StructElementAddrInst:
+ case SILInstructionKind::RefTailAddrInst:
+ case SILInstructionKind::RefElementAddrInst:
+ case SILInstructionKind::BeginAccessInst:
+ case SILInstructionKind::EnumInst: {
// TODO Any more instructions to add here?
- visitResultTyInst(currIns);
+ visitResultTyInst(cast<SingleValueInstruction>(currIns));
break;
}
- case ValueKind::StoreInst: {
+ case SILInstructionKind::StoreInst: {
auto *SI = dyn_cast<StoreInst>(currIns);
visitStoreInst(SI);
break;
}
- case ValueKind::RetainValueInst: {
+ case SILInstructionKind::RetainValueInst: {
auto *RETI = dyn_cast<RetainValueInst>(currIns);
visitRetainInst(RETI);
break;
}
- case ValueKind::ReleaseValueInst: {
+ case SILInstructionKind::ReleaseValueInst: {
auto *RELI = dyn_cast<ReleaseValueInst>(currIns);
visitReleaseInst(RELI);
break;
}
- case ValueKind::DebugValueInst: {
+ case SILInstructionKind::DebugValueInst: {
auto *DI = dyn_cast<DebugValueInst>(currIns);
visitDebugValueInst(DI);
break;
}
- case ValueKind::DestroyValueInst: {
+ case SILInstructionKind::DestroyValueInst: {
auto *DI = dyn_cast<DestroyValueInst>(currIns);
visitDestroyValueInst(DI);
break;
}
- case ValueKind::SwitchEnumInst: {
+ case SILInstructionKind::SwitchEnumInst: {
auto *SEI = dyn_cast<SwitchEnumInst>(currIns);
visitSwitchEnumInst(SEI);
break;
}
- case ValueKind::TupleElementAddrInst:
- case ValueKind::TupleExtractInst: {
- visitTupleInst(currIns);
+ case SILInstructionKind::TupleElementAddrInst:
+ case SILInstructionKind::TupleExtractInst: {
+ visitTupleInst(cast<SingleValueInstruction>(currIns));
break;
}
- case ValueKind::AllocStackInst: {
+ case SILInstructionKind::AllocStackInst: {
auto *ASI = dyn_cast<AllocStackInst>(currIns);
visitAllocStackInst(ASI);
break;
}
- case ValueKind::PointerToAddressInst: {
+ case SILInstructionKind::PointerToAddressInst: {
auto *PTA = dyn_cast<PointerToAddressInst>(currIns);
visitPointerToAddressInst(PTA);
break;
}
- case ValueKind::ReturnInst: {
+ case SILInstructionKind::ReturnInst: {
auto *RI = dyn_cast<ReturnInst>(currIns);
visitReturnInst(RI);
break;
}
- case ValueKind::DeallocStackInst: {
+ case SILInstructionKind::DeallocStackInst: {
auto *DI = dyn_cast<DeallocStackInst>(currIns);
visitDeallocInst(DI);
break;
@@ -748,7 +748,7 @@
}
}
-void LargeValueVisitor::visitResultTyInst(SILInstruction *instr) {
+void LargeValueVisitor::visitResultTyInst(SingleValueInstruction *instr) {
GenericEnvironment *genEnv = instr->getFunction()->getGenericEnvironment();
auto loweredTy = instr->getFunction()->getLoweredFunctionType();
if (!genEnv && loweredTy->isPolymorphic()) {
@@ -767,7 +767,7 @@
}
}
-void LargeValueVisitor::visitTupleInst(SILInstruction *instr) {
+void LargeValueVisitor::visitTupleInst(SingleValueInstruction *instr) {
SILType currSILType = instr->getType().getObjectType();
CanType currCanType = currSILType.getSwiftRValueType();
if (auto funcType = dyn_cast<SILFunctionType>(currCanType)) {
@@ -853,7 +853,7 @@
void convertIndirectBasicBlockArgs();
void convertApplyResults();
void allocateForArg(SILValue value);
- AllocStackInst *allocateForApply(SILValue value, SILType type);
+ AllocStackInst *allocateForApply(SILInstruction *apply, SILType type);
SILArgument *replaceArgType(SILBuilder &argBuilder, SILArgument *arg,
SILType newSILType);
};
@@ -889,49 +889,49 @@
for (auto *user : optimizableLoad->getUses()) {
SILInstruction *userIns = user->getUser();
switch (userIns->getKind()) {
- case ValueKind::CopyAddrInst:
- case ValueKind::DeallocStackInst:
+ case SILInstructionKind::CopyAddrInst:
+ case SILInstructionKind::DeallocStackInst:
break;
- case ValueKind::ApplyInst:
- case ValueKind::TryApplyInst:
- case ValueKind::PartialApplyInst: {
+ case SILInstructionKind::ApplyInst:
+ case SILInstructionKind::TryApplyInst:
+ case SILInstructionKind::PartialApplyInst: {
if (std::find(pass.applies.begin(), pass.applies.end(), userIns) ==
pass.applies.end()) {
pass.applies.push_back(userIns);
}
break;
}
- case ValueKind::RetainValueInst: {
+ case SILInstructionKind::RetainValueInst: {
auto *insToInsert = dyn_cast<RetainValueInst>(userIns);
assert(insToInsert && "Unexpected cast failure");
pass.retainInstsToMod.push_back(insToInsert);
break;
}
- case ValueKind::ReleaseValueInst: {
+ case SILInstructionKind::ReleaseValueInst: {
auto *insToInsert = dyn_cast<ReleaseValueInst>(userIns);
assert(insToInsert && "Unexpected cast failure");
pass.releaseInstsToMod.push_back(insToInsert);
break;
}
- case ValueKind::StoreInst: {
+ case SILInstructionKind::StoreInst: {
auto *insToInsert = dyn_cast<StoreInst>(userIns);
assert(insToInsert && "Unexpected cast failure");
pass.storeInstsToMod.push_back(insToInsert);
break;
}
- case ValueKind::DebugValueInst: {
+ case SILInstructionKind::DebugValueInst: {
auto *insToInsert = dyn_cast<DebugValueInst>(userIns);
assert(insToInsert && "Unexpected cast failure");
pass.debugInstsToMod.push_back(insToInsert);
break;
}
- case ValueKind::DestroyValueInst: {
+ case SILInstructionKind::DestroyValueInst: {
auto *insToInsert = dyn_cast<DestroyValueInst>(userIns);
assert(insToInsert && "Unexpected cast failure");
pass.destroyValueInstsToMod.push_back(insToInsert);
break;
}
- case ValueKind::StructExtractInst: {
+ case SILInstructionKind::StructExtractInst: {
auto *instToInsert = dyn_cast<StructExtractInst>(userIns);
if (std::find(pass.structExtractInstsToMod.begin(),
pass.structExtractInstsToMod.end(),
@@ -940,7 +940,7 @@
}
break;
}
- case ValueKind::SwitchEnumInst: {
+ case SILInstructionKind::SwitchEnumInst: {
auto *instToInsert = dyn_cast<SwitchEnumInst>(userIns);
if (std::find(pass.switchEnumInstsToMod.begin(),
pass.switchEnumInstsToMod.end(),
@@ -963,9 +963,9 @@
for (auto *user : unoptimizableLoad->getUses()) {
SILInstruction *userIns = user->getUser();
switch (userIns->getKind()) {
- case ValueKind::ApplyInst:
- case ValueKind::TryApplyInst:
- case ValueKind::PartialApplyInst: {
+ case SILInstructionKind::ApplyInst:
+ case SILInstructionKind::TryApplyInst:
+ case SILInstructionKind::PartialApplyInst: {
ApplySite site(userIns);
SILValue callee = site.getCallee();
if (callee == unoptimizableLoad) {
@@ -1017,12 +1017,12 @@
for (auto *user : unoptimizableLoad->getUses()) {
SILInstruction *userIns = user->getUser();
switch (userIns->getKind()) {
- case ValueKind::CopyAddrInst:
- case ValueKind::DeallocStackInst:
+ case SILInstructionKind::CopyAddrInst:
+ case SILInstructionKind::DeallocStackInst:
break;
- case ValueKind::ApplyInst:
- case ValueKind::TryApplyInst:
- case ValueKind::PartialApplyInst: {
+ case SILInstructionKind::ApplyInst:
+ case SILInstructionKind::TryApplyInst:
+ case SILInstructionKind::PartialApplyInst: {
ApplySite site(userIns);
if (!modifiableApply(site, pass.Mod)) {
break;
@@ -1049,48 +1049,48 @@
usersToMod.push_back(user);
break;
}
- case ValueKind::RetainValueInst: {
+ case SILInstructionKind::RetainValueInst: {
auto *insToInsert = dyn_cast<RetainValueInst>(userIns);
assert(insToInsert && "Unexpected cast failure");
pass.retainInstsToMod.push_back(insToInsert);
usersToMod.push_back(user);
break;
}
- case ValueKind::ReleaseValueInst: {
+ case SILInstructionKind::ReleaseValueInst: {
auto *insToInsert = dyn_cast<ReleaseValueInst>(userIns);
assert(insToInsert && "Unexpected cast failure");
pass.releaseInstsToMod.push_back(insToInsert);
usersToMod.push_back(user);
break;
}
- case ValueKind::StoreInst: {
+ case SILInstructionKind::StoreInst: {
auto *insToInsert = dyn_cast<StoreInst>(userIns);
assert(insToInsert && "Unexpected cast failure");
pass.storeInstsToMod.push_back(insToInsert);
usersToMod.push_back(user);
break;
}
- case ValueKind::DebugValueInst: {
+ case SILInstructionKind::DebugValueInst: {
auto *insToInsert = dyn_cast<DebugValueInst>(userIns);
assert(insToInsert && "Unexpected cast failure");
pass.debugInstsToMod.push_back(insToInsert);
usersToMod.push_back(user);
break;
}
- case ValueKind::DestroyValueInst: {
+ case SILInstructionKind::DestroyValueInst: {
auto *insToInsert = dyn_cast<DestroyValueInst>(userIns);
assert(insToInsert && "Unexpected cast failure");
pass.destroyValueInstsToMod.push_back(insToInsert);
usersToMod.push_back(user);
break;
}
- case ValueKind::StructExtractInst: {
+ case SILInstructionKind::StructExtractInst: {
auto *instToInsert = dyn_cast<StructExtractInst>(userIns);
pass.structExtractInstsToMod.push_back(instToInsert);
usersToMod.push_back(user);
break;
}
- case ValueKind::SwitchEnumInst: {
+ case SILInstructionKind::SwitchEnumInst: {
auto *instToInsert = dyn_cast<SwitchEnumInst>(userIns);
pass.switchEnumInstsToMod.push_back(instToInsert);
usersToMod.push_back(user);
@@ -1234,7 +1234,7 @@
if (!ApplySite::isa(currIns)) {
continue;
}
- if (dyn_cast<PartialApplyInst>(currIns)) {
+ if (isa<PartialApplyInst>(currIns)) {
continue;
}
auto applySite = ApplySite(currIns);
@@ -1263,8 +1263,10 @@
}
auto newSILType = getNewSILType(genEnv, resultStorageType, pass.Mod);
auto *newVal = allocateForApply(currIns, newSILType.getObjectType());
- currIns->replaceAllUsesWith(newVal);
- if (auto tryApplyIns = dyn_cast<TryApplyInst>(currIns)) {
+ if (auto apply = dyn_cast<ApplyInst>(currIns)) {
+ apply->replaceAllUsesWith(newVal);
+ } else {
+ auto tryApplyIns = cast<TryApplyInst>(currIns);
auto *normalBB = tryApplyIns->getNormalBB();
SILBuilder argBuilder(normalBB->begin());
assert(normalBB->getNumArguments() == 1 &&
@@ -1338,8 +1340,7 @@
assert(pass.allocToApplyRetMap.find(allocInstr) !=
pass.allocToApplyRetMap.end() &&
"Alloc is not for apply results");
- auto *applyInst =
- dyn_cast<SILInstruction>(pass.allocToApplyRetMap[allocInstr]);
+ auto *applyInst = pass.allocToApplyRetMap[allocInstr];
assert(applyInst && "Value is not an apply");
auto II = applyInst->getIterator();
SILBuilder loadBuilder(II);
@@ -1388,14 +1389,15 @@
}
}
-AllocStackInst *LoadableStorageAllocation::allocateForApply(SILValue value,
- SILType type) {
+AllocStackInst *
+LoadableStorageAllocation::allocateForApply(SILInstruction *apply,
+ SILType type) {
SILBuilder allocBuilder(pass.F->begin()->begin());
- auto *allocInstr = allocBuilder.createAllocStack(getLocForValue(value), type);
+ auto *allocInstr = allocBuilder.createAllocStack(apply->getLoc(), type);
pass.largeLoadableArgs.push_back(allocInstr);
- pass.allocToApplyRetMap[allocInstr] = value;
- pass.applyRetToAllocMap[value] = allocInstr;
+ pass.allocToApplyRetMap[allocInstr] = apply;
+ pass.applyRetToAllocMap[apply] = allocInstr;
for (TermInst *termInst : pass.returnInsts) {
SILBuilder deallocBuilder(termInst);
@@ -1429,7 +1431,7 @@
private:
llvm::SetVector<SILFunction *> modFuncs;
- llvm::SetVector<SILInstruction *> conversionInstrs;
+ llvm::SetVector<SingleValueInstruction *> conversionInstrs;
llvm::SetVector<BuiltinInst *> builtinInstrs;
llvm::SetVector<LoadInst *> loadInstrsOfFunc;
llvm::SetVector<UncheckedEnumDataInst *> uncheckedEnumDataOfFunc;
@@ -1437,7 +1439,7 @@
uncheckedTakeEnumDataAddrOfFunc;
llvm::SetVector<StoreInst *> storeToBlockStorageInstrs;
llvm::DenseSet<SILInstruction *> modApplies;
- llvm::DenseMap<SILValue, SILValue> allApplyRetToAllocMap;
+ llvm::DenseMap<SILInstruction *, SILValue> allApplyRetToAllocMap;
};
} // end anonymous namespace
@@ -1462,14 +1464,13 @@
SILBuilder copyBuilder(storeUser);
SILValue tgt = storeUser->getDest();
createOutlinedCopyCall(copyBuilder, allocInstr, tgt, pass);
- storeUser->replaceAllUsesWith(tgt);
- storeUser->getParent()->erase(storeUser);
+ storeUser->eraseFromParent();
}
}
}
static void allocateAndSetForInstrOperand(StructLoweringState &pass,
- SILInstruction *instrOperand) {
+ SingleValueInstruction *instrOperand){
assert(instrOperand->getType().isObject());
SILBuilder allocBuilder(pass.F->begin()->begin());
AllocStackInst *allocInstr = allocBuilder.createAllocStack(
@@ -1535,21 +1536,21 @@
setInstrUsers(pass, allocInstr, value, store);
}
-static bool allUsesAreReplaceable(SILInstruction *instr,
+static bool allUsesAreReplaceable(SingleValueInstruction *instr,
irgen::IRGenModule &Mod) {
bool allUsesAreReplaceable = true;
for (auto *user : instr->getUses()) {
SILInstruction *userIns = user->getUser();
switch (userIns->getKind()) {
- case ValueKind::RetainValueInst:
- case ValueKind::ReleaseValueInst:
- case ValueKind::StoreInst:
- case ValueKind::DebugValueInst:
- case ValueKind::DestroyValueInst:
+ case SILInstructionKind::RetainValueInst:
+ case SILInstructionKind::ReleaseValueInst:
+ case SILInstructionKind::StoreInst:
+ case SILInstructionKind::DebugValueInst:
+ case SILInstructionKind::DestroyValueInst:
break;
- case ValueKind::ApplyInst:
- case ValueKind::TryApplyInst:
- case ValueKind::PartialApplyInst: {
+ case SILInstructionKind::ApplyInst:
+ case SILInstructionKind::TryApplyInst:
+ case SILInstructionKind::PartialApplyInst: {
// Replaceable only if it is not the function pointer
ApplySite site(userIns);
if (!modifiableApply(site, Mod)) {
@@ -1573,8 +1574,8 @@
}
break;
}
- case ValueKind::StructExtractInst:
- case ValueKind::SwitchEnumInst: {
+ case SILInstructionKind::StructExtractInst:
+ case SILInstructionKind::SwitchEnumInst: {
break;
}
default:
@@ -1584,7 +1585,7 @@
return allUsesAreReplaceable;
}
-static void castTupleInstr(SILInstruction *instr, IRGenModule &Mod) {
+static void castTupleInstr(SingleValueInstruction *instr, IRGenModule &Mod) {
SILType currSILType = instr->getType().getObjectType();
CanType currCanType = currSILType.getSwiftRValueType();
SILFunctionType *funcType = dyn_cast<SILFunctionType>(currCanType);
@@ -1601,15 +1602,15 @@
auto II = instr->getIterator();
++II;
SILBuilder castBuilder(II);
- SILInstruction *castInstr = nullptr;
+ SingleValueInstruction *castInstr = nullptr;
switch (instr->getKind()) {
// Add cast to the new sil function type:
- case ValueKind::TupleExtractInst: {
+ case SILInstructionKind::TupleExtractInst: {
castInstr = castBuilder.createUncheckedBitCast(instr->getLoc(), instr,
newSILType.getObjectType());
break;
}
- case ValueKind::TupleElementAddrInst: {
+ case SILInstructionKind::TupleElementAddrInst: {
castInstr = castBuilder.createUncheckedAddrCast(
instr->getLoc(), instr, newSILType.getAddressType());
break;
@@ -1725,9 +1726,8 @@
}
SILBasicBlock *defaultBB =
instr->hasDefault() ? instr->getDefaultBB() : nullptr;
- auto *newInstr = enumBuilder.createSwitchEnumAddr(
+ enumBuilder.createSwitchEnumAddr(
instr->getLoc(), copiedValue, defaultBB, caseBBs);
- instr->replaceAllUsesWith(newInstr);
instr->getParent()->erase(instr);
}
@@ -1780,8 +1780,7 @@
SILValue currOperand = operand.get();
SILType silType = currOperand->getType();
if (isLargeLoadableType(genEnv, silType, pass.Mod)) {
- SILInstruction *currOperandInstr =
- dyn_cast<SILInstruction>(currOperand);
+ auto currOperandInstr = dyn_cast<SingleValueInstruction>(currOperand);
// Get its storage location as a new operand
if (!currOperandInstr) {
allocateAndSetForArgumentOperand(pass, currOperand, applyInst);
@@ -1826,7 +1825,7 @@
}
}
- for (SILInstruction *instr : pass.tupleInstsToMod) {
+ for (SingleValueInstruction *instr : pass.tupleInstsToMod) {
castTupleInstr(instr, pass.Mod);
}
@@ -1896,71 +1895,68 @@
SILBuilder copyBuilder(instr);
createOutlinedCopyCall(copyBuilder, src, tgt, pass);
- instr->replaceAllUsesWith(tgt);
instr->getParent()->erase(instr);
}
for (RetainValueInst *instr : pass.retainInstsToMod) {
SILBuilder retainBuilder(instr);
- auto *newInstr = retainBuilder.createRetainValueAddr(
+ retainBuilder.createRetainValueAddr(
instr->getLoc(), instr->getOperand(), instr->getAtomicity());
- instr->replaceAllUsesWith(newInstr);
instr->getParent()->erase(instr);
}
for (ReleaseValueInst *instr : pass.releaseInstsToMod) {
SILBuilder releaseBuilder(instr);
- auto *newInstr = releaseBuilder.createReleaseValueAddr(
+ releaseBuilder.createReleaseValueAddr(
instr->getLoc(), instr->getOperand(), instr->getAtomicity());
- instr->replaceAllUsesWith(newInstr);
instr->getParent()->erase(instr);
}
- for (SILInstruction *instr : pass.resultTyInstsToMod) {
+ for (SingleValueInstruction *instr : pass.resultTyInstsToMod) {
// Update the return type of these instrs
// Note: The operand was already updated!
SILType currSILType = instr->getType().getObjectType();
SILType newSILType = getNewSILType(genEnv, currSILType, pass.Mod);
SILBuilder resultTyBuilder(instr);
SILLocation Loc = instr->getLoc();
- SILInstruction *newInstr = nullptr;
+ SingleValueInstruction *newInstr = nullptr;
switch (instr->getKind()) {
- case ValueKind::StructExtractInst: {
- auto *convInstr = dyn_cast<StructExtractInst>(instr);
+ case SILInstructionKind::StructExtractInst: {
+ auto *convInstr = cast<StructExtractInst>(instr);
newInstr = resultTyBuilder.createStructExtract(
Loc, convInstr->getOperand(), convInstr->getField(),
newSILType.getObjectType());
break;
}
- case ValueKind::StructElementAddrInst: {
- auto *convInstr = dyn_cast<StructElementAddrInst>(instr);
+ case SILInstructionKind::StructElementAddrInst: {
+ auto *convInstr = cast<StructElementAddrInst>(instr);
newInstr = resultTyBuilder.createStructElementAddr(
Loc, convInstr->getOperand(), convInstr->getField(),
newSILType.getAddressType());
break;
}
- case ValueKind::RefTailAddrInst: {
- auto *convInstr = dyn_cast<RefTailAddrInst>(instr);
+ case SILInstructionKind::RefTailAddrInst: {
+ auto *convInstr = cast<RefTailAddrInst>(instr);
newInstr = resultTyBuilder.createRefTailAddr(Loc, convInstr->getOperand(),
newSILType.getAddressType());
break;
}
- case ValueKind::RefElementAddrInst: {
- auto *convInstr = dyn_cast<RefElementAddrInst>(instr);
+ case SILInstructionKind::RefElementAddrInst: {
+ auto *convInstr = cast<RefElementAddrInst>(instr);
newInstr = resultTyBuilder.createRefElementAddr(
Loc, convInstr->getOperand(), convInstr->getField(),
newSILType.getAddressType());
break;
}
- case ValueKind::BeginAccessInst: {
- auto *convInstr = dyn_cast<BeginAccessInst>(instr);
+ case SILInstructionKind::BeginAccessInst: {
+ auto *convInstr = cast<BeginAccessInst>(instr);
newInstr = resultTyBuilder.createBeginAccess(Loc, convInstr->getOperand(),
convInstr->getAccessKind(),
convInstr->getEnforcement());
break;
}
- case ValueKind::EnumInst: {
- auto *convInstr = dyn_cast<EnumInst>(instr);
+ case SILInstructionKind::EnumInst: {
+ auto *convInstr = cast<EnumInst>(instr);
SILValue operand =
convInstr->hasOperand() ? convInstr->getOperand() : SILValue();
newInstr = resultTyBuilder.createEnum(
@@ -1971,7 +1967,7 @@
llvm_unreachable("Unhandled aggrTy instr");
}
instr->replaceAllUsesWith(newInstr);
- instr->getParent()->erase(instr);
+ instr->eraseFromParent();
}
for (MethodInst *instr : pass.methodInstsToMod) {
@@ -1993,19 +1989,19 @@
MethodInst *newInstr = nullptr;
switch (instr->getKind()) {
- case ValueKind::ClassMethodInst: {
+ case SILInstructionKind::ClassMethodInst: {
SILValue selfValue = instr->getOperand(0);
newInstr = methodBuilder.createClassMethod(loc, selfValue, member,
newSILType, isVolatile);
break;
}
- case ValueKind::SuperMethodInst: {
+ case SILInstructionKind::SuperMethodInst: {
SILValue selfValue = instr->getOperand(0);
newInstr = methodBuilder.createSuperMethod(loc, selfValue, member,
newSILType, isVolatile);
break;
}
- case ValueKind::DynamicMethodInst: {
+ case SILInstructionKind::DynamicMethodInst: {
auto *DMI = dyn_cast<DynamicMethodInst>(instr);
assert(DMI && "ValueKind is Witness Method but dyn_cast failed");
SILValue selfValue = instr->getOperand(0);
@@ -2013,7 +2009,7 @@
newSILType, isVolatile);
break;
}
- case ValueKind::WitnessMethodInst: {
+ case SILInstructionKind::WitnessMethodInst: {
auto *WMI = dyn_cast<WitnessMethodInst>(instr);
assert(WMI && "ValueKind is Witness Method but dyn_cast failed");
newInstr = methodBuilder.createWitnessMethod(
@@ -2045,7 +2041,7 @@
auto IIR = instr->getReverseIterator();
for (++IIR; IIR != instr->getParent()->rend(); ++IIR) {
auto *currIIInstr = &(*IIR);
- if (currIIInstr->getKind() != ValueKind::DeallocStackInst) {
+ if (currIIInstr->getKind() != SILInstructionKind::DeallocStackInst) {
// got the right location - stop.
--IIR;
break;
@@ -2068,9 +2064,8 @@
auto emptyTy = retBuilder.getModule().Types.getLoweredType(
TupleType::getEmpty(retBuilder.getModule().getASTContext()));
auto newRetTuple = retBuilder.createTuple(regLoc, emptyTy, {});
- auto newRet = retBuilder.createReturn(newRetTuple->getLoc(), newRetTuple);
- instr->replaceAllUsesWith(newRet);
- instr->getParent()->erase(instr);
+ retBuilder.createReturn(newRetTuple->getLoc(), newRetTuple);
+ instr->eraseFromParent();
}
}
@@ -2222,11 +2217,10 @@
// Collect common info
ApplySite applySite = ApplySite(applyInst);
SILValue callee = applySite.getCallee();
- if (ApplySite::isa(callee)) {
+ if (auto site = ApplySite::isa(callee)) {
// We need to re-create the callee's apply before recreating this one
// else verification will fail with wrong SubstCalleeType
- auto calleInstr = dyn_cast<SILInstruction>(callee);
- assert(calleInstr && "Expected ApplySite Instr");
+ auto calleInstr = site.getInstruction();
if (modApplies.find(calleInstr) != modApplies.end()) {
recreateSingleApply(calleInstr);
modApplies.erase(calleInstr);
@@ -2252,12 +2246,12 @@
// If we turned a direct result into an indirect parameter
// Find the new alloc we created earlier.
// and pass it as first parameter:
- if (applyInst->getKind() != ValueKind::PartialApplyInst &&
+ if (applyInst->getKind() != SILInstructionKind::PartialApplyInst &&
modResultType(genEnv, origCanType, *currIRMod) &&
modifiableApply(applySite, *getIRGenModule())) {
assert(allApplyRetToAllocMap.find(applyInst) !=
allApplyRetToAllocMap.end());
- auto newAlloc = allApplyRetToAllocMap[applyInst];
+ auto newAlloc = allApplyRetToAllocMap.find(applyInst)->second;
callArgs.push_back(newAlloc);
}
SmallVector<Substitution, 4> newSubs =
@@ -2270,39 +2264,35 @@
callArgs.push_back(currOperand);
}
// Recreate apply with new operands due to substitution-type cache
- SILInstruction *newApply = nullptr;
switch (applyInst->getKind()) {
- case ValueKind::ApplyInst: {
- auto *castedApply = dyn_cast<ApplyInst>(applyInst);
- assert(castedApply && "ValueKind is ApplyInst but cast to it failed");
- newApply = applyBuilder.createApply(castedApply->getLoc(), callee, newSubs,
- callArgs, castedApply->isNonThrowing());
- applyInst->replaceAllUsesWith(newApply);
+ case SILInstructionKind::ApplyInst: {
+ auto *castedApply = cast<ApplyInst>(applyInst);
+ SILValue newApply =
+ applyBuilder.createApply(castedApply->getLoc(), callee, newSubs,
+ callArgs, castedApply->isNonThrowing());
+ castedApply->replaceAllUsesWith(newApply);
break;
}
- case ValueKind::TryApplyInst: {
- auto *castedApply = dyn_cast<TryApplyInst>(applyInst);
- assert(castedApply && "ValueKind is TryApplyInst but cast to it failed");
- newApply = applyBuilder.createTryApply(
+ case SILInstructionKind::TryApplyInst: {
+ auto *castedApply = cast<TryApplyInst>(applyInst);
+ applyBuilder.createTryApply(
castedApply->getLoc(), callee, newSubs, callArgs,
castedApply->getNormalBB(), castedApply->getErrorBB());
- applyInst->replaceAllUsesWith(newApply);
break;
}
- case ValueKind::PartialApplyInst: {
- auto *castedApply = dyn_cast<PartialApplyInst>(applyInst);
- assert(castedApply &&
- "ValueKind is PartialApplyInst but cast to it failed");
+ case SILInstructionKind::PartialApplyInst: {
+ auto *castedApply = cast<PartialApplyInst>(applyInst);
// Change the type of the Closure
auto partialApplyConvention = castedApply->getType()
.getSwiftRValueType()
->getAs<SILFunctionType>()
->getCalleeConvention();
- newApply = applyBuilder.createPartialApply(castedApply->getLoc(), callee,
- newSubs, callArgs,
- partialApplyConvention);
- applyInst->replaceAllUsesWith(newApply);
+ auto newApply =
+ applyBuilder.createPartialApply(castedApply->getLoc(), callee,
+ newSubs, callArgs,
+ partialApplyConvention);
+ castedApply->replaceAllUsesWith(newApply);
break;
}
default:
@@ -2351,7 +2341,7 @@
SILType newType = getNewSILType(genEnv, origType, *currIRMod);
auto caseTy = enumInstr->getOperand()->getType().getEnumElementType(
enumInstr->getElement(), F->getModule());
- SILInstruction *newInstr = nullptr;
+ SingleValueInstruction *newInstr = nullptr;
if (caseTy != newType) {
auto *takeEnum = enumBuilder.createUncheckedEnumData(
enumInstr->getLoc(), enumInstr->getOperand(), enumInstr->getElement(),
@@ -2385,7 +2375,7 @@
SILType newType = getNewSILType(genEnv, origType, *currIRMod);
auto caseTy = enumInstr->getOperand()->getType().getEnumElementType(
enumInstr->getElement(), F->getModule());
- SILInstruction *newInstr = nullptr;
+ SingleValueInstruction *newInstr = nullptr;
if (caseTy != origType.getObjectType()) {
auto *takeEnum = enumBuilder.createUncheckedTakeEnumDataAddr(
enumInstr->getLoc(), enumInstr->getOperand(), enumInstr->getElement(),
@@ -2405,9 +2395,7 @@
void LoadableByAddress::fixStoreToBlockStorageInstrs() {
for (auto *instr : storeToBlockStorageInstrs) {
auto dest = instr->getDest();
- ProjectBlockStorageInst *destBlock =
- dyn_cast<ProjectBlockStorageInst>(dest);
- assert(destBlock && "Expected Block Storage dest");
+ auto destBlock = cast<ProjectBlockStorageInst>(dest);
SILType destType = destBlock->getType();
auto src = instr->getSrc();
SILType srcType = src->getType();
@@ -2447,28 +2435,23 @@
SILType newType =
getNewSILFunctionType(genEnv, currSILFunctionType, *currIRMod);
SILBuilder convBuilder(convInstr);
- SILInstruction *newInstr = nullptr;
+ SingleValueInstruction *newInstr = nullptr;
switch (convInstr->getKind()) {
- case ValueKind::ThinToThickFunctionInst: {
- ThinToThickFunctionInst *instr =
- dyn_cast<ThinToThickFunctionInst>(convInstr);
- assert(instr && "Unexpected conversion instruction");
+ case SILInstructionKind::ThinToThickFunctionInst: {
+ auto instr = cast<ThinToThickFunctionInst>(convInstr);
newInstr = convBuilder.createThinToThickFunction(
instr->getLoc(), instr->getOperand(), newType);
break;
}
- case ValueKind::ThinFunctionToPointerInst: {
- ThinFunctionToPointerInst *instr =
- dyn_cast<ThinFunctionToPointerInst>(convInstr);
- assert(instr && "Unexpected conversion instruction");
+ case SILInstructionKind::ThinFunctionToPointerInst: {
+ auto instr = cast<ThinFunctionToPointerInst>(convInstr);
newType = getNewSILType(genEnv, instr->getType(), *getIRGenModule());
newInstr = convBuilder.createThinFunctionToPointer(
instr->getLoc(), instr->getOperand(), newType);
break;
}
- case ValueKind::ConvertFunctionInst: {
- auto *instr = dyn_cast<ConvertFunctionInst>(convInstr);
- assert(instr && "Unexpected conversion instruction");
+ case SILInstructionKind::ConvertFunctionInst: {
+ auto instr = cast<ConvertFunctionInst>(convInstr);
newInstr = convBuilder.createConvertFunction(
instr->getLoc(), instr->getOperand(), newType);
break;
@@ -2549,26 +2532,27 @@
for (auto *user : FRI->getUses()) {
SILInstruction *currInstr = user->getUser();
switch (currInstr->getKind()) {
- case ValueKind::ApplyInst:
- case ValueKind::TryApplyInst:
- case ValueKind::PartialApplyInst: {
+ case SILInstructionKind::ApplyInst:
+ case SILInstructionKind::TryApplyInst:
+ case SILInstructionKind::PartialApplyInst: {
if (modApplies.count(currInstr) == 0) {
modApplies.insert(currInstr);
}
break;
}
- case ValueKind::ThinFunctionToPointerInst:
- case ValueKind::ThinToThickFunctionInst: {
- conversionInstrs.insert(currInstr);
+ case SILInstructionKind::ThinFunctionToPointerInst:
+ case SILInstructionKind::ThinToThickFunctionInst: {
+ conversionInstrs.insert(
+ cast<SingleValueInstruction>(currInstr));
break;
}
- case ValueKind::BuiltinInst: {
- auto *instr = dyn_cast<BuiltinInst>(currInstr);
+ case SILInstructionKind::BuiltinInst: {
+ auto *instr = cast<BuiltinInst>(currInstr);
builtinInstrs.insert(instr);
break;
}
- case ValueKind::DebugValueAddrInst:
- case ValueKind::DebugValueInst: {
+ case SILInstructionKind::DebugValueAddrInst:
+ case SILInstructionKind::DebugValueInst: {
break;
}
default:
diff --git a/lib/IRGen/LocalTypeData.cpp b/lib/IRGen/LocalTypeData.cpp
index 3deddfb..fe2fc05 100644
--- a/lib/IRGen/LocalTypeData.cpp
+++ b/lib/IRGen/LocalTypeData.cpp
@@ -254,12 +254,34 @@
CanType type,
IsExact_t isExact,
llvm::Value *metadata) {
+ struct Callback : FulfillmentMap::InterestingKeysCallback {
+ bool isInterestingType(CanType type) const override {
+ return true;
+ }
+ bool hasInterestingType(CanType type) const override {
+ return true;
+ }
+ bool hasLimitedInterestingConformances(CanType type) const override {
+ return false;
+ }
+ GenericSignature::ConformsToArray
+ getInterestingConformances(CanType type) const override {
+ llvm_unreachable("no limits");
+ }
+ CanType getSuperclassBound(CanType type) const override {
+ if (auto arch = dyn_cast<ArchetypeType>(type))
+ if (auto superclassTy = arch->getSuperclass())
+ return superclassTy->getCanonicalType();
+ return CanType();
+ }
+ } callbacks;
+
// Look for anything at all that's fulfilled by this. If we don't find
// anything, stop.
FulfillmentMap fulfillments;
if (!fulfillments.searchTypeMetadata(IGF.IGM, type, isExact,
/*source*/ 0, MetadataPath(),
- FulfillmentMap::Everything())) {
+ callbacks)) {
return;
}
diff --git a/lib/IRGen/MetadataLayout.cpp b/lib/IRGen/MetadataLayout.cpp
index 8fde127..fcda034 100644
--- a/lib/IRGen/MetadataLayout.cpp
+++ b/lib/IRGen/MetadataLayout.cpp
@@ -126,12 +126,6 @@
/******************************* NOMINAL TYPES ********************************/
-Offset NominalMetadataLayout::getParentOffset(IRGenFunction &IGF) const {
- assert(Parent.isValid());
- assert(Parent.isStatic() && "resilient metadata layout unsupported!");
- return Offset(Parent.getStaticOffset());
-}
-
Size
NominalMetadataLayout::getStaticGenericRequirementsOffset() const {
assert(GenericRequirements.isValid());
@@ -146,24 +140,6 @@
return Offset(GenericRequirements.getStaticOffset());
}
-/// Given a reference to some metadata, derive a reference to the
-/// type's parent type.
-llvm::Value *irgen::emitParentMetadataRef(IRGenFunction &IGF,
- NominalTypeDecl *decl,
- llvm::Value *metadata) {
- auto slot = emitAddressOfParentMetadataSlot(IGF, metadata, decl);
- return IGF.emitInvariantLoad(slot);
-}
-
-Address irgen::emitAddressOfParentMetadataSlot(IRGenFunction &IGF,
- llvm::Value *metadata,
- NominalTypeDecl *decl) {
- auto offset = IGF.IGM.getMetadataLayout(decl).getParentOffset(IGF);
- return IGF.emitAddressAtOffset(metadata, offset,
- IGF.IGM.TypeMetadataPtrTy,
- IGF.IGM.getPointerAlignment());
-}
-
static llvm::Value *emitLoadOfGenericRequirement(IRGenFunction &IGF,
llvm::Value *metadata,
NominalTypeDecl *decl,
@@ -246,12 +222,6 @@
super::addInstanceAlignMask();
}
- void addParentMetadataRef(ClassDecl *forClass, Type classType) {
- if (forClass == Target)
- Layout.Parent = getNextOffset();
- super::addParentMetadataRef(forClass, classType);
- }
-
void noteStartOfGenericRequirements(ClassDecl *forClass) {
if (forClass == Target)
Layout.GenericRequirements = getNextOffset();
@@ -404,11 +374,6 @@
super::addPayloadSize();
}
- void addParentMetadataRef() {
- Layout.Parent = getNextOffset();
- super::addParentMetadataRef();
- }
-
void noteStartOfGenericRequirements() {
Layout.GenericRequirements = getNextOffset();
super::noteStartOfGenericRequirements();
@@ -441,11 +406,6 @@
Scanner(IRGenModule &IGM, StructDecl *decl, StructMetadataLayout &layout)
: super(IGM, decl), Layout(layout) {}
- void addParentMetadataRef() {
- Layout.Parent = getNextOffset();
- super::addParentMetadataRef();
- }
-
void noteStartOfGenericRequirements() {
Layout.GenericRequirements = getNextOffset();
super::noteStartOfGenericRequirements();
diff --git a/lib/IRGen/MetadataLayout.h b/lib/IRGen/MetadataLayout.h
index 1c817ad..42ec292 100644
--- a/lib/IRGen/MetadataLayout.h
+++ b/lib/IRGen/MetadataLayout.h
@@ -120,7 +120,6 @@
class NominalMetadataLayout : public MetadataLayout {
protected:
StoredOffset GenericRequirements;
- StoredOffset Parent;
NominalMetadataLayout(Kind kind) : MetadataLayout(kind) {}
@@ -134,8 +133,6 @@
Offset getGenericRequirementsOffset(IRGenFunction &IGF) const;
- Offset getParentOffset(IRGenFunction &IGF) const;
-
static bool classof(const MetadataLayout *layout) {
return true; // No non-nominal metadata for now.
}
@@ -287,11 +284,6 @@
}
};
-/// Emit the address of the 'parent' slot in the given nominal-type metadata.
-Address emitAddressOfParentMetadataSlot(IRGenFunction &IGF,
- llvm::Value *metadata,
- NominalTypeDecl *decl);
-
/// Emit the address of the field-offset slot in the given class metadata.
Address emitAddressOfClassFieldOffset(IRGenFunction &IGF,
llvm::Value *metadata,
diff --git a/lib/IRGen/MetadataPath.h b/lib/IRGen/MetadataPath.h
index 001cae0..0dd1566 100644
--- a/lib/IRGen/MetadataPath.h
+++ b/lib/IRGen/MetadataPath.h
@@ -61,9 +61,6 @@
// Everything past this point has no index.
- /// The parent metadata of a nominal type.
- NominalParent,
-
/// An impossible path.
Impossible,
};
@@ -102,7 +99,6 @@
case Kind::OutOfLineBaseProtocol:
case Kind::NominalTypeArgumentConformance:
case Kind::NominalTypeArgument:
- case Kind::NominalParent:
return OperationCost::Load;
case Kind::AssociatedConformance:
@@ -144,11 +140,6 @@
Path.push_back(Component(Component::Kind::Impossible));
}
- /// Add a step to this path which gets the parent metadata.
- void addNominalParentComponent() {
- Path.push_back(Component(Component::Kind::NominalParent));
- }
-
/// Add a step to this path which gets the type metadata stored at
/// requirement index n in a generic type metadata.
void addNominalTypeArgumentComponent(unsigned index) {
@@ -208,9 +199,6 @@
for (auto C : Path) {
switch (C.getKind()) {
- case Component::Kind::NominalParent:
- Root = A.createParent(Root);
- continue;
case Component::Kind::NominalTypeArgument:
Root = A.createGenericArgument(C.getPrimaryIndex(), Root);
continue;
diff --git a/lib/IRGen/NominalMetadataVisitor.h b/lib/IRGen/NominalMetadataVisitor.h
index 214032f..3944a4e 100644
--- a/lib/IRGen/NominalMetadataVisitor.h
+++ b/lib/IRGen/NominalMetadataVisitor.h
@@ -67,8 +67,7 @@
GenericTypeRequirements requirements(IGM, typeDecl);
if (requirements.empty()) return;
- auto subs = type->castTo<BoundGenericType>()
- ->getContextSubstitutionMap(IGM.getSwiftModule(),
+ auto subs = type->getContextSubstitutionMap(IGM.getSwiftModule(),
typeDecl);
requirements.enumerateFulfillments(IGM, subs,
[&](unsigned reqtIndex, CanType argType,
diff --git a/lib/IRGen/StructMetadataVisitor.h b/lib/IRGen/StructMetadataVisitor.h
index 3910b75..17dc558 100644
--- a/lib/IRGen/StructMetadataVisitor.h
+++ b/lib/IRGen/StructMetadataVisitor.h
@@ -47,7 +47,6 @@
// StructMetadata header.
asImpl().addNominalTypeDescriptor();
- asImpl().addParentMetadataRef();
// If changing this layout, you must update the magic number in
// emitParentMetadataRef.
@@ -80,7 +79,6 @@
void addMetadataFlags() { addPointer(); }
void addValueWitnessTable() { addPointer(); }
void addNominalTypeDescriptor() { addPointer(); }
- void addParentMetadataRef() { addPointer(); }
void addFieldOffset(VarDecl*) { addPointer(); }
void addGenericArgument(CanType argument) { addPointer(); }
void addGenericWitnessTable(CanType argument, ProtocolConformanceRef conf) {
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index c7b950c..79565bb 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -579,7 +579,12 @@
ParserResult<BraceStmt> Parser::parseBraceItemList(Diag<> ID) {
if (Tok.isNot(tok::l_brace)) {
diagnose(Tok, ID);
- return nullptr;
+
+ // Attempt to recover by looking for a left brace on the same line
+ while (Tok.isNot(tok::eof, tok::l_brace) && !Tok.isAtStartOfLine())
+ skipSingle();
+ if (Tok.isNot(tok::l_brace))
+ return nullptr;
}
SourceLoc LBLoc = consumeToken(tok::l_brace);
diff --git a/lib/ParseSIL/ParseSIL.cpp b/lib/ParseSIL/ParseSIL.cpp
index 0e1526f..f389d26 100644
--- a/lib/ParseSIL/ParseSIL.cpp
+++ b/lib/ParseSIL/ParseSIL.cpp
@@ -352,7 +352,7 @@
SourceLoc Tmp;
return parseTypedValueRef(Result, Tmp, B);
}
- bool parseSILOpcode(ValueKind &Opcode, SourceLoc &OpcodeLoc,
+ bool parseSILOpcode(SILInstructionKind &Opcode, SourceLoc &OpcodeLoc,
StringRef &OpcodeName);
bool parseSILDebugVar(SILDebugVariable &Var);
@@ -365,7 +365,7 @@
bool parsedComma = false);
bool parseSILInstruction(SILBuilder &B);
bool parseCallInstruction(SILLocation InstLoc,
- ValueKind Opcode, SILBuilder &B,
+ SILInstructionKind Opcode, SILBuilder &B,
SILInstruction *&ResultVal);
bool parseSILFunctionRef(SILLocation InstLoc, SILFunction *&ResultFn);
@@ -1389,16 +1389,16 @@
/// getInstructionKind - This method maps the string form of a SIL instruction
/// opcode to an enum.
-bool SILParser::parseSILOpcode(ValueKind &Opcode, SourceLoc &OpcodeLoc,
+bool SILParser::parseSILOpcode(SILInstructionKind &Opcode, SourceLoc &OpcodeLoc,
StringRef &OpcodeName) {
OpcodeLoc = P.Tok.getLoc();
OpcodeName = P.Tok.getText();
// Parse this textually to avoid Swift keywords (like 'return') from
// interfering with opcode recognition.
- Optional<ValueKind> MaybeOpcode =
- llvm::StringSwitch<Optional<ValueKind>>(OpcodeName)
-#define INST(Id, Parent, TextualName, MemBehavior, MayRelease) \
- .Case(#TextualName, ValueKind::Id)
+ Optional<SILInstructionKind> MaybeOpcode =
+ llvm::StringSwitch<Optional<SILInstructionKind>>(OpcodeName)
+#define FULL_INST(Id, TextualName, Parent, MemBehavior, MayRelease) \
+ .Case(#TextualName, SILInstructionKind::Id)
#include "swift/SIL/SILNodes.def"
.Default(None);
@@ -1815,19 +1815,46 @@
return true;
}
- StringRef ResultName;
- SourceLoc ResultNameLoc;
+ SmallVector<std::pair<StringRef, SourceLoc>, 4> resultNames;
+ SourceLoc resultClauseBegin;
// If the instruction has a name '%foo =', parse it.
if (P.Tok.is(tok::sil_local_name)) {
- ResultName = P.Tok.getText();
- ResultNameLoc = P.Tok.getLoc();
+ resultClauseBegin = P.Tok.getLoc();
+ resultNames.push_back(std::make_pair(P.Tok.getText(), P.Tok.getLoc()));
P.consumeToken(tok::sil_local_name);
+
+ // If the instruction has a '(%foo, %bar) = ', parse it.
+ } else if (P.consumeIf(tok::l_paren)) {
+ resultClauseBegin = P.PreviousLoc;
+
+ if (!P.consumeIf(tok::r_paren)) {
+ while (true) {
+ if (!P.Tok.is(tok::sil_local_name)) {
+ P.diagnose(P.Tok, diag::expected_sil_value_name);
+ return true;
+ }
+
+ resultNames.push_back(std::make_pair(P.Tok.getText(), P.Tok.getLoc()));
+ P.consumeToken(tok::sil_local_name);
+
+ if (P.consumeIf(tok::comma))
+ continue;
+ if (P.consumeIf(tok::r_paren))
+ break;
+
+ P.diagnose(P.Tok, diag::expected_tok_in_sil_instr, ",");
+ return true;
+ }
+ }
+ }
+
+ if (resultClauseBegin.isValid()) {
if (P.parseToken(tok::equal, diag::expected_equal_in_sil_instr))
return true;
}
-
- ValueKind Opcode;
+
+ SILInstructionKind Opcode;
SourceLoc OpcodeLoc;
StringRef OpcodeName;
@@ -1895,12 +1922,7 @@
// opcode we find.
SILInstruction *ResultVal;
switch (Opcode) {
- case ValueKind::SILPHIArgument:
- case ValueKind::SILFunctionArgument:
- case ValueKind::SILUndef:
- llvm_unreachable("not an instruction");
-
- case ValueKind::AllocBoxInst: {
+ case SILInstructionKind::AllocBoxInst: {
SILType Ty;
if (parseSILType(Ty)) return true;
SILDebugVariable VarInfo;
@@ -1911,13 +1933,13 @@
ResultVal = B.createAllocBox(InstLoc, Ty.castTo<SILBoxType>(), VarInfo);
break;
}
- case ValueKind::ApplyInst:
- case ValueKind::PartialApplyInst:
- case ValueKind::TryApplyInst:
+ case SILInstructionKind::ApplyInst:
+ case SILInstructionKind::PartialApplyInst:
+ case SILInstructionKind::TryApplyInst:
if (parseCallInstruction(InstLoc, Opcode, B, ResultVal))
return true;
break;
- case ValueKind::IntegerLiteralInst: {
+ case SILInstructionKind::IntegerLiteralInst: {
SILType Ty;
if (parseSILType(Ty) ||
P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ","))
@@ -1955,7 +1977,7 @@
ResultVal = B.createIntegerLiteral(InstLoc, Ty, value);
break;
}
- case ValueKind::FloatLiteralInst: {
+ case SILInstructionKind::FloatLiteralInst: {
SILType Ty;
if (parseSILType(Ty) ||
P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ","))
@@ -1988,7 +2010,7 @@
P.consumeToken(tok::integer_literal);
break;
}
- case ValueKind::StringLiteralInst: {
+ case SILInstructionKind::StringLiteralInst: {
if (P.Tok.getKind() != tok::identifier) {
P.diagnose(P.Tok, diag::sil_string_no_encoding);
return true;
@@ -2025,7 +2047,7 @@
break;
}
- case ValueKind::ConstStringLiteralInst: {
+ case SILInstructionKind::ConstStringLiteralInst: {
if (P.Tok.getKind() != tok::identifier) {
P.diagnose(P.Tok, diag::sil_string_no_encoding);
return true;
@@ -2060,7 +2082,7 @@
break;
}
- case ValueKind::AllocValueBufferInst: {
+ case SILInstructionKind::AllocValueBufferInst: {
SILType Ty;
if (parseSILType(Ty) ||
parseVerbatim("in") ||
@@ -2070,7 +2092,7 @@
ResultVal = B.createAllocValueBuffer(InstLoc, Ty, Val);
break;
}
- case ValueKind::ProjectValueBufferInst: {
+ case SILInstructionKind::ProjectValueBufferInst: {
SILType Ty;
if (parseSILType(Ty) ||
parseVerbatim("in") ||
@@ -2080,7 +2102,7 @@
ResultVal = B.createProjectValueBuffer(InstLoc, Ty, Val);
break;
}
- case ValueKind::DeallocValueBufferInst: {
+ case SILInstructionKind::DeallocValueBufferInst: {
SILType Ty;
if (parseSILType(Ty) ||
parseVerbatim("in") ||
@@ -2091,7 +2113,7 @@
break;
}
- case ValueKind::ProjectBoxInst: {
+ case SILInstructionKind::ProjectBoxInst: {
if (parseTypedValueRef(Val, B) ||
P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ","))
return true;
@@ -2114,7 +2136,7 @@
break;
}
- case ValueKind::ProjectExistentialBoxInst: {
+ case SILInstructionKind::ProjectExistentialBoxInst: {
SILType Ty;
if (parseSILType(Ty) ||
parseVerbatim("in") ||
@@ -2125,7 +2147,7 @@
break;
}
- case ValueKind::FunctionRefInst: {
+ case SILInstructionKind::FunctionRefInst: {
SILFunction *Fn;
if (parseSILFunctionRef(InstLoc, Fn) ||
parseSILDebugLocation(InstLoc, B))
@@ -2133,7 +2155,7 @@
ResultVal = B.createFunctionRef(InstLoc, Fn);
break;
}
- case ValueKind::BuiltinInst: {
+ case SILInstructionKind::BuiltinInst: {
if (P.Tok.getKind() != tok::string_literal) {
P.diagnose(P.Tok, diag::expected_tok_in_sil_instr,"builtin name");
return true;
@@ -2208,7 +2230,7 @@
ResultVal = B.createBuiltin(InstLoc, Id, ResultTy, subs, Args);
break;
}
- case ValueKind::OpenExistentialAddrInst:
+ case SILInstructionKind::OpenExistentialAddrInst:
if (parseOpenExistAddrKind() || parseTypedValueRef(Val, B)
|| parseVerbatim("to") || parseSILType(Ty)
|| parseSILDebugLocation(InstLoc, B))
@@ -2217,7 +2239,7 @@
ResultVal = B.createOpenExistentialAddr(InstLoc, Val, Ty, AccessKind);
break;
- case ValueKind::OpenExistentialBoxInst:
+ case SILInstructionKind::OpenExistentialBoxInst:
if (parseTypedValueRef(Val, B) || parseVerbatim("to") || parseSILType(Ty)
|| parseSILDebugLocation(InstLoc, B))
return true;
@@ -2225,28 +2247,28 @@
ResultVal = B.createOpenExistentialBox(InstLoc, Val, Ty);
break;
- case ValueKind::OpenExistentialBoxValueInst:
+ case SILInstructionKind::OpenExistentialBoxValueInst:
if (parseTypedValueRef(Val, B) || parseVerbatim("to") || parseSILType(Ty)
|| parseSILDebugLocation(InstLoc, B))
return true;
ResultVal = B.createOpenExistentialBoxValue(InstLoc, Val, Ty);
break;
- case ValueKind::OpenExistentialMetatypeInst:
+ case SILInstructionKind::OpenExistentialMetatypeInst:
if (parseTypedValueRef(Val, B) || parseVerbatim("to") || parseSILType(Ty)
|| parseSILDebugLocation(InstLoc, B))
return true;
ResultVal = B.createOpenExistentialMetatype(InstLoc, Val, Ty);
break;
- case ValueKind::OpenExistentialRefInst:
+ case SILInstructionKind::OpenExistentialRefInst:
if (parseTypedValueRef(Val, B) || parseVerbatim("to") || parseSILType(Ty)
|| parseSILDebugLocation(InstLoc, B))
return true;
ResultVal = B.createOpenExistentialRef(InstLoc, Val, Ty);
break;
- case ValueKind::OpenExistentialValueInst:
+ case SILInstructionKind::OpenExistentialValueInst:
if (parseTypedValueRef(Val, B) || parseVerbatim("to") || parseSILType(Ty)
|| parseSILDebugLocation(InstLoc, B))
return true;
@@ -2254,14 +2276,14 @@
break;
#define UNARY_INSTRUCTION(ID) \
- case ValueKind::ID##Inst: \
+ case SILInstructionKind::ID##Inst: \
if (parseTypedValueRef(Val, B)) return true; \
if (parseSILDebugLocation(InstLoc, B)) return true; \
ResultVal = B.create##ID(InstLoc, Val); \
break;
#define REFCOUNTING_INSTRUCTION(ID) \
- case ValueKind::ID##Inst: { \
+ case SILInstructionKind::ID##Inst: { \
Atomicity atomicity = Atomicity::Atomic; \
StringRef Optional; \
if (parseSILOptional(Optional, *this)) { \
@@ -2308,14 +2330,14 @@
#undef UNARY_INSTRUCTION
#undef REFCOUNTING_INSTRUCTION
- case ValueKind::DebugValueInst:
- case ValueKind::DebugValueAddrInst: {
+ case SILInstructionKind::DebugValueInst:
+ case SILInstructionKind::DebugValueAddrInst: {
SILDebugVariable VarInfo;
if (parseTypedValueRef(Val, B) ||
parseSILDebugVar(VarInfo) ||
parseSILDebugLocation(InstLoc, B))
return true;
- if (Opcode == ValueKind::DebugValueInst)
+ if (Opcode == SILInstructionKind::DebugValueInst)
ResultVal = B.createDebugValue(InstLoc, Val, VarInfo);
else
ResultVal = B.createDebugValueAddr(InstLoc, Val, VarInfo);
@@ -2323,7 +2345,7 @@
}
// unchecked_ownership_conversion <reg> : <type>, <ownership> to <ownership>
- case ValueKind::UncheckedOwnershipConversionInst: {
+ case SILInstructionKind::UncheckedOwnershipConversionInst: {
ValueOwnershipKind LHSKind = ValueOwnershipKind::Any;
ValueOwnershipKind RHSKind = ValueOwnershipKind::Any;
SourceLoc Loc;
@@ -2345,7 +2367,7 @@
break;
}
- case ValueKind::LoadInst: {
+ case SILInstructionKind::LoadInst: {
LoadOwnershipQualifier Qualifier;
SourceLoc AddrLoc;
@@ -2357,7 +2379,7 @@
break;
}
- case ValueKind::LoadBorrowInst: {
+ case SILInstructionKind::LoadBorrowInst: {
SourceLoc AddrLoc;
if (parseTypedValueRef(Val, AddrLoc, B) || parseSILDebugLocation(InstLoc, B))
@@ -2367,7 +2389,7 @@
break;
}
- case ValueKind::BeginBorrowInst: {
+ case SILInstructionKind::BeginBorrowInst: {
SourceLoc AddrLoc;
if (parseTypedValueRef(Val, AddrLoc, B) || parseSILDebugLocation(InstLoc, B))
@@ -2377,8 +2399,8 @@
break;
}
- case ValueKind::LoadUnownedInst:
- case ValueKind::LoadWeakInst: {
+ case SILInstructionKind::LoadUnownedInst:
+ case SILInstructionKind::LoadWeakInst: {
bool isTake = false;
SourceLoc addrLoc;
if (parseSILOptional(isTake, *this, "take") ||
@@ -2386,7 +2408,7 @@
parseSILDebugLocation(InstLoc, B))
return true;
- if (Opcode == ValueKind::LoadUnownedInst) {
+ if (Opcode == SILInstructionKind::LoadUnownedInst) {
if (!Val->getType().is<UnownedStorageType>()) {
P.diagnose(addrLoc, diag::sil_operand_not_unowned_address, "source",
OpcodeName);
@@ -2404,7 +2426,7 @@
break;
}
- case ValueKind::MarkDependenceInst: {
+ case SILInstructionKind::MarkDependenceInst: {
SILValue Base;
if (parseTypedValueRef(Val, B) ||
parseVerbatim("on") ||
@@ -2416,7 +2438,7 @@
break;
}
- case ValueKind::KeyPathInst: {
+ case SILInstructionKind::KeyPathInst: {
SmallVector<KeyPathPatternComponent, 4> components;
SILType Ty;
if (parseSILType(Ty)
@@ -2762,28 +2784,28 @@
}
// Conversion instructions.
- case ValueKind::UncheckedRefCastInst:
- case ValueKind::UncheckedAddrCastInst:
- case ValueKind::UncheckedTrivialBitCastInst:
- case ValueKind::UncheckedBitwiseCastInst:
- case ValueKind::UpcastInst:
- case ValueKind::AddressToPointerInst:
- case ValueKind::BridgeObjectToRefInst:
- case ValueKind::BridgeObjectToWordInst:
- case ValueKind::RefToRawPointerInst:
- case ValueKind::RawPointerToRefInst:
- case ValueKind::RefToUnownedInst:
- case ValueKind::UnownedToRefInst:
- case ValueKind::RefToUnmanagedInst:
- case ValueKind::UnmanagedToRefInst:
- case ValueKind::ThinFunctionToPointerInst:
- case ValueKind::PointerToThinFunctionInst:
- case ValueKind::ThinToThickFunctionInst:
- case ValueKind::ThickToObjCMetatypeInst:
- case ValueKind::ObjCToThickMetatypeInst:
- case ValueKind::ConvertFunctionInst:
- case ValueKind::ObjCExistentialMetatypeToObjectInst:
- case ValueKind::ObjCMetatypeToObjectInst: {
+ case SILInstructionKind::UncheckedRefCastInst:
+ case SILInstructionKind::UncheckedAddrCastInst:
+ case SILInstructionKind::UncheckedTrivialBitCastInst:
+ case SILInstructionKind::UncheckedBitwiseCastInst:
+ case SILInstructionKind::UpcastInst:
+ case SILInstructionKind::AddressToPointerInst:
+ case SILInstructionKind::BridgeObjectToRefInst:
+ case SILInstructionKind::BridgeObjectToWordInst:
+ case SILInstructionKind::RefToRawPointerInst:
+ case SILInstructionKind::RawPointerToRefInst:
+ case SILInstructionKind::RefToUnownedInst:
+ case SILInstructionKind::UnownedToRefInst:
+ case SILInstructionKind::RefToUnmanagedInst:
+ case SILInstructionKind::UnmanagedToRefInst:
+ case SILInstructionKind::ThinFunctionToPointerInst:
+ case SILInstructionKind::PointerToThinFunctionInst:
+ case SILInstructionKind::ThinToThickFunctionInst:
+ case SILInstructionKind::ThickToObjCMetatypeInst:
+ case SILInstructionKind::ObjCToThickMetatypeInst:
+ case SILInstructionKind::ConvertFunctionInst:
+ case SILInstructionKind::ObjCExistentialMetatypeToObjectInst:
+ case SILInstructionKind::ObjCMetatypeToObjectInst: {
SILType Ty;
Identifier ToToken;
SourceLoc ToLoc;
@@ -2801,76 +2823,76 @@
switch (Opcode) {
default: llvm_unreachable("Out of sync with parent switch");
- case ValueKind::UncheckedRefCastInst:
+ case SILInstructionKind::UncheckedRefCastInst:
ResultVal = B.createUncheckedRefCast(InstLoc, Val, Ty);
break;
- case ValueKind::UncheckedAddrCastInst:
+ case SILInstructionKind::UncheckedAddrCastInst:
ResultVal = B.createUncheckedAddrCast(InstLoc, Val, Ty);
break;
- case ValueKind::UncheckedTrivialBitCastInst:
+ case SILInstructionKind::UncheckedTrivialBitCastInst:
ResultVal = B.createUncheckedTrivialBitCast(InstLoc, Val, Ty);
break;
- case ValueKind::UncheckedBitwiseCastInst:
+ case SILInstructionKind::UncheckedBitwiseCastInst:
ResultVal = B.createUncheckedBitwiseCast(InstLoc, Val, Ty);
break;
- case ValueKind::UpcastInst:
+ case SILInstructionKind::UpcastInst:
ResultVal = B.createUpcast(InstLoc, Val, Ty);
break;
- case ValueKind::ConvertFunctionInst:
+ case SILInstructionKind::ConvertFunctionInst:
ResultVal = B.createConvertFunction(InstLoc, Val, Ty);
break;
- case ValueKind::AddressToPointerInst:
+ case SILInstructionKind::AddressToPointerInst:
ResultVal = B.createAddressToPointer(InstLoc, Val, Ty);
break;
- case ValueKind::BridgeObjectToRefInst:
+ case SILInstructionKind::BridgeObjectToRefInst:
ResultVal = B.createBridgeObjectToRef(InstLoc, Val, Ty);
break;
- case ValueKind::BridgeObjectToWordInst:
+ case SILInstructionKind::BridgeObjectToWordInst:
ResultVal = B.createBridgeObjectToWord(InstLoc, Val);
break;
- case ValueKind::RefToRawPointerInst:
+ case SILInstructionKind::RefToRawPointerInst:
ResultVal = B.createRefToRawPointer(InstLoc, Val, Ty);
break;
- case ValueKind::RawPointerToRefInst:
+ case SILInstructionKind::RawPointerToRefInst:
ResultVal = B.createRawPointerToRef(InstLoc, Val, Ty);
break;
- case ValueKind::RefToUnownedInst:
+ case SILInstructionKind::RefToUnownedInst:
ResultVal = B.createRefToUnowned(InstLoc, Val, Ty);
break;
- case ValueKind::UnownedToRefInst:
+ case SILInstructionKind::UnownedToRefInst:
ResultVal = B.createUnownedToRef(InstLoc, Val, Ty);
break;
- case ValueKind::RefToUnmanagedInst:
+ case SILInstructionKind::RefToUnmanagedInst:
ResultVal = B.createRefToUnmanaged(InstLoc, Val, Ty);
break;
- case ValueKind::UnmanagedToRefInst:
+ case SILInstructionKind::UnmanagedToRefInst:
ResultVal = B.createUnmanagedToRef(InstLoc, Val, Ty);
break;
- case ValueKind::ThinFunctionToPointerInst:
+ case SILInstructionKind::ThinFunctionToPointerInst:
ResultVal = B.createThinFunctionToPointer(InstLoc, Val, Ty);
break;
- case ValueKind::PointerToThinFunctionInst:
+ case SILInstructionKind::PointerToThinFunctionInst:
ResultVal = B.createPointerToThinFunction(InstLoc, Val, Ty);
break;
- case ValueKind::ThinToThickFunctionInst:
+ case SILInstructionKind::ThinToThickFunctionInst:
ResultVal = B.createThinToThickFunction(InstLoc, Val, Ty);
break;
- case ValueKind::ThickToObjCMetatypeInst:
+ case SILInstructionKind::ThickToObjCMetatypeInst:
ResultVal = B.createThickToObjCMetatype(InstLoc, Val, Ty);
break;
- case ValueKind::ObjCToThickMetatypeInst:
+ case SILInstructionKind::ObjCToThickMetatypeInst:
ResultVal = B.createObjCToThickMetatype(InstLoc, Val, Ty);
break;
- case ValueKind::ObjCMetatypeToObjectInst:
+ case SILInstructionKind::ObjCMetatypeToObjectInst:
ResultVal = B.createObjCMetatypeToObject(InstLoc, Val, Ty);
break;
- case ValueKind::ObjCExistentialMetatypeToObjectInst:
+ case SILInstructionKind::ObjCExistentialMetatypeToObjectInst:
ResultVal = B.createObjCExistentialMetatypeToObject(InstLoc, Val, Ty);
break;
}
break;
}
- case ValueKind::PointerToAddressInst: {
+ case SILInstructionKind::PointerToAddressInst: {
SILType Ty;
Identifier ToToken;
SourceLoc ToLoc;
@@ -2897,7 +2919,7 @@
isStrict, isInvariant);
break;
}
- case ValueKind::RefToBridgeObjectInst: {
+ case SILInstructionKind::RefToBridgeObjectInst: {
SILValue BitsVal;
if (parseTypedValueRef(Val, B) ||
P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
@@ -2908,7 +2930,7 @@
break;
}
- case ValueKind::CheckedCastAddrBranchInst: {
+ case SILInstructionKind::CheckedCastAddrBranchInst: {
Identifier consumptionKindToken;
SourceLoc consumptionKindLoc;
if (parseSILIdentifier(consumptionKindToken, consumptionKindLoc,
@@ -2940,7 +2962,7 @@
getBBForReference(FailureBBName, FailureBBLoc));
break;
}
- case ValueKind::UncheckedRefCastAddrInst:
+ case SILInstructionKind::UncheckedRefCastAddrInst:
if (parseSourceAndDestAddress() || parseSILDebugLocation(InstLoc, B))
return true;
@@ -2948,7 +2970,7 @@
DestAddr, TargetType);
break;
- case ValueKind::UnconditionalCheckedCastAddrInst:
+ case SILInstructionKind::UnconditionalCheckedCastAddrInst:
if (parseSourceAndDestAddress() || parseSILDebugLocation(InstLoc, B))
return true;
@@ -2956,7 +2978,7 @@
InstLoc, SourceAddr, SourceType, DestAddr, TargetType);
break;
- case ValueKind::UnconditionalCheckedCastValueInst:
+ case SILInstructionKind::UnconditionalCheckedCastValueInst:
if (parseTypedValueRef(Val, B) || parseVerbatim("to") || parseSILType(Ty)
|| parseSILDebugLocation(InstLoc, B))
return true;
@@ -2964,7 +2986,7 @@
ResultVal = B.createUnconditionalCheckedCastValue(InstLoc, Val, Ty);
break;
- case ValueKind::UnconditionalCheckedCastInst:
+ case SILInstructionKind::UnconditionalCheckedCastInst:
if (parseTypedValueRef(Val, B) || parseVerbatim("to") || parseSILType(Ty))
return true;
@@ -2974,9 +2996,9 @@
ResultVal = B.createUnconditionalCheckedCast(InstLoc, Val, Ty);
break;
- case ValueKind::CheckedCastBranchInst: {
+ case SILInstructionKind::CheckedCastBranchInst: {
bool isExact = false;
- if (Opcode == ValueKind::CheckedCastBranchInst &&
+ if (Opcode == SILInstructionKind::CheckedCastBranchInst &&
parseSILOptional(isExact, *this, "exact"))
return true;
@@ -2990,7 +3012,7 @@
getBBForReference(FailureBBName, FailureBBLoc));
break;
}
- case ValueKind::CheckedCastValueBranchInst:
+ case SILInstructionKind::CheckedCastValueBranchInst:
if (parseTypedValueRef(Val, B) || parseVerbatim("to") || parseSILType(Ty)
|| parseConditionalBranchDestinations())
return true;
@@ -3000,7 +3022,7 @@
getBBForReference(FailureBBName, FailureBBLoc));
break;
- case ValueKind::MarkUninitializedInst: {
+ case SILInstructionKind::MarkUninitializedInst: {
if (P.parseToken(tok::l_square, diag::expected_tok_in_sil_instr, "["))
return true;
@@ -3040,7 +3062,7 @@
break;
}
- case ValueKind::MarkUninitializedBehaviorInst: {
+ case SILInstructionKind::MarkUninitializedBehaviorInst: {
UnresolvedValueName InitStorageFuncName, StorageName,
SetterFuncName, SelfName;
SmallVector<ParsedSubstitution, 4> ParsedInitStorageSubs,
@@ -3109,7 +3131,7 @@
break;
}
- case ValueKind::MarkFunctionEscapeInst: {
+ case SILInstructionKind::MarkFunctionEscapeInst: {
SmallVector<SILValue, 4> OpList;
do {
if (parseTypedValueRef(Val, B)) return true;
@@ -3122,7 +3144,7 @@
break;
}
- case ValueKind::StoreInst: {
+ case SILInstructionKind::StoreInst: {
UnresolvedValueName From;
SourceLoc ToLoc, AddrLoc;
Identifier ToToken;
@@ -3158,7 +3180,7 @@
break;
}
- case ValueKind::EndBorrowInst: {
+ case SILInstructionKind::EndBorrowInst: {
UnresolvedValueName BorrowedFromName, BorrowedValueName;
SourceLoc ToLoc;
Identifier ToToken;
@@ -3188,18 +3210,18 @@
break;
}
- case ValueKind::BeginAccessInst:
- case ValueKind::BeginUnpairedAccessInst:
- case ValueKind::EndAccessInst:
- case ValueKind::EndUnpairedAccessInst: {
+ case SILInstructionKind::BeginAccessInst:
+ case SILInstructionKind::BeginUnpairedAccessInst:
+ case SILInstructionKind::EndAccessInst:
+ case SILInstructionKind::EndUnpairedAccessInst: {
ParsedEnum<SILAccessKind> kind;
ParsedEnum<SILAccessEnforcement> enforcement;
ParsedEnum<bool> aborting;
- bool isBeginAccess = (Opcode == ValueKind::BeginAccessInst ||
- Opcode == ValueKind::BeginUnpairedAccessInst);
+ bool isBeginAccess = (Opcode == SILInstructionKind::BeginAccessInst ||
+ Opcode == SILInstructionKind::BeginUnpairedAccessInst);
bool wantsEnforcement = (isBeginAccess ||
- Opcode == ValueKind::EndUnpairedAccessInst);
+ Opcode == SILInstructionKind::EndUnpairedAccessInst);
while (P.consumeIf(tok::l_square)) {
Identifier ident;
@@ -3271,7 +3293,7 @@
SILValue bufferVal;
SourceLoc bufferLoc;
- if (Opcode == ValueKind::BeginUnpairedAccessInst &&
+ if (Opcode == SILInstructionKind::BeginUnpairedAccessInst &&
(P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
parseTypedValueRef(bufferVal, bufferLoc, B)))
return true;
@@ -3285,11 +3307,11 @@
return true;
}
- if (Opcode == ValueKind::BeginAccessInst) {
+ if (Opcode == SILInstructionKind::BeginAccessInst) {
ResultVal = B.createBeginAccess(InstLoc, addrVal, *kind, *enforcement);
- } else if (Opcode == ValueKind::EndAccessInst) {
+ } else if (Opcode == SILInstructionKind::EndAccessInst) {
ResultVal = B.createEndAccess(InstLoc, addrVal, *aborting);
- } else if (Opcode == ValueKind::BeginUnpairedAccessInst) {
+ } else if (Opcode == SILInstructionKind::BeginUnpairedAccessInst) {
ResultVal = B.createBeginUnpairedAccess(InstLoc, addrVal, bufferVal,
*kind, *enforcement);
} else {
@@ -3299,10 +3321,10 @@
break;
}
- case ValueKind::StoreBorrowInst:
- case ValueKind::AssignInst:
- case ValueKind::StoreUnownedInst:
- case ValueKind::StoreWeakInst: {
+ case SILInstructionKind::StoreBorrowInst:
+ case SILInstructionKind::AssignInst:
+ case SILInstructionKind::StoreUnownedInst:
+ case SILInstructionKind::StoreWeakInst: {
UnresolvedValueName from;
SourceLoc toLoc, addrLoc;
@@ -3312,8 +3334,8 @@
if (parseValueName(from) ||
parseSILIdentifier(toToken, toLoc,
diag::expected_tok_in_sil_instr, "to") ||
- ((Opcode == ValueKind::StoreWeakInst ||
- Opcode == ValueKind::StoreUnownedInst) &&
+ ((Opcode == SILInstructionKind::StoreWeakInst ||
+ Opcode == SILInstructionKind::StoreUnownedInst) &&
parseSILOptional(isInit, *this, "initialization")) ||
parseTypedValueRef(addrVal, addrLoc, B) ||
parseSILDebugLocation(InstLoc, B))
@@ -3330,14 +3352,14 @@
return true;
}
- if (Opcode == ValueKind::StoreBorrowInst) {
+ if (Opcode == SILInstructionKind::StoreBorrowInst) {
SILType valueTy = addrVal->getType().getObjectType();
ResultVal = B.createStoreBorrow(
InstLoc, getLocalValue(from, valueTy, InstLoc, B), addrVal);
break;
}
- if (Opcode == ValueKind::StoreUnownedInst) {
+ if (Opcode == SILInstructionKind::StoreUnownedInst) {
auto refType = addrVal->getType().getAs<UnownedStorageType>();
if (!refType) {
P.diagnose(addrLoc, diag::sil_operand_not_unowned_address,
@@ -3351,7 +3373,7 @@
break;
}
- if (Opcode == ValueKind::StoreWeakInst) {
+ if (Opcode == SILInstructionKind::StoreWeakInst) {
auto refType = addrVal->getType().getAs<WeakStorageType>();
if (!refType) {
P.diagnose(addrLoc, diag::sil_operand_not_weak_address,
@@ -3367,35 +3389,35 @@
SILType ValType = addrVal->getType().getObjectType();
- assert(Opcode == ValueKind::AssignInst);
+ assert(Opcode == SILInstructionKind::AssignInst);
ResultVal = B.createAssign(InstLoc,
getLocalValue(from, ValType, InstLoc, B),
addrVal);
break;
}
- case ValueKind::AllocStackInst:
- case ValueKind::MetatypeInst: {
+ case SILInstructionKind::AllocStackInst:
+ case SILInstructionKind::MetatypeInst: {
SILType Ty;
if (parseSILType(Ty))
return true;
- if (Opcode == ValueKind::AllocStackInst) {
+ if (Opcode == SILInstructionKind::AllocStackInst) {
SILDebugVariable VarInfo;
if (parseSILDebugVar(VarInfo) ||
parseSILDebugLocation(InstLoc, B))
return true;
ResultVal = B.createAllocStack(InstLoc, Ty, VarInfo);
} else {
- assert(Opcode == ValueKind::MetatypeInst);
+ assert(Opcode == SILInstructionKind::MetatypeInst);
if (parseSILDebugLocation(InstLoc, B))
return true;
ResultVal = B.createMetatype(InstLoc, Ty);
}
break;
}
- case ValueKind::AllocRefInst:
- case ValueKind::AllocRefDynamicInst: {
+ case SILInstructionKind::AllocRefInst:
+ case SILInstructionKind::AllocRefDynamicInst: {
bool IsObjC = false;
bool OnStack = false;
SmallVector<SILType, 2> ElementTypes;
@@ -3429,7 +3451,7 @@
P.parseToken(tok::r_square, diag::expected_in_attribute_list);
}
SILValue Metadata;
- if (Opcode == ValueKind::AllocRefDynamicInst) {
+ if (Opcode == SILInstructionKind::AllocRefDynamicInst) {
if (parseTypedValueRef(Metadata, B) ||
P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ","))
return true;
@@ -3446,7 +3468,7 @@
P.diagnose(P.Tok, diag::sil_objc_with_tail_elements);
return true;
}
- if (Opcode == ValueKind::AllocRefDynamicInst) {
+ if (Opcode == SILInstructionKind::AllocRefDynamicInst) {
if (OnStack)
return true;
@@ -3459,13 +3481,13 @@
break;
}
- case ValueKind::DeallocStackInst:
+ case SILInstructionKind::DeallocStackInst:
if (parseTypedValueRef(Val, B) ||
parseSILDebugLocation(InstLoc, B))
return true;
ResultVal = B.createDeallocStack(InstLoc, Val);
break;
- case ValueKind::DeallocRefInst: {
+ case SILInstructionKind::DeallocRefInst: {
bool OnStack = false;
if (parseSILOptional(OnStack, *this, "stack"))
return true;
@@ -3476,7 +3498,7 @@
ResultVal = B.createDeallocRef(InstLoc, Val, OnStack);
break;
}
- case ValueKind::DeallocPartialRefInst: {
+ case SILInstructionKind::DeallocPartialRefInst: {
SILValue Metatype, Instance;
if (parseTypedValueRef(Instance, B) ||
P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
@@ -3487,15 +3509,15 @@
ResultVal = B.createDeallocPartialRef(InstLoc, Instance, Metatype);
break;
}
- case ValueKind::DeallocBoxInst:
+ case SILInstructionKind::DeallocBoxInst:
if (parseTypedValueRef(Val, B) ||
parseSILDebugLocation(InstLoc, B))
return true;
ResultVal = B.createDeallocBox(InstLoc, Val);
break;
- case ValueKind::ValueMetatypeInst:
- case ValueKind::ExistentialMetatypeInst: {
+ case SILInstructionKind::ValueMetatypeInst:
+ case SILInstructionKind::ExistentialMetatypeInst: {
SILType Ty;
if (parseSILType(Ty) ||
P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
@@ -3504,19 +3526,19 @@
return true;
switch (Opcode) {
default: llvm_unreachable("Out of sync with parent switch");
- case ValueKind::ValueMetatypeInst:
+ case SILInstructionKind::ValueMetatypeInst:
ResultVal = B.createValueMetatype(InstLoc, Ty, Val);
break;
- case ValueKind::ExistentialMetatypeInst:
+ case SILInstructionKind::ExistentialMetatypeInst:
ResultVal = B.createExistentialMetatype(InstLoc, Ty, Val);
break;
- case ValueKind::DeallocBoxInst:
+ case SILInstructionKind::DeallocBoxInst:
ResultVal = B.createDeallocBox(InstLoc, Val);
break;
}
break;
}
- case ValueKind::DeallocExistentialBoxInst: {
+ case SILInstructionKind::DeallocExistentialBoxInst: {
CanType ConcreteTy;
if (parseTypedValueRef(Val, B)
|| P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",")
@@ -3528,7 +3550,7 @@
ResultVal = B.createDeallocExistentialBox(InstLoc, ConcreteTy, Val);
break;
}
- case ValueKind::TupleInst: {
+ case SILInstructionKind::TupleInst: {
// Tuple instructions have two different syntaxes, one for simple tuple
// types, one for complicated ones.
if (P.Tok.isNot(tok::sil_dollar)) {
@@ -3603,7 +3625,7 @@
ResultVal = B.createTuple(InstLoc, Ty, OpList);
break;
}
- case ValueKind::EnumInst: {
+ case SILInstructionKind::EnumInst: {
SILType Ty;
SILDeclRef Elt;
SILValue Operand;
@@ -3624,9 +3646,9 @@
cast<EnumElementDecl>(Elt.getDecl()), Ty);
break;
}
- case ValueKind::InitEnumDataAddrInst:
- case ValueKind::UncheckedEnumDataInst:
- case ValueKind::UncheckedTakeEnumDataAddrInst: {
+ case SILInstructionKind::InitEnumDataAddrInst:
+ case SILInstructionKind::UncheckedEnumDataInst:
+ case SILInstructionKind::UncheckedTakeEnumDataAddrInst: {
SILValue Operand;
SILDeclRef EltRef;
if (parseTypedValueRef(Operand, B) ||
@@ -3639,14 +3661,14 @@
auto ResultTy = Operand->getType().getEnumElementType(Elt, SILMod);
switch (Opcode) {
- case swift::ValueKind::InitEnumDataAddrInst:
+ case swift::SILInstructionKind::InitEnumDataAddrInst:
ResultVal = B.createInitEnumDataAddr(InstLoc, Operand, Elt, ResultTy);
break;
- case swift::ValueKind::UncheckedTakeEnumDataAddrInst:
+ case swift::SILInstructionKind::UncheckedTakeEnumDataAddrInst:
ResultVal = B.createUncheckedTakeEnumDataAddr(InstLoc, Operand, Elt,
ResultTy);
break;
- case swift::ValueKind::UncheckedEnumDataInst:
+ case swift::SILInstructionKind::UncheckedEnumDataInst:
ResultVal = B.createUncheckedEnumData(InstLoc, Operand, Elt, ResultTy);
break;
default:
@@ -3654,7 +3676,7 @@
}
break;
}
- case ValueKind::InjectEnumAddrInst: {
+ case SILInstructionKind::InjectEnumAddrInst: {
SILValue Operand;
SILDeclRef EltRef;
if (parseTypedValueRef(Operand, B) ||
@@ -3667,8 +3689,8 @@
ResultVal = B.createInjectEnumAddr(InstLoc, Operand, Elt);
break;
}
- case ValueKind::TupleElementAddrInst:
- case ValueKind::TupleExtractInst: {
+ case SILInstructionKind::TupleElementAddrInst:
+ case SILInstructionKind::TupleExtractInst: {
SourceLoc NameLoc;
if (parseTypedValueRef(Val, B) ||
P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ","))
@@ -3686,7 +3708,7 @@
if (parseSILDebugLocation(InstLoc, B))
return true;
auto ResultTy = TT->getElement(Field).getType()->getCanonicalType();
- if (Opcode == ValueKind::TupleElementAddrInst)
+ if (Opcode == SILInstructionKind::TupleElementAddrInst)
ResultVal = B.createTupleElementAddr(InstLoc, Val, Field,
SILType::getPrimitiveAddressType(ResultTy));
else
@@ -3694,21 +3716,21 @@
SILType::getPrimitiveObjectType(ResultTy));
break;
}
- case ValueKind::ReturnInst: {
+ case SILInstructionKind::ReturnInst: {
if (parseTypedValueRef(Val, B) ||
parseSILDebugLocation(InstLoc, B))
return true;
ResultVal = B.createReturn(InstLoc, Val);
break;
}
- case ValueKind::ThrowInst: {
+ case SILInstructionKind::ThrowInst: {
if (parseTypedValueRef(Val, B) ||
parseSILDebugLocation(InstLoc, B))
return true;
ResultVal = B.createThrow(InstLoc, Val);
break;
}
- case ValueKind::BranchInst: {
+ case SILInstructionKind::BranchInst: {
Identifier BBName;
SourceLoc NameLoc;
if (parseSILIdentifier(BBName, NameLoc, diag::expected_sil_block_name))
@@ -3727,7 +3749,7 @@
Args);
break;
}
- case ValueKind::CondBranchInst: {
+ case SILInstructionKind::CondBranchInst: {
UnresolvedValueName Cond;
Identifier BBName, BBName2;
SourceLoc NameLoc, NameLoc2;
@@ -3753,15 +3775,15 @@
Args2);
break;
}
- case ValueKind::UnreachableInst:
+ case SILInstructionKind::UnreachableInst:
if (parseSILDebugLocation(InstLoc, B))
return true;
ResultVal = B.createUnreachable(InstLoc);
break;
- case ValueKind::ClassMethodInst:
- case ValueKind::SuperMethodInst:
- case ValueKind::DynamicMethodInst: {
+ case SILInstructionKind::ClassMethodInst:
+ case SILInstructionKind::SuperMethodInst:
+ case SILInstructionKind::DynamicMethodInst: {
bool IsVolatile = false;
if (parseSILOptional(IsVolatile, *this, "volatile"))
return true;
@@ -3783,22 +3805,22 @@
switch (Opcode) {
default: llvm_unreachable("Out of sync with parent switch");
- case ValueKind::ClassMethodInst:
+ case SILInstructionKind::ClassMethodInst:
ResultVal = B.createClassMethod(InstLoc, Val, Member, MethodTy,
IsVolatile);
break;
- case ValueKind::SuperMethodInst:
+ case SILInstructionKind::SuperMethodInst:
ResultVal = B.createSuperMethod(InstLoc, Val, Member, MethodTy,
IsVolatile);
break;
- case ValueKind::DynamicMethodInst:
+ case SILInstructionKind::DynamicMethodInst:
ResultVal = B.createDynamicMethod(InstLoc, Val, Member, MethodTy,
IsVolatile);
break;
}
break;
}
- case ValueKind::WitnessMethodInst: {
+ case SILInstructionKind::WitnessMethodInst: {
bool IsVolatile = false;
if (parseSILOptional(IsVolatile, *this, "volatile"))
return true;
@@ -3845,7 +3867,7 @@
MethodTy, IsVolatile);
break;
}
- case ValueKind::CopyAddrInst: {
+ case SILInstructionKind::CopyAddrInst: {
bool IsTake = false, IsInit = false;
UnresolvedValueName SrcLName;
SILValue DestLVal;
@@ -3875,7 +3897,7 @@
IsInitialization_t(IsInit));
break;
}
- case ValueKind::BindMemoryInst: {
+ case SILInstructionKind::BindMemoryInst: {
SILValue IndexVal;
Identifier ToToken;
SourceLoc ToLoc;
@@ -3896,8 +3918,8 @@
ResultVal = B.createBindMemory(InstLoc, Val, IndexVal, EltTy);
break;
}
- case ValueKind::ObjectInst:
- case ValueKind::StructInst: {
+ case SILInstructionKind::ObjectInst:
+ case SILInstructionKind::StructInst: {
SILType Ty;
if (parseSILType(Ty) ||
P.parseToken(tok::l_paren, diag::expected_tok_in_sil_instr, "("))
@@ -3908,7 +3930,7 @@
unsigned NumBaseElems = 0;
if (P.Tok.isNot(tok::r_paren)) {
do {
- if (Opcode == ValueKind::ObjectInst) {
+ if (Opcode == SILInstructionKind::ObjectInst) {
if (parseSILOptional(OpsAreTailElems, *this, "tail_elems"))
return true;
}
@@ -3923,15 +3945,15 @@
parseSILDebugLocation(InstLoc, B))
return true;
- if (Opcode == ValueKind::StructInst) {
+ if (Opcode == SILInstructionKind::StructInst) {
ResultVal = B.createStruct(InstLoc, Ty, OpList);
} else {
ResultVal = B.createObject(InstLoc, Ty, OpList, NumBaseElems);
}
break;
}
- case ValueKind::StructElementAddrInst:
- case ValueKind::StructExtractInst: {
+ case SILInstructionKind::StructElementAddrInst:
+ case SILInstructionKind::StructExtractInst: {
ValueDecl *FieldV;
SourceLoc NameLoc = P.Tok.getLoc();
if (parseTypedValueRef(Val, B) ||
@@ -3948,7 +3970,7 @@
// FIXME: substitution means this type should be explicit to improve
// performance.
auto ResultTy = Val->getType().getFieldType(Field, SILMod);
- if (Opcode == ValueKind::StructElementAddrInst)
+ if (Opcode == SILInstructionKind::StructElementAddrInst)
ResultVal = B.createStructElementAddr(InstLoc, Val, Field,
ResultTy.getAddressType());
else
@@ -3956,7 +3978,7 @@
ResultTy.getObjectType());
break;
}
- case ValueKind::RefElementAddrInst: {
+ case SILInstructionKind::RefElementAddrInst: {
ValueDecl *FieldV;
SourceLoc NameLoc;
if (parseTypedValueRef(Val, B) ||
@@ -3973,7 +3995,7 @@
ResultVal = B.createRefElementAddr(InstLoc, Val, Field, ResultTy);
break;
}
- case ValueKind::RefTailAddrInst: {
+ case SILInstructionKind::RefTailAddrInst: {
SourceLoc NameLoc;
SILType ResultObjTy;
if (parseTypedValueRef(Val, B) ||
@@ -3985,7 +4007,7 @@
ResultVal = B.createRefTailAddr(InstLoc, Val, ResultTy);
break;
}
- case ValueKind::IsNonnullInst: {
+ case SILInstructionKind::IsNonnullInst: {
SourceLoc Loc;
if (parseTypedValueRef(Val, Loc, B) ||
parseSILDebugLocation(InstLoc, B))
@@ -3993,7 +4015,7 @@
ResultVal = B.createIsNonnull(InstLoc, Val);
break;
}
- case ValueKind::IndexAddrInst: {
+ case SILInstructionKind::IndexAddrInst: {
SILValue IndexVal;
if (parseTypedValueRef(Val, B) ||
P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
@@ -4003,7 +4025,7 @@
ResultVal = B.createIndexAddr(InstLoc, Val, IndexVal);
break;
}
- case ValueKind::TailAddrInst: {
+ case SILInstructionKind::TailAddrInst: {
SILValue IndexVal;
SILType ResultObjTy;
if (parseTypedValueRef(Val, B) ||
@@ -4017,7 +4039,7 @@
ResultVal = B.createTailAddr(InstLoc, Val, IndexVal, ResultTy);
break;
}
- case ValueKind::IndexRawPointerInst: {
+ case SILInstructionKind::IndexRawPointerInst: {
SILValue IndexVal;
if (parseTypedValueRef(Val, B) ||
P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
@@ -4027,7 +4049,7 @@
ResultVal = B.createIndexRawPointer(InstLoc, Val, IndexVal);
break;
}
- case ValueKind::ObjCProtocolInst: {
+ case SILInstructionKind::ObjCProtocolInst: {
Identifier ProtocolName;
SILType Ty;
if (P.parseToken(tok::pound, diag::expected_sil_constant) ||
@@ -4049,7 +4071,7 @@
ResultVal = B.createObjCProtocol(InstLoc, cast<ProtocolDecl>(VD), Ty);
break;
}
- case ValueKind::AllocGlobalInst: {
+ case SILInstructionKind::AllocGlobalInst: {
Identifier GlobalName;
SourceLoc IdLoc;
if (P.parseToken(tok::at_sign, diag::expected_sil_value_name) ||
@@ -4067,8 +4089,8 @@
ResultVal = B.createAllocGlobal(InstLoc, global);
break;
}
- case ValueKind::GlobalAddrInst:
- case ValueKind::GlobalValueInst: {
+ case SILInstructionKind::GlobalAddrInst:
+ case SILInstructionKind::GlobalValueInst: {
Identifier GlobalName;
SourceLoc IdLoc;
SILType Ty;
@@ -4086,7 +4108,7 @@
return true;
}
- SILType expectedType = (Opcode == ValueKind::GlobalAddrInst ?
+ SILType expectedType = (Opcode == SILInstructionKind::GlobalAddrInst ?
global->getLoweredType().getAddressType() :
global->getLoweredType());
if (expectedType != Ty) {
@@ -4096,15 +4118,15 @@
return true;
}
- if (Opcode == ValueKind::GlobalAddrInst) {
+ if (Opcode == SILInstructionKind::GlobalAddrInst) {
ResultVal = B.createGlobalAddr(InstLoc, global);
} else {
ResultVal = B.createGlobalValue(InstLoc, global);
}
break;
}
- case ValueKind::SelectEnumInst:
- case ValueKind::SelectEnumAddrInst: {
+ case SILInstructionKind::SelectEnumInst:
+ case SILInstructionKind::SelectEnumAddrInst: {
if (parseTypedValueRef(Val, B))
return true;
@@ -4158,7 +4180,7 @@
caseName.first,
getLocalValue(caseName.second, ResultType, InstLoc, B)));
- if (Opcode == ValueKind::SelectEnumInst)
+ if (Opcode == SILInstructionKind::SelectEnumInst)
ResultVal = B.createSelectEnum(InstLoc, Val, ResultType,
DefaultValue, CaseValues);
else
@@ -4167,8 +4189,8 @@
break;
}
- case ValueKind::SwitchEnumInst:
- case ValueKind::SwitchEnumAddrInst: {
+ case SILInstructionKind::SwitchEnumInst:
+ case SILInstructionKind::SwitchEnumAddrInst: {
if (parseTypedValueRef(Val, B))
return true;
@@ -4202,13 +4224,13 @@
}
if (parseSILDebugLocation(InstLoc, B))
return true;
- if (Opcode == ValueKind::SwitchEnumInst)
+ if (Opcode == SILInstructionKind::SwitchEnumInst)
ResultVal = B.createSwitchEnum(InstLoc, Val, DefaultBB, CaseBBs);
else
ResultVal = B.createSwitchEnumAddr(InstLoc, Val, DefaultBB, CaseBBs);
break;
}
- case ValueKind::SwitchValueInst: {
+ case SILInstructionKind::SwitchValueInst: {
if (parseTypedValueRef(Val, B))
return true;
@@ -4291,7 +4313,7 @@
ResultVal = B.createSwitchValue(InstLoc, Val, DefaultBB, CaseBBs);
break;
}
- case ValueKind::SelectValueInst: {
+ case SILInstructionKind::SelectValueInst: {
if (parseTypedValueRef(Val, B))
return true;
@@ -4353,20 +4375,20 @@
DefaultValue, CaseValues);
break;
}
- case ValueKind::DeinitExistentialAddrInst: {
+ case SILInstructionKind::DeinitExistentialAddrInst: {
if (parseTypedValueRef(Val, B) ||
parseSILDebugLocation(InstLoc, B))
return true;
ResultVal = B.createDeinitExistentialAddr(InstLoc, Val);
break;
}
- case ValueKind::DeinitExistentialValueInst: {
+ case SILInstructionKind::DeinitExistentialValueInst: {
if (parseTypedValueRef(Val, B) || parseSILDebugLocation(InstLoc, B))
return true;
ResultVal = B.createDeinitExistentialValue(InstLoc, Val);
break;
}
- case ValueKind::InitExistentialAddrInst: {
+ case SILInstructionKind::InitExistentialAddrInst: {
CanType Ty;
SourceLoc TyLoc;
if (parseTypedValueRef(Val, B) ||
@@ -4394,7 +4416,7 @@
conformances);
break;
}
- case ValueKind::InitExistentialValueInst: {
+ case SILInstructionKind::InitExistentialValueInst: {
CanType FormalConcreteTy;
SILType ExistentialTy;
SourceLoc TyLoc;
@@ -4415,7 +4437,7 @@
InstLoc, ExistentialTy, FormalConcreteTy, Val, conformances);
break;
}
- case ValueKind::AllocExistentialBoxInst: {
+ case SILInstructionKind::AllocExistentialBoxInst: {
SILType ExistentialTy;
CanType ConcreteFormalTy;
SourceLoc TyLoc;
@@ -4437,7 +4459,7 @@
break;
}
- case ValueKind::InitExistentialRefInst: {
+ case SILInstructionKind::InitExistentialRefInst: {
CanType FormalConcreteTy;
SILType ExistentialTy;
SourceLoc TyLoc;
@@ -4462,7 +4484,7 @@
conformances);
break;
}
- case ValueKind::InitExistentialMetatypeInst: {
+ case SILInstructionKind::InitExistentialMetatypeInst: {
SourceLoc TyLoc;
SILType ExistentialTy;
if (parseTypedValueRef(Val, B) ||
@@ -4487,7 +4509,7 @@
conformances);
break;
}
- case ValueKind::DynamicMethodBranchInst: {
+ case SILInstructionKind::DynamicMethodBranchInst: {
SILDeclRef Member;
Identifier BBName, BBName2;
SourceLoc NameLoc, NameLoc2;
@@ -4508,7 +4530,7 @@
NameLoc2));
break;
}
- case ValueKind::ProjectBlockStorageInst: {
+ case SILInstructionKind::ProjectBlockStorageInst: {
if (parseTypedValueRef(Val, B) ||
parseSILDebugLocation(InstLoc, B))
return true;
@@ -4516,7 +4538,7 @@
ResultVal = B.createProjectBlockStorage(InstLoc, Val);
break;
}
- case ValueKind::InitBlockStorageHeaderInst: {
+ case SILInstructionKind::InitBlockStorageHeaderInst: {
Identifier invoke, type;
SourceLoc invokeLoc, typeLoc;
@@ -4572,14 +4594,24 @@
}
}
- // Store the named value if we had a name.
- if (ResultNameLoc.isValid())
- setLocalValue(ResultVal, ResultName, ResultNameLoc);
+ // Match the results clause if we had one.
+ if (resultClauseBegin.isValid()) {
+ auto results = ResultVal->getResults();
+ if (results.size() != resultNames.size()) {
+ P.diagnose(resultClauseBegin, diag::wrong_result_count_in_sil_instr,
+ results.size());
+ } else {
+ for (size_t i : indices(results)) {
+ setLocalValue(results[i], resultNames[i].first, resultNames[i].second);
+ }
+ }
+ }
+
return false;
}
bool SILParser::parseCallInstruction(SILLocation InstLoc,
- ValueKind Opcode, SILBuilder &B,
+ SILInstructionKind Opcode, SILBuilder &B,
SILInstruction *&ResultVal) {
UnresolvedValueName FnName;
SmallVector<UnresolvedValueName, 4> ArgNames;
@@ -4652,7 +4684,7 @@
switch (Opcode) {
default: llvm_unreachable("Unexpected case");
- case ValueKind::ApplyInst : {
+ case SILInstructionKind::ApplyInst : {
if (parseSILDebugLocation(InstLoc, B))
return true;
if (substConv.getNumSILArguments() != ArgNames.size()) {
@@ -4671,7 +4703,7 @@
ResultVal = B.createApply(InstLoc, FnVal, subs, Args, IsNonThrowingApply);
break;
}
- case ValueKind::PartialApplyInst: {
+ case SILInstructionKind::PartialApplyInst: {
if (parseSILDebugLocation(InstLoc, B))
return true;
if (substFTI->getParameters().size() < ArgNames.size()) {
@@ -4694,7 +4726,7 @@
PartialApplyConvention);
break;
}
- case ValueKind::TryApplyInst: {
+ case SILInstructionKind::TryApplyInst: {
Identifier normalBBName, errorBBName;
SourceLoc normalBBLoc, errorBBLoc;
if (P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
diff --git a/lib/RemoteAST/RemoteAST.cpp b/lib/RemoteAST/RemoteAST.cpp
index 508f84d..7501eee 100644
--- a/lib/RemoteAST/RemoteAST.cpp
+++ b/lib/RemoteAST/RemoteAST.cpp
@@ -21,6 +21,7 @@
#include "swift/AST/Decl.h"
#include "swift/AST/Module.h"
#include "swift/AST/NameLookup.h"
+#include "swift/AST/SubstitutionMap.h"
#include "swift/AST/Types.h"
#include "swift/AST/TypeRepr.h"
#include "swift/Basic/Mangler.h"
@@ -133,6 +134,14 @@
NominalTypeDecl *createNominalTypeDecl(const Demangle::NodePointer &node);
+ Type createNominalType(NominalTypeDecl *decl) {
+ // If the declaration is generic, fail.
+ if (decl->isGenericContext())
+ return Type();
+
+ return decl->getDeclaredType();
+ }
+
Type createNominalType(NominalTypeDecl *decl, Type parent) {
// If the declaration is generic, fail.
if (decl->getGenericParams())
@@ -145,6 +154,36 @@
return NominalType::get(decl, parent, Ctx);
}
+ Type createBoundGenericType(NominalTypeDecl *decl, ArrayRef<Type> args) {
+ // If the declaration isn't generic, fail.
+ if (!decl->isGenericContext())
+ return Type();
+
+ // Build a SubstitutionMap.
+ auto *genericSig = decl->getGenericSignature();
+ auto genericParams = genericSig->getSubstitutableParams();
+ if (genericParams.size() != args.size())
+ return Type();
+
+ auto subMap = genericSig->getSubstitutionMap(
+ [&](SubstitutableType *t) -> Type {
+ for (unsigned i = 0, e = genericParams.size(); i < e; ++i) {
+ if (t->isEqual(genericParams[i]))
+ return args[i];
+ }
+ return Type();
+ },
+ // FIXME: Wrong module
+ LookUpConformanceInModule(decl->getParentModule()));
+
+ auto origType = decl->getDeclaredInterfaceType();
+
+ // FIXME: We're not checking that the type satisfies the generic
+ // requirements of the signature here.
+ auto substType = origType.subst(subMap);
+ return substType;
+ }
+
Type createBoundGenericType(NominalTypeDecl *decl, ArrayRef<Type> args,
Type parent) {
// If the declaration isn't generic, fail.
diff --git a/lib/SIL/Dominance.cpp b/lib/SIL/Dominance.cpp
index 09b406d..eb27420 100644
--- a/lib/SIL/Dominance.cpp
+++ b/lib/SIL/Dominance.cpp
@@ -63,7 +63,7 @@
/// Does value A properly dominate instruction B?
bool DominanceInfo::properlyDominates(SILValue a, SILInstruction *b) {
- if (auto *Inst = dyn_cast<SILInstruction>(a)) {
+ if (auto *Inst = a->getDefiningInstruction()) {
return properlyDominates(Inst, b);
}
if (auto *Arg = dyn_cast<SILArgument>(a)) {
diff --git a/lib/SIL/DynamicCasts.cpp b/lib/SIL/DynamicCasts.cpp
index 314e578..669c0d3 100644
--- a/lib/SIL/DynamicCasts.cpp
+++ b/lib/SIL/DynamicCasts.cpp
@@ -1175,14 +1175,12 @@
/// Carry out the operations required for an indirect conditional cast
/// using a scalar cast operation.
-void swift::
-emitIndirectConditionalCastWithScalar(SILBuilder &B, ModuleDecl *M,
- SILLocation loc,
- CastConsumptionKind consumption,
- SILValue src, CanType sourceType,
- SILValue dest, CanType targetType,
- SILBasicBlock *indirectSuccBB,
- SILBasicBlock *indirectFailBB) {
+void swift::emitIndirectConditionalCastWithScalar(
+ SILBuilder &B, ModuleDecl *M, SILLocation loc,
+ CastConsumptionKind consumption, SILValue src, CanType sourceType,
+ SILValue dest, CanType targetType, SILBasicBlock *indirectSuccBB,
+ SILBasicBlock *indirectFailBB, ProfileCounter TrueCount,
+ ProfileCounter FalseCount) {
assert(canUseScalarCheckedCastInstructions(B.getModule(),
sourceType, targetType));
@@ -1207,7 +1205,7 @@
SILType targetValueType = dest->getType().getObjectType();
B.createCheckedCastBranch(loc, /*exact*/ false, srcValue, targetValueType,
- scalarSuccBB, scalarFailBB);
+ scalarSuccBB, scalarFailBB, TrueCount, FalseCount);
// Emit the success block.
B.setInsertionPoint(scalarSuccBB); {
diff --git a/lib/SIL/InstructionUtils.cpp b/lib/SIL/InstructionUtils.cpp
index 695c402..b2455bf 100644
--- a/lib/SIL/InstructionUtils.cpp
+++ b/lib/SIL/InstructionUtils.cpp
@@ -40,7 +40,7 @@
case ValueKind::StructElementAddrInst:
case ValueKind::TupleElementAddrInst:
case ValueKind::UncheckedTakeEnumDataAddrInst:
- V2 = cast<SILInstruction>(V2)->getOperand(0);
+ V2 = cast<SingleValueInstruction>(V2)->getOperand(0);
break;
default:
break;
@@ -63,16 +63,15 @@
static bool isRCIdentityPreservingCast(ValueKind Kind) {
switch (Kind) {
- case ValueKind::UpcastInst:
- case ValueKind::UncheckedRefCastInst:
- case ValueKind::UncheckedRefCastAddrInst:
- case ValueKind::UnconditionalCheckedCastInst:
- case ValueKind::UnconditionalCheckedCastValueInst:
- case ValueKind::RefToBridgeObjectInst:
- case ValueKind::BridgeObjectToRefInst:
- return true;
- default:
- return false;
+ case ValueKind::UpcastInst:
+ case ValueKind::UncheckedRefCastInst:
+ case ValueKind::UnconditionalCheckedCastInst:
+ case ValueKind::UnconditionalCheckedCastValueInst:
+ case ValueKind::RefToBridgeObjectInst:
+ case ValueKind::BridgeObjectToRefInst:
+ return true;
+ default:
+ return false;
}
}
@@ -127,7 +126,7 @@
auto K = V->getKind();
if (isRCIdentityPreservingCast(K) ||
K == ValueKind::UncheckedTrivialBitCastInst) {
- V = cast<SILInstruction>(V)->getOperand(0);
+ V = cast<SingleValueInstruction>(V)->getOperand(0);
continue;
}
@@ -143,7 +142,7 @@
if (isRCIdentityPreservingCast(K)
|| K == ValueKind::UncheckedTrivialBitCastInst
|| K == ValueKind::MarkDependenceInst) {
- V = cast<SILInstruction>(V)->getOperand(0);
+ V = cast<SingleValueInstruction>(V)->getOperand(0);
continue;
}
@@ -157,8 +156,8 @@
V = stripSinglePredecessorArgs(V);
- while (isa<UpcastInst>(V))
- V = stripSinglePredecessorArgs(cast<UpcastInst>(V)->getOperand());
+ while (auto upcast = dyn_cast<UpcastInst>(V))
+ V = stripSinglePredecessorArgs(upcast->getOperand());
return V;
}
@@ -184,7 +183,7 @@
V = stripSinglePredecessorArgs(V);
if (!Projection::isAddressProjection(V))
return V;
- V = cast<SILInstruction>(V)->getOperand(0);
+ V = cast<SingleValueInstruction>(V)->getOperand(0);
}
}
@@ -193,7 +192,7 @@
V = stripSinglePredecessorArgs(V);
if (!Projection::isAddressProjection(V))
return V;
- auto *Inst = cast<SILInstruction>(V);
+ auto *Inst = cast<SingleValueInstruction>(V);
if (Inst->getNumOperands() > 1)
return V;
V = Inst->getOperand(0);
@@ -205,7 +204,7 @@
V = stripSinglePredecessorArgs(V);
if (!Projection::isObjectProjection(V))
return V;
- V = cast<SILInstruction>(V)->getOperand(0);
+ V = cast<SingleValueInstruction>(V)->getOperand(0);
}
}
@@ -242,7 +241,7 @@
struct OwnershipQualifiedKindVisitor : SILInstructionVisitor<OwnershipQualifiedKindVisitor, OwnershipQualifiedKind> {
- OwnershipQualifiedKind visitValueBase(ValueBase *V) {
+ OwnershipQualifiedKind visitSILInstruction(SILInstruction *I) {
return OwnershipQualifiedKind::NotApplicable;
}
diff --git a/lib/SIL/Linker.h b/lib/SIL/Linker.h
index 20be5a0..a1a23e6 100644
--- a/lib/SIL/Linker.h
+++ b/lib/SIL/Linker.h
@@ -70,7 +70,7 @@
SILVTable *processClassDecl(const ClassDecl *C);
/// We do not want to visit callee functions if we just have a value base.
- bool visitValueBase(ValueBase *V) { return false; }
+ bool visitSILInstruction(SILInstruction *I) { return false; }
bool visitApplyInst(ApplyInst *AI);
bool visitPartialApplyInst(PartialApplyInst *PAI);
diff --git a/lib/SIL/LoopInfo.cpp b/lib/SIL/LoopInfo.cpp
index 1e2cc87..65271c9 100644
--- a/lib/SIL/LoopInfo.cpp
+++ b/lib/SIL/LoopInfo.cpp
@@ -39,7 +39,7 @@
// The deallocation of a stack allocation must be in the loop, otherwise the
// deallocation will be fed by a phi node of two allocations.
if (I->isAllocatingStack()) {
- for (auto *UI : I->getUses()) {
+ for (auto *UI : cast<SingleValueInstruction>(I)->getUses()) {
if (UI->getUser()->isDeallocatingStack()) {
if (!contains(UI->getUser()->getParent()))
return false;
@@ -64,7 +64,8 @@
isa<OpenExistentialMetatypeInst>(I) ||
isa<OpenExistentialValueInst>(I) || isa<OpenExistentialBoxInst>(I) ||
isa<OpenExistentialBoxValueInst>(I)) {
- for (auto *UI : I->getUses())
+ SingleValueInstruction *OI = cast<SingleValueInstruction>(I);
+ for (auto *UI : OI->getUses())
if (!contains(UI->getUser()))
return false;
return true;
diff --git a/lib/SIL/Projection.cpp b/lib/SIL/Projection.cpp
index 62927dd..85188ca 100644
--- a/lib/SIL/Projection.cpp
+++ b/lib/SIL/Projection.cpp
@@ -58,7 +58,7 @@
// Projection
//===----------------------------------------------------------------------===//
-Projection::Projection(SILInstruction *I) : Value() {
+Projection::Projection(SingleValueInstruction *I) : Value() {
if (!I)
return;
/// Initialize given the specific instruction type and verify with asserts
@@ -68,7 +68,7 @@
// be None so the Projection will be invalid.
default:
return;
- case ValueKind::StructElementAddrInst: {
+ case SILInstructionKind::StructElementAddrInst: {
auto *SEAI = cast<StructElementAddrInst>(I);
Value = ValueTy(ProjectionKind::Struct, SEAI->getFieldNo());
assert(getKind() == ProjectionKind::Struct);
@@ -77,7 +77,7 @@
SEAI->getType());
break;
}
- case ValueKind::StructExtractInst: {
+ case SILInstructionKind::StructExtractInst: {
auto *SEI = cast<StructExtractInst>(I);
Value = ValueTy(ProjectionKind::Struct, SEI->getFieldNo());
assert(getKind() == ProjectionKind::Struct);
@@ -86,7 +86,7 @@
SEI->getType());
break;
}
- case ValueKind::RefElementAddrInst: {
+ case SILInstructionKind::RefElementAddrInst: {
auto *REAI = cast<RefElementAddrInst>(I);
Value = ValueTy(ProjectionKind::Class, REAI->getFieldNo());
assert(getKind() == ProjectionKind::Class);
@@ -95,14 +95,14 @@
REAI->getType());
break;
}
- case ValueKind::RefTailAddrInst: {
+ case SILInstructionKind::RefTailAddrInst: {
auto *RTAI = cast<RefTailAddrInst>(I);
auto *Ty = RTAI->getTailType().getSwiftRValueType().getPointer();
Value = ValueTy(ProjectionKind::TailElems, Ty);
assert(getKind() == ProjectionKind::TailElems);
break;
}
- case ValueKind::ProjectBoxInst: {
+ case SILInstructionKind::ProjectBoxInst: {
auto *PBI = cast<ProjectBoxInst>(I);
Value = ValueTy(ProjectionKind::Box, static_cast<uintptr_t>(0));
assert(getKind() == ProjectionKind::Box);
@@ -112,7 +112,7 @@
(void) PBI;
break;
}
- case ValueKind::TupleExtractInst: {
+ case SILInstructionKind::TupleExtractInst: {
auto *TEI = cast<TupleExtractInst>(I);
Value = ValueTy(ProjectionKind::Tuple, TEI->getFieldNo());
assert(getKind() == ProjectionKind::Tuple);
@@ -121,7 +121,7 @@
TEI->getType());
break;
}
- case ValueKind::TupleElementAddrInst: {
+ case SILInstructionKind::TupleElementAddrInst: {
auto *TEAI = cast<TupleElementAddrInst>(I);
Value = ValueTy(ProjectionKind::Tuple, TEAI->getFieldNo());
assert(getKind() == ProjectionKind::Tuple);
@@ -130,7 +130,7 @@
TEAI->getType());
break;
}
- case ValueKind::UncheckedEnumDataInst: {
+ case SILInstructionKind::UncheckedEnumDataInst: {
auto *UEDI = cast<UncheckedEnumDataInst>(I);
Value = ValueTy(ProjectionKind::Enum, UEDI->getElementNo());
assert(getKind() == ProjectionKind::Enum);
@@ -139,7 +139,7 @@
UEDI->getType());
break;
}
- case ValueKind::UncheckedTakeEnumDataAddrInst: {
+ case SILInstructionKind::UncheckedTakeEnumDataAddrInst: {
auto *UTEDAI = cast<UncheckedTakeEnumDataAddrInst>(I);
Value = ValueTy(ProjectionKind::Enum, UTEDAI->getElementNo());
assert(getKind() == ProjectionKind::Enum);
@@ -148,7 +148,7 @@
UTEDAI->getType());
break;
}
- case ValueKind::IndexAddrInst: {
+ case SILInstructionKind::IndexAddrInst: {
// We can represent all integers provided here since getIntegerIndex only
// returns 32 bit values. When that changes, this code will need to be
// updated and a MaxLargeIndex will need to be used here. Currently we
@@ -163,7 +163,7 @@
}
break;
}
- case ValueKind::UpcastInst: {
+ case SILInstructionKind::UpcastInst: {
auto *Ty = I->getType().getSwiftRValueType().getPointer();
assert(Ty->isCanonical());
Value = ValueTy(ProjectionKind::Upcast, Ty);
@@ -172,7 +172,7 @@
I->getType());
break;
}
- case ValueKind::UncheckedRefCastInst: {
+ case SILInstructionKind::UncheckedRefCastInst: {
auto *Ty = I->getType().getSwiftRValueType().getPointer();
assert(Ty->isCanonical());
Value = ValueTy(ProjectionKind::RefCast, Ty);
@@ -181,8 +181,8 @@
I->getType());
break;
}
- case ValueKind::UncheckedBitwiseCastInst:
- case ValueKind::UncheckedAddrCastInst: {
+ case SILInstructionKind::UncheckedBitwiseCastInst:
+ case SILInstructionKind::UncheckedAddrCastInst: {
auto *Ty = I->getType().getSwiftRValueType().getPointer();
assert(Ty->isCanonical());
Value = ValueTy(ProjectionKind::BitwiseCast, Ty);
@@ -194,7 +194,7 @@
}
}
-NullablePtr<SILInstruction>
+NullablePtr<SingleValueInstruction>
Projection::createObjectProjection(SILBuilder &B, SILLocation Loc,
SILValue Base) const {
SILType BaseTy = Base->getType();
@@ -232,7 +232,7 @@
llvm_unreachable("Unhandled ProjectionKind in switch.");
}
-NullablePtr<SILInstruction>
+NullablePtr<SingleValueInstruction>
Projection::createAddressProjection(SILBuilder &B, SILLocation Loc,
SILValue Base) const {
SILType BaseTy = Base->getType();
@@ -361,7 +361,7 @@
if (!AP.isValid())
break;
P.Path.push_back(AP);
- Iter = cast<SILInstruction>(*Iter).getOperand(0);
+ Iter = cast<SingleValueInstruction>(*Iter).getOperand(0);
}
// Return None if we have an empty projection list or if Start == Iter.
@@ -774,7 +774,7 @@
}
}
-NullablePtr<SILInstruction>
+NullablePtr<SingleValueInstruction>
Projection::
createAggFromFirstLevelProjections(SILBuilder &B, SILLocation Loc,
SILType BaseType,
@@ -804,7 +804,7 @@
break;
case ProjectionKind::Enum:
if (auto *EI = dyn_cast<EnumInst>(I)) {
- if (EI->getElement() == getEnumElementDecl(I->getType())) {
+ if (EI->getElement() == getEnumElementDecl(EI->getType())) {
assert(EI->hasOperand() && "expected data operand");
return EI->getOperand();
}
@@ -853,7 +853,7 @@
return Tree.getNode(Parent.getValue());
}
-NullablePtr<SILInstruction>
+NullablePtr<SingleValueInstruction>
ProjectionTreeNode::
createProjection(SILBuilder &B, SILLocation Loc, SILValue Arg) const {
if (!Proj)
@@ -876,8 +876,17 @@
DEBUG(llvm::dbgs() << " " << *User);
- // First try to create a Projection for User.
- auto P = Projection(User);
+ // The projections we can handle are always single-value instructions.
+ auto projectionInst = dyn_cast<SingleValueInstruction>(User);
+ if (!projectionInst) {
+ DEBUG(llvm::dbgs() << " Failed to create projection. Adding "
+ "to non projection user!\n");
+ addNonProjectionUser(Op);
+ continue;
+ }
+
+ // Check whether the user is such a projection.
+ auto P = Projection(projectionInst);
// If we fail to create a projection, add User as a user to this node and
// continue.
@@ -890,8 +899,6 @@
DEBUG(llvm::dbgs() << " Created projection.\n");
- assert(User->hasValue() && "Projections should have a value");
-
// we have a projection to the next level children, create the next
// level children nodes lazily.
if (!Initialized)
@@ -906,7 +913,7 @@
DEBUG(llvm::dbgs() << " Found child for projection: "
<< ChildNode->getType() << "\n");
- SILValue V = SILValue(User);
+ SILValue V = SILValue(projectionInst);
Worklist.push_back({V, ChildNode});
} else {
DEBUG(llvm::dbgs() << " Did not find a child for projection!. "
@@ -993,7 +1000,7 @@
createNextLevelChildrenForTuple(Tree, TT);
}
-SILInstruction *
+SingleValueInstruction *
ProjectionTreeNode::
createAggregate(SILBuilder &B, SILLocation Loc, ArrayRef<SILValue> Args) const {
assert(Initialized && "Node must be initialized to create aggregates");
@@ -1042,7 +1049,7 @@
});
}
- SILInstruction *createInstruction() const {
+ SingleValueInstruction *createInstruction() const {
assert(isComplete() && "Cannot create instruction until the aggregate is "
"complete");
assert(!Invalidated && "Must not be invalidated to create an instruction");
@@ -1157,7 +1164,7 @@
}
// Form and return the aggregate.
- NullablePtr<swift::SILInstruction> AI =
+ NullablePtr<SingleValueInstruction> AI =
Projection::createAggFromFirstLevelProjections(Builder, Loc,
Node->getType(),
ChildValues);
@@ -1293,8 +1300,9 @@
// projection to the worklist for processing.
for (unsigned ChildIdx : reversed(Node->ChildProjections)) {
const ProjectionTreeNode *ChildNode = getNode(ChildIdx);
- SILInstruction *I = ChildNode->createProjection(B, Loc, V).get();
- DEBUG(llvm::dbgs() << " Adding Child: " << I->getType() << ": " << *I);
+ auto I = ChildNode->createProjection(B, Loc, V).get();
+ DEBUG(llvm::dbgs() << " Adding Child: " << I->getType() << ": "
+ << *I);
Worklist.push_back(std::make_tuple(ChildNode, SILValue(I)));
}
} else {
diff --git a/lib/SIL/SILBasicBlock.cpp b/lib/SIL/SILBasicBlock.cpp
index e989698..957136d 100644
--- a/lib/SIL/SILBasicBlock.cpp
+++ b/lib/SIL/SILBasicBlock.cpp
@@ -95,6 +95,14 @@
InstList.remove(I);
}
+void SILBasicBlock::eraseInstructions() {
+ for (auto It = begin(); It != end();) {
+ auto *Inst = &*It++;
+ Inst->replaceAllUsesOfAllResultsWithUndef();
+ Inst->eraseFromParent();
+ }
+}
+
/// Returns the iterator following the erased instruction.
SILBasicBlock::iterator SILBasicBlock::erase(SILInstruction *I) {
// Notify the delete handlers that this instruction is going away.
diff --git a/lib/SIL/SILBuilder.cpp b/lib/SIL/SILBuilder.cpp
index 36f4f67..06d7bff 100644
--- a/lib/SIL/SILBuilder.cpp
+++ b/lib/SIL/SILBuilder.cpp
@@ -90,9 +90,9 @@
// If legal, create an unchecked_ref_cast from the given operand and result
// type, otherwise return null.
-SILInstruction *SILBuilder::tryCreateUncheckedRefCast(SILLocation Loc,
- SILValue Op,
- SILType ResultTy) {
+SingleValueInstruction *
+SILBuilder::tryCreateUncheckedRefCast(SILLocation Loc, SILValue Op,
+ SILType ResultTy) {
if (!SILType::canRefCast(Op->getType(), ResultTy, getModule()))
return nullptr;
@@ -101,9 +101,8 @@
}
// Create the appropriate cast instruction based on result type.
-SILInstruction *SILBuilder::createUncheckedBitCast(SILLocation Loc,
- SILValue Op,
- SILType Ty) {
+SingleValueInstruction *
+SILBuilder::createUncheckedBitCast(SILLocation Loc, SILValue Op, SILType Ty) {
if (Ty.isTrivial(getModule()))
return insert(UncheckedTrivialBitCastInst::create(
getSILDebugLocation(Loc), Op, Ty, getFunction(), OpenedArchetypes));
@@ -415,21 +414,30 @@
while (I && I->getNumOperands() == 1 &&
I->getNumTypeDependentOperands() == 0) {
- I = dyn_cast<SILInstruction>(I->getOperand(0));
- if (!I || !Visited.insert(I).second)
+ // All the open instructions are single-value instructions.
+ auto SVI = dyn_cast<SingleValueInstruction>(I->getOperand(0));
+ // Within SimplifyCFG this function may be called for an instruction
+ // within unreachable code. And within an unreachable block it can happen
+ // that defs do not dominate uses (because there is no dominance defined).
+ // To avoid the infinite loop when following the chain of instructions via
+ // their operands, bail if the operand is not an instruction or this
+ // instruction was seen already.
+ if (!SVI || !Visited.insert(SVI).second)
return;
// If it is a definition of an opened archetype,
// register it and exit.
- auto Archetype = getOpenedArchetypeOf(I);
- if (!Archetype)
+ auto Archetype = getOpenedArchetypeOf(SVI);
+ if (!Archetype) {
+ I = SVI;
continue;
+ }
auto Def = OpenedArchetypes.getOpenedArchetypeDef(Archetype);
// Return if it is a known open archetype.
if (Def)
return;
// Otherwise register it and return.
if (OpenedArchetypesTracker)
- OpenedArchetypesTracker->addOpenedArchetypeDef(Archetype, I);
+ OpenedArchetypesTracker->addOpenedArchetypeDef(Archetype, SVI);
return;
}
diff --git a/lib/SIL/SILFunction.cpp b/lib/SIL/SILFunction.cpp
index 1e4747e..318f18f 100644
--- a/lib/SIL/SILFunction.cpp
+++ b/lib/SIL/SILFunction.cpp
@@ -57,7 +57,8 @@
SILModule &M, SILLinkage linkage, StringRef name,
CanSILFunctionType loweredType, GenericEnvironment *genericEnv,
Optional<SILLocation> loc, IsBare_t isBareSILFunction,
- IsTransparent_t isTrans, IsSerialized_t isSerialized, IsThunk_t isThunk,
+ IsTransparent_t isTrans, IsSerialized_t isSerialized,
+ ProfileCounter entryCount, IsThunk_t isThunk,
SubclassScope classSubclassScope, Inline_t inlineStrategy, EffectsKind E,
SILFunction *insertBefore, const SILDebugScope *debugScope) {
// Get a StringMapEntry for the function. As a sop to error cases,
@@ -72,8 +73,8 @@
auto fn = new (M) SILFunction(M, linkage, name, loweredType, genericEnv, loc,
isBareSILFunction, isTrans, isSerialized,
- isThunk, classSubclassScope, inlineStrategy, E,
- insertBefore, debugScope);
+ entryCount, isThunk, classSubclassScope,
+ inlineStrategy, E, insertBefore, debugScope);
if (entry) entry->setValue(fn);
return fn;
@@ -84,18 +85,18 @@
GenericEnvironment *genericEnv,
Optional<SILLocation> Loc, IsBare_t isBareSILFunction,
IsTransparent_t isTrans, IsSerialized_t isSerialized,
- IsThunk_t isThunk, SubclassScope classSubclassScope,
+ ProfileCounter entryCount, IsThunk_t isThunk,
+ SubclassScope classSubclassScope,
Inline_t inlineStrategy, EffectsKind E,
SILFunction *InsertBefore,
const SILDebugScope *DebugScope)
: Module(Module), Name(Name), LoweredType(LoweredType),
GenericEnv(genericEnv), SpecializationInfo(nullptr),
- DebugScope(DebugScope), Bare(isBareSILFunction),
- Transparent(isTrans), Serialized(isSerialized), Thunk(isThunk),
+ DebugScope(DebugScope), Bare(isBareSILFunction), Transparent(isTrans),
+ Serialized(isSerialized), Thunk(isThunk),
ClassSubclassScope(unsigned(classSubclassScope)), GlobalInitFlag(false),
InlineStrategy(inlineStrategy), Linkage(unsigned(Linkage)),
- KeepAsPublic(false), EffectsKindAttr(E) {
-
+ KeepAsPublic(false), EffectsKindAttr(E), EntryCount(entryCount) {
if (InsertBefore)
Module.functions.insert(SILModule::iterator(InsertBefore), this);
else
@@ -139,15 +140,25 @@
return SILDeclRef::isClangGenerated(getClangNode());
}
-void SILFunction::numberValues(llvm::DenseMap<const ValueBase*,
- unsigned> &ValueToNumberMap) const {
+void SILFunction::numberValues(llvm::DenseMap<const SILNode*, unsigned> &
+ ValueToNumberMap) const {
unsigned idx = 0;
for (auto &BB : *this) {
for (auto I = BB.args_begin(), E = BB.args_end(); I != E; ++I)
ValueToNumberMap[*I] = idx++;
- for (auto &I : BB)
- ValueToNumberMap[&I] = idx++;
+ for (auto &I : BB) {
+ auto results = I.getResults();
+ if (results.empty()) {
+ ValueToNumberMap[&I] = idx++;
+ } else {
+ // Assign the instruction node the first result ID.
+ ValueToNumberMap[&I] = idx;
+ for (auto result : results) {
+ ValueToNumberMap[result] = idx++;
+ }
+ }
+ }
}
}
diff --git a/lib/SIL/SILFunctionType.cpp b/lib/SIL/SILFunctionType.cpp
index 4a51087..dbb400d 100644
--- a/lib/SIL/SILFunctionType.cpp
+++ b/lib/SIL/SILFunctionType.cpp
@@ -100,6 +100,9 @@
assert(getRepresentation() == SILFunctionTypeRepresentation::WitnessMethod);
auto selfTy = getSelfInstanceType();
if (auto paramTy = dyn_cast<GenericTypeParamType>(selfTy)) {
+ auto superclass = GenericSig->getSuperclassBound(paramTy, M);
+ if (superclass)
+ return nullptr;
assert(paramTy->getDepth() == 0 && paramTy->getIndex() == 0);
auto protos = GenericSig->getConformsTo(paramTy, M);
assert(protos.size() == 1);
diff --git a/lib/SIL/SILGlobalVariable.cpp b/lib/SIL/SILGlobalVariable.cpp
index bffc48f..58612ac 100644
--- a/lib/SIL/SILGlobalVariable.cpp
+++ b/lib/SIL/SILGlobalVariable.cpp
@@ -79,7 +79,7 @@
bool SILGlobalVariable::isValidStaticInitializerInst(const SILInstruction *I,
SILModule &M) {
switch (I->getKind()) {
- case ValueKind::BuiltinInst: {
+ case SILInstructionKind::BuiltinInst: {
auto *bi = cast<BuiltinInst>(I);
switch (M.getBuiltinInfo(bi->getName()).ID) {
case BuiltinValueKind::PtrToInt:
@@ -91,7 +91,7 @@
}
return false;
}
- case ValueKind::StringLiteralInst:
+ case SILInstructionKind::StringLiteralInst:
switch (cast<StringLiteralInst>(I)->getEncoding()) {
case StringLiteralInst::Encoding::UTF8:
case StringLiteralInst::Encoding::UTF16:
@@ -102,11 +102,11 @@
return false;
}
return false;
- case ValueKind::StructInst:
- case ValueKind::TupleInst:
- case ValueKind::IntegerLiteralInst:
- case ValueKind::FloatLiteralInst:
- case ValueKind::ObjectInst:
+ case SILInstructionKind::StructInst:
+ case SILInstructionKind::TupleInst:
+ case SILInstructionKind::IntegerLiteralInst:
+ case SILInstructionKind::FloatLiteralInst:
+ case SILInstructionKind::ObjectInst:
return true;
default:
return false;
diff --git a/lib/SIL/SILInstruction.cpp b/lib/SIL/SILInstruction.cpp
index 90fc0f3..ca7832d 100644
--- a/lib/SIL/SILInstruction.cpp
+++ b/lib/SIL/SILInstruction.cpp
@@ -94,8 +94,8 @@
//===----------------------------------------------------------------------===//
// Assert that all subclasses of ValueBase implement classof.
-#define VALUE(CLASS, PARENT) \
- ASSERT_IMPLEMENTS_STATIC(CLASS, PARENT, classof, bool(const ValueBase*));
+#define NODE(CLASS, PARENT) \
+ ASSERT_IMPLEMENTS_STATIC(CLASS, PARENT, classof, bool(const SILNode*));
#include "swift/SIL/SILNodes.def"
SILFunction *SILInstruction::getFunction() {
@@ -113,7 +113,11 @@
/// block and deletes it.
///
void SILInstruction::eraseFromParent() {
- assert(use_empty() && "There are uses of instruction being deleted.");
+#ifndef NDEBUG
+ for (auto result : getResults()) {
+ assert(result->use_empty() && "Uses of SILInstruction remain at deletion.");
+ }
+#endif
getParent()->erase(this);
}
@@ -168,16 +172,33 @@
}
}
+ArrayRef<ValueBase> SILInstruction::getResultsImpl() const {
+ switch (getKind()) {
+#define NON_VALUE_INST(ID, NAME, PARENT, MEMBEHAVIOR, MAYRELEASE) \
+ case SILInstructionKind::ID:
+#include "swift/SIL/SILNodes.def"
+ return {};
+
+#define SINGLE_VALUE_INST(ID, NAME, PARENT, MEMBEHAVIOR, MAYRELEASE) \
+ case SILInstructionKind::ID:
+#include "swift/SIL/SILNodes.def"
+ return static_cast<const SingleValueInstruction *>(this)->getResultsImpl();
+
+ // add any multi-result instructions here...
+ }
+ llvm_unreachable("bad kind");
+}
+
// Initialize the static members of SILInstruction.
int SILInstruction::NumCreatedInstructions = 0;
int SILInstruction::NumDeletedInstructions = 0;
/// Map a SILInstruction name to its SILInstructionKind.
-SILInstructionKind swift::getSILInstructionKind(StringRef InstName) {
- auto Kind = getSILValueKind(InstName);
- if (Kind >= ValueKind::First_SILInstruction &&
- Kind <= ValueKind::Last_SILInstruction)
- return SILInstructionKind(Kind);
+SILInstructionKind swift::getSILInstructionKind(StringRef name) {
+#define FULL_INST(ID, NAME, PARENT, MEMBEHAVIOR, MAYRELEASE) \
+ if (name == #NAME) \
+ return SILInstructionKind::ID;
+#include "swift/SIL/SILNodes.def"
#ifdef NDEBUG
llvm::errs() << "Unknown SIL instruction name\n";
@@ -187,15 +208,45 @@
}
/// Map SILInstructionKind to a corresponding SILInstruction name.
-StringRef swift::getSILInstructionName(SILInstructionKind Kind) {
- return getSILValueName(ValueKind(Kind));
+StringRef swift::getSILInstructionName(SILInstructionKind kind) {
+ switch (kind) {
+#define FULL_INST(ID, NAME, PARENT, MEMBEHAVIOR, MAYRELEASE) \
+ case SILInstructionKind::ID: \
+ return #NAME;
+#include "swift/SIL/SILNodes.def"
+ }
+ llvm_unreachable("bad kind");
+}
+
+void SILInstruction::replaceAllUsesOfAllResultsWithUndef() {
+ for (auto result : getResults()) {
+ result->replaceAllUsesWithUndef();
+ }
+}
+
+void SILInstruction::replaceAllUsesPairwiseWith(SILInstruction *other) {
+ auto results = getResults();
+
+ // If we don't have any results, fast-path out without asking the other
+ // instruction for its results.
+ if (results.empty()) {
+ assert(other->getResults().empty());
+ return;
+ }
+
+ // Replace values with the corresponding values of the other instruction.
+ auto otherResults = other->getResults();
+ assert(results.size() == otherResults.size());
+ for (auto i : indices(results)) {
+ results[i]->replaceAllUsesWith(otherResults[i]);
+ }
}
namespace {
class InstructionDestroyer
: public SILInstructionVisitor<InstructionDestroyer> {
public:
-#define INST(CLASS, PARENT, TEXTUALNAME, MEMBEHAVIOR, MAYRELEASE) \
+#define INST(CLASS, PARENT) \
void visit##CLASS(CLASS *I) { I->~CLASS(); }
#include "swift/SIL/SILNodes.def"
};
@@ -216,7 +267,7 @@
InstructionIdentityComparer(const SILInstruction *L) : LHS(L) { }
/// Make sure we only process instructions we know how to process.
- bool visitValueBase(const ValueBase *RHS) {
+ bool visitSILInstruction(const SILInstruction *RHS) {
return false;
}
@@ -735,14 +786,10 @@
}
namespace {
- class AllOperandsAccessor : public SILVisitor<AllOperandsAccessor,
- ArrayRef<Operand> > {
+ class AllOperandsAccessor : public SILInstructionVisitor<AllOperandsAccessor,
+ ArrayRef<Operand> > {
public:
-#define VALUE(CLASS, PARENT) \
- ArrayRef<Operand> visit##CLASS(const CLASS *I) { \
- llvm_unreachable("accessing non-instruction " #CLASS); \
- }
-#define INST(CLASS, PARENT, TEXTUALNAME, MEMBEHAVIOR, RELEASINGBEHAVIOR) \
+#define INST(CLASS, PARENT) \
ArrayRef<Operand> visit##CLASS(const CLASS *I) { \
ASSERT_IMPLEMENTS(CLASS, SILInstruction, getAllOperands, \
ArrayRef<Operand>() const); \
@@ -752,14 +799,10 @@
};
class AllOperandsMutableAccessor
- : public SILVisitor<AllOperandsMutableAccessor,
- MutableArrayRef<Operand> > {
+ : public SILInstructionVisitor<AllOperandsMutableAccessor,
+ MutableArrayRef<Operand> > {
public:
-#define VALUE(CLASS, PARENT) \
- MutableArrayRef<Operand> visit##CLASS(const CLASS *I) { \
- llvm_unreachable("accessing non-instruction " #CLASS); \
- }
-#define INST(CLASS, PARENT, TEXTUALNAME, MEMBEHAVIOR, RELEASINGBEHAVIOR) \
+#define INST(CLASS, PARENT) \
MutableArrayRef<Operand> visit##CLASS(CLASS *I) { \
ASSERT_IMPLEMENTS(CLASS, SILInstruction, getAllOperands, \
MutableArrayRef<Operand>()); \
@@ -773,14 +816,10 @@
ExpectedType)>::value)
class TypeDependentOperandsAccessor
- : public SILVisitor<TypeDependentOperandsAccessor,
- ArrayRef<Operand>> {
+ : public SILInstructionVisitor<TypeDependentOperandsAccessor,
+ ArrayRef<Operand>> {
public:
-#define VALUE(CLASS, PARENT) \
- ArrayRef<Operand> visit##CLASS(const CLASS *I) { \
- llvm_unreachable("accessing non-instruction " #CLASS); \
- }
-#define INST(CLASS, PARENT, TEXTUALNAME, MEMBEHAVIOR, RELEASINGBEHAVIOR) \
+#define INST(CLASS, PARENT) \
ArrayRef<Operand> visit##CLASS(const CLASS *I) { \
if (!IMPLEMENTS_METHOD(CLASS, SILInstruction, getTypeDependentOperands, \
ArrayRef<Operand>() const)) \
@@ -791,14 +830,10 @@
};
class TypeDependentOperandsMutableAccessor
- : public SILVisitor<TypeDependentOperandsMutableAccessor,
- MutableArrayRef<Operand> > {
+ : public SILInstructionVisitor<TypeDependentOperandsMutableAccessor,
+ MutableArrayRef<Operand> > {
public:
-#define VALUE(CLASS, PARENT) \
- MutableArrayRef<Operand> visit##CLASS(const CLASS *I) { \
- llvm_unreachable("accessing non-instruction " #CLASS); \
- }
-#define INST(CLASS, PARENT, TEXTUALNAME, MEMBEHAVIOR, RELEASINGBEHAVIOR) \
+#define INST(CLASS, PARENT) \
MutableArrayRef<Operand> visit##CLASS(CLASS *I) { \
if (!IMPLEMENTS_METHOD(CLASS, SILInstruction, getTypeDependentOperands, \
MutableArrayRef<Operand>())) \
@@ -868,28 +903,20 @@
}
switch (getKind()) {
-#define INST(CLASS, PARENT, TEXTUALNAME, MEMBEHAVIOR, RELEASINGBEHAVIOR) \
- case ValueKind::CLASS: \
+#define FULL_INST(CLASS, TEXTUALNAME, PARENT, MEMBEHAVIOR, RELEASINGBEHAVIOR) \
+ case SILInstructionKind::CLASS: \
return MemoryBehavior::MEMBEHAVIOR;
#include "swift/SIL/SILNodes.def"
- case ValueKind::SILPHIArgument:
- case ValueKind::SILFunctionArgument:
- case ValueKind::SILUndef:
- llvm_unreachable("Non-instructions are unreachable.");
}
llvm_unreachable("We've just exhausted the switch.");
}
SILInstruction::ReleasingBehavior SILInstruction::getReleasingBehavior() const {
switch (getKind()) {
-#define INST(CLASS, PARENT, TEXTUALNAME, MEMBEHAVIOR, RELEASINGBEHAVIOR) \
- case ValueKind::CLASS: \
+#define FULL_INST(CLASS, TEXTUALNAME, PARENT, MEMBEHAVIOR, RELEASINGBEHAVIOR) \
+ case SILInstructionKind::CLASS: \
return ReleasingBehavior::RELEASINGBEHAVIOR;
#include "swift/SIL/SILNodes.def"
- case ValueKind::SILPHIArgument:
- case ValueKind::SILFunctionArgument:
- case ValueKind::SILUndef:
- llvm_unreachable("Non-instructions are unreachable.");
}
llvm_unreachable("We've just exhausted the switch.");
}
@@ -914,37 +941,37 @@
default:
llvm_unreachable("Unhandled releasing instruction!");
- case ValueKind::ApplyInst:
- case ValueKind::TryApplyInst:
- case ValueKind::DestroyAddrInst:
- case ValueKind::StrongReleaseInst:
- case ValueKind::UnownedReleaseInst:
- case ValueKind::ReleaseValueInst:
- case ValueKind::ReleaseValueAddrInst:
+ case SILInstructionKind::ApplyInst:
+ case SILInstructionKind::TryApplyInst:
+ case SILInstructionKind::DestroyAddrInst:
+ case SILInstructionKind::StrongReleaseInst:
+ case SILInstructionKind::UnownedReleaseInst:
+ case SILInstructionKind::ReleaseValueInst:
+ case SILInstructionKind::ReleaseValueAddrInst:
return true;
- case ValueKind::DestroyValueInst:
+ case SILInstructionKind::DestroyValueInst:
assert(!SILModuleConventions(getModule()).useLoweredAddresses());
return true;
- case ValueKind::UnconditionalCheckedCastAddrInst:
- case ValueKind::UnconditionalCheckedCastValueInst:
+ case SILInstructionKind::UnconditionalCheckedCastAddrInst:
+ case SILInstructionKind::UnconditionalCheckedCastValueInst:
return true;
- case ValueKind::CheckedCastAddrBranchInst: {
+ case SILInstructionKind::CheckedCastAddrBranchInst: {
// Failing casts with take_always can release.
auto *Cast = cast<CheckedCastAddrBranchInst>(this);
return Cast->getConsumptionKind() == CastConsumptionKind::TakeAlways;
}
- case ValueKind::CopyAddrInst: {
+ case SILInstructionKind::CopyAddrInst: {
auto *CopyAddr = cast<CopyAddrInst>(this);
// copy_addr without initialization can cause a release.
return CopyAddr->isInitializationOfDest() ==
IsInitialization_t::IsNotInitialization;
}
- case ValueKind::BuiltinInst: {
+ case SILInstructionKind::BuiltinInst: {
auto *BI = cast<BuiltinInst>(this);
// Builtins without side effects also do not release.
if (!BI->mayHaveSideEffects())
@@ -976,8 +1003,8 @@
bool SILInstruction::mayReleaseOrReadRefCount() const {
switch (getKind()) {
- case ValueKind::IsUniqueInst:
- case ValueKind::IsUniqueOrPinnedInst:
+ case SILInstructionKind::IsUniqueInst:
+ case SILInstructionKind::IsUniqueOrPinnedInst:
return true;
default:
return mayRelease();
@@ -987,7 +1014,7 @@
namespace {
class TrivialCloner : public SILCloner<TrivialCloner> {
friend class SILCloner<TrivialCloner>;
- friend class SILVisitor<TrivialCloner>;
+ friend class SILInstructionVisitor<TrivialCloner>;
SILInstruction *Result = nullptr;
TrivialCloner(SILFunction *F) : SILCloner(*F) {}
public:
@@ -1084,9 +1111,9 @@
bool SILInstruction::mayTrap() const {
switch(getKind()) {
- case ValueKind::CondFailInst:
- case ValueKind::UnconditionalCheckedCastInst:
- case ValueKind::UnconditionalCheckedCastAddrInst:
+ case SILInstructionKind::CondFailInst:
+ case SILInstructionKind::UnconditionalCheckedCastInst:
+ case SILInstructionKind::UnconditionalCheckedCastAddrInst:
return true;
default:
return false;
diff --git a/lib/SIL/SILInstructions.cpp b/lib/SIL/SILInstructions.cpp
index e3fa6c5..23c9ab2 100644
--- a/lib/SIL/SILInstructions.cpp
+++ b/lib/SIL/SILInstructions.cpp
@@ -131,8 +131,7 @@
ArrayRef<SILValue> TypeDependentOperands,
SILFunction &F,
SILDebugVariable Var)
- : AllocationInst(ValueKind::AllocStackInst, Loc,
- elementType.getAddressType()),
+ : InstructionBase(Loc, elementType.getAddressType()),
NumOperands(TypeDependentOperands.size()),
VarInfo(Var, getTrailingObjects<char>()) {
TrailingOperandsList::InitOperandsList(getAllOperands().begin(), this,
@@ -159,7 +158,7 @@
return getLoc().getAsASTNode<VarDecl>();
}
-AllocRefInstBase::AllocRefInstBase(ValueKind Kind,
+AllocRefInstBase::AllocRefInstBase(SILInstructionKind Kind,
SILDebugLocation Loc,
SILType ObjectType,
bool objc, bool canBeOnStack,
@@ -231,8 +230,7 @@
AllocBoxInst::AllocBoxInst(SILDebugLocation Loc, CanSILBoxType BoxType,
ArrayRef<SILValue> TypeDependentOperands,
SILFunction &F, SILDebugVariable Var)
- : AllocationInst(ValueKind::AllocBoxInst, Loc,
- SILType::getPrimitiveObjectType(BoxType)),
+ : InstructionBase(Loc, SILType::getPrimitiveObjectType(BoxType)),
NumOperands(TypeDependentOperands.size()),
VarInfo(Var, getTrailingObjects<char>()) {
TrailingOperandsList::InitOperandsList(getAllOperands().begin(), this,
@@ -294,8 +292,7 @@
SILDebugLocation Loc, SILType ExistentialType, CanType ConcreteType,
ArrayRef<ProtocolConformanceRef> Conformances,
ArrayRef<SILValue> TypeDependentOperands, SILFunction *Parent)
- : AllocationInst(ValueKind::AllocExistentialBoxInst, Loc,
- ExistentialType.getObjectType()),
+ : InstructionBase(Loc, ExistentialType.getObjectType()),
NumOperands(TypeDependentOperands.size()),
ConcreteType(ConcreteType), Conformances(Conformances) {
TrailingOperandsList::InitOperandsList(getAllOperands().begin(), this,
@@ -374,7 +371,7 @@
BuiltinInst::BuiltinInst(SILDebugLocation Loc, Identifier Name,
SILType ReturnType, SubstitutionList Subs,
ArrayRef<SILValue> Args)
- : SILInstruction(ValueKind::BuiltinInst, Loc, ReturnType), Name(Name),
+ : InstructionBase(Loc, ReturnType), Name(Name),
NumSubstitutions(Subs.size()), Operands(this, Args) {
static_assert(IsTriviallyCopyable<Substitution>::value,
"assuming Substitution is trivially copyable");
@@ -402,8 +399,8 @@
ArrayRef<SILValue> Args, ArrayRef<SILValue> TypeDependentOperands,
bool isNonThrowing,
const GenericSpecializationInformation *SpecializationInfo)
- : ApplyInstBase(ValueKind::ApplyInst, Loc, Callee, SubstCalleeTy, Subs,
- Args, TypeDependentOperands, SpecializationInfo, Result) {
+ : InstructionBase(Loc, Callee, SubstCalleeTy, Subs, Args,
+ TypeDependentOperands, SpecializationInfo, Result) {
setNonThrowing(isNonThrowing);
}
@@ -452,9 +449,9 @@
// PartialApplyInst
// should derive the type of its result by partially applying the callee's
// type.
- : ApplyInstBase(ValueKind::PartialApplyInst, Loc, Callee, SubstCalleeTy,
- Subs, Args, TypeDependentOperands, SpecializationInfo,
- ClosureType) {}
+ : InstructionBase(Loc, Callee, SubstCalleeTy, Subs,
+ Args, TypeDependentOperands, SpecializationInfo,
+ ClosureType) {}
PartialApplyInst *PartialApplyInst::create(
SILDebugLocation Loc, SILValue Callee, ArrayRef<SILValue> Args,
@@ -476,10 +473,11 @@
SpecializationInfo);
}
-TryApplyInstBase::TryApplyInstBase(ValueKind valueKind, SILDebugLocation Loc,
+TryApplyInstBase::TryApplyInstBase(SILInstructionKind kind,
+ SILDebugLocation loc,
SILBasicBlock *normalBB,
SILBasicBlock *errorBB)
- : TermInst(valueKind, Loc), DestBBs{{this, normalBB}, {this, errorBB}} {}
+ : TermInst(kind, loc), DestBBs{{this, normalBB}, {this, errorBB}} {}
TryApplyInst::TryApplyInst(
SILDebugLocation Loc, SILValue callee, SILType substCalleeTy,
@@ -487,9 +485,9 @@
ArrayRef<SILValue> TypeDependentOperands, SILBasicBlock *normalBB,
SILBasicBlock *errorBB,
const GenericSpecializationInformation *SpecializationInfo)
- : ApplyInstBase(ValueKind::TryApplyInst, Loc, callee, substCalleeTy, subs,
- args, TypeDependentOperands, SpecializationInfo, normalBB,
- errorBB) {}
+ : InstructionBase(Loc, callee, substCalleeTy, subs, args,
+ TypeDependentOperands, SpecializationInfo, normalBB,
+ errorBB) {}
TryApplyInst *TryApplyInst::create(
SILDebugLocation Loc, SILValue callee, SubstitutionList subs,
@@ -509,7 +507,7 @@
}
FunctionRefInst::FunctionRefInst(SILDebugLocation Loc, SILFunction *F)
- : LiteralInst(ValueKind::FunctionRefInst, Loc, F->getLoweredType()),
+ : InstructionBase(Loc, F->getLoweredType()),
Function(F) {
F->incrementRefCount();
}
@@ -527,21 +525,18 @@
AllocGlobalInst::AllocGlobalInst(SILDebugLocation Loc,
SILGlobalVariable *Global)
- : SILInstruction(ValueKind::AllocGlobalInst, Loc),
+ : InstructionBase(Loc),
Global(Global) {}
-AllocGlobalInst::AllocGlobalInst(SILDebugLocation Loc)
- : SILInstruction(ValueKind::AllocGlobalInst, Loc) {}
-
GlobalAddrInst::GlobalAddrInst(SILDebugLocation DebugLoc,
SILGlobalVariable *Global)
- : GlobalAccessInst(ValueKind::GlobalAddrInst, DebugLoc, Global,
- Global->getLoweredType().getAddressType()) {}
+ : InstructionBase(DebugLoc, Global->getLoweredType().getAddressType(),
+ Global) {}
GlobalValueInst::GlobalValueInst(SILDebugLocation DebugLoc,
SILGlobalVariable *Global)
- : GlobalAccessInst(ValueKind::GlobalValueInst, DebugLoc, Global,
- Global->getLoweredType().getObjectType()) {}
+ : InstructionBase(DebugLoc, Global->getLoweredType().getObjectType(),
+ Global) {}
const IntrinsicInfo &BuiltinInst::getIntrinsicInfo() const {
@@ -571,7 +566,7 @@
IntegerLiteralInst::IntegerLiteralInst(SILDebugLocation Loc, SILType Ty,
const llvm::APInt &Value)
- : LiteralInst(ValueKind::IntegerLiteralInst, Loc, Ty),
+ : InstructionBase(Loc, Ty),
numBits(Value.getBitWidth()) {
std::uninitialized_copy_n(Value.getRawData(), Value.getNumWords(),
getTrailingObjects<llvm::APInt::WordType>());
@@ -616,7 +611,7 @@
FloatLiteralInst::FloatLiteralInst(SILDebugLocation Loc, SILType Ty,
const APInt &Bits)
- : LiteralInst(ValueKind::FloatLiteralInst, Loc, Ty),
+ : InstructionBase(Loc, Ty),
numBits(Bits.getBitWidth()) {
std::uninitialized_copy_n(Bits.getRawData(), Bits.getNumWords(),
getTrailingObjects<llvm::APInt::WordType>());
@@ -660,7 +655,7 @@
StringLiteralInst::StringLiteralInst(SILDebugLocation Loc, StringRef Text,
Encoding encoding, SILType Ty)
- : LiteralInst(ValueKind::StringLiteralInst, Loc, Ty), Length(Text.size()),
+ : InstructionBase(Loc, Ty), Length(Text.size()),
TheEncoding(encoding) {
memcpy(getTrailingObjects<char>(), Text.data(), Text.size());
}
@@ -684,7 +679,7 @@
ConstStringLiteralInst::ConstStringLiteralInst(SILDebugLocation Loc,
StringRef Text,
Encoding encoding, SILType Ty)
- : LiteralInst(ValueKind::ConstStringLiteralInst, Loc, Ty),
+ : InstructionBase(Loc, Ty),
Length(Text.size()), TheEncoding(encoding) {
memcpy(getTrailingObjects<char>(), Text.data(), Text.size());
}
@@ -709,17 +704,17 @@
StoreInst::StoreInst(
SILDebugLocation Loc, SILValue Src, SILValue Dest,
StoreOwnershipQualifier Qualifier = StoreOwnershipQualifier::Unqualified)
- : SILInstruction(ValueKind::StoreInst, Loc), Operands(this, Src, Dest),
+ : InstructionBase(Loc), Operands(this, Src, Dest),
OwnershipQualifier(Qualifier) {}
StoreBorrowInst::StoreBorrowInst(SILDebugLocation DebugLoc, SILValue Src,
SILValue Dest)
- : SILInstruction(ValueKind::StoreBorrowInst, DebugLoc, Dest->getType()),
+ : InstructionBase(DebugLoc, Dest->getType()),
Operands(this, Src, Dest) {}
EndBorrowInst::EndBorrowInst(SILDebugLocation DebugLoc, SILValue Src,
SILValue Dest)
- : SILInstruction(ValueKind::EndBorrowInst, DebugLoc),
+ : InstructionBase(DebugLoc),
Operands(this, Src, Dest) {}
EndBorrowArgumentInst::EndBorrowArgumentInst(SILDebugLocation DebugLoc,
@@ -747,7 +742,7 @@
}
AssignInst::AssignInst(SILDebugLocation Loc, SILValue Src, SILValue Dest)
- : SILInstruction(ValueKind::AssignInst, Loc), Operands(this, Src, Dest) {}
+ : InstructionBase(Loc), Operands(this, Src, Dest) {}
MarkFunctionEscapeInst *
MarkFunctionEscapeInst::create(SILDebugLocation Loc,
@@ -760,7 +755,7 @@
MarkFunctionEscapeInst::MarkFunctionEscapeInst(SILDebugLocation Loc,
ArrayRef<SILValue> Elems)
- : SILInstruction(ValueKind::MarkFunctionEscapeInst, Loc),
+ : InstructionBase(Loc),
Operands(this, Elems) {}
static SILType getPinResultType(SILType operandType) {
@@ -777,7 +772,7 @@
CopyAddrInst::CopyAddrInst(SILDebugLocation Loc, SILValue SrcLValue,
SILValue DestLValue, IsTake_t isTakeOfSrc,
IsInitialization_t isInitializationOfDest)
- : SILInstruction(ValueKind::CopyAddrInst, Loc), IsTakeOfSrc(isTakeOfSrc),
+ : InstructionBase(Loc), IsTakeOfSrc(isTakeOfSrc),
IsInitializationOfDest(isInitializationOfDest),
Operands(this, SrcLValue, DestLValue) {}
@@ -800,7 +795,7 @@
SILValue Index,
SILType BoundType,
ArrayRef<SILValue> TypeDependentOperands)
- : SILInstruction(ValueKind::BindMemoryInst, Loc),
+ : InstructionBase(Loc),
BoundType(BoundType),
NumOperands(NumFixedOpers + TypeDependentOperands.size()) {
TrailingOperandsList::InitOperandsList(getAllOperands().begin(), this,
@@ -812,13 +807,13 @@
CanType srcType,
SILValue dest,
CanType targetType)
- : SILInstruction(ValueKind::UncheckedRefCastAddrInst, Loc),
+ : InstructionBase(Loc),
Operands(this, src, dest), SourceType(srcType), TargetType(targetType) {}
UnconditionalCheckedCastAddrInst::UnconditionalCheckedCastAddrInst(
SILDebugLocation Loc, SILValue src, CanType srcType, SILValue dest,
CanType targetType)
- : SILInstruction(ValueKind::UnconditionalCheckedCastAddrInst, Loc),
+ : InstructionBase(Loc),
Operands(this, src, dest), SourceType(srcType), TargetType(targetType) {}
StructInst *StructInst::create(SILDebugLocation Loc, SILType Ty,
@@ -831,7 +826,7 @@
StructInst::StructInst(SILDebugLocation Loc, SILType Ty,
ArrayRef<SILValue> Elems)
- : SILInstruction(ValueKind::StructInst, Loc, Ty), Operands(this, Elems) {
+ : InstructionBase(Loc, Ty), Operands(this, Elems) {
assert(!Ty.getStructOrBoundGenericStruct()->hasUnreferenceableStorage());
}
@@ -846,7 +841,7 @@
ObjectInst::ObjectInst(SILDebugLocation Loc, SILType Ty,
ArrayRef<SILValue> Elems, unsigned NumBaseElements)
- : SILInstruction(ValueKind::ObjectInst, Loc, Ty),
+ : InstructionBase(Loc, Ty),
NumBaseElements(NumBaseElements), Operands(this, Elems) {}
TupleInst *TupleInst::create(SILDebugLocation Loc, SILType Ty,
@@ -859,11 +854,11 @@
TupleInst::TupleInst(SILDebugLocation Loc, SILType Ty,
ArrayRef<SILValue> Elems)
- : SILInstruction(ValueKind::TupleInst, Loc, Ty), Operands(this, Elems) {}
+ : InstructionBase(Loc, Ty), Operands(this, Elems) {}
MetatypeInst::MetatypeInst(SILDebugLocation Loc, SILType Metatype,
ArrayRef<SILValue> TypeDependentOperands)
- : SILInstruction(ValueKind::MetatypeInst, Loc, Metatype),
+ : InstructionBase(Loc, Metatype),
NumOperands(TypeDependentOperands.size()) {
TrailingOperandsList::InitOperandsList(getAllOperands().begin(), this,
TypeDependentOperands);
@@ -1038,31 +1033,32 @@
TermInst::SuccessorListTy TermInst::getSuccessors() {
-#define TERMINATOR(TYPE, PARENT, TEXTUALNAME, EFFECT, RELEASING) \
- if (auto I = dyn_cast<TYPE>(this)) \
- return I->getSuccessors();
+ switch (getKind()) {
+#define TERMINATOR(ID, NAME, PARENT, MEMBEHAVIOR, MAYRELEASE) \
+ case SILInstructionKind::ID: return cast<ID>(this)->getSuccessors();
#include "swift/SIL/SILNodes.def"
-
- llvm_unreachable("not a terminator?!");
+ default: llvm_unreachable("not a terminator");
+ }
+ llvm_unreachable("bad instruction kind");
}
bool TermInst::isFunctionExiting() const {
switch (getTermKind()) {
- case TermKind::BranchInst:
- case TermKind::CondBranchInst:
- case TermKind::SwitchValueInst:
- case TermKind::SwitchEnumInst:
- case TermKind::SwitchEnumAddrInst:
- case TermKind::DynamicMethodBranchInst:
- case TermKind::CheckedCastBranchInst:
- case TermKind::CheckedCastValueBranchInst:
- case TermKind::CheckedCastAddrBranchInst:
- case TermKind::UnreachableInst:
- case TermKind::TryApplyInst:
- return false;
- case TermKind::ReturnInst:
- case TermKind::ThrowInst:
- return true;
+ case TermKind::BranchInst:
+ case TermKind::CondBranchInst:
+ case TermKind::SwitchValueInst:
+ case TermKind::SwitchEnumInst:
+ case TermKind::SwitchEnumAddrInst:
+ case TermKind::DynamicMethodBranchInst:
+ case TermKind::CheckedCastBranchInst:
+ case TermKind::CheckedCastValueBranchInst:
+ case TermKind::CheckedCastAddrBranchInst:
+ case TermKind::UnreachableInst:
+ case TermKind::TryApplyInst:
+ return false;
+ case TermKind::ReturnInst:
+ case TermKind::ThrowInst:
+ return true;
}
llvm_unreachable("Unhandled TermKind in switch.");
@@ -1070,7 +1066,7 @@
BranchInst::BranchInst(SILDebugLocation Loc, SILBasicBlock *DestBB,
ArrayRef<SILValue> Args)
- : TermInst(ValueKind::BranchInst, Loc), DestBB(this, DestBB),
+ : InstructionBase(Loc), DestBB(this, DestBB),
Operands(this, Args) {}
BranchInst *BranchInst::create(SILDebugLocation Loc, SILBasicBlock *DestBB,
@@ -1090,26 +1086,32 @@
CondBranchInst::CondBranchInst(SILDebugLocation Loc, SILValue Condition,
SILBasicBlock *TrueBB, SILBasicBlock *FalseBB,
ArrayRef<SILValue> Args, unsigned NumTrue,
- unsigned NumFalse)
- : TermInst(ValueKind::CondBranchInst, Loc),
- DestBBs{{this, TrueBB}, {this, FalseBB}}, NumTrueArgs(NumTrue),
- NumFalseArgs(NumFalse), Operands(this, Args, Condition) {
+ unsigned NumFalse, ProfileCounter TrueBBCount,
+ ProfileCounter FalseBBCount)
+ : InstructionBase(Loc), DestBBs{{this, TrueBB, TrueBBCount},
+ {this, FalseBB, FalseBBCount}},
+ NumTrueArgs(NumTrue), NumFalseArgs(NumFalse),
+ Operands(this, Args, Condition) {
assert(Args.size() == (NumTrueArgs + NumFalseArgs) &&
"Invalid number of args");
assert(TrueBB != FalseBB && "Identical destinations");
}
-CondBranchInst *CondBranchInst::create(SILDebugLocation Loc,
- SILValue Condition,
+CondBranchInst *CondBranchInst::create(SILDebugLocation Loc, SILValue Condition,
SILBasicBlock *TrueBB,
- SILBasicBlock *FalseBB, SILFunction &F) {
- return create(Loc, Condition, TrueBB, {}, FalseBB, {}, F);
+ SILBasicBlock *FalseBB,
+ ProfileCounter TrueBBCount,
+ ProfileCounter FalseBBCount,
+ SILFunction &F) {
+ return create(Loc, Condition, TrueBB, {}, FalseBB, {}, TrueBBCount,
+ FalseBBCount, F);
}
CondBranchInst *
CondBranchInst::create(SILDebugLocation Loc, SILValue Condition,
SILBasicBlock *TrueBB, ArrayRef<SILValue> TrueArgs,
SILBasicBlock *FalseBB, ArrayRef<SILValue> FalseArgs,
+ ProfileCounter TrueBBCount, ProfileCounter FalseBBCount,
SILFunction &F) {
SmallVector<SILValue, 4> Args;
Args.append(TrueArgs.begin(), TrueArgs.end());
@@ -1119,7 +1121,8 @@
decltype(Operands)::getExtraSize(Args.size()),
alignof(CondBranchInst));
return ::new (Buffer) CondBranchInst(Loc, Condition, TrueBB, FalseBB, Args,
- TrueArgs.size(), FalseArgs.size());
+ TrueArgs.size(), FalseArgs.size(),
+ TrueBBCount, FalseBBCount);
}
OperandValueArrayRef CondBranchInst::getTrueArgs() const {
@@ -1209,7 +1212,7 @@
SILBasicBlock *DefaultBB,
ArrayRef<SILValue> Cases,
ArrayRef<SILBasicBlock *> BBs)
- : TermInst(ValueKind::SwitchValueInst, Loc), NumCases(Cases.size()),
+ : InstructionBase(Loc), NumCases(Cases.size()),
HasDefault(bool(DefaultBB)), Operands(this, Cases, Operand) {
// Initialize the successor array.
@@ -1281,9 +1284,9 @@
SelectValueInst::SelectValueInst(SILDebugLocation Loc, SILValue Operand,
SILType Type, SILValue DefaultResult,
ArrayRef<SILValue> CaseValuesAndResults)
- : SelectInstBase(ValueKind::SelectValueInst, Loc, Type,
- CaseValuesAndResults.size() / 2, bool(DefaultResult),
- CaseValuesAndResults, Operand) {
+ : InstructionBase(Loc, Type,
+ CaseValuesAndResults.size() / 2, bool(DefaultResult),
+ CaseValuesAndResults, Operand) {
unsigned OperandBitWidth = 0;
@@ -1333,9 +1336,10 @@
}
SelectEnumInstBase::SelectEnumInstBase(
- ValueKind Kind, SILDebugLocation Loc, SILValue Operand, SILType Ty,
+ SILInstructionKind Kind, SILDebugLocation Loc, SILType Ty, SILValue Operand,
SILValue DefaultValue,
- ArrayRef<std::pair<EnumElementDecl *, SILValue>> CaseValues)
+ ArrayRef<std::pair<EnumElementDecl *, SILValue>> CaseValues,
+ Optional<ArrayRef<ProfileCounter>> CaseCounts, ProfileCounter DefaultCount)
: SelectInstBase(Kind, Loc, Ty, CaseValues.size(), bool(DefaultValue),
getCaseOperands(CaseValues, DefaultValue), Operand) {
// Initialize the case and successor arrays.
@@ -1348,42 +1352,48 @@
template <typename SELECT_ENUM_INST>
SELECT_ENUM_INST *SelectEnumInstBase::createSelectEnum(
SILDebugLocation Loc, SILValue Operand, SILType Ty, SILValue DefaultValue,
- ArrayRef<std::pair<EnumElementDecl *, SILValue>> CaseValues,
- SILFunction &F) {
+ ArrayRef<std::pair<EnumElementDecl *, SILValue>> CaseValues, SILFunction &F,
+ Optional<ArrayRef<ProfileCounter>> CaseCounts,
+ ProfileCounter DefaultCount) {
// Allocate enough room for the instruction with tail-allocated
// EnumElementDecl and operand arrays. There are `CaseBBs.size()` decls
// and `CaseBBs.size() + (DefaultBB ? 1 : 0)` values.
unsigned numCases = CaseValues.size();
void *buf = F.getModule().allocateInst(
- sizeof(SELECT_ENUM_INST) + sizeof(EnumElementDecl*) * numCases
- + TailAllocatedOperandList<1>::getExtraSize(numCases + (bool)DefaultValue),
- alignof(SELECT_ENUM_INST));
- return ::new (buf) SELECT_ENUM_INST(Loc,Operand,Ty,DefaultValue,CaseValues);
+ sizeof(SELECT_ENUM_INST) + sizeof(EnumElementDecl *) * numCases +
+ sizeof(ProfileCounter) + TailAllocatedOperandList<1>::getExtraSize(
+ numCases + (bool)DefaultValue),
+ alignof(SELECT_ENUM_INST));
+ return ::new (buf) SELECT_ENUM_INST(Loc, Operand, Ty, DefaultValue,
+ CaseValues, CaseCounts, DefaultCount);
}
SelectEnumInst *SelectEnumInst::create(
- SILDebugLocation Loc, SILValue Operand, SILType Type,
- SILValue DefaultValue,
- ArrayRef<std::pair<EnumElementDecl *, SILValue>> CaseValues,
- SILFunction &F) {
+ SILDebugLocation Loc, SILValue Operand, SILType Type, SILValue DefaultValue,
+ ArrayRef<std::pair<EnumElementDecl *, SILValue>> CaseValues, SILFunction &F,
+ Optional<ArrayRef<ProfileCounter>> CaseCounts,
+ ProfileCounter DefaultCount) {
return createSelectEnum<SelectEnumInst>(Loc, Operand, Type, DefaultValue,
- CaseValues, F);
+ CaseValues, F, CaseCounts,
+ DefaultCount);
}
SelectEnumAddrInst *SelectEnumAddrInst::create(
- SILDebugLocation Loc, SILValue Operand, SILType Type,
- SILValue DefaultValue,
- ArrayRef<std::pair<EnumElementDecl *, SILValue>> CaseValues,
- SILFunction &F) {
+ SILDebugLocation Loc, SILValue Operand, SILType Type, SILValue DefaultValue,
+ ArrayRef<std::pair<EnumElementDecl *, SILValue>> CaseValues, SILFunction &F,
+ Optional<ArrayRef<ProfileCounter>> CaseCounts,
+ ProfileCounter DefaultCount) {
return createSelectEnum<SelectEnumAddrInst>(Loc, Operand, Type, DefaultValue,
- CaseValues, F);
+ CaseValues, F, CaseCounts,
+ DefaultCount);
}
SwitchEnumInstBase::SwitchEnumInstBase(
- ValueKind Kind, SILDebugLocation Loc, SILValue Operand,
+ SILInstructionKind Kind, SILDebugLocation Loc, SILValue Operand,
SILBasicBlock *DefaultBB,
- ArrayRef<std::pair<EnumElementDecl *, SILBasicBlock *>> CaseBBs)
+ ArrayRef<std::pair<EnumElementDecl *, SILBasicBlock *>> CaseBBs,
+ Optional<ArrayRef<ProfileCounter>> CaseCounts, ProfileCounter DefaultCount)
: TermInst(Kind, Loc), Operands(this, Operand), NumCases(CaseBBs.size()),
HasDefault(bool(DefaultBB)) {
// Initialize the case and successor arrays.
@@ -1391,11 +1401,17 @@
auto *succs = getSuccessorBuf();
for (unsigned i = 0, size = CaseBBs.size(); i < size; ++i) {
cases[i] = CaseBBs[i].first;
- ::new (succs + i) SILSuccessor(this, CaseBBs[i].second);
+ if (CaseCounts) {
+ ::new (succs + i)
+ SILSuccessor(this, CaseBBs[i].second, CaseCounts.getValue()[i]);
+ } else {
+ ::new (succs + i) SILSuccessor(this, CaseBBs[i].second);
+ }
}
- if (HasDefault)
- ::new (succs + NumCases) SILSuccessor(this, DefaultBB);
+ if (HasDefault) {
+ ::new (succs + NumCases) SILSuccessor(this, DefaultBB, DefaultCount);
+ }
}
void SwitchEnumInstBase::swapCase(unsigned i, unsigned j) {
@@ -1493,18 +1509,20 @@
SWITCH_ENUM_INST *SwitchEnumInstBase::createSwitchEnum(
SILDebugLocation Loc, SILValue Operand, SILBasicBlock *DefaultBB,
ArrayRef<std::pair<EnumElementDecl *, SILBasicBlock *>> CaseBBs,
- SILFunction &F) {
+ SILFunction &F, Optional<ArrayRef<ProfileCounter>> CaseCounts,
+ ProfileCounter DefaultCount) {
// Allocate enough room for the instruction with tail-allocated
// EnumElementDecl and SILSuccessor arrays. There are `CaseBBs.size()` decls
// and `CaseBBs.size() + (DefaultBB ? 1 : 0)` successors.
unsigned numCases = CaseBBs.size();
unsigned numSuccessors = numCases + (DefaultBB ? 1 : 0);
- void *buf = F.getModule().allocateInst(sizeof(SWITCH_ENUM_INST)
- + sizeof(EnumElementDecl*) * numCases
- + sizeof(SILSuccessor) * numSuccessors,
- alignof(SWITCH_ENUM_INST));
- return ::new (buf) SWITCH_ENUM_INST(Loc, Operand, DefaultBB, CaseBBs);
+ void *buf = F.getModule().allocateInst(
+ sizeof(SWITCH_ENUM_INST) + sizeof(EnumElementDecl *) * numCases +
+ sizeof(SILSuccessor) * numSuccessors,
+ alignof(SWITCH_ENUM_INST));
+ return ::new (buf) SWITCH_ENUM_INST(Loc, Operand, DefaultBB, CaseBBs,
+ CaseCounts, DefaultCount);
}
NullablePtr<EnumElementDecl> SwitchEnumInstBase::getUniqueCaseForDefault() {
@@ -1537,17 +1555,19 @@
SwitchEnumInst *SwitchEnumInst::create(
SILDebugLocation Loc, SILValue Operand, SILBasicBlock *DefaultBB,
ArrayRef<std::pair<EnumElementDecl *, SILBasicBlock *>> CaseBBs,
- SILFunction &F) {
- return
- createSwitchEnum<SwitchEnumInst>(Loc, Operand, DefaultBB, CaseBBs, F);
+ SILFunction &F, Optional<ArrayRef<ProfileCounter>> CaseCounts,
+ ProfileCounter DefaultCount) {
+ return createSwitchEnum<SwitchEnumInst>(Loc, Operand, DefaultBB, CaseBBs, F,
+ CaseCounts, DefaultCount);
}
SwitchEnumAddrInst *SwitchEnumAddrInst::create(
SILDebugLocation Loc, SILValue Operand, SILBasicBlock *DefaultBB,
ArrayRef<std::pair<EnumElementDecl *, SILBasicBlock *>> CaseBBs,
- SILFunction &F) {
- return createSwitchEnum<SwitchEnumAddrInst>
- (Loc, Operand, DefaultBB, CaseBBs, F);
+ SILFunction &F, Optional<ArrayRef<ProfileCounter>> CaseCounts,
+ ProfileCounter DefaultCount) {
+ return createSwitchEnum<SwitchEnumAddrInst>(Loc, Operand, DefaultBB, CaseBBs,
+ F, CaseCounts, DefaultCount);
}
DynamicMethodBranchInst::DynamicMethodBranchInst(SILDebugLocation Loc,
@@ -1555,7 +1575,7 @@
SILDeclRef Member,
SILBasicBlock *HasMethodBB,
SILBasicBlock *NoMethodBB)
- : TermInst(ValueKind::DynamicMethodBranchInst, Loc),
+ : InstructionBase(Loc),
Member(Member),
DestBBs{{this, HasMethodBB}, {this, NoMethodBB}},
Operands(this, Operand)
@@ -1760,7 +1780,7 @@
SubstitutionList SetterSubs,
SILValue Self,
SILType Ty)
- : SILInstruction(ValueKind::MarkUninitializedBehaviorInst, DebugLoc, Ty),
+ : InstructionBase(DebugLoc, Ty),
Operands(this, InitStorage, Storage, Setter, Self),
NumInitStorageSubstitutions(InitStorageSubs.size()),
NumSetterSubstitutions(SetterSubs.size())
@@ -1908,7 +1928,8 @@
CheckedCastBranchInst *CheckedCastBranchInst::create(
SILDebugLocation DebugLoc, bool IsExact, SILValue Operand, SILType DestTy,
SILBasicBlock *SuccessBB, SILBasicBlock *FailureBB, SILFunction &F,
- SILOpenedArchetypesState &OpenedArchetypes) {
+ SILOpenedArchetypesState &OpenedArchetypes, ProfileCounter Target1Count,
+ ProfileCounter Target2Count) {
SILModule &Mod = F.getModule();
SmallVector<SILValue, 8> TypeDependentOperands;
collectTypeDependentOperands(TypeDependentOperands, OpenedArchetypes, F,
@@ -1916,9 +1937,9 @@
unsigned size =
totalSizeToAlloc<swift::Operand>(1 + TypeDependentOperands.size());
void *Buffer = Mod.allocateInst(size, alignof(CheckedCastBranchInst));
- return ::new (Buffer) CheckedCastBranchInst(DebugLoc, IsExact, Operand,
- TypeDependentOperands, DestTy,
- SuccessBB, FailureBB);
+ return ::new (Buffer) CheckedCastBranchInst(
+ DebugLoc, IsExact, Operand, TypeDependentOperands, DestTy, SuccessBB,
+ FailureBB, Target1Count, Target2Count);
}
CheckedCastValueBranchInst *
@@ -2223,7 +2244,7 @@
SubstitutionList Subs,
ArrayRef<SILValue> Args,
SILType Ty)
- : SILInstruction(ValueKind::KeyPathInst, Loc, Ty),
+ : InstructionBase(Loc, Ty),
Pattern(Pattern), NumSubstitutions(Subs.size()),
NumOperands(Pattern->getNumOperands())
{
diff --git a/lib/SIL/SILModule.cpp b/lib/SIL/SILModule.cpp
index 6f5628b..a58001d 100644
--- a/lib/SIL/SILModule.cpp
+++ b/lib/SIL/SILModule.cpp
@@ -229,15 +229,11 @@
witnessTables.erase(Wt);
}
-SILFunction *SILModule::getOrCreateFunction(SILLocation loc,
- StringRef name,
- SILLinkage linkage,
- CanSILFunctionType type,
- IsBare_t isBareSILFunction,
- IsTransparent_t isTransparent,
- IsSerialized_t isSerialized,
- IsThunk_t isThunk,
- SubclassScope subclassScope) {
+SILFunction *SILModule::getOrCreateFunction(
+ SILLocation loc, StringRef name, SILLinkage linkage,
+ CanSILFunctionType type, IsBare_t isBareSILFunction,
+ IsTransparent_t isTransparent, IsSerialized_t isSerialized,
+ ProfileCounter entryCount, IsThunk_t isThunk, SubclassScope subclassScope) {
if (auto fn = lookUpFunction(name)) {
assert(fn->getLoweredFunctionType() == type);
assert(fn->getLinkage() == linkage ||
@@ -245,9 +241,9 @@
return fn;
}
- auto fn = SILFunction::create(*this, linkage, name, type, nullptr,
- loc, isBareSILFunction, isTransparent,
- isSerialized, isThunk, subclassScope);
+ auto fn = SILFunction::create(*this, linkage, name, type, nullptr, loc,
+ isBareSILFunction, isTransparent, isSerialized,
+ entryCount, isThunk, subclassScope);
fn->setDebugScope(new (*this) SILDebugScope(loc, fn));
return fn;
}
@@ -282,7 +278,8 @@
SILFunction *SILModule::getOrCreateFunction(SILLocation loc,
SILDeclRef constant,
- ForDefinition_t forDefinition) {
+ ForDefinition_t forDefinition,
+ ProfileCounter entryCount) {
auto name = constant.mangle();
auto constantType = Types.getConstantType(constant).castTo<SILFunctionType>();
@@ -320,11 +317,10 @@
else if (constant.isAlwaysInline())
inlineStrategy = AlwaysInline;
- auto *F = SILFunction::create(*this, linkage, name,
- constantType, nullptr,
- None, IsNotBare, IsTrans, IsSer, IsNotThunk,
- constant.getSubclassScope(),
- inlineStrategy, EK);
+ auto *F =
+ SILFunction::create(*this, linkage, name, constantType, nullptr, None,
+ IsNotBare, IsTrans, IsSer, entryCount, IsNotThunk,
+ constant.getSubclassScope(), inlineStrategy, EK);
F->setDebugScope(new (*this) SILDebugScope(loc, F));
F->setGlobalInit(constant.isGlobal());
@@ -364,30 +360,26 @@
return F;
}
-
-SILFunction *SILModule::getOrCreateSharedFunction(SILLocation loc,
- StringRef name,
- CanSILFunctionType type,
- IsBare_t isBareSILFunction,
- IsTransparent_t isTransparent,
- IsSerialized_t isSerialized,
- IsThunk_t isThunk) {
- return getOrCreateFunction(loc, name, SILLinkage::Shared,
- type, isBareSILFunction, isTransparent, isSerialized,
- isThunk, SubclassScope::NotApplicable);
+SILFunction *SILModule::getOrCreateSharedFunction(
+ SILLocation loc, StringRef name, CanSILFunctionType type,
+ IsBare_t isBareSILFunction, IsTransparent_t isTransparent,
+ IsSerialized_t isSerialized, ProfileCounter entryCount, IsThunk_t isThunk) {
+ return getOrCreateFunction(loc, name, SILLinkage::Shared, type,
+ isBareSILFunction, isTransparent, isSerialized,
+ entryCount, isThunk, SubclassScope::NotApplicable);
}
SILFunction *SILModule::createFunction(
SILLinkage linkage, StringRef name, CanSILFunctionType loweredType,
GenericEnvironment *genericEnv, Optional<SILLocation> loc,
IsBare_t isBareSILFunction, IsTransparent_t isTrans,
- IsSerialized_t isSerialized, IsThunk_t isThunk, SubclassScope subclassScope,
- Inline_t inlineStrategy, EffectsKind EK, SILFunction *InsertBefore,
- const SILDebugScope *DebugScope) {
+ IsSerialized_t isSerialized, ProfileCounter entryCount, IsThunk_t isThunk,
+ SubclassScope subclassScope, Inline_t inlineStrategy, EffectsKind EK,
+ SILFunction *InsertBefore, const SILDebugScope *DebugScope) {
return SILFunction::create(*this, linkage, name, loweredType, genericEnv, loc,
- isBareSILFunction, isTrans, isSerialized, isThunk,
- subclassScope, inlineStrategy, EK, InsertBefore,
- DebugScope);
+ isBareSILFunction, isTrans, isSerialized,
+ entryCount, isThunk, subclassScope, inlineStrategy,
+ EK, InsertBefore, DebugScope);
}
const IntrinsicInfo &SILModule::getIntrinsicInfo(Identifier ID) {
@@ -734,9 +726,9 @@
NotificationHandlers.remove(Handler);
}
-void SILModule::notifyDeleteHandlers(ValueBase *V) {
+void SILModule::notifyDeleteHandlers(SILNode *node) {
for (auto *Handler : NotificationHandlers) {
- Handler->handleDeleteNotification(V);
+ Handler->handleDeleteNotification(node);
}
}
diff --git a/lib/SIL/SILOpenedArchetypesTracker.cpp b/lib/SIL/SILOpenedArchetypesTracker.cpp
index 82552e1..e3e8b7f 100644
--- a/lib/SIL/SILOpenedArchetypesTracker.cpp
+++ b/lib/SIL/SILOpenedArchetypesTracker.cpp
@@ -16,7 +16,7 @@
using namespace swift;
void SILOpenedArchetypesTracker::addOpenedArchetypeDef(CanArchetypeType archetype,
- SILValue Def) {
+ SingleValueInstruction *Def) {
auto OldDef = getOpenedArchetypeDef(archetype);
if (OldDef) {
if (auto *OldI = dyn_cast<GlobalAddrInst>(OldDef)) {
@@ -25,7 +25,7 @@
OldDef->replaceAllUsesWith(Def);
// Remove the placeholder instruction.
OldI->eraseFromParent();
- OldDef = SILValue();
+ OldDef = nullptr;
}
}
assert((!OldDef || OldDef == Def) &&
@@ -65,7 +65,7 @@
auto &SILMod = CurF->getModule();
// Create a placeholder representing a forward definition.
// Add the placeholder at the beginning of the entry block.
- SILValue Placeholder;
+ SingleValueInstruction *Placeholder;
if (!CurF->getEntryBlock()->empty()) {
SILBuilder B(CurF->getEntryBlock()->begin());
Placeholder =
@@ -95,7 +95,9 @@
auto Archetype = getOpenedArchetypeOf(I);
if (!Archetype)
return false;
- addOpenedArchetypeDef(Archetype, I);
+ auto SVI =
+ const_cast<SingleValueInstruction*>(cast<SingleValueInstruction>(I));
+ addOpenedArchetypeDef(Archetype, SVI);
return true;
}
@@ -108,8 +110,8 @@
bool Registered = false;
for (auto &Op : I->getTypeDependentOperands()) {
auto OpenedArchetypeDef = Op.get();
- if (auto *DefInst = dyn_cast<SILInstruction>(OpenedArchetypeDef)) {
- addOpenedArchetypeDef(getOpenedArchetypeOf(DefInst), OpenedArchetypeDef);
+ if (auto *DefInst = dyn_cast<SingleValueInstruction>(OpenedArchetypeDef)) {
+ addOpenedArchetypeDef(getOpenedArchetypeOf(DefInst), DefInst);
Registered = true;
}
}
@@ -122,19 +124,23 @@
const SILInstruction *I) {
assert(I->getFunction() == getFunction() &&
"Instruction does not belong to a proper SILFunction");
- auto Archetype = getOpenedArchetypeOf(I);
+ auto archetype = getOpenedArchetypeOf(I);
// Remove the archetype definition if it was registered before.
// It may happen that this archetype was not registered in the
// SILOpenedArchetypesTracker, because the tracker was created
// without scanning the whole function and thus may not aware
// of all opened archetypes of the function.
- if (Archetype && getOpenedArchetypeDef(Archetype))
- removeOpenedArchetypeDef(Archetype, I);
+ if (archetype) {
+ auto def = getOpenedArchetypeDef(archetype);
+ if (def == I) {
+ OpenedArchetypeDefs.erase(archetype);
+ }
+ }
}
void SILOpenedArchetypesTracker::handleDeleteNotification(
- swift::ValueBase *Value) {
- if (auto I = dyn_cast<SILInstruction>(Value))
+ swift::SILNode *node) {
+ if (auto I = dyn_cast<SILInstruction>(node))
if (I->getFunction() == getFunction())
unregisterOpenedArchetypes(I);
}
@@ -145,7 +151,8 @@
if (isa<OpenExistentialAddrInst>(I) || isa<OpenExistentialRefInst>(I) ||
isa<OpenExistentialBoxInst>(I) || isa<OpenExistentialBoxValueInst>(I) ||
isa<OpenExistentialMetatypeInst>(I) || isa<OpenExistentialValueInst>(I)) {
- auto Ty = getOpenedArchetypeOf(I->getType().getSwiftRValueType());
+ auto SVI = cast<SingleValueInstruction>(I);
+ auto Ty = getOpenedArchetypeOf(SVI->getType().getSwiftRValueType());
assert(Ty && Ty->isOpenedExistential() &&
"Type should be an opened archetype");
return Ty;
@@ -180,9 +187,9 @@
// First perform a quick check.
for (auto &Op : OpenedArchetypeOperands) {
auto Def = Op.get();
- if (isa<SILInstruction>(Def) &&
- getOpenedArchetypeOf(cast<SILInstruction>(Def)) == archetypeTy)
- return Def;
+ if (auto SVI = dyn_cast<SingleValueInstruction>(Def))
+ if (getOpenedArchetypeOf(SVI) == archetypeTy)
+ return Def;
}
// Then use a regular lookup.
if (OpenedArchetypesTracker)
diff --git a/lib/SIL/SILOwnershipVerifier.cpp b/lib/SIL/SILOwnershipVerifier.cpp
index 1553796..307c4fc 100644
--- a/lib/SIL/SILOwnershipVerifier.cpp
+++ b/lib/SIL/SILOwnershipVerifier.cpp
@@ -191,23 +191,23 @@
}
// These operations forward both owned and guaranteed ownership.
-static bool isOwnershipForwardingValueKind(ValueKind K) {
+static bool isOwnershipForwardingValueKind(SILNodeKind K) {
switch (K) {
- case ValueKind::TupleInst:
- case ValueKind::StructInst:
- case ValueKind::EnumInst:
- case ValueKind::OpenExistentialRefInst:
- case ValueKind::UpcastInst:
- case ValueKind::UncheckedRefCastInst:
- case ValueKind::ConvertFunctionInst:
- case ValueKind::RefToBridgeObjectInst:
- case ValueKind::BridgeObjectToRefInst:
- case ValueKind::UnconditionalCheckedCastInst:
- case ValueKind::UncheckedEnumDataInst:
- case ValueKind::MarkUninitializedInst:
- case ValueKind::SelectEnumInst:
- case ValueKind::SwitchEnumInst:
- case ValueKind::CheckedCastBranchInst:
+ case SILNodeKind::TupleInst:
+ case SILNodeKind::StructInst:
+ case SILNodeKind::EnumInst:
+ case SILNodeKind::OpenExistentialRefInst:
+ case SILNodeKind::UpcastInst:
+ case SILNodeKind::UncheckedRefCastInst:
+ case SILNodeKind::ConvertFunctionInst:
+ case SILNodeKind::RefToBridgeObjectInst:
+ case SILNodeKind::BridgeObjectToRefInst:
+ case SILNodeKind::UnconditionalCheckedCastInst:
+ case SILNodeKind::UncheckedEnumDataInst:
+ case SILNodeKind::MarkUninitializedInst:
+ case SILNodeKind::SelectEnumInst:
+ case SILNodeKind::SwitchEnumInst:
+ case SILNodeKind::CheckedCastBranchInst:
return true;
default:
return false;
@@ -216,12 +216,12 @@
// These operations forward guaranteed ownership, but don't necessarily forward
// owned values.
-static bool isGuaranteedForwardingValueKind(ValueKind K) {
+static bool isGuaranteedForwardingValueKind(SILNodeKind K) {
switch (K) {
- case ValueKind::TupleExtractInst:
- case ValueKind::StructExtractInst:
- case ValueKind::OpenExistentialValueInst:
- case ValueKind::OpenExistentialBoxValueInst:
+ case SILNodeKind::TupleExtractInst:
+ case SILNodeKind::StructExtractInst:
+ case SILNodeKind::OpenExistentialValueInst:
+ case SILNodeKind::OpenExistentialBoxValueInst:
return true;
default:
return isOwnershipForwardingValueKind(K);
@@ -229,15 +229,15 @@
}
static bool isGuaranteedForwardingValue(SILValue V) {
- return isGuaranteedForwardingValueKind(V->getKind());
+ return isGuaranteedForwardingValueKind(SILNodeKind(V->getKind()));
}
static bool isGuaranteedForwardingInst(SILInstruction *I) {
- return isGuaranteedForwardingValueKind(I->getKind());
+ return isGuaranteedForwardingValueKind(SILNodeKind(I->getKind()));
}
static bool isOwnershipForwardingInst(SILInstruction *I) {
- return isOwnershipForwardingValueKind(I->getKind());
+ return isOwnershipForwardingValueKind(SILNodeKind(I->getKind()));
}
//===----------------------------------------------------------------------===//
@@ -403,17 +403,13 @@
return Result.ShouldCheckForDataflowViolations;
}
- OwnershipUseCheckerResult visitValueBase(ValueBase *) {
- llvm_unreachable("Unimplemented?!");
- }
-
OwnershipUseCheckerResult visitCallee(CanSILFunctionType SubstCalleeType);
OwnershipUseCheckerResult
checkTerminatorArgumentMatchesDestBB(SILBasicBlock *DestBB, unsigned OpIndex);
// Create declarations for all instructions, so we get a warning at compile
// time if any instructions do not have an implementation.
-#define INST(Id, Parent, TextualName, MemBehavior, MayRelease) \
+#define INST(Id, Parent) \
OwnershipUseCheckerResult visit##Id(Id *);
#include "swift/SIL/SILNodes.def"
};
@@ -1691,20 +1687,28 @@
// or trivial. We now split into two cases, if the user is a terminator or
// not. If we do not have a terminator, then just add User->getUses() to the
// worklist.
- auto *TI = dyn_cast<TermInst>(User);
- if (!TI) {
- if (SILValue(User).getOwnershipKind() == ValueOwnershipKind::Trivial) {
+ if (auto *value = dyn_cast<SingleValueInstruction>(User)) {
+ if (SILValue(value).getOwnershipKind() == ValueOwnershipKind::Trivial) {
continue;
}
// Now, we /must/ have a guaranteed subobject, so lets assert that the
// user
// is actually guaranteed and add the subobject's users to our worklist.
- assert(SILValue(User).getOwnershipKind() ==
+ assert(SILValue(value).getOwnershipKind() ==
ValueOwnershipKind::Guaranteed &&
"Our value is guaranteed and this is a forwarding instruction. "
"Should have guaranteed ownership as well.");
- std::copy(User->use_begin(), User->use_end(), std::back_inserter(Users));
+ std::copy(value->use_begin(), value->use_end(),
+ std::back_inserter(Users));
+ continue;
+ }
+
+ // TODO: MultiValueInstruction
+ assert(User->getResults().empty());
+
+ auto *TI = dyn_cast<TermInst>(User);
+ if (!TI) {
continue;
}
diff --git a/lib/SIL/SILPrinter.cpp b/lib/SIL/SILPrinter.cpp
index 586da8c..351c3c6 100644
--- a/lib/SIL/SILPrinter.cpp
+++ b/lib/SIL/SILPrinter.cpp
@@ -447,13 +447,12 @@
/// SILPrinter class - This holds the internal implementation details of
/// printing SIL structures.
-class SILPrinter : public SILVisitor<SILPrinter> {
+class SILPrinter : public SILInstructionVisitor<SILPrinter> {
SILPrintContext &Ctx;
struct {
llvm::formatted_raw_ostream OS;
PrintOptions ASTOptions;
} PrintState;
- SILValue subjectValue;
unsigned LastBufferID;
// Printers for the underlying stream.
@@ -464,6 +463,7 @@
}
SIMPLE_PRINTER(char)
SIMPLE_PRINTER(unsigned)
+ SIMPLE_PRINTER(uint64_t)
SIMPLE_PRINTER(StringRef)
SIMPLE_PRINTER(Identifier)
SIMPLE_PRINTER(ID)
@@ -644,7 +644,7 @@
//===--------------------------------------------------------------------===//
// SILInstruction Printing Logic
- bool printTypeDependentOperands(SILInstruction *I) {
+ bool printTypeDependentOperands(const SILInstruction *I) {
ArrayRef<Operand> TypeDepOps = I->getTypeDependentOperands();
if (TypeDepOps.empty())
return false;
@@ -659,10 +659,27 @@
/// Print out the users of the SILValue \p V. Return true if we printed out
/// either an id or a use list. Return false otherwise.
- bool printUsersOfSILValue(SILValue V, bool printedSlashes) {
+ bool printUsersOfSILNode(const SILNode *node, bool printedSlashes) {
+ SILInstruction::ResultArrayRef values;
+ if (auto value = dyn_cast<ValueBase>(node)) {
+ // The base pointer of the ultimate ArrayRef here is just the
+ // ValueBase; we aren't forming a reference to a temporary array.
+ values = ArrayRef<ValueBase>(value, 1);
+ } else if (auto inst = dyn_cast<SILInstruction>(node)) {
+ values = inst->getResults();
+ }
- if (V->hasValue() && V->use_empty())
- return printedSlashes;
+ // If the set of values is empty, we need to print the ID of
+ // the instruction. Otherwise, if none of the values has a use,
+ // we don't need to do anything.
+ if (!values.empty()) {
+ bool hasUse = false;
+ for (auto value : values) {
+ if (!value->use_empty()) hasUse = true;
+ }
+ if (!hasUse)
+ return printedSlashes;
+ }
if (printedSlashes) {
*this << "; ";
@@ -670,23 +687,21 @@
PrintState.OS.PadToColumn(50);
*this << "// ";
}
- if (!V->hasValue()) {
- *this << "id: " << Ctx.getID(V);
+ if (values.empty()) {
+ *this << "id: " << Ctx.getID(node);
return true;
}
- if (V->use_empty())
- return true;
+ llvm::SmallVector<ID, 32> UserIDs;
+ for (auto value : values)
+ for (auto *Op : value->getUses())
+ UserIDs.push_back(Ctx.getID(Op->getUser()));
*this << "user";
- if (std::next(V->use_begin()) != V->use_end())
+ if (UserIDs.size() != 1)
*this << 's';
*this << ": ";
- llvm::SmallVector<ID, 32> UserIDs;
- for (auto *Op : V->getUses())
- UserIDs.push_back(Ctx.getID(Op->getUser()));
-
// If we are asked to, display the user ids sorted to give a stable use
// order in the printer's output. This makes diffing large sections of SIL
// significantly easier.
@@ -825,69 +840,114 @@
}
}
- void printInstOpCode(SILInstruction *I) {
- *this << getSILValueName(I->getKind()) << " ";
+ void printInstOpCode(const SILInstruction *I) {
+ *this << getSILInstructionName(I->getKind()) << " ";
}
- void print(SILValue V) {
- if (auto *FRI = dyn_cast<FunctionRefInst>(V))
+ void print(const SILInstruction *I) {
+ if (auto *FRI = dyn_cast<FunctionRefInst>(I))
*this << " // function_ref "
<< demangleSymbol(FRI->getReferencedFunction()->getName())
<< "\n";
*this << " ";
- SILInstruction *I = dyn_cast<SILInstruction>(V);
-
- // Print result.
- if (V->hasValue()) {
- if (I && I->isStaticInitializerInst() && I == &I->getParent()->back()) {
- *this << "%initval = ";
- } else {
- ID Name = Ctx.getID(V);
- *this << Name << " = ";
+ // Print results.
+ auto results = I->getResults();
+ if (results.size() == 1 &&
+ I->isStaticInitializerInst() &&
+ I == &I->getParent()->back()) {
+ *this << "%initval = ";
+ } else if (results.size() == 1) {
+ ID Name = Ctx.getID(results[0]);
+ *this << Name << " = ";
+ } else if (results.size() > 1) {
+ *this << '(';
+ bool first = true;
+ for (auto result : results) {
+ if (first) {
+ first = false;
+ } else {
+ *this << ", ";
+ }
+ ID Name = Ctx.getID(result);
+ *this << Name;
}
+ *this << ") = ";
}
- // First if we have a SILInstruction, print the opcode.
- if (auto *I = dyn_cast<SILInstruction>(V))
- printInstOpCode(I);
+ // Print the opcode.
+ printInstOpCode(I);
- // Then print the value.
- visit(V);
+ // Use the visitor to print the rest of the instruction.
+ visit(const_cast<SILInstruction*>(I));
+ // Maybe print debugging information.
bool printedSlashes = false;
- if (I) {
- if (Ctx.printDebugInfo() && !I->isStaticInitializerInst()) {
- auto &SM = I->getModule().getASTContext().SourceMgr;
- printDebugLocRef(I->getLoc(), SM);
- printDebugScopeRef(I->getDebugScope(), SM);
- }
- printedSlashes = printTypeDependentOperands(I);
+ if (Ctx.printDebugInfo() && !I->isStaticInitializerInst()) {
+ auto &SM = I->getModule().getASTContext().SourceMgr;
+ printDebugLocRef(I->getLoc(), SM);
+ printDebugScopeRef(I->getDebugScope(), SM);
}
+ printedSlashes = printTypeDependentOperands(I);
// Print users, or id for valueless instructions.
- printedSlashes = printUsersOfSILValue(V, printedSlashes);
+ printedSlashes = printUsersOfSILNode(I, printedSlashes);
// Print SIL location.
if (Ctx.printVerbose()) {
- if (I) {
- printSILLocation(I->getLoc(), I->getModule(), I->getDebugScope(),
- printedSlashes);
- }
+ printSILLocation(I->getLoc(), I->getModule(), I->getDebugScope(),
+ printedSlashes);
}
*this << '\n';
}
-
- void printInContext(SILValue V) {
- subjectValue = V;
- auto sortByID = [&](SILValue a, SILValue b) {
+ void print(const SILNode *node) {
+ switch (node->getKind()) {
+#define INST(ID, PARENT) \
+ case SILNodeKind::ID:
+#include "swift/SIL/SILNodes.def"
+ print(cast<SingleValueInstruction>(node));
+ return;
+
+ // TODO: MultiValueInstruction
+
+#define ARGUMENT(ID, PARENT) \
+ case SILNodeKind::ID:
+#include "swift/SIL/SILNodes.def"
+ printSILArgument(cast<SILArgument>(node));
+ return;
+
+ case SILNodeKind::SILUndef:
+ printSILUndef(cast<SILUndef>(node));
+ return;
+ }
+ llvm_unreachable("bad kind");
+ }
+
+ void printSILArgument(const SILArgument *arg) {
+ // This should really only happen during debugging.
+ *this << Ctx.getID(arg) << " = argument of "
+ << Ctx.getID(arg->getParent()) << " : " << arg->getType();
+
+ // Print users.
+ (void) printUsersOfSILNode(arg, false);
+
+ *this << '\n';
+ }
+
+ void printSILUndef(const SILUndef *undef) {
+ // This should really only happen during debugging.
+ *this << "undef<" << undef->getType() << ">\n";
+ }
+
+ void printInContext(const SILNode *node) {
+ auto sortByID = [&](const SILNode *a, const SILNode *b) {
return Ctx.getID(a).Number < Ctx.getID(b).Number;
};
- if (auto *I = dyn_cast<SILInstruction>(V)) {
+ if (auto *I = dyn_cast<SILInstruction>(node)) {
auto operands = map<SmallVector<SILValue,4>>(I->getAllOperands(),
[](Operand const &o) {
return o.get();
@@ -900,30 +960,21 @@
}
*this << "-> ";
- print(V);
-
- auto users = map<SmallVector<SILValue,4>>(V->getUses(),
- [](Operand *o) {
- return o->getUser();
- });
- std::sort(users.begin(), users.end(), sortByID);
- for (auto &user : users) {
- *this << " ";
- print(user);
+ print(node);
+
+ if (auto V = dyn_cast<ValueBase>(node)) {
+ auto users = map<SmallVector<const SILInstruction*,4>>(V->getUses(),
+ [](Operand *o) {
+ return o->getUser();
+ });
+ std::sort(users.begin(), users.end(), sortByID);
+ for (auto &user : users) {
+ *this << " ";
+ print(user);
+ }
}
}
- void visitSILArgument(SILArgument *A) {
- // This should really only happen during debugging.
- *this << "argument of " << Ctx.getID(A->getParent()) << " : "
- << A->getType();
- }
-
- void visitSILUndef(SILUndef *A) {
- // This should really only happen during debugging.
- *this << "undef<" << A->getType() << ">";
- }
-
void printDebugVar(SILDebugVariable Var) {
if (Var.Name.empty())
return;
@@ -1279,6 +1330,10 @@
*this << getIDAndType(CI->getOperand()) << " to " << CI->getCastType()
<< ", " << Ctx.getID(CI->getSuccessBB()) << ", "
<< Ctx.getID(CI->getFailureBB());
+ if (CI->getTrueBBCount())
+ *this << " !true_count(" << CI->getTrueBBCount().getValue() << ")";
+ if (CI->getFalseBBCount())
+ *this << " !false_count(" << CI->getFalseBBCount().getValue() << ")";
}
void visitCheckedCastValueBranchInst(CheckedCastValueBranchInst *CI) {
@@ -1305,6 +1360,10 @@
<< getIDAndType(CI->getDest()) << ", "
<< Ctx.getID(CI->getSuccessBB()) << ", "
<< Ctx.getID(CI->getFailureBB());
+ if (CI->getTrueBBCount())
+ *this << " !true_count(" << CI->getTrueBBCount().getValue() << ")";
+ if (CI->getFalseBBCount())
+ *this << " !false_count(" << CI->getFalseBBCount().getValue() << ")";
}
void printUncheckedConversionInst(ConversionInst *CI, SILValue operand) {
@@ -1657,6 +1716,11 @@
*this << "[nonatomic] ";
*this << getIDAndType(I->getOperand(0));
}
+ void visitStrongPinInst(StrongPinInst *I) {
+ if (I->isNonAtomic())
+ *this << "[nonatomic] ";
+ *this << getIDAndType(I->getOperand());
+ }
void visitIsUniqueInst(IsUniqueInst *CUI) {
*this << getIDAndType(CUI->getOperand());
}
@@ -1765,9 +1829,16 @@
std::tie(elt, dest) = SOI->getCase(i);
*this << ", case " << SILDeclRef(elt, SILDeclRef::Kind::EnumElement)
<< ": " << Ctx.getID(dest);
+ if (SOI->getCaseCount(i)) {
+ *this << " !case_count(" << SOI->getCaseCount(i).getValue() << ")";
+ }
}
- if (SOI->hasDefault())
+ if (SOI->hasDefault()) {
*this << ", default " << Ctx.getID(SOI->getDefaultBB());
+ if (SOI->getDefaultCount()) {
+ *this << " !default_count(" << SOI->getDefaultCount().getValue() << ")";
+ }
+ }
}
void visitSwitchEnumInst(SwitchEnumInst *SOI) {
@@ -1842,6 +1913,10 @@
printBranchArgs(CBI->getTrueArgs());
*this << ", " << Ctx.getID(CBI->getFalseBB());
printBranchArgs(CBI->getFalseArgs());
+ if (CBI->getTrueBBCount())
+ *this << " !true_count(" << CBI->getTrueBBCount().getValue() << ")";
+ if (CBI->getFalseBBCount())
+ *this << " !false_count(" << CBI->getFalseBBCount().getValue() << ")";
}
void visitKeyPathInst(KeyPathInst *KPI) {
@@ -1985,11 +2060,24 @@
// Printing for SILInstruction, SILBasicBlock, SILFunction, and SILModule
//===----------------------------------------------------------------------===//
-void ValueBase::dump() const {
+void SILNode::dump() const {
print(llvm::errs());
}
-void ValueBase::print(raw_ostream &OS) const {
+void SILNode::print(raw_ostream &OS) const {
+ SILPrintContext Ctx(OS);
+ SILPrinter(Ctx).print(this);
+}
+
+void SILInstruction::dump() const {
+ print(llvm::errs());
+}
+
+void SingleValueInstruction::dump() const {
+ SILInstruction::dump();
+}
+
+void SILInstruction::print(raw_ostream &OS) const {
SILPrintContext Ctx(OS);
SILPrinter(Ctx).print(this);
}
@@ -2167,6 +2255,9 @@
}
if (!isExternalDeclaration()) {
+ if (auto eCount = getEntryCount()) {
+ OS << " !function_entry_count(" << eCount.getValue() << ")";
+ }
OS << " {\n";
SILPrinter(PrintCtx, (Aliases.empty() ? nullptr : &Aliases))
@@ -2429,10 +2520,18 @@
OS << "\n\n";
}
-void ValueBase::dumpInContext() const {
+void SILNode::dumpInContext() const {
printInContext(llvm::errs());
}
-void ValueBase::printInContext(llvm::raw_ostream &OS) const {
+void SILNode::printInContext(llvm::raw_ostream &OS) const {
+ SILPrintContext Ctx(OS);
+ SILPrinter(Ctx).printInContext(this);
+}
+
+void SILInstruction::dumpInContext() const {
+ printInContext(llvm::errs());
+}
+void SILInstruction::printInContext(llvm::raw_ostream &OS) const {
SILPrintContext Ctx(OS);
SILPrinter(Ctx).printInContext(this);
}
@@ -2779,11 +2878,11 @@
return R;
}
-ID SILPrintContext::getID(SILValue V) {
- if (isa<SILUndef>(V))
+ID SILPrintContext::getID(const SILNode *node) {
+ if (isa<SILUndef>(node))
return {ID::SILUndef, 0};
- SILBasicBlock *BB = V->getParentBlock();
+ SILBasicBlock *BB = node->getParentBlock();
if (SILFunction *F = BB->getParent()) {
setContext(F);
// Lazily initialize the instruction -> ID mapping.
@@ -2795,10 +2894,26 @@
if (ValueToIDMap.empty()) {
unsigned idx = 0;
for (auto &I : *BB) {
- ValueToIDMap[&I] = idx++;
+ // Give the instruction itself the next ID.
+ ValueToIDMap[&I] = idx;
+
+ // If there are no results, make sure we don't reuse that ID.
+ auto results = I.getResults();
+ if (results.empty()) {
+ idx++;
+
+ // Otherwise, assign all of the results an index. Note that
+ // we'll assign the same ID to both the instruction and the
+ // first result.
+ } else {
+ for (auto result : results) {
+ ValueToIDMap[result] = idx++;
+ }
+ }
}
}
}
- ID R = {ID::SSAValue, ValueToIDMap[V]};
+
+ ID R = {ID::SSAValue, ValueToIDMap[node]};
return R;
}
diff --git a/lib/SIL/SILValue.cpp b/lib/SIL/SILValue.cpp
index 6ed5a0e..d1c6c82 100644
--- a/lib/SIL/SILValue.cpp
+++ b/lib/SIL/SILValue.cpp
@@ -57,33 +57,59 @@
}
}
-SILBasicBlock *ValueBase::getParentBlock() const {
- auto *NonConstThis = const_cast<ValueBase *>(this);
+SILInstruction *ValueBase::getDefiningInstruction() {
+ if (auto inst = dyn_cast<SingleValueInstruction>(this))
+ return inst;
+ // TODO: MultiValueInstruction
+ return nullptr;
+}
+
+Optional<ValueBase::DefiningInstructionResult>
+ValueBase::getDefiningInstructionResult() {
+ if (auto inst = dyn_cast<SingleValueInstruction>(this))
+ return DefiningInstructionResult{ inst, 0 };
+ // TODO: MultiValueInstruction
+ return None;
+}
+
+SILBasicBlock *SILNode::getParentBlock() const {
+ auto *NonConstThis = const_cast<SILNode *>(this);
if (auto *Inst = dyn_cast<SILInstruction>(NonConstThis))
return Inst->getParent();
+ // TODO: MultiValueInstruction
if (auto *Arg = dyn_cast<SILArgument>(NonConstThis))
return Arg->getParent();
return nullptr;
}
-SILFunction *ValueBase::getFunction() const {
- auto *NonConstThis = const_cast<ValueBase *>(this);
+SILFunction *SILNode::getFunction() const {
+ auto *NonConstThis = const_cast<SILNode *>(this);
if (auto *Inst = dyn_cast<SILInstruction>(NonConstThis))
return Inst->getFunction();
+ // TODO: MultiValueInstruction
if (auto *Arg = dyn_cast<SILArgument>(NonConstThis))
return Arg->getFunction();
return nullptr;
}
-SILModule *ValueBase::getModule() const {
- auto *NonConstThis = const_cast<ValueBase *>(this);
+SILModule *SILNode::getModule() const {
+ auto *NonConstThis = const_cast<SILNode *>(this);
if (auto *Inst = dyn_cast<SILInstruction>(NonConstThis))
return &Inst->getModule();
+ // TODO: MultiValueInstruction
if (auto *Arg = dyn_cast<SILArgument>(NonConstThis))
return &Arg->getModule();
return nullptr;
}
+const SILNode *SILNode::getCanonicalSILNodeSlowPath() const {
+ assert(getStorageLoc() != SILNodeStorageLocation::Instruction &&
+ hasMultipleSILNodes(getKind()));
+ return &static_cast<const SILInstruction &>(
+ static_cast<const SingleValueInstruction &>(
+ static_cast<const ValueBase &>(*this)));
+}
+
//===----------------------------------------------------------------------===//
// ValueOwnershipKind
//===----------------------------------------------------------------------===//
@@ -183,9 +209,10 @@
return Classifier.visit(const_cast<ValueBase *>(Value));
}
+#if 0
/// Map a SILValue mnemonic name to its ValueKind.
ValueKind swift::getSILValueKind(StringRef Name) {
-#define INST(Id, Parent, TextualName, MemoryBehavior, ReleasingBehavior) \
+#define SINGLE_VALUE_INST(Id, TextualName, Parent, MemoryBehavior, ReleasingBehavior) \
if (Name == #TextualName) \
return ValueKind::Id;
@@ -206,16 +233,15 @@
/// Map ValueKind to a corresponding mnemonic name.
StringRef swift::getSILValueName(ValueKind Kind) {
switch (Kind) {
-#define INST(Id, Parent, TextualName, MemoryBehavior, ReleasingBehavior) \
+#define SINGLE_VALUE_INST(Id, TextualName, Parent, MemoryBehavior, ReleasingBehavior) \
case ValueKind::Id: \
- return #TextualName; \
- break;
+ return #TextualName;
#define VALUE(Id, Parent) \
case ValueKind::Id: \
- return #Id; \
- break;
+ return #Id;
#include "swift/SIL/SILNodes.def"
}
}
+#endif
diff --git a/lib/SIL/SILVerifier.cpp b/lib/SIL/SILVerifier.cpp
index 0a97d1f..ef91739 100644
--- a/lib/SIL/SILVerifier.cpp
+++ b/lib/SIL/SILVerifier.cpp
@@ -79,11 +79,11 @@
/// Metaprogramming-friendly base class.
template <class Impl>
-class SILVerifierBase : public SILVisitor<Impl> {
+class SILVerifierBase : public SILInstructionVisitor<Impl> {
public:
// visitCLASS calls visitPARENT and checkCLASS.
// checkCLASS does nothing by default.
-#define VALUE(CLASS, PARENT) \
+#define INST(CLASS, PARENT) \
void visit##CLASS(CLASS *I) { \
static_cast<Impl*>(this)->visit##PARENT(I); \
static_cast<Impl*>(this)->check##CLASS(I); \
@@ -91,10 +91,10 @@
void check##CLASS(CLASS *I) {}
#include "swift/SIL/SILNodes.def"
- void visitValueBase(ValueBase *V) {
- static_cast<Impl*>(this)->checkValueBase(V);
+ void visitSILInstruction(SILInstruction *I) {
+ static_cast<Impl*>(this)->checkSILInstruction(I);
}
- void checkValueBase(ValueBase *V) {}
+ void checkSILInstruction(SILInstruction *I) {}
};
} // end anonymous namespace
@@ -471,14 +471,14 @@
// Check the SILLLocation attached to the instruction.
checkInstructionsSILLocation(I);
- checkLegalType(I->getFunction(), I, I);
-
// Check ownership.
SILFunction *F = I->getFunction();
assert(F && "Expected value base with parent function");
- // Check ownership.
- checkValueBaseOwnership(I);
+ for (auto result : I->getResults()) {
+ checkLegalType(F, result, I);
+ checkValueBaseOwnership(result);
+ }
}
void checkValueBaseOwnership(ValueBase *V) {
@@ -486,10 +486,6 @@
if (!isSILOwnershipEnabled())
return;
- // If V does not have a value, bail.
- if (!V->hasValue())
- return;
-
SILFunction *F = V->getFunction();
assert(F && "Expected value base with parent function");
// If we do not have qualified ownership, then do not verify value base
@@ -518,32 +514,34 @@
}
// Verify that all of our uses are in this function.
- for (Operand *use : I->getUses()) {
- auto user = use->getUser();
- require(user, "instruction user is null?");
- require(isa<SILInstruction>(user),
- "instruction used by non-instruction");
- auto userI = cast<SILInstruction>(user);
- require(userI->getParent(),
- "instruction used by unparented instruction");
- if (I->isStaticInitializerInst()) {
- require(userI->getParent() == BB,
- "instruction used by instruction not in same static initializer");
- } else {
- require(userI->getFunction() == &F,
- "instruction used by instruction in different function");
- }
+ for (auto result : I->getResults()) {
+ for (Operand *use : result->getUses()) {
+ auto user = use->getUser();
+ require(user, "instruction user is null?");
+ require(isa<SILInstruction>(user),
+ "instruction used by non-instruction");
+ auto userI = cast<SILInstruction>(user);
+ require(userI->getParent(),
+ "instruction used by unparented instruction");
+ if (I->isStaticInitializerInst()) {
+ require(userI->getParent() == BB,
+ "instruction used by instruction not in same static initializer");
+ } else {
+ require(userI->getFunction() == &F,
+ "instruction used by instruction in different function");
+ }
- auto operands = userI->getAllOperands();
- require(operands.begin() <= use && use <= operands.end(),
- "use doesn't actually belong to instruction it claims to");
+ auto operands = userI->getAllOperands();
+ require(operands.begin() <= use && use <= operands.end(),
+ "use doesn't actually belong to instruction it claims to");
+ }
}
// Verify some basis structural stuff about an instruction's operands.
for (auto &operand : I->getAllOperands()) {
require(operand.get(), "instruction has null operand");
- if (auto *valueI = dyn_cast<SILInstruction>(operand.get())) {
+ if (auto *valueI = operand.get()->getDefiningInstruction()) {
require(valueI->getParent(),
"instruction uses value of unparented instruction");
if (I->isStaticInitializerInst()) {
@@ -598,7 +596,7 @@
// Check the location kind.
SILLocation L = I->getLoc();
SILLocation::LocationKind LocKind = L.getKind();
- ValueKind InstKind = I->getKind();
+ SILInstructionKind InstKind = I->getKind();
// Check that there is at most one debug variable defined
// for each argument slot. This catches SIL transformations
@@ -642,20 +640,20 @@
// Fix incoming.
if (LocKind == SILLocation::CleanupKind ||
LocKind == SILLocation::InlinedKind)
- require(InstKind != ValueKind::ReturnInst ||
- InstKind != ValueKind::AutoreleaseReturnInst,
+ require(InstKind != SILInstructionKind::ReturnInst ||
+ InstKind != SILInstructionKind::AutoreleaseReturnInst,
"cleanup and inlined locations are not allowed on return instructions");
#endif
if (LocKind == SILLocation::ReturnKind ||
LocKind == SILLocation::ImplicitReturnKind)
- require(InstKind == ValueKind::BranchInst ||
- InstKind == ValueKind::ReturnInst ||
- InstKind == ValueKind::UnreachableInst,
+ require(InstKind == SILInstructionKind::BranchInst ||
+ InstKind == SILInstructionKind::ReturnInst ||
+ InstKind == SILInstructionKind::UnreachableInst,
"return locations are only allowed on branch and return instructions");
if (LocKind == SILLocation::ArtificialUnreachableKind)
- require(InstKind == ValueKind::UnreachableInst,
+ require(InstKind == SILInstructionKind::UnreachableInst,
"artificial locations are only allowed on Unreachable instructions");
}
@@ -876,9 +874,9 @@
require((ValueBase *)V == AI->getFunction()->getSelfMetadataArgument(),
"wrong self metadata operand");
} else {
- require(isa<SILInstruction>(V),
+ require(isa<SingleValueInstruction>(V),
"opened archetype operand should refer to a SIL instruction");
- auto Archetype = getOpenedArchetypeOf(cast<SILInstruction>(V));
+ auto Archetype = getOpenedArchetypeOf(cast<SingleValueInstruction>(V));
require(Archetype,
"opened archetype operand should define an opened archetype");
require(FoundOpenedArchetypes.count(Archetype),
@@ -1925,7 +1923,6 @@
}
void checkBindMemoryInst(BindMemoryInst *BI) {
- require(!BI->getType(), "BI must not produce a type");
require(BI->getBoundType(), "BI must have a bound type");
require(BI->getBase()->getType().is<BuiltinRawPointerType>(),
"bind_memory base be a RawPointer");
@@ -2343,34 +2340,34 @@
if (inst->isTypeDependentOperand(*use))
continue;
switch (inst->getKind()) {
- case ValueKind::ApplyInst:
- case ValueKind::TryApplyInst:
- case ValueKind::PartialApplyInst:
+ case SILInstructionKind::ApplyInst:
+ case SILInstructionKind::TryApplyInst:
+ case SILInstructionKind::PartialApplyInst:
if (isConsumingOrMutatingApplyUse(use))
return true;
else
break;
- case ValueKind::CopyAddrInst:
+ case SILInstructionKind::CopyAddrInst:
if (isConsumingOrMutatingCopyAddrUse(use))
return true;
else
break;
- case ValueKind::DestroyAddrInst:
+ case SILInstructionKind::DestroyAddrInst:
return true;
- case ValueKind::UncheckedAddrCastInst:
+ case SILInstructionKind::UncheckedAddrCastInst:
// Escaping use lets be conservative here.
return true;
- case ValueKind::CheckedCastAddrBranchInst:
+ case SILInstructionKind::CheckedCastAddrBranchInst:
if (cast<CheckedCastAddrBranchInst>(inst)->getConsumptionKind() !=
CastConsumptionKind::CopyOnSuccess)
return true;
break;
- case ValueKind::LoadInst:
+ case SILInstructionKind::LoadInst:
// A 'non-taking' value load is harmless.
return cast<LoadInst>(inst)->getOwnershipQualifier() ==
LoadOwnershipQualifier::Take;
break;
- case ValueKind::DebugValueAddrInst:
+ case SILInstructionKind::DebugValueAddrInst:
// Harmless use.
break;
default:
@@ -4072,7 +4069,7 @@
/// - flow-sensitive states must be equivalent on all paths into a block
void verifyFlowSensitiveRules(SILFunction *F) {
struct BBState {
- std::vector<SILInstruction*> Stack;
+ std::vector<SingleValueInstruction*> Stack;
std::set<BeginAccessInst*> Accesses;
};
@@ -4090,7 +4087,7 @@
CurInstruction = &i;
if (i.isAllocatingStack()) {
- state.Stack.push_back(&i);
+ state.Stack.push_back(cast<SingleValueInstruction>(&i));
} else if (i.isDeallocatingStack()) {
SILValue op = i.getOperand(0);
@@ -4263,7 +4260,13 @@
require(FoundSelfInPredecessor, "Must be a successor of each predecessor.");
}
- SILVisitor::visitSILBasicBlock(BB);
+ SILInstructionVisitor::visitSILBasicBlock(BB);
+ }
+
+ void visitBasicBlockArguments(SILBasicBlock *BB) {
+ for (auto argI = BB->args_begin(), argEnd = BB->args_end(); argI != argEnd;
+ ++argI)
+ visitSILArgument(*argI);
}
void visitSILBasicBlocks(SILFunction *F) {
@@ -4496,11 +4499,12 @@
for (const SILInstruction &I : StaticInitializerBlock) {
assert(isValidStaticInitializerInst(&I, getModule()) &&
"illegal static initializer");
- if (&I == &StaticInitializerBlock.back()) {
- assert(I.use_empty() && "Init value must not have another use");
+ auto init = cast<SingleValueInstruction>(&I);
+ if (init == &StaticInitializerBlock.back()) {
+ assert(init->use_empty() && "Init value must not have another use");
} else {
- assert(!I.use_empty() && "dead instruction in static initializer");
- assert(!isa<ObjectInst>(&I) &&
+ assert(!init->use_empty() && "dead instruction in static initializer");
+ assert(!isa<ObjectInst>(init) &&
"object instruction is only allowed for final initial value");
}
assert(I.getParent() == &StaticInitializerBlock);
diff --git a/lib/SIL/ValueOwnershipKindClassifier.cpp b/lib/SIL/ValueOwnershipKindClassifier.cpp
index 61a57fe..ebe7618 100644
--- a/lib/SIL/ValueOwnershipKindClassifier.cpp
+++ b/lib/SIL/ValueOwnershipKindClassifier.cpp
@@ -20,7 +20,6 @@
#define CONSTANT_OWNERSHIP_INST(OWNERSHIP, INST) \
ValueOwnershipKind ValueOwnershipKindClassifier::visit##INST##Inst( \
INST##Inst *Arg) { \
- assert(Arg->hasValue() && "Expected to have a result"); \
if (ValueOwnershipKind::OWNERSHIP == ValueOwnershipKind::Trivial) { \
assert((Arg->getType().isAddress() || \
Arg->getType().isTrivial(Arg->getModule())) && \
@@ -60,9 +59,7 @@
// not though.
CONSTANT_OWNERSHIP_INST(Trivial, AddressToPointer)
CONSTANT_OWNERSHIP_INST(Trivial, AllocStack)
-CONSTANT_OWNERSHIP_INST(Trivial, BindMemory)
CONSTANT_OWNERSHIP_INST(Trivial, BeginAccess)
-CONSTANT_OWNERSHIP_INST(Trivial, BeginUnpairedAccess)
CONSTANT_OWNERSHIP_INST(Trivial, BridgeObjectToWord)
CONSTANT_OWNERSHIP_INST(Trivial, ClassMethod)
CONSTANT_OWNERSHIP_INST(Trivial, DynamicMethod)
@@ -79,7 +76,6 @@
CONSTANT_OWNERSHIP_INST(Trivial, IsNonnull)
CONSTANT_OWNERSHIP_INST(Trivial, IsUnique)
CONSTANT_OWNERSHIP_INST(Trivial, IsUniqueOrPinned)
-CONSTANT_OWNERSHIP_INST(Trivial, MarkFunctionEscape)
CONSTANT_OWNERSHIP_INST(Trivial, MarkUninitializedBehavior)
CONSTANT_OWNERSHIP_INST(Trivial, Metatype)
CONSTANT_OWNERSHIP_INST(Trivial, ObjCToThickMetatype)
@@ -106,10 +102,8 @@
CONSTANT_OWNERSHIP_INST(Trivial, ThinFunctionToPointer)
CONSTANT_OWNERSHIP_INST(Trivial, TupleElementAddr)
CONSTANT_OWNERSHIP_INST(Trivial, UncheckedAddrCast)
-CONSTANT_OWNERSHIP_INST(Trivial, UncheckedRefCastAddr)
CONSTANT_OWNERSHIP_INST(Trivial, UncheckedTakeEnumDataAddr)
CONSTANT_OWNERSHIP_INST(Trivial, UncheckedTrivialBitCast)
-CONSTANT_OWNERSHIP_INST(Trivial, UnconditionalCheckedCastAddr)
CONSTANT_OWNERSHIP_INST(Trivial, ValueMetatype)
CONSTANT_OWNERSHIP_INST(Trivial, WitnessMethod)
CONSTANT_OWNERSHIP_INST(Trivial, StoreBorrow)
@@ -154,77 +148,6 @@
CONSTANT_OR_TRIVIAL_OWNERSHIP_INST(Unowned, UncheckedBitwiseCast)
#undef CONSTANT_OR_TRIVIAL_OWNERSHIP_INST
-// These are instructions that do not have any result, so we should never reach
-// this point in the code since we need a SILValue to compute
-// ValueOwnershipKind. We define methods so that all instructions have a method
-// on the visitor (causing the compiler to warn if a new instruction is added
-// within a method being added).
-#define NO_RESULT_OWNERSHIP_INST(INST) \
- ValueOwnershipKind ValueOwnershipKindClassifier::visit##INST##Inst( \
- INST##Inst *I) { \
- assert(!I->hasValue() && "Expected an instruction without a result"); \
- llvm_unreachable("Instruction without a result can not have ownership"); \
- }
-NO_RESULT_OWNERSHIP_INST(DeallocStack)
-NO_RESULT_OWNERSHIP_INST(DeallocRef)
-NO_RESULT_OWNERSHIP_INST(DeallocPartialRef)
-NO_RESULT_OWNERSHIP_INST(DeallocValueBuffer)
-NO_RESULT_OWNERSHIP_INST(DeallocBox)
-NO_RESULT_OWNERSHIP_INST(DeallocExistentialBox)
-NO_RESULT_OWNERSHIP_INST(EndAccess)
-NO_RESULT_OWNERSHIP_INST(EndBorrow)
-NO_RESULT_OWNERSHIP_INST(EndBorrowArgument)
-NO_RESULT_OWNERSHIP_INST(EndUnpairedAccess)
-NO_RESULT_OWNERSHIP_INST(Store)
-NO_RESULT_OWNERSHIP_INST(StoreWeak)
-NO_RESULT_OWNERSHIP_INST(StoreUnowned)
-NO_RESULT_OWNERSHIP_INST(Assign)
-NO_RESULT_OWNERSHIP_INST(DebugValue)
-NO_RESULT_OWNERSHIP_INST(DebugValueAddr)
-NO_RESULT_OWNERSHIP_INST(CopyAddr)
-NO_RESULT_OWNERSHIP_INST(DestroyAddr)
-NO_RESULT_OWNERSHIP_INST(StrongRetain)
-NO_RESULT_OWNERSHIP_INST(StrongRelease)
-NO_RESULT_OWNERSHIP_INST(StrongRetainUnowned)
-NO_RESULT_OWNERSHIP_INST(StrongUnpin)
-NO_RESULT_OWNERSHIP_INST(UnmanagedRetainValue)
-NO_RESULT_OWNERSHIP_INST(UnmanagedReleaseValue)
-NO_RESULT_OWNERSHIP_INST(UnmanagedAutoreleaseValue)
-NO_RESULT_OWNERSHIP_INST(UnownedRetain)
-NO_RESULT_OWNERSHIP_INST(UnownedRelease)
-NO_RESULT_OWNERSHIP_INST(RetainValue)
-NO_RESULT_OWNERSHIP_INST(ReleaseValue)
-NO_RESULT_OWNERSHIP_INST(RetainValueAddr)
-NO_RESULT_OWNERSHIP_INST(ReleaseValueAddr)
-NO_RESULT_OWNERSHIP_INST(SetDeallocating)
-NO_RESULT_OWNERSHIP_INST(AutoreleaseValue)
-NO_RESULT_OWNERSHIP_INST(FixLifetime)
-NO_RESULT_OWNERSHIP_INST(DestroyValue)
-NO_RESULT_OWNERSHIP_INST(AllocGlobal)
-NO_RESULT_OWNERSHIP_INST(InjectEnumAddr)
-NO_RESULT_OWNERSHIP_INST(DeinitExistentialAddr)
-NO_RESULT_OWNERSHIP_INST(DeinitExistentialValue)
-NO_RESULT_OWNERSHIP_INST(CondFail)
-NO_RESULT_OWNERSHIP_INST(EndLifetime)
-
-// Terminators. These do not produce SILValue, so they do not have a
-// ValueOwnershipKind. They do have ownership implications in terms of the
-// SILArguments that they feed into. But that code is in SILArgument.
-NO_RESULT_OWNERSHIP_INST(Unreachable)
-NO_RESULT_OWNERSHIP_INST(Return)
-NO_RESULT_OWNERSHIP_INST(Throw)
-NO_RESULT_OWNERSHIP_INST(TryApply)
-NO_RESULT_OWNERSHIP_INST(Branch)
-NO_RESULT_OWNERSHIP_INST(CondBranch)
-NO_RESULT_OWNERSHIP_INST(SwitchValue)
-NO_RESULT_OWNERSHIP_INST(SwitchEnum)
-NO_RESULT_OWNERSHIP_INST(SwitchEnumAddr)
-NO_RESULT_OWNERSHIP_INST(DynamicMethodBranch)
-NO_RESULT_OWNERSHIP_INST(CheckedCastBranch)
-NO_RESULT_OWNERSHIP_INST(CheckedCastValueBranch)
-NO_RESULT_OWNERSHIP_INST(CheckedCastAddrBranch)
-#undef NO_RESULT_OWNERSHIP_INST
-
// For a forwarding instruction, we loop over all operands and make sure that
// all non-trivial values have the same ownership.
ValueOwnershipKind
@@ -281,7 +204,6 @@
#define FORWARDING_OWNERSHIP_INST(INST) \
ValueOwnershipKind ValueOwnershipKindClassifier::visit##INST##Inst( \
INST##Inst *I) { \
- assert(I->hasValue() && "Expected to have a value"); \
return visitForwardingInst(I); \
}
FORWARDING_OWNERSHIP_INST(BridgeObjectToRef)
@@ -404,7 +326,6 @@
llvm::Intrinsic::ID ID) {
// LLVM intrinsics do not traffic in ownership, so if we have a result, it
// must be trivial.
- assert(BI->hasValue() && "Can only get here if we have a SILValue");
assert(BI->getType().isTrivial(BI->getModule()) &&
"LLVM intrinsics should always be trivial");
return ValueOwnershipKind::Trivial;
@@ -420,7 +341,6 @@
#define CONSTANT_OWNERSHIP_BUILTIN(OWNERSHIP, ID) \
ValueOwnershipKind ValueOwnershipKindBuiltinVisitor::visit##ID( \
BuiltinInst *BI, StringRef Attr) { \
- assert(BI->hasValue() && "Expected to have type"); \
if (ValueOwnershipKind::OWNERSHIP == ValueOwnershipKind::Trivial) { \
assert(BI->getType().isTrivial(BI->getModule()) && \
"Only trivial types can have trivial ownership"); \
diff --git a/lib/SIL/ValueOwnershipKindClassifier.h b/lib/SIL/ValueOwnershipKindClassifier.h
index 6c16243..2d4c7fb 100644
--- a/lib/SIL/ValueOwnershipKindClassifier.h
+++ b/lib/SIL/ValueOwnershipKindClassifier.h
@@ -19,7 +19,7 @@
namespace sil {
class ValueOwnershipKindClassifier
- : public SILVisitor<ValueOwnershipKindClassifier, ValueOwnershipKind> {
+ : public SILValueVisitor<ValueOwnershipKindClassifier, ValueOwnershipKind> {
public:
ValueOwnershipKindClassifier() = default;
@@ -33,9 +33,6 @@
return visitForwardingInst(I, I->getAllOperands());
}
- ValueOwnershipKind visitValueBase(ValueBase *V) {
- llvm_unreachable("unimplemented method on ValueBaseOwnershipVisitor");
- }
#define VALUE(Id, Parent) ValueOwnershipKind visit##Id(Id *ID);
#include "swift/SIL/SILNodes.def"
};
diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp
index 5dfc2e1..aaa8b13 100644
--- a/lib/SILGen/SILGen.cpp
+++ b/lib/SILGen/SILGen.cpp
@@ -28,6 +28,7 @@
#include "swift/SIL/SILArgument.h"
#include "swift/SIL/SILDebugScope.h"
#include "swift/Subsystems.h"
+#include "llvm/ProfileData/InstrProfReader.h"
#include "llvm/Support/Debug.h"
#include "ManagedValue.h"
#include "RValue.h"
@@ -41,6 +42,16 @@
SILGenModule::SILGenModule(SILModule &M, ModuleDecl *SM)
: M(M), Types(M.Types), SwiftModule(SM), TopLevelSGF(nullptr),
Profiler(nullptr) {
+ SILOptions &Opts = M.getOptions();
+ if (!Opts.UseProfile.empty()) {
+ auto ReaderOrErr = llvm::IndexedInstrProfReader::create(Opts.UseProfile);
+ if (auto E = ReaderOrErr.takeError()) {
+ diagnose(SourceLoc(), diag::profile_read_error, Opts.UseProfile,
+ llvm::toString(std::move(E)));
+ Opts.UseProfile.erase();
+ }
+ PGOReader = std::move(ReaderOrErr.get());
+ }
}
SILGenModule::~SILGenModule() {
@@ -429,8 +440,8 @@
C);
return M.createFunction(SILLinkage::Public, SWIFT_ENTRY_POINT_FUNCTION,
- topLevelType, nullptr, Loc, IsBare,
- IsNotTransparent, IsNotSerialized, IsNotThunk,
+ topLevelType, nullptr, Loc, IsBare, IsNotTransparent,
+ IsNotSerialized, ProfileCounter(), IsNotThunk,
SubclassScope::NotApplicable);
}
@@ -483,6 +494,13 @@
return nullptr;
}
+static bool hasSILBody(FuncDecl *fd) {
+ if (fd->getAccessorKind() == AccessorKind::IsMaterializeForSet)
+ return !isa<ProtocolDecl>(fd->getDeclContext());
+
+ return fd->getBody(/*canSynthesize=*/false);
+}
+
SILFunction *SILGenModule::getFunction(SILDeclRef constant,
ForDefinition_t forDefinition) {
// If we already emitted the function, return it (potentially preparing it
@@ -490,10 +508,18 @@
if (auto emitted = getEmittedFunction(constant, forDefinition))
return emitted;
+ ProfileCounter count = ProfileCounter();
+ if (constant.hasDecl()) {
+ if (auto *fd = constant.getFuncDecl()) {
+ if (hasSILBody(fd)) {
+ count = loadProfilerCount(fd->getBody(/*canSynthesize=*/false));
+ }
+ }
+ }
// Note: Do not provide any SILLocation. You can set it afterwards.
auto *F = M.getOrCreateFunction(constant.hasDecl() ? constant.getDecl()
: (Decl *)nullptr,
- constant, forDefinition);
+ constant, forDefinition, count);
assert(F && "SILFunction should have been defined");
@@ -673,13 +699,6 @@
}
}
-static bool hasSILBody(FuncDecl *fd) {
- if (fd->getAccessorKind() == AccessorKind::IsMaterializeForSet)
- return !isa<ProtocolDecl>(fd->getDeclContext());
-
- return fd->getBody(/*canSynthesize=*/false);
-}
-
void SILGenModule::emitFunction(FuncDecl *fd) {
SILDeclRef::Loc decl = fd;
diff --git a/lib/SILGen/SILGen.h b/lib/SILGen/SILGen.h
index 5f41b31..b98e89a 100644
--- a/lib/SILGen/SILGen.h
+++ b/lib/SILGen/SILGen.h
@@ -19,11 +19,13 @@
#include "swift/AST/ASTContext.h"
#include "swift/AST/AnyFunctionRef.h"
#include "swift/AST/DiagnosticEngine.h"
+#include "swift/Basic/ProfileCounter.h"
#include "swift/SIL/SILDebugScope.h"
#include "swift/SIL/SILFunction.h"
#include "swift/SIL/SILModule.h"
#include "swift/SIL/TypeLowering.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ProfileData/InstrProfReader.h"
#include <deque>
namespace swift {
@@ -60,6 +62,24 @@
/// disabled.
std::unique_ptr<SILGenProfiling> Profiler;
+ /// The indexed profile data to be used for PGO, or nullptr.
+ std::unique_ptr<llvm::IndexedInstrProfReader> PGOReader;
+
+ /// Load the profiled execution count corresponding to \p N, if one is
+ /// available.
+ ProfileCounter loadProfilerCount(ASTNode N) {
+ if (PGOReader && Profiler && Profiler->hasRegionCounters())
+ return Profiler->getExecutionCount(N);
+ return ProfileCounter();
+ }
+
+ /// Get the PGO's node parent
+ Optional<ASTNode> getPGOParent(ASTNode Node) {
+ if (PGOReader && Profiler && Profiler->hasRegionCounters())
+ return Profiler->getPGOParent(Node);
+ return None;
+ }
+
/// Mapping from SILDeclRefs to emitted SILFunctions.
llvm::DenseMap<SILDeclRef, SILFunction*> emittedFunctions;
/// Mapping from ProtocolConformances to emitted SILWitnessTables.
diff --git a/lib/SILGen/SILGenBuilder.cpp b/lib/SILGen/SILGenBuilder.cpp
index 4ce3707..fcb9238 100644
--- a/lib/SILGen/SILGenBuilder.cpp
+++ b/lib/SILGen/SILGenBuilder.cpp
@@ -558,9 +558,12 @@
void SILGenBuilder::createCheckedCastBranch(SILLocation loc, bool isExact,
ManagedValue operand, SILType type,
SILBasicBlock *trueBlock,
- SILBasicBlock *falseBlock) {
+ SILBasicBlock *falseBlock,
+ ProfileCounter Target1Count,
+ ProfileCounter Target2Count) {
SILBuilder::createCheckedCastBranch(loc, isExact, operand.forward(SGF), type,
- trueBlock, falseBlock);
+ trueBlock, falseBlock, Target1Count,
+ Target2Count);
}
void SILGenBuilder::createCheckedCastValueBranch(SILLocation loc,
@@ -713,16 +716,26 @@
{
// TODO: We could store the data in CaseBB form and not have to do this.
llvm::SmallVector<DeclBlockPair, 8> caseBlocks;
+ llvm::SmallVector<ProfileCounter, 8> caseBlockCounts;
std::transform(caseDataArray.begin(), caseDataArray.end(),
std::back_inserter(caseBlocks),
[](NormalCaseData &caseData) -> DeclBlockPair {
return {caseData.decl, caseData.block};
});
+ std::transform(caseDataArray.begin(), caseDataArray.end(),
+ std::back_inserter(caseBlockCounts),
+ [](NormalCaseData &caseData) -> ProfileCounter {
+ return caseData.count;
+ });
SILBasicBlock *defaultBlock =
defaultBlockData ? defaultBlockData->block : nullptr;
+ ProfileCounter defaultBlockCount =
+ defaultBlockData ? defaultBlockData->count : ProfileCounter();
+ ArrayRef<ProfileCounter> caseBlockCountsRef = caseBlockCounts;
if (isAddressOnly) {
builder.createSwitchEnumAddr(loc, optional.getValue(), defaultBlock,
- caseBlocks);
+ caseBlocks, caseBlockCountsRef,
+ defaultBlockCount);
} else {
if (optional.getType().isAddress()) {
// TODO: Refactor this into a maybe load.
@@ -733,7 +746,8 @@
}
}
builder.createSwitchEnum(loc, optional.forward(getSGF()), defaultBlock,
- caseBlocks);
+ caseBlocks, caseBlockCountsRef,
+ defaultBlockCount);
}
}
diff --git a/lib/SILGen/SILGenBuilder.h b/lib/SILGen/SILGenBuilder.h
index a6d6291..c455835 100644
--- a/lib/SILGen/SILGenBuilder.h
+++ b/lib/SILGen/SILGenBuilder.h
@@ -26,6 +26,7 @@
#include "JumpDest.h"
#include "ManagedValue.h"
#include "RValue.h"
+#include "swift/Basic/ProfileCounter.h"
#include "swift/SIL/SILBuilder.h"
namespace swift {
@@ -257,7 +258,9 @@
void createCheckedCastBranch(SILLocation loc, bool isExact,
ManagedValue operand, SILType type,
SILBasicBlock *trueBlock,
- SILBasicBlock *falseBlock);
+ SILBasicBlock *falseBlock,
+ ProfileCounter Target1Count,
+ ProfileCounter Target2Count);
using SILBuilder::createCheckedCastValueBranch;
void createCheckedCastValueBranch(SILLocation loc, ManagedValue operand,
@@ -334,11 +337,13 @@
SILBasicBlock *block;
NullablePtr<SILBasicBlock> contBlock;
NormalCaseHandler handler;
+ ProfileCounter count;
NormalCaseData(EnumElementDecl *decl, SILBasicBlock *block,
NullablePtr<SILBasicBlock> contBlock,
- NormalCaseHandler handler)
- : decl(decl), block(block), contBlock(contBlock), handler(handler) {}
+ NormalCaseHandler handler, ProfileCounter count)
+ : decl(decl), block(block), contBlock(contBlock), handler(handler),
+ count(count) {}
~NormalCaseData() = default;
};
@@ -347,12 +352,13 @@
NullablePtr<SILBasicBlock> contBlock;
DefaultCaseHandler handler;
DefaultDispatchTime dispatchTime;
+ ProfileCounter count;
DefaultCaseData(SILBasicBlock *block, NullablePtr<SILBasicBlock> contBlock,
DefaultCaseHandler handler,
- DefaultDispatchTime dispatchTime)
+ DefaultDispatchTime dispatchTime, ProfileCounter count)
: block(block), contBlock(contBlock), handler(handler),
- dispatchTime(dispatchTime) {}
+ dispatchTime(dispatchTime), count(count) {}
~DefaultCaseData() = default;
};
@@ -367,17 +373,19 @@
ManagedValue optional)
: builder(builder), loc(loc), optional(optional) {}
- void addDefaultCase(SILBasicBlock *defaultBlock,
- NullablePtr<SILBasicBlock> contBlock,
- DefaultCaseHandler handle,
- DefaultDispatchTime dispatchTime =
- DefaultDispatchTime::AfterNormalCases) {
- defaultBlockData.emplace(defaultBlock, contBlock, handle, dispatchTime);
+ void addDefaultCase(
+ SILBasicBlock *defaultBlock, NullablePtr<SILBasicBlock> contBlock,
+ DefaultCaseHandler handle,
+ DefaultDispatchTime dispatchTime = DefaultDispatchTime::AfterNormalCases,
+ ProfileCounter count = ProfileCounter()) {
+ defaultBlockData.emplace(defaultBlock, contBlock, handle, dispatchTime,
+ count);
}
void addCase(EnumElementDecl *decl, SILBasicBlock *caseBlock,
- NullablePtr<SILBasicBlock> contBlock, NormalCaseHandler handle) {
- caseDataArray.emplace_back(decl, caseBlock, contBlock, handle);
+ NullablePtr<SILBasicBlock> contBlock, NormalCaseHandler handle,
+ ProfileCounter count = ProfileCounter()) {
+ caseDataArray.emplace_back(decl, caseBlock, contBlock, handle, count);
}
void emit() &&;
diff --git a/lib/SILGen/SILGenDecl.cpp b/lib/SILGen/SILGenDecl.cpp
index 83c3554..ffe41f8 100644
--- a/lib/SILGen/SILGenDecl.cpp
+++ b/lib/SILGen/SILGenDecl.cpp
@@ -10,9 +10,9 @@
//
//===----------------------------------------------------------------------===//
-#include "SILGen.h"
#include "Initialization.h"
#include "RValue.h"
+#include "SILGen.h"
#include "SILGenDynamicCast.h"
#include "Scope.h"
#include "SwitchCaseFullExpr.h"
@@ -21,6 +21,7 @@
#include "swift/AST/Module.h"
#include "swift/AST/NameLookup.h"
#include "swift/AST/ProtocolConformance.h"
+#include "swift/Basic/ProfileCounter.h"
#include "swift/SIL/FormalLinkage.h"
#include "swift/SIL/PrettyStackTrace.h"
#include "swift/SIL/SILArgument.h"
@@ -386,7 +387,7 @@
// The variable may have its lifetime extended by a closure, heap-allocate
// it using a box.
- SILInstruction *allocBox =
+ SILValue allocBox =
SGF.B.createAllocBox(decl, boxType, {decl->isLet(), ArgNo});
// Mark the memory as uninitialized, so DI will track it for us.
@@ -908,12 +909,13 @@
// Try to perform the cast to the destination type, producing an optional that
// indicates whether we succeeded.
auto destType = OptionalType::get(pattern->getCastTypeLoc().getType());
-
- value = emitConditionalCheckedCast(SGF, loc, value, pattern->getType(),
- destType, pattern->getCastKind(),
- SGFContext())
- .getAsSingleValue(SGF, loc);
-
+
+ value =
+ emitConditionalCheckedCast(SGF, loc, value, pattern->getType(), destType,
+ pattern->getCastKind(), SGFContext(),
+ ProfileCounter(), ProfileCounter())
+ .getAsSingleValue(SGF, loc);
+
// Now that we have our result as an optional, we can use an enum projection
// to do all the work.
EnumElementPatternInitialization::
@@ -1184,8 +1186,10 @@
/// specified JumpDest. The insertion point is left in the block where the
/// condition has matched and any bound variables are in scope.
///
-void SILGenFunction::emitStmtCondition(StmtCondition Cond,
- JumpDest FailDest, SILLocation loc) {
+void SILGenFunction::emitStmtCondition(StmtCondition Cond, JumpDest FailDest,
+ SILLocation loc,
+ ProfileCounter NumTrueTaken,
+ ProfileCounter NumFalseTaken) {
assert(B.hasValidInsertionPoint() &&
"emitting condition at unreachable point");
@@ -1240,8 +1244,9 @@
// on success we fall through to a new block.
SILBasicBlock *ContBB = createBasicBlock();
auto FailBB = Cleanups.emitBlockForCleanups(FailDest, loc);
- B.createCondBranch(booleanTestLoc, booleanTestValue, ContBB, FailBB);
-
+ B.createCondBranch(booleanTestLoc, booleanTestValue, ContBB, FailBB,
+ NumTrueTaken, NumFalseTaken);
+
// Finally, emit the continue block and keep emitting the rest of the
// condition.
B.emitBlock(ContBB);
diff --git a/lib/SILGen/SILGenDynamicCast.cpp b/lib/SILGen/SILGenDynamicCast.cpp
index 226a8e2..b63a3b4 100644
--- a/lib/SILGen/SILGenDynamicCast.cpp
+++ b/lib/SILGen/SILGenDynamicCast.cpp
@@ -117,7 +117,9 @@
void emitConditional(
ManagedValue operand, CastConsumptionKind consumption, SGFContext ctx,
const std::function<void(ManagedValue)> &handleTrue,
- const std::function<void(Optional<ManagedValue>)> &handleFalse) {
+ const std::function<void(Optional<ManagedValue>)> &handleFalse,
+ ProfileCounter TrueCount = ProfileCounter(),
+ ProfileCounter FalseCount = ProfileCounter()) {
// The cast instructions don't know how to work with anything
// but the most general possible abstraction level.
AbstractionPattern abstraction =
@@ -140,7 +142,7 @@
createAbstractResultBuffer(hasAbstraction, origTargetTL, ctx);
SGF.B.createCheckedCastAddrBranch(
Loc, consumption, operand.forward(SGF), SourceType, resultBuffer,
- TargetType, trueBB, falseBB);
+ TargetType, trueBB, falseBB, TrueCount, FalseCount);
} else if (Strategy == CastStrategy::Address) {
// Opaque value mode
operandValue = std::move(operand);
@@ -155,7 +157,7 @@
}
SGF.B.createCheckedCastBranch(Loc, /*exact*/ false, operandValue,
origTargetTL.getLoweredType(), trueBB,
- falseBB);
+ falseBB, TrueCount, FalseCount);
}
// Emit the success block.
@@ -285,22 +287,23 @@
void SILGenFunction::emitCheckedCastBranch(
SILLocation loc, Expr *source, Type targetType, SGFContext ctx,
std::function<void(ManagedValue)> handleTrue,
- std::function<void(Optional<ManagedValue>)> handleFalse) {
+ std::function<void(Optional<ManagedValue>)> handleFalse,
+ ProfileCounter TrueCount, ProfileCounter FalseCount) {
CheckedCastEmitter emitter(*this, loc, source->getType(), targetType);
ManagedValue operand = emitter.emitOperand(source);
emitter.emitConditional(operand, CastConsumptionKind::TakeAlways, ctx,
- handleTrue, handleFalse);
+ handleTrue, handleFalse, TrueCount, FalseCount);
}
void SILGenFunction::emitCheckedCastBranch(
SILLocation loc, ConsumableManagedValue src, Type sourceType,
CanType targetType, SGFContext ctx,
std::function<void(ManagedValue)> handleTrue,
- std::function<void(Optional<ManagedValue>)> handleFalse) {
+ std::function<void(Optional<ManagedValue>)> handleFalse,
+ ProfileCounter TrueCount, ProfileCounter FalseCount) {
CheckedCastEmitter emitter(*this, loc, sourceType, targetType);
- emitter.emitConditional(src.getFinalManagedValue(),
- src.getFinalConsumption(), ctx, handleTrue,
- handleFalse);
+ emitter.emitConditional(src.getFinalManagedValue(), src.getFinalConsumption(),
+ ctx, handleTrue, handleFalse, TrueCount, FalseCount);
}
namespace {
@@ -395,7 +398,9 @@
void emitConditional(ManagedValue operand, CastConsumptionKind consumption,
SGFContext ctx,
const std::function<void(ManagedValue)> &handleTrue,
- const std::function<void()> &handleFalse) {
+ const std::function<void()> &handleFalse,
+ ProfileCounter TrueCount = ProfileCounter(),
+ ProfileCounter FalseCount = ProfileCounter()) {
// The cast instructions don't know how to work with anything
// but the most general possible abstraction level.
AbstractionPattern abstraction = SGF.SGM.Types.getMostGeneralAbstraction();
@@ -414,10 +419,9 @@
assert(operand.getType().isAddress());
resultBuffer =
createAbstractResultBuffer(hasAbstraction, origTargetTL, ctx);
- SGF.B.createCheckedCastAddrBranch(Loc, consumption,
- operand.forward(SGF), SourceType,
- resultBuffer, TargetType,
- trueBB, falseBB);
+ SGF.B.createCheckedCastAddrBranch(
+ Loc, consumption, operand.forward(SGF), SourceType, resultBuffer,
+ TargetType, trueBB, falseBB, TrueCount, FalseCount);
} else {
// Tolerate being passed an address here. It comes up during switch
//emission.
@@ -427,8 +431,8 @@
Loc, scalarOperandValue, LoadOwnershipQualifier::Take);
}
SGF.B.createCheckedCastBranch(Loc, /*exact*/ false, scalarOperandValue,
- origTargetTL.getLoweredType(),
- trueBB, falseBB);
+ origTargetTL.getLoweredType(), trueBB,
+ falseBB, TrueCount, FalseCount);
}
// Emit the success block.
@@ -541,21 +545,23 @@
void SILGenFunction::emitCheckedCastBranchOld(
SILLocation loc, Expr *source, Type targetType, SGFContext ctx,
std::function<void(ManagedValue)> handleTrue,
- std::function<void()> handleFalse) {
+ std::function<void()> handleFalse, ProfileCounter TrueCount,
+ ProfileCounter FalseCount) {
CheckedCastEmitterOld emitter(*this, loc, source->getType(), targetType);
ManagedValue operand = emitter.emitOperand(source);
emitter.emitConditional(operand, CastConsumptionKind::TakeAlways, ctx,
- handleTrue, handleFalse);
+ handleTrue, handleFalse, TrueCount, FalseCount);
}
void SILGenFunction::emitCheckedCastBranchOld(
SILLocation loc, ConsumableManagedValue src, Type sourceType,
CanType targetType, SGFContext ctx,
std::function<void(ManagedValue)> handleTrue,
- std::function<void()> handleFalse) {
+ std::function<void()> handleFalse, ProfileCounter TrueCount,
+ ProfileCounter FalseCount) {
CheckedCastEmitterOld emitter(*this, loc, sourceType, targetType);
emitter.emitConditional(src.getFinalManagedValue(), src.getFinalConsumption(),
- ctx, handleTrue, handleFalse);
+ ctx, handleTrue, handleFalse, TrueCount, FalseCount);
}
/// Emit a collection downcast expression.
@@ -664,13 +670,10 @@
return emitter.emitUnconditionalCast(operandValue, C);
}
-RValue Lowering::emitConditionalCheckedCast(SILGenFunction &SGF,
- SILLocation loc,
- ManagedValue operand,
- Type operandType,
- Type optTargetType,
- CheckedCastKind castKind,
- SGFContext C) {
+RValue Lowering::emitConditionalCheckedCast(
+ SILGenFunction &SGF, SILLocation loc, ManagedValue operand,
+ Type operandType, Type optTargetType, CheckedCastKind castKind,
+ SGFContext C, ProfileCounter TrueCount, ProfileCounter FalseCount) {
// Drill into the result type.
CanType resultObjectType =
optTargetType->getCanonicalType().getAnyOptionalObjectType();
@@ -755,7 +758,8 @@
SGF.B.createInjectEnumAddr(loc, resultBuffer, noneDecl);
SGF.Cleanups.emitBranchAndCleanups(scope.getExitDest(), loc);
}
- });
+ },
+ TrueCount, FalseCount);
// Enter the continuation block.
SILBasicBlock *contBlock = scope.exit();
diff --git a/lib/SILGen/SILGenDynamicCast.h b/lib/SILGen/SILGenDynamicCast.h
index 45133a6..490c20b 100644
--- a/lib/SILGen/SILGenDynamicCast.h
+++ b/lib/SILGen/SILGenDynamicCast.h
@@ -25,13 +25,11 @@
CheckedCastKind castKind,
SGFContext C);
-RValue emitConditionalCheckedCast(SILGenFunction &SGF,
- SILLocation loc,
- ManagedValue operand,
- Type operandType,
- Type targetType,
- CheckedCastKind castKind,
- SGFContext C);
+RValue emitConditionalCheckedCast(SILGenFunction &SGF, SILLocation loc,
+ ManagedValue operand, Type operandType,
+ Type targetType, CheckedCastKind castKind,
+ SGFContext C, ProfileCounter TrueCount,
+ ProfileCounter FalseCount);
SILValue emitIsa(SILGenFunction &SGF, SILLocation loc,
Expr *operand, Type targetType,
diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp
index 6c8723f..5a5143d 100644
--- a/lib/SILGen/SILGenExpr.cpp
+++ b/lib/SILGen/SILGenExpr.cpp
@@ -2170,9 +2170,23 @@
RValue RValueEmitter::
visitConditionalCheckedCastExpr(ConditionalCheckedCastExpr *E,
SGFContext C) {
+ ProfileCounter trueCount = ProfileCounter();
+ ProfileCounter falseCount = ProfileCounter();
+ auto parent = SGF.SGM.getPGOParent(E);
+ if (parent) {
+ auto &Node = parent.getValue();
+ auto *NodeS = Node.get<Stmt *>();
+ if (auto *IS = dyn_cast<IfStmt>(NodeS)) {
+ trueCount = SGF.SGM.loadProfilerCount(IS->getThenStmt());
+ if (auto *ElseStmt = IS->getElseStmt()) {
+ falseCount = SGF.SGM.loadProfilerCount(ElseStmt);
+ }
+ }
+ }
ManagedValue operand = SGF.emitRValueAsSingleValue(E->getSubExpr());
return emitConditionalCheckedCast(SGF, E, operand, E->getSubExpr()->getType(),
- E->getType(), E->getCastKind(), C);
+ E->getType(), E->getCastKind(), C,
+ trueCount, falseCount);
}
RValue RValueEmitter::visitIsExpr(IsExpr *E, SGFContext C) {
@@ -3027,12 +3041,9 @@
auto name = Mangle::ASTMangler()
.mangleKeyPathGetterThunkHelper(property, genericSig, baseType,
interfaceSubs);
- auto thunk = SGF.SGM.M.getOrCreateSharedFunction(loc, name,
- signature,
- IsBare,
- IsNotTransparent,
- IsNotSerialized,
- IsThunk);
+ auto thunk = SGF.SGM.M.getOrCreateSharedFunction(
+ loc, name, signature, IsBare, IsNotTransparent, IsNotSerialized,
+ ProfileCounter(), IsThunk);
if (!thunk->empty())
return thunk;
@@ -3152,12 +3163,9 @@
genericSig,
baseType,
interfaceSubs);
- auto thunk = SGF.SGM.M.getOrCreateSharedFunction(loc, name,
- signature,
- IsBare,
- IsNotTransparent,
- IsNotSerialized,
- IsThunk);
+ auto thunk = SGF.SGM.M.getOrCreateSharedFunction(
+ loc, name, signature, IsBare, IsNotTransparent, IsNotSerialized,
+ ProfileCounter(), IsThunk);
if (!thunk->empty())
return thunk;
@@ -3314,12 +3322,9 @@
auto name = Mangle::ASTMangler().mangleKeyPathEqualsHelper(indexTypes,
genericSig);
- equals = SGM.M.getOrCreateSharedFunction(loc, name,
- signature,
- IsBare,
- IsNotTransparent,
- IsNotSerialized,
- IsThunk);
+ equals = SGM.M.getOrCreateSharedFunction(loc, name, signature, IsBare,
+ IsNotTransparent, IsNotSerialized,
+ ProfileCounter(), IsThunk);
if (!equals->empty()) {
return;
}
@@ -3482,12 +3487,9 @@
auto name = Mangle::ASTMangler().mangleKeyPathHashHelper(indexTypes,
genericSig);
- hash = SGM.M.getOrCreateSharedFunction(loc, name,
- signature,
- IsBare,
- IsNotTransparent,
- IsNotSerialized,
- IsThunk);
+ hash = SGM.M.getOrCreateSharedFunction(loc, name, signature, IsBare,
+ IsNotTransparent, IsNotSerialized,
+ ProfileCounter(), IsThunk);
if (!hash->empty()) {
return;
}
@@ -4421,6 +4423,9 @@
RValue RValueEmitter::visitIfExpr(IfExpr *E, SGFContext C) {
auto &lowering = SGF.getTypeLowering(E->getType());
+ auto NumTrueTaken = SGF.SGM.loadProfilerCount(E->getThenExpr());
+ auto NumFalseTaken = SGF.SGM.loadProfilerCount(E->getElseExpr());
+
if (lowering.isLoadable() || !SGF.silConv.useLoweredAddresses()) {
// If the result is loadable, emit each branch and forward its result
// into the destination block argument.
@@ -4429,7 +4434,8 @@
Condition cond = SGF.emitCondition(E->getCondExpr(),
/*hasFalse*/ true,
/*invertCondition*/ false,
- SGF.getLoweredType(E->getType()));
+ SGF.getLoweredType(E->getType()),
+ NumTrueTaken, NumFalseTaken);
cond.enterTrue(SGF);
SGF.emitProfilerIncrement(E->getThenExpr());
@@ -4464,7 +4470,9 @@
Condition cond = SGF.emitCondition(E->getCondExpr(),
/*hasFalse*/ true,
- /*invertCondition*/ false);
+ /*invertCondition*/ false,
+ /*contArgs*/ {},
+ NumTrueTaken, NumFalseTaken);
cond.enterTrue(SGF);
SGF.emitProfilerIncrement(E->getThenExpr());
{
diff --git a/lib/SILGen/SILGenFunction.h b/lib/SILGen/SILGenFunction.h
index 1c93cef..13f6c2c 100644
--- a/lib/SILGen/SILGenFunction.h
+++ b/lib/SILGen/SILGenFunction.h
@@ -21,6 +21,7 @@
#include "SILGen.h"
#include "SILGenBuilder.h"
#include "swift/AST/AnyFunctionRef.h"
+#include "swift/Basic/ProfileCounter.h"
#include "swift/SIL/SILBuilder.h"
#include "llvm/ADT/PointerIntPair.h"
@@ -370,10 +371,11 @@
/// Emit code to increment a counter for profiling.
void emitProfilerIncrement(ASTNode N) {
- if (SGM.Profiler && SGM.Profiler->hasRegionCounters())
+ if (SGM.Profiler && SGM.Profiler->hasRegionCounters() &&
+ SGM.M.getOptions().UseProfile.empty())
SGM.Profiler->emitCounterIncrement(B, N);
}
-
+
SILGenFunction(SILGenModule &SGM, SILFunction &F);
~SILGenFunction();
@@ -592,13 +594,20 @@
/// \param contArgs - the types of the arguments to the continuation BB.
/// Matching argument values must be passed to exitTrue and exitFalse
/// of the resulting Condition object.
- Condition emitCondition(Expr *E,
- bool hasFalseCode = true, bool invertValue = false,
- ArrayRef<SILType> contArgs = {});
+ /// \param NumTrueTaken - The number of times the condition evaluates to true.
+ /// \param NumFalseTaken - The number of times the condition evaluates to
+ /// false.
+ Condition emitCondition(Expr *E, bool hasFalseCode = true,
+ bool invertValue = false,
+ ArrayRef<SILType> contArgs = {},
+ ProfileCounter NumTrueTaken = ProfileCounter(),
+ ProfileCounter NumFalseTaken = ProfileCounter());
- Condition emitCondition(SILValue V, SILLocation Loc,
- bool hasFalseCode = true, bool invertValue = false,
- ArrayRef<SILType> contArgs = {});
+ Condition emitCondition(SILValue V, SILLocation Loc, bool hasFalseCode = true,
+ bool invertValue = false,
+ ArrayRef<SILType> contArgs = {},
+ ProfileCounter NumTrueTaken = ProfileCounter(),
+ ProfileCounter NumFalseTaken = ProfileCounter());
/// Create a new basic block.
///
@@ -923,8 +932,9 @@
//===--------------------------------------------------------------------===//
SILValue emitOSVersionRangeCheck(SILLocation loc, const VersionRange &range);
- void emitStmtCondition(StmtCondition Cond, JumpDest FailDest,
- SILLocation loc);
+ void emitStmtCondition(StmtCondition Cond, JumpDest FailDest, SILLocation loc,
+ ProfileCounter NumTrueTaken = ProfileCounter(),
+ ProfileCounter NumFalseTaken = ProfileCounter());
void emitConditionalPBD(PatternBindingDecl *PBD, SILBasicBlock *FailBB);
@@ -1440,11 +1450,13 @@
/// terminated.
/// \param handleFalse A callback to invoke in the failure path. The
/// current BB should be terminated.
- void emitCheckedCastBranch(
- SILLocation loc, ConsumableManagedValue src, Type sourceType,
- CanType targetType, SGFContext C,
- std::function<void(ManagedValue)> handleTrue,
- std::function<void(Optional<ManagedValue>)> handleFalse);
+ void
+ emitCheckedCastBranch(SILLocation loc, ConsumableManagedValue src,
+ Type sourceType, CanType targetType, SGFContext C,
+ std::function<void(ManagedValue)> handleTrue,
+ std::function<void(Optional<ManagedValue>)> handleFalse,
+ ProfileCounter TrueCount = ProfileCounter(),
+ ProfileCounter FalseCount = ProfileCounter());
/// A form of checked cast branch that uses the old non-ownership preserving
/// semantics.
@@ -1455,7 +1467,9 @@
void emitCheckedCastBranchOld(SILLocation loc, Expr *source, Type targetType,
SGFContext ctx,
std::function<void(ManagedValue)> handleTrue,
- std::function<void()> handleFalse);
+ std::function<void()> handleFalse,
+ ProfileCounter TrueCount = ProfileCounter(),
+ ProfileCounter FalseCount = ProfileCounter());
/// \brief Emit a conditional checked cast branch, starting from an
/// expression. Terminates the current BB.
@@ -1469,10 +1483,13 @@
/// terminated.
/// \param handleFalse A callback to invoke in the failure path. The
/// current BB should be terminated.
- void emitCheckedCastBranch(
- SILLocation loc, Expr *src, Type targetType, SGFContext C,
- std::function<void(ManagedValue)> handleTrue,
- std::function<void(Optional<ManagedValue>)> handleFalse);
+ void
+ emitCheckedCastBranch(SILLocation loc, Expr *src, Type targetType,
+ SGFContext C,
+ std::function<void(ManagedValue)> handleTrue,
+ std::function<void(Optional<ManagedValue>)> handleFalse,
+ ProfileCounter TrueCount = ProfileCounter(),
+ ProfileCounter FalseCount = ProfileCounter());
/// A form of checked cast branch that uses the old non-ownership preserving
/// semantics.
@@ -1484,7 +1501,9 @@
Type sourceType, CanType targetType,
SGFContext ctx,
std::function<void(ManagedValue)> handleTrue,
- std::function<void()> handleFalse);
+ std::function<void()> handleFalse,
+ ProfileCounter TrueCount = ProfileCounter(),
+ ProfileCounter FalseCount = ProfileCounter());
/// Emit the control flow for an optional 'bind' operation, branching to the
/// active failure destination if the optional value addressed by optionalAddr
diff --git a/lib/SILGen/SILGenMaterializeForSet.cpp b/lib/SILGen/SILGenMaterializeForSet.cpp
index 4ca810e..8597760 100644
--- a/lib/SILGen/SILGenMaterializeForSet.cpp
+++ b/lib/SILGen/SILGenMaterializeForSet.cpp
@@ -700,10 +700,9 @@
auto callback = SGM.M.createFunction(
callbackLinkage, CallbackName, callbackType, genericEnv,
- SILLocation(Witness), IsBare, F.isTransparent(), F.isSerialized(), IsNotThunk,
- SubclassScope::NotApplicable,
- /*inlineStrategy=*/InlineDefault,
- /*EK=*/EffectsKind::Unspecified,
+ SILLocation(Witness), IsBare, F.isTransparent(), F.isSerialized(),
+ F.getEntryCount(), IsNotThunk, SubclassScope::NotApplicable,
+ /*inlineStrategy=*/InlineDefault, /*EK=*/EffectsKind::Unspecified,
/*InsertBefore=*/&F);
callback->setDebugScope(new (SGM.M) SILDebugScope(Witness, callback));
diff --git a/lib/SILGen/SILGenPattern.cpp b/lib/SILGen/SILGenPattern.cpp
index 391d0d0..8c3e142 100644
--- a/lib/SILGen/SILGenPattern.cpp
+++ b/lib/SILGen/SILGenPattern.cpp
@@ -11,26 +11,27 @@
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "patternmatch-silgen"
-#include "SILGen.h"
-#include "Scope.h"
#include "Cleanup.h"
#include "ExitableFullExpr.h"
#include "Initialization.h"
#include "RValue.h"
-#include "llvm/ADT/MapVector.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/FormattedStream.h"
+#include "SILGen.h"
+#include "Scope.h"
#include "swift/AST/ASTWalker.h"
#include "swift/AST/DiagnosticsSIL.h"
#include "swift/AST/Pattern.h"
#include "swift/AST/SILOptions.h"
#include "swift/AST/Types.h"
+#include "swift/Basic/ProfileCounter.h"
#include "swift/Basic/STLExtras.h"
#include "swift/SIL/DynamicCasts.h"
#include "swift/SIL/SILArgument.h"
#include "swift/SIL/SILUndef.h"
#include "swift/SIL/TypeLowering.h"
+#include "llvm/ADT/MapVector.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/FormattedStream.h"
using namespace swift;
using namespace Lowering;
@@ -314,6 +315,9 @@
/// Whether the row will be irrefutable after this specialization.
bool Irrefutable;
+
+ /// Profile Count of hte row we intend to specialize.
+ ProfileCounter Count;
};
/// Changes that we wish to apply to a row which we have specialized.
@@ -470,7 +474,8 @@
void emitEnumElementDispatch(ArrayRef<RowToSpecialize> rows,
ConsumableManagedValue src,
const SpecializationHandler &handleSpec,
- const FailureHandler &failure);
+ const FailureHandler &failure,
+ ProfileCounter defaultCaseCount);
void emitBoolDispatch(ArrayRef<RowToSpecialize> rows,
ConsumableManagedValue src,
const SpecializationHandler &handleSpec,
@@ -1324,9 +1329,15 @@
auto addRowToSpecialize = [&](Pattern *pattern, unsigned rowIndex) {
assert(getSpecializingPattern(clauses[rowIndex][column]) == pattern);
bool irrefutable = clauses[rowIndex].isIrrefutableAfterSpecializing(column);
- rowsToSpecialize.push_back({pattern, rowIndex, irrefutable});
+ auto caseBlock = clauses[rowIndex].getClientData<CaseStmt>();
+ ProfileCounter count = ProfileCounter();
+ if (caseBlock) {
+ count = SGF.SGM.loadProfilerCount(caseBlock);
+ }
+ rowsToSpecialize.push_back({pattern, rowIndex, irrefutable, count});
};
+ ProfileCounter defaultCaseCount = ProfileCounter();
Pattern *firstSpecializer = getSpecializingPattern(clauses[firstRow][column]);
assert(firstSpecializer && "specializing unspecializable row?");
addRowToSpecialize(firstSpecializer, firstRow);
@@ -1335,7 +1346,13 @@
for (++lastRow; lastRow != clauses.rows(); ++lastRow) {
Pattern *specializer =
getSimilarSpecializingPattern(clauses[lastRow][column], firstSpecializer);
- if (!specializer) break;
+ if (!specializer) {
+ auto caseBlock = clauses[lastRow].getClientData<CaseStmt>();
+ if (caseBlock) {
+ defaultCaseCount = SGF.SGM.loadProfilerCount(caseBlock);
+ }
+ break;
+ }
addRowToSpecialize(specializer, lastRow);
}
assert(lastRow - firstRow == rowsToSpecialize.size());
@@ -1380,7 +1397,8 @@
return emitIsDispatch(rowsToSpecialize, arg, handler, failure);
case PatternKind::EnumElement:
case PatternKind::OptionalSome:
- return emitEnumElementDispatch(rowsToSpecialize, arg, handler, failure);
+ return emitEnumElementDispatch(rowsToSpecialize, arg, handler, failure,
+ defaultCaseCount);
case PatternKind::Bool:
return emitBoolDispatch(rowsToSpecialize, arg, handler, failure);
}
@@ -1648,7 +1666,7 @@
assert(!SGF.B.hasValidInsertionPoint() && "did not end block");
},
// Failure block: branch out to the continuation block.
- [&] { (*innerFailure)(loc); });
+ [&] { (*innerFailure)(loc); }, rows[0].Count);
}
/// Perform specialized dispatch for a sequence of EnumElementPattern or an
@@ -1878,8 +1896,8 @@
/// OptionalSomePattern.
void PatternMatchEmission::emitEnumElementDispatch(
ArrayRef<RowToSpecialize> rows, ConsumableManagedValue src,
- const SpecializationHandler &handleCase,
- const FailureHandler &outerFailure) {
+ const SpecializationHandler &handleCase, const FailureHandler &outerFailure,
+ ProfileCounter defaultCaseCount) {
// If sil ownership is enabled and we have that our source type is an object,
// use the dispatch code path.
if (SGF.getOptions().EnableSILOwnership && src.getType().isObject()) {
@@ -1904,6 +1922,7 @@
// instructions want only the first information, so we split them up.
SmallVector<std::pair<EnumElementDecl*, SILBasicBlock*>, 4> caseBBs;
SmallVector<CaseInfo, 4> caseInfos;
+ SmallVector<ProfileCounter, 4> caseCounts;
SILBasicBlock *defaultBB = nullptr;
caseBBs.reserve(rows.size());
@@ -1935,6 +1954,7 @@
caseInfos.resize(caseInfos.size() + 1);
caseInfos.back().FormalElement = formalElt;
caseInfos.back().FirstMatcher = row.Pattern;
+ caseCounts.push_back(row.Count);
}
assert(caseToIndex[elt] == index);
assert(caseBBs[index].first == elt);
@@ -2019,10 +2039,13 @@
SILValue srcValue = src.getFinalManagedValue().forward(SGF);
SILLocation loc = PatternMatchStmt;
loc.setDebugLoc(rows[0].Pattern);
+ ArrayRef<ProfileCounter> caseCountsArrayRef = caseCounts;
if (addressOnlyEnum) {
- SGF.B.createSwitchEnumAddr(loc, srcValue, defaultBB, caseBBs);
+ SGF.B.createSwitchEnumAddr(loc, srcValue, defaultBB, caseBBs,
+ caseCountsArrayRef, defaultCaseCount);
} else {
- SGF.B.createSwitchEnum(loc, srcValue, defaultBB, caseBBs);
+ SGF.B.createSwitchEnum(loc, srcValue, defaultBB, caseBBs,
+ caseCountsArrayRef, defaultCaseCount);
}
// Okay, now emit all the cases.
diff --git a/lib/SILGen/SILGenProfiling.cpp b/lib/SILGen/SILGenProfiling.cpp
index f564dfd..32f9175 100644
--- a/lib/SILGen/SILGenProfiling.cpp
+++ b/lib/SILGen/SILGenProfiling.cpp
@@ -82,7 +82,7 @@
assert(isa<AbstractFunctionDecl>(D) ||
isa<TopLevelCodeDecl>(D) && "Cannot create profiler for this decl");
const auto &Opts = SGM.M.getOptions();
- if (!Opts.GenerateProfile || isUnmappedDecl(D))
+ if ((!Opts.GenerateProfile && Opts.UseProfile.empty()) || isUnmappedDecl(D))
return;
SGM.Profiler =
llvm::make_unique<SILGenProfiling>(SGM, Opts.EmitProfileCoverageMapping);
@@ -139,10 +139,11 @@
}
std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
- if (auto *IE = dyn_cast<IfExpr>(E))
+ if (auto *IE = dyn_cast<IfExpr>(E)) {
CounterMap[IE->getThenExpr()] = NextCounter++;
- else if (isa<AutoClosureExpr>(E) || isa<ClosureExpr>(E))
+ } else if (isa<AutoClosureExpr>(E) || isa<ClosureExpr>(E)) {
CounterMap[E] = NextCounter++;
+ }
return {true, E};
}
};
@@ -271,6 +272,195 @@
}
};
+/// An ASTWalker that maps ASTNodes to profiling counters.
+struct PGOMapping : public ASTWalker {
+ /// The next counter value to assign.
+ unsigned NextCounter;
+
+ /// The map of statements to counters.
+ llvm::DenseMap<ASTNode, ProfileCounter> &LoadedCounterMap;
+ llvm::Expected<llvm::InstrProfRecord> &LoadedCounts;
+ llvm::DenseMap<ASTNode, ASTNode> &CondToParentMap;
+ llvm::DenseMap<ASTNode, unsigned> CounterMap;
+
+ PGOMapping(llvm::DenseMap<ASTNode, ProfileCounter> &LoadedCounterMap,
+ llvm::Expected<llvm::InstrProfRecord> &LoadedCounts,
+ llvm::DenseMap<ASTNode, ASTNode> &PGORegionCondToParentMap)
+ : NextCounter(0), LoadedCounterMap(LoadedCounterMap),
+ LoadedCounts(LoadedCounts), CondToParentMap(PGORegionCondToParentMap) {}
+
+ unsigned getParentCounter() const {
+ if (Parent.isNull())
+ return 0;
+ else if (Parent.getKind() == ASTWalker::ParentKind::Decl) {
+ auto it = CounterMap.find(Parent.getAsDecl());
+ return (it != CounterMap.end()) ? it->getSecond() : 0;
+ } else if (Parent.getKind() == ASTWalker::ParentKind::Stmt) {
+ auto it = CounterMap.find(Parent.getAsStmt());
+ return (it != CounterMap.end()) ? it->getSecond() : 0;
+ } else if (Parent.getKind() == ASTWalker::ParentKind::Expr) {
+ auto it = CounterMap.find(Parent.getAsExpr());
+ return (it != CounterMap.end()) ? it->getSecond() : 0;
+ }
+ return 0;
+ }
+
+ ProfileCounter subtract(ProfileCounter L, ProfileCounter R) {
+ if (!L.hasValue() || !R.hasValue()) {
+ return L;
+ }
+ uint64_t LV = L.getValue();
+ uint64_t RV = R.getValue();
+ assert(LV >= RV && "Invalid counter subtraction");
+ return LV - RV;
+ }
+
+ /// Load the execution count corresponding to \p Node from a profile, if one
+ /// is available.
+ ProfileCounter loadExecutionCount(ASTNode Node) {
+ if (!Node)
+ return ProfileCounter();
+
+ auto CounterIt = CounterMap.find(Node);
+ assert(CounterIt != CounterMap.end() &&
+ "region does not have an associated counter");
+
+ unsigned CounterIndexForFunc = CounterIt->second;
+ return LoadedCounts->Counts[CounterIndexForFunc];
+ }
+
+ bool walkToDeclPre(Decl *D) override {
+ if (isUnmappedDecl(D))
+ return false;
+ if (auto *AFD = dyn_cast<AbstractFunctionDecl>(D)) {
+ auto node = AFD->getBody();
+ CounterMap[node] = NextCounter++;
+ auto count = loadExecutionCount(node);
+ LoadedCounterMap[node] = count;
+ }
+ if (auto *TLCD = dyn_cast<TopLevelCodeDecl>(D)) {
+ auto node = TLCD->getBody();
+ CounterMap[node] = NextCounter++;
+ auto count = loadExecutionCount(node);
+ LoadedCounterMap[node] = count;
+ }
+ return true;
+ }
+
+ std::pair<bool, Stmt *> walkToStmtPre(Stmt *S) override {
+ unsigned parent = getParentCounter();
+ if (auto *IS = dyn_cast<IfStmt>(S)) {
+ auto thenStmt = IS->getThenStmt();
+ CounterMap[thenStmt] = NextCounter++;
+ auto thenCount = loadExecutionCount(thenStmt);
+ LoadedCounterMap[thenStmt] = thenCount;
+ if (auto elseStmt = IS->getElseStmt()) {
+ CounterMap[elseStmt] = parent;
+ auto count = loadExecutionCount(elseStmt);
+ if (!parent) {
+ auto thenVal = thenCount.getValue();
+ for (auto pCount = NextCounter - 1; pCount > 0; --pCount) {
+ auto cCount = LoadedCounts->Counts[pCount];
+ if (cCount > thenVal) {
+ count = cCount;
+ break;
+ }
+ }
+ }
+ LoadedCounterMap[elseStmt] = subtract(count, thenCount);
+ auto Cond = IS->getCond();
+ for (const auto &elt : Cond) {
+ if (elt.getKind() ==
+ StmtConditionElement::ConditionKind::CK_PatternBinding) {
+ CondToParentMap[elt.getInitializer()] = IS;
+ }
+ }
+ }
+ } else if (auto *US = dyn_cast<GuardStmt>(S)) {
+ auto guardBody = US->getBody();
+ CounterMap[guardBody] = NextCounter++;
+ auto guardCount = loadExecutionCount(guardBody);
+ LoadedCounterMap[guardBody] = guardCount;
+ CounterMap[US] = parent;
+ auto count = loadExecutionCount(US);
+ LoadedCounterMap[US] = subtract(count, guardCount);
+ } else if (auto *WS = dyn_cast<WhileStmt>(S)) {
+ auto whileBody = WS->getBody();
+ CounterMap[whileBody] = NextCounter++;
+ auto whileCount = loadExecutionCount(whileBody);
+ LoadedCounterMap[whileBody] = whileCount;
+ CounterMap[WS] = parent;
+ auto count = loadExecutionCount(WS);
+ LoadedCounterMap[WS] = count;
+ } else if (auto *RWS = dyn_cast<RepeatWhileStmt>(S)) {
+ auto rwsBody = RWS->getBody();
+ CounterMap[rwsBody] = NextCounter++;
+ auto rwsBodyCount = loadExecutionCount(rwsBody);
+ LoadedCounterMap[rwsBody] = rwsBodyCount;
+ CounterMap[RWS] = parent;
+ auto count = loadExecutionCount(RWS);
+ LoadedCounterMap[RWS] = count;
+ } else if (auto *FES = dyn_cast<ForEachStmt>(S)) {
+ auto fesBody = FES->getBody();
+ CounterMap[fesBody] = NextCounter++;
+ auto fesCount = loadExecutionCount(fesBody);
+ LoadedCounterMap[fesBody] = fesCount;
+ CounterMap[FES] = parent;
+ auto count = loadExecutionCount(FES);
+ LoadedCounterMap[FES] = count;
+ walkPatternForProfiling(FES->getIterator(), *this);
+ } else if (auto *SS = dyn_cast<SwitchStmt>(S)) {
+ CounterMap[SS] = NextCounter++;
+ auto ssCount = loadExecutionCount(SS);
+ LoadedCounterMap[SS] = ssCount;
+ } else if (auto *CS = dyn_cast<CaseStmt>(S)) {
+ CounterMap[CS] = NextCounter++;
+ auto csCount = loadExecutionCount(CS);
+ LoadedCounterMap[CS] = csCount;
+ } else if (auto *DCS = dyn_cast<DoCatchStmt>(S)) {
+ CounterMap[DCS] = NextCounter++;
+ auto dcsCount = loadExecutionCount(DCS);
+ LoadedCounterMap[DCS] = dcsCount;
+ } else if (auto *CS = dyn_cast<CatchStmt>(S)) {
+ auto csBody = CS->getBody();
+ CounterMap[csBody] = NextCounter++;
+ auto csBodyCount = loadExecutionCount(csBody);
+ LoadedCounterMap[csBody] = csBodyCount;
+ }
+ return {true, S};
+ }
+
+ std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
+ unsigned parent = getParentCounter();
+ if (auto *IE = dyn_cast<IfExpr>(E)) {
+ auto thenExpr = IE->getThenExpr();
+ CounterMap[thenExpr] = NextCounter++;
+ auto thenCount = loadExecutionCount(thenExpr);
+ LoadedCounterMap[thenExpr] = thenCount;
+ if (auto elseExpr = IE->getElseExpr()) {
+ CounterMap[elseExpr] = parent;
+ auto count = loadExecutionCount(elseExpr);
+ if (!parent) {
+ auto thenVal = thenCount.getValue();
+ for (auto pCount = NextCounter - 1; pCount > 0; --pCount) {
+ auto cCount = LoadedCounts->Counts[pCount];
+ if (cCount > thenVal) {
+ count = cCount;
+ break;
+ }
+ }
+ }
+ LoadedCounterMap[elseExpr] = subtract(count, thenCount);
+ }
+ } else if (isa<AutoClosureExpr>(E) || isa<ClosureExpr>(E)) {
+ CounterMap[E] = NextCounter++;
+ auto eCount = loadExecutionCount(E);
+ LoadedCounterMap[E] = eCount;
+ }
+ return {true, E};
+ }
+};
+
struct CoverageMapping : public ASTWalker {
private:
const SourceManager &SM;
@@ -698,6 +888,10 @@
CurrentFuncLinkage = FormalLinkage::HiddenUnique;
}
+ PGOFuncName = llvm::getPGOFuncName(
+ CurrentFuncName, getEquivalentPGOLinkage(CurrentFuncLinkage),
+ CurrentFileName);
+
walkForProfiling(Root, Mapper);
NumRegionCounters = Mapper.NextCounter;
@@ -712,6 +906,45 @@
getEquivalentPGOLinkage(CurrentFuncLinkage)),
FunctionHash, RegionCounterMap, CurrentFileName);
}
+
+ if (SGM.PGOReader) {
+ auto LoadedCounts =
+ SGM.PGOReader->getInstrProfRecord(PGOFuncName, FunctionHash);
+ if (auto E = LoadedCounts.takeError()) {
+ llvm::handleAllErrors(std::move(E),
+ [&E](const llvm::InstrProfError &Err) {
+ Err.log(llvm::dbgs());
+ return;
+ });
+ llvm::dbgs() << PGOFuncName << "\n";
+ return;
+ }
+ PGOMapping pgoMapper(PGORegionLoadedCounterMap, LoadedCounts,
+ PGORegionCondToParentMap);
+ walkForProfiling(Root, pgoMapper);
+ }
+}
+
+ProfileCounter SILGenProfiling::getExecutionCount(ASTNode Node) {
+ if (!Node) {
+ return ProfileCounter();
+ }
+ auto it = PGORegionLoadedCounterMap.find(Node);
+ if (it == PGORegionLoadedCounterMap.end()) {
+ return ProfileCounter();
+ }
+ return it->getSecond();
+}
+
+Optional<ASTNode> SILGenProfiling::getPGOParent(ASTNode Node) {
+ if (!Node) {
+ return None;
+ }
+ auto it = PGORegionCondToParentMap.find(Node);
+ if (it == PGORegionCondToParentMap.end()) {
+ return None;
+ }
+ return it->getSecond();
}
static SILLocation getLocation(ASTNode Node) {
diff --git a/lib/SILGen/SILGenProfiling.h b/lib/SILGen/SILGenProfiling.h
index 45e2cb7..562fb21 100644
--- a/lib/SILGen/SILGenProfiling.h
+++ b/lib/SILGen/SILGenProfiling.h
@@ -13,10 +13,12 @@
#ifndef SWIFT_SILGEN_PROFILING_H
#define SWIFT_SILGEN_PROFILING_H
-#include "llvm/ADT/DenseMap.h"
#include "swift/AST/ASTNode.h"
#include "swift/AST/Stmt.h"
+#include "swift/Basic/ProfileCounter.h"
#include "swift/SIL/FormalLinkage.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ProfileData/InstrProf.h"
namespace swift {
@@ -41,7 +43,10 @@
FormalLinkage CurrentFuncLinkage;
unsigned NumRegionCounters;
uint64_t FunctionHash;
+ std::string PGOFuncName;
llvm::DenseMap<ASTNode, unsigned> RegionCounterMap;
+ llvm::DenseMap<ASTNode, ProfileCounter> PGORegionLoadedCounterMap;
+ llvm::DenseMap<ASTNode, ASTNode> PGORegionCondToParentMap;
std::vector<std::tuple<std::string, uint64_t, std::string>> CoverageData;
@@ -55,6 +60,14 @@
/// Emit SIL to increment the counter for \c Node.
void emitCounterIncrement(SILGenBuilder &Builder, ASTNode Node);
+ /// Get previously Loaded the execution count corresponding to \p Node
+ /// from a profile, if one is available.
+ ProfileCounter getExecutionCount(ASTNode Node);
+
+ /// Get PGORegion's parent ASTNode
+ /// used to get a condition's parent IfStmt or IfCond
+ Optional<ASTNode> getPGOParent(ASTNode Node);
+
private:
/// Map counters to ASTNodes and set them up for profiling the given function.
void assignRegionCounters(Decl *Root);
@@ -72,6 +85,7 @@
};
} // end namespace Lowering
+
} // end namespace swift
#endif // SWIFT_SILGEN_PROFILING
diff --git a/lib/SILGen/SILGenStmt.cpp b/lib/SILGen/SILGenStmt.cpp
index 1a44a62..fd1e468 100644
--- a/lib/SILGen/SILGenStmt.cpp
+++ b/lib/SILGen/SILGenStmt.cpp
@@ -10,14 +10,15 @@
//
//===----------------------------------------------------------------------===//
-#include "SILGen.h"
#include "Condition.h"
#include "Initialization.h"
#include "LValue.h"
#include "RValue.h"
+#include "SILGen.h"
#include "Scope.h"
#include "SwitchCaseFullExpr.h"
#include "swift/AST/DiagnosticsSIL.h"
+#include "swift/Basic/ProfileCounter.h"
#include "swift/SIL/SILArgument.h"
#include "llvm/Support/SaveAndRestore.h"
@@ -138,9 +139,11 @@
SGF.B.emitBlock(BB, BranchLoc);
}
-Condition SILGenFunction::emitCondition(Expr *E,
- bool hasFalseCode, bool invertValue,
- ArrayRef<SILType> contArgs) {
+Condition SILGenFunction::emitCondition(Expr *E, bool hasFalseCode,
+ bool invertValue,
+ ArrayRef<SILType> contArgs,
+ ProfileCounter NumTrueTaken,
+ ProfileCounter NumFalseTaken) {
assert(B.hasValidInsertionPoint() &&
"emitting condition at unreachable point");
@@ -152,14 +155,15 @@
}
assert(V->getType().castTo<BuiltinIntegerType>()->isFixedWidth(1));
- return emitCondition(V, E, hasFalseCode, invertValue, contArgs);
+ return emitCondition(V, E, hasFalseCode, invertValue, contArgs, NumTrueTaken,
+ NumFalseTaken);
}
-
-
Condition SILGenFunction::emitCondition(SILValue V, SILLocation Loc,
bool hasFalseCode, bool invertValue,
- ArrayRef<SILType> contArgs) {
+ ArrayRef<SILType> contArgs,
+ ProfileCounter NumTrueTaken,
+ ProfileCounter NumFalseTaken) {
assert(B.hasValidInsertionPoint() &&
"emitting condition at unreachable point");
@@ -180,10 +184,12 @@
SILBasicBlock *TrueBB = createBasicBlock();
if (invertValue)
- B.createCondBranch(Loc, V, FalseDestBB, TrueBB);
+ B.createCondBranch(Loc, V, FalseDestBB, TrueBB, NumFalseTaken,
+ NumTrueTaken);
else
- B.createCondBranch(Loc, V, TrueBB, FalseDestBB);
-
+ B.createCondBranch(Loc, V, TrueBB, FalseDestBB, NumTrueTaken,
+ NumFalseTaken);
+
return Condition(TrueBB, FalseBB, ContBB, Loc);
}
@@ -484,7 +490,7 @@
JumpDest falseDest = contDest;
if (S->getElseStmt())
falseDest = createJumpDest(S);
-
+
// Emit the condition, along with the "then" part of the if properly guarded
// by the condition and a jump to ContBB. If the condition fails, jump to
// the CondFalseBB.
@@ -492,8 +498,12 @@
// Enter a scope for any bound pattern variables.
LexicalScope trueScope(SGF, S);
- SGF.emitStmtCondition(S->getCond(), falseDest, S);
-
+ auto NumTrueTaken = SGF.SGM.loadProfilerCount(S->getThenStmt());
+ auto NumFalseTaken = SGF.SGM.loadProfilerCount(S->getElseStmt());
+
+ SGF.emitStmtCondition(S->getCond(), falseDest, S, NumTrueTaken,
+ NumFalseTaken);
+
// In the success path, emit the 'then' part if the if.
SGF.emitProfilerIncrement(S->getThenStmt());
SGF.emitStmt(S->getThenStmt());
@@ -553,7 +563,9 @@
// Emit the condition bindings, branching to the bodyBB if they fail. Since
// we didn't push a scope, the bound variables are live after this statement.
- SGF.emitStmtCondition(S->getCond(), bodyBB, S);
+ auto NumFalseTaken = SGF.SGM.loadProfilerCount(S->getBody());
+ auto NumNonTaken = SGF.SGM.loadProfilerCount(S);
+ SGF.emitStmtCondition(S->getCond(), bodyBB, S, NumNonTaken, NumFalseTaken);
}
void StmtEmitter::visitWhileStmt(WhileStmt *S) {
@@ -576,8 +588,10 @@
{
// Enter a scope for any bound pattern variables.
Scope conditionScope(SGF.Cleanups, S);
-
- SGF.emitStmtCondition(S->getCond(), breakDest, S);
+
+ auto NumTrueTaken = SGF.SGM.loadProfilerCount(S->getBody());
+ auto NumFalseTaken = SGF.SGM.loadProfilerCount(S);
+ SGF.emitStmtCondition(S->getCond(), breakDest, S, NumTrueTaken, NumFalseTaken);
// In the success path, emit the body of the while.
SGF.emitProfilerIncrement(S->getBody());
@@ -729,8 +743,12 @@
if (SGF.B.hasValidInsertionPoint()) {
// Evaluate the condition with the false edge leading directly
// to the continuation block.
- Condition Cond = SGF.emitCondition(S->getCond(), /*hasFalseCode*/ false);
-
+ auto NumTrueTaken = SGF.SGM.loadProfilerCount(S->getBody());
+ auto NumFalseTaken = SGF.SGM.loadProfilerCount(S);
+ Condition Cond = SGF.emitCondition(S->getCond(), /*hasFalseCode*/ false,
+ /*invertValue*/ false, /*contArgs*/ {},
+ NumTrueTaken, NumFalseTaken);
+
Cond.enterTrue(SGF);
if (SGF.B.hasValidInsertionPoint()) {
SGF.B.createBranch(S->getCond(), loopBB);
@@ -866,7 +884,8 @@
RegularLocation L(S->getBody());
L.pointToEnd();
scope.exitAndBranch(L);
- });
+ },
+ SGF.SGM.loadProfilerCount(S->getBody()));
// We add loop fail block, just to be defensive about intermediate
// transformations performing cleanups at scope.exit(). We still jump to the
@@ -877,7 +896,8 @@
[&](ManagedValue inputValue, SwitchCaseFullExpr &scope) {
assert(!inputValue && "None should not be passed an argument!");
scope.exitAndBranch(S);
- });
+ },
+ SGF.SGM.loadProfilerCount(S));
std::move(switchEnumBuilder).emit();
diff --git a/lib/SILGen/SILGenThunk.cpp b/lib/SILGen/SILGenThunk.cpp
index ea598d3..f1139a8 100644
--- a/lib/SILGen/SILGenThunk.cpp
+++ b/lib/SILGen/SILGenThunk.cpp
@@ -42,7 +42,7 @@
auto F = M.getOrCreateFunction(constant.getDecl(), name, SILLinkage::Shared,
constantInfo.SILFnType, IsBare, IsTransparent,
- IsSerializable, IsThunk);
+ IsSerializable, ProfileCounter(), IsThunk);
if (F->empty()) {
// Emit the thunk if we haven't yet.
@@ -166,7 +166,7 @@
SILGenBuilder::getPartialApplyResultType(toFn->getType(), /*appliedParams=*/1,
SGM.M, subs,
ParameterConvention::Direct_Owned);
- SILInstruction *toClosure =
+ SILValue toClosure =
B.createPartialApply(vd, toFn, substTy, subs, {selfArg}, closureTy);
if (resultTy != closureTy)
toClosure = B.createConvertFunction(vd, toClosure, resultTy);
@@ -270,7 +270,8 @@
fromInterfaceType, toInterfaceType, M.getSwiftModule());
auto loc = RegularLocation::getAutoGeneratedLocation();
+
return M.getOrCreateSharedFunction(loc, name, thunkType, IsBare,
IsTransparent, IsSerializable,
- IsReabstractionThunk);
+ ProfileCounter(), IsReabstractionThunk);
}
diff --git a/lib/SILGen/SILGenType.cpp b/lib/SILGen/SILGenType.cpp
index d42bbdb..5fbf293 100644
--- a/lib/SILGen/SILGenType.cpp
+++ b/lib/SILGen/SILGenType.cpp
@@ -690,10 +690,9 @@
InlineStrategy = AlwaysInline;
auto *f = M.createFunction(
- linkage, nameBuffer, witnessSILFnType,
- genericEnv, SILLocation(witnessRef.getDecl()),
- IsNotBare, IsTransparent, isSerialized, IsThunk,
- SubclassScope::NotApplicable, InlineStrategy);
+ linkage, nameBuffer, witnessSILFnType, genericEnv,
+ SILLocation(witnessRef.getDecl()), IsNotBare, IsTransparent, isSerialized,
+ ProfileCounter(), IsThunk, SubclassScope::NotApplicable, InlineStrategy);
f->setDebugScope(new (M)
SILDebugScope(RegularLocation(witnessRef.getDecl()), f));
diff --git a/lib/SILOptimizer/ARC/ARCRegionState.cpp b/lib/SILOptimizer/ARC/ARCRegionState.cpp
index 13c1d99..e4c2eed 100644
--- a/lib/SILOptimizer/ARC/ARCRegionState.cpp
+++ b/lib/SILOptimizer/ARC/ARCRegionState.cpp
@@ -516,9 +516,9 @@
static bool isStrongEntranceInstruction(const SILInstruction &I) {
switch (I.getKind()) {
- case ValueKind::AllocRefInst:
- case ValueKind::AllocRefDynamicInst:
- case ValueKind::AllocBoxInst:
+ case SILInstructionKind::AllocRefInst:
+ case SILInstructionKind::AllocRefDynamicInst:
+ case SILInstructionKind::AllocBoxInst:
return true;
default:
return false;
diff --git a/lib/SILOptimizer/ARC/RCStateTransition.cpp b/lib/SILOptimizer/ARC/RCStateTransition.cpp
index c74532a..23a2c1d 100644
--- a/lib/SILOptimizer/ARC/RCStateTransition.cpp
+++ b/lib/SILOptimizer/ARC/RCStateTransition.cpp
@@ -42,25 +42,25 @@
// RCStateTransitionKind
//===----------------------------------------------------------------------===//
-RCStateTransitionKind swift::getRCStateTransitionKind(ValueBase *V) {
- switch (V->getKind()) {
- case ValueKind::StrongRetainInst:
- case ValueKind::RetainValueInst:
+RCStateTransitionKind swift::getRCStateTransitionKind(SILNode *N) {
+ switch (N->getKind()) {
+ case SILNodeKind::StrongRetainInst:
+ case SILNodeKind::RetainValueInst:
return RCStateTransitionKind::StrongIncrement;
- case ValueKind::StrongReleaseInst:
- case ValueKind::ReleaseValueInst:
+ case SILNodeKind::StrongReleaseInst:
+ case SILNodeKind::ReleaseValueInst:
return RCStateTransitionKind::StrongDecrement;
- case ValueKind::SILFunctionArgument: {
- auto *Arg = cast<SILFunctionArgument>(V);
+ case SILNodeKind::SILFunctionArgument: {
+ auto *Arg = cast<SILFunctionArgument>(N);
if (Arg->hasConvention(SILArgumentConvention::Direct_Owned))
return RCStateTransitionKind::StrongEntrance;
return RCStateTransitionKind::Unknown;
}
- case ValueKind::ApplyInst: {
- auto *AI = cast<ApplyInst>(V);
+ case SILNodeKind::ApplyInst: {
+ auto *AI = cast<ApplyInst>(N);
if (isAutoreleasePoolCall(AI))
return RCStateTransitionKind::AutoreleasePoolCall;
@@ -78,13 +78,13 @@
return RCStateTransitionKind::Unknown;
}
- case ValueKind::AllocRefInst:
- case ValueKind::AllocRefDynamicInst:
+ case SILNodeKind::AllocRefInst:
+ case SILNodeKind::AllocRefDynamicInst:
// AllocRef* are always allocating new classes so they are introducing new
// values at +1.
return RCStateTransitionKind::StrongEntrance;
- case ValueKind::AllocBoxInst:
+ case SILNodeKind::AllocBoxInst:
// AllocBox introduce their container result at +1.
return RCStateTransitionKind::StrongEntrance;
diff --git a/lib/SILOptimizer/ARC/RCStateTransition.h b/lib/SILOptimizer/ARC/RCStateTransition.h
index 4772b2d..65829ff 100644
--- a/lib/SILOptimizer/ARC/RCStateTransition.h
+++ b/lib/SILOptimizer/ARC/RCStateTransition.h
@@ -41,18 +41,18 @@
#include "RCStateTransition.def"
};
-/// \returns the RCStateTransitionKind corresponding to \p V.
-RCStateTransitionKind getRCStateTransitionKind(ValueBase *V);
+/// \returns the RCStateTransitionKind corresponding to \p N.
+RCStateTransitionKind getRCStateTransitionKind(SILNode *N);
/// Define predicates to test for RCStateTransition abstract value kinds.
#define ABSTRACT_VALUE(Name, Start, End) \
bool isRCStateTransition ## Name(RCStateTransitionKind Kind); \
- static inline bool isRCStateTransition ## Name(ValueBase *V) { \
- return isRCStateTransition ## Name(getRCStateTransitionKind(V)); \
+ static inline bool isRCStateTransition ## Name(SILNode *N) { \
+ return isRCStateTransition ## Name(getRCStateTransitionKind(N)); \
}
#define KIND(Name) \
- static inline bool isRCStateTransition ## Name(ValueBase *V) { \
- return RCStateTransitionKind::Name == getRCStateTransitionKind(V); \
+ static inline bool isRCStateTransition ## Name(SILNode *N) { \
+ return RCStateTransitionKind::Name == getRCStateTransitionKind(N); \
}
#include "RCStateTransition.def"
@@ -72,7 +72,7 @@
/// An RCStateTransition can represent either an RC end point (i.e. an initial
/// or terminal RC transition) or a ptr set of Mutators.
- ValueBase *EndPoint;
+ SILNode *EndPoint;
ImmutablePointerSet<SILInstruction> *Mutators =
ImmutablePointerSetFactory<SILInstruction>::getEmptySet();
RCStateTransitionKind Kind;
diff --git a/lib/SILOptimizer/ARC/RCStateTransitionVisitors.cpp b/lib/SILOptimizer/ARC/RCStateTransitionVisitors.cpp
index 9f71f14..ee79d35 100644
--- a/lib/SILOptimizer/ARC/RCStateTransitionVisitors.cpp
+++ b/lib/SILOptimizer/ARC/RCStateTransitionVisitors.cpp
@@ -65,7 +65,7 @@
template <class ARCState>
typename BottomUpDataflowRCStateVisitor<ARCState>::DataflowResult
BottomUpDataflowRCStateVisitor<ARCState>::
-visitAutoreleasePoolCall(ValueBase *V) {
+visitAutoreleasePoolCall(SILNode *N) {
DataflowState.clear();
// We just cleared our BB State so we have no more possible effects.
@@ -107,8 +107,8 @@
template <class ARCState>
typename BottomUpDataflowRCStateVisitor<ARCState>::DataflowResult
-BottomUpDataflowRCStateVisitor<ARCState>::visitStrongDecrement(ValueBase *V) {
- auto *I = dyn_cast<SILInstruction>(V);
+BottomUpDataflowRCStateVisitor<ARCState>::visitStrongDecrement(SILNode *N) {
+ auto *I = dyn_cast<SILInstruction>(N);
if (!I)
return DataflowResult();
@@ -137,8 +137,8 @@
template <class ARCState>
typename BottomUpDataflowRCStateVisitor<ARCState>::DataflowResult
-BottomUpDataflowRCStateVisitor<ARCState>::visitStrongIncrement(ValueBase *V) {
- auto *I = dyn_cast<SILInstruction>(V);
+BottomUpDataflowRCStateVisitor<ARCState>::visitStrongIncrement(SILNode *N) {
+ auto *I = dyn_cast<SILInstruction>(N);
if (!I)
return DataflowResult();
@@ -191,7 +191,7 @@
template <class ARCState>
typename TopDownDataflowRCStateVisitor<ARCState>::DataflowResult
TopDownDataflowRCStateVisitor<ARCState>::
-visitAutoreleasePoolCall(ValueBase *V) {
+visitAutoreleasePoolCall(SILNode *N) {
DataflowState.clear();
// We just cleared our BB State so we have no more possible effects.
return DataflowResult(RCStateTransitionDataflowResultKind::NoEffects);
@@ -199,8 +199,8 @@
template <class ARCState>
typename TopDownDataflowRCStateVisitor<ARCState>::DataflowResult
-TopDownDataflowRCStateVisitor<ARCState>::visitStrongDecrement(ValueBase *V) {
- auto *I = dyn_cast<SILInstruction>(V);
+TopDownDataflowRCStateVisitor<ARCState>::visitStrongDecrement(SILNode *N) {
+ auto *I = dyn_cast<SILInstruction>(N);
if (!I)
return DataflowResult();
@@ -241,8 +241,8 @@
template <class ARCState>
typename TopDownDataflowRCStateVisitor<ARCState>::DataflowResult
-TopDownDataflowRCStateVisitor<ARCState>::visitStrongIncrement(ValueBase *V) {
- auto *I = dyn_cast<SILInstruction>(V);
+TopDownDataflowRCStateVisitor<ARCState>::visitStrongIncrement(SILNode *N) {
+ auto *I = dyn_cast<SILInstruction>(N);
if (!I)
return DataflowResult();
@@ -340,20 +340,20 @@
template <class ARCState>
typename TopDownDataflowRCStateVisitor<ARCState>::DataflowResult
TopDownDataflowRCStateVisitor<ARCState>::
-visitStrongEntrance(ValueBase *V) {
- if (auto *Arg = dyn_cast<SILFunctionArgument>(V))
+visitStrongEntrance(SILNode *N) {
+ if (auto *Arg = dyn_cast<SILFunctionArgument>(N))
return visitStrongEntranceArgument(Arg);
- if (auto *AI = dyn_cast<ApplyInst>(V))
+ if (auto *AI = dyn_cast<ApplyInst>(N))
return visitStrongEntranceApply(AI);
- if (auto *ARI = dyn_cast<AllocRefInst>(V))
+ if (auto *ARI = dyn_cast<AllocRefInst>(N))
return visitStrongEntranceAllocRef(ARI);
- if (auto *ARI = dyn_cast<AllocRefDynamicInst>(V))
+ if (auto *ARI = dyn_cast<AllocRefDynamicInst>(N))
return visitStrongEntranceAllocRefDynamic(ARI);
- if (auto *ABI = dyn_cast<AllocBoxInst>(V))
+ if (auto *ABI = dyn_cast<AllocBoxInst>(N))
return visitStrongAllocBox(ABI);
return DataflowResult();
diff --git a/lib/SILOptimizer/ARC/RCStateTransitionVisitors.h b/lib/SILOptimizer/ARC/RCStateTransitionVisitors.h
index 9a71d64..f51f518 100644
--- a/lib/SILOptimizer/ARC/RCStateTransitionVisitors.h
+++ b/lib/SILOptimizer/ARC/RCStateTransitionVisitors.h
@@ -38,14 +38,14 @@
ImplTy &asImpl() { return *reinterpret_cast<ImplTy *>(this); }
public:
-#define KIND(K) ResultTy visit ## K(ValueBase *) { return ResultTy(); }
+#define KIND(K) ResultTy visit ## K(SILNode *) { return ResultTy(); }
#include "RCStateTransition.def"
- ResultTy visit(ValueBase *V) {
- switch (getRCStateTransitionKind(V)) {
+ ResultTy visit(SILNode *N) {
+ switch (getRCStateTransitionKind(N)) {
#define KIND(K) \
case RCStateTransitionKind::K: \
- return asImpl().visit ## K(V);
+ return asImpl().visit ## K(N);
#include "RCStateTransition.def"
}
llvm_unreachable("Covered switch isn't covered?!");
@@ -128,9 +128,9 @@
ARCState &DataflowState, bool FreezeOwnedArgEpilogueReleases,
IncToDecStateMapTy &IncToDecStateMap,
ImmutablePointerSetFactory<SILInstruction> &SetFactory);
- DataflowResult visitAutoreleasePoolCall(ValueBase *V);
- DataflowResult visitStrongDecrement(ValueBase *V);
- DataflowResult visitStrongIncrement(ValueBase *V);
+ DataflowResult visitAutoreleasePoolCall(SILNode *N);
+ DataflowResult visitStrongDecrement(SILNode *N);
+ DataflowResult visitStrongIncrement(SILNode *N);
};
} // end swift namespace
@@ -163,10 +163,10 @@
RCIdentityFunctionInfo *RCFI, ARCState &State,
DecToIncStateMapTy &DecToIncStateMap,
ImmutablePointerSetFactory<SILInstruction> &SetFactory);
- DataflowResult visitAutoreleasePoolCall(ValueBase *V);
- DataflowResult visitStrongDecrement(ValueBase *V);
- DataflowResult visitStrongIncrement(ValueBase *V);
- DataflowResult visitStrongEntrance(ValueBase *V);
+ DataflowResult visitAutoreleasePoolCall(SILNode *N);
+ DataflowResult visitStrongDecrement(SILNode *N);
+ DataflowResult visitStrongIncrement(SILNode *N);
+ DataflowResult visitStrongEntrance(SILNode *N);
private:
DataflowResult visitStrongEntranceApply(ApplyInst *AI);
diff --git a/lib/SILOptimizer/Analysis/ARCAnalysis.cpp b/lib/SILOptimizer/Analysis/ARCAnalysis.cpp
index e48dbb9..2c2feb6 100644
--- a/lib/SILOptimizer/Analysis/ARCAnalysis.cpp
+++ b/lib/SILOptimizer/Analysis/ARCAnalysis.cpp
@@ -116,42 +116,42 @@
bool swift::canNeverUseValues(SILInstruction *Inst) {
switch (Inst->getKind()) {
// These instructions do not use other values.
- case ValueKind::FunctionRefInst:
- case ValueKind::IntegerLiteralInst:
- case ValueKind::FloatLiteralInst:
- case ValueKind::StringLiteralInst:
- case ValueKind::AllocStackInst:
- case ValueKind::AllocRefInst:
- case ValueKind::AllocRefDynamicInst:
- case ValueKind::AllocBoxInst:
- case ValueKind::MetatypeInst:
- case ValueKind::WitnessMethodInst:
+ case SILInstructionKind::FunctionRefInst:
+ case SILInstructionKind::IntegerLiteralInst:
+ case SILInstructionKind::FloatLiteralInst:
+ case SILInstructionKind::StringLiteralInst:
+ case SILInstructionKind::AllocStackInst:
+ case SILInstructionKind::AllocRefInst:
+ case SILInstructionKind::AllocRefDynamicInst:
+ case SILInstructionKind::AllocBoxInst:
+ case SILInstructionKind::MetatypeInst:
+ case SILInstructionKind::WitnessMethodInst:
return true;
// DeallocStackInst do not use reference counted values.
- case ValueKind::DeallocStackInst:
+ case SILInstructionKind::DeallocStackInst:
return true;
// Debug values do not use referenced counted values in a manner we care
// about.
- case ValueKind::DebugValueInst:
- case ValueKind::DebugValueAddrInst:
+ case SILInstructionKind::DebugValueInst:
+ case SILInstructionKind::DebugValueAddrInst:
return true;
// Casts do not use pointers in a manner that we care about since we strip
// them during our analysis. The reason for this is if the cast is not dead
// then there must be some other use after the cast that we will protect if a
// release is not in between the cast and the use.
- case ValueKind::UpcastInst:
- case ValueKind::AddressToPointerInst:
- case ValueKind::PointerToAddressInst:
- case ValueKind::UncheckedRefCastInst:
- case ValueKind::UncheckedRefCastAddrInst:
- case ValueKind::UncheckedAddrCastInst:
- case ValueKind::RefToRawPointerInst:
- case ValueKind::RawPointerToRefInst:
- case ValueKind::UnconditionalCheckedCastInst:
- case ValueKind::UncheckedBitwiseCastInst:
+ case SILInstructionKind::UpcastInst:
+ case SILInstructionKind::AddressToPointerInst:
+ case SILInstructionKind::PointerToAddressInst:
+ case SILInstructionKind::UncheckedRefCastInst:
+ case SILInstructionKind::UncheckedRefCastAddrInst:
+ case SILInstructionKind::UncheckedAddrCastInst:
+ case SILInstructionKind::RefToRawPointerInst:
+ case SILInstructionKind::RawPointerToRefInst:
+ case SILInstructionKind::UnconditionalCheckedCastInst:
+ case SILInstructionKind::UncheckedBitwiseCastInst:
return true;
// If we have a trivial bit cast between trivial types, it is not something
@@ -165,37 +165,37 @@
// trivial value though could be used as a trivial value in ways that ARC
// dataflow will not understand implying we need to treat it as a use to be
// safe.
- case ValueKind::UncheckedTrivialBitCastInst: {
+ case SILInstructionKind::UncheckedTrivialBitCastInst: {
SILValue Op = cast<UncheckedTrivialBitCastInst>(Inst)->getOperand();
return Op->getType().isTrivial(Inst->getModule());
}
// Typed GEPs do not use pointers. The user of the typed GEP may but we will
// catch that via the dataflow.
- case ValueKind::StructExtractInst:
- case ValueKind::TupleExtractInst:
- case ValueKind::StructElementAddrInst:
- case ValueKind::TupleElementAddrInst:
- case ValueKind::UncheckedTakeEnumDataAddrInst:
- case ValueKind::RefElementAddrInst:
- case ValueKind::RefTailAddrInst:
- case ValueKind::UncheckedEnumDataInst:
- case ValueKind::IndexAddrInst:
- case ValueKind::IndexRawPointerInst:
+ case SILInstructionKind::StructExtractInst:
+ case SILInstructionKind::TupleExtractInst:
+ case SILInstructionKind::StructElementAddrInst:
+ case SILInstructionKind::TupleElementAddrInst:
+ case SILInstructionKind::UncheckedTakeEnumDataAddrInst:
+ case SILInstructionKind::RefElementAddrInst:
+ case SILInstructionKind::RefTailAddrInst:
+ case SILInstructionKind::UncheckedEnumDataInst:
+ case SILInstructionKind::IndexAddrInst:
+ case SILInstructionKind::IndexRawPointerInst:
return true;
// Aggregate formation by themselves do not create new uses since it is their
// users that would create the appropriate uses.
- case ValueKind::EnumInst:
- case ValueKind::StructInst:
- case ValueKind::TupleInst:
+ case SILInstructionKind::EnumInst:
+ case SILInstructionKind::StructInst:
+ case SILInstructionKind::TupleInst:
return true;
// Only uses non reference counted values.
- case ValueKind::CondFailInst:
+ case SILInstructionKind::CondFailInst:
return true;
- case ValueKind::BuiltinInst: {
+ case SILInstructionKind::BuiltinInst: {
auto *BI = cast<BuiltinInst>(Inst);
// Certain builtin function refs we know can never use non-trivial values.
@@ -203,8 +203,8 @@
}
// We do not care about branch inst, since if the branch inst's argument is
// dead, LLVM will clean it up.
- case ValueKind::BranchInst:
- case ValueKind::CondBranchInst:
+ case SILInstructionKind::BranchInst:
+ case SILInstructionKind::CondBranchInst:
return true;
default:
return false;
@@ -1116,14 +1116,14 @@
//===----------------------------------------------------------------------===//
// Analysis of builtin "unsafeGuaranteed" instructions
//===----------------------------------------------------------------------===//
-std::pair<SILInstruction *, SILInstruction *>
+std::pair<SingleValueInstruction *, SingleValueInstruction *>
swift::getSingleUnsafeGuaranteedValueResult(BuiltinInst *BI) {
assert(BI->getBuiltinKind() &&
*BI->getBuiltinKind() == BuiltinValueKind::UnsafeGuaranteed &&
"Expecting a unsafeGuaranteed builtin");
- SILInstruction *GuaranteedValue = nullptr;
- SILInstruction *Token = nullptr;
+ SingleValueInstruction *GuaranteedValue = nullptr;
+ SingleValueInstruction *Token = nullptr;
auto Failed = std::make_pair(nullptr, nullptr);
@@ -1153,7 +1153,7 @@
return std::make_pair(GuaranteedValue, Token);
}
-BuiltinInst *swift::getUnsafeGuaranteedEndUser(SILInstruction *UnsafeGuaranteedToken) {
+BuiltinInst *swift::getUnsafeGuaranteedEndUser(SILValue UnsafeGuaranteedToken) {
BuiltinInst *UnsafeGuaranteedEndI = nullptr;
for (auto *Operand : getNonDebugUses(UnsafeGuaranteedToken)) {
diff --git a/lib/SILOptimizer/Analysis/AccessSummaryAnalysis.cpp b/lib/SILOptimizer/Analysis/AccessSummaryAnalysis.cpp
index 59b00de..bcb328b 100644
--- a/lib/SILOptimizer/Analysis/AccessSummaryAnalysis.cpp
+++ b/lib/SILOptimizer/Analysis/AccessSummaryAnalysis.cpp
@@ -64,7 +64,7 @@
SILInstruction *user = operand->getUser();
switch (user->getKind()) {
- case ValueKind::BeginAccessInst: {
+ case SILInstructionKind::BeginAccessInst: {
auto *BAI = cast<BeginAccessInst>(user);
const IndexTrieNode *subPath = findSubPathAccessed(BAI);
summary.mergeWith(BAI->getAccessKind(), BAI->getLoc(), subPath);
@@ -75,31 +75,33 @@
// elsewhere.
break;
}
- case ValueKind::EndUnpairedAccessInst:
+ case SILInstructionKind::EndUnpairedAccessInst:
// Don't diagnose unpaired access statically.
assert(cast<EndUnpairedAccessInst>(user)->getEnforcement() ==
SILAccessEnforcement::Dynamic);
break;
- case ValueKind::StructElementAddrInst:
- case ValueKind::TupleElementAddrInst:
+ case SILInstructionKind::StructElementAddrInst:
+ case SILInstructionKind::TupleElementAddrInst: {
// Eventually we'll summarize individual struct elements separately.
// For now an access to a part of the struct is treated as an access
// to the whole struct.
- worklist.append(user->use_begin(), user->use_end());
+ auto inst = cast<SingleValueInstruction>(user);
+ worklist.append(inst->use_begin(), inst->use_end());
break;
- case ValueKind::DebugValueAddrInst:
- case ValueKind::AddressToPointerInst:
+ }
+ case SILInstructionKind::DebugValueAddrInst:
+ case SILInstructionKind::AddressToPointerInst:
// Ignore these uses, they don't affect formal accesses.
break;
- case ValueKind::PartialApplyInst:
+ case SILInstructionKind::PartialApplyInst:
processPartialApply(info, argumentIndex, cast<PartialApplyInst>(user),
operand, order);
break;
- case ValueKind::ApplyInst:
+ case SILInstructionKind::ApplyInst:
processFullApply(info, argumentIndex, cast<ApplyInst>(user), operand,
order);
break;
- case ValueKind::TryApplyInst:
+ case SILInstructionKind::TryApplyInst:
processFullApply(info, argumentIndex, cast<TryApplyInst>(user), operand,
order);
break;
@@ -128,19 +130,19 @@
// It is fine to call the partial apply
switch (user->getKind()) {
- case ValueKind::ApplyInst:
- case ValueKind::TryApplyInst:
+ case SILInstructionKind::ApplyInst:
+ case SILInstructionKind::TryApplyInst:
return true;
- case ValueKind::ConvertFunctionInst:
- return llvm::all_of(user->getUses(),
+ case SILInstructionKind::ConvertFunctionInst:
+ return llvm::all_of(cast<ConvertFunctionInst>(user)->getUses(),
hasExpectedUsesOfNoEscapePartialApply);
- case ValueKind::PartialApplyInst:
+ case SILInstructionKind::PartialApplyInst:
return partialApplyUse->get() != cast<PartialApplyInst>(user)->getCallee();
- case ValueKind::StoreInst:
- case ValueKind::DestroyValueInst:
+ case SILInstructionKind::StoreInst:
+ case SILInstructionKind::DestroyValueInst:
// @block_storage is passed by storing it to the stack. We know this is
// still nonescaping simply because our original argument convention is
// @inout_aliasable. In this SIL, both store and destroy_value are users
@@ -432,9 +434,9 @@
/// user return a pair of the single user and the projection index.
/// Otherwise, return a pair with the component nullptr and the second
/// unspecified.
-static std::pair<SILInstruction *, unsigned>
-getSingleAddressProjectionUser(SILInstruction *I) {
- SILInstruction *SingleUser = nullptr;
+static std::pair<SingleValueInstruction *, unsigned>
+getSingleAddressProjectionUser(SingleValueInstruction *I) {
+ SingleValueInstruction *SingleUser = nullptr;
unsigned ProjectionIndex = 0;
for (Operand *Use : I->getUses()) {
@@ -447,14 +449,18 @@
return std::make_pair(nullptr, 0);
switch (User->getKind()) {
- case ValueKind::StructElementAddrInst:
- ProjectionIndex = cast<StructElementAddrInst>(User)->getFieldNo();
- SingleUser = User;
+ case SILInstructionKind::StructElementAddrInst: {
+ auto inst = cast<StructElementAddrInst>(User);
+ ProjectionIndex = inst->getFieldNo();
+ SingleUser = inst;
break;
- case ValueKind::TupleElementAddrInst:
- ProjectionIndex = cast<TupleElementAddrInst>(User)->getFieldNo();
- SingleUser = User;
+ }
+ case SILInstructionKind::TupleElementAddrInst: {
+ auto inst = cast<TupleElementAddrInst>(User);
+ ProjectionIndex = inst->getFieldNo();
+ SingleUser = inst;
break;
+ }
default:
return std::make_pair(nullptr, 0);
}
@@ -470,9 +476,9 @@
// For each single-user projection of BAI, construct or get a node
// from the trie representing the index of the field or tuple element
// accessed by that projection.
- SILInstruction *Iter = BAI;
+ SingleValueInstruction *Iter = BAI;
while (true) {
- std::pair<SILInstruction *, unsigned> ProjectionUser =
+ std::pair<SingleValueInstruction *, unsigned> ProjectionUser =
getSingleAddressProjectionUser(Iter);
if (!ProjectionUser.first)
break;
diff --git a/lib/SILOptimizer/Analysis/AliasAnalysis.cpp b/lib/SILOptimizer/Analysis/AliasAnalysis.cpp
index 3cb3435..5b2d77f 100644
--- a/lib/SILOptimizer/Analysis/AliasAnalysis.cpp
+++ b/lib/SILOptimizer/Analysis/AliasAnalysis.cpp
@@ -302,18 +302,18 @@
/// TBAA to know what the real types associated with the SILInstruction are.
static bool isTypedAccessOracle(SILInstruction *I) {
switch (I->getKind()) {
- case ValueKind::RefElementAddrInst:
- case ValueKind::RefTailAddrInst:
- case ValueKind::StructElementAddrInst:
- case ValueKind::TupleElementAddrInst:
- case ValueKind::UncheckedTakeEnumDataAddrInst:
- case ValueKind::LoadInst:
- case ValueKind::StoreInst:
- case ValueKind::AllocStackInst:
- case ValueKind::AllocBoxInst:
- case ValueKind::ProjectBoxInst:
- case ValueKind::DeallocStackInst:
- case ValueKind::DeallocBoxInst:
+ case SILInstructionKind::RefElementAddrInst:
+ case SILInstructionKind::RefTailAddrInst:
+ case SILInstructionKind::StructElementAddrInst:
+ case SILInstructionKind::TupleElementAddrInst:
+ case SILInstructionKind::UncheckedTakeEnumDataAddrInst:
+ case SILInstructionKind::LoadInst:
+ case SILInstructionKind::StoreInst:
+ case SILInstructionKind::AllocStackInst:
+ case SILInstructionKind::AllocBoxInst:
+ case SILInstructionKind::ProjectBoxInst:
+ case SILInstructionKind::DeallocStackInst:
+ case SILInstructionKind::DeallocBoxInst:
return true;
default:
return false;
@@ -352,7 +352,8 @@
static SILType findTypedAccessType(SILValue V) {
// First look at the origin of V and see if we have any instruction that is a
// typed oracle.
- if (auto *I = dyn_cast<SILInstruction>(V))
+ // TODO: MultiValueInstruction
+ if (auto *I = dyn_cast<SingleValueInstruction>(V))
if (isTypedAccessOracle(I))
return V->getType();
diff --git a/lib/SILOptimizer/Analysis/ArraySemantic.cpp b/lib/SILOptimizer/Analysis/ArraySemantic.cpp
index 85a4e09..24cc25a 100644
--- a/lib/SILOptimizer/Analysis/ArraySemantic.cpp
+++ b/lib/SILOptimizer/Analysis/ArraySemantic.cpp
@@ -112,27 +112,52 @@
}
/// Match array semantic calls.
-swift::ArraySemanticsCall::ArraySemanticsCall(ValueBase *V,
- StringRef SemanticStr,
- bool MatchPartialName) {
- if (auto *AI = dyn_cast<ApplyInst>(V))
- if (auto *Fn = AI->getReferencedFunction())
- if ((MatchPartialName &&
- Fn->hasSemanticsAttrThatStartsWith(SemanticStr)) ||
- (!MatchPartialName && Fn->hasSemanticsAttr(SemanticStr))) {
- SemanticsCall = AI;
- // Need a 'self' argument otherwise this is not a semantic call that
- // we recognize.
- if (getKind() < ArrayCallKind::kArrayInit && !hasSelf())
- SemanticsCall = nullptr;
+swift::ArraySemanticsCall::ArraySemanticsCall(SILValue V,
+ StringRef semanticName,
+ bool matchPartialName)
+ : SemanticsCall(nullptr) {
+ if (auto AI = dyn_cast<ApplyInst>(V))
+ initialize(AI, semanticName, matchPartialName);
+}
- // A arguments must be passed reference count neutral except for self.
- if (SemanticsCall && !isValidSignature())
- SemanticsCall = nullptr;
- return;
- }
- // Otherwise, this is not the semantic call we are looking for.
- SemanticsCall = nullptr;
+/// Match array semantic calls.
+swift::ArraySemanticsCall::ArraySemanticsCall(SILInstruction *I,
+ StringRef semanticName,
+ bool matchPartialName)
+ : SemanticsCall(nullptr) {
+ if (auto AI = dyn_cast<ApplyInst>(I))
+ initialize(AI, semanticName, matchPartialName);
+}
+
+/// Match array semantic calls.
+swift::ArraySemanticsCall::ArraySemanticsCall(ApplyInst *AI,
+ StringRef semanticName,
+ bool matchPartialName)
+ : SemanticsCall(nullptr) {
+ initialize(AI, semanticName, matchPartialName);
+}
+
+void ArraySemanticsCall::initialize(ApplyInst *AI, StringRef semanticName,
+ bool matchPartialName) {
+ auto *fn = AI->getReferencedFunction();
+ if (!fn)
+ return;
+
+ if (!(matchPartialName
+ ? fn->hasSemanticsAttrThatStartsWith(semanticName)
+ : fn->hasSemanticsAttr(semanticName)))
+ return;
+
+ SemanticsCall = AI;
+
+ // Need a 'self' argument otherwise this is not a semantic call that
+ // we recognize.
+ if (getKind() < ArrayCallKind::kArrayInit && !hasSelf())
+ SemanticsCall = nullptr;
+
+ // A arguments must be passed reference count neutral except for self.
+ if (SemanticsCall && !isValidSignature())
+ SemanticsCall = nullptr;
}
/// Determine which kind of array semantics call this is.
@@ -347,7 +372,7 @@
InsertPt = Inst;
}
- return LI->clone(InsertBefore);
+ return cast<LoadInst>(LI->clone(InsertBefore));
}
static ApplyInst *hoistOrCopyCall(ApplyInst *AI, SILInstruction *InsertBefore,
diff --git a/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp b/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp
index 417678f..8aca566 100644
--- a/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp
+++ b/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp
@@ -24,60 +24,70 @@
using namespace swift;
-static bool isProjection(ValueBase *V) {
- switch (V->getKind()) {
- case ValueKind::IndexAddrInst:
- case ValueKind::IndexRawPointerInst:
- case ValueKind::StructElementAddrInst:
- case ValueKind::TupleElementAddrInst:
- case ValueKind::UncheckedTakeEnumDataAddrInst:
- case ValueKind::StructExtractInst:
- case ValueKind::UncheckedEnumDataInst:
- case ValueKind::MarkDependenceInst:
- case ValueKind::PointerToAddressInst:
- case ValueKind::AddressToPointerInst:
- case ValueKind::InitEnumDataAddrInst:
- return true;
- case ValueKind::TupleExtractInst: {
- auto *TEI = cast<TupleExtractInst>(V);
- // Special handling for extracting the pointer-result from an
- // array construction. We handle this like a ref_element_addr
- // rather than a projection. See the handling of tuple_extract
- // in analyzeInstruction().
- if (TEI->getFieldNo() == 1 &&
- ArraySemanticsCall(TEI->getOperand(), "array.uninitialized", false))
- return false;
- return true;
- }
- default:
- return false;
+static bool isExtractOfArrayUninitializedPointer(TupleExtractInst *TEI) {
+ if (TEI->getFieldNo() == 1) {
+ if (auto apply = dyn_cast<ApplyInst>(TEI->getOperand()))
+ if (ArraySemanticsCall(apply, "array.uninitialized", false))
+ return true;
+ }
+ return false;
+}
+
+static SingleValueInstruction *isProjection(SILNode *node) {
+ switch (node->getKind()) {
+ case SILNodeKind::IndexAddrInst:
+ case SILNodeKind::IndexRawPointerInst:
+ case SILNodeKind::StructElementAddrInst:
+ case SILNodeKind::TupleElementAddrInst:
+ case SILNodeKind::UncheckedTakeEnumDataAddrInst:
+ case SILNodeKind::StructExtractInst:
+ case SILNodeKind::UncheckedEnumDataInst:
+ case SILNodeKind::MarkDependenceInst:
+ case SILNodeKind::PointerToAddressInst:
+ case SILNodeKind::AddressToPointerInst:
+ case SILNodeKind::InitEnumDataAddrInst:
+ return cast<SingleValueInstruction>(node);
+ case SILNodeKind::TupleExtractInst: {
+ auto *TEI = cast<TupleExtractInst>(node);
+ // Special handling for extracting the pointer-result from an
+ // array construction. We handle this like a ref_element_addr
+ // rather than a projection. See the handling of tuple_extract
+ // in analyzeInstruction().
+ if (isExtractOfArrayUninitializedPointer(TEI))
+ return nullptr;
+ return TEI;
+ }
+ default:
+ return nullptr;
}
}
-static bool isNonWritableMemoryAddress(ValueBase *V) {
+static bool isNonWritableMemoryAddress(SILNode *V) {
switch (V->getKind()) {
- case ValueKind::FunctionRefInst:
- case ValueKind::WitnessMethodInst:
- case ValueKind::ClassMethodInst:
- case ValueKind::SuperMethodInst:
- case ValueKind::DynamicMethodInst:
- case ValueKind::StringLiteralInst:
- case ValueKind::ThinToThickFunctionInst:
- case ValueKind::ThinFunctionToPointerInst:
- case ValueKind::PointerToThinFunctionInst:
- // These instructions return pointers to memory which can't be a
- // destination of a store.
- return true;
- default:
- return false;
+ case SILNodeKind::FunctionRefInst:
+ case SILNodeKind::WitnessMethodInst:
+ case SILNodeKind::ClassMethodInst:
+ case SILNodeKind::SuperMethodInst:
+ case SILNodeKind::DynamicMethodInst:
+ case SILNodeKind::StringLiteralInst:
+ case SILNodeKind::ThinToThickFunctionInst:
+ case SILNodeKind::ThinFunctionToPointerInst:
+ case SILNodeKind::PointerToThinFunctionInst:
+ // These instructions return pointers to memory which can't be a
+ // destination of a store.
+ return true;
+ default:
+ return false;
}
}
static ValueBase *skipProjections(ValueBase *V) {
for (;;) {
- if (!isProjection(V))
+ if (auto SVI = isProjection(V)) {
+ V = SVI->getOperand(0);
+ } else {
return V;
- V = cast<SILInstruction>(V)->getOperand(0);
+ }
}
llvm_unreachable("there is no escape from an infinite loop");
}
@@ -97,9 +107,6 @@
if (isa<FunctionRefInst>(V))
return nullptr;
- if (!V->hasValue())
- return nullptr;
-
if (!EA->isPointer(V))
return nullptr;
@@ -394,11 +401,11 @@
for (auto &I : BB) {
switch (I.getKind()) {
- case ValueKind::StrongReleaseInst:
- case ValueKind::ReleaseValueInst:
- case ValueKind::UnownedReleaseInst:
- case ValueKind::ApplyInst:
- case ValueKind::TryApplyInst: {
+ case SILInstructionKind::StrongReleaseInst:
+ case SILInstructionKind::ReleaseValueInst:
+ case SILInstructionKind::UnownedReleaseInst:
+ case SILInstructionKind::ApplyInst:
+ case SILInstructionKind::TryApplyInst: {
/// Actually we only add instructions which may release a reference.
/// We need the use points only for getting the end of a reference's
/// liferange. And that must be a releasing instruction.
@@ -536,10 +543,12 @@
/// somehow refer to the Node's value.
/// Use-points are only values which are relevant for lifeness computation,
/// e.g. release or apply instructions.
-bool EscapeAnalysis::ConnectionGraph::isUsePoint(ValueBase *V, CGNode *Node) {
+bool EscapeAnalysis::ConnectionGraph::isUsePoint(SILNode *UsePoint,
+ CGNode *Node) {
assert(Node->getEscapeState() < EscapeState::Global &&
"Use points are only valid for non-escaping nodes");
- auto Iter = UsePoints.find(V);
+ UsePoint = UsePoint->getCanonicalSILNodeInObject();
+ auto Iter = UsePoints.find(UsePoint);
if (Iter == UsePoints.end())
return false;
int Idx = Iter->second;
@@ -549,7 +558,7 @@
}
void EscapeAnalysis::ConnectionGraph::
-getUsePoints(CGNode *Node, llvm::SmallVectorImpl<ValueBase *> &UsePoints) {
+getUsePoints(CGNode *Node, llvm::SmallVectorImpl<SILNode *> &UsePoints) {
assert(Node->getEscapeState() < EscapeState::Global &&
"Use points are only valid for non-escaping nodes");
for (int Idx = Node->UsePoints.find_first(); Idx >= 0;
@@ -620,7 +629,7 @@
const EscapeAnalysis::ConnectionGraph *OrigGraph;
// The same IDs as the SILPrinter uses.
- llvm::DenseMap<const ValueBase *, unsigned> InstToIDMap;
+ llvm::DenseMap<const SILNode *, unsigned> InstToIDMap;
typedef std::vector<Node>::iterator iterator;
typedef SmallVectorImpl<Node *>::iterator child_iterator;
@@ -846,7 +855,7 @@
OS << "CG of " << F->getName() << '\n';
// Assign the same IDs to SILValues as the SILPrinter does.
- llvm::DenseMap<const ValueBase *, unsigned> InstToIDMap;
+ llvm::DenseMap<const SILNode *, unsigned> InstToIDMap;
InstToIDMap[nullptr] = (unsigned)-1;
F->numberValues(InstToIDMap);
@@ -897,8 +906,8 @@
const char *Separator = "";
for (unsigned VIdx = Nd->UsePoints.find_first(); VIdx != -1u;
VIdx = Nd->UsePoints.find_next(VIdx)) {
- ValueBase *V = UsePointTable[VIdx];
- OS << Separator << '%' << InstToIDMap[V];
+ auto node = UsePointTable[VIdx];
+ OS << Separator << '%' << InstToIDMap[node];
Separator = ",";
}
break;
@@ -1039,7 +1048,6 @@
}
bool EscapeAnalysis::isPointer(ValueBase *V) {
- assert(V->hasValue());
SILType Ty = V->getType();
auto Iter = isPointerCache.find(Ty);
if (Iter != isPointerCache.end())
@@ -1119,8 +1127,8 @@
}
/// Returns true if all uses of \p I are tuple_extract instructions.
-static bool onlyUsedInTupleExtract(SILInstruction *I) {
- for (Operand *Use : getNonDebugUses(I)) {
+static bool onlyUsedInTupleExtract(SILValue V) {
+ for (Operand *Use : getNonDebugUses(V)) {
if (!isa<TupleExtractInst>(Use->getUser()))
return false;
}
@@ -1203,12 +1211,12 @@
case ArrayCallKind::kArrayUninitialized:
// Check if the result is used in the usual way: extracting the
// array and the element pointer with tuple_extract.
- if (onlyUsedInTupleExtract(I)) {
+ if (onlyUsedInTupleExtract(ASC.getCallResult())) {
// array.uninitialized may have a first argument which is the
// allocated array buffer. The call is like a struct(buffer)
// instruction.
if (CGNode *BufferNode = ConGraph->getNode(FAS.getArgument(0), this)) {
- CGNode *ArrayNode = ConGraph->getNode(I, this);
+ CGNode *ArrayNode = ConGraph->getNode(ASC.getCallResult(), this);
CGNode *ArrayContent = ConGraph->getContentNode(ArrayNode);
ConGraph->defer(ArrayContent, BufferNode);
}
@@ -1217,7 +1225,8 @@
break;
case ArrayCallKind::kGetArrayOwner:
if (CGNode *BufferNode = ConGraph->getNode(ASC.getSelf(), this)) {
- ConGraph->defer(ConGraph->getNode(I, this), BufferNode);
+ ConGraph->defer(ConGraph->getNode(ASC.getCallResult(), this),
+ BufferNode);
}
return;
case ArrayCallKind::kGetElement:
@@ -1225,7 +1234,7 @@
CGNode *DestNode = nullptr;
// This is like a load from a ref_element_addr.
if (ASC.hasGetElementDirectResult()) {
- DestNode = ConGraph->getNode(FAS.getInstruction(), this);
+ DestNode = ConGraph->getNode(ASC.getCallResult(), this);
} else {
CGNode *DestAddrNode = ConGraph->getNode(FAS.getArgument(0), this);
assert(DestAddrNode && "indirect result must have node");
@@ -1246,7 +1255,7 @@
case ArrayCallKind::kGetElementAddress:
// This is like a ref_element_addr.
if (CGNode *SelfNode = ConGraph->getNode(ASC.getSelf(), this)) {
- ConGraph->defer(ConGraph->getNode(I, this),
+ ConGraph->defer(ConGraph->getNode(ASC.getCallResult(), this),
ConGraph->getContentNode(SelfNode));
}
return;
@@ -1338,35 +1347,35 @@
return;
switch (I->getKind()) {
- case ValueKind::AllocStackInst:
- case ValueKind::AllocRefInst:
- case ValueKind::AllocBoxInst:
- ConGraph->getNode(I, this);
+ case SILInstructionKind::AllocStackInst:
+ case SILInstructionKind::AllocRefInst:
+ case SILInstructionKind::AllocBoxInst:
+ ConGraph->getNode(cast<SingleValueInstruction>(I), this);
return;
- case ValueKind::DeallocStackInst:
- case ValueKind::StrongRetainInst:
- case ValueKind::StrongRetainUnownedInst:
- case ValueKind::RetainValueInst:
- case ValueKind::UnownedRetainInst:
- case ValueKind::BranchInst:
- case ValueKind::CondBranchInst:
- case ValueKind::SwitchEnumInst:
- case ValueKind::DebugValueInst:
- case ValueKind::DebugValueAddrInst:
- case ValueKind::ValueMetatypeInst:
- case ValueKind::InitExistentialMetatypeInst:
- case ValueKind::OpenExistentialMetatypeInst:
- case ValueKind::ExistentialMetatypeInst:
- case ValueKind::DeallocRefInst:
- case ValueKind::SetDeallocatingInst:
- case ValueKind::FixLifetimeInst:
+ case SILInstructionKind::DeallocStackInst:
+ case SILInstructionKind::StrongRetainInst:
+ case SILInstructionKind::StrongRetainUnownedInst:
+ case SILInstructionKind::RetainValueInst:
+ case SILInstructionKind::UnownedRetainInst:
+ case SILInstructionKind::BranchInst:
+ case SILInstructionKind::CondBranchInst:
+ case SILInstructionKind::SwitchEnumInst:
+ case SILInstructionKind::DebugValueInst:
+ case SILInstructionKind::DebugValueAddrInst:
+ case SILInstructionKind::ValueMetatypeInst:
+ case SILInstructionKind::InitExistentialMetatypeInst:
+ case SILInstructionKind::OpenExistentialMetatypeInst:
+ case SILInstructionKind::ExistentialMetatypeInst:
+ case SILInstructionKind::DeallocRefInst:
+ case SILInstructionKind::SetDeallocatingInst:
+ case SILInstructionKind::FixLifetimeInst:
// These instructions don't have any effect on escaping.
return;
- case ValueKind::StrongReleaseInst:
- case ValueKind::ReleaseValueInst:
- case ValueKind::StrongUnpinInst:
- case ValueKind::UnownedReleaseInst: {
+ case SILInstructionKind::StrongReleaseInst:
+ case SILInstructionKind::ReleaseValueInst:
+ case SILInstructionKind::StrongUnpinInst:
+ case SILInstructionKind::UnownedReleaseInst: {
SILValue OpV = I->getOperand(0);
if (CGNode *AddrNode = ConGraph->getNode(OpV, this)) {
// A release instruction may deallocate the pointer operand. This may
@@ -1382,29 +1391,31 @@
}
return;
}
- case ValueKind::LoadInst:
- case ValueKind::LoadWeakInst:
+ case SILInstructionKind::LoadInst:
+ case SILInstructionKind::LoadWeakInst:
// We treat ref_element_addr like a load (see NodeType::Content).
- case ValueKind::RefElementAddrInst:
- case ValueKind::RefTailAddrInst:
- case ValueKind::ProjectBoxInst:
- case ValueKind::InitExistentialAddrInst:
- case ValueKind::OpenExistentialAddrInst:
- if (isPointer(I)) {
- CGNode *AddrNode = ConGraph->getNode(I->getOperand(0), this);
+ case SILInstructionKind::RefElementAddrInst:
+ case SILInstructionKind::RefTailAddrInst:
+ case SILInstructionKind::ProjectBoxInst:
+ case SILInstructionKind::InitExistentialAddrInst:
+ case SILInstructionKind::OpenExistentialAddrInst: {
+ auto SVI = cast<SingleValueInstruction>(I);
+ if (isPointer(SVI)) {
+ CGNode *AddrNode = ConGraph->getNode(SVI->getOperand(0), this);
if (!AddrNode) {
// A load from an address we don't handle -> be conservative.
- CGNode *ValueNode = ConGraph->getNode(I, this);
+ CGNode *ValueNode = ConGraph->getNode(SVI, this);
ConGraph->setEscapesGlobal(ValueNode);
return;
}
CGNode *PointsTo = ConGraph->getContentNode(AddrNode);
// No need for a separate node for the load instruction:
// just reuse the content node.
- ConGraph->setNode(I, PointsTo);
+ ConGraph->setNode(SVI, PointsTo);
}
return;
- case ValueKind::CopyAddrInst: {
+ }
+ case SILInstructionKind::CopyAddrInst: {
// Be conservative if the dest may be the final release.
if (!cast<CopyAddrInst>(I)->isInitializationOfDest()) {
setAllEscaping(I, ConGraph);
@@ -1433,8 +1444,8 @@
return;
}
break;
- case ValueKind::StoreInst:
- case ValueKind::StoreWeakInst:
+ case SILInstructionKind::StoreInst:
+ case SILInstructionKind::StoreWeakInst:
if (CGNode *ValueNode = ConGraph->getNode(I->getOperand(StoreInst::Src),
this)) {
CGNode *AddrNode = ConGraph->getNode(I->getOperand(StoreInst::Dest),
@@ -1449,40 +1460,42 @@
}
}
return;
- case ValueKind::PartialApplyInst: {
+ case SILInstructionKind::PartialApplyInst: {
// The result of a partial_apply is a thick function which stores the
// boxed partial applied arguments. We create defer-edges from the
// partial_apply values to the arguments.
- CGNode *ResultNode = ConGraph->getNode(I, this);
+ auto PAI = cast<PartialApplyInst>(I);
+ CGNode *ResultNode = ConGraph->getNode(PAI, this);
assert(ResultNode && "thick functions must have a CG node");
- for (const Operand &Op : I->getAllOperands()) {
+ for (const Operand &Op : PAI->getAllOperands()) {
if (CGNode *ArgNode = ConGraph->getNode(Op.get(), this)) {
ResultNode = ConGraph->defer(ResultNode, ArgNode);
}
}
return;
}
- case ValueKind::SelectEnumInst:
- case ValueKind::SelectEnumAddrInst:
+ case SILInstructionKind::SelectEnumInst:
+ case SILInstructionKind::SelectEnumAddrInst:
analyzeSelectInst(cast<SelectEnumInstBase>(I), ConGraph);
return;
- case ValueKind::SelectValueInst:
+ case SILInstructionKind::SelectValueInst:
analyzeSelectInst(cast<SelectValueInst>(I), ConGraph);
return;
- case ValueKind::StructInst:
- case ValueKind::TupleInst:
- case ValueKind::EnumInst: {
+ case SILInstructionKind::StructInst:
+ case SILInstructionKind::TupleInst:
+ case SILInstructionKind::EnumInst: {
// Aggregate composition is like assigning the aggregate fields to the
// resulting aggregate value.
+ auto SVI = cast<SingleValueInstruction>(I);
CGNode *ResultNode = nullptr;
- for (const Operand &Op : I->getAllOperands()) {
+ for (const Operand &Op : SVI->getAllOperands()) {
if (CGNode *FieldNode = ConGraph->getNode(Op.get(), this)) {
if (!ResultNode) {
// A small optimization to reduce the graph size: we re-use the
// first field node as result node.
- ConGraph->setNode(I, FieldNode);
+ ConGraph->setNode(SVI, FieldNode);
ResultNode = FieldNode;
- assert(isPointer(I));
+ assert(isPointer(SVI));
} else {
ResultNode = ConGraph->defer(ResultNode, FieldNode);
}
@@ -1490,41 +1503,40 @@
}
return;
}
- case ValueKind::TupleExtractInst: {
+ case SILInstructionKind::TupleExtractInst: {
// This is a tuple_extract which extracts the second result of an
// array.uninitialized call. The first result is the array itself.
// The second result (which is a pointer to the array elements) must be
// the content node of the first result. It's just like a ref_element_addr
// instruction.
auto *TEI = cast<TupleExtractInst>(I);
- assert(TEI->getFieldNo() == 1 &&
- ArraySemanticsCall(TEI->getOperand(), "array.uninitialized", false)
+ assert(isExtractOfArrayUninitializedPointer(TEI)
&& "tuple_extract should be handled as projection");
CGNode *ArrayNode = ConGraph->getNode(TEI->getOperand(), this);
CGNode *ArrayElements = ConGraph->getContentNode(ArrayNode);
- ConGraph->setNode(I, ArrayElements);
+ ConGraph->setNode(TEI, ArrayElements);
return;
}
- case ValueKind::UncheckedRefCastInst:
- case ValueKind::ConvertFunctionInst:
- case ValueKind::UpcastInst:
- case ValueKind::InitExistentialRefInst:
- case ValueKind::OpenExistentialRefInst:
- case ValueKind::UnownedToRefInst:
- case ValueKind::RefToUnownedInst:
- case ValueKind::RawPointerToRefInst:
- case ValueKind::RefToRawPointerInst:
- case ValueKind::RefToBridgeObjectInst:
- case ValueKind::BridgeObjectToRefInst:
- case ValueKind::UncheckedAddrCastInst:
- case ValueKind::UnconditionalCheckedCastInst:
- case ValueKind::StrongPinInst:
+ case SILInstructionKind::UncheckedRefCastInst:
+ case SILInstructionKind::ConvertFunctionInst:
+ case SILInstructionKind::UpcastInst:
+ case SILInstructionKind::InitExistentialRefInst:
+ case SILInstructionKind::OpenExistentialRefInst:
+ case SILInstructionKind::UnownedToRefInst:
+ case SILInstructionKind::RefToUnownedInst:
+ case SILInstructionKind::RawPointerToRefInst:
+ case SILInstructionKind::RefToRawPointerInst:
+ case SILInstructionKind::RefToBridgeObjectInst:
+ case SILInstructionKind::BridgeObjectToRefInst:
+ case SILInstructionKind::UncheckedAddrCastInst:
+ case SILInstructionKind::UnconditionalCheckedCastInst:
+ case SILInstructionKind::StrongPinInst:
// A cast is almost like a projection.
if (CGNode *OpNode = ConGraph->getNode(I->getOperand(0), this)) {
- ConGraph->setNode(I, OpNode);
+ ConGraph->setNode(cast<SingleValueInstruction>(I), OpNode);
}
break;
- case ValueKind::UncheckedRefCastAddrInst: {
+ case SILInstructionKind::UncheckedRefCastAddrInst: {
auto *URCAI = cast<UncheckedRefCastAddrInst>(I);
CGNode *SrcNode = ConGraph->getNode(URCAI->getSrc(), this);
CGNode *DestNode = ConGraph->getNode(URCAI->getDest(), this);
@@ -1532,7 +1544,7 @@
ConGraph->defer(DestNode, SrcNode);
return;
}
- case ValueKind::ReturnInst:
+ case SILInstructionKind::ReturnInst:
if (CGNode *ValueNd = ConGraph->getNode(cast<ReturnInst>(I)->getOperand(),
this)) {
ConGraph->defer(ConGraph->getReturnNode(), ValueNd);
@@ -1586,8 +1598,8 @@
}
return true;
}
- if (isProjection(V)) {
- V = dyn_cast<SILInstruction>(V)->getOperand(0);
+ if (auto SVI = isProjection(V)) {
+ V = SVI->getOperand(0);
continue;
}
return false;
@@ -1611,7 +1623,8 @@
}
// Even if the instruction does not write memory it could e.g. return the
// address of global memory. Therefore we have to define it as escaping.
- setEscapesGlobal(ConGraph, I);
+ for (auto result : I->getResults())
+ setEscapesGlobal(ConGraph, result);
}
void EscapeAnalysis::recompute(FunctionInfo *Initial) {
@@ -1744,11 +1757,14 @@
// Map the return value.
if (CGNode *RetNd = CalleeGraph->getReturnNodeOrNull()) {
+ // The non-ApplySite instructions that cause calls are to things like
+ // destructors that don't have return values.
+ assert(FAS);
ValueBase *CallerReturnVal = nullptr;
if (auto *TAI = dyn_cast<TryApplyInst>(AS)) {
CallerReturnVal = TAI->getNormalBB()->getArgument(0);
} else {
- CallerReturnVal = AS;
+ CallerReturnVal = cast<ApplyInst>(AS);
}
CGNode *CallerRetNd = CallerGraph->getNode(CallerReturnVal, this);
Callee2CallerMapping.add(RetNd, CallerRetNd);
@@ -1773,7 +1789,7 @@
return SummaryGraph->mergeFrom(Graph, Mapping);
}
-bool EscapeAnalysis::canEscapeToUsePoint(SILValue V, ValueBase *UsePoint,
+bool EscapeAnalysis::canEscapeToUsePoint(SILValue V, SILNode *UsePoint,
ConnectionGraph *ConGraph) {
assert((FullApplySite::isa(UsePoint) || isa<RefCountingInst>(UsePoint)) &&
@@ -1980,13 +1996,16 @@
}
}
-void EscapeAnalysis::handleDeleteNotification(ValueBase *I) {
- if (SILBasicBlock *Parent = I->getParentBlock()) {
+void EscapeAnalysis::handleDeleteNotification(SILNode *node) {
+ auto value = dyn_cast<ValueBase>(node);
+ if (!value) return;
+
+ if (SILBasicBlock *Parent = node->getParentBlock()) {
SILFunction *F = Parent->getParent();
if (FunctionInfo *FInfo = Function2Info.lookup(F)) {
if (FInfo->isValid()) {
- FInfo->Graph.removeFromGraph(I);
- FInfo->SummaryGraph.removeFromGraph(I);
+ FInfo->Graph.removeFromGraph(value);
+ FInfo->SummaryGraph.removeFromGraph(value);
}
}
}
diff --git a/lib/SILOptimizer/Analysis/IVAnalysis.cpp b/lib/SILOptimizer/Analysis/IVAnalysis.cpp
index 5a8dfe3..7033efe 100644
--- a/lib/SILOptimizer/Analysis/IVAnalysis.cpp
+++ b/lib/SILOptimizer/Analysis/IVAnalysis.cpp
@@ -19,8 +19,13 @@
using namespace swift::PatternMatch;
#if !defined(NDEBUG)
-static bool inSCC(ValueBase *Value, IVInfo::SCCType &SCC) {
- return std::find(SCC.begin(), SCC.end(), Value) != SCC.end();
+static bool inSCC(ValueBase *value, IVInfo::SCCType &SCC) {
+ SILNode *valueNode = value->getCanonicalSILNodeInObject();
+ for (SILNode *node : SCC) {
+ if (node->getCanonicalSILNodeInObject() == valueNode)
+ return true;
+ }
+ return false;
}
#endif
@@ -48,9 +53,11 @@
continue;
}
+ // TODO: MultiValueInstruction
+
auto *I = cast<SILInstruction>(SCC[i]);
switch (I->getKind()) {
- case ValueKind::BuiltinInst: {
+ case SILInstructionKind::BuiltinInst: {
if (FoundBuiltin)
return nullptr;
@@ -69,7 +76,7 @@
break;
}
- case ValueKind::TupleExtractInst: {
+ case SILInstructionKind::TupleExtractInst: {
assert(inSCC(cast<TupleExtractInst>(I)->getOperand(), SCC) &&
"TupleExtract operand not an induction var");
break;
@@ -93,6 +100,8 @@
if (!(IV = isInductionSequence(SCC)))
return;
- for (auto V : SCC)
- InductionVariableMap[V] = IV;
+ for (auto node : SCC) {
+ if (auto value = dyn_cast<ValueBase>(node))
+ InductionVariableMap[value] = IV;
+ }
}
diff --git a/lib/SILOptimizer/Analysis/MemoryBehavior.cpp b/lib/SILOptimizer/Analysis/MemoryBehavior.cpp
index c8ca544..c3beacf 100644
--- a/lib/SILOptimizer/Analysis/MemoryBehavior.cpp
+++ b/lib/SILOptimizer/Analysis/MemoryBehavior.cpp
@@ -322,8 +322,7 @@
MemBehavior
AliasAnalysis::computeMemoryBehavior(SILInstruction *Inst, SILValue V,
RetainObserveKind InspectionMode) {
- MemBehaviorKeyTy Key = toMemoryBehaviorKey(SILValue(Inst), V,
- InspectionMode);
+ MemBehaviorKeyTy Key = toMemoryBehaviorKey(Inst, V, InspectionMode);
// Check if we've already computed this result.
auto It = MemoryBehaviorCache.find(Key);
if (It != MemoryBehaviorCache.end()) {
@@ -333,10 +332,10 @@
// Flush the cache if the size of the cache is too large.
if (MemoryBehaviorCache.size() > MemoryBehaviorAnalysisMaxCacheSize) {
MemoryBehaviorCache.clear();
- MemoryBehaviorValueBaseToIndex.clear();
+ MemoryBehaviorNodeToIndex.clear();
- // Key is no longer valid as we cleared the MemoryBehaviorValueBaseToIndex.
- Key = toMemoryBehaviorKey(SILValue(Inst), V, InspectionMode);
+ // Key is no longer valid as we cleared the MemoryBehaviorNodeToIndex.
+ Key = toMemoryBehaviorKey(Inst, V, InspectionMode);
}
// Calculate the aliasing result and store it in the cache.
@@ -354,12 +353,15 @@
return MemoryBehaviorVisitor(this, SEA, EA, V, InspectionMode).visit(Inst);
}
-MemBehaviorKeyTy AliasAnalysis::toMemoryBehaviorKey(SILValue V1, SILValue V2,
+MemBehaviorKeyTy AliasAnalysis::toMemoryBehaviorKey(SILInstruction *V1,
+ SILValue V2,
RetainObserveKind M) {
- size_t idx1 = MemoryBehaviorValueBaseToIndex.getIndex(V1);
+ size_t idx1 =
+ MemoryBehaviorNodeToIndex.getIndex(V1->getCanonicalSILNodeInObject());
assert(idx1 != std::numeric_limits<size_t>::max() &&
"~0 index reserved for empty/tombstone keys");
- size_t idx2 = MemoryBehaviorValueBaseToIndex.getIndex(V2);
+ size_t idx2 =
+ MemoryBehaviorNodeToIndex.getIndex(V2->getCanonicalSILNodeInObject());
assert(idx2 != std::numeric_limits<size_t>::max() &&
"~0 index reserved for empty/tombstone keys");
return {idx1, idx2, M};
diff --git a/lib/SILOptimizer/Analysis/RCIdentityAnalysis.cpp b/lib/SILOptimizer/Analysis/RCIdentityAnalysis.cpp
index 4b21759..978d163 100644
--- a/lib/SILOptimizer/Analysis/RCIdentityAnalysis.cpp
+++ b/lib/SILOptimizer/Analysis/RCIdentityAnalysis.cpp
@@ -65,7 +65,7 @@
static SILValue stripRCIdentityPreservingInsts(SILValue V) {
// First strip off RC identity preserving casts.
if (isRCIdentityPreservingCast(V->getKind()))
- return cast<SILInstruction>(V)->getOperand(0);
+ return cast<SingleValueInstruction>(V)->getOperand(0);
// Then if we have a struct_extract that is extracting a non-trivial member
// from a struct with no other non-trivial members, a ref count operation on
@@ -481,14 +481,14 @@
/// means that from an RC use perspective, the object can be ignored since it is
/// up to the frontend to communicate via fix_lifetime and mark_dependence these
/// dependencies.
-static bool isNonOverlappingTrivialAccess(SILInstruction *User) {
- if (auto *TEI = dyn_cast<TupleExtractInst>(User)) {
+static bool isNonOverlappingTrivialAccess(SILValue value) {
+ if (auto *TEI = dyn_cast<TupleExtractInst>(value)) {
// If the tuple we are extracting from only has one non trivial element and
// we are not extracting from that element, this is an ARC escape.
return TEI->isTrivialEltOfOneRCIDTuple();
}
- if (auto *SEI = dyn_cast<StructExtractInst>(User)) {
+ if (auto *SEI = dyn_cast<StructExtractInst>(value)) {
// If the struct we are extracting from only has one non trivial element and
// we are not extracting from that element, this is an ARC escape.
return SEI->isTrivialFieldOfOneRCIDStruct();
@@ -524,26 +524,28 @@
if (!VisitedInsts.insert(User).second)
continue;
- // Otherwise attempt to strip off one layer of RC identical instructions
- // from User.
- SILValue StrippedRCID = stripRCIdentityPreservingInsts(User);
+ for (auto value : User->getResults()) {
+ // Otherwise attempt to strip off one layer of RC identical instructions
+ // from User.
+ SILValue StrippedRCID = stripRCIdentityPreservingInsts(value);
- // If StrippedRCID is not V, then we know that User's result is
- // conservatively not RCIdentical to V.
- if (StrippedRCID != V) {
- // If the user is extracting a trivial field of an aggregate structure
- // that does not overlap with the ref counted part of the aggregate, we
- // can ignore it.
- if (isNonOverlappingTrivialAccess(User))
+ // If StrippedRCID is not V, then we know that User's result is
+ // conservatively not RCIdentical to V.
+ if (StrippedRCID != V) {
+ // If the user is extracting a trivial field of an aggregate structure
+ // that does not overlap with the ref counted part of the aggregate, we
+ // can ignore it.
+ if (isNonOverlappingTrivialAccess(value))
+ continue;
+
+ // Otherwise, it is an RC user that our user wants.
+ Users.push_back(User);
continue;
+ }
- // Otherwise, it is an RC user that our user wants.
- Users.push_back(User);
- continue;
+ // Otherwise, add the result to our list to continue searching.
+ Worklist.push_back(value);
}
-
- // Otherwise, add all of User's uses to our list to continue searching.
- Worklist.push_back(User);
}
}
}
diff --git a/lib/SILOptimizer/Analysis/SideEffectAnalysis.cpp b/lib/SILOptimizer/Analysis/SideEffectAnalysis.cpp
index 46cee51..bda9abb 100644
--- a/lib/SILOptimizer/Analysis/SideEffectAnalysis.cpp
+++ b/lib/SILOptimizer/Analysis/SideEffectAnalysis.cpp
@@ -104,7 +104,7 @@
case ValueKind::ProjectBoxInst:
case ValueKind::UncheckedTakeEnumDataAddrInst:
case ValueKind::PointerToAddressInst:
- V = cast<SILInstruction>(V)->getOperand(0);
+ V = cast<SingleValueInstruction>(V)->getOperand(0);
break;
default:
return V;
@@ -120,7 +120,7 @@
case ValueKind::TupleExtractInst:
case ValueKind::UncheckedEnumDataInst:
case ValueKind::UncheckedTrivialBitCastInst:
- V = cast<SILInstruction>(V)->getOperand(0);
+ V = cast<SingleValueInstruction>(V)->getOperand(0);
break;
default:
return V;
@@ -285,12 +285,14 @@
int RecursionDepth) {
if (FullApplySite FAS = FullApplySite::isa(I)) {
// Is this a call to a semantics function?
- ArraySemanticsCall ASC(I);
- if (ASC && ASC.hasSelf()) {
- FunctionEffects ApplyEffects(FAS.getNumArguments());
- if (getSemanticEffects(ApplyEffects, ASC)) {
- FInfo->FE.mergeFromApply(ApplyEffects, FAS);
- return;
+ if (auto apply = dyn_cast<ApplyInst>(FAS.getInstruction())) {
+ ArraySemanticsCall ASC(apply);
+ if (ASC && ASC.hasSelf()) {
+ FunctionEffects ApplyEffects(FAS.getNumArguments());
+ if (getSemanticEffects(ApplyEffects, ASC)) {
+ FInfo->FE.mergeFromApply(ApplyEffects, FAS);
+ return;
+ }
}
}
@@ -326,43 +328,43 @@
}
// Handle some kind of instructions specially.
switch (I->getKind()) {
- case ValueKind::FixLifetimeInst:
+ case SILInstructionKind::FixLifetimeInst:
// A fix_lifetime instruction acts like a read on the operand. Retains can move after it
// but the last release can't move before it.
FInfo->FE.getEffectsOn(I->getOperand(0))->Reads = true;
return;
- case ValueKind::AllocStackInst:
- case ValueKind::DeallocStackInst:
+ case SILInstructionKind::AllocStackInst:
+ case SILInstructionKind::DeallocStackInst:
return;
- case ValueKind::StrongRetainInst:
- case ValueKind::StrongRetainUnownedInst:
- case ValueKind::RetainValueInst:
- case ValueKind::UnownedRetainInst:
+ case SILInstructionKind::StrongRetainInst:
+ case SILInstructionKind::StrongRetainUnownedInst:
+ case SILInstructionKind::RetainValueInst:
+ case SILInstructionKind::UnownedRetainInst:
FInfo->FE.getEffectsOn(I->getOperand(0))->Retains = true;
return;
- case ValueKind::StrongReleaseInst:
- case ValueKind::ReleaseValueInst:
- case ValueKind::UnownedReleaseInst:
+ case SILInstructionKind::StrongReleaseInst:
+ case SILInstructionKind::ReleaseValueInst:
+ case SILInstructionKind::UnownedReleaseInst:
FInfo->FE.getEffectsOn(I->getOperand(0))->Releases = true;
// TODO: Check the call graph to be less conservative about what
// destructors might be called.
FInfo->FE.setWorstEffects();
return;
- case ValueKind::UnconditionalCheckedCastInst:
+ case SILInstructionKind::UnconditionalCheckedCastInst:
FInfo->FE.getEffectsOn(cast<UnconditionalCheckedCastInst>(I)->getOperand())->Reads = true;
FInfo->FE.Traps = true;
return;
- case ValueKind::LoadInst:
+ case SILInstructionKind::LoadInst:
FInfo->FE.getEffectsOn(cast<LoadInst>(I)->getOperand())->Reads = true;
return;
- case ValueKind::StoreInst:
+ case SILInstructionKind::StoreInst:
FInfo->FE.getEffectsOn(cast<StoreInst>(I)->getDest())->Writes = true;
return;
- case ValueKind::CondFailInst:
+ case SILInstructionKind::CondFailInst:
FInfo->FE.Traps = true;
return;
- case ValueKind::PartialApplyInst: {
+ case SILInstructionKind::PartialApplyInst: {
FInfo->FE.AllocsObjects = true;
auto *PAI = cast<PartialApplyInst>(I);
auto Args = PAI->getArguments();
@@ -374,7 +376,7 @@
}
return;
}
- case ValueKind::BuiltinInst: {
+ case SILInstructionKind::BuiltinInst: {
auto *BInst = cast<BuiltinInst>(I);
auto &BI = BInst->getBuiltinInfo();
switch (BI.ID) {
@@ -489,10 +491,12 @@
ApplyEffects.ParamEffects.resize(FAS.getNumArguments());
// Is this a call to a semantics function?
- ArraySemanticsCall ASC(FAS.getInstruction());
- if (ASC && ASC.hasSelf()) {
- if (getSemanticEffects(ApplyEffects, ASC))
- return;
+ if (auto apply = dyn_cast<ApplyInst>(FAS.getInstruction())) {
+ ArraySemanticsCall ASC(apply);
+ if (ASC && ASC.hasSelf()) {
+ if (getSemanticEffects(ApplyEffects, ASC))
+ return;
+ }
}
if (SILFunction *SingleCallee = FAS.getReferencedFunction()) {
diff --git a/lib/SILOptimizer/Analysis/ValueTracking.cpp b/lib/SILOptimizer/Analysis/ValueTracking.cpp
index c914f5e..afe73ec 100644
--- a/lib/SILOptimizer/Analysis/ValueTracking.cpp
+++ b/lib/SILOptimizer/Analysis/ValueTracking.cpp
@@ -53,20 +53,18 @@
Processed.insert(V);
// It should be a local object.
V = getUnderlyingObject(V);
- if (auto I = dyn_cast<SILInstruction>(V)) {
- if (isa<AllocationInst>(V))
- continue;
- if (isa<StrongPinInst>(I)) {
- WorkList.push_back(I->getOperand(0));
- continue;
+ if (isa<AllocationInst>(V))
+ continue;
+ if (auto I = dyn_cast<StrongPinInst>(V)) {
+ WorkList.push_back(I->getOperand());
+ continue;
+ }
+ if (isa<StructInst>(V) || isa<TupleInst>(V) || isa<EnumInst>(V)) {
+ // A compound value is local, if all of its components are local.
+ for (auto &Op : cast<SingleValueInstruction>(V)->getAllOperands()) {
+ WorkList.push_back(Op.get());
}
- if (isa<StructInst>(I) || isa<TupleInst>(I) || isa<EnumInst>(I)) {
- // A compound value is local, if all of its components are local.
- for (auto &Op : I->getAllOperands()) {
- WorkList.push_back(Op.get());
- }
- continue;
- }
+ continue;
}
if (auto *Arg = dyn_cast<SILPHIArgument>(V)) {
@@ -108,7 +106,7 @@
case ValueKind::UncheckedTrivialBitCastInst:
// Extracting from a zero class returns a zero.
case ValueKind::StructExtractInst:
- return isZeroValue(cast<SILInstruction>(Value)->getOperand(0));
+ return isZeroValue(cast<SingleValueInstruction>(Value)->getOperand(0));
default:
break;
}
@@ -180,7 +178,7 @@
switch (Def->getKind()) {
// Bitcast of non-negative is non-negative
case ValueKind::UncheckedTrivialBitCastInst:
- Value = cast<SILInstruction>(Def)->getOperand(0);
+ Value = cast<UncheckedTrivialBitCastInst>(Def)->getOperand();
continue;
default:
break;
diff --git a/lib/SILOptimizer/IPO/CapturePromotion.cpp b/lib/SILOptimizer/IPO/CapturePromotion.cpp
index c82273e..333ae6e 100644
--- a/lib/SILOptimizer/IPO/CapturePromotion.cpp
+++ b/lib/SILOptimizer/IPO/CapturePromotion.cpp
@@ -193,7 +193,7 @@
/// one or more captures from 'inout' (by-reference) to by-value.
class ClosureCloner : public SILClonerWithScopes<ClosureCloner> {
public:
- friend class SILVisitor<ClosureCloner>;
+ friend class SILInstructionVisitor<ClosureCloner>;
friend class SILCloner<ClosureCloner>;
ClosureCloner(SILFunction *Orig, IsSerialized_t Serialized,
@@ -428,8 +428,9 @@
auto *Fn = M.createFunction(
Orig->getLinkage(), ClonedName, ClonedTy, Orig->getGenericEnvironment(),
Orig->getLocation(), Orig->isBare(), IsNotTransparent, Serialized,
- Orig->isThunk(), Orig->getClassSubclassScope(), Orig->getInlineStrategy(),
- Orig->getEffectsKind(), Orig, Orig->getDebugScope());
+ Orig->getEntryCount(), Orig->isThunk(), Orig->getClassSubclassScope(),
+ Orig->getInlineStrategy(), Orig->getEffectsKind(), Orig,
+ Orig->getDebugScope());
for (auto &Attr : Orig->getSemanticsAttrs())
Fn->addSemanticsAttr(Attr);
if (Orig->hasUnqualifiedOwnership()) {
@@ -677,11 +678,10 @@
// Loads of a struct_element_addr of an argument get replaced with a
// struct_extract of the new passed in value. The value should be borrowed
// already, so we can just extract the value.
- SILBuilderWithPostProcess<ClosureCloner, 1> B(this, LI);
- assert(B.getFunction().hasUnqualifiedOwnership() ||
+ assert(getBuilder().getFunction().hasUnqualifiedOwnership() ||
Val.getOwnershipKind().isTrivialOr(ValueOwnershipKind::Guaranteed));
- Val =
- B.emitStructExtract(LI->getLoc(), Val, SEAI->getField(), LI->getType());
+ Val = getBuilder().emitStructExtract(LI->getLoc(), Val, SEAI->getField(),
+ LI->getType());
// If we were performing a load [copy], then we need to a perform a copy
// here since when cloning, we do not eliminate the destroy on the copied
@@ -814,8 +814,8 @@
/// Visit a random value base.
///
/// These are considered to be escapes.
- bool visitValueBase(ValueBase *V) {
- DEBUG(llvm::dbgs() << " FAIL! Have unknown escaping user: " << *V);
+ bool visitSILInstruction(SILInstruction *I) {
+ DEBUG(llvm::dbgs() << " FAIL! Have unknown escaping user: " << *I);
return false;
}
@@ -850,7 +850,7 @@
}
/// Add the Operands of a transitive use instruction to the worklist.
- void addUserOperandsToWorklist(SILInstruction *I) {
+ void addUserOperandsToWorklist(SingleValueInstruction *I) {
for (auto *User : I->getUses()) {
Worklist.push_back(User);
}
@@ -1046,7 +1046,8 @@
// derived from a projection like instruction). In fact such a thing may not
// even make any sense!
if (isa<CopyValueInst>(User) || isa<MarkUninitializedInst>(User)) {
- return all_of(User->getUses(), [&State](Operand *UserOp) -> bool {
+ return all_of(cast<SingleValueInstruction>(User)->getUses(),
+ [&State](Operand *UserOp) -> bool {
return scanUsesForEscapesAndMutations(UserOp, State);
});
}
@@ -1178,7 +1179,7 @@
// Otherwise, handle the alloc_box case. If we have a mark_uninitialized on
// the box, we create the project value through that.
- SILInstruction *Box = cast<AllocBoxInst>(PartialOperand);
+ SingleValueInstruction *Box = cast<AllocBoxInst>(PartialOperand);
if (auto *Op = Box->getSingleUse()) {
if (auto *MUI = dyn_cast<MarkUninitializedInst>(Op->getUser())) {
Box = MUI;
diff --git a/lib/SILOptimizer/IPO/CapturePropagation.cpp b/lib/SILOptimizer/IPO/CapturePropagation.cpp
index 489dc85..5a0496e 100644
--- a/lib/SILOptimizer/IPO/CapturePropagation.cpp
+++ b/lib/SILOptimizer/IPO/CapturePropagation.cpp
@@ -94,7 +94,7 @@
class CapturePropagationCloner
: public TypeSubstCloner<CapturePropagationCloner> {
using SuperTy = TypeSubstCloner<CapturePropagationCloner>;
- friend class SILVisitor<CapturePropagationCloner>;
+ friend class SILInstructionVisitor<CapturePropagationCloner>;
friend class SILCloner<CapturePropagationCloner>;
SILFunction *OrigF;
@@ -141,12 +141,12 @@
void CapturePropagationCloner::cloneConstValue(SILValue Val) {
assert(IsCloningConstant && "incorrect mode");
- auto Inst = dyn_cast<SILInstruction>(Val);
- if (!Inst)
+ if (ValueMap.find(Val) != ValueMap.end())
return;
- auto II = InstructionMap.find(Inst);
- if (II != InstructionMap.end())
+ // TODO: MultiValueInstruction?
+ auto Inst = dyn_cast<SingleValueInstruction>(Val);
+ if (!Inst)
return;
if (Inst->getNumOperands() > 0) {
@@ -258,11 +258,10 @@
if (NewFTy->getGenericSignature())
GenericEnv = OrigF->getGenericEnvironment();
SILFunction *NewF = OrigF->getModule().createFunction(
- SILLinkage::Shared, Name, NewFTy,
- GenericEnv, OrigF->getLocation(), OrigF->isBare(),
- OrigF->isTransparent(), Serialized, OrigF->isThunk(),
- OrigF->getClassSubclassScope(), OrigF->getInlineStrategy(),
- OrigF->getEffectsKind(),
+ SILLinkage::Shared, Name, NewFTy, GenericEnv, OrigF->getLocation(),
+ OrigF->isBare(), OrigF->isTransparent(), Serialized,
+ OrigF->getEntryCount(), OrigF->isThunk(), OrigF->getClassSubclassScope(),
+ OrigF->getInlineStrategy(), OrigF->getEffectsKind(),
/*InsertBefore*/ OrigF, OrigF->getDebugScope());
if (OrigF->hasUnqualifiedOwnership()) {
NewF->setUnqualifiedOwnership();
@@ -387,7 +386,7 @@
return nullptr;
}
assert(isa<ApplyInst>(&I) && "unknown FullApplySite instruction");
- RetValue = &I;
+ RetValue = cast<ApplyInst>(&I);
continue;
}
if (auto *RI = dyn_cast<ReturnInst>(&I)) {
diff --git a/lib/SILOptimizer/IPO/ClosureSpecializer.cpp b/lib/SILOptimizer/IPO/ClosureSpecializer.cpp
index 802c014..32e151c 100644
--- a/lib/SILOptimizer/IPO/ClosureSpecializer.cpp
+++ b/lib/SILOptimizer/IPO/ClosureSpecializer.cpp
@@ -112,7 +112,7 @@
class ClosureSpecCloner : public SILClonerWithScopes<ClosureSpecCloner> {
public:
using SuperTy = SILClonerWithScopes<ClosureSpecCloner>;
- friend class SILVisitor<ClosureSpecCloner>;
+ friend class SILInstructionVisitor<ClosureSpecCloner>;
friend class SILCloner<ClosureSpecCloner>;
ClosureSpecCloner(const CallSiteDescriptor &CallSiteDesc,
@@ -187,7 +187,7 @@
SILParameterInfo getClosureParameterInfo() const { return ClosureParamInfo; }
- SILInstruction *
+ SingleValueInstruction *
createNewClosure(SILBuilder &B, SILValue V,
llvm::SmallVectorImpl<SILValue> &Args) const {
if (isa<PartialApplyInst>(getClosure()))
@@ -219,7 +219,7 @@
return OperandValueArrayRef(ArrayRef<Operand>());
}
- inline SILInstruction *getClosure() const;
+ inline SingleValueInstruction *getClosure() const;
unsigned getNumArguments() const {
if (auto *PAI = dyn_cast<PartialApplyInst>(getClosure()))
@@ -255,18 +255,18 @@
namespace {
struct ClosureInfo {
- SILInstruction *Closure;
+ SingleValueInstruction *Closure;
ValueLifetimeAnalysis::Frontier LifetimeFrontier;
llvm::SmallVector<CallSiteDescriptor, 8> CallSites;
- ClosureInfo(SILInstruction *Closure): Closure(Closure) {}
+ ClosureInfo(SingleValueInstruction *Closure): Closure(Closure) {}
ClosureInfo(ClosureInfo &&) =default;
ClosureInfo &operator=(ClosureInfo &&) =default;
};
} // end anonymous namespace
-SILInstruction *CallSiteDescriptor::getClosure() const {
+SingleValueInstruction *CallSiteDescriptor::getClosure() const {
return CInfo->Closure;
}
@@ -281,7 +281,7 @@
static void rewriteApplyInst(const CallSiteDescriptor &CSDesc,
SILFunction *NewF) {
FullApplySite AI = CSDesc.getApplyInst();
- SILInstruction *Closure = CSDesc.getClosure();
+ SingleValueInstruction *Closure = CSDesc.getClosure();
SILBuilderWithScope Builder(Closure);
FunctionRefInst *FRI = Builder.createFunctionRef(AI.getLoc(), NewF);
@@ -403,19 +403,21 @@
Builder.setInsertionPoint(AI.getInstruction());
}
} else {
- NewAI = Builder.createApply(AI.getLoc(), FRI,
- SubstitutionList(),
- NewArgs, cast<ApplyInst>(AI)->isNonThrowing());
+ auto oldApply = cast<ApplyInst>(AI);
+ auto newApply = Builder.createApply(oldApply->getLoc(), FRI,
+ SubstitutionList(),
+ NewArgs, oldApply->isNonThrowing());
// If we passed in the original closure as @owned, then insert a release
// right after NewAI. This is to balance the +1 from being an @owned
// argument to AI.
if (CSDesc.isClosureConsumed() && CSDesc.closureHasRefSemanticContext())
- Builder.createReleaseValue(Closure->getLoc(), Closure, Builder.getDefaultAtomicity());
- }
+ Builder.createReleaseValue(Closure->getLoc(), Closure,
+ Builder.getDefaultAtomicity());
- // Replace all uses of the old apply with the new apply.
- if (isa<ApplyInst>(AI))
- AI.getInstruction()->replaceAllUsesWith(NewAI.getInstruction());
+ // Replace all uses of the old apply with the new apply.
+ oldApply->replaceAllUsesWith(newApply);
+ }
+
// Erase the old apply.
AI.getInstruction()->eraseFromParent();
@@ -614,10 +616,10 @@
// and not the original linkage.
// Otherwise the new function could have an external linkage (in case the
// original function was de-serialized) and would not be code-gen'd.
- getSpecializedLinkage(ClosureUser, ClosureUser->getLinkage()),
- ClonedName, ClonedTy,
- ClosureUser->getGenericEnvironment(), ClosureUser->getLocation(),
- IsBare, ClosureUser->isTransparent(), CallSiteDesc.isSerialized(),
+ getSpecializedLinkage(ClosureUser, ClosureUser->getLinkage()), ClonedName,
+ ClonedTy, ClosureUser->getGenericEnvironment(),
+ ClosureUser->getLocation(), IsBare, ClosureUser->isTransparent(),
+ CallSiteDesc.isSerialized(), ClosureUser->getEntryCount(),
ClosureUser->isThunk(), ClosureUser->getClassSubclassScope(),
ClosureUser->getInlineStrategy(), ClosureUser->getEffectsKind(),
ClosureUser, ClosureUser->getDebugScope());
@@ -741,7 +743,7 @@
llvm::SmallVectorImpl<ClosureInfo*> &ClosureCandidates,
llvm::DenseSet<FullApplySite> &MultipleClosureAI);
bool specialize(SILFunction *Caller,
- std::vector<SILInstruction *> &PropagatedClosures);
+ std::vector<SingleValueInstruction *> &PropagatedClosures);
public:
SILClosureSpecializerTransform() {}
@@ -762,7 +764,7 @@
if (F->isExternalDeclaration())
return;
- std::vector<SILInstruction *> PropagatedClosures;
+ std::vector<SingleValueInstruction *> PropagatedClosures;
if (!specialize(F, PropagatedClosures))
return;
@@ -774,7 +776,7 @@
// specialized all of their uses.
DEBUG(llvm::dbgs() << "Trying to remove dead closures!\n");
sortUnique(PropagatedClosures);
- for (SILInstruction *Closure : PropagatedClosures) {
+ for (auto *Closure : PropagatedClosures) {
DEBUG(llvm::dbgs() << " Visiting: " << *Closure);
if (!tryDeleteDeadClosure(Closure)) {
DEBUG(llvm::dbgs() << " Failed to delete closure!\n");
@@ -809,11 +811,12 @@
// If II is not a closure that we support specializing, skip it...
if (!isSupportedClosure(&II))
continue;
+ auto ClosureInst = cast<SingleValueInstruction>(&II);
ClosureInfo *CInfo = nullptr;
// Go through all uses of our closure.
- for (auto *Use : II.getUses()) {
+ for (auto *Use : ClosureInst->getUses()) {
// If this use is not an apply inst or an apply inst with
// substitutions, there is nothing interesting for us to do, so
// continue...
@@ -856,7 +859,7 @@
// corresponding to our partial apply.
Optional<unsigned> ClosureIndex;
for (unsigned i = 0, e = AI.getNumArguments(); i != e; ++i) {
- if (AI.getArgument(i) != SILValue(&II))
+ if (AI.getArgument(i) != ClosureInst)
continue;
ClosureIndex = i;
DEBUG(llvm::dbgs() << " Found callsite with closure argument at "
@@ -902,7 +905,7 @@
// don't need to be released.
llvm::TinyPtrVector<SILBasicBlock *> NonFailureExitBBs;
if (ClosureParamInfo.isGuaranteed() &&
- !isa<ThinToThickFunctionInst>(&II) &&
+ !isa<ThinToThickFunctionInst>(ClosureInst) &&
!findAllNonFailureExitBBs(ApplyCallee, NonFailureExitBBs)) {
continue;
}
@@ -910,7 +913,7 @@
// Compute the final release points of the closure. We will insert
// release of the captured arguments here.
if (!CInfo) {
- CInfo = new ClosureInfo(&II);
+ CInfo = new ClosureInfo(ClosureInst);
ValueLifetimeAnalysis VLA(CInfo->Closure);
VLA.computeFrontier(CInfo->LifetimeFrontier,
ValueLifetimeAnalysis::AllowToModifyCFG);
@@ -929,7 +932,7 @@
}
bool SILClosureSpecializerTransform::specialize(SILFunction *Caller,
- std::vector<SILInstruction *> &PropagatedClosures) {
+ std::vector<SingleValueInstruction *> &PropagatedClosures) {
DEBUG(llvm::dbgs() << "Optimizing callsites that take closure argument in "
<< Caller->getName() << '\n');
diff --git a/lib/SILOptimizer/IPO/EagerSpecializer.cpp b/lib/SILOptimizer/IPO/EagerSpecializer.cpp
index 9df86d7..e569dd7 100644
--- a/lib/SILOptimizer/IPO/EagerSpecializer.cpp
+++ b/lib/SILOptimizer/IPO/EagerSpecializer.cpp
@@ -100,11 +100,12 @@
if (NewRetVal->getType().isVoid()) {
// Canonicalize Void return type into something that isTrivialReturnBlock
// expects.
- auto *TupleI = cast<SILInstruction>(RetInst->getOperand(0));
- if (TupleI->hasOneUse()) {
+ auto *TupleI = dyn_cast<TupleInst>(RetInst->getOperand(0));
+ if (TupleI && TupleI->hasOneUse()) {
TupleI->moveBefore(RetInst);
} else {
- TupleI = TupleI->clone(RetInst);
+ Builder.setInsertionPoint(RetInst);
+ TupleI = Builder.createTuple(RetInst->getLoc(), {});
RetInst->setOperand(0, TupleI);
}
MergedBB = RetBB->split(TupleI->getIterator());
diff --git a/lib/SILOptimizer/IPO/GlobalOpt.cpp b/lib/SILOptimizer/IPO/GlobalOpt.cpp
index 09aca85..d55d583 100644
--- a/lib/SILOptimizer/IPO/GlobalOpt.cpp
+++ b/lib/SILOptimizer/IPO/GlobalOpt.cpp
@@ -127,14 +127,14 @@
SILFunction *AddrF,
SILFunction *InitF,
SILGlobalVariable *SILG,
- SILInstruction *InitVal,
+ SingleValueInstruction *InitVal,
GlobalInitCalls &Calls);
};
/// Helper class to copy only a set of SIL instructions providing in the
/// constructor.
class InstructionsCloner : public SILClonerWithScopes<InstructionsCloner> {
- friend class SILVisitor<InstructionsCloner>;
+ friend class SILInstructionVisitor<InstructionsCloner>;
friend class SILCloner<InstructionsCloner>;
ArrayRef<SILInstruction *> Insns;
@@ -162,7 +162,10 @@
void postProcess(SILInstruction *Orig, SILInstruction *Cloned) {
DestBB->push_back(Cloned);
SILClonerWithScopes<InstructionsCloner>::postProcess(Orig, Cloned);
- AvailVals.push_back(std::make_pair(Orig, Cloned));
+ auto origResults = Orig->getResults(), clonedResults = Cloned->getResults();
+ assert(origResults.size() == clonedResults.size());
+ for (auto i : indices(origResults))
+ AvailVals.push_back(std::make_pair(origResults[i], clonedResults[i]));
}
// Clone all instructions from Insns into DestBB
@@ -239,7 +242,7 @@
SmallVector<SILInstruction *, 8> ReverseInsns;
SmallVector<SILInstruction *, 8> Insns;
ReverseInsns.push_back(Store);
- ReverseInsns.push_back(dyn_cast<SILInstruction>(Store->getDest()));
+ ReverseInsns.push_back(dyn_cast<SingleValueInstruction>(Store->getDest()));
if (!analyzeStaticInitializer(V, ReverseInsns))
return nullptr;
@@ -599,33 +602,30 @@
/// a chain of struct_element_addr followed by a load.
/// The sequence is traversed starting from the load
/// instruction.
-static SILInstruction *convertLoadSequence(SILInstruction *I,
- SILInstruction *Value,
- SILBuilder &B) {
+static SILValue convertLoadSequence(SILValue oldSequence,
+ SILValue newRootValue,
+ SILBuilder &B) {
- if (isa<GlobalAddrInst>(I))
- return Value;
+ if (isa<GlobalAddrInst>(oldSequence))
+ return newRootValue;
- if (auto *LI = dyn_cast<LoadInst>(I)) {
- Value =
- convertLoadSequence(cast<SILInstruction>(LI->getOperand()), Value, B);
- LI->replaceAllUsesWith(Value);
- return Value;
+ if (auto *LI = dyn_cast<LoadInst>(oldSequence)) {
+ auto newValue = convertLoadSequence(LI->getOperand(), newRootValue, B);
+ LI->replaceAllUsesWith(newValue);
+ return newValue;
}
// It is a series of struct_element_addr followed by load.
- if (auto *SEAI = dyn_cast<StructElementAddrInst>(I)) {
- Value =
- convertLoadSequence(cast<SILInstruction>(SEAI->getOperand()), Value, B);
- auto *SEI = B.createStructExtract(SEAI->getLoc(), Value, SEAI->getField());
- return SEI;
+ if (auto *SEAI = dyn_cast<StructElementAddrInst>(oldSequence)) {
+ auto newValue = convertLoadSequence(SEAI->getOperand(), newRootValue, B);
+ newValue = B.createStructExtract(SEAI->getLoc(), newValue, SEAI->getField());
+ return newValue;
}
- if (auto *TEAI = dyn_cast<TupleElementAddrInst>(I)) {
- Value =
- convertLoadSequence(cast<SILInstruction>(TEAI->getOperand()), Value, B);
- auto *TEI = B.createTupleExtract(TEAI->getLoc(), Value, TEAI->getFieldNo());
- return TEI;
+ if (auto *TEAI = dyn_cast<TupleElementAddrInst>(oldSequence)) {
+ auto newValue = convertLoadSequence(TEAI->getOperand(), newRootValue, B);
+ newValue = B.createTupleExtract(TEAI->getLoc(), newValue, TEAI->getFieldNo());
+ return newValue;
}
llvm_unreachable("Unknown instruction sequence for reading from a global");
@@ -633,7 +633,7 @@
}
static SILGlobalVariable *getVariableOfStaticInitializer(SILFunction *InitFunc,
- SILInstruction *&InitVal) {
+ SingleValueInstruction *&InitVal) {
InitVal = nullptr;
SILGlobalVariable *GVar = nullptr;
// We only handle a single SILBasicBlock for now.
@@ -658,12 +658,13 @@
if (HasStore || SI->getDest() != SGA)
return nullptr;
HasStore = true;
- InitVal = dyn_cast<SILInstruction>(SI->getSrc());
+ SILValue value = SI->getSrc();
// We only handle StructInst and TupleInst being stored to a
// global variable for now.
- if (!isa<StructInst>(InitVal) && !isa<TupleInst>(InitVal))
+ if (!isa<StructInst>(value) && !isa<TupleInst>(value))
return nullptr;
+ InitVal = cast<SingleValueInstruction>(value);
} else if (!SILGlobalVariable::isValidStaticInitializerInst(&I,
I.getModule())) {
return nullptr;
@@ -679,7 +680,7 @@
/// Utility class for cloning init values into the static initializer of a
/// SILGlobalVariable.
class StaticInitCloner : public SILCloner<StaticInitCloner> {
- friend class SILVisitor<StaticInitCloner>;
+ friend class SILInstructionVisitor<StaticInitCloner>;
friend class SILCloner<StaticInitCloner>;
/// The number of not yet cloned operands for each instruction.
@@ -702,11 +703,11 @@
/// SILGlobalVariable.
///
/// \return Returns the cloned instruction in the SILGlobalVariable.
- SILInstruction *clone(SILInstruction *InitVal);
+ SingleValueInstruction *clone(SingleValueInstruction *InitVal);
/// Convenience function to clone a single \p InitVal.
static void appendToInitializer(SILGlobalVariable *GVar,
- SILInstruction *InitVal) {
+ SingleValueInstruction *InitVal) {
StaticInitCloner Cloner(GVar);
Cloner.add(InitVal);
Cloner.clone(InitVal);
@@ -732,12 +733,13 @@
} else {
// Recursively add all operands.
for (const Operand &Op : Ops) {
- add(cast<SILInstruction>(Op.get()));
+ add(cast<SingleValueInstruction>(Op.get()));
}
}
}
-SILInstruction *StaticInitCloner::clone(SILInstruction *InitVal) {
+SingleValueInstruction *
+StaticInitCloner::clone(SingleValueInstruction *InitVal) {
assert(NumOpsToClone.count(InitVal) != 0 && "InitVal was not added");
// Find the right order to clone: all operands of an instruction must be
// cloned before the instruction itself.
@@ -748,15 +750,17 @@
visit(I);
// Check if users of I can now be cloned.
- for (Operand *Use : I->getUses()) {
- SILInstruction *User = Use->getUser();
- if (NumOpsToClone.count(User) != 0 && --NumOpsToClone[User] == 0)
- ReadyToClone.push_back(User);
+ for (SILValue result : I->getResults()) {
+ for (Operand *Use : result->getUses()) {
+ SILInstruction *User = Use->getUser();
+ if (NumOpsToClone.count(User) != 0 && --NumOpsToClone[User] == 0)
+ ReadyToClone.push_back(User);
+ }
}
}
- assert(InstructionMap.count(InitVal) != 0 &&
+ assert(ValueMap.count(InitVal) != 0 &&
"Could not schedule all instructions for cloning");
- return InstructionMap[InitVal];
+ return cast<SingleValueInstruction>(ValueMap[InitVal]);
}
} // end anonymous namespace
@@ -765,7 +769,7 @@
void SILGlobalOpt::
replaceLoadsByKnownValue(BuiltinInst *CallToOnce, SILFunction *AddrF,
SILFunction *InitF, SILGlobalVariable *SILG,
- SILInstruction *InitVal,
+ SingleValueInstruction *InitVal,
GlobalInitCalls &Calls) {
assert(isAssignedOnlyOnceInInitializer(SILG) &&
"The value of the initializer should be known at compile-time");
@@ -850,7 +854,7 @@
return;
// If the globalinit_func is trivial, continue; otherwise bail.
- SILInstruction *InitVal;
+ SingleValueInstruction *InitVal;
SILGlobalVariable *SILG = getVariableOfStaticInitializer(InitF, InitVal);
if (!SILG)
return;
@@ -884,7 +888,7 @@
return nullptr;
// If the globalinit_func is trivial, continue; otherwise bail.
- SILInstruction *dummyInitVal;
+ SingleValueInstruction *dummyInitVal;
auto *SILG = getVariableOfStaticInitializer(InitF, dummyInitVal);
if (!SILG || !SILG->isDefinition())
return nullptr;
@@ -929,7 +933,7 @@
/// Check if instruction I is a load from instruction V or
/// or a struct_element_addr from instruction V.
/// returns instruction I if this condition holds, or nullptr otherwise.
-static LoadInst *getValidLoad(SILInstruction *I, SILInstruction *V) {
+static LoadInst *getValidLoad(SILInstruction *I, SILValue V) {
if (auto *LI = dyn_cast<LoadInst>(I)) {
if (LI->getOperand() == V)
return LI;
@@ -1010,9 +1014,9 @@
}
/// Check if \p V is a valid instruction for a static initializer, including
-/// all it's operands.
+/// all its operands.
static bool isValidInitVal(SILValue V) {
- if (SILInstruction *I = dyn_cast<SILInstruction>(V)) {
+ if (auto I = dyn_cast<SingleValueInstruction>(V)) {
if (!SILGlobalVariable::isValidStaticInitializerInst(I, I->getModule()))
return false;
@@ -1031,7 +1035,7 @@
return false;
// If any of the operands is not empty, the whole struct/tuple is not empty.
- for (Operand &Op : cast<SILInstruction>(V)->getAllOperands()) {
+ for (Operand &Op : cast<SingleValueInstruction>(V)->getAllOperands()) {
if (!isEmptyInitVal(Op.get()))
return false;
}
@@ -1047,73 +1051,74 @@
bool SILGlobalOpt::isValidUseOfObject(SILInstruction *I, bool isCOWObject,
ApplyInst **FindStringCall) {
switch (I->getKind()) {
- case ValueKind::DebugValueAddrInst:
- case ValueKind::DebugValueInst:
- case ValueKind::LoadInst:
- case ValueKind::DeallocRefInst:
- case ValueKind::StrongRetainInst:
- case ValueKind::StrongReleaseInst:
- return true;
+ case SILInstructionKind::DebugValueAddrInst:
+ case SILInstructionKind::DebugValueInst:
+ case SILInstructionKind::LoadInst:
+ case SILInstructionKind::DeallocRefInst:
+ case SILInstructionKind::StrongRetainInst:
+ case SILInstructionKind::StrongReleaseInst:
+ return true;
- case ValueKind::ReturnInst:
- case ValueKind::TryApplyInst:
- case ValueKind::PartialApplyInst:
- case ValueKind::StoreInst:
- /// We don't have a representation for COW objects in SIL, so we do some
- /// ad-hoc testing: We can ignore uses of a COW object if any use after
- /// this will do a uniqueness checking before the object is modified.
- return isCOWObject;
+ case SILInstructionKind::ReturnInst:
+ case SILInstructionKind::TryApplyInst:
+ case SILInstructionKind::PartialApplyInst:
+ case SILInstructionKind::StoreInst:
+ /// We don't have a representation for COW objects in SIL, so we do some
+ /// ad-hoc testing: We can ignore uses of a COW object if any use after
+ /// this will do a uniqueness checking before the object is modified.
+ return isCOWObject;
- case ValueKind::ApplyInst:
- if (!isCOWObject)
- return false;
- // There should only be a single call to findStringSwitchCase. But even
- // if there are multiple calls, it's not problem - we'll just optimize the
- // last one we find.
- if (cast<ApplyInst>(I)->hasSemantics("findStringSwitchCase"))
- *FindStringCall = cast<ApplyInst>(I);
- return true;
-
- case ValueKind::StructInst:
- if (isCOWType(I->getType())) {
- // The object is wrapped into a COW container.
- isCOWObject = true;
- }
- break;
-
- case ValueKind::UncheckedRefCastInst:
- case ValueKind::StructElementAddrInst:
- case ValueKind::AddressToPointerInst:
- assert(!isCOWObject && "instruction cannot have a COW object as operand");
- break;
-
- case ValueKind::TupleInst:
- case ValueKind::TupleExtractInst:
- case ValueKind::EnumInst:
- break;
-
- case ValueKind::StructExtractInst:
- // To be on the safe side we don't consider the object as COW if it is
- // extracted again from the COW container: the uniqueness check may be
- // optimized away in this case.
- isCOWObject = false;
- break;
-
- case ValueKind::BuiltinInst: {
- // Handle the case for comparing addresses. This occurs when the Array
- // comparison function is inlined.
- auto *BI = cast<BuiltinInst>(I);
- BuiltinValueKind K = BI->getBuiltinInfo().ID;
- if (K == BuiltinValueKind::ICMP_EQ || K == BuiltinValueKind::ICMP_NE)
- return true;
+ case SILInstructionKind::ApplyInst:
+ if (!isCOWObject)
return false;
+ // There should only be a single call to findStringSwitchCase. But even
+ // if there are multiple calls, it's not problem - we'll just optimize the
+ // last one we find.
+ if (cast<ApplyInst>(I)->hasSemantics("findStringSwitchCase"))
+ *FindStringCall = cast<ApplyInst>(I);
+ return true;
+
+ case SILInstructionKind::StructInst:
+ if (isCOWType(cast<StructInst>(I)->getType())) {
+ // The object is wrapped into a COW container.
+ isCOWObject = true;
}
+ break;
- default:
- return false;
+ case SILInstructionKind::UncheckedRefCastInst:
+ case SILInstructionKind::StructElementAddrInst:
+ case SILInstructionKind::AddressToPointerInst:
+ assert(!isCOWObject && "instruction cannot have a COW object as operand");
+ break;
+
+ case SILInstructionKind::TupleInst:
+ case SILInstructionKind::TupleExtractInst:
+ case SILInstructionKind::EnumInst:
+ break;
+
+ case SILInstructionKind::StructExtractInst:
+ // To be on the safe side we don't consider the object as COW if it is
+ // extracted again from the COW container: the uniqueness check may be
+ // optimized away in this case.
+ isCOWObject = false;
+ break;
+
+ case SILInstructionKind::BuiltinInst: {
+ // Handle the case for comparing addresses. This occurs when the Array
+ // comparison function is inlined.
+ auto *BI = cast<BuiltinInst>(I);
+ BuiltinValueKind K = BI->getBuiltinInfo().ID;
+ if (K == BuiltinValueKind::ICMP_EQ || K == BuiltinValueKind::ICMP_NE)
+ return true;
+ return false;
}
- for (Operand *Use : getNonDebugUses(I)) {
+ default:
+ return false;
+ }
+
+ auto SVI = cast<SingleValueInstruction>(I);
+ for (Operand *Use : getNonDebugUses(SVI)) {
if (!isValidUseOfObject(Use->getUser(), isCOWObject, FindStringCall))
return false;
}
@@ -1257,7 +1262,7 @@
return;
// Is there a store for all tail allocated elements?
- for (SILValue V : TailStores) {
+ for (auto V : TailStores) {
if (!V)
return;
}
@@ -1278,10 +1283,10 @@
StaticInitCloner Cloner(Glob);
for (VarDecl *Field : Fields) {
StoreInst *MemberStore = MemberStores[Field];
- Cloner.add(cast<SILInstruction>(MemberStore->getSrc()));
+ Cloner.add(cast<SingleValueInstruction>(MemberStore->getSrc()));
}
for (StoreInst *TailStore : TailStores) {
- Cloner.add(cast<SILInstruction>(TailStore->getSrc()));
+ Cloner.add(cast<SingleValueInstruction>(TailStore->getSrc()));
}
// Create the class property initializers
@@ -1290,14 +1295,14 @@
StoreInst *MemberStore = MemberStores[Field];
assert(MemberStore);
ObjectArgs.push_back(Cloner.clone(
- cast<SILInstruction>(MemberStore->getSrc())));
+ cast<SingleValueInstruction>(MemberStore->getSrc())));
MemberStore->eraseFromParent();
}
// Create the initializers for the tail elements.
unsigned NumBaseElements = ObjectArgs.size();
for (StoreInst *TailStore : TailStores) {
ObjectArgs.push_back(Cloner.clone(
- cast<SILInstruction>(TailStore->getSrc())));
+ cast<SingleValueInstruction>(TailStore->getSrc())));
TailStore->eraseFromParent();
}
// Create the initializer for the object itself.
@@ -1313,7 +1318,7 @@
Operand *Use = *ARI->use_begin();
SILInstruction *User = Use->getUser();
switch (User->getKind()) {
- case ValueKind::DeallocRefInst:
+ case SILInstructionKind::DeallocRefInst:
User->eraseFromParent();
break;
default:
diff --git a/lib/SILOptimizer/IPO/GlobalPropertyOpt.cpp b/lib/SILOptimizer/IPO/GlobalPropertyOpt.cpp
index b455452..6b86ad1 100644
--- a/lib/SILOptimizer/IPO/GlobalPropertyOpt.cpp
+++ b/lib/SILOptimizer/IPO/GlobalPropertyOpt.cpp
@@ -72,7 +72,7 @@
return os << "field " << entry.Field->getName() << '\n';
if (!entry.Value)
return os << "unknown-address\n";
- if (auto *Inst = dyn_cast<SILInstruction>(entry.Value))
+ if (auto *Inst = entry.Value->getDefiningInstruction())
return os << Inst->getFunction()->getName() << ": " << entry.Value;
if (auto *Arg = dyn_cast<SILArgument>(entry.Value))
return os << Arg->getFunction()->getName() << ": " << entry.Value;
@@ -260,13 +260,14 @@
// We don't handle these instructions if we see them in store addresses.
// So going through them lets stores be as bad as if the address would
// escape.
- if (canAddressEscape(User, false))
+ auto value = cast<SingleValueInstruction>(User);
+ if (canAddressEscape(value, false))
return true;
continue;
}
- if (isa<MarkDependenceInst>(User)) {
+ if (auto markDependence = dyn_cast<MarkDependenceInst>(User)) {
unsigned opNum = UI->getOperandNumber();
- if (opNum == 0 && canAddressEscape(User, acceptStore))
+ if (opNum == 0 && canAddressEscape(markDependence, acceptStore))
return true;
continue;
}
@@ -321,11 +322,12 @@
return;
}
} else if (isa<RefElementAddrInst>(Inst) || isa<StructElementAddrInst>(Inst)) {
- if (isArrayAddressType(Inst->getType())) {
+ auto projection = cast<SingleValueInstruction>(Inst);
+ if (isArrayAddressType(projection->getType())) {
// If the address of an array-field escapes, we give up for that field.
- if (canAddressEscape(Inst, true)) {
- setAddressEscapes(getAddrEntry(Inst));
- DEBUG(llvm::dbgs() << " field address escapes: " << *Inst);
+ if (canAddressEscape(projection, true)) {
+ setAddressEscapes(getAddrEntry(projection));
+ DEBUG(llvm::dbgs() << " field address escapes: " << *projection);
}
return;
}
@@ -375,10 +377,12 @@
// For everything else which we didn't handle above: we set the property of
// the instruction value to false.
- if (SILType Type = Inst->getType()) {
+ for (auto result : Inst->getResults()) {
+ SILType Type = result->getType();
if (isArrayType(Type) || isTupleWithArray(Type.getSwiftRValueType())) {
- DEBUG(llvm::dbgs() << " value could be non-native array: " << *Inst);
- setNotNative(getValueEntry(Inst));
+ DEBUG(llvm::dbgs() << " value could be non-native array: "
+ << *result);
+ setNotNative(getValueEntry(result));
}
}
}
diff --git a/lib/SILOptimizer/IPO/LetPropertiesOpts.cpp b/lib/SILOptimizer/IPO/LetPropertiesOpts.cpp
index b9d026d..775fbcb 100644
--- a/lib/SILOptimizer/IPO/LetPropertiesOpts.cpp
+++ b/lib/SILOptimizer/IPO/LetPropertiesOpts.cpp
@@ -32,6 +32,18 @@
using namespace swift;
namespace {
+
+using InstructionList = SmallVector<SILInstruction *, 8>;
+
+struct InitSequence {
+ InstructionList Instructions;
+ SILValue Result;
+
+ bool isValid() const {
+ return (bool) Result;
+ }
+};
+
/// Promote values of non-static let properties initialized by means
/// of constant values of simple types into their uses.
///
@@ -44,15 +56,14 @@
class LetPropertiesOpt {
SILModule *Module;
- typedef SmallVector<SILInstruction *, 8> Instructions;
typedef SmallVector<VarDecl *, 4> Properties;
llvm::SetVector<SILFunction *> ChangedFunctions;
// Map each let property to a set of instructions accessing it.
- llvm::MapVector<VarDecl *, Instructions> AccessMap;
+ llvm::MapVector<VarDecl *, InstructionList> AccessMap;
// Map each let property to the instruction sequence which initializes it.
- llvm::MapVector<VarDecl *, Instructions> InitMap;
+ llvm::MapVector<VarDecl *, InitSequence> InitMap;
// Properties in this set should not be processed by this pass
// anymore.
llvm::SmallPtrSet<VarDecl *, 16> SkipProcessing;
@@ -76,51 +87,44 @@
bool isConstantLetProperty(VarDecl *Property);
void collectPropertyAccess(SILInstruction *I, VarDecl *Property, bool NonRemovable);
void collectStructPropertiesAccess(StructInst *SI, bool NonRemovable);
- void optimizeLetPropertyAccess(VarDecl *SILG,
- SmallVectorImpl<SILInstruction *> &Init);
+ void optimizeLetPropertyAccess(VarDecl *SILG, const InitSequence &Init);
bool analyzeInitValue(SILInstruction *I, VarDecl *Prop);
};
/// Helper class to copy only a set of SIL instructions providing in the
/// constructor.
-class InstructionsCloner : public SILClonerWithScopes<InstructionsCloner> {
- friend class SILVisitor<InstructionsCloner>;
- friend class SILCloner<InstructionsCloner>;
+class InitSequenceCloner : public SILClonerWithScopes<InitSequenceCloner> {
+ friend class SILInstructionVisitor<InitSequenceCloner>;
+ friend class SILCloner<InitSequenceCloner>;
- ArrayRef<SILInstruction *> Insns;
+ const InitSequence &Init;
+ SILInstruction *DestIP;
- protected:
- SILBasicBlock *FromBB;
- SILInstruction *Dest;
-
- public:
- // A map of old to new available values.
- SmallVector<std::pair<ValueBase *, SILValue>, 16> AvailVals;
-
- InstructionsCloner(SILFunction &F, ArrayRef<SILInstruction *> Insns,
- SILInstruction *Dest = nullptr)
- : SILClonerWithScopes(Dest ? *Dest->getFunction() : F), Insns(Insns),
- FromBB(nullptr), Dest(Dest) {}
+public:
+ InitSequenceCloner(const InitSequence &init, SILInstruction *destIP)
+ : SILClonerWithScopes(*destIP->getFunction()), Init(init), DestIP(destIP) {}
void process(SILInstruction *I) { visit(I); }
SILBasicBlock *remapBasicBlock(SILBasicBlock *BB) { return BB; }
SILValue remapValue(SILValue Value) {
- return SILCloner<InstructionsCloner>::remapValue(Value);
+ return SILCloner<InitSequenceCloner>::remapValue(Value);
}
- void postProcess(SILInstruction *Orig, SILInstruction *Cloned) {
- Dest->getParent()->push_front(Cloned);
- Cloned->moveBefore(Dest);
- SILClonerWithScopes<InstructionsCloner>::postProcess(Orig, Cloned);
- AvailVals.push_back(std::make_pair(Orig, Cloned));
+ void postProcess(SILInstruction *orig, SILInstruction *cloned) {
+ DestIP->getParent()->push_front(cloned);
+ cloned->moveBefore(DestIP);
+ SILClonerWithScopes<InitSequenceCloner>::postProcess(orig, cloned);
}
- // Clone all instructions from Insns into DestBB
- void clone() {
- for (auto I : Insns)
+ /// Clone all the instructions from Insns into the destination function,
+ /// immediately before the destination block, and return the value of
+ /// the result.
+ SILValue clone() {
+ for (auto I : Init.Instructions)
process(I);
+ return remapValue(Init.Result);
}
};
@@ -141,14 +145,12 @@
/// to have a constant value. Replace all loads from the
/// property by its constant value.
void LetPropertiesOpt::optimizeLetPropertyAccess(VarDecl *Property,
- SmallVectorImpl<SILInstruction *> &Init) {
+ const InitSequence &init) {
+ assert(init.isValid());
if (SkipProcessing.count(Property))
return;
- if (Init.empty())
- return;
-
auto *Ty = dyn_cast<NominalTypeDecl>(Property->getDeclContext());
if (SkipTypeProcessing.count(Ty))
return;
@@ -191,55 +193,56 @@
for (auto Load: Loads) {
SILFunction *F = Load->getFunction();
+ // A helper function to copy the initializer into the target function
+ // at the target insertion point.
+ auto cloneInitAt = [&](SILInstruction *insertionPoint) -> SILValue {
+ InitSequenceCloner cloner(init, insertionPoint);
+ return cloner.clone();
+ };
+
// Look for any instructions accessing let properties.
- if (isa<RefElementAddrInst>(Load)) {
+ if (auto proj = dyn_cast<RefElementAddrInst>(Load)) {
// Copy the initializer into the function
// Replace the access to a let property by the value
// computed by this initializer.
- InstructionsCloner Cloner(*F, Init, Load);
- Cloner.clone();
- SILInstruction *I = &*std::prev(Load->getIterator());
- SILBuilderWithScope B(Load);
- for (auto UI = Load->use_begin(), E = Load->use_end(); UI != E;) {
+ SILValue clonedInit = cloneInitAt(proj);
+ SILBuilderWithScope B(proj);
+ for (auto UI = proj->use_begin(), E = proj->use_end(); UI != E;) {
auto *User = UI->getUser();
++UI;
if (isa<StoreInst>(User))
continue;
- replaceLoadSequence(User, I, B);
+ replaceLoadSequence(User, clonedInit, B);
eraseUsesOfInstruction(User);
User->eraseFromParent();
++NumReplaced;
}
ChangedFunctions.insert(F);
- } else if (isa<StructExtractInst>(Load)) {
+ } else if (auto proj = dyn_cast<StructExtractInst>(Load)) {
// Copy the initializer into the function
// Replace the access to a let property by the value
// computed by this initializer.
- InstructionsCloner Cloner(*F, Init, Load);
- Cloner.clone();
- SILInstruction *I = &*std::prev(Load->getIterator());
- Load->replaceAllUsesWith(I);
+ SILValue clonedInit = cloneInitAt(proj);
+ proj->replaceAllUsesWith(clonedInit);
DEBUG(llvm::dbgs() << "Access to " << *Property << " was replaced:\n";
- I->dumpInContext());
+ clonedInit->dumpInContext());
- Load->eraseFromParent();
+ proj->eraseFromParent();
++NumReplaced;
ChangedFunctions.insert(F);
- } else if (isa<StructElementAddrInst>(Load)) {
+ } else if (auto proj = dyn_cast<StructElementAddrInst>(Load)) {
// Copy the initializer into the function
// Replace the access to a let property by the value
// computed by this initializer.
- InstructionsCloner Cloner(*F, Init, Load);
- Cloner.clone();
- SILInstruction *I = &*std::prev(Load->getIterator());
- SILBuilderWithScope B(Load);
- for (auto UI = Load->use_begin(), E = Load->use_end(); UI != E;) {
+ SILValue clonedInit = cloneInitAt(proj);
+ SILBuilderWithScope B(proj);
+ for (auto UI = proj->use_begin(), E = proj->use_end(); UI != E;) {
auto *User = UI->getUser();
++UI;
if (isa<StoreInst>(User))
continue;
- replaceLoadSequence(User, I, B);
+ replaceLoadSequence(User, clonedInit, B);
eraseUsesOfInstruction(User);
User->eraseFromParent();
++NumReplaced;
@@ -256,25 +259,32 @@
}
}
-/// Compare to SILValues structurally.
-static bool CmpSILValues(SILValue LHS, SILValue RHS) {
+/// Compare two SILValues structurally.
+static bool isStructurallyIdentical(SILValue LHS, SILValue RHS) {
+ if (LHS == RHS)
+ return true;
+
if (LHS->getType() != RHS->getType())
return false;
- auto L = dyn_cast<SILInstruction>(LHS);
- return L->isIdenticalTo(dyn_cast<SILInstruction>(RHS), CmpSILValues);
+ auto lResult = LHS->getDefiningInstructionResult();
+ auto rResult = RHS->getDefiningInstructionResult();
+ assert(lResult && rResult &&
+ "operands of instructions approved by analyzeStaticInitializer "
+ "should always be defined by instructions");
+ return (lResult->ResultIndex == rResult->ResultIndex &&
+ lResult->Instruction->isIdenticalTo(rResult->Instruction,
+ isStructurallyIdentical));
};
-/// Compare two sequences of SIL instructions. They should be structurally equivalent.
-static bool compareInsnSequences(SmallVectorImpl<SILInstruction *> &LHS,
- SmallVectorImpl<SILInstruction *> &RHS) {
- if (LHS.size() != RHS.size())
- return false;
-
- for (int i=0, e=LHS.size(); i < e; ++i)
- if (!LHS[i]->isIdenticalTo(RHS[i], CmpSILValues))
- return false;
- return true;
+/// Compare two sequences of SIL instructions. They should be structurally
+/// equivalent.
+static bool isSameInitSequence(const InitSequence &LHS,
+ const InitSequence &RHS) {
+ assert(LHS.isValid() && RHS.isValid());
+ // This will recursively check all the instructions. It's possible
+ // that they'll be composed slightly differently, but it shouldn't matter.
+ return isStructurallyIdentical(LHS.Result, RHS.Result);
}
/// Check if a given let property can be assigned externally.
@@ -407,11 +417,10 @@
// Analyze the init value being stored by the instruction into a property.
bool
LetPropertiesOpt::analyzeInitValue(SILInstruction *I, VarDecl *Property) {
- SmallVector<SILInstruction *, 8> Insns;
SmallVector<SILInstruction *, 8> ReverseInsns;
- SILValue ValueOfProperty;
+ SILValue value;
if (auto SI = dyn_cast<StructInst>(I)) {
- ValueOfProperty = SI->getFieldValue(Property);
+ value = SI->getFieldValue(Property);
} else if (auto SI = dyn_cast<StoreInst>(I)) {
auto Dest = SI->getDest();
@@ -421,27 +430,31 @@
cast<StructElementAddrInst>(Dest)->getField() == Property)) &&
"Store instruction should store into a proper let property");
(void) Dest;
- ValueOfProperty = SI->getSrc();
+ value = SI->getSrc();
}
// Bail if a value of a property is not a statically known constant init.
- if (!analyzeStaticInitializer(ValueOfProperty, ReverseInsns))
+ if (!analyzeStaticInitializer(value, ReverseInsns))
return false;
- // Produce a correct order of instructions.
+ // Fill in the InitSequence by reversing the instructions and
+ // setting the result index.
+ InitSequence sequence;
while (!ReverseInsns.empty()) {
- Insns.push_back(ReverseInsns.pop_back_val());
+ sequence.Instructions.push_back(ReverseInsns.pop_back_val());
}
+ sequence.Result = value;
- auto &InitInsns = InitMap[Property];
- if (!InitInsns.empty() && !compareInsnSequences(InitInsns, Insns)) {
+ auto &cachedSequence = InitMap[Property];
+ if (cachedSequence.isValid() &&
+ !isSameInitSequence(cachedSequence, sequence)) {
// The found init value is different from the already seen init value.
return false;
} else {
DEBUG(llvm::dbgs() << "The value of property '" << *Property
<< "' is statically known so far\n");
// Remember the statically known value.
- InitInsns = Insns;
+ cachedSequence = std::move(sequence);
return true;
}
}
@@ -510,7 +523,8 @@
return true;
if (isa<StructElementAddrInst>(I) || isa<TupleElementAddrInst>(I)) {
- for (auto Use : getNonDebugUses(I))
+ auto projection = cast<SingleValueInstruction>(I);
+ for (auto Use : getNonDebugUses(projection))
if (!isValidPropertyLoad(Use->getUser()))
return false;
return true;
@@ -533,14 +547,15 @@
if (isa<RefElementAddrInst>(I) || isa<StructElementAddrInst>(I)) {
// Check if there is a store to this property.
- for (auto Use : getNonDebugUses(I)) {
+ auto projection = cast<SingleValueInstruction>(I);
+ for (auto Use : getNonDebugUses(projection)) {
auto *User = Use->getUser();
if (auto *SI = dyn_cast<StoreInst>(User)) {
// There is a store into this property.
// Analyze the assigned value and check if it is a constant
// statically known initializer.
- if (SI->getDest() != I || !analyzeInitValue(SI, Property)) {
+ if (SI->getDest() != projection || !analyzeInitValue(SI, Property)) {
SkipProcessing.insert(Property);
return;
}
diff --git a/lib/SILOptimizer/IPO/UsePrespecialized.cpp b/lib/SILOptimizer/IPO/UsePrespecialized.cpp
index c766e15..b9d6b30 100644
--- a/lib/SILOptimizer/IPO/UsePrespecialized.cpp
+++ b/lib/SILOptimizer/IPO/UsePrespecialized.cpp
@@ -140,7 +140,13 @@
<< " : " << NewF->getName() << "\n");
auto NewAI = replaceWithSpecializedFunction(AI, NewF, ReInfo);
- AI.getInstruction()->replaceAllUsesWith(NewAI.getInstruction());
+ if (auto oldApply = dyn_cast<ApplyInst>(AI)) {
+ oldApply->replaceAllUsesWith(cast<ApplyInst>(NewAI));
+ } else if (auto oldPApply = dyn_cast<PartialApplyInst>(AI)) {
+ oldPApply->replaceAllUsesWith(cast<PartialApplyInst>(NewAI));
+ } else {
+ assert(isa<TryApplyInst>(NewAI));
+ }
recursivelyDeleteTriviallyDeadInstructions(AI.getInstruction(), true);
Changed = true;
}
diff --git a/lib/SILOptimizer/LoopTransforms/ArrayBoundsCheckOpts.cpp b/lib/SILOptimizer/LoopTransforms/ArrayBoundsCheckOpts.cpp
index a53289c..e927083 100644
--- a/lib/SILOptimizer/LoopTransforms/ArrayBoundsCheckOpts.cpp
+++ b/lib/SILOptimizer/LoopTransforms/ArrayBoundsCheckOpts.cpp
@@ -483,8 +483,8 @@
return Changed;
}
-static CondFailInst *hasCondFailUse(SILInstruction *I) {
- for (auto *Op : I->getUses())
+static CondFailInst *hasCondFailUse(SILValue V) {
+ for (auto *Op : V->getUses())
if (auto C = dyn_cast<CondFailInst>(Op->getUser()))
return C;
return nullptr;
@@ -935,7 +935,7 @@
// Get the first induction value.
auto FirstVal = Ind->getFirstValue();
// Clone the struct for the start index.
- auto Start = cast<SILInstruction>(CheckToHoist.getIndex())
+ auto Start = cast<SingleValueInstruction>(CheckToHoist.getIndex())
->clone(Preheader->getTerminator());
// Set the new start index to the first value of the induction.
Start->setOperand(0, FirstVal);
@@ -947,7 +947,7 @@
// Get the last induction value.
auto LastVal = Ind->getLastValue(Loc, Builder);
// Clone the struct for the end index.
- auto End = cast<SILInstruction>(CheckToHoist.getIndex())
+ auto End = cast<SingleValueInstruction>(CheckToHoist.getIndex())
->clone(Preheader->getTerminator());
// Set the new end index to the last value of the induction.
End->setOperand(0, LastVal);
@@ -1073,7 +1073,7 @@
/// A dominating cond_fail on the same value ensures that this value is false.
static bool isValueKnownFalseAt(SILValue Val, SILInstruction *At,
DominanceInfo *DT) {
- auto *Inst = dyn_cast<SILInstruction>(Val);
+ auto *Inst = Val->getDefiningInstruction();
if (!Inst ||
std::next(SILBasicBlock::iterator(Inst)) == Inst->getParent()->end())
return false;
diff --git a/lib/SILOptimizer/LoopTransforms/COWArrayOpt.cpp b/lib/SILOptimizer/LoopTransforms/COWArrayOpt.cpp
index 359dec8..b7267e7 100644
--- a/lib/SILOptimizer/LoopTransforms/COWArrayOpt.cpp
+++ b/lib/SILOptimizer/LoopTransforms/COWArrayOpt.cpp
@@ -53,7 +53,7 @@
static SILValue getAccessPath(SILValue V, SmallVectorImpl<unsigned>& Path) {
V = stripCasts(V);
ProjectionIndex PI(V);
- if (!PI.isValid() || V->getKind() == ValueKind::IndexAddrInst)
+ if (!PI.isValid() || isa<IndexAddrInst>(V))
return V;
SILValue UnderlyingObject = getAccessPath(PI.Aggregate, Path);
@@ -100,10 +100,10 @@
UserList AggregateAddressUsers;
UserList StructAddressUsers;
- UserList StructLoads;
+ SmallVector<LoadInst*, 16> StructLoads;
UserList StructValueUsers;
UserOperList ElementAddressUsers;
- UserOperList ElementLoads;
+ SmallVector<std::pair<LoadInst*, Operand*>, 16> ElementLoads;
UserOperList ElementValueUsers;
VisitedSet Visited;
@@ -140,11 +140,7 @@
protected:
static bool definesSingleObjectType(ValueBase *V) {
- if (auto *Arg = dyn_cast<SILArgument>(V))
- return Arg->getType().isObject();
- if (auto *Inst = dyn_cast<SILInstruction>(V))
- return Inst->hasValue() && Inst->getType().isObject();
- return false;
+ return V->getType().isObject();
}
/// If AccessPathSuffix is non-empty, then the value is the address of an
@@ -170,8 +166,8 @@
continue;
}
- if (isa<StructElementAddrInst>(UseInst)) {
- collectAddressUses(UseInst, AccessPathSuffix, StructVal);
+ if (auto proj = dyn_cast<StructElementAddrInst>(UseInst)) {
+ collectAddressUses(proj, AccessPathSuffix, StructVal);
continue;
}
@@ -186,8 +182,8 @@
continue;
}
- if (isa<StructElementAddrInst>(UseInst)) {
- collectAddressUses(UseInst, AccessPathSuffix, &*UI);
+ if (auto proj = dyn_cast<StructElementAddrInst>(UseInst)) {
+ collectAddressUses(proj, AccessPathSuffix, &*UI);
continue;
}
@@ -201,10 +197,18 @@
continue;
}
- ProjectionIndex PI(UseInst);
+ // Check for uses of projections.
+
+ // These are all single-value instructions.
+ auto ProjInst = dyn_cast<SingleValueInstruction>(UseInst);
+ if (!ProjInst) {
+ AggregateAddressUsers.push_back(UseInst);
+ continue;
+ }
+ ProjectionIndex PI(ProjInst);
// Do not form a path from an IndexAddrInst without otherwise
// distinguishing it from subelement addressing.
- if (!PI.isValid() || V->getKind() == ValueKind::IndexAddrInst) {
+ if (!PI.isValid() || isa<IndexAddrInst>(V)) {
// Found a use of an aggregate containing the given element.
AggregateAddressUsers.push_back(UseInst);
continue;
@@ -220,7 +224,7 @@
// Recursively check for users after stripping this component from the
// access path.
- collectAddressUses(UseInst, AccessPathSuffix.slice(1), nullptr);
+ collectAddressUses(ProjInst, AccessPathSuffix.slice(1), nullptr);
}
}
};
@@ -631,20 +635,19 @@
/// Returns true if this instruction is a safe array use if all of its users are
/// also safe array users.
-static bool isTransitiveSafeUser(SILInstruction *I) {
+static SILValue isTransitiveSafeUser(SILInstruction *I) {
switch (I->getKind()) {
- case ValueKind::StructExtractInst:
- case ValueKind::TupleExtractInst:
- case ValueKind::UncheckedEnumDataInst:
- case ValueKind::StructInst:
- case ValueKind::TupleInst:
- case ValueKind::EnumInst:
- case ValueKind::UncheckedRefCastInst:
- case ValueKind::UncheckedBitwiseCastInst:
- assert(I->hasValue() && "We assume these are unary");
- return true;
+ case SILInstructionKind::StructExtractInst:
+ case SILInstructionKind::TupleExtractInst:
+ case SILInstructionKind::UncheckedEnumDataInst:
+ case SILInstructionKind::StructInst:
+ case SILInstructionKind::TupleInst:
+ case SILInstructionKind::EnumInst:
+ case SILInstructionKind::UncheckedRefCastInst:
+ case SILInstructionKind::UncheckedBitwiseCastInst:
+ return cast<SingleValueInstruction>(I);
default:
- return false;
+ return nullptr;
}
}
@@ -667,8 +670,8 @@
/// Is this a unary transitive safe user instruction. This means that the
/// instruction is safe only if all of its users are safe. Check this
/// recursively.
- if (isTransitiveSafeUser(UseInst)) {
- if (std::all_of(UseInst->use_begin(), UseInst->use_end(),
+ if (auto inst = isTransitiveSafeUser(UseInst)) {
+ if (std::all_of(inst->use_begin(), inst->use_end(),
[this](Operand *Op) -> bool {
return checkSafeArrayElementUse(Op->getUser(),
Op->get());
@@ -765,8 +768,8 @@
// all of its users are safe array element uses, recursively check its uses
// and return false if any of them are not transitive escape array element
// uses.
- if (isTransitiveSafeUser(UseInst)) {
- return std::all_of(UseInst->use_begin(), UseInst->use_end(),
+ if (auto result = isTransitiveSafeUser(UseInst)) {
+ return std::all_of(result->use_begin(), result->use_end(),
[this, &ArrayVal](Operand *UI) -> bool {
return checkSafeArrayElementUse(UI->getUser(),
ArrayVal);
@@ -874,7 +877,8 @@
return false;
StartInst = ASI;
} else {
- StartInst = cast<SILInstruction>(V);
+ // True because of the caller.
+ StartInst = V->getDefiningInstruction();
}
for (auto II = std::next(SILBasicBlock::iterator(StartInst)),
IE = StartInst->getParent()->end();
@@ -936,9 +940,9 @@
static SILValue
stripValueProjections(SILValue V,
SmallVectorImpl<SILInstruction *> &ValuePrjs) {
- while (V->getKind() == ValueKind::StructExtractInst) {
- ValuePrjs.push_back(cast<SILInstruction>(V));
- V = cast<SILInstruction>(V)->getOperand(0);
+ while (auto SEI = dyn_cast<StructExtractInst>(V)) {
+ ValuePrjs.push_back(SEI);
+ V = SEI->getOperand();
}
return V;
}
@@ -1232,8 +1236,9 @@
// are release before we hit a make_unique instruction.
ApplyInst *SemCall = Sem;
if (Sem.getKind() == ArrayCallKind::kGetElement) {
- SILValue Elem = (Sem.hasGetElementDirectResult() ? Inst :
- SemCall->getArgument(0));
+ SILValue Elem = (Sem.hasGetElementDirectResult()
+ ? Sem.getCallResult()
+ : SemCall->getArgument(0));
if (!Elem->getType().isTrivial(Module))
CreatedNonTrivialValues.insert(Elem);
} else if (Sem.getKind() == ArrayCallKind::kMakeMutable) {
@@ -1933,7 +1938,7 @@
SILBasicBlock *StartBB;
SmallPtrSet<SILBasicBlock *, 16> OutsideBBs;
- friend class SILVisitor<RegionCloner>;
+ friend class SILInstructionVisitor<RegionCloner>;
friend class SILCloner<RegionCloner>;
public:
@@ -2086,7 +2091,8 @@
// Update outside used instruction values.
for (auto &Inst : *OrigBB) {
- updateSSAForValue(OrigBB, &Inst, SSAUp);
+ for (auto result : Inst.getResults())
+ updateSSAForValue(OrigBB, result, SSAUp);
}
}
}
@@ -2213,6 +2219,24 @@
C.removeCall();
}
+/// Collects all loop dominated blocks outside the loop that are immediately
+/// dominated by the loop.
+static void
+collectImmediateLoopDominatedBlocks(const SILLoop *Lp, DominanceInfoNode *Node,
+ SmallVectorImpl<SILBasicBlock *> &Blocks) {
+ SILBasicBlock *BB = Node->getBlock();
+
+ // Base case: First loop dominated block outside of loop.
+ if (!Lp->contains(BB)) {
+ Blocks.push_back(BB);
+ return;
+ }
+
+ // Loop contains the basic block. Look at immediately dominated nodes.
+ for (auto *Child : *Node)
+ collectImmediateLoopDominatedBlocks(Lp, Child, Blocks);
+}
+
void ArrayPropertiesSpecializer::specializeLoopNest() {
auto *Lp = getLoop();
assert(Lp);
@@ -2225,22 +2249,19 @@
auto *CheckBlock = splitBasicBlockAndBranch(B,
HoistableLoopPreheader->getTerminator(), DomTree, nullptr);
- // Get the exit blocks of the original loop.
auto *Header = CheckBlock->getSingleSuccessorBlock();
assert(Header);
- // Our loop info is not really completely valid anymore since the cloner does
- // not update it. However, exit blocks of the original loop are still valid.
+ // Collect all loop dominated blocks (e.g exit blocks could be among them). We
+ // need to update their dominator.
+ SmallVector<SILBasicBlock *, 16> LoopDominatedBlocks;
+ collectImmediateLoopDominatedBlocks(Lp, DomTree->getNode(Header),
+ LoopDominatedBlocks);
+
+ // Collect all exit blocks.
SmallVector<SILBasicBlock *, 16> ExitBlocks;
Lp->getExitBlocks(ExitBlocks);
- // Collect the exit blocks dominated by the loop - they will be dominated by
- // the check block.
- SmallVector<SILBasicBlock *, 16> ExitBlocksDominatedByPreheader;
- for (auto *ExitBlock: ExitBlocks)
- if (DomTree->dominates(CheckBlock, ExitBlock))
- ExitBlocksDominatedByPreheader.push_back(ExitBlock);
-
// Split the preheader before the first instruction.
SILBasicBlock *NewPreheader =
splitBasicBlockAndBranch(B, &*CheckBlock->begin(), DomTree, nullptr);
@@ -2269,8 +2290,8 @@
IsFastNativeArray, ClonedPreheader, NewPreheader);
CheckBlock->getTerminator()->eraseFromParent();
- // Fixup the exit blocks. They are now dominated by the check block.
- for (auto *BB : ExitBlocksDominatedByPreheader)
+ // Fixup the loop dominated blocks. They are now dominated by the check block.
+ for (auto *BB : LoopDominatedBlocks)
DomTree->changeImmediateDominator(DomTree->getNode(BB),
DomTree->getNode(CheckBlock));
diff --git a/lib/SILOptimizer/LoopTransforms/LICM.cpp b/lib/SILOptimizer/LoopTransforms/LICM.cpp
index 29bbf18..9820f24 100644
--- a/lib/SILOptimizer/LoopTransforms/LICM.cpp
+++ b/lib/SILOptimizer/LoopTransforms/LICM.cpp
@@ -115,7 +115,7 @@
ValueBase *Def = Op.get();
// Operand is defined outside the loop.
- if (auto *Inst = dyn_cast<SILInstruction>(Def))
+ if (auto *Inst = Def->getDefiningInstruction())
return !L->contains(Inst->getParent());
if (auto *Arg = dyn_cast<SILArgument>(Def))
return !L->contains(Arg->getParent());
diff --git a/lib/SILOptimizer/LoopTransforms/LoopRotate.cpp b/lib/SILOptimizer/LoopTransforms/LoopRotate.cpp
index 8723cc4..aca1f15 100644
--- a/lib/SILOptimizer/LoopTransforms/LoopRotate.cpp
+++ b/lib/SILOptimizer/LoopTransforms/LoopRotate.cpp
@@ -42,7 +42,7 @@
ValueBase *Def = Op.get();
// Operand is outside the loop or marked invariant.
- if (auto *Inst = dyn_cast<SILInstruction>(Def))
+ if (auto *Inst = Def->getDefiningInstruction())
return !L->contains(Inst->getParent()) || Inv.count(Inst);
if (auto *Arg = dyn_cast<SILArgument>(Def))
return !L->contains(Arg->getParent());
@@ -101,61 +101,64 @@
}
}
+static void updateSSAForUseOfValue(
+ SILSSAUpdater &Updater, SmallVectorImpl<SILPHIArgument *> &InsertedPHIs,
+ const llvm::DenseMap<ValueBase *, SILValue> &ValueMap,
+ SILBasicBlock *Header, SILBasicBlock *EntryCheckBlock,
+ SILValue Res) {
+ // Find the mapped instruction.
+ assert(ValueMap.count(Res) && "Expected to find value in map!");
+ SILValue MappedValue = ValueMap.find(Res)->second;
+ assert(MappedValue);
+ assert(Res->getType() == MappedValue->getType() && "The types must match");
+
+ InsertedPHIs.clear();
+ Updater.Initialize(Res->getType());
+ Updater.AddAvailableValue(Header, Res);
+ Updater.AddAvailableValue(EntryCheckBlock, MappedValue);
+
+
+ // Because of the way that phi nodes are represented we have to collect all
+ // uses before we update SSA. Modifying one phi node can invalidate another
+ // unrelated phi nodes operands through the common branch instruction (that
+ // has to be modified). This would invalidate a plain ValueUseIterator.
+ // Instead we collect uses wrapping uses in branches specially so that we
+ // can reconstruct the use even after the branch has been modified.
+ SmallVector<UseWrapper, 8> StoredUses;
+ for (auto *U : Res->getUses())
+ StoredUses.push_back(UseWrapper(U));
+ for (auto U : StoredUses) {
+ Operand *Use = U;
+ SILInstruction *User = Use->getUser();
+ assert(User && "Missing user");
+
+ // Ignore uses in the same basic block.
+ if (User->getParent() == Header)
+ continue;
+
+ assert(User->getParent() != EntryCheckBlock &&
+ "The entry check block should dominate the header");
+ Updater.RewriteUse(*Use);
+ }
+ // Canonicalize inserted phis to avoid extra BB Args.
+ for (SILPHIArgument *Arg : InsertedPHIs) {
+ if (SILValue Inst = replaceBBArgWithCast(Arg)) {
+ Arg->replaceAllUsesWith(Inst);
+ // DCE+SimplifyCFG runs as a post-pass cleanup.
+ // DCE replaces dead arg values with undef.
+ // SimplifyCFG deletes the dead BB arg.
+ }
+ }
+}
+
static void updateSSAForUseOfInst(
SILSSAUpdater &Updater, SmallVectorImpl<SILPHIArgument *> &InsertedPHIs,
const llvm::DenseMap<ValueBase *, SILValue> &ValueMap,
- SILBasicBlock *Header, SILBasicBlock *EntryCheckBlock, ValueBase *Inst) {
- if (Inst->use_empty())
- return;
-
- // Find the mapped instruction.
- assert(ValueMap.count(Inst) && "Expected to find value in map!");
- SILValue MappedValue = ValueMap.find(Inst)->second;
- assert(MappedValue);
-
- // For each use of a specific result value of the instruction.
- if (Inst->hasValue()) {
- SILValue Res(Inst);
- assert(Res->getType() == MappedValue->getType() && "The types must match");
-
- InsertedPHIs.clear();
- Updater.Initialize(Res->getType());
- Updater.AddAvailableValue(Header, Res);
- Updater.AddAvailableValue(EntryCheckBlock, MappedValue);
-
-
- // Because of the way that phi nodes are represented we have to collect all
- // uses before we update SSA. Modifying one phi node can invalidate another
- // unrelated phi nodes operands through the common branch instruction (that
- // has to be modified). This would invalidate a plain ValueUseIterator.
- // Instead we collect uses wrapping uses in branches specially so that we
- // can reconstruct the use even after the branch has been modified.
- SmallVector<UseWrapper, 8> StoredUses;
- for (auto *U : Res->getUses())
- StoredUses.push_back(UseWrapper(U));
- for (auto U : StoredUses) {
- Operand *Use = U;
- SILInstruction *User = Use->getUser();
- assert(User && "Missing user");
-
- // Ignore uses in the same basic block.
- if (User->getParent() == Header)
- continue;
-
- assert(User->getParent() != EntryCheckBlock &&
- "The entry check block should dominate the header");
- Updater.RewriteUse(*Use);
- }
- // Canonicalize inserted phis to avoid extra BB Args.
- for (SILPHIArgument *Arg : InsertedPHIs) {
- if (SILInstruction *Inst = replaceBBArgWithCast(Arg)) {
- Arg->replaceAllUsesWith(Inst);
- // DCE+SimplifyCFG runs as a post-pass cleanup.
- // DCE replaces dead arg values with undef.
- // SimplifyCFG deletes the dead BB arg.
- }
- }
- }
+ SILBasicBlock *Header, SILBasicBlock *EntryCheckBlock,
+ SILInstruction *Inst) {
+ for (auto result : Inst->getResults())
+ updateSSAForUseOfValue(Updater, InsertedPHIs, ValueMap, Header,
+ EntryCheckBlock, result);
}
/// Rewrite the code we just created in the preheader and update SSA form.
@@ -167,9 +170,9 @@
SILSSAUpdater Updater(&InsertedPHIs);
// Fix PHIs (incoming arguments).
- for (auto *Inst : Header->getArguments())
- updateSSAForUseOfInst(Updater, InsertedPHIs, ValueMap, Header,
- EntryCheckBlock, Inst);
+ for (auto *Arg : Header->getArguments())
+ updateSSAForUseOfValue(Updater, InsertedPHIs, ValueMap, Header,
+ EntryCheckBlock, Arg);
auto InstIter = Header->begin();
@@ -345,11 +348,15 @@
// The other instructions are just cloned to the preheader.
TermInst *PreheaderBranch = Preheader->getTerminator();
for (auto &Inst : *Header) {
- if (SILInstruction *I = Inst.clone(PreheaderBranch)) {
- mapOperands(I, ValueMap);
+ if (SILInstruction *cloned = Inst.clone(PreheaderBranch)) {
+ mapOperands(cloned, ValueMap);
// The actual operand will sort out which result idx to use.
- ValueMap[&Inst] = I;
+ auto instResults = Inst.getResults();
+ auto clonedResults = cloned->getResults();
+ assert(instResults.size() == clonedResults.size());
+ for (auto i : indices(instResults))
+ ValueMap[instResults[i]] = clonedResults[i];
}
}
diff --git a/lib/SILOptimizer/LoopTransforms/LoopUnroll.cpp b/lib/SILOptimizer/LoopTransforms/LoopUnroll.cpp
index fc93029..dd43738 100644
--- a/lib/SILOptimizer/LoopTransforms/LoopUnroll.cpp
+++ b/lib/SILOptimizer/LoopTransforms/LoopUnroll.cpp
@@ -37,7 +37,7 @@
class LoopCloner : public SILCloner<LoopCloner> {
SILLoop *Loop;
- friend class SILVisitor<LoopCloner>;
+ friend class SILInstructionVisitor<LoopCloner>;
friend class SILCloner<LoopCloner>;
public:
@@ -51,9 +51,6 @@
MapVector<SILBasicBlock *, SILBasicBlock *> &getBBMap() { return BBMap; }
DenseMap<SILValue, SILValue> &getValueMap() { return ValueMap; }
- DenseMap<SILInstruction *, SILInstruction *> &getInstMap() {
- return InstructionMap;
- }
protected:
SILValue remapValue(SILValue V) {
@@ -293,8 +290,7 @@
/// value to live out value in the cloned loop.
static void collectLoopLiveOutValues(
DenseMap<SILValue, SmallVector<SILValue, 8>> &LoopLiveOutValues,
- SILLoop *Loop, DenseMap<SILValue, SILValue> &ClonedValues,
- DenseMap<SILInstruction *, SILInstruction *> &ClonedInstructions) {
+ SILLoop *Loop, DenseMap<SILValue, SILValue> &ClonedValues) {
for (auto *Block : Loop->getBlocks()) {
// Look at block arguments.
for (auto *Arg : Block->getArguments()) {
@@ -312,15 +308,17 @@
}
// And the instructions.
for (auto &Inst : *Block) {
- for (auto *Op : Inst.getUses()) {
- // Is this use outside the loop.
- if (!Loop->contains(Op->getUser())) {
+ for (SILValue result : Inst.getResults()) {
+ for (auto *Op : result->getUses()) {
+ // Ignore uses inside the loop.
+ if (Loop->contains(Op->getUser()))
+ continue;
+
auto UsedValue = Op->get();
- assert(UsedValue == &Inst && "Instructions must match");
- assert(ClonedInstructions.count(&Inst) && "Unmapped instruction!");
+ assert(UsedValue == result && "Instructions must match");
if (!LoopLiveOutValues.count(UsedValue))
- LoopLiveOutValues[UsedValue].push_back(ClonedInstructions[&Inst]);
+ LoopLiveOutValues[UsedValue].push_back(ClonedValues[result]);
}
}
}
@@ -405,18 +403,11 @@
// subsequent iterations we only need to update this map with the values
// from the new iteration's clone.
if (Cnt == 1)
- collectLoopLiveOutValues(LoopLiveOutValues, Loop, Cloner.getValueMap(),
- Cloner.getInstMap());
+ collectLoopLiveOutValues(LoopLiveOutValues, Loop, Cloner.getValueMap());
else {
for (auto &MapEntry : LoopLiveOutValues) {
- // If this is an argument look up the value in the value map.
- SILValue MappedValue;
- if (isa<SILArgument>(MapEntry.first))
- MappedValue = Cloner.getValueMap()[MapEntry.first];
- // Otherwise, consult the instruction map.
- else
- MappedValue = Cloner
- .getInstMap()[cast<SILInstruction>(MapEntry.first)];
+ // Look it up in the value map.
+ SILValue MappedValue = Cloner.getValueMap()[MapEntry.first];
MapEntry.second.push_back(MappedValue);
assert(MapEntry.second.size() == Cnt);
}
diff --git a/lib/SILOptimizer/Mandatory/AccessEnforcementSelection.cpp b/lib/SILOptimizer/Mandatory/AccessEnforcementSelection.cpp
index 21ecd6f..2be7614 100644
--- a/lib/SILOptimizer/Mandatory/AccessEnforcementSelection.cpp
+++ b/lib/SILOptimizer/Mandatory/AccessEnforcementSelection.cpp
@@ -175,7 +175,7 @@
void run();
private:
- void analyzeUsesOfBox(SILInstruction *source);
+ void analyzeUsesOfBox(SingleValueInstruction *source);
void analyzeProjection(ProjectBoxInst *projection);
/// Note that the given instruction is a use of the box (or a use of
@@ -214,7 +214,7 @@
// FIXME: This should cover a superset of AllocBoxToStack's findUnexpectedBoxUse
// to avoid perturbing codegen. They should be sharing the same analysis.
-void SelectEnforcement::analyzeUsesOfBox(SILInstruction *source) {
+void SelectEnforcement::analyzeUsesOfBox(SingleValueInstruction *source) {
// Collect accesses rooted off of projections.
for (auto use : source->getUses()) {
auto user = use->getUser();
diff --git a/lib/SILOptimizer/Mandatory/AccessMarkerElimination.cpp b/lib/SILOptimizer/Mandatory/AccessMarkerElimination.cpp
index 456a23d..44d360f 100644
--- a/lib/SILOptimizer/Mandatory/AccessMarkerElimination.cpp
+++ b/lib/SILOptimizer/Mandatory/AccessMarkerElimination.cpp
@@ -77,7 +77,6 @@
// Delete any associated end_access instructions.
if (auto endAccess = dyn_cast<EndAccessInst>(op->getUser())) {
- assert(endAccess->use_empty() && "found use of end_access");
endAccess->eraseFromParent();
// Forward all other uses to the original address.
@@ -123,7 +122,6 @@
if (shouldPreserveAccess(BUA->getEnforcement()))
return false;
- BUA->replaceAllUsesWith(BUA->getSource());
return true;
}
// end_unpaired_access instructions will be directly removed and
@@ -132,7 +130,6 @@
if (shouldPreserveAccess(EUA->getEnforcement()))
return false;
- assert(EUA->use_empty() && "use of end_unpaired_access");
return true;
}
return false;
diff --git a/lib/SILOptimizer/Mandatory/AddressLowering.cpp b/lib/SILOptimizer/Mandatory/AddressLowering.cpp
index 1b19f09..531bea9 100644
--- a/lib/SILOptimizer/Mandatory/AddressLowering.cpp
+++ b/lib/SILOptimizer/Mandatory/AddressLowering.cpp
@@ -112,15 +112,19 @@
// Visit all call results.
// Stop when the visitor returns `false`.
-void visitCallResults(ApplySite apply,
- std::function<bool(SILInstruction *)> visitor) {
- if (apply.getType().is<TupleType>()) {
- for (auto *operand : apply.getInstruction()->getUses()) {
- if (!visitor(operand->getUser()))
- break;
+static void visitCallResults(ApplySite apply,
+ llvm::function_ref<bool(SILValue)> visitor) {
+ // FIXME: this entire implementation only really works for ApplyInst.
+ auto applyInst = cast<ApplyInst>(apply);
+ if (applyInst->getType().is<TupleType>()) {
+ // TODO: MultiValueInstruction
+ for (auto *operand : applyInst->getUses()) {
+ if (auto extract = dyn_cast<TupleExtractInst>(operand->getUser()))
+ if (!visitor(extract))
+ break;
}
} else
- visitor(apply.getInstruction());
+ visitor(applyInst);
}
//===----------------------------------------------------------------------===//
@@ -233,7 +237,7 @@
ValueStorageMap valueStorageMap;
// All call sites with formally indirect SILArgument or SILResult conventions.
// Calls are removed from the set when rewritten.
- SmallSetVector<SILInstruction *, 16> indirectApplies;
+ SmallSetVector<ApplySite, 16> indirectApplies;
// All function-exiting terminators (return or throw instructions).
SmallVector<TermInst *, 8> returnInsts;
// Delete these instructions after performing transformations.
@@ -250,8 +254,9 @@
void markDead(SILInstruction *inst) {
#ifndef NDEBUG
- for (Operand *use : inst->getUses())
- assert(instsToDelete.count(use->getUser()));
+ for (auto result : inst->getResults())
+ for (Operand *use : result->getUses())
+ assert(instsToDelete.count(use->getUser()));
#endif
instsToDelete.insert(inst);
}
@@ -305,11 +310,11 @@
}
}
for (auto &II : *BB) {
- if (ApplySite::isa(&II))
- visitApply(ApplySite(&II));
+ if (auto apply = ApplySite::isa(&II))
+ visitApply(apply);
- if (II.hasValue())
- visitValue(SILValue(&II));
+ for (auto result : II.getResults())
+ visitValue(result);
}
}
}
@@ -323,16 +328,16 @@
if (operand.get()->getType().isObject()) {
auto argConv = calleeConv.getSILArgumentConvention(calleeArgIdx);
if (argConv.isIndirectConvention()) {
- pass.indirectApplies.insert(applySite.getInstruction());
+ pass.indirectApplies.insert(applySite);
}
}
++calleeArgIdx;
}
if (applySite.getSubstCalleeType()->hasIndirectFormalResults()) {
- pass.indirectApplies.insert(applySite.getInstruction());
+ pass.indirectApplies.insert(applySite);
if (!applySite.getType().is<TupleType>())
- pass.valueStorageMap.insertValue(applySite.getInstruction());
+ pass.valueStorageMap.insertValue(cast<ApplyInst>(applySite));
return;
}
@@ -375,7 +380,8 @@
protected:
void convertIndirectFunctionArgs();
unsigned insertIndirectReturnArgs();
- bool canProjectFrom(SILInstruction *innerVal, SILInstruction *composingUse);
+ bool canProjectFrom(SingleValueInstruction *innerVal,
+ SILInstruction *composingUse);
void allocateForValue(SILValue value, ValueStorage &storage);
};
} // end anonymous namespace
@@ -472,7 +478,7 @@
///
/// TODO: This should be a common utility.
static SILLocation getLocForValue(SILValue value) {
- if (auto *instr = dyn_cast<SILInstruction>(value)) {
+ if (auto *instr = value->getDefiningInstruction()) {
return instr->getLoc();
}
if (auto *arg = dyn_cast<SILArgument>(value)) {
@@ -488,22 +494,24 @@
///
/// TODO: Handle struct.
/// TODO: Make this a visitor.
-bool OpaqueStorageAllocation::canProjectFrom(SILInstruction *innerVal,
+bool OpaqueStorageAllocation::canProjectFrom(SingleValueInstruction *innerVal,
SILInstruction *composingUse) {
if (!OptimizeOpaqueAddressLowering)
return false;
+ SILValue composingValue;
switch (composingUse->getKind()) {
default:
return false;
- case ValueKind::ApplyInst:
+ case SILInstructionKind::ApplyInst:
// @in operands never need their own storage since they are non-mutating
// uses. They simply reuse the storage allocated for their operand. So it
// wouldn't make sense to "project" out of the apply argument.
return false;
- case ValueKind::EnumInst:
+ case SILInstructionKind::EnumInst:
+ composingValue = cast<EnumInst>(composingUse);
break;
- case ValueKind::InitExistentialValueInst: {
+ case SILInstructionKind::InitExistentialValueInst: {
// Ensure that all opened archetypes are available at the inner value's
// definition.
auto *initExistential = cast<InitExistentialValueInst>(composingUse);
@@ -511,21 +519,23 @@
if (!pass.domInfo->properlyDominates(operand.get(), innerVal))
return false;
}
+ composingValue = initExistential;
break;
}
- case ValueKind::ReturnInst:
+ case SILInstructionKind::ReturnInst:
return true;
- case ValueKind::StoreInst: {
+ case SILInstructionKind::StoreInst: {
if (cast<StoreInst>(composingUse)->getSrc() == innerVal
&& isa<CopyValueInst>(innerVal)) {
return true;
}
return false;
}
- case ValueKind::TupleInst:
+ case SILInstructionKind::TupleInst:
+ composingValue = cast<TupleInst>(composingUse);
break;
}
- ValueStorage &storage = pass.valueStorageMap.getStorage(composingUse);
+ ValueStorage &storage = pass.valueStorageMap.getStorage(composingValue);
if (SILValue addr = storage.storageAddress) {
if (auto *stackInst = dyn_cast<AllocStackInst>(addr)) {
assert(pass.domInfo->properlyDominates(stackInst, innerVal));
@@ -545,11 +555,11 @@
ValueStorage &storage) {
assert(!isa<SILFunctionArgument>(value));
- if (ApplySite::isa(value)) {
+ if (auto apply = ApplySite::isa(value)) {
// Result tuples will be canonicalized during apply rewriting so the tuple
// itself is unused.
if (value->getType().is<TupleType>()) {
- assert(ApplySite(value).getSubstCalleeType()->getNumResults() > 1);
+ assert(apply.getSubstCalleeType()->getNumResults() > 1);
return;
}
}
@@ -564,7 +574,7 @@
// TODO: Handle block arguments.
// TODO: Handle subobjects with a single composition, and other non-mutating
// uses such as @in arguments.
- if (auto *def = dyn_cast<SILInstruction>(value)) {
+ if (auto *def = dyn_cast<SingleValueInstruction>(value)) {
Operand *useOper = *value->use_begin();
if (canProjectFrom(def, useOper->getUser())) {
storage.setComposedOperand(useOper);
@@ -662,14 +672,14 @@
default:
DEBUG(user->dump());
llvm_unreachable("Unexpected subobject composition.");
- case ValueKind::EnumInst: {
+ case SILInstructionKind::EnumInst: {
auto *enumInst = cast<EnumInst>(user);
SILValue enumAddr = materializeAddress(enumInst);
return B.createInitEnumDataAddr(enumInst->getLoc(), enumAddr,
enumInst->getElement(),
operand->get()->getType().getAddressType());
}
- case ValueKind::InitExistentialValueInst: {
+ case SILInstructionKind::InitExistentialValueInst: {
auto *initExistentialValue = cast<InitExistentialValueInst>(user);
SILValue containerAddr = materializeAddress(initExistentialValue);
auto canTy = initExistentialValue->getFormalConcreteType();
@@ -679,11 +689,11 @@
initExistentialValue->getLoc(), containerAddr, canTy,
concreteTL.getLoweredType(), initExistentialValue->getConformances());
}
- case ValueKind::ReturnInst: {
+ case SILInstructionKind::ReturnInst: {
assert(pass.loweredFnConv.hasIndirectSILResults());
return pass.F->getArguments()[0];
}
- case ValueKind::TupleInst: {
+ case SILInstructionKind::TupleInst: {
auto *tupleInst = cast<TupleInst>(user);
// Function return values.
if (tupleInst->hasOneUse()
@@ -717,9 +727,12 @@
ApplySite apply;
SILBuilder argBuilder;
+ /// For now, we assume that the apply site is a normal apply.
+ ApplyInst *getApplyInst() const { return cast<ApplyInst>(apply); }
+
public:
- ApplyRewriter(SILInstruction *origCall, AddressLoweringState &pass)
- : pass(pass), apply(origCall), argBuilder(origCall) {
+ ApplyRewriter(ApplySite origCall, AddressLoweringState &pass)
+ : pass(pass), apply(origCall), argBuilder(origCall.getInstruction()) {
argBuilder.setSILConventions(
SILModuleConventions::getLoweredAddressConventions());
}
@@ -731,9 +744,10 @@
protected:
void
- canonicalizeResults(SmallVectorImpl<SILInstruction *> &directResultValues,
+ canonicalizeResults(MutableArrayRef<SingleValueInstruction *> directResultValues,
ArrayRef<Operand *> nonCanonicalUses);
- SILValue materializeIndirectResultAddress(SILInstruction *origDirectResultVal,
+ SILValue materializeIndirectResultAddress(
+ SingleValueInstruction *origDirectResultVal,
SILType argTy);
};
} // end anonymous namespace
@@ -762,17 +776,17 @@
SILInstruction *lastUse = argLoad ? argLoad : applyInst;
switch (applyInst->getKind()) {
- case ValueKind::ApplyInst: {
+ case SILInstructionKind::ApplyInst: {
SILBuilder deallocBuilder(&*std::next(lastUse->getIterator()));
deallocBuilder.setSILConventions(
SILModuleConventions::getLoweredAddressConventions());
deallocBuilder.createDeallocStack(allocInst->getLoc(), allocInst);
break;
}
- case ValueKind::TryApplyInst:
+ case SILInstructionKind::TryApplyInst:
// TODO!!!: insert dealloc in the catch block.
llvm_unreachable("not implemented for this instruction!");
- case ValueKind::PartialApplyInst:
+ case SILInstructionKind::PartialApplyInst:
llvm_unreachable("partial apply cannot have indirect results.");
default:
llvm_unreachable("not implemented for this instruction!");
@@ -820,19 +834,18 @@
// that result if one exists. This function will add an entry to
// directResultValues whenever it needs to materialize a TupleExtractInst.
void ApplyRewriter::canonicalizeResults(
- SmallVectorImpl<SILInstruction *> &directResultValues,
+ MutableArrayRef<SingleValueInstruction *> directResultValues,
ArrayRef<Operand *> nonCanonicalUses) {
- auto *applyInst = apply.getInstruction();
+ auto *applyInst = getApplyInst();
for (Operand *operand : nonCanonicalUses) {
auto *destroyInst = dyn_cast<DestroyValueInst>(operand->getUser());
if (!destroyInst)
llvm::report_fatal_error("Simultaneous use of multiple call results.");
- for (unsigned resultIdx = 0, endIdx = directResultValues.size();
- resultIdx < endIdx; ++resultIdx) {
- SILInstruction *result = directResultValues[resultIdx];
+ for (unsigned resultIdx : indices(directResultValues)) {
+ SingleValueInstruction *result = directResultValues[resultIdx];
if (!result) {
SILBuilder resultBuilder(std::next(SILBasicBlock::iterator(applyInst)));
resultBuilder.setSILConventions(
@@ -856,7 +869,7 @@
///
/// origDirectResultVal may be nullptr for unused results.
SILValue ApplyRewriter::materializeIndirectResultAddress(
- SILInstruction *origDirectResultVal, SILType argTy) {
+ SingleValueInstruction *origDirectResultVal, SILType argTy) {
if (origDirectResultVal
&& origDirectResultVal->getType().isAddressOnly(pass.F->getModule())) {
@@ -891,12 +904,12 @@
void ApplyRewriter::convertApplyWithIndirectResults() {
assert(apply.getSubstCalleeType()->hasIndirectFormalResults());
- SILInstruction *origCallInst = apply.getInstruction();
+ auto *origCallInst = getApplyInst();
SILFunctionConventions origFnConv = apply.getSubstCalleeConv();
// Gather the original direct return values.
// Canonicalize results so no user uses more than one result.
- SmallVector<SILInstruction *, 8> origDirectResultValues(
+ SmallVector<SingleValueInstruction *, 8> origDirectResultValues(
origFnConv.getNumDirectSILResults());
SmallVector<Operand *, 4> nonCanonicalUses;
if (origCallInst->getType().is<TupleType>()) {
@@ -950,7 +963,7 @@
for_each(
apply.getSubstCalleeType()->getResults(),
origDirectResultValues,
- [&](SILResultInfo resultInfo, SILInstruction *origDirectResultVal) {
+ [&](SILResultInfo resultInfo, SingleValueInstruction *origDirectResultVal) {
// Assume that all original results are direct in SIL.
assert(!origFnConv.isSILIndirect(resultInfo));
@@ -979,17 +992,17 @@
}
// Create a new apply with indirect result operands.
- SILInstruction *newCallInst;
+ ApplyInst *newCallInst;
switch (origCallInst->getKind()) {
- case ValueKind::ApplyInst:
+ case SILInstructionKind::ApplyInst:
newCallInst = callBuilder.createApply(
loc, apply.getCallee(), apply.getSubstitutions(), newCallArgs,
cast<ApplyInst>(origCallInst)->isNonThrowing(), nullptr);
break;
- case ValueKind::TryApplyInst:
+ case SILInstructionKind::TryApplyInst:
// TODO: insert dealloc in the catch block.
llvm_unreachable("not implemented for this instruction!");
- case ValueKind::PartialApplyInst:
+ case SILInstructionKind::PartialApplyInst:
// Partial apply does not have formally indirect results.
default:
llvm_unreachable("not implemented for this instruction!");
@@ -1030,11 +1043,11 @@
}
// Either the new call instruction has only a single direct result, or we
// map the original tuple field to the new tuple field.
- SILInstruction *newValue = newCallInst;
+ SILValue newValue = newCallInst;
if (loweredCalleeConv.getNumDirectSILResults() > 1) {
- assert(newCallInst->getType().is<TupleType>());
+ assert(newValue->getType().is<TupleType>());
newValue = resultBuilder.createTupleExtract(
- extractInst->getLoc(), newCallInst,
+ extractInst->getLoc(), newValue,
newDirectResultIndices[origResultIdx]);
}
extractInst->replaceAllUsesWith(newValue);
@@ -1148,8 +1161,8 @@
}
SILValue origFullResult = returnInst->getOperand();
returnInst->setOperand(newReturnVal);
- if (auto *fullResultInst = dyn_cast<SILInstruction>(origFullResult)) {
- if (fullResultInst->use_empty())
+ if (auto *fullResultInst = origFullResult->getDefiningInstruction()) {
+ if (!fullResultInst->hasUsesOfAnyResult())
pass.markDead(fullResultInst);
}
}
@@ -1160,8 +1173,9 @@
namespace {
class AddressOnlyUseRewriter
- : SILInstructionVisitor<AddressOnlyUseRewriter, void> {
- friend SILVisitor<AddressOnlyUseRewriter, void>;
+ : SILInstructionVisitor<AddressOnlyUseRewriter> {
+ friend SILVisitorBase<AddressOnlyUseRewriter>;
+ friend SILInstructionVisitor<AddressOnlyUseRewriter>;
AddressLoweringState &pass;
@@ -1182,22 +1196,21 @@
}
protected:
- void markRewritten(SILValue addr) {
- auto &storage = pass.valueStorageMap.getStorage(currOper->getUser());
+ void markRewritten(SILValue oldValue, SILValue addr) {
+ auto &storage = pass.valueStorageMap.getStorage(oldValue);
storage.storageAddress = addr;
storage.markRewritten();
}
- void beforeVisit(ValueBase *V) {
- DEBUG(llvm::dbgs() << " REWRITE USE "; V->dump());
+ void beforeVisit(SILInstruction *I) {
+ DEBUG(llvm::dbgs() << " REWRITE USE "; I->dump());
- auto *I = cast<SILInstruction>(V);
B.setInsertionPoint(I);
B.setCurrentDebugScope(I->getDebugScope());
}
- void visitValueBase(ValueBase *V) {
- DEBUG(V->dump());
+ void visitSILInstruction(SILInstruction *I) {
+ DEBUG(I->dump());
llvm_unreachable("Unimplemented?!");
}
@@ -1217,7 +1230,7 @@
SILValue destAddr = addrMat.materializeAddress(copyInst);
B.createCopyAddr(copyInst->getLoc(), srcAddr, destAddr, IsNotTake,
IsInitialization);
- markRewritten(destAddr);
+ markRewritten(copyInst, destAddr);
}
void visitDebugValueInst(DebugValueInst *debugInst) {
@@ -1298,8 +1311,9 @@
namespace {
class AddressOnlyDefRewriter
- : SILInstructionVisitor<AddressOnlyDefRewriter, void> {
- friend SILVisitor<AddressOnlyDefRewriter, void>;
+ : SILInstructionVisitor<AddressOnlyDefRewriter> {
+ friend SILVisitorBase<AddressOnlyDefRewriter>;
+ friend SILInstructionVisitor<AddressOnlyDefRewriter>;
AddressLoweringState &pass;
@@ -1317,24 +1331,27 @@
void visitInst(SILInstruction *inst) { visit(inst); }
protected:
- void beforeVisit(ValueBase *V) {
- storage = &pass.valueStorageMap.getStorage(V);
+ void beforeVisit(SILInstruction *I) {
+ // This cast succeeds beecause only specific instructions get added to
+ // the value storage map.
+ storage = &pass.valueStorageMap.getStorage(cast<SingleValueInstruction>(I));
- DEBUG(llvm::dbgs() << "REWRITE DEF "; V->dump());
+ DEBUG(llvm::dbgs() << "REWRITE DEF "; I->dump());
if (storage->storageAddress)
DEBUG(llvm::dbgs() << " STORAGE "; storage->storageAddress->dump());
- auto *I = cast<SILInstruction>(V);
B.setInsertionPoint(I);
B.setCurrentDebugScope(I->getDebugScope());
}
- void visitValueBase(ValueBase *V) {
- DEBUG(V->dump());
+ void visitSILInstruction(SILInstruction *I) {
+ DEBUG(I->dump());
llvm_unreachable("Unimplemented?!");
}
void visitApplyInst(ApplyInst *applyInst) {
+ assert(isa<SingleValueInstruction>(applyInst) &&
+ "beforeVisit assumes that ApplyInst is an SVI");
assert(!storage->isRewritten());
// Completely rewrite the apply instruction, handling any remaining
// (loadable) indirect parameters, allocating memory for indirect
@@ -1420,8 +1437,7 @@
// This must be an indirect result for an apply that has not yet been
// rewritten. Rewrite the apply.
SILValue srcVal = extractInst->getOperand();
- assert(ApplySite::isa(srcVal));
- ApplyRewriter(cast<SILInstruction>(srcVal), pass)
+ ApplyRewriter(cast<ApplyInst>(srcVal), pass)
.convertApplyWithIndirectResults();
assert(storage->storageAddress);
@@ -1436,7 +1452,8 @@
for (auto &valueStorageI : pass.valueStorageMap) {
SILValue valueDef = valueStorageI.first;
- if (auto *defInst = dyn_cast<SILInstruction>(valueDef))
+ // TODO: MultiValueInstruction: ApplyInst
+ if (auto *defInst = dyn_cast<SingleValueInstruction>(valueDef))
defVisitor.visitInst(defInst);
SmallVector<Operand *, 8> uses(valueDef->getUses());
@@ -1445,12 +1462,11 @@
}
// Rewrite any remaining (loadable) indirect parameters.
- for (SILInstruction *applyInst : pass.indirectApplies) {
- ApplySite apply(applyInst);
+ for (ApplySite apply : pass.indirectApplies) {
// Calls with indirect formal results have already been rewritten.
if (apply.getSubstCalleeType()->hasIndirectFormalResults()) {
bool isRewritten = false;
- visitCallResults(apply, [&](SILInstruction *result) {
+ visitCallResults(apply, [&](SILValue result) {
if (result->getType().isAddressOnly(pass.F->getModule())) {
assert(pass.valueStorageMap.getStorage(result).isRewritten());
isRewritten = true;
@@ -1459,13 +1475,13 @@
return true;
});
if (!isRewritten) {
- ApplyRewriter rewriter(applyInst, pass);
+ ApplyRewriter rewriter(apply, pass);
rewriter.rewriteParameters();
rewriter.convertApplyWithIndirectResults();
continue;
}
}
- ApplyRewriter(applyInst, pass).rewriteParameters();
+ ApplyRewriter(apply, pass).rewriteParameters();
}
if (pass.F->getLoweredFunctionType()->hasIndirectFormalResults())
ReturnRewriter(pass).rewriteReturns();
@@ -1506,14 +1522,16 @@
// Add the rest of the instructions to the dead list in post order.
// FIXME: make sure we cleaned up address-only BB arguments.
for (auto &valueStorageI : reversed(pass.valueStorageMap)) {
- auto *deadInst = dyn_cast<SILInstruction>(valueStorageI.first);
+ // TODO: MultiValueInstruction: ApplyInst
+ auto *deadInst = dyn_cast<SingleValueInstruction>(valueStorageI.first);
if (!deadInst)
continue;
DEBUG(llvm::dbgs() << "DEAD "; deadInst->dump());
#ifndef NDEBUG
- for (Operand *operand : deadInst->getUses())
- assert(pass.instsToDelete.count(operand->getUser()));
+ for (auto result : deadInst->getResults())
+ for (Operand *operand : result->getUses())
+ assert(pass.instsToDelete.count(operand->getUser()));
#endif
pass.instsToDelete.insert(deadInst);
}
diff --git a/lib/SILOptimizer/Mandatory/ConstantPropagation.cpp b/lib/SILOptimizer/Mandatory/ConstantPropagation.cpp
index 71157e4..8202e9e 100644
--- a/lib/SILOptimizer/Mandatory/ConstantPropagation.cpp
+++ b/lib/SILOptimizer/Mandatory/ConstantPropagation.cpp
@@ -36,9 +36,8 @@
}
/// \brief Construct (int, overflow) result tuple.
-static SILInstruction *constructResultWithOverflowTuple(BuiltinInst *BI,
- APInt Res,
- bool Overflow) {
+static SILValue constructResultWithOverflowTuple(BuiltinInst *BI,
+ APInt Res, bool Overflow) {
// Get the SIL subtypes of the returned tuple type.
SILType FuncResType = BI->getType();
assert(FuncResType.castTo<TupleType>()->getNumElements() == 2);
@@ -57,7 +56,7 @@
}
/// \brief Fold arithmetic intrinsics with overflow.
-static SILInstruction *
+static SILValue
constantFoldBinaryWithOverflow(BuiltinInst *BI, llvm::Intrinsic::ID ID,
bool ReportOverflow,
Optional<bool> &ResultsInError) {
@@ -159,7 +158,7 @@
return constructResultWithOverflowTuple(BI, Res, Overflow);
}
-static SILInstruction *
+static SILValue
constantFoldBinaryWithOverflow(BuiltinInst *BI, BuiltinValueKind ID,
Optional<bool> &ResultsInError) {
OperandValueArrayRef Args = BI->getArguments();
@@ -170,9 +169,8 @@
ResultsInError);
}
-static SILInstruction *constantFoldIntrinsic(BuiltinInst *BI,
- llvm::Intrinsic::ID ID,
- Optional<bool> &ResultsInError) {
+static SILValue constantFoldIntrinsic(BuiltinInst *BI, llvm::Intrinsic::ID ID,
+ Optional<bool> &ResultsInError) {
switch (ID) {
default: break;
case llvm::Intrinsic::expect: {
@@ -224,8 +222,7 @@
return nullptr;
}
-static SILInstruction *constantFoldCompare(BuiltinInst *BI,
- BuiltinValueKind ID) {
+static SILValue constantFoldCompare(BuiltinInst *BI, BuiltinValueKind ID) {
OperandValueArrayRef Args = BI->getArguments();
// Fold for integer constant arguments.
@@ -394,7 +391,7 @@
return nullptr;
}
-static SILInstruction *
+static SILValue
constantFoldAndCheckDivision(BuiltinInst *BI, BuiltinValueKind ID,
Optional<bool> &ResultsInError) {
assert(ID == BuiltinValueKind::SDiv ||
@@ -462,9 +459,9 @@
///
/// The list of operations we constant fold might not be complete. Start with
/// folding the operations used by the standard library.
-static SILInstruction *constantFoldBinary(BuiltinInst *BI,
- BuiltinValueKind ID,
- Optional<bool> &ResultsInError) {
+static SILValue constantFoldBinary(BuiltinInst *BI,
+ BuiltinValueKind ID,
+ Optional<bool> &ResultsInError) {
switch (ID) {
default:
llvm_unreachable("Not all BUILTIN_BINARY_OPERATIONs are covered!");
@@ -573,7 +570,7 @@
return std::pair<bool, bool>(SrcTySigned, DstTySigned);
}
-static SILInstruction *
+static SILValue
constantFoldAndCheckIntegerConversions(BuiltinInst *BI,
const BuiltinInfo &Builtin,
Optional<bool> &ResultsInError) {
@@ -753,8 +750,8 @@
}
-static SILInstruction *constantFoldBuiltin(BuiltinInst *BI,
- Optional<bool> &ResultsInError) {
+static SILValue constantFoldBuiltin(BuiltinInst *BI,
+ Optional<bool> &ResultsInError) {
const IntrinsicInfo &Intrinsic = BI->getIntrinsicInfo();
SILModule &M = BI->getModule();
@@ -971,7 +968,8 @@
SILValue Val = Op.get();
Op.drop();
if (Val->use_empty()) {
- auto *DeadI = dyn_cast<SILInstruction>(Val);
+ auto *DeadI = Val->getDefiningInstruction();
+ assert(DeadI);
recursivelyDeleteTriviallyDeadInstructions(DeadI, /*force*/ true,
RemoveCallback);
WorkList.remove(DeadI);
@@ -996,7 +994,7 @@
llvm::SetVector<SILInstruction *> &WorkList) {
for (auto &BB : F) {
for (auto &I : BB) {
- if (isFoldable(&I) && !I.use_empty()) {
+ if (isFoldable(&I) && I.hasUsesOfAnyResult()) {
WorkList.insert(&I);
continue;
}
@@ -1051,7 +1049,7 @@
llvm::SetVector<SILInstruction *> FoldedUsers;
CastOptimizer CastOpt(
- [&](SILInstruction *I, ValueBase *V) { /* ReplaceInstUsesAction */
+ [&](SingleValueInstruction *I, ValueBase *V) { /* ReplaceInstUsesAction */
InvalidateInstructions = true;
I->replaceAllUsesWith(V);
@@ -1122,20 +1120,23 @@
isa<UnconditionalCheckedCastAddrInst>(I)) {
// Try to perform cast optimizations. Invalidation is handled by a
// callback inside the cast optimizer.
- ValueBase *Result = nullptr;
+ SILInstruction *Result = nullptr;
switch(I->getKind()) {
default:
llvm_unreachable("Unexpected instruction for cast optimizations");
- case ValueKind::CheckedCastBranchInst:
+ case SILInstructionKind::CheckedCastBranchInst:
Result = CastOpt.simplifyCheckedCastBranchInst(cast<CheckedCastBranchInst>(I));
break;
- case ValueKind::CheckedCastAddrBranchInst:
+ case SILInstructionKind::CheckedCastAddrBranchInst:
Result = CastOpt.simplifyCheckedCastAddrBranchInst(cast<CheckedCastAddrBranchInst>(I));
break;
- case ValueKind::UnconditionalCheckedCastInst:
- Result = CastOpt.optimizeUnconditionalCheckedCastInst(cast<UnconditionalCheckedCastInst>(I));
+ case SILInstructionKind::UnconditionalCheckedCastInst: {
+ auto Value =
+ CastOpt.optimizeUnconditionalCheckedCastInst(cast<UnconditionalCheckedCastInst>(I));
+ if (Value) Result = Value->getDefiningInstruction();
break;
- case ValueKind::UnconditionalCheckedCastAddrInst:
+ }
+ case SILInstructionKind::UnconditionalCheckedCastAddrInst:
Result = CastOpt.optimizeUnconditionalCheckedCastAddrInst(cast<UnconditionalCheckedCastAddrInst>(I));
break;
}
@@ -1145,15 +1146,16 @@
isa<CheckedCastAddrBranchInst>(Result) ||
isa<UnconditionalCheckedCastInst>(Result) ||
isa<UnconditionalCheckedCastAddrInst>(Result))
- WorkList.insert(cast<SILInstruction>(Result));
+ WorkList.insert(Result);
}
continue;
}
// Go through all users of the constant and try to fold them.
+ // TODO: MultiValueInstruction
FoldedUsers.clear();
- for (auto Use : I->getUses()) {
+ for (auto Use : cast<SingleValueInstruction>(I)->getUses()) {
SILInstruction *User = Use->getUser();
DEBUG(llvm::dbgs() << " User: " << *User);
@@ -1200,6 +1202,10 @@
if (!C)
continue;
+ // We can currently only do this constant-folding of single-value
+ // instructions.
+ auto UserV = cast<SingleValueInstruction>(User);
+
// Ok, we have succeeded. Add user to the FoldedUsers list and perform the
// necessary cleanups, RAUWs, etc.
FoldedUsers.insert(User);
@@ -1211,7 +1217,7 @@
// any tuple_extract instructions using the apply. This is a common case
// for functions returning multiple values.
if (auto *TI = dyn_cast<TupleInst>(C)) {
- for (auto UI = User->use_begin(), E = User->use_end(); UI != E;) {
+ for (auto UI = UserV->use_begin(), E = UserV->use_end(); UI != E;) {
Operand *O = *UI++;
// If the user is a tuple_extract, just substitute the right value in.
@@ -1220,21 +1226,21 @@
TEI->replaceAllUsesWith(NewVal);
TEI->dropAllReferences();
FoldedUsers.insert(TEI);
- if (auto *Inst = dyn_cast<SILInstruction>(NewVal))
+ if (auto *Inst = NewVal->getDefiningInstruction())
WorkList.insert(Inst);
}
}
- if (User->use_empty())
+ if (UserV->use_empty())
FoldedUsers.insert(TI);
}
// We were able to fold, so all users should use the new folded value.
- User->replaceAllUsesWith(C);
+ UserV->replaceAllUsesWith(C);
// The new constant could be further folded now, add it to the worklist.
- if (auto *Inst = dyn_cast<SILInstruction>(C))
+ if (auto *Inst = C->getDefiningInstruction())
WorkList.insert(Inst);
}
diff --git a/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp b/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp
index 42dc987..f0f6248 100644
--- a/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp
+++ b/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp
@@ -43,7 +43,7 @@
}
-DIMemoryObjectInfo::DIMemoryObjectInfo(SILInstruction *MI) {
+DIMemoryObjectInfo::DIMemoryObjectInfo(SingleValueInstruction *MI) {
auto &Module = MI->getModule();
MemoryInst = MI;
@@ -338,7 +338,7 @@
continue;
if (auto project = dyn_cast<ProjectBoxInst>(User)) {
- collectUses(User, project->getFieldIndex());
+ collectUses(project, project->getFieldIndex());
continue;
}
@@ -392,8 +392,8 @@
}
// Look through begin_access.
- if (isa<BeginAccessInst>(User)) {
- collectUses(User, BaseEltNo);
+ if (auto I = dyn_cast<BeginAccessInst>(User)) {
+ collectUses(I, BaseEltNo);
continue;
}
@@ -550,14 +550,14 @@
// that is looking into the memory object (i.e., the memory object needs to
// be explicitly initialized by a copy_addr or some other use of the
// projected address).
- if (isa<InitEnumDataAddrInst>(User)) {
+ if (auto I = dyn_cast<InitEnumDataAddrInst>(User)) {
assert(!InStructSubElement &&
"init_enum_data_addr shouldn't apply to struct subelements");
// Keep track of the fact that we're inside of an enum. This informs our
// recursion that tuple stores are not scalarized outside, and that stores
// should not be treated as partial stores.
llvm::SaveAndRestore<bool> X(InEnumSubElement, true);
- collectUses(User, BaseEltNo);
+ collectUses(I, BaseEltNo);
continue;
}
@@ -609,7 +609,7 @@
// Now that we've walked all of the immediate uses, scalarize any operations
// working on tuples if we need to for canonicalization or analysis reasons.
if (!UsesToScalarize.empty()) {
- SILInstruction *PointerInst = cast<SILInstruction>(Pointer);
+ SILInstruction *PointerInst = Pointer->getDefiningInstruction();
SmallVector<SILValue, 4> ElementAddrs;
SILBuilderWithScope AddrBuilder(++SILBasicBlock::iterator(PointerInst),
PointerInst);
diff --git a/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.h b/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.h
index 43bb692..1a3021a 100644
--- a/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.h
+++ b/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.h
@@ -49,7 +49,7 @@
public:
/// This is the instruction that represents the memory. It is either an
/// allocation (alloc_box, alloc_stack) or a mark_uninitialized.
- SILInstruction *MemoryInst;
+ SingleValueInstruction *MemoryInst;
/// This is the base type of the memory allocation.
SILType MemorySILType;
@@ -64,7 +64,7 @@
unsigned NumElements;
public:
- DIMemoryObjectInfo(SILInstruction *MemoryInst);
+ DIMemoryObjectInfo(SingleValueInstruction *MemoryInst);
SILLocation getLoc() const { return MemoryInst->getLoc(); }
SILFunction &getFunction() const { return *MemoryInst->getFunction(); }
@@ -76,7 +76,7 @@
return MemorySILType.getSwiftRValueType();
}
- SILInstruction *getAddress() const {
+ SingleValueInstruction *getAddress() const {
if (isa<AllocStackInst>(MemoryInst))
return MemoryInst;
assert(false);
diff --git a/lib/SILOptimizer/Mandatory/DIMemoryUseCollectorOwnership.cpp b/lib/SILOptimizer/Mandatory/DIMemoryUseCollectorOwnership.cpp
index 7415453..80a5fe0 100644
--- a/lib/SILOptimizer/Mandatory/DIMemoryUseCollectorOwnership.cpp
+++ b/lib/SILOptimizer/Mandatory/DIMemoryUseCollectorOwnership.cpp
@@ -90,7 +90,8 @@
return {MemorySILType, VDecl->isLet()};
}
-DIMemoryObjectInfo::DIMemoryObjectInfo(SILInstruction *MI) : MemoryInst(MI) {
+DIMemoryObjectInfo::DIMemoryObjectInfo(SingleValueInstruction *MI)
+ : MemoryInst(MI) {
auto &Module = MI->getModule();
std::tie(MemorySILType, IsLet) = computeMemorySILType(MemoryInst);
@@ -418,10 +419,12 @@
if (!isa<SelectEnumInst>(User) && !isa<SelectEnumAddrInst>(User))
continue;
- if (!User->hasOneUse())
+ auto value = cast<SingleValueInstruction>(User);
+
+ if (!value->hasOneUse())
continue;
- User = User->use_begin()->getUser();
+ User = value->use_begin()->getUser();
if (auto *CBI = dyn_cast<CondBranchInst>(User)) {
trackFailureBlock(MemoryInfo, CBI, CBI->getTrueBB());
return;
@@ -668,7 +671,7 @@
continue;
if (auto *PBI = dyn_cast<ProjectBoxInst>(User)) {
- collectUses(User, PBI->getFieldIndex());
+ collectUses(PBI, PBI->getFieldIndex());
continue;
}
@@ -736,7 +739,8 @@
// Look through begin_access and begin_borrow
if (isa<BeginAccessInst>(User) || isa<BeginBorrowInst>(User)) {
- collectUses(User, BaseEltNo);
+ auto begin = cast<SingleValueInstruction>(User);
+ collectUses(begin, BaseEltNo);
continue;
}
@@ -917,14 +921,14 @@
// that is looking into the memory object (i.e., the memory object needs to
// be explicitly initialized by a copy_addr or some other use of the
// projected address).
- if (isa<InitEnumDataAddrInst>(User)) {
+ if (auto init = dyn_cast<InitEnumDataAddrInst>(User)) {
assert(!InStructSubElement &&
"init_enum_data_addr shouldn't apply to struct subelements");
// Keep track of the fact that we're inside of an enum. This informs our
// recursion that tuple stores are not scalarized outside, and that stores
// should not be treated as partial stores.
llvm::SaveAndRestore<bool> X(InEnumSubElement, true);
- collectUses(User, BaseEltNo);
+ collectUses(init, BaseEltNo);
continue;
}
@@ -974,7 +978,7 @@
// Now that we've walked all of the immediate uses, scalarize any operations
// working on tuples if we need to for canonicalization or analysis reasons.
if (!UsesToScalarize.empty()) {
- SILInstruction *PointerInst = cast<SILInstruction>(Pointer);
+ SILInstruction *PointerInst = Pointer->getDefiningInstruction();
SmallVector<SILValue, 4> ElementAddrs;
SILBuilderWithScope AddrBuilder(++SILBasicBlock::iterator(PointerInst),
PointerInst);
@@ -1103,7 +1107,8 @@
// Loads of the box produce self, so collect uses from them.
if (isa<LoadInst>(User) || isa<LoadBorrowInst>(User)) {
- collectClassSelfUses(User, TheMemory.MemorySILType, EltNumbering);
+ auto load = cast<SingleValueInstruction>(User);
+ collectClassSelfUses(load, TheMemory.MemorySILType, EltNumbering);
continue;
}
@@ -1385,7 +1390,8 @@
// Look through begin_borrow and unchecked_ref_cast.
if (isa<BeginBorrowInst>(UCIOpUser) ||
isa<UncheckedRefCastInst>(UCIOpUser)) {
- copy(UCIOpUser->getUses(), std::back_inserter(Worklist));
+ auto I = cast<SingleValueInstruction>(UCIOpUser);
+ copy(I->getUses(), std::back_inserter(Worklist));
continue;
}
@@ -1474,14 +1480,15 @@
}
// Otherwise, look through the upcast and continue.
- std::copy(User->use_begin(), User->use_end(),
+ std::copy(UCI->use_begin(), UCI->use_end(),
std::back_inserter(Worklist));
continue;
}
// Look through begin_borrow and copy_value.
if (isa<BeginBorrowInst>(User) || isa<CopyValueInst>(User)) {
- std::copy(User->use_begin(), User->use_end(),
+ auto value = cast<SingleValueInstruction>(User);
+ std::copy(value->use_begin(), value->use_end(),
std::back_inserter(Worklist));
continue;
}
@@ -1527,7 +1534,7 @@
// *NOTE* Even though this takes a SILInstruction it actually only accepts
// load_borrow and load instructions. This is enforced via an assert.
void collectDelegatingClassInitSelfLoadUses(MarkUninitializedInst *MUI,
- SILInstruction *LI);
+ SingleValueInstruction *LI);
};
} // end anonymous namespace
@@ -1583,7 +1590,7 @@
// Stores *to* the allocation are writes. If the value being stored is a
// call to self.init()... then we have a self.init call.
if (auto *AI = dyn_cast<AssignInst>(User)) {
- if (auto *AssignSource = dyn_cast<SILInstruction>(AI->getOperand(0))) {
+ if (auto *AssignSource = AI->getOperand(0)->getDefiningInstruction()) {
if (isSelfInitUse(AssignSource)) {
UseInfo.trackUse(DIMemoryUse(User, DIUseKind::SelfInit, 0, 1));
continue;
@@ -1607,7 +1614,8 @@
// Loads of the box produce self, so collect uses from them.
if (isa<LoadInst>(User) || isa<LoadBorrowInst>(User)) {
- collectDelegatingClassInitSelfLoadUses(MUI, User);
+ collectDelegatingClassInitSelfLoadUses(MUI,
+ cast<SingleValueInstruction>(User));
continue;
}
@@ -1667,7 +1675,7 @@
// Stores *to* the allocation are writes. If the value being stored is a
// call to self.init()... then we have a self.init call.
if (auto *AI = dyn_cast<AssignInst>(User)) {
- if (auto *AssignSource = dyn_cast<SILInstruction>(AI->getOperand(0)))
+ if (auto *AssignSource = AI->getOperand(0)->getDefiningInstruction())
if (isSelfInitUse(AssignSource))
Kind = DIUseKind::SelfInit;
if (auto *AssignSource = dyn_cast<SILArgument>(AI->getOperand(0))) {
@@ -1692,7 +1700,7 @@
}
void DelegatingInitElementUseCollector::collectDelegatingClassInitSelfLoadUses(
- MarkUninitializedInst *MUI, SILInstruction *LI) {
+ MarkUninitializedInst *MUI, SingleValueInstruction *LI) {
assert(isa<LoadBorrowInst>(LI) || isa<LoadInst>(LI));
// If we have a load, then this is a use of the box. Look at the uses of
@@ -1712,8 +1720,8 @@
continue;
// Look through begin_borrow.
- if (isa<BeginBorrowInst>(User)) {
- std::copy(User->use_begin(), User->use_end(),
+ if (auto borrow = dyn_cast<BeginBorrowInst>(User)) {
+ std::copy(borrow->use_begin(), borrow->use_end(),
std::back_inserter(Worklist));
continue;
}
diff --git a/lib/SILOptimizer/Mandatory/DIMemoryUseCollectorOwnership.h b/lib/SILOptimizer/Mandatory/DIMemoryUseCollectorOwnership.h
index da3800d..bc07e9e 100644
--- a/lib/SILOptimizer/Mandatory/DIMemoryUseCollectorOwnership.h
+++ b/lib/SILOptimizer/Mandatory/DIMemoryUseCollectorOwnership.h
@@ -55,7 +55,7 @@
public:
/// This is the instruction that represents the memory. It is either an
/// allocation (alloc_box, alloc_stack) or a mark_uninitialized.
- SILInstruction *MemoryInst;
+ SingleValueInstruction *MemoryInst;
/// This is the base type of the memory allocation.
SILType MemorySILType;
@@ -70,7 +70,7 @@
unsigned NumElements;
public:
- DIMemoryObjectInfo(SILInstruction *MemoryInst);
+ DIMemoryObjectInfo(SingleValueInstruction *MemoryInst);
SILLocation getLoc() const { return MemoryInst->getLoc(); }
SILFunction &getFunction() const { return *MemoryInst->getFunction(); }
@@ -80,7 +80,7 @@
CanType getType() const { return MemorySILType.getSwiftRValueType(); }
- SILInstruction *getAddress() const {
+ SingleValueInstruction *getAddress() const {
if (isa<MarkUninitializedInst>(MemoryInst) ||
isa<AllocStackInst>(MemoryInst))
return MemoryInst;
diff --git a/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp b/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp
index f6fe944..3142757 100644
--- a/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp
+++ b/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp
@@ -1327,15 +1327,15 @@
continue;
// Look through upcasts.
- if (isa<UpcastInst>(BBIOpUser)) {
- std::copy(BBIOpUser->use_begin(), BBIOpUser->use_end(),
+ if (auto upcast = dyn_cast<UpcastInst>(BBIOpUser)) {
+ std::copy(upcast->use_begin(), upcast->use_end(),
std::back_inserter(Worklist));
continue;
}
// Look through unchecked_ref_cast.
- if (isa<UncheckedRefCastInst>(BBIOpUser)) {
- std::copy(BBIOpUser->use_begin(), BBIOpUser->use_end(),
+ if (auto cast = dyn_cast<UncheckedRefCastInst>(BBIOpUser)) {
+ std::copy(cast->use_begin(), cast->use_end(),
std::back_inserter(Worklist));
continue;
}
@@ -1496,7 +1496,7 @@
auto *LI = Inst;
bool hasReturnUse = false, hasUnknownUses = false;
- for (auto LoadUse : LI->getUses()) {
+ for (auto LoadUse : cast<SingleValueInstruction>(LI)->getUses()) {
auto *User = LoadUse->getUser();
// Ignore retains of the struct/enum before the return.
@@ -1892,7 +1892,7 @@
SILInstruction *Release = Destroys[ReleaseID];
if (isa<DestroyAddrInst>(Release)) {
SILValue Addr = Release->getOperand(0);
- if (auto *AddrI = dyn_cast<SILInstruction>(Addr))
+ if (auto *AddrI = Addr->getDefiningInstruction())
recursivelyDeleteTriviallyDeadInstructions(AddrI);
}
Release->eraseFromParent();
diff --git a/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp b/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp
index 184a953..dd776f8 100644
--- a/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp
+++ b/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp
@@ -790,7 +790,7 @@
case ValueKind::RefTailAddrInst:
case ValueKind::TailAddrInst:
case ValueKind::IndexAddrInst:
- Iter = cast<SILInstruction>(Iter)->getOperand(0);
+ Iter = cast<SingleValueInstruction>(Iter)->getOperand(0);
continue;
// Base address producers.
diff --git a/lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp b/lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp
index f3301a6..5f914d3 100644
--- a/lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp
+++ b/lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp
@@ -192,11 +192,10 @@
// Process conditional branches with constant conditions.
if (auto *CBI = dyn_cast<CondBranchInst>(TI)) {
SILValue V = CBI->getCondition();
- auto *CondI = dyn_cast<SILInstruction>(V);
SILLocation Loc = CBI->getLoc();
if (IntegerLiteralInst *ConstCond =
- dyn_cast_or_null<IntegerLiteralInst>(CondI)) {
+ dyn_cast_or_null<IntegerLiteralInst>(V)) {
SILBuilderWithScope B(&BB, CBI);
// Determine which of the successors is unreachable and create a new
@@ -399,18 +398,20 @@
}
static void setOutsideBlockUsesToUndef(SILInstruction *I) {
- if (I->use_empty())
- return;
+ if (!I->hasUsesOfAnyResult())
+ return;
SILBasicBlock *BB = I->getParent();
SILModule &Mod = BB->getModule();
// Replace all uses outside of I's basic block by undef.
- llvm::SmallVector<Operand *, 16> Uses(I->use_begin(), I->use_end());
+ llvm::SmallVector<Operand *, 16> Uses;
+ for (auto result : I->getResults())
+ Uses.append(result->use_begin(), result->use_end());
+
for (auto *Use : Uses)
- if (auto *User = dyn_cast<SILInstruction>(Use->getUser()))
- if (User->getParent() != BB)
- Use->set(SILUndef::get(Use->get()->getType(), Mod));
+ if (Use->getUser()->getParent() != BB)
+ Use->set(SILUndef::get(Use->get()->getType(), Mod));
}
static SILInstruction *getAsCallToNoReturn(SILInstruction *I) {
diff --git a/lib/SILOptimizer/Mandatory/GuaranteedARCOpts.cpp b/lib/SILOptimizer/Mandatory/GuaranteedARCOpts.cpp
index 94d6cdf..4b1f57d 100644
--- a/lib/SILOptimizer/Mandatory/GuaranteedARCOpts.cpp
+++ b/lib/SILOptimizer/Mandatory/GuaranteedARCOpts.cpp
@@ -24,7 +24,7 @@
struct GuaranteedARCOptsVisitor
: SILInstructionVisitor<GuaranteedARCOptsVisitor, bool> {
- bool visitValueBase(ValueBase *V) { return false; }
+ bool visitSILInstruction(SILInstruction *I) { return false; }
bool visitDestroyAddrInst(DestroyAddrInst *DAI);
bool visitStrongReleaseInst(StrongReleaseInst *SRI);
bool visitDestroyValueInst(DestroyValueInst *DVI);
diff --git a/lib/SILOptimizer/Mandatory/MandatoryInlining.cpp b/lib/SILOptimizer/Mandatory/MandatoryInlining.cpp
index 0c603bf..9e56867 100644
--- a/lib/SILOptimizer/Mandatory/MandatoryInlining.cpp
+++ b/lib/SILOptimizer/Mandatory/MandatoryInlining.cpp
@@ -62,8 +62,8 @@
bool needsNotifications() override { return true; }
// Handle notifications about removals of instructions.
- void handleDeleteNotification(swift::ValueBase *Value) override {
- if (auto DeletedI = dyn_cast<SILInstruction>(Value)) {
+ void handleDeleteNotification(SILNode *node) override {
+ if (auto DeletedI = dyn_cast<SILInstruction>(node)) {
if (CurrentI == SILBasicBlock::iterator(DeletedI)) {
if (CurrentI != CurrentI->getParent()->begin()) {
--CurrentI;
@@ -164,10 +164,10 @@
ArrayRef<SILValue> FullArgs) {
SmallVector<SILInstruction*, 16> InstsToDelete;
for (SILValue V : FullArgs) {
- if (auto *I = dyn_cast<SILInstruction>(V))
- if (I != CalleeValue &&
- isInstructionTriviallyDead(I))
- InstsToDelete.push_back(I);
+ if (V != CalleeValue)
+ if (auto *I = V->getDefiningInstruction())
+ if (isInstructionTriviallyDead(I))
+ InstsToDelete.push_back(I);
}
recursivelyDeleteTriviallyDeadInstructions(InstsToDelete, true);
@@ -337,11 +337,11 @@
return std::make_tuple(InnerAI, I);
replaceDeadApply(InnerAI, NewInst);
- if (auto *II = dyn_cast<SILInstruction>(NewInst))
- I = II->getIterator();
- else
- I = NewInst->getParentBlock()->begin();
- auto NewAI = FullApplySite::isa(NewInstPair.second.getInstruction());
+
+ auto newApplyAI = NewInstPair.second.getInstruction();
+ assert(newApplyAI && "devirtualized but removed apply site?");
+ I = newApplyAI->getIterator();
+ auto NewAI = FullApplySite::isa(newApplyAI);
// *NOTE*, it is important that we return I here since we may have
// devirtualized but not have a full apply site anymore.
if (!NewAI)
diff --git a/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp b/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp
index ae811e4..0eba2c4 100644
--- a/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp
+++ b/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp
@@ -72,8 +72,6 @@
Pointer = SEAI->getOperand();
else if (auto BAI = dyn_cast<BeginAccessInst>(Pointer))
Pointer = BAI->getSource();
- else if (auto BUAI = dyn_cast<BeginUnpairedAccessInst>(Pointer))
- Pointer = BUAI->getSource();
else
return Pointer;
}
@@ -92,7 +90,8 @@
///
/// If this pointer is to within an existential projection, it returns ~0U.
///
-static unsigned computeSubelement(SILValue Pointer, SILInstruction *RootInst) {
+static unsigned computeSubelement(SILValue Pointer,
+ SingleValueInstruction *RootInst) {
unsigned SubEltNumber = 0;
SILModule &M = RootInst->getModule();
@@ -101,22 +100,17 @@
if (RootInst == Pointer)
return SubEltNumber;
- auto *Inst = cast<SILInstruction>(Pointer);
- if (auto *PBI = dyn_cast<ProjectBoxInst>(Inst)) {
+ if (auto *PBI = dyn_cast<ProjectBoxInst>(Pointer)) {
Pointer = PBI->getOperand();
continue;
}
- if (auto *BAI = dyn_cast<BeginAccessInst>(Inst)) {
+ if (auto *BAI = dyn_cast<BeginAccessInst>(Pointer)) {
Pointer = BAI->getSource();
continue;
}
- if (auto *BUAI = dyn_cast<BeginUnpairedAccessInst>(Inst)) {
- Pointer = BUAI->getSource();
- continue;
- }
- if (auto *TEAI = dyn_cast<TupleElementAddrInst>(Inst)) {
+ if (auto *TEAI = dyn_cast<TupleElementAddrInst>(Pointer)) {
SILType TT = TEAI->getOperand()->getType();
// Keep track of what subelement is being referenced.
@@ -127,7 +121,7 @@
continue;
}
- if (auto *SEAI = dyn_cast<StructElementAddrInst>(Inst)) {
+ if (auto *SEAI = dyn_cast<StructElementAddrInst>(Pointer)) {
SILType ST = SEAI->getOperand()->getType();
// Keep track of what subelement is being referenced.
@@ -142,7 +136,7 @@
}
- assert((isa<InitExistentialAddrInst>(Inst) || isa<InjectEnumAddrInst>(Inst))&&
+ assert(isa<InitExistentialAddrInst>(Pointer) &&
"Unknown access path instruction");
// Cannot promote loads and stores from within an existential projection.
return ~0U;
@@ -207,7 +201,7 @@
SILModule &Module;
/// TheMemory - This is either an alloc_box or alloc_stack instruction.
- SILInstruction *TheMemory;
+ AllocationInst *TheMemory;
/// This is the SILType of the memory object.
SILType MemoryType;
@@ -229,7 +223,7 @@
bool HasAnyEscape = false;
public:
- AllocOptimize(SILInstruction *TheMemory,
+ AllocOptimize(AllocationInst *TheMemory,
SmallVectorImpl<DIMemoryUse> &Uses,
SmallVectorImpl<SILInstruction*> &Releases);
@@ -263,7 +257,7 @@
} // end anonymous namespace
-AllocOptimize::AllocOptimize(SILInstruction *TheMemory,
+AllocOptimize::AllocOptimize(AllocationInst *TheMemory,
SmallVectorImpl<DIMemoryUse> &Uses,
SmallVectorImpl<SILInstruction*> &Releases)
: Module(TheMemory->getModule()), TheMemory(TheMemory), Uses(Uses),
@@ -626,25 +620,30 @@
// diagnostics pass this like one.
// We only handle load and copy_addr right now.
+ SILValue src;
if (auto CAI = dyn_cast<CopyAddrInst>(Inst)) {
// If this is a CopyAddr, verify that the element type is loadable. If not,
// we can't explode to a load.
- if (!CAI->getSrc()->getType().isLoadable(Module))
+ src = CAI->getSrc();
+ if (!src->getType().isLoadable(Module))
return false;
- } else if (!isa<LoadInst>(Inst))
+ } else if (auto load = dyn_cast<LoadInst>(Inst)) {
+ src = load->getOperand();
+ } else {
return false;
-
+ }
+
// If the box has escaped at this instruction, we can't safely promote the
// load.
if (hasEscapedAt(Inst))
return false;
- SILType LoadTy = Inst->getOperand(0)->getType().getObjectType();
+ SILType LoadTy = src->getType().getObjectType();
// If this is a load/copy_addr from a struct field that we want to promote,
// compute the access path down to the field so we can determine precise
// def/use behavior.
- unsigned FirstElt = computeSubelement(Inst->getOperand(0), TheMemory);
+ unsigned FirstElt = computeSubelement(src, TheMemory);
// If this is a load from within an enum projection, we can't promote it since
// we don't track subelements in a type that could be changing.
@@ -692,20 +691,20 @@
// Aggregate together all of the subelements into something that has the same
// type as the load did, and emit smaller) loads for any subelements that were
// not available.
- auto NewVal = AggregateAvailableValues(Inst, LoadTy, Inst->getOperand(0),
+ auto Load = cast<LoadInst>(Inst);
+ auto NewVal = AggregateAvailableValues(Load, LoadTy, Load->getOperand(),
AvailableValues, FirstElt);
++NumLoadPromoted;
// Simply replace the load.
- assert(isa<LoadInst>(Inst));
- DEBUG(llvm::dbgs() << " *** Promoting load: " << *Inst << "\n");
+ DEBUG(llvm::dbgs() << " *** Promoting load: " << *Load << "\n");
DEBUG(llvm::dbgs() << " To value: " << *NewVal << "\n");
- Inst->replaceAllUsesWith(NewVal);
- SILValue Addr = Inst->getOperand(0);
- Inst->eraseFromParent();
- if (auto *AddrI = dyn_cast<SILInstruction>(Addr))
+ Load->replaceAllUsesWith(NewVal);
+ SILValue Addr = Load->getOperand();
+ Load->eraseFromParent();
+ if (auto *AddrI = Addr->getDefiningInstruction())
recursivelyDeleteTriviallyDeadInstructions(AddrI);
return true;
}
@@ -833,7 +832,7 @@
NewInst->dump();
llvm_unreachable("Unknown instruction generated by copy_addr lowering");
- case ValueKind::StoreInst:
+ case SILInstructionKind::StoreInst:
// If it is a store to the memory object (as oppose to a store to
// something else), track it as an access.
if (StoreUse.isValid()) {
@@ -843,7 +842,7 @@
}
continue;
- case ValueKind::LoadInst:
+ case SILInstructionKind::LoadInst:
// If it is a load from the memory object (as oppose to a load from
// something else), track it as an access. We need to explicitly check to
// see if the load accesses "TheMemory" because it could either be a load
@@ -856,12 +855,12 @@
}
continue;
- case ValueKind::RetainValueInst:
- case ValueKind::StrongRetainInst:
- case ValueKind::StrongReleaseInst:
- case ValueKind::UnownedRetainInst:
- case ValueKind::UnownedReleaseInst:
- case ValueKind::ReleaseValueInst: // Destroy overwritten value
+ case SILInstructionKind::RetainValueInst:
+ case SILInstructionKind::StrongRetainInst:
+ case SILInstructionKind::StrongReleaseInst:
+ case SILInstructionKind::UnownedRetainInst:
+ case SILInstructionKind::UnownedReleaseInst:
+ case SILInstructionKind::ReleaseValueInst: // Destroy overwritten value
// These are ignored.
continue;
}
@@ -994,9 +993,10 @@
++I;
continue;
}
+ auto Alloc = cast<AllocationInst>(Inst);
- DEBUG(llvm::dbgs() << "*** DI Optimize looking at: " << *Inst << "\n");
- DIMemoryObjectInfo MemInfo(Inst);
+ DEBUG(llvm::dbgs() << "*** DI Optimize looking at: " << *Alloc << "\n");
+ DIMemoryObjectInfo MemInfo(Alloc);
// Set up the datastructure used to collect the uses of the allocation.
SmallVector<DIMemoryUse, 16> Uses;
@@ -1005,12 +1005,12 @@
// Walk the use list of the pointer, collecting them.
collectDIElementUsesFrom(MemInfo, Uses, Releases);
- Changed |= AllocOptimize(Inst, Uses, Releases).doIt();
+ Changed |= AllocOptimize(Alloc, Uses, Releases).doIt();
// Carefully move iterator to avoid invalidation problems.
++I;
- if (Inst->use_empty()) {
- Inst->eraseFromParent();
+ if (Alloc->use_empty()) {
+ Alloc->eraseFromParent();
++NumAllocRemoved;
Changed = true;
}
diff --git a/lib/SILOptimizer/PassManager/PassManager.cpp b/lib/SILOptimizer/PassManager/PassManager.cpp
index 5aa0f81..736ca54 100644
--- a/lib/SILOptimizer/PassManager/PassManager.cpp
+++ b/lib/SILOptimizer/PassManager/PassManager.cpp
@@ -291,12 +291,12 @@
assert(analysesUnlocked() && "Expected all analyses to be unlocked!");
- PrettyStackTraceSILFunctionTransform X(SFT, NumPassesRun);
- DebugPrintEnabler DebugPrint(NumPassesRun);
-
SFT->injectPassManager(this);
SFT->injectFunction(F);
+ PrettyStackTraceSILFunctionTransform X(SFT, NumPassesRun);
+ DebugPrintEnabler DebugPrint(NumPassesRun);
+
// If nothing changed since the last run of this pass, we can skip this
// pass.
CompletedPasses &completedPasses = CompletedPassesMap[F];
@@ -440,12 +440,12 @@
const SILOptions &Options = getOptions();
- PrettyStackTraceSILModuleTransform X(SMT, NumPassesRun);
- DebugPrintEnabler DebugPrint(NumPassesRun);
-
SMT->injectPassManager(this);
SMT->injectModule(Mod);
+ PrettyStackTraceSILModuleTransform X(SMT, NumPassesRun);
+ DebugPrintEnabler DebugPrint(NumPassesRun);
+
updateSILModuleStatsBeforeTransform(*Mod, SMT, *this, NumPassesRun);
CurrentPassHasInvalidated = false;
@@ -719,7 +719,7 @@
std::vector<Node> Nodes;
/// The SILValue IDs which are printed as edge source labels.
- llvm::DenseMap<const ValueBase *, unsigned> InstToIDMap;
+ llvm::DenseMap<const SILNode *, unsigned> InstToIDMap;
typedef std::vector<Node>::iterator iterator;
};
diff --git a/lib/SILOptimizer/SILCombiner/SILCombine.cpp b/lib/SILOptimizer/SILCombiner/SILCombine.cpp
index 0df5c69..53a653d 100644
--- a/lib/SILOptimizer/SILCombiner/SILCombine.cpp
+++ b/lib/SILOptimizer/SILCombiner/SILCombine.cpp
@@ -150,7 +150,7 @@
<< " New = " << *Result << '\n');
// Everything uses the new instruction now.
- replaceInstUsesWith(*I, Result);
+ replaceInstUsesWith(*cast<SingleValueInstruction>(I), Result);
// Push the new instruction and any users onto the worklist.
Worklist.addUsersToWorklist(Result);
@@ -181,12 +181,11 @@
<< " New = " << *Result << '\n');
// Everything uses the new instruction now.
- replaceInstUsesWith(*I, Result);
+ replaceInstUsesPairwiseWith(I, Result);
// Push the new instruction and any users onto the worklist.
Worklist.add(Result);
- Worklist.addUsersToWorklist(Result);
-
+ Worklist.addUsersOfAllResultsToWorklist(Result);
eraseInstFromFunction(*I);
} else {
@@ -199,7 +198,7 @@
eraseInstFromFunction(*I);
} else {
Worklist.add(I);
- Worklist.addUsersToWorklist(I);
+ Worklist.addUsersOfAllResultsToWorklist(I);
}
}
MadeChange = true;
@@ -266,16 +265,31 @@
// replaceable with another preexisting expression. Here we add all uses of I
// to the worklist, replace all uses of I with the new value, then return I,
// so that the combiner will know that I was modified.
-SILInstruction *SILCombiner::replaceInstUsesWith(SILInstruction &I,
- ValueBase *V) {
+void SILCombiner::replaceInstUsesWith(SingleValueInstruction &I, ValueBase *V) {
Worklist.addUsersToWorklist(&I); // Add all modified instrs to worklist.
DEBUG(llvm::dbgs() << "SC: Replacing " << I << "\n"
" with " << *V << '\n');
I.replaceAllUsesWith(V);
+}
- return &I;
+/// Replace all of the results of the old instruction with the
+/// corresponding results of the new instruction.
+void SILCombiner::replaceInstUsesPairwiseWith(SILInstruction *oldI,
+ SILInstruction *newI) {
+ DEBUG(llvm::dbgs() << "SC: Replacing " << *oldI << "\n"
+ " with " << *newI << '\n');
+
+ auto oldResults = oldI->getResults();
+ auto newResults = newI->getResults();
+ assert(oldResults.size() == newResults.size());
+ for (auto i : indices(oldResults)) {
+ // Add all modified instrs to worklist.
+ Worklist.addUsersToWorklist(oldResults[i]);
+
+ oldResults[i]->replaceAllUsesWith(newResults[i]);
+ }
}
// Some instructions can never be "trivially dead" due to side effects or
@@ -289,12 +303,14 @@
bool AddOperandsToWorklist) {
DEBUG(llvm::dbgs() << "SC: ERASE " << I << '\n');
- assert(onlyHaveDebugUses(&I) && "Cannot erase instruction that is used!");
+ assert(onlyHaveDebugUsesOfAllResults(&I) &&
+ "Cannot erase instruction that is used!");
+
// Make sure that we reprocess all operands now that we reduced their
// use counts.
if (I.getNumOperands() < 8 && AddOperandsToWorklist) {
for (auto &OpI : I.getAllOperands()) {
- if (auto *Op = llvm::dyn_cast<SILInstruction>(&*OpI.get())) {
+ if (auto *Op = OpI.get()->getDefiningInstruction()) {
DEBUG(llvm::dbgs() << "SC: add op " << *Op <<
" from erased inst to worklist\n");
Worklist.add(Op);
@@ -302,8 +318,9 @@
}
}
- for (Operand *DU : getDebugUses(&I))
- Worklist.remove(DU->getUser());
+ for (auto result : I.getResults())
+ for (Operand *DU : getDebugUses(result))
+ Worklist.remove(DU->getUser());
Worklist.remove(&I);
eraseFromParentWithDebugInsts(&I, InstIter);
@@ -339,7 +356,10 @@
}
}
- void handleDeleteNotification(ValueBase *I) override {
+ void handleDeleteNotification(SILNode *node) override {
+ auto I = dyn_cast<SILInstruction>(node);
+ if (!I) return;
+
// Linear searching the tracking list doesn't hurt because usually it only
// contains a few elements.
auto Iter = std::find(TrackingList.begin(), TrackingList.end(), I);
diff --git a/lib/SILOptimizer/SILCombiner/SILCombiner.h b/lib/SILOptimizer/SILCombiner/SILCombiner.h
index c5786b2..9fd6333 100644
--- a/lib/SILOptimizer/SILCombiner/SILCombiner.h
+++ b/lib/SILOptimizer/SILCombiner/SILCombiner.h
@@ -51,10 +51,8 @@
/// If the given ValueBase is a SILInstruction add it to the worklist.
void addValue(ValueBase *V) {
- auto *I = dyn_cast<SILInstruction>(V);
- if (!I)
- return;
- add(I);
+ if (auto *I = V->getDefiningInstruction())
+ add(I);
}
/// Add the given list of instructions in reverse order to the worklist. This
@@ -82,13 +80,22 @@
}
/// When an instruction has been simplified, add all of its users to the
- /// worklist since additional simplifications of its users may have been
+ /// worklist, since additional simplifications of its users may have been
/// exposed.
void addUsersToWorklist(ValueBase *I) {
for (auto UI : I->getUses())
add(UI->getUser());
}
+ /// When an instruction has been simplified, add all of its users to the
+ /// worklist, since additional simplifications of its users may have been
+ /// exposed.
+ void addUsersOfAllResultsToWorklist(SILInstruction *I) {
+ for (auto result : I->getResults()) {
+ addUsersToWorklist(result);
+ }
+ }
+
/// Check that the worklist is empty and nuke the backing store for the map if
/// it is large.
void zap() {
@@ -130,7 +137,7 @@
: AA(AA), Worklist(), MadeChange(false), RemoveCondFails(removeCondFails),
Iteration(0), Builder(B),
CastOpt(/* ReplaceInstUsesAction */
- [&](SILInstruction *I, ValueBase * V) {
+ [&](SingleValueInstruction *I, ValueBase * V) {
replaceInstUsesWith(*I, V);
},
/* EraseAction */
@@ -152,7 +159,9 @@
// replaceable with another preexisting expression. Here we add all uses of I
// to the worklist, replace all uses of I with the new value, then return I,
// so that the combiner will know that I was modified.
- SILInstruction *replaceInstUsesWith(SILInstruction &I, ValueBase *V);
+ void replaceInstUsesWith(SingleValueInstruction &I, ValueBase *V);
+
+ void replaceInstUsesPairwiseWith(SILInstruction *oldI, SILInstruction *newI);
// Some instructions can never be "trivially dead" due to side effects or
// producing a void value. In those cases, since we cannot rely on
@@ -175,7 +184,7 @@
}
/// Base visitor that does not do anything.
- SILInstruction *visitValueBase(ValueBase *V) { return nullptr; }
+ SILInstruction *visitSILInstruction(SILInstruction *I) { return nullptr; }
/// Instruction visitors.
SILInstruction *visitReleaseValueInst(ReleaseValueInst *DI);
diff --git a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
index d57ad29..16a7ba2 100644
--- a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
+++ b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
@@ -342,7 +342,9 @@
Builder.createStrongRelease(AI.getLoc(), PAI, Builder.getDefaultAtomicity());
}
- SilCombiner->replaceInstUsesWith(*AI.getInstruction(), NAI.getInstruction());
+ if (auto apply = dyn_cast<ApplyInst>(AI))
+ SilCombiner->replaceInstUsesWith(*apply,
+ cast<ApplyInst>(NAI.getInstruction()));
SilCombiner->eraseInstFromFunction(*AI.getInstruction());
return true;
}
@@ -477,6 +479,7 @@
for (auto *Use : Value->getUses()) {
SILInstruction *Inst = Use->getUser();
if (isa<RefCountingInst>(Inst) ||
+ isa<StrongPinInst>(Inst) ||
isa<DebugValueInst>(Inst)) {
Uses.push_back(Inst);
continue;
@@ -485,7 +488,7 @@
isa<StructExtractInst>(Inst) ||
isa<PointerToAddressInst>(Inst)) {
Uses.push_back(Inst);
- if (recursivelyCollectARCUsers(Uses, Inst))
+ if (recursivelyCollectARCUsers(Uses, cast<SingleValueInstruction>(Inst)))
continue;
}
return false;
@@ -616,7 +619,7 @@
return getAddressOfStackInit(ASI, CAI);
return CAISrc;
}
- return SingleWrite;
+ return cast<InitExistentialAddrInst>(SingleWrite);
}
/// Find the init_existential, which could be used to determine a concrete
@@ -744,8 +747,8 @@
NewAI = Builder.createApply(AI.getLoc(), AI.getCallee(), Substitutions,
Args, cast<ApplyInst>(AI)->isNonThrowing());
- if (isa<ApplyInst>(NewAI))
- replaceInstUsesWith(*AI.getInstruction(), NewAI.getInstruction());
+ if (auto apply = dyn_cast<ApplyInst>(NewAI))
+ replaceInstUsesWith(*cast<ApplyInst>(AI.getInstruction()), apply);
eraseInstFromFunction(*AI.getInstruction());
return NewAI.getInstruction();
@@ -753,7 +756,8 @@
/// Derive a concrete type of self and conformance from the init_existential
/// instruction.
-static Optional<std::tuple<ProtocolConformanceRef, CanType, SILValue, SILValue>>
+static Optional<std::tuple<ProtocolConformanceRef, CanType,
+ SingleValueInstruction*, SILValue>>
getConformanceAndConcreteType(ASTContext &Ctx,
FullApplySite AI,
SILInstruction *InitExistential,
@@ -763,7 +767,7 @@
CanType ConcreteType;
// The existential type result of the found init_existential.
CanType ExistentialType;
- SILValue ConcreteTypeDef;
+ SingleValueInstruction *ConcreteTypeDef = nullptr;
SILValue NewSelf;
// FIXME: Factor this out. All we really need here is the ExistentialSig
@@ -812,7 +816,8 @@
if (ConcreteType->isOpenedExistential()) {
assert(!InitExistential->getTypeDependentOperands().empty() &&
"init_existential is supposed to have a typedef operand");
- ConcreteTypeDef = InitExistential->getTypeDependentOperands()[0].get();
+ ConcreteTypeDef = cast<SingleValueInstruction>(
+ InitExistential->getTypeDependentOperands()[0].get());
}
return std::make_tuple(*ExactConformance, ConcreteType,
@@ -863,7 +868,7 @@
ProtocolConformanceRef Conformance = std::get<0>(*ConformanceAndConcreteType);
CanType ConcreteType = std::get<1>(*ConformanceAndConcreteType);
- SILValue ConcreteTypeDef = std::get<2>(*ConformanceAndConcreteType);
+ auto ConcreteTypeDef = std::get<2>(*ConformanceAndConcreteType);
SILValue NewSelf = std::get<3>(*ConformanceAndConcreteType);
SILOpenedArchetypesTracker *OldOpenedArchetypesTracker =
diff --git a/lib/SILOptimizer/SILCombiner/SILCombinerBuiltinVisitors.cpp b/lib/SILOptimizer/SILCombiner/SILCombinerBuiltinVisitors.cpp
index ab63eed..81f2492 100644
--- a/lib/SILOptimizer/SILCombiner/SILCombinerBuiltinVisitors.cpp
+++ b/lib/SILOptimizer/SILCombiner/SILCombinerBuiltinVisitors.cpp
@@ -287,12 +287,12 @@
/// Given an index_raw_pointer Ptr, size_of(Metatype) * Distance create an
/// address_to_pointer (index_addr ptr, Distance : $*Metatype) : $RawPointer
/// instruction.
-static SILInstruction *createIndexAddrFrom(IndexRawPointerInst *I,
- MetatypeInst *Metatype,
- BuiltinInst *TruncOrBitCast,
- SILValue Ptr, SILValue Distance,
- SILType RawPointerTy,
- SILBuilder &Builder) {
+static SILValue createIndexAddrFrom(IndexRawPointerInst *I,
+ MetatypeInst *Metatype,
+ BuiltinInst *TruncOrBitCast,
+ SILValue Ptr, SILValue Distance,
+ SILType RawPointerTy,
+ SILBuilder &Builder) {
Builder.setCurrentDebugScope(I->getDebugScope());
SILType InstanceType =
Metatype->getType().getMetatypeInstanceType(I->getModule());
@@ -408,9 +408,11 @@
getBitOpArgs(Prev, op, prevBits)) {
combine(bits, prevBits);
}
- if (isNeutral(bits))
+ if (isNeutral(bits)) {
// The bit operation has no effect, e.g. x | 0 -> x
- return C->replaceInstUsesWith(*BI, op);
+ C->replaceInstUsesWith(*BI, op);
+ return BI;
+ }
if (isZero(bits))
// The bit operation yields to a constant, e.g. x & 0 -> 0
diff --git a/lib/SILOptimizer/SILCombiner/SILCombinerCastVisitors.cpp b/lib/SILOptimizer/SILCombiner/SILCombinerCastVisitors.cpp
index 84f9934..3072069 100644
--- a/lib/SILOptimizer/SILCombiner/SILCombinerCastVisitors.cpp
+++ b/lib/SILOptimizer/SILCombiner/SILCombinerCastVisitors.cpp
@@ -524,7 +524,8 @@
auto Converted = CFI->getConverted();
while (!CFI->use_empty()) {
auto *Use = *(CFI->use_begin());
- assert(!Use->getUser()->hasValue() && "Did not expect user with a result!");
+ assert(Use->getUser()->getResults().empty() &&
+ "Did not expect user with a result!");
Use->set(Converted);
}
diff --git a/lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp b/lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp
index 0bf6a53..7f6c5eb 100644
--- a/lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp
+++ b/lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp
@@ -431,7 +431,7 @@
// Erase the 'live-range'
for (auto *Inst : ToDelete) {
- Inst->replaceAllUsesWithUndef();
+ Inst->replaceAllUsesOfAllResultsWithUndef();
eraseInstFromFunction(*Inst);
}
return eraseInstFromFunction(*AS);
@@ -477,7 +477,7 @@
// Given a load with multiple struct_extracts/tuple_extracts and no other
// uses, canonicalize the load into several (struct_element_addr (load))
// pairs.
- using ProjInstPairTy = std::pair<Projection, SILInstruction *>;
+ using ProjInstPairTy = std::pair<Projection, SingleValueInstruction *>;
// Go through the loads uses and add any users that are projections to the
// projection list.
@@ -489,7 +489,8 @@
if (!isa<StructExtractInst>(User) && !isa<TupleExtractInst>(User))
return nullptr;
- Projections.push_back({Projection(User), User});
+ auto extract = cast<SingleValueInstruction>(User);
+ Projections.push_back({Projection(extract), extract});
}
// The reason why we sort the list is so that we will process projections with
@@ -667,7 +668,7 @@
for (auto *Inst : ToRemove) {
// Replace any still-remaining uses with undef and erase.
- Inst->replaceAllUsesWithUndef();
+ Inst->replaceAllUsesOfAllResultsWithUndef();
eraseInstFromFunction(*Inst);
}
@@ -1055,7 +1056,7 @@
for (auto *Inst : ToRemove) {
// Replace any still-remaining uses with undef values and erase.
- Inst->replaceAllUsesWithUndef();
+ Inst->replaceAllUsesOfAllResultsWithUndef();
eraseInstFromFunction(*Inst);
}
@@ -1358,7 +1359,7 @@
if (auto *UC = dyn_cast<UpcastInst>(MDVal))
MDVal = UC->getOperand();
- SILInstruction *NewInst = nullptr;
+ SingleValueInstruction *NewInst = nullptr;
if (auto *MI = dyn_cast<MetatypeInst>(MDVal)) {
auto &Mod = ARDI->getModule();
auto SILInstanceTy = MI->getType().getMetatypeInstanceType(Mod);
diff --git a/lib/SILOptimizer/Transforms/ARCCodeMotion.cpp b/lib/SILOptimizer/Transforms/ARCCodeMotion.cpp
index e5f8d10..f8642e2 100644
--- a/lib/SILOptimizer/Transforms/ARCCodeMotion.cpp
+++ b/lib/SILOptimizer/Transforms/ARCCodeMotion.cpp
@@ -653,7 +653,7 @@
//
// We can not move a release above the instruction that defines the
// released value.
- if (II == Ptr)
+ if (II == Ptr->getDefiningInstruction())
return true;
// Identical RC root blocks code motion, we will be able to move this release
// further once we move the blocking release.
diff --git a/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp b/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp
index dee5158..b457d15 100644
--- a/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp
+++ b/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp
@@ -141,7 +141,8 @@
// If we have a copy value or a mark_uninitialized, add its uses to the work
// list and continue.
if (isa<MarkUninitializedInst>(User) || isa<CopyValueInst>(User)) {
- copy(User->getUses(), std::back_inserter(Worklist));
+ copy(cast<SingleValueInstruction>(User)->getUses(),
+ std::back_inserter(Worklist));
continue;
}
@@ -212,8 +213,8 @@
// If we have a copy_value, the copy value does not cause an escape, but its
// uses might do so... so add the copy_value's uses to the worklist and
// continue.
- if (isa<CopyValueInst>(User)) {
- copy(User->getUses(), std::back_inserter(Worklist));
+ if (auto CVI = dyn_cast<CopyValueInst>(User)) {
+ copy(CVI->getUses(), std::back_inserter(Worklist));
continue;
}
@@ -385,7 +386,8 @@
// If our user instruction is a copy_value or a marked_uninitialized, visit
// the users recursively.
if (isa<MarkUninitializedInst>(User) || isa<CopyValueInst>(User)) {
- copy(User->getUses(), std::back_inserter(Worklist));
+ copy(cast<SingleValueInstruction>(User)->getUses(),
+ std::back_inserter(Worklist));
continue;
}
@@ -514,11 +516,11 @@
// Look through any mark_uninitialized, copy_values.
if (isa<MarkUninitializedInst>(User) || isa<CopyValueInst>(User)) {
- transform(User->getUses(), std::back_inserter(Worklist),
+ auto Inst = cast<SingleValueInstruction>(User);
+ transform(Inst->getUses(), std::back_inserter(Worklist),
[](Operand *Op) -> SILInstruction * { return Op->getUser(); });
- User->replaceAllUsesWith(
- SILUndef::get(User->getType(), User->getModule()));
- User->eraseFromParent();
+ Inst->replaceAllUsesWithUndef();
+ Inst->eraseFromParent();
continue;
}
@@ -538,7 +540,7 @@
/// promoting some of its box parameters to stack addresses.
class PromotedParamCloner : public SILClonerWithScopes<PromotedParamCloner> {
public:
- friend class SILVisitor<PromotedParamCloner>;
+ friend class SILInstructionVisitor<PromotedParamCloner>;
friend class SILCloner<PromotedParamCloner>;
PromotedParamCloner(SILFunction *Orig, IsSerialized_t Serialized,
@@ -639,8 +641,9 @@
auto *Fn = M.createFunction(
SILLinkage::Shared, ClonedName, ClonedTy, Orig->getGenericEnvironment(),
Orig->getLocation(), Orig->isBare(), IsNotTransparent, Serialized,
- Orig->isThunk(), Orig->getClassSubclassScope(), Orig->getInlineStrategy(),
- Orig->getEffectsKind(), Orig, Orig->getDebugScope());
+ Orig->getEntryCount(), Orig->isThunk(), Orig->getClassSubclassScope(),
+ Orig->getInlineStrategy(), Orig->getEffectsKind(), Orig,
+ Orig->getDebugScope());
for (auto &Attr : Orig->getSemanticsAttrs()) {
Fn->addSemanticsAttr(Attr);
}
@@ -811,7 +814,7 @@
// address because we've proven we can keep this value on the stack. The
// partial_apply had ownership of this box so we must now release it
// explicitly when the partial_apply is released.
- SILInstruction *Box = cast<SILInstruction>(O.get());
+ auto *Box = cast<SingleValueInstruction>(O.get());
assert((isa<AllocBoxInst>(Box) || isa<CopyValueInst>(Box)) &&
"Expected either an alloc box or a copy of an alloc box");
SILBuilder B(Box);
diff --git a/lib/SILOptimizer/Transforms/ArrayCountPropagation.cpp b/lib/SILOptimizer/Transforms/ArrayCountPropagation.cpp
index e82a519..87e44b8 100644
--- a/lib/SILOptimizer/Transforms/ArrayCountPropagation.cpp
+++ b/lib/SILOptimizer/Transforms/ArrayCountPropagation.cpp
@@ -123,7 +123,9 @@
for (auto *Opd : Def->getUses()) {
auto *User = Opd->getUser();
// Ignore reference counting and debug instructions.
- if (isa<RefCountingInst>(User) || isa<DebugValueInst>(User))
+ if (isa<RefCountingInst>(User) ||
+ isa<StrongPinInst>(User) ||
+ isa<DebugValueInst>(User))
continue;
// Array value projection.
@@ -134,11 +136,13 @@
}
// Check array semantic calls.
- ArraySemanticsCall ArrayOp(User);
- if (ArrayOp && ArrayOp.doesNotChangeArray()) {
- if (ArrayOp.getKind() == ArrayCallKind::kGetCount)
- CountCalls.insert(ArrayOp);
- continue;
+ if (auto apply = dyn_cast<ApplyInst>(User)) {
+ ArraySemanticsCall ArrayOp(apply);
+ if (ArrayOp && ArrayOp.doesNotChangeArray()) {
+ if (ArrayOp.getKind() == ArrayCallKind::kGetCount)
+ CountCalls.insert(ArrayOp);
+ continue;
+ }
}
// An operation that escapes or modifies the array value.
diff --git a/lib/SILOptimizer/Transforms/ArrayElementValuePropagation.cpp b/lib/SILOptimizer/Transforms/ArrayElementValuePropagation.cpp
index 522d673..be7f376 100644
--- a/lib/SILOptimizer/Transforms/ArrayElementValuePropagation.cpp
+++ b/lib/SILOptimizer/Transforms/ArrayElementValuePropagation.cpp
@@ -190,7 +190,9 @@
for (auto *Opd : Def->getUses()) {
auto *User = Opd->getUser();
// Ignore reference counting and debug instructions.
- if (isa<RefCountingInst>(User) || isa<DebugValueInst>(User))
+ if (isa<RefCountingInst>(User) ||
+ isa<StrongPinInst>(User) ||
+ isa<DebugValueInst>(User))
continue;
// Array value projection.
diff --git a/lib/SILOptimizer/Transforms/AssumeSingleThreaded.cpp b/lib/SILOptimizer/Transforms/AssumeSingleThreaded.cpp
index 5587520..ca3c528 100644
--- a/lib/SILOptimizer/Transforms/AssumeSingleThreaded.cpp
+++ b/lib/SILOptimizer/Transforms/AssumeSingleThreaded.cpp
@@ -45,6 +45,8 @@
for (auto &I : BB) {
if (auto RCInst = dyn_cast<RefCountingInst>(&I))
RCInst->setNonAtomic();
+ if (auto RCInst = dyn_cast<StrongPinInst>(&I))
+ RCInst->setNonAtomic();
}
}
invalidateAnalysis(SILAnalysis::InvalidationKind::Instructions);
diff --git a/lib/SILOptimizer/Transforms/CSE.cpp b/lib/SILOptimizer/Transforms/CSE.cpp
index 5684342..38aa71e 100644
--- a/lib/SILOptimizer/Transforms/CSE.cpp
+++ b/lib/SILOptimizer/Transforms/CSE.cpp
@@ -82,7 +82,7 @@
using hash_code = llvm::hash_code;
public:
- hash_code visitValueBase(ValueBase *) {
+ hash_code visitSILInstruction(SILInstruction *) {
llvm_unreachable("No hash implemented for the given type");
}
@@ -395,20 +395,18 @@
if (LHS.isSentinel() || RHS.isSentinel())
return LHSI == RHSI;
- if (isa<OpenExistentialRefInst>(LHSI) && isa<OpenExistentialRefInst>(RHSI)) {
- if (LHSI->getNumOperands() != RHSI->getNumOperands())
- return false;
-
+ auto LOpen = dyn_cast<OpenExistentialRefInst>(LHSI);
+ auto ROpen = dyn_cast<OpenExistentialRefInst>(RHSI);
+ if (LOpen && ROpen) {
// Check operands.
- for (unsigned i = 0, e = LHSI->getNumOperands(); i != e; ++i)
- if (LHSI->getOperand(i) != RHSI->getOperand(i))
- return false;
+ if (LOpen->getOperand() != ROpen->getOperand())
+ return false;
// Consider the types of two open_existential_ref instructions to be equal,
// if the sets of protocols they conform to are equal.
- auto LHSArchetypeTy = LHSI->getType().castTo<ArchetypeType>();
+ auto LHSArchetypeTy = LOpen->getType().castTo<ArchetypeType>();
auto LHSConformsTo = LHSArchetypeTy->getConformsTo();
- auto RHSArchetypeTy = RHSI->getType().castTo<ArchetypeType>();
+ auto RHSArchetypeTy = ROpen->getType().castTo<ArchetypeType>();
auto RHSConformsTo = RHSArchetypeTy->getConformsTo();
return LHSConformsTo == RHSConformsTo;
}
@@ -430,7 +428,7 @@
typedef llvm::ScopedHashTableVal<SimpleValue, ValueBase *> SimpleValueHTType;
typedef llvm::RecyclingAllocator<llvm::BumpPtrAllocator, SimpleValueHTType>
AllocatorTy;
- typedef llvm::ScopedHashTable<SimpleValue, ValueBase *,
+ typedef llvm::ScopedHashTable<SimpleValue, SILInstruction *,
llvm::DenseMapInfo<SimpleValue>,
AllocatorTy> ScopedHTType;
@@ -507,7 +505,7 @@
};
bool processNode(DominanceInfoNode *Node);
- bool processOpenExistentialRef(SILInstruction *Inst, ValueBase *V,
+ bool processOpenExistentialRef(OpenExistentialRefInst *Inst, ValueBase *V,
SILBasicBlock::iterator &I);
};
} // namespace swift
@@ -564,7 +562,7 @@
// is remapping the archetypes when it is required.
class InstructionCloner : public SILCloner<InstructionCloner> {
friend class SILCloner<InstructionCloner>;
- friend class SILVisitor<InstructionCloner>;
+ friend class SILInstructionVisitor<InstructionCloner>;
SILInstruction *Result = nullptr;
public:
InstructionCloner(SILFunction *F) : SILCloner(*F) {}
@@ -644,12 +642,15 @@
/// \Inst is the open_existential_ref instruction
/// \V is the dominating open_existential_ref instruction
/// \I is the iterator referring to the current instruction.
-bool CSE::processOpenExistentialRef(SILInstruction *Inst, ValueBase *V,
+bool CSE::processOpenExistentialRef(OpenExistentialRefInst *Inst, ValueBase *V,
SILBasicBlock::iterator &I) {
- assert(isa<OpenExistentialRefInst>(Inst));
+ // All the open instructions are single-value instructions.
+ auto VI = dyn_cast<SingleValueInstruction>(V);
+ if (!VI) return false;
+
llvm::SmallSetVector<SILInstruction *, 16> Candidates;
auto OldOpenedArchetype = getOpenedArchetypeOf(Inst);
- auto NewOpenedArchetype = getOpenedArchetypeOf(dyn_cast<SILInstruction>(V));
+ auto NewOpenedArchetype = getOpenedArchetypeOf(VI);
// Collect all candidates that may contain opened archetypes
// that need to be replaced.
@@ -684,7 +685,7 @@
// TODO: Move it to CSE instance to avoid recreating it every time?
SILOpenedArchetypesTracker OpenedArchetypesTracker(Inst->getFunction());
// Register the new archetype to be used.
- OpenedArchetypesTracker.registerOpenedArchetypes(dyn_cast<SILInstruction>(V));
+ OpenedArchetypesTracker.registerOpenedArchetypes(VI);
// Use a cloner. It makes copying the instruction and remapping of
// opened archetypes trivial.
InstructionCloner Cloner(I->getFunction());
@@ -700,22 +701,31 @@
auto Candidate = Candidates.pop_back_val();
if (Processed.count(Candidate))
continue;
- // True if a candidate depends on the old opened archetype.
- bool DependsOnOldOpenedArchetype = !Candidate->getTypeDependentOperands().empty();
- if (!Candidate->use_empty() &&
- Candidate->getType().hasOpenedExistential()) {
- // Check if the result type of the candidate depends on the opened
- // existential in question.
+
+ // Compute if a candidate depends on the old opened archetype.
+ // It always does if it has any type-dependent operands.
+ bool DependsOnOldOpenedArchetype =
+ !Candidate->getTypeDependentOperands().empty();
+
+ // Look for dependencies propagated via the candidate's results.
+ for (auto CandidateResult : Candidate->getResults()) {
+ if (CandidateResult->use_empty() ||
+ !CandidateResult->getType().hasOpenedExistential())
+ continue;
+
+ // Check if the result type depends on this specific opened existential.
auto ResultDependsOnOldOpenedArchetype =
- Candidate->getType().getSwiftRValueType().findIf(
+ CandidateResult->getType().getSwiftRValueType().findIf(
[&OldOpenedArchetype](Type t) -> bool {
return (CanType(t) == OldOpenedArchetype);
});
+
+ // If it does, the candidate depends on the opened existential.
if (ResultDependsOnOldOpenedArchetype) {
DependsOnOldOpenedArchetype |= ResultDependsOnOldOpenedArchetype;
- // We need to update uses of this candidate, because their types
- // may be affected.
- for (auto Use : Candidate->getUses()) {
+
+ // The users of this candidate are new candidates.
+ for (auto Use : CandidateResult->getUses()) {
Candidates.insert(Use->getUser());
}
}
@@ -733,7 +743,7 @@
auto NewI = Cloner.clone(Candidate);
// Result types of candidate's uses instructions may be using this archetype.
// Thus, we need to try to replace it there.
- Candidate->replaceAllUsesWith(NewI);
+ Candidate->replaceAllUsesPairwiseWith(NewI);
if (I == Candidate->getIterator())
I = NewI->getIterator();
eraseFromParentWithDebugInsts(Candidate, I);
@@ -767,7 +777,7 @@
if (SILValue V = simplifyInstruction(Inst)) {
DEBUG(llvm::dbgs() << "SILCSE SIMPLIFY: " << *Inst << " to: " << *V
<< '\n');
- Inst->replaceAllUsesWith(V);
+ cast<SingleValueInstruction>(Inst)->replaceAllUsesWith(V);
Inst->eraseFromParent();
Changed = true;
++NumSimplify;
@@ -786,14 +796,17 @@
// Now that we know we have an instruction we understand see if the
// instruction has an available value. If so, use it.
- if (ValueBase *V = AvailableValues->lookup(Inst)) {
- DEBUG(llvm::dbgs() << "SILCSE CSE: " << *Inst << " to: " << *V << '\n');
+ if (SILInstruction *AvailInst = AvailableValues->lookup(Inst)) {
+ DEBUG(llvm::dbgs() << "SILCSE CSE: " << *Inst << " to: " << *AvailInst
+ << '\n');
// Instructions producing a new opened archetype need a special handling,
// because replacing these instructions may require a replacement
// of the opened archetype type operands in some of the uses.
if (!isa<OpenExistentialRefInst>(Inst) ||
- processOpenExistentialRef(Inst, V, I)) {
- Inst->replaceAllUsesWith(V);
+ processOpenExistentialRef(cast<OpenExistentialRefInst>(Inst),
+ cast<OpenExistentialRefInst>(AvailInst),
+ I)) {
+ Inst->replaceAllUsesPairwiseWith(AvailInst);
Inst->eraseFromParent();
Changed = true;
++NumCSE;
@@ -859,58 +872,58 @@
return !EMI->getOperand()->getType().isAddress();
}
switch (Inst->getKind()) {
- case ValueKind::FunctionRefInst:
- case ValueKind::GlobalAddrInst:
- case ValueKind::IntegerLiteralInst:
- case ValueKind::FloatLiteralInst:
- case ValueKind::StringLiteralInst:
- case ValueKind::StructInst:
- case ValueKind::StructExtractInst:
- case ValueKind::StructElementAddrInst:
- case ValueKind::TupleInst:
- case ValueKind::TupleExtractInst:
- case ValueKind::TupleElementAddrInst:
- case ValueKind::MetatypeInst:
- case ValueKind::ValueMetatypeInst:
- case ValueKind::ObjCProtocolInst:
- case ValueKind::RefElementAddrInst:
- case ValueKind::RefTailAddrInst:
- case ValueKind::ProjectBoxInst:
- case ValueKind::IndexRawPointerInst:
- case ValueKind::IndexAddrInst:
- case ValueKind::PointerToAddressInst:
- case ValueKind::AddressToPointerInst:
- case ValueKind::CondFailInst:
- case ValueKind::EnumInst:
- case ValueKind::UncheckedEnumDataInst:
- case ValueKind::IsNonnullInst:
- case ValueKind::UncheckedTrivialBitCastInst:
- case ValueKind::UncheckedBitwiseCastInst:
- case ValueKind::RefToRawPointerInst:
- case ValueKind::RawPointerToRefInst:
- case ValueKind::RefToUnownedInst:
- case ValueKind::UnownedToRefInst:
- case ValueKind::RefToUnmanagedInst:
- case ValueKind::UnmanagedToRefInst:
- case ValueKind::UpcastInst:
- case ValueKind::ThickToObjCMetatypeInst:
- case ValueKind::ObjCToThickMetatypeInst:
- case ValueKind::UncheckedRefCastInst:
- case ValueKind::UncheckedAddrCastInst:
- case ValueKind::ObjCMetatypeToObjectInst:
- case ValueKind::ObjCExistentialMetatypeToObjectInst:
- case ValueKind::SelectEnumInst:
- case ValueKind::SelectValueInst:
- case ValueKind::RefToBridgeObjectInst:
- case ValueKind::BridgeObjectToRefInst:
- case ValueKind::BridgeObjectToWordInst:
- case ValueKind::ThinFunctionToPointerInst:
- case ValueKind::PointerToThinFunctionInst:
- case ValueKind::MarkDependenceInst:
- case ValueKind::OpenExistentialRefInst:
- return true;
- default:
- return false;
+ case SILInstructionKind::FunctionRefInst:
+ case SILInstructionKind::GlobalAddrInst:
+ case SILInstructionKind::IntegerLiteralInst:
+ case SILInstructionKind::FloatLiteralInst:
+ case SILInstructionKind::StringLiteralInst:
+ case SILInstructionKind::StructInst:
+ case SILInstructionKind::StructExtractInst:
+ case SILInstructionKind::StructElementAddrInst:
+ case SILInstructionKind::TupleInst:
+ case SILInstructionKind::TupleExtractInst:
+ case SILInstructionKind::TupleElementAddrInst:
+ case SILInstructionKind::MetatypeInst:
+ case SILInstructionKind::ValueMetatypeInst:
+ case SILInstructionKind::ObjCProtocolInst:
+ case SILInstructionKind::RefElementAddrInst:
+ case SILInstructionKind::RefTailAddrInst:
+ case SILInstructionKind::ProjectBoxInst:
+ case SILInstructionKind::IndexRawPointerInst:
+ case SILInstructionKind::IndexAddrInst:
+ case SILInstructionKind::PointerToAddressInst:
+ case SILInstructionKind::AddressToPointerInst:
+ case SILInstructionKind::CondFailInst:
+ case SILInstructionKind::EnumInst:
+ case SILInstructionKind::UncheckedEnumDataInst:
+ case SILInstructionKind::IsNonnullInst:
+ case SILInstructionKind::UncheckedTrivialBitCastInst:
+ case SILInstructionKind::UncheckedBitwiseCastInst:
+ case SILInstructionKind::RefToRawPointerInst:
+ case SILInstructionKind::RawPointerToRefInst:
+ case SILInstructionKind::RefToUnownedInst:
+ case SILInstructionKind::UnownedToRefInst:
+ case SILInstructionKind::RefToUnmanagedInst:
+ case SILInstructionKind::UnmanagedToRefInst:
+ case SILInstructionKind::UpcastInst:
+ case SILInstructionKind::ThickToObjCMetatypeInst:
+ case SILInstructionKind::ObjCToThickMetatypeInst:
+ case SILInstructionKind::UncheckedRefCastInst:
+ case SILInstructionKind::UncheckedAddrCastInst:
+ case SILInstructionKind::ObjCMetatypeToObjectInst:
+ case SILInstructionKind::ObjCExistentialMetatypeToObjectInst:
+ case SILInstructionKind::SelectEnumInst:
+ case SILInstructionKind::SelectValueInst:
+ case SILInstructionKind::RefToBridgeObjectInst:
+ case SILInstructionKind::BridgeObjectToRefInst:
+ case SILInstructionKind::BridgeObjectToWordInst:
+ case SILInstructionKind::ThinFunctionToPointerInst:
+ case SILInstructionKind::PointerToThinFunctionInst:
+ case SILInstructionKind::MarkDependenceInst:
+ case SILInstructionKind::OpenExistentialRefInst:
+ return true;
+ default:
+ return false;
}
}
diff --git a/lib/SILOptimizer/Transforms/CopyForwarding.cpp b/lib/SILOptimizer/Transforms/CopyForwarding.cpp
index 0221cb1..ec8ce27 100644
--- a/lib/SILOptimizer/Transforms/CopyForwarding.cpp
+++ b/lib/SILOptimizer/Transforms/CopyForwarding.cpp
@@ -481,19 +481,19 @@
continue;
}
switch (UserInst->getKind()) {
- case ValueKind::LoadInst:
+ case SILInstructionKind::LoadInst:
IsLoadedFrom = true;
SrcUserInsts.insert(UserInst);
break;
- case ValueKind::ExistentialMetatypeInst:
- case ValueKind::InjectEnumAddrInst:
- case ValueKind::StoreInst:
+ case SILInstructionKind::ExistentialMetatypeInst:
+ case SILInstructionKind::InjectEnumAddrInst:
+ case SILInstructionKind::StoreInst:
SrcUserInsts.insert(UserInst);
break;
- case ValueKind::DebugValueAddrInst:
+ case SILInstructionKind::DebugValueAddrInst:
SrcDebugValueInsts.insert(cast<DebugValueAddrInst>(UserInst));
break;
- case ValueKind::DeallocStackInst:
+ case SILInstructionKind::DeallocStackInst:
break;
default:
// Most likely one of:
@@ -914,10 +914,11 @@
findAddressRootAndUsers(ValueBase *Def,
SmallPtrSetImpl<SILInstruction*> &RootUserInsts) {
if (isa<InitEnumDataAddrInst>(Def) || isa<InitExistentialAddrInst>(Def)) {
- SILValue InitRoot = cast<SILInstruction>(Def)->getOperand(0);
+ auto InitInst = cast<SingleValueInstruction>(Def);
+ SILValue InitRoot = InitInst->getOperand(0);
for (auto *Use : InitRoot->getUses()) {
auto *UserInst = Use->getUser();
- if (UserInst == Def)
+ if (UserInst == InitInst)
continue;
RootUserInsts.insert(UserInst);
}
@@ -954,12 +955,13 @@
while (SI != SE) {
--SI;
SILInstruction *UserInst = &*SI;
- if (UserInst == CopyDestDef)
+ if (UserInst == CopyDestDef->getDefiningInstruction())
seenCopyDestDef = true;
// If we see another use of Dest, then Dest is live after the Src location
// is initialized, so we really need the copy.
- if (UserInst == CopyDestRoot || DestUserInsts.count(UserInst)
+ if (UserInst == CopyDestRoot->getDefiningInstruction()
+ || DestUserInsts.count(UserInst)
|| RootUserInsts.count(UserInst)) {
if (auto *DVAI = dyn_cast<DebugValueAddrInst>(UserInst)) {
DebugValueInstsToDelete.push_back(DVAI);
@@ -1004,7 +1006,7 @@
}
// Rematerialize the projection if needed by simply moving it.
if (seenCopyDestDef) {
- cast<SILInstruction>(CopyDestDef)->moveBefore(&*SI);
+ CopyDestDef->getDefiningInstruction()->moveBefore(&*SI);
}
// Now that an init was found, it is safe to substitute all recorded uses
// with the copy's dest.
@@ -1349,7 +1351,8 @@
{
AliasAnalysis *AA = nullptr;
- static bool collectLoads(SILInstruction *CurrentInst, SILInstruction *addr,
+ static bool collectLoads(SILInstruction *CurrentInst,
+ SingleValueInstruction *addr,
llvm::SmallPtrSetImpl<SILInstruction *> &loadInsts);
bool checkNoSourceModification(CopyAddrInst *copyInst,
@@ -1407,7 +1410,7 @@
/// Transitively explore all data flow uses of the given \p address until
/// reaching a load or returning false.
bool TempRValueOptPass::
-collectLoads(SILInstruction *user, SILInstruction *address,
+collectLoads(SILInstruction *user, SingleValueInstruction *address,
llvm::SmallPtrSetImpl<SILInstruction *> &loadInsts) {
// All normal uses (loads) must be in the initialization block.
// (The destroy and dealloc are commonly in a different block though.)
@@ -1428,23 +1431,26 @@
DEBUG(llvm::dbgs() << " Temp use may write/destroy its source" << *user);
return false;
- case ValueKind::StructElementAddrInst:
- case ValueKind::TupleElementAddrInst:
+ case SILInstructionKind::StructElementAddrInst:
+ case SILInstructionKind::TupleElementAddrInst: {
// Transitively look through projections on stack addresses.
- for (auto *useOper : user->getUses()) {
- if (!collectLoads(useOper->getUser(), user, loadInsts))
+ auto proj = cast<SingleValueInstruction>(user);
+ for (auto *useOper : proj->getUses()) {
+ if (!collectLoads(useOper->getUser(), proj, loadInsts))
return false;
}
return true;
+ }
- case ValueKind::LoadInst:
- case ValueKind::LoadBorrowInst:
+ case SILInstructionKind::LoadInst:
+ case SILInstructionKind::LoadBorrowInst: {
// Loads are the end of the data flow chain. The users of the load can't
// access the temporary storage.
loadInsts.insert(user);
return true;
+ }
- case ValueKind::CopyAddrInst: {
+ case SILInstructionKind::CopyAddrInst: {
// copy_addr which read from the temporary are like loads.
// TODO: Handle copy_addr [take]. But this doesn't seem to be important.
auto *copyFromTmp = cast<CopyAddrInst>(user);
@@ -1452,7 +1458,7 @@
DEBUG(llvm::dbgs() << " Temp written or taken" << *user);
return false;
}
- loadInsts.insert(user);
+ loadInsts.insert(copyFromTmp);
return true;
}
}
@@ -1538,20 +1544,20 @@
Operand *use = *tempObj->use_begin();
SILInstruction *user = use->getUser();
switch (user->getKind()) {
- case ValueKind::DestroyAddrInst:
- case ValueKind::DeallocStackInst:
- user->eraseFromParent();
- break;
- case ValueKind::CopyAddrInst:
- case ValueKind::StructElementAddrInst:
- case ValueKind::TupleElementAddrInst:
- case ValueKind::LoadInst:
- case ValueKind::LoadBorrowInst:
- use->set(copyInst->getSrc());
- break;
+ case SILInstructionKind::DestroyAddrInst:
+ case SILInstructionKind::DeallocStackInst:
+ user->eraseFromParent();
+ break;
+ case SILInstructionKind::CopyAddrInst:
+ case SILInstructionKind::StructElementAddrInst:
+ case SILInstructionKind::TupleElementAddrInst:
+ case SILInstructionKind::LoadInst:
+ case SILInstructionKind::LoadBorrowInst:
+ use->set(copyInst->getSrc());
+ break;
- default:
- llvm_unreachable("unhandled instruction");
+ default:
+ llvm_unreachable("unhandled instruction");
}
}
tempObj->eraseFromParent();
diff --git a/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp b/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp
index 767dd6a..df77071 100644
--- a/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp
+++ b/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp
@@ -73,7 +73,7 @@
class DCE : public SILFunctionTransform {
typedef llvm::DomTreeNodeBase<SILBasicBlock> PostDomTreeNode;
- llvm::SmallPtrSet<ValueBase *, 16> LiveValues;
+ llvm::SmallPtrSet<SILNode *, 16> LiveValues;
llvm::SmallPtrSet<SILBasicBlock *, 16> LiveBlocks;
llvm::SmallVector<SILInstruction *, 64> Worklist;
PostDominanceInfo *PDT;
@@ -160,7 +160,7 @@
unsigned computeMinPredecessorLevels(PostDomTreeNode *Node);
void insertControllingInfo(SILBasicBlock *Block, unsigned Level);
- void markValueLive(ValueBase *V);
+ void markValueLive(SILNode *V);
void markTerminatorArgsLive(SILBasicBlock *Pred, SILBasicBlock *Succ,
size_t ArgIndex);
void markControllingTerminatorsLive(SILBasicBlock *Block);
@@ -178,7 +178,8 @@
// Keep track of the fact that V is live and add it to our worklist
// so that we can process the values it depends on.
-void DCE::markValueLive(ValueBase *V) {
+void DCE::markValueLive(SILNode *V) {
+ V = V->getCanonicalSILNodeInObject();
if (LiveValues.count(V) || isa<SILUndef>(V))
return;
@@ -193,6 +194,8 @@
return;
}
+ // TODO: MultiValueInstruction
+
assert(isa<SILArgument>(V) &&
"Only expected instructions and arguments!");
@@ -239,7 +242,7 @@
// A fix_lifetime (with a non-address type) is only alive if it's
// definition is alive.
SILValue Op = FLI->getOperand();
- auto *OpInst = dyn_cast<SILInstruction>(Op);
+ auto *OpInst = Op->getDefiningInstruction();
if (OpInst && !Op->getType().isAddress()) {
addReverseDependency(OpInst, FLI);
} else {
@@ -363,8 +366,9 @@
// Conceptually, the dependency from a debug instruction to its definition
// is in reverse direction: Only if its definition is alive, also the
// debug_value instruction is alive.
- for (Operand *DU : getDebugUses(I))
- markValueLive(DU->getUser());
+ for (auto result : I->getResults())
+ for (Operand *DU : getDebugUses(result))
+ markValueLive(DU->getUser());
// Handle all other reverse-dependency instructions, like cond_fail and
// fix_lifetime. Only if the definition is alive, the user itself is alive.
@@ -374,7 +378,7 @@
return;
}
- switch (ValueKindAsTermKind(I->getKind())) {
+ switch (cast<TermInst>(I)->getTermKind()) {
case TermKind::BranchInst:
case TermKind::UnreachableInst:
return;
@@ -459,10 +463,7 @@
DEBUG(llvm::dbgs() << "Removing dead argument:\n");
DEBUG(Inst->dump());
- if (Inst->hasValue()) {
- auto *Undef = SILUndef::get(Inst->getType(), Inst->getModule());
- Inst->replaceAllUsesWith(Undef);
- }
+ Inst->replaceAllUsesWithUndef();
Changed = true;
}
@@ -489,11 +490,7 @@
DEBUG(llvm::dbgs() << "Removing dead instruction:\n");
DEBUG(Inst->dump());
- if (Inst->hasValue()) {
- auto *Undef = SILUndef::get(Inst->getType(), Inst->getModule());
- Inst->replaceAllUsesWith(Undef);
- }
-
+ Inst->replaceAllUsesOfAllResultsWithUndef();
if (isa<ApplyInst>(Inst))
CallsChanged = true;
diff --git a/lib/SILOptimizer/Transforms/DeadObjectElimination.cpp b/lib/SILOptimizer/Transforms/DeadObjectElimination.cpp
index 10b7199..a33bfee 100644
--- a/lib/SILOptimizer/Transforms/DeadObjectElimination.cpp
+++ b/lib/SILOptimizer/Transforms/DeadObjectElimination.cpp
@@ -181,8 +181,7 @@
void static
removeInstructions(ArrayRef<SILInstruction*> UsersToRemove) {
for (auto *I : UsersToRemove) {
- if (!I->use_empty())
- I->replaceAllUsesWith(SILUndef::get(I->getType(), I->getModule()));
+ I->replaceAllUsesOfAllResultsWithUndef();
// Now we know that I should not have any uses... erase it from its parent.
I->eraseFromParent();
}
@@ -197,7 +196,7 @@
static bool canZapInstruction(SILInstruction *Inst) {
// It is ok to eliminate various retains/releases. We are either removing
// everything or nothing.
- if (isa<RefCountingInst>(Inst))
+ if (isa<RefCountingInst>(Inst) || isa<StrongPinInst>(Inst))
return true;
// If we see a store here, we have already checked that we are storing into
@@ -255,20 +254,22 @@
// At this point, we can remove the instruction as long as all of its users
// can be removed as well. Scan its users and add them to the worklist for
// recursive processing.
- for (auto *Op : I->getUses()) {
- auto *User = Op->getUser();
+ for (auto result : I->getResults()) {
+ for (auto *Op : result->getUses()) {
+ auto *User = Op->getUser();
- // Make sure that we are only storing into our users, not storing our
- // users which would be an escape.
- if (auto *SI = dyn_cast<StoreInst>(User))
- if (Op->get() == SI->getSrc()) {
- DEBUG(llvm::dbgs() << " Found store of pointer. Failure: " <<
- *SI);
- return true;
- }
+ // Make sure that we are only storing into our users, not storing our
+ // users which would be an escape.
+ if (auto *SI = dyn_cast<StoreInst>(User))
+ if (Op->get() == SI->getSrc()) {
+ DEBUG(llvm::dbgs() << " Found store of pointer. Failure: " <<
+ *SI);
+ return true;
+ }
- // Otherwise, add normal instructions to the worklist for processing.
- Worklist.push_back(User);
+ // Otherwise, add normal instructions to the worklist for processing.
+ Worklist.push_back(User);
+ }
}
}
@@ -388,7 +389,9 @@
auto User = Op->getUser();
// Lifetime endpoints that don't allow the address to escape.
- if (isa<RefCountingInst>(User) || isa<DebugValueInst>(User)) {
+ if (isa<RefCountingInst>(User) ||
+ isa<StrongPinInst>(User) ||
+ isa<DebugValueInst>(User)) {
AllUsers.insert(User);
continue;
}
@@ -409,44 +412,46 @@
AllUsers.insert(User);
continue;
}
- if (isa<PointerToAddressInst>(User)) {
+ if (auto PTAI = dyn_cast<PointerToAddressInst>(User)) {
// Only one pointer-to-address is allowed for safety.
if (SeenPtrToAddr)
return false;
SeenPtrToAddr = true;
- if (!recursivelyCollectInteriorUses(User, AddressNode, IsInteriorAddress))
+ if (!recursivelyCollectInteriorUses(PTAI, AddressNode, IsInteriorAddress))
return false;
continue;
}
// Recursively follow projections.
- ProjectionIndex PI(User);
- if (PI.isValid()) {
- IndexTrieNode *ProjAddrNode = AddressNode;
- bool ProjInteriorAddr = IsInteriorAddress;
- if (Projection::isAddressProjection(User)) {
- if (User->getKind() == ValueKind::IndexAddrInst) {
- // Don't support indexing within an interior address.
- if (IsInteriorAddress)
- return false;
+ if (auto ProjInst = dyn_cast<SingleValueInstruction>(User)) {
+ ProjectionIndex PI(ProjInst);
+ if (PI.isValid()) {
+ IndexTrieNode *ProjAddrNode = AddressNode;
+ bool ProjInteriorAddr = IsInteriorAddress;
+ if (Projection::isAddressProjection(ProjInst)) {
+ if (isa<IndexAddrInst>(ProjInst)) {
+ // Don't support indexing within an interior address.
+ if (IsInteriorAddress)
+ return false;
+ }
+ else if (!IsInteriorAddress) {
+ // Push an extra zero index node for the first interior address.
+ ProjAddrNode = AddressNode->getChild(0);
+ ProjInteriorAddr = true;
+ }
}
- else if (!IsInteriorAddress) {
- // Push an extra zero index node for the first interior address.
- ProjAddrNode = AddressNode->getChild(0);
- ProjInteriorAddr = true;
+ else if (IsInteriorAddress) {
+ // Don't expect to extract values once we've taken an address.
+ return false;
}
+ if (!recursivelyCollectInteriorUses(ProjInst,
+ ProjAddrNode->getChild(PI.Index),
+ ProjInteriorAddr)) {
+ return false;
+ }
+ continue;
}
- else if (IsInteriorAddress) {
- // Don't expect to extract values once we've taken an address.
- return false;
- }
- if (!recursivelyCollectInteriorUses(User,
- ProjAddrNode->getChild(PI.Index),
- ProjInteriorAddr)) {
- return false;
- }
- continue;
}
// Otherwise bail.
DEBUG(llvm::dbgs() << " Found an escaping use: " << *User);
@@ -532,7 +537,7 @@
// TODO: This relies on the lowest level array.uninitialized not being
// inlined. To do better we could either run this pass before semantic inlining,
// or we could also handle calls to array.init.
-static bool removeAndReleaseArray(SILInstruction *NewArrayValue,
+static bool removeAndReleaseArray(SingleValueInstruction *NewArrayValue,
DeadEndBlocks &DEBlocks) {
TupleExtractInst *ArrayDef = nullptr;
TupleExtractInst *StorageAddress = nullptr;
diff --git a/lib/SILOptimizer/Transforms/DeadStoreElimination.cpp b/lib/SILOptimizer/Transforms/DeadStoreElimination.cpp
index 337ae48..c59d7bf 100644
--- a/lib/SILOptimizer/Transforms/DeadStoreElimination.cpp
+++ b/lib/SILOptimizer/Transforms/DeadStoreElimination.cpp
@@ -147,14 +147,14 @@
/// general sense but are inert from a load store perspective.
static bool isDeadStoreInertInstruction(SILInstruction *Inst) {
switch (Inst->getKind()) {
- case ValueKind::StrongRetainInst:
- case ValueKind::StrongRetainUnownedInst:
- case ValueKind::UnownedRetainInst:
- case ValueKind::RetainValueInst:
- case ValueKind::DeallocStackInst:
- case ValueKind::DeallocRefInst:
- case ValueKind::CondFailInst:
- case ValueKind::FixLifetimeInst:
+ case SILInstructionKind::StrongRetainInst:
+ case SILInstructionKind::StrongRetainUnownedInst:
+ case SILInstructionKind::UnownedRetainInst:
+ case SILInstructionKind::RetainValueInst:
+ case SILInstructionKind::DeallocStackInst:
+ case SILInstructionKind::DeallocRefInst:
+ case SILInstructionKind::CondFailInst:
+ case SILInstructionKind::FixLifetimeInst:
return true;
default:
return false;
@@ -1109,7 +1109,8 @@
}
// Check whether this instruction will invalidate any other locations.
- invalidateBase(I, getBlockState(I), Kind);
+ for (auto result : I->getResults())
+ invalidateBase(result, getBlockState(I), Kind);
}
void DSEContext::runIterativeDSE() {
@@ -1214,10 +1215,10 @@
for (auto &X : S->LiveAddr) {
Changed = true;
auto I = S->LiveStores.find(X);
- SILInstruction *Inst = cast<SILInstruction>(I->first);
+ SILInstruction *Inst = I->first->getDefiningInstruction();
auto *IT = &*std::next(Inst->getIterator());
SILBuilderWithScope Builder(IT);
- Builder.createStore(Inst->getLoc(), I->second, Inst,
+ Builder.createStore(Inst->getLoc(), I->second, I->first,
StoreOwnershipQualifier::Unqualified);
}
// Delete the dead stores.
diff --git a/lib/SILOptimizer/Transforms/Devirtualizer.cpp b/lib/SILOptimizer/Transforms/Devirtualizer.cpp
index 935d178..922969a 100644
--- a/lib/SILOptimizer/Transforms/Devirtualizer.cpp
+++ b/lib/SILOptimizer/Transforms/Devirtualizer.cpp
@@ -76,7 +76,7 @@
auto *AI = Apply.getInstruction();
if (!isa<TryApplyInst>(AI))
- AI->replaceAllUsesWith(NewInstPair.first);
+ cast<SingleValueInstruction>(AI)->replaceAllUsesWith(NewInstPair.first);
DeadApplies.push_back(AI);
NewApplies.push_back(NewInstPair.second);
diff --git a/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp b/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp
index 70ba575..d3270a0 100644
--- a/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp
+++ b/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp
@@ -499,8 +499,8 @@
}
// Scan the result type of the instruction.
- if (I.getType()) {
- I.getType().getSwiftRValueType().visit(FindArchetypesAndGenericTypes);
+ for (auto V : I.getResults()) {
+ V->getType().getSwiftRValueType().visit(FindArchetypesAndGenericTypes);
}
if (UsesGenerics)
@@ -649,11 +649,11 @@
NewFGenericEnv = nullptr;
}
- NewF = M.createFunction(
- linkage, Name, NewFTy, NewFGenericEnv, F->getLocation(), F->isBare(),
- F->isTransparent(), F->isSerialized(), F->isThunk(),
- F->getClassSubclassScope(), F->getInlineStrategy(), F->getEffectsKind(),
- nullptr, F->getDebugScope());
+ NewF = M.createFunction(linkage, Name, NewFTy, NewFGenericEnv,
+ F->getLocation(), F->isBare(), F->isTransparent(),
+ F->isSerialized(), F->getEntryCount(), F->isThunk(),
+ F->getClassSubclassScope(), F->getInlineStrategy(),
+ F->getEffectsKind(), nullptr, F->getDebugScope());
if (F->hasUnqualifiedOwnership()) {
NewF->setUnqualifiedOwnership();
}
@@ -948,8 +948,8 @@
continue;
}
// Create a release to balance it out.
- assert(isa<ApplyInst>(X) && "Unknown epilogue retain");
- createDecrementBefore(X, dyn_cast<ApplyInst>(X)->getParent()->getTerminator());
+ auto AI = cast<ApplyInst>(X);
+ createDecrementBefore(AI, AI->getParent()->getTerminator());
}
}
}
@@ -1018,12 +1018,12 @@
}
SILInstruction *Call = findOnlyApply(F);
- if (isa<ApplyInst>(Call)) {
- Builder.setInsertionPoint(&*std::next(SILBasicBlock::iterator(Call)));
- Builder.createRetainValue(RegularLocation(SourceLoc()), Call,
+ if (auto AI = dyn_cast<ApplyInst>(Call)) {
+ Builder.setInsertionPoint(&*std::next(SILBasicBlock::iterator(AI)));
+ Builder.createRetainValue(RegularLocation(SourceLoc()), AI,
Builder.getDefaultAtomicity());
} else {
- SILBasicBlock *NormalBB = dyn_cast<TryApplyInst>(Call)->getNormalBB();
+ SILBasicBlock *NormalBB = cast<TryApplyInst>(Call)->getNormalBB();
Builder.setInsertionPoint(&*NormalBB->begin());
Builder.createRetainValue(RegularLocation(SourceLoc()),
NormalBB->getArgument(0), Builder.getDefaultAtomicity());
diff --git a/lib/SILOptimizer/Transforms/MarkUninitializedFixup.cpp b/lib/SILOptimizer/Transforms/MarkUninitializedFixup.cpp
index 981ef7c..5613b0b 100644
--- a/lib/SILOptimizer/Transforms/MarkUninitializedFixup.cpp
+++ b/lib/SILOptimizer/Transforms/MarkUninitializedFixup.cpp
@@ -22,7 +22,7 @@
// Top Level Entry Point
//===----------------------------------------------------------------------===//
-static SILInstruction *
+static ProjectBoxInst *
getInitialProjectBox(MarkUninitializedInst *MUI,
ArrayRef<ProjectBoxInst *> Projections) {
assert(!Projections.empty());
@@ -113,7 +113,7 @@
// That means now our project box now has the alloc_box as its
// operand. Grab that project_box.
- SILInstruction *PBI = getInitialProjectBox(MUI, Projections);
+ auto *PBI = getInitialProjectBox(MUI, Projections);
// Then create the new mark_uninitialized and force all uses of the
// project_box to go through the new mark_uninitialized.
diff --git a/lib/SILOptimizer/Transforms/Outliner.cpp b/lib/SILOptimizer/Transforms/Outliner.cpp
index 12bc9d7..add7ab7 100644
--- a/lib/SILOptimizer/Transforms/Outliner.cpp
+++ b/lib/SILOptimizer/Transforms/Outliner.cpp
@@ -207,7 +207,7 @@
/// bb10(%45 : $Optional<String>):
class BridgedProperty : public OutlinePattern {
std::string OutlinedName;
- SILInstruction *FirstInst;
+ SingleValueInstruction *FirstInst; // A load or class_method
SILBasicBlock *StartBB;
SILBasicBlock *SomeBB;
SILBasicBlock *NoneBB;
diff --git a/lib/SILOptimizer/Transforms/OwnershipModelEliminator.cpp b/lib/SILOptimizer/Transforms/OwnershipModelEliminator.cpp
index f59c614..55e41a1 100644
--- a/lib/SILOptimizer/Transforms/OwnershipModelEliminator.cpp
+++ b/lib/SILOptimizer/Transforms/OwnershipModelEliminator.cpp
@@ -46,13 +46,12 @@
B.setOpenedArchetypesTracker(&OpenedArchetypesTracker);
}
- void beforeVisit(ValueBase *V) {
- auto *I = cast<SILInstruction>(V);
+ void beforeVisit(SILInstruction *I) {
B.setInsertionPoint(I);
B.setCurrentDebugScope(I->getDebugScope());
}
- bool visitValueBase(ValueBase *V) { return false; }
+ bool visitSILInstruction(SILInstruction *I) { return false; }
bool visitLoadInst(LoadInst *LI);
bool visitStoreInst(StoreInst *SI);
bool visitStoreBorrowInst(StoreBorrowInst *SI);
@@ -176,7 +175,6 @@
// Now that we have set the unqualified ownership flag, destroy value
// operation will delegate to the appropriate strong_release, etc.
B.emitCopyValueOperation(URVI->getLoc(), URVI->getOperand());
- URVI->replaceAllUsesWith(URVI->getOperand());
URVI->eraseFromParent();
return true;
}
diff --git a/lib/SILOptimizer/Transforms/PerformanceInliner.cpp b/lib/SILOptimizer/Transforms/PerformanceInliner.cpp
index 2fd9c1e..6f5d22d 100644
--- a/lib/SILOptimizer/Transforms/PerformanceInliner.cpp
+++ b/lib/SILOptimizer/Transforms/PerformanceInliner.cpp
@@ -128,15 +128,24 @@
return SPA;
}
- bool isProfitableToInline(FullApplySite AI,
- Weight CallerWeight,
- ConstantTracker &callerTracker,
- int &NumCallerBlocks);
+ bool profileBasedDecision(
+ const FullApplySite &AI, int Benefit, SILFunction *Callee, int CalleeCost,
+ int &NumCallerBlocks,
+ const llvm::DenseMapIterator<
+ swift::SILBasicBlock *, uint64_t,
+ llvm::DenseMapInfo<swift::SILBasicBlock *>,
+ llvm::detail::DenseMapPair<swift::SILBasicBlock *, uint64_t>, true>
+ &bbIt);
- bool decideInWarmBlock(FullApplySite AI,
- Weight CallerWeight,
- ConstantTracker &callerTracker,
- int &NumCallerBlocks);
+ bool isProfitableToInline(
+ FullApplySite AI, Weight CallerWeight, ConstantTracker &callerTracker,
+ int &NumCallerBlocks,
+ const llvm::DenseMap<SILBasicBlock *, uint64_t> &BBToWeightMap);
+
+ bool decideInWarmBlock(
+ FullApplySite AI, Weight CallerWeight, ConstantTracker &callerTracker,
+ int &NumCallerBlocks,
+ const llvm::DenseMap<SILBasicBlock *, uint64_t> &BBToWeightMap);
bool decideInColdBlock(FullApplySite AI, SILFunction *Callee);
@@ -165,10 +174,63 @@
return ReabstractionInfo::canBeSpecialized(AI, F, Subs);
}
-bool SILPerformanceInliner::isProfitableToInline(FullApplySite AI,
- Weight CallerWeight,
- ConstantTracker &callerTracker,
- int &NumCallerBlocks) {
+bool SILPerformanceInliner::profileBasedDecision(
+ const FullApplySite &AI, int Benefit, SILFunction *Callee, int CalleeCost,
+ int &NumCallerBlocks,
+ const llvm::DenseMapIterator<
+ swift::SILBasicBlock *, uint64_t,
+ llvm::DenseMapInfo<swift::SILBasicBlock *>,
+ llvm::detail::DenseMapPair<swift::SILBasicBlock *, uint64_t>, true>
+ &bbIt) {
+ if (CalleeCost < TrivialFunctionThreshold) {
+ // We do not increase code size below this threshold
+ return true;
+ }
+ auto callerCount = bbIt->getSecond();
+ if (callerCount < 1) {
+ // Never called - do not inline
+ DEBUG(dumpCaller(AI.getFunction()); llvm::dbgs()
+ << "profiled decision: NO"
+ << ", reason= Never Called." << '\n';);
+ return false;
+ }
+ auto calleeCount = Callee->getEntryCount();
+ if (calleeCount) {
+ // If we have Callee count - use SI heuristic:
+ auto calleCountVal = calleeCount.getValue();
+ auto percent = (long double)callerCount / (long double)calleCountVal;
+ if (percent < 0.8) {
+ DEBUG(dumpCaller(AI.getFunction());
+ llvm::dbgs() << "profiled decision: NO"
+ << ", reason=SI " << std::to_string(percent) << "%"
+ << '\n';);
+ return false;
+ }
+ DEBUG(dumpCaller(AI.getFunction()); llvm::dbgs() << "profiled decision: YES"
+ << ", reason=SI "
+ << std::to_string(percent)
+ << "%" << '\n';);
+ } else {
+ // No callee count - use a "modified" aggressive IHF for now
+ if (CalleeCost > Benefit && callerCount < 100) {
+ DEBUG(dumpCaller(AI.getFunction());
+ llvm::dbgs() << "profiled decision: NO"
+ << ", reason=IHF " << callerCount << '\n';);
+ return false;
+ }
+ DEBUG(dumpCaller(AI.getFunction()); llvm::dbgs() << "profiled decision: YES"
+ << ", reason=IHF "
+ << callerCount << '\n';);
+ }
+ // We're gonna inline!
+ NumCallerBlocks += Callee->size();
+ return true;
+}
+
+bool SILPerformanceInliner::isProfitableToInline(
+ FullApplySite AI, Weight CallerWeight, ConstantTracker &callerTracker,
+ int &NumCallerBlocks,
+ const llvm::DenseMap<SILBasicBlock *, uint64_t> &BBToWeightMap) {
SILFunction *Callee = AI.getReferencedFunction();
bool IsGeneric = !AI.getSubstitutions().empty();
@@ -253,7 +315,7 @@
// Check if inlining the callee would allow for further
// optimizations like devirtualization or generic specialization.
if (!def)
- def = dyn_cast_or_null<SILInstruction>(FAI.getCallee());
+ def = dyn_cast_or_null<SingleValueInstruction>(FAI.getCallee());
if (!def)
continue;
@@ -362,6 +424,14 @@
NumCallerBlocks / BlockLimitDenominator;
Benefit -= blockMinus;
+ // If we have profile info - use it for final inlining decision.
+ auto *bb = AI.getInstruction()->getParent();
+ auto bbIt = BBToWeightMap.find(bb);
+ if (bbIt != BBToWeightMap.end()) {
+ return profileBasedDecision(AI, Benefit, Callee, CalleeCost,
+ NumCallerBlocks, bbIt);
+ }
+
// This is the final inlining decision.
if (CalleeCost > Benefit) {
return false;
@@ -423,11 +493,10 @@
return None;
}
-bool SILPerformanceInliner::
-decideInWarmBlock(FullApplySite AI,
- Weight CallerWeight,
- ConstantTracker &callerTracker,
- int &NumCallerBlocks) {
+bool SILPerformanceInliner::decideInWarmBlock(
+ FullApplySite AI, Weight CallerWeight, ConstantTracker &callerTracker,
+ int &NumCallerBlocks,
+ const llvm::DenseMap<SILBasicBlock *, uint64_t> &BBToWeightMap) {
if (!AI.getSubstitutions().empty()) {
// Only inline generics if definitively clear that it should be done.
auto ShouldInlineGeneric = shouldInlineGeneric(AI);
@@ -445,7 +514,8 @@
return true;
}
- return isProfitableToInline(AI, CallerWeight, callerTracker, NumCallerBlocks);
+ return isProfitableToInline(AI, CallerWeight, callerTracker, NumCallerBlocks,
+ BBToWeightMap);
}
/// Return true if inlining this call site into a cold block is profitable.
@@ -505,6 +575,94 @@
}
}
+static bool containsWeight(TermInst *inst) {
+ for (auto &succ : inst->getSuccessors()) {
+ if (succ.getCount()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static void
+addToBBCounts(llvm::DenseMap<SILBasicBlock *, uint64_t> &BBToWeightMap,
+ uint64_t numToAdd, swift::TermInst *termInst) {
+ for (auto &succ : termInst->getSuccessors()) {
+ auto *currBB = succ.getBB();
+ assert(BBToWeightMap.find(currBB) != BBToWeightMap.end() &&
+ "Expected to find block in map");
+ BBToWeightMap[currBB] += numToAdd;
+ }
+}
+
+static void
+calculateBBWeights(SILFunction *Caller, DominanceInfo *DT,
+ llvm::DenseMap<SILBasicBlock *, uint64_t> &BBToWeightMap) {
+ auto entryCount = Caller->getEntryCount();
+ if (!entryCount) {
+ // No profile for function - return
+ return;
+ }
+ // Add all blocks to BBToWeightMap without count 0
+ for (auto &block : Caller->getBlocks()) {
+ BBToWeightMap[&block] = 0;
+ }
+ BBToWeightMap[Caller->getEntryBlock()] = entryCount.getValue();
+ DominanceOrder domOrder(&Caller->front(), DT, Caller->size());
+ while (SILBasicBlock *block = domOrder.getNext()) {
+ auto bbIt = BBToWeightMap.find(block);
+ assert(bbIt != BBToWeightMap.end() && "Expected to find block in map");
+ auto bbCount = bbIt->getSecond();
+ auto *termInst = block->getTerminator();
+ if (containsWeight(termInst)) {
+ // Instruction already contains accurate counters - use them as-is
+ uint64_t countSum = 0;
+ uint64_t blocksWithoutCount = 0;
+ for (auto &succ : termInst->getSuccessors()) {
+ auto *currBB = succ.getBB();
+ assert(BBToWeightMap.find(currBB) != BBToWeightMap.end() &&
+ "Expected to find block in map");
+ auto currCount = succ.getCount();
+ if (!currCount) {
+ ++blocksWithoutCount;
+ continue;
+ }
+ auto currCountVal = currCount.getValue();
+ countSum += currCountVal;
+ BBToWeightMap[currBB] += currCountVal;
+ }
+ if (countSum < bbCount) {
+ // inaccurate profile - fill in the gaps for BBs without a count:
+ if (blocksWithoutCount > 0) {
+ auto numToAdd = (bbCount - countSum) / blocksWithoutCount;
+ for (auto &succ : termInst->getSuccessors()) {
+ auto *currBB = succ.getBB();
+ auto currCount = succ.getCount();
+ if (!currCount) {
+ BBToWeightMap[currBB] += numToAdd;
+ }
+ }
+ }
+ } else {
+ auto numOfSucc = termInst->getSuccessors().size();
+ assert(numOfSucc > 0 && "Expected successors > 0");
+ auto numToAdd = (countSum - bbCount) / numOfSucc;
+ addToBBCounts(BBToWeightMap, numToAdd, termInst);
+ }
+ } else {
+ // Fill counters speculatively
+ auto numOfSucc = termInst->getSuccessors().size();
+ if (numOfSucc == 0) {
+ // No successors to fill
+ continue;
+ }
+ auto numToAdd = bbCount / numOfSucc;
+ addToBBCounts(BBToWeightMap, numToAdd, termInst);
+ }
+ domOrder.pushChildrenIf(block, [&](SILBasicBlock *child) { return true; });
+ }
+}
+
void SILPerformanceInliner::collectAppliesToInline(
SILFunction *Caller, SmallVectorImpl<FullApplySite> &Applies) {
DominanceInfo *DT = DA->get(Caller);
@@ -552,6 +710,9 @@
DominanceOrder domOrder(&Caller->front(), DT, Caller->size());
int NumCallerBlocks = (int)Caller->size();
+ llvm::DenseMap<SILBasicBlock *, uint64_t> BBToWeightMap;
+ calculateBBWeights(Caller, DT, BBToWeightMap);
+
// Go through all instructions and find candidates for inlining.
// We do this in dominance order for the constTracker.
SmallVector<FullApplySite, 8> InitialCandidates;
@@ -575,7 +736,8 @@
// The actual weight including a possible weight correction.
Weight W(BlockWeight, WeightCorrections.lookup(AI));
- if (decideInWarmBlock(AI, W, constTracker, NumCallerBlocks))
+ if (decideInWarmBlock(AI, W, constTracker, NumCallerBlocks,
+ BBToWeightMap))
InitialCandidates.push_back(AI);
}
}
@@ -607,8 +769,9 @@
assert(Callee && "apply_inst does not have a direct callee anymore");
const unsigned CallsToCalleeThreshold = 1024;
- if (CalleeCount[Callee] <= CallsToCalleeThreshold)
+ if (CalleeCount[Callee] <= CallsToCalleeThreshold) {
Applies.push_back(AI);
+ }
}
}
diff --git a/lib/SILOptimizer/Transforms/RedundantLoadElimination.cpp b/lib/SILOptimizer/Transforms/RedundantLoadElimination.cpp
index 76ad412..f8fdc04 100644
--- a/lib/SILOptimizer/Transforms/RedundantLoadElimination.cpp
+++ b/lib/SILOptimizer/Transforms/RedundantLoadElimination.cpp
@@ -98,12 +98,9 @@
STATISTIC(NumForwardedLoads, "Number of loads forwarded");
-/// Return the deallocate stack instructions corresponding to the given
-/// AllocStackInst.
-static SILInstruction *findAllocStackInst(SILInstruction *I) {
- if (auto *DSI = dyn_cast<DeallocStackInst>(I))
- return dyn_cast<SILInstruction>(DSI->getOperand());
- return nullptr;
+static AllocStackInst *findAllocStackInst(DeallocStackInst *I) {
+ // It's allowed to be undef in unreachable code.
+ return dyn_cast<AllocStackInst>(I->getOperand());
}
/// ComputeAvailSetMax - If we ignore all unknown writes, what is the max
@@ -149,15 +146,15 @@
/// general sense but are inert from a load store perspective.
static bool isRLEInertInstruction(SILInstruction *Inst) {
switch (Inst->getKind()) {
- case ValueKind::StrongRetainInst:
- case ValueKind::StrongRetainUnownedInst:
- case ValueKind::UnownedRetainInst:
- case ValueKind::RetainValueInst:
- case ValueKind::DeallocStackInst:
- case ValueKind::CondFailInst:
- case ValueKind::IsUniqueInst:
- case ValueKind::IsUniqueOrPinnedInst:
- case ValueKind::FixLifetimeInst:
+ case SILInstructionKind::StrongRetainInst:
+ case SILInstructionKind::StrongRetainUnownedInst:
+ case SILInstructionKind::UnownedRetainInst:
+ case SILInstructionKind::RetainValueInst:
+ case SILInstructionKind::DeallocStackInst:
+ case SILInstructionKind::CondFailInst:
+ case SILInstructionKind::IsUniqueInst:
+ case SILInstructionKind::IsUniqueOrPinnedInst:
+ case SILInstructionKind::FixLifetimeInst:
return true;
default:
return false;
@@ -237,7 +234,7 @@
/// Keeps a list of replaceable instructions in the current basic block as
/// well as their SILValue replacement.
- llvm::DenseMap<SILInstruction *, SILValue> RedundantLoads;
+ llvm::DenseMap<SingleValueInstruction *, SILValue> RedundantLoads;
/// LSLocation read or written has been extracted, expanded and mapped to the
/// bit position in the bitvector. Update it in the ForwardSetIn of the
@@ -352,7 +349,9 @@
/// Returns the redundant loads and their replacement in the currently basic
/// block.
- llvm::DenseMap<SILInstruction *, SILValue> &getRL() { return RedundantLoads; }
+ llvm::DenseMap<SingleValueInstruction *, SILValue> &getRL() {
+ return RedundantLoads;
+ }
/// Look into the value for the given LSLocation at end of the basic block,
/// return one of the three ValueState type.
@@ -386,10 +385,10 @@
void processUnknownWriteInstForRLE(RLEContext &Ctx, SILInstruction *I);
- void processDeallocStackInst(RLEContext &Ctx, SILInstruction *I,
+ void processDeallocStackInst(RLEContext &Ctx, DeallocStackInst *I,
RLEKind Kind);
- void processDeallocStackInstForGenKillSet(RLEContext &Ctx, SILInstruction *I);
- void processDeallocStackInstForRLE(RLEContext &Ctx, SILInstruction *I);
+ void processDeallocStackInstForGenKillSet(RLEContext &Ctx, DeallocStackInst *I);
+ void processDeallocStackInstForRLE(RLEContext &Ctx, DeallocStackInst *I);
/// Process LoadInst. Extract LSLocations from LoadInst.
void processLoadInst(RLEContext &Ctx, LoadInst *LI, RLEKind Kind);
@@ -723,7 +722,7 @@
// replace it with, we can record it for now and forwarded it after all the
// forwardable values are recorded in the function.
//
- RedundantLoads[I] = TheForwardingValue;
+ RedundantLoads[cast<SingleValueInstruction>(I)] = TheForwardingValue;
DEBUG(llvm::dbgs() << "FORWARD " << TheForwardingValue << " to" << *I);
return true;
@@ -1000,7 +999,7 @@
}
void BlockState::
-processDeallocStackInstForGenKillSet(RLEContext &Ctx, SILInstruction *I) {
+processDeallocStackInstForGenKillSet(RLEContext &Ctx, DeallocStackInst *I) {
SILValue ASI = findAllocStackInst(I);
for (unsigned i = 0; i < LocationNum; ++i) {
LSLocation &R = Ctx.getLocation(i);
@@ -1013,7 +1012,7 @@
}
void BlockState::
-processDeallocStackInstForRLE(RLEContext &Ctx, SILInstruction *I) {
+processDeallocStackInstForRLE(RLEContext &Ctx, DeallocStackInst *I) {
SILValue ASI = findAllocStackInst(I);
for (unsigned i = 0; i < LocationNum; ++i) {
LSLocation &R = Ctx.getLocation(i);
@@ -1026,7 +1025,7 @@
}
void BlockState::
-processDeallocStackInst(RLEContext &Ctx, SILInstruction *I, RLEKind Kind) {
+processDeallocStackInst(RLEContext &Ctx, DeallocStackInst *I, RLEKind Kind) {
// Are we computing the genset and killset ?
if (isComputeAvailGenKillSet(Kind)) {
processDeallocStackInstForGenKillSet(Ctx, I);
@@ -1574,7 +1573,10 @@
// NOTE: we could end up with different SIL depending on the ordering load
// forwarding is performed.
for (auto I = B.rbegin(), E = B.rend(); I != E; ++I) {
- auto Iter = Loads.find(&*I);
+ auto V = dyn_cast<SingleValueInstruction>(&*I);
+ if (!V)
+ continue;
+ auto Iter = Loads.find(V);
if (Iter == Loads.end())
continue;
DEBUG(llvm::dbgs() << "Replacing " << SILValue(Iter->first) << "With "
@@ -1593,7 +1595,7 @@
// used as the replacement Value, i.e. F.second, for some other RLE pairs.
//
// TODO: we should fix this, otherwise we are missing RLE opportunities.
- if (!X->use_empty())
+ if (X->hasUsesOfAnyResult())
continue;
recursivelyDeleteTriviallyDeadInstructions(X, true);
}
diff --git a/lib/SILOptimizer/Transforms/RemovePin.cpp b/lib/SILOptimizer/Transforms/RemovePin.cpp
index 2c03c17..86492f7 100644
--- a/lib/SILOptimizer/Transforms/RemovePin.cpp
+++ b/lib/SILOptimizer/Transforms/RemovePin.cpp
@@ -40,10 +40,9 @@
/// \brief Can this instruction read the pinned bit of the reference count.
/// Reading the pinned prevents us from moving the pin instructions across it.
static bool mayReadPinFlag(SILInstruction *I) {
- auto Kind = I->getKind();
- if (Kind == ValueKind::IsUniqueOrPinnedInst)
+ if (isa<IsUniqueOrPinnedInst>(I))
return true;
- if (Kind != ValueKind::ApplyInst)
+ if (!isa<ApplyInst>(I))
return false;
if (!I->mayReadFromMemory())
return false;
@@ -58,7 +57,7 @@
/// The set of currently available pins that have not been invalidate by an
/// instruction that mayRelease memory.
- llvm::SmallPtrSet<SILInstruction *, 16> AvailablePins;
+ llvm::SmallPtrSet<StrongPinInst *, 16> AvailablePins;
AliasAnalysis *AA;
@@ -89,9 +88,9 @@
DEBUG(llvm::dbgs() << " Visiting: " << *CurInst);
// Add StrongPinInst to available pins.
- if (isa<StrongPinInst>(CurInst)) {
+ if (auto pin = dyn_cast<StrongPinInst>(CurInst)) {
DEBUG(llvm::dbgs() << " Found pin!\n");
- AvailablePins.insert(CurInst);
+ AvailablePins.insert(pin);
continue;
}
@@ -181,11 +180,19 @@
for (auto *U : Users) {
// A mark_dependence is safe if it is marking a dependence on a base that
- // is the strong_pinned value.
+ // is the strong_pinned value:
+ // %0 = strong_pin ...
+ // %1 = mark_dependence ... on %0
+ // or
+ // %0 = strong_pin ...
+ // %1 = foo ... %0 ...
+ // %2 = mark_dependence ... on %1
if (auto *MD = dyn_cast<MarkDependenceInst>(U))
if (Pin == MD->getBase() ||
- std::find(Users.begin(), Users.end(), MD->getBase()) !=
- Users.end()) {
+ std::find_if(Users.begin(), Users.end(),
+ [&](SILInstruction *I) {
+ return MD->getBase()->getDefiningInstruction() == I;
+ }) != Users.end()) {
MarkDeps.push_back(MD);
continue;
}
@@ -236,7 +243,7 @@
// TODO: We already created an ArraySemanticsCall in
// isSafeArraySemanticFunction. I wonder if we can refactor into a third
// method that takes an array semantic call. Then we can reuse the work.
- ArraySemanticsCall Call(I);
+ ArraySemanticsCall Call(cast<ApplyInst>(I));
// If our call does not have guaranteed self, bail.
if (!Call.hasGuaranteedSelf())
@@ -249,7 +256,7 @@
/// Removes available pins that could be released by executing of 'I'.
void invalidateAvailablePins(SILInstruction *I) {
// Collect pins that we have to clear because they might have been released.
- SmallVector<SILInstruction *, 16> RemovePin;
+ SmallVector<StrongPinInst *, 16> RemovePin;
for (auto *P : AvailablePins) {
if (!isSafeArraySemanticFunction(I) &&
(mayDecrementRefCount(I, P, AA) ||
diff --git a/lib/SILOptimizer/Transforms/SILCodeMotion.cpp b/lib/SILOptimizer/Transforms/SILCodeMotion.cpp
index 2452ff8..bdb57cb 100644
--- a/lib/SILOptimizer/Transforms/SILCodeMotion.cpp
+++ b/lib/SILOptimizer/Transforms/SILCodeMotion.cpp
@@ -73,10 +73,8 @@
++NumRefCountOpsSimplified;
- auto *RCI = cast<RefCountingInst>(I);
-
// If we have a retain value...
- if (isa<RetainValueInst>(I)) {
+ if (auto RCI = dyn_cast<RetainValueInst>(I)) {
// And our payload is refcounted, insert a strong_retain onto the
// payload.
if (UEDITy.isReferenceCounted(Mod)) {
@@ -93,6 +91,7 @@
// payload.
assert(isa<ReleaseValueInst>(I) && "If I is not a retain value here, it must "
"be a release value since enums do not have reference semantics.");
+ auto *RCI = cast<ReleaseValueInst>(I);
// If our payload has reference semantics, insert the strong release.
if (UEDITy.isReferenceCounted(Mod)) {
@@ -154,7 +153,7 @@
/// \brief Returns True if we can sink this instruction to another basic block.
static bool canSinkInstruction(SILInstruction *Inst) {
- return Inst->use_empty() && !isa<TermInst>(Inst);
+ return !Inst->hasUsesOfAnyResult() && !isa<TermInst>(Inst);
}
/// \brief Returns true if this instruction is a skip barrier, which means that
@@ -322,15 +321,15 @@
if (!FirstStruct || !SecondStruct)
return None;
- assert(First->getNumOperands() == Second->getNumOperands() &&
- First->getType() == Second->getType() &&
+ assert(FirstStruct->getNumOperands() == SecondStruct->getNumOperands() &&
+ FirstStruct->getType() == SecondStruct->getType() &&
"Types should be identical");
llvm::Optional<unsigned> DifferentOperandIndex;
// Check operands.
for (unsigned i = 0, e = First->getNumOperands(); i != e; ++i) {
- if (First->getOperand(i) != Second->getOperand(i)) {
+ if (FirstStruct->getOperand(i) != SecondStruct->getOperand(i)) {
// Only track one different operand for now
if (DifferentOperandIndex)
return None;
@@ -344,7 +343,7 @@
// Found a different operand, now check to see if its type is something
// cheap enough to sink.
// TODO: Sink more than just integers.
- const auto &ArgTy = First->getOperand(*DifferentOperandIndex)->getType();
+ SILType ArgTy = FirstStruct->getOperand(*DifferentOperandIndex)->getType();
if (!ArgTy.is<BuiltinIntegerType>())
return None;
@@ -408,16 +407,17 @@
SILBasicBlock *FirstPred = *BB->pred_begin();
TermInst *FirstTerm = FirstPred->getTerminator();
auto FirstPredArg = FirstTerm->getOperand(ArgNum);
- auto *FSI = dyn_cast<SILInstruction>(FirstPredArg);
-
- // The list of identical instructions.
- SmallVector<SILValue, 8> Clones;
- Clones.push_back(FirstPredArg);
+ auto *FSI = dyn_cast<SingleValueInstruction>(FirstPredArg);
+ // TODO: MultiValueInstruction?
// We only move instructions with a single use.
if (!FSI || !hasOneNonDebugUse(FSI))
return false;
+ // The list of identical instructions.
+ SmallVector<SingleValueInstruction*, 8> Clones;
+ Clones.push_back(FSI);
+
// Don't move instructions that are sensitive to their location.
//
// If this instruction can read memory, we try to be conservatively not to
@@ -443,9 +443,18 @@
// Find the Nth argument passed to BB.
SILValue Arg = TI->getOperand(ArgNum);
- auto *SI = dyn_cast<SILInstruction>(Arg);
- if (!SI || !hasOneNonDebugUse(SI))
+
+ // If it's not the same basic kind of node, neither isIdenticalTo nor
+ // cheaperToPassOperandsAsArguments will return true.
+ if (Arg->getKind() != FSI->getValueKind())
return false;
+
+ // Since it's the same kind, Arg must also be a single-value instruction.
+ auto *SI = cast<SingleValueInstruction>(Arg);
+
+ if (!hasOneNonDebugUse(SI))
+ return false;
+
if (SI->isIdenticalTo(FSI)) {
Clones.push_back(SI);
continue;
@@ -466,10 +475,7 @@
Clones.push_back(SI);
}
- if (!FSI)
- return false;
-
- auto *Undef = SILUndef::get(FirstPredArg->getType(), BB->getModule());
+ auto *Undef = SILUndef::get(FSI->getType(), BB->getModule());
// Delete the debug info of the instruction that we are about to sink.
deleteAllDebugUses(FSI);
@@ -495,7 +501,8 @@
assert((isa<BranchInst>(TI) || isa<CondBranchInst>(TI)) &&
"Branch instruction required");
- auto *CloneInst = dyn_cast<SILInstruction>(*CloneIt);
+ // TODO: MultiValueInstruction
+ auto *CloneInst = *CloneIt;
TI->setOperand(ArgNum, CloneInst->getOperand(*DifferentOperandIndex));
// Now delete the clone as we only needed it operand.
if (CloneInst != FSI)
@@ -511,9 +518,9 @@
}
// Sink one of the copies of the instruction.
- FirstPredArg->replaceAllUsesWith(Undef);
+ FSI->replaceAllUsesWithUndef();
FSI->moveBefore(&*BB->begin());
- BB->getArgument(ArgNum)->replaceAllUsesWith(FirstPredArg);
+ BB->getArgument(ArgNum)->replaceAllUsesWith(FSI);
// The argument is no longer in use. Replace all incoming inputs with undef
// and try to delete the instruction.
@@ -673,7 +680,7 @@
}
Changed = true;
for (auto I : Dups) {
- I->replaceAllUsesWith(&*InstToSink);
+ I->replaceAllUsesPairwiseWith(&*InstToSink);
I->eraseFromParent();
NumSunk++;
}
@@ -970,7 +977,7 @@
void clear() { ValueToCaseMap.clear(); }
- bool visitValueBase(ValueBase *V) { return false; }
+ bool visitSILInstruction(SILInstruction *I) { return false; }
bool visitEnumInst(EnumInst *EI) {
DEBUG(llvm::dbgs() << " Storing enum into map: " << *EI);
diff --git a/lib/SILOptimizer/Transforms/SILMem2Reg.cpp b/lib/SILOptimizer/Transforms/SILMem2Reg.cpp
index 9955915..1dfc54d 100644
--- a/lib/SILOptimizer/Transforms/SILMem2Reg.cpp
+++ b/lib/SILOptimizer/Transforms/SILMem2Reg.cpp
@@ -187,7 +187,7 @@
return false;
// Recursively search for other (non-)loads in the instruction's uses.
- for (auto UI : I->getUses()) {
+ for (auto UI : cast<SingleValueInstruction>(I)->getUses()) {
SILInstruction *II = UI->getUser();
if (II->getParent() != singleBlock)
singleBlock = nullptr;
@@ -290,7 +290,7 @@
if (!isa<StructElementAddrInst>(op) && !isa<TupleElementAddrInst>(op))
return false;
- op = cast<SILInstruction>(op)->getOperand(0);
+ op = cast<SingleValueInstruction>(op)->getOperand(0);
}
return true;
}
@@ -305,7 +305,7 @@
return;
// Recursively search for other loads in the instruction's uses.
- for (auto UI : I->getUses()) {
+ for (auto UI : cast<SingleValueInstruction>(I)->getUses()) {
collectLoads(UI->getUser(), Loads);
}
}
@@ -316,7 +316,7 @@
SILValue op = LI->getOperand();
while (op != ASI) {
assert(isa<StructElementAddrInst>(op) || isa<TupleElementAddrInst>(op));
- SILInstruction *Inst = cast<SILInstruction>(op);
+ auto *Inst = cast<SingleValueInstruction>(op);
projections.push_back(Projection(Inst));
op = Inst->getOperand(0);
}
@@ -330,7 +330,7 @@
LI->eraseFromParent();
while (op != ASI && op->use_empty()) {
assert(isa<StructElementAddrInst>(op) || isa<TupleElementAddrInst>(op));
- SILInstruction *Inst = cast<SILInstruction>(op);
+ auto *Inst = cast<SingleValueInstruction>(op);
SILValue next = Inst->getOperand(0);
Inst->eraseFromParent();
op = next;
@@ -370,18 +370,19 @@
++BBI;
if (isLoadFromStack(Inst, ASI)) {
+ auto Load = cast<LoadInst>(Inst);
if (RunningVal) {
// If we are loading from the AllocStackInst and we already know the
// content of the Alloca then use it.
- DEBUG(llvm::dbgs() << "*** Promoting load: " << *Inst);
+ DEBUG(llvm::dbgs() << "*** Promoting load: " << *Load);
- replaceLoad(cast<LoadInst>(Inst), RunningVal, ASI);
+ replaceLoad(Load, RunningVal, ASI);
NumInstRemoved++;
- } else if (Inst->getOperand(0) == ASI) {
+ } else if (Load->getOperand() == ASI) {
// If we don't know the content of the AllocStack then the loaded
// value *is* the new value;
- DEBUG(llvm::dbgs() << "*** First load: " << *Inst);
- RunningVal = Inst;
+ DEBUG(llvm::dbgs() << "*** First load: " << *Load);
+ RunningVal = Load;
}
continue;
}
@@ -509,13 +510,13 @@
}
}
- SILValue InstVal = Inst;
-
// Remove dead address instructions that may be uses of the allocation.
- while (InstVal->use_empty() && (isa<StructElementAddrInst>(InstVal) ||
- isa<TupleElementAddrInst>(InstVal))) {
- SILInstruction *I = cast<SILInstruction>(InstVal);
- InstVal = I->getOperand(0);
+ SILNode *Node = Inst;
+ while (isa<StructElementAddrInst>(Node) ||
+ isa<TupleElementAddrInst>(Node)) {
+ auto *I = cast<SingleValueInstruction>(Node);
+ if (!I->use_empty()) break;
+ Node = I->getOperand(0);
I->eraseFromParent();
NumInstRemoved++;
}
diff --git a/lib/SILOptimizer/Transforms/SILSROA.cpp b/lib/SILOptimizer/Transforms/SILSROA.cpp
index 350fc22..5393655 100644
--- a/lib/SILOptimizer/Transforms/SILSROA.cpp
+++ b/lib/SILOptimizer/Transforms/SILSROA.cpp
@@ -50,7 +50,7 @@
// Stores to AI.
llvm::SmallVector<StoreInst *, 4> Stores;
// Instructions which extract from aggregates.
- llvm::SmallVector<SILInstruction *, 4> ExtractInsts;
+ llvm::SmallVector<SingleValueInstruction *, 4> ExtractInsts;
// TupleType if we are visiting a tuple.
TupleType *TT = nullptr;
@@ -65,17 +65,17 @@
void chopUpAlloca(std::vector<AllocStackInst *> &Worklist);
private:
- SILInstruction *createAgg(SILBuilder &B, SILLocation Loc, SILType Ty,
- ArrayRef<SILValue> Elements);
- SILInstruction *createAggProjection(SILBuilder &B, SILLocation Loc,
- SILValue Operand, unsigned EltNo);
+ SILValue createAgg(SILBuilder &B, SILLocation Loc, SILType Ty,
+ ArrayRef<SILValue> Elements);
+ SILValue createAggProjection(SILBuilder &B, SILLocation Loc,
+ SILValue Operand, unsigned EltNo);
unsigned getEltNoForProjection(SILInstruction *Inst);
void createAllocas(llvm::SmallVector<AllocStackInst *, 4> &NewAllocations);
};
} // end anonymous namespace
-SILInstruction *
+SILValue
SROAMemoryUseAnalyzer::createAgg(SILBuilder &B, SILLocation Loc,
SILType Ty,
ArrayRef<SILValue> Elements) {
@@ -87,7 +87,7 @@
return B.createStruct(Loc, Ty, Elements);
}
-SILInstruction *
+SILValue
SROAMemoryUseAnalyzer::createAggProjection(SILBuilder &B, SILLocation Loc,
SILValue Operand,
unsigned EltNo) {
@@ -237,8 +237,8 @@
for (auto *NewAI : NewAllocations)
Elements.push_back(B.createLoad(LI->getLoc(), NewAI,
LoadOwnershipQualifier::Unqualified));
- auto *Agg = createAgg(B, LI->getLoc(), LI->getType().getObjectType(),
- Elements);
+ SILValue Agg = createAgg(B, LI->getLoc(), LI->getType().getObjectType(),
+ Elements);
LI->replaceAllUsesWith(Agg);
LI->eraseFromParent();
}
diff --git a/lib/SILOptimizer/Transforms/SimplifyCFG.cpp b/lib/SILOptimizer/Transforms/SimplifyCFG.cpp
index 940f2fd..fe6da5e 100644
--- a/lib/SILOptimizer/Transforms/SimplifyCFG.cpp
+++ b/lib/SILOptimizer/Transforms/SimplifyCFG.cpp
@@ -211,33 +211,31 @@
if (Inst->use_empty())
continue;
- if (Inst->hasValue()) {
- SILValue NewRes(AvailValPair.second);
+ SILValue NewRes(AvailValPair.second);
- SmallVector<UseWrapper, 16> UseList;
- // Collect the uses of the value.
- for (auto Use : Inst->getUses())
- UseList.push_back(UseWrapper(Use));
+ SmallVector<UseWrapper, 16> UseList;
+ // Collect the uses of the value.
+ for (auto Use : Inst->getUses())
+ UseList.push_back(UseWrapper(Use));
- SSAUp.Initialize(Inst->getType());
- SSAUp.AddAvailableValue(DestBB, Inst);
- SSAUp.AddAvailableValue(SrcBB, NewRes);
+ SSAUp.Initialize(Inst->getType());
+ SSAUp.AddAvailableValue(DestBB, Inst);
+ SSAUp.AddAvailableValue(SrcBB, NewRes);
- if (UseList.empty())
+ if (UseList.empty())
+ continue;
+
+ // Update all the uses.
+ for (auto U : UseList) {
+ Operand *Use = U;
+ SILInstruction *User = Use->getUser();
+ assert(User && "Missing user");
+
+ // Ignore uses in the same basic block.
+ if (User->getParent() == DestBB)
continue;
- // Update all the uses.
- for (auto U : UseList) {
- Operand *Use = U;
- SILInstruction *User = Use->getUser();
- assert(User && "Missing user");
-
- // Ignore uses in the same basic block.
- if (User->getParent() == DestBB)
- continue;
-
- SSAUp.RewriteUse(*Use);
- }
+ SSAUp.RewriteUse(*Use);
}
}
}
@@ -394,9 +392,9 @@
}
/// Create an enum element by extracting the operand of a switch_enum.
-static SILInstruction *createEnumElement(SILBuilder &Builder,
- SwitchEnumInst *SEI,
- EnumElementDecl *EnumElement) {
+static SILValue createEnumElement(SILBuilder &Builder,
+ SwitchEnumInst *SEI,
+ EnumElementDecl *EnumElement) {
auto EnumVal = SEI->getOperand();
// Do we have a payload.
auto EnumTy = EnumVal->getType();
@@ -411,9 +409,9 @@
/// Create a value for the condition of the terminator that flows along the edge
/// with 'EdgeIdx'. Insert it before the 'UserInst'.
-static SILInstruction *createValueForEdge(SILInstruction *UserInst,
- SILInstruction *DominatingTerminator,
- unsigned EdgeIdx) {
+static SILValue createValueForEdge(SILInstruction *UserInst,
+ SILInstruction *DominatingTerminator,
+ unsigned EdgeIdx) {
SILBuilderWithScope Builder(UserInst);
if (auto *CBI = dyn_cast<CondBranchInst>(DominatingTerminator))
@@ -557,7 +555,7 @@
// Replace dominated user instructions.
for (auto *UserInst : UsersToReplace) {
- SILInstruction *EdgeValue = nullptr;
+ SILValue EdgeValue;
for (auto &Op : UserInst->getAllOperands()) {
if (stripExpectIntrinsic(Op.get()) == DominatingCondition) {
if (!EdgeValue)
@@ -1031,8 +1029,14 @@
return false;
// We need to update ssa if a value is used outside the duplicated block.
- if (!NeedToUpdateSSA)
- NeedToUpdateSSA |= isUsedOutsideOfBlock(&Inst, DestBB);
+ if (!NeedToUpdateSSA) {
+ for (auto result : Inst.getResults()) {
+ if (isUsedOutsideOfBlock(result, DestBB)) {
+ NeedToUpdateSSA = true;
+ break;
+ }
+ }
+ }
}
// Don't jump thread through a potential header - this can produce irreducible
@@ -1087,7 +1091,9 @@
bool SimplifyCFG::simplifyBranchOperands(OperandValueArrayRef Operands) {
bool Simplified = false;
for (auto O = Operands.begin(), E = Operands.end(); O != E; ++O)
- if (auto *I = dyn_cast<SILInstruction>(*O))
+ // All of our interesting simplifications are on single-value instructions
+ // for now.
+ if (auto *I = dyn_cast<SingleValueInstruction>(*O))
if (SILValue Result = simplifyInstruction(I)) {
DEBUG(llvm::dbgs() << "simplify branch operand " << *I);
I->replaceAllUsesWith(Result);
@@ -1454,7 +1460,8 @@
Builder.createCondBranch(
BI->getLoc(),
invertExpectAndApplyTo(Builder, BI->getCondition(), Cond),
- FalseSide, FalseArgs, TrueSide, TrueArgs);
+ FalseSide, FalseArgs, TrueSide, TrueArgs, BI->getFalseBBCount(),
+ BI->getTrueBBCount());
BI->eraseFromParent();
addToWorklist(ThisBB);
return true;
@@ -1469,10 +1476,9 @@
if (TrueTrampolineDest && TrueTrampolineDest != FalseSide) {
DEBUG(llvm::dbgs() << "true-trampoline from bb" << ThisBB->getDebugID() <<
" to bb" << TrueTrampolineDest->getDebugID() << '\n');
- SILBuilderWithScope(BI)
- .createCondBranch(BI->getLoc(), BI->getCondition(),
- TrueTrampolineDest, TrueArgs,
- FalseSide, FalseArgs);
+ SILBuilderWithScope(BI).createCondBranch(
+ BI->getLoc(), BI->getCondition(), TrueTrampolineDest, TrueArgs,
+ FalseSide, FalseArgs, BI->getTrueBBCount(), BI->getFalseBBCount());
BI->eraseFromParent();
if (LoopHeaders.count(TrueSide))
@@ -1486,10 +1492,10 @@
if (FalseTrampolineDest && FalseTrampolineDest != TrueSide) {
DEBUG(llvm::dbgs() << "false-trampoline from bb" << ThisBB->getDebugID() <<
" to bb" << FalseTrampolineDest->getDebugID() << '\n');
- SILBuilderWithScope(BI)
- .createCondBranch(BI->getLoc(), BI->getCondition(),
- TrueSide, TrueArgs,
- FalseTrampolineDest, FalseArgs);
+ SILBuilderWithScope(BI).createCondBranch(
+ BI->getLoc(), BI->getCondition(), TrueSide, TrueArgs,
+ FalseTrampolineDest, FalseArgs, BI->getTrueBBCount(),
+ BI->getFalseBBCount());
BI->eraseFromParent();
if (LoopHeaders.count(FalseSide))
LoopHeaders.insert(ThisBB);
@@ -1518,9 +1524,9 @@
DEBUG(llvm::dbgs() << "true-trampoline from bb" << ThisBB->getDebugID() <<
" to bb" << TrueTrampolineBr->getDestBB()->getDebugID() << '\n');
SILBuilderWithScope(BI).createCondBranch(
- BI->getLoc(), BI->getCondition(),
- TrueTrampolineBr->getDestBB(), TrueTrampolineBr->getArgs(),
- FalseSide, FalseArgs);
+ BI->getLoc(), BI->getCondition(), TrueTrampolineBr->getDestBB(),
+ TrueTrampolineBr->getArgs(), FalseSide, FalseArgs, BI->getTrueBBCount(),
+ BI->getFalseBBCount());
BI->eraseFromParent();
if (LoopHeaders.count(TrueSide))
@@ -1536,9 +1542,9 @@
DEBUG(llvm::dbgs() << "false-trampoline from bb" << ThisBB->getDebugID() <<
" to bb" << FalseTrampolineBr->getDestBB()->getDebugID() << '\n');
SILBuilderWithScope(BI).createCondBranch(
- BI->getLoc(), BI->getCondition(),
- TrueSide, TrueArgs,
- FalseTrampolineBr->getDestBB(), FalseTrampolineBr->getArgs());
+ BI->getLoc(), BI->getCondition(), TrueSide, TrueArgs,
+ FalseTrampolineBr->getDestBB(), FalseTrampolineBr->getArgs(),
+ BI->getTrueBBCount(), BI->getFalseBBCount());
BI->eraseFromParent();
if (LoopHeaders.count(FalseSide))
LoopHeaders.insert(ThisBB);
@@ -1844,10 +1850,10 @@
switch (MaybeDead->getKind()) {
// These technically have side effects, but not ones that matter
// in a block that we shouldn't really reach...
- case ValueKind::StrongRetainInst:
- case ValueKind::StrongReleaseInst:
- case ValueKind::RetainValueInst:
- case ValueKind::ReleaseValueInst:
+ case SILInstructionKind::StrongRetainInst:
+ case SILInstructionKind::StrongReleaseInst:
+ case SILInstructionKind::RetainValueInst:
+ case SILInstructionKind::ReleaseValueInst:
break;
default:
@@ -1859,11 +1865,7 @@
}
}
- if (!MaybeDead->use_empty()) {
- auto Undef = SILUndef::get(MaybeDead->getType(), BB->getModule());
- MaybeDead->replaceAllUsesWith(Undef);
- }
-
+ MaybeDead->replaceAllUsesOfAllResultsWithUndef();
DeadInstrs.push_back(&*MaybeDead);
Changed = true;
}
@@ -2341,11 +2343,11 @@
// Add the default-entry of the original instruction as case-entry.
CaseBBs.push_back(std::make_pair(elementDecl.get(), SWI->getDefaultBB()));
- if (SWI->getKind() == ValueKind::SwitchEnumInst) {
+ if (isa<SwitchEnumInst>(SWI)) {
SILBuilderWithScope(SWI)
.createSwitchEnum(SWI->getLoc(), SWI->getOperand(), nullptr, CaseBBs);
} else {
- assert(SWI->getKind() == ValueKind::SwitchEnumAddrInst &&
+ assert(isa<SwitchEnumAddrInst>(SWI) &&
"unknown switch_enum instruction");
SILBuilderWithScope(SWI).createSwitchEnumAddr(
SWI->getLoc(), SWI->getOperand(), nullptr, CaseBBs);
@@ -2447,7 +2449,7 @@
deleteTriviallyDeadOperandsOfDeadArgument(MutableArrayRef<Operand> TermOperands,
unsigned DeadArgIndex, SILModule &M) {
Operand &Op = TermOperands[DeadArgIndex];
- auto *I = dyn_cast<SILInstruction>(Op.get());
+ auto *I = Op.get()->getDefiningInstruction();
if (!I)
return;
Op.set(SILUndef::get(Op.get()->getType(), M));
@@ -2484,7 +2486,8 @@
Builder.createCondBranch(CBI->getLoc(), CBI->getCondition(),
CBI->getTrueBB(), TrueArgs, CBI->getFalseBB(),
- FalseArgs);
+ FalseArgs, CBI->getTrueBBCount(),
+ CBI->getFalseBBCount());
Branch->eraseFromParent();
return;
}
@@ -2603,7 +2606,8 @@
}
B.createCondBranch(CBI->getLoc(), CBI->getCondition(), CBI->getTrueBB(),
- NewTrueValues, CBI->getFalseBB(), NewFalseValues);
+ NewTrueValues, CBI->getFalseBB(), NewFalseValues,
+ CBI->getTrueBBCount(), CBI->getFalseBBCount());
}
bool ArgumentSplitter::createNewArguments() {
@@ -2651,7 +2655,7 @@
NewArgumentValues.push_back(NewArg);
}
- SILInstruction *Agg = nullptr;
+ SingleValueInstruction *Agg;
{
SILBuilder B(ParentBB->begin());
@@ -2663,7 +2667,6 @@
auto Loc = RegularLocation::getAutoGeneratedLocation();
Agg = Projection::createAggFromFirstLevelProjections(
B, Loc, Arg->getType(), NewArgumentValues).get();
- assert(Agg->hasValue() && "Expected a result");
}
Arg->replaceAllUsesWith(Agg);
@@ -3141,7 +3144,7 @@
IntegerLiteralInst *Literal = nullptr;
/// The result value.
- SILInstruction *Result = nullptr;
+ SingleValueInstruction *Result = nullptr;
/// The block which contains the cond_br of the input value comparison
/// or the block which assigns the default value.
@@ -3390,11 +3393,14 @@
return false;
auto *Use = *A->use_begin();
- auto *User = cast<SILInstruction>(Use->getUser());
+ auto *User = Use->getUser();
+
+ // Handle projections.
if (!isa<StructExtractInst>(User) &&
!isa<TupleExtractInst>(User) &&
!isa<UncheckedEnumDataInst>(User))
return false;
+ auto proj = cast<SingleValueInstruction>(User);
// For now, just handle the case where all predecessors are
// unconditional branches.
@@ -3408,7 +3414,7 @@
if (isa<TupleInst>(BranchArg))
continue;
if (auto *EI = dyn_cast<EnumInst>(BranchArg)) {
- if (EI->getElement() == cast<UncheckedEnumDataInst>(User)->getElement())
+ if (EI->getElement() == cast<UncheckedEnumDataInst>(proj)->getElement())
continue;
}
return false;
@@ -3419,20 +3425,20 @@
DEBUG(llvm::dbgs() << "unwrap argument:" << *A);
A->replaceAllUsesWith(SILUndef::get(A->getType(), BB->getModule()));
auto *NewArg =
- BB->replacePHIArgument(i, User->getType(), ValueOwnershipKind::Owned);
- User->replaceAllUsesWith(NewArg);
+ BB->replacePHIArgument(i, proj->getType(), ValueOwnershipKind::Owned);
+ proj->replaceAllUsesWith(NewArg);
// Rewrite the branch operand for each incoming branch.
for (auto *Pred : BB->getPredecessorBlocks()) {
if (auto *Branch = cast<BranchInst>(Pred->getTerminator())) {
- auto V = getInsertedValue(cast<SILInstruction>(Branch->getArg(i)),
- User);
+ auto V = getInsertedValue(cast<SingleValueInstruction>(Branch->getArg(i)),
+ proj);
Branch->setOperand(i, V);
addToWorklist(Pred);
}
}
- User->eraseFromParent();
+ proj->eraseFromParent();
return true;
}
diff --git a/lib/SILOptimizer/Transforms/Sink.cpp b/lib/SILOptimizer/Transforms/Sink.cpp
index 427e511..40bb7ee 100644
--- a/lib/SILOptimizer/Transforms/Sink.cpp
+++ b/lib/SILOptimizer/Transforms/Sink.cpp
@@ -73,25 +73,27 @@
// TODO: We may want to delete debug instructions to allow us to sink more
// instructions.
- for (auto *Operand : II->getUses()) {
- SILInstruction *User = Operand->getUser();
+ for (auto result : II->getResults()) {
+ for (auto *Operand : result->getUses()) {
+ SILInstruction *User = Operand->getUser();
- // Check if the instruction is already in the user's block.
- if (User->getParent() == CurrentBlock) return false;
+ // Check if the instruction is already in the user's block.
+ if (User->getParent() == CurrentBlock) return false;
- // Record the block of the first user and move on to
- // other users.
- if (!Dest) {
- Dest = User->getParent();
- continue;
+ // Record the block of the first user and move on to
+ // other users.
+ if (!Dest) {
+ Dest = User->getParent();
+ continue;
+ }
+
+ // Find a location that dominates all users. If we did not find such
+ // a block or if it is the current block then bail out.
+ Dest = DT->findNearestCommonDominator(Dest, User->getParent());
+
+ if (!Dest || Dest == CurrentBlock)
+ return false;
}
-
- // Find a location that dominates all users. If we did not find such
- // a block or if it is the current block then bail out.
- Dest = DT->findNearestCommonDominator(Dest, User->getParent());
-
- if (!Dest || Dest == CurrentBlock)
- return false;
}
if (!Dest) return false;
diff --git a/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp b/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
index 5ca42e6..2c96bcf 100644
--- a/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
+++ b/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
@@ -59,13 +59,13 @@
FullApplySite NAI;
switch (AI.getInstruction()->getKind()) {
- case ValueKind::ApplyInst:
+ case SILInstructionKind::ApplyInst:
NAI = Builder.createApply(AI.getLoc(), AI.getCallee(),
AI.getSubstitutions(),
Ret,
cast<ApplyInst>(AI)->isNonThrowing());
break;
- case ValueKind::TryApplyInst: {
+ case SILInstructionKind::TryApplyInst: {
auto *TryApplyI = cast<TryApplyInst>(AI.getInstruction());
NAI = Builder.createTryApply(AI.getLoc(), AI.getCallee(),
AI.getSubstitutions(),
@@ -155,25 +155,26 @@
VirtBuilder.createUnreachable(AI.getLoc());
} else {
IdenBuilder.createBranch(AI.getLoc(), Continue,
- ArrayRef<SILValue>(IdenAI.getInstruction()));
+ { cast<ApplyInst>(IdenAI) });
VirtBuilder.createBranch(AI.getLoc(), Continue,
- ArrayRef<SILValue>(VirtAI.getInstruction()));
+ { cast<ApplyInst>(VirtAI) });
}
}
// Remove the old Apply instruction.
assert(AI.getInstruction() == &Continue->front() &&
"AI should be the first instruction in the split Continue block");
- if (!isa<TryApplyInst>(AI)) {
- AI.getInstruction()->replaceAllUsesWith(Arg);
- AI.getInstruction()->eraseFromParent();
- assert(!Continue->empty() &&
- "There should be at least a terminator after AI");
- } else {
+ if (isa<TryApplyInst>(AI)) {
AI.getInstruction()->eraseFromParent();
assert(Continue->empty() &&
"There should not be an instruction after try_apply");
Continue->eraseFromParent();
+ } else {
+ auto apply = cast<ApplyInst>(AI);
+ apply->replaceAllUsesWith(Arg);
+ apply->eraseFromParent();
+ assert(!Continue->empty() &&
+ "There should be at least a terminator after AI");
}
// Update the stats.
diff --git a/lib/SILOptimizer/Transforms/StackPromotion.cpp b/lib/SILOptimizer/Transforms/StackPromotion.cpp
index 07e9bbe..5c1d0c4 100644
--- a/lib/SILOptimizer/Transforms/StackPromotion.cpp
+++ b/lib/SILOptimizer/Transforms/StackPromotion.cpp
@@ -115,10 +115,10 @@
// Collect all use-points of the allocation. These are refcount instructions
// and apply instructions.
- llvm::SmallVector<ValueBase *, 8> BaseUsePoints;
+ llvm::SmallVector<SILNode *, 8> BaseUsePoints;
llvm::SmallVector<SILInstruction *, 8> UsePoints;
ConGraph->getUsePoints(Node, BaseUsePoints);
- for (ValueBase *UsePoint : BaseUsePoints) {
+ for (SILNode *UsePoint : BaseUsePoints) {
if (SILInstruction *I = dyn_cast<SILInstruction>(UsePoint)) {
UsePoints.push_back(I);
} else {
diff --git a/lib/SILOptimizer/Transforms/UnsafeGuaranteedPeephole.cpp b/lib/SILOptimizer/Transforms/UnsafeGuaranteedPeephole.cpp
index b17b337..dce03e0 100644
--- a/lib/SILOptimizer/Transforms/UnsafeGuaranteedPeephole.cpp
+++ b/lib/SILOptimizer/Transforms/UnsafeGuaranteedPeephole.cpp
@@ -64,8 +64,8 @@
auto *CurInst = &*It++;
if (CurInst != Retain &&
(isa<StrongRetainInst>(CurInst) || isa<RetainValueInst>(CurInst)) &&
- RCFI.getRCIdentityRoot(CurInst->getOperand(0)) ==
- SILValue(UnsafeGuaranteedI)) {
+ RCFI.getRCIdentityRoot(CurInst->getOperand(0))
+ ->getDefiningInstruction() == UnsafeGuaranteedI) {
CandidateRetain = CurInst;
continue;
}
@@ -80,8 +80,8 @@
if (CandidateRetain != nullptr && CurInst != Release &&
(isa<StrongReleaseInst>(CurInst) || isa<ReleaseValueInst>(CurInst)) &&
- RCFI.getRCIdentityRoot(CurInst->getOperand(0)) ==
- SILValue(UnsafeGuaranteedI)) {
+ RCFI.getRCIdentityRoot(CurInst->getOperand(0))
+ ->getDefiningInstruction() == UnsafeGuaranteedI) {
// Delete the retain/release pair.
InstsToDelete.push_back(CandidateRetain);
InstsToDelete.push_back(CurInst);
@@ -155,8 +155,8 @@
// %4 = builtin "unsafeGuaranteed"<Foo>(%0 : $Foo)
// %5 = tuple_extract %4 : $(Foo, Builtin.Int8), 0
// %6 = tuple_extract %4 : $(Foo, Builtin.Int8), 1
- SILInstruction *UnsafeGuaranteedValue;
- SILInstruction *UnsafeGuaranteedToken;
+ SingleValueInstruction *UnsafeGuaranteedValue;
+ SingleValueInstruction *UnsafeGuaranteedToken;
std::tie(UnsafeGuaranteedValue, UnsafeGuaranteedToken) =
getSingleUnsafeGuaranteedValueResult(UnsafeGuaranteedI);
diff --git a/lib/SILOptimizer/UtilityPasses/AADumper.cpp b/lib/SILOptimizer/UtilityPasses/AADumper.cpp
index 31e83c0..6da3331 100644
--- a/lib/SILOptimizer/UtilityPasses/AADumper.cpp
+++ b/lib/SILOptimizer/UtilityPasses/AADumper.cpp
@@ -41,8 +41,8 @@
for (auto *Arg : BB.getArguments())
Values.push_back(SILValue(Arg));
for (auto &II : BB)
- if (II.hasValue())
- Values.push_back(&II);
+ for (auto result : II.getResults())
+ Values.push_back(result);
}
return Values.size() > 1;
}
diff --git a/lib/SILOptimizer/UtilityPasses/BasicCalleePrinter.cpp b/lib/SILOptimizer/UtilityPasses/BasicCalleePrinter.cpp
index e59965f..cce51c8 100644
--- a/lib/SILOptimizer/UtilityPasses/BasicCalleePrinter.cpp
+++ b/lib/SILOptimizer/UtilityPasses/BasicCalleePrinter.cpp
@@ -35,7 +35,7 @@
void printCallees(FullApplySite FAS) {
llvm::outs() << "Function call site:\n";
- if (auto *Callee = dyn_cast<SILInstruction>(FAS.getCallee()))
+ if (auto *Callee = FAS.getCallee()->getDefiningInstruction())
llvm::outs() << *Callee;
llvm::outs() << *FAS.getInstruction();
diff --git a/lib/SILOptimizer/UtilityPasses/BugReducerTester.cpp b/lib/SILOptimizer/UtilityPasses/BugReducerTester.cpp
index ae03632..d03573d 100644
--- a/lib/SILOptimizer/UtilityPasses/BugReducerTester.cpp
+++ b/lib/SILOptimizer/UtilityPasses/BugReducerTester.cpp
@@ -88,7 +88,8 @@
SILFunction *F = getFunction()->getModule().getOrCreateSharedFunction(
RegularLocation::getAutoGeneratedLocation(), RuntimeCrasherFunctionName,
- FuncType, IsBare, IsNotTransparent, IsSerialized, IsNotThunk);
+ FuncType, IsBare, IsNotTransparent, IsSerialized, ProfileCounter(),
+ IsNotThunk);
if (F->isDefinition())
return F;
diff --git a/lib/SILOptimizer/UtilityPasses/IVInfoPrinter.cpp b/lib/SILOptimizer/UtilityPasses/IVInfoPrinter.cpp
index 725964c..b6ccb65 100644
--- a/lib/SILOptimizer/UtilityPasses/IVInfoPrinter.cpp
+++ b/lib/SILOptimizer/UtilityPasses/IVInfoPrinter.cpp
@@ -55,15 +55,17 @@
dumpIV(Info.getInductionVariableHeader(A), A);
}
- for (auto &I : BB)
- if (Info.isInductionVariable(&I)) {
- if (!FoundIV)
- llvm::errs() << "Induction variables for function: " <<
- F.getName() << "\n";
+ for (auto &I : BB) {
+ auto value = dyn_cast<SingleValueInstruction>(&I);
+ if (!value) continue;
+ if (!Info.isInductionVariable(value)) continue;
+ if (!FoundIV)
+ llvm::errs() << "Induction variables for function: " <<
+ F.getName() << "\n";
- FoundIV = true;
- dumpIV(Info.getInductionVariableHeader(&I), &I);
- }
+ FoundIV = true;
+ dumpIV(Info.getInductionVariableHeader(value), value);
+ }
}
if (FoundIV)
diff --git a/lib/SILOptimizer/UtilityPasses/InstCount.cpp b/lib/SILOptimizer/UtilityPasses/InstCount.cpp
index a63b9cf..9501a3f 100644
--- a/lib/SILOptimizer/UtilityPasses/InstCount.cpp
+++ b/lib/SILOptimizer/UtilityPasses/InstCount.cpp
@@ -53,13 +53,13 @@
STATISTIC(TotalSharedExternalFuncs, "Number of shared external funcs");
// Individual instruction statistics
-#define INST(Id, Parent, TextualName, MemBehavior, ReleasingBehavior) \
+#define INST(Id, Parent) \
STATISTIC(Num##Id, "Number of " #Id);
#include "swift/SIL/SILNodes.def"
namespace {
-struct InstCountVisitor : SILVisitor<InstCountVisitor> {
+struct InstCountVisitor : SILInstructionVisitor<InstCountVisitor> {
// We store these locally so that we do not continually check if the function
// is external or not. Instead, we just check once at the end and accumulate.
unsigned InstCount = 0;
@@ -67,16 +67,16 @@
void visitSILBasicBlock(SILBasicBlock *BB) {
BlockCount++;
- SILVisitor<InstCountVisitor>::visitSILBasicBlock(BB);
+ SILInstructionVisitor<InstCountVisitor>::visitSILBasicBlock(BB);
}
void visitSILFunction(SILFunction *F) {
- SILVisitor<InstCountVisitor>::visitSILFunction(F);
+ SILInstructionVisitor<InstCountVisitor>::visitSILFunction(F);
}
void visitValueBase(ValueBase *V) { }
-#define INST(Id, Parent, TextualName, MemBehavior, ReleasingBehavior) \
+#define INST(Id, Parent) \
void visit##Id(Id *I) { \
++Num##Id; \
++InstCount; \
diff --git a/lib/SILOptimizer/UtilityPasses/MemBehaviorDumper.cpp b/lib/SILOptimizer/UtilityPasses/MemBehaviorDumper.cpp
index dc41e52..a1d0eaa 100644
--- a/lib/SILOptimizer/UtilityPasses/MemBehaviorDumper.cpp
+++ b/lib/SILOptimizer/UtilityPasses/MemBehaviorDumper.cpp
@@ -33,9 +33,10 @@
for (auto &BB : Fn) {
for (auto *Arg : BB.getArguments())
Values.push_back(SILValue(Arg));
- for (auto &II : BB)
- if (II.hasValue())
- Values.push_back(&II);
+ for (auto &II : BB) {
+ for (auto result : II.getResults())
+ Values.push_back(result);
+ }
}
return Values.size() > 1;
}
@@ -81,7 +82,7 @@
bool Write = AA->mayWriteToMemory(&I, V);
bool SideEffects = AA->mayHaveSideEffects(&I, V);
llvm::outs() << "PAIR #" << PairCount++ << ".\n"
- << " " << SILValue(&I) << " " << V
+ << " " << I << " " << V
<< " r=" << Read << ",w=" << Write
<< ",se=" << SideEffects << "\n";
}
diff --git a/lib/SILOptimizer/UtilityPasses/RCIdentityDumper.cpp b/lib/SILOptimizer/UtilityPasses/RCIdentityDumper.cpp
index f04abf8..fa1a132 100644
--- a/lib/SILOptimizer/UtilityPasses/RCIdentityDumper.cpp
+++ b/lib/SILOptimizer/UtilityPasses/RCIdentityDumper.cpp
@@ -50,8 +50,7 @@
Results.push_back({Arg, RCId->getRCIdentityRoot(Arg)});
}
for (auto &II : BB) {
- if (II.hasValue()) {
- SILValue V(&II);
+ for (auto V : II.getResults()) {
ValueToValueIDMap[V] = ValueCount++;
Results.push_back({V, RCId->getRCIdentityRoot(V)});
}
diff --git a/lib/SILOptimizer/UtilityPasses/SimplifyUnreachableContainingBlocks.cpp b/lib/SILOptimizer/UtilityPasses/SimplifyUnreachableContainingBlocks.cpp
index f1ad790..c208b93 100644
--- a/lib/SILOptimizer/UtilityPasses/SimplifyUnreachableContainingBlocks.cpp
+++ b/lib/SILOptimizer/UtilityPasses/SimplifyUnreachableContainingBlocks.cpp
@@ -43,7 +43,7 @@
auto *I = &*II;
++II;
- I->replaceAllUsesWithUndef();
+ I->replaceAllUsesOfAllResultsWithUndef();
I->eraseFromParent();
}
}
diff --git a/lib/SILOptimizer/UtilityPasses/ValueOwnershipKindDumper.cpp b/lib/SILOptimizer/UtilityPasses/ValueOwnershipKindDumper.cpp
index 900abe9..67e5573 100644
--- a/lib/SILOptimizer/UtilityPasses/ValueOwnershipKindDumper.cpp
+++ b/lib/SILOptimizer/UtilityPasses/ValueOwnershipKindDumper.cpp
@@ -43,29 +43,33 @@
for (auto &BB : *F) {
// We only verify instructions right now.
for (auto &II : BB) {
- // If the instruction doesn't have a value, bail.
- if (!II.hasValue())
- continue;
- SILValue V(&II);
- llvm::outs() << "Visiting: " << II;
- auto Kind = V.getOwnershipKind();
- llvm::outs() << " " << Kind << "\n";
- if (Kind == ValueOwnershipKind::Any)
+ // If the instruction doesn't have any results, bail.
+ auto results = II.getResults();
+ if (results.empty())
continue;
- if (Kind == ValueOwnershipKind::Trivial) {
- if (auto *EI = dyn_cast<EnumInst>(V)) {
- checkEnumInstIsTrivial(EI);
+ llvm::outs() << "Visiting: " << II;
+
+ for (auto V : results) {
+ auto Kind = V.getOwnershipKind();
+ llvm::outs() << " " << Kind << "\n";
+ if (Kind == ValueOwnershipKind::Any)
continue;
- }
- SILType Ty = V->getType();
- if (!Ty.isTrivial(M) && !Ty.isAddress()) {
- llvm_unreachable("Error! Trivial ownership without trivial type\n");
- }
- } else {
- if (V->getType().isTrivial(M)) {
- llvm_unreachable(
- "Error! Non Trivial ownership with trivial type\n");
+
+ if (Kind == ValueOwnershipKind::Trivial) {
+ if (auto *EI = dyn_cast<EnumInst>(V)) {
+ checkEnumInstIsTrivial(EI);
+ continue;
+ }
+ SILType Ty = V->getType();
+ if (!Ty.isTrivial(M) && !Ty.isAddress()) {
+ llvm_unreachable("Error! Trivial ownership without trivial type\n");
+ }
+ } else {
+ if (V->getType().isTrivial(M)) {
+ llvm_unreachable(
+ "Error! Non Trivial ownership with trivial type\n");
+ }
}
}
}
diff --git a/lib/SILOptimizer/Utils/CFG.cpp b/lib/SILOptimizer/Utils/CFG.cpp
index 9632f61..452e58d 100644
--- a/lib/SILOptimizer/Utils/CFG.cpp
+++ b/lib/SILOptimizer/Utils/CFG.cpp
@@ -50,9 +50,10 @@
assert(FalseArgs.size() == Dest->getNumArguments());
}
- NewBr = Builder.createCondBranch(CBI->getLoc(), CBI->getCondition(),
- CBI->getTrueBB(), TrueArgs,
- CBI->getFalseBB(), FalseArgs);
+ NewBr = Builder.createCondBranch(
+ CBI->getLoc(), CBI->getCondition(), CBI->getTrueBB(), TrueArgs,
+ CBI->getFalseBB(), FalseArgs, CBI->getTrueBBCount(),
+ CBI->getFalseBBCount());
} else if (auto *BI = dyn_cast<BranchInst>(Branch)) {
SmallVector<SILValue, 8> Args;
@@ -120,9 +121,10 @@
assert(FalseArgs.size() == CBI->getFalseBB()->getNumArguments() &&
"Destination block's number of arguments must match");
- CBI = Builder.createCondBranch(CBI->getLoc(), CBI->getCondition(),
- CBI->getTrueBB(), TrueArgs,
- CBI->getFalseBB(), FalseArgs);
+ CBI = Builder.createCondBranch(
+ CBI->getLoc(), CBI->getCondition(), CBI->getTrueBB(), TrueArgs,
+ CBI->getFalseBB(), FalseArgs, CBI->getTrueBBCount(),
+ CBI->getFalseBBCount());
Branch->dropAllReferences();
Branch->eraseFromParent();
return CBI;
@@ -205,8 +207,9 @@
else
FalseDest = NewDest;
- B.createCondBranch(CondBr->getLoc(), CondBr->getCondition(),
- TrueDest, TrueArgs, FalseDest, FalseArgs);
+ B.createCondBranch(CondBr->getLoc(), CondBr->getCondition(), TrueDest,
+ TrueArgs, FalseDest, FalseArgs, CondBr->getTrueBBCount(),
+ CondBr->getFalseBBCount());
CondBr->dropAllReferences();
CondBr->eraseFromParent();
return;
@@ -256,7 +259,8 @@
auto SuccessBB = !EdgeIdx ? NewDest : CBI->getSuccessBB();
auto FailureBB = EdgeIdx ? NewDest : CBI->getFailureBB();
B.createCheckedCastBranch(CBI->getLoc(), CBI->isExact(), CBI->getOperand(),
- CBI->getCastType(), SuccessBB, FailureBB);
+ CBI->getCastType(), SuccessBB, FailureBB,
+ CBI->getTrueBBCount(), CBI->getFalseBBCount());
CBI->eraseFromParent();
return;
}
@@ -277,10 +281,12 @@
assert(EdgeIdx == 0 || EdgeIdx == 1 && "Invalid edge index");
auto SuccessBB = !EdgeIdx ? NewDest : CBI->getSuccessBB();
auto FailureBB = EdgeIdx ? NewDest : CBI->getFailureBB();
+ auto TrueCount = CBI->getTrueBBCount();
+ auto FalseCount = CBI->getFalseBBCount();
B.createCheckedCastAddrBranch(CBI->getLoc(), CBI->getConsumptionKind(),
CBI->getSrc(), CBI->getSourceType(),
CBI->getDest(), CBI->getTargetType(),
- SuccessBB, FailureBB);
+ SuccessBB, FailureBB, TrueCount, FalseCount);
CBI->eraseFromParent();
return;
}
@@ -372,8 +378,9 @@
FalseDest = NewDest;
}
- B.createCondBranch(CondBr->getLoc(), CondBr->getCondition(),
- TrueDest, TrueArgs, FalseDest, FalseArgs);
+ B.createCondBranch(CondBr->getLoc(), CondBr->getCondition(), TrueDest,
+ TrueArgs, FalseDest, FalseArgs, CondBr->getTrueBBCount(),
+ CondBr->getFalseBBCount());
CondBr->dropAllReferences();
CondBr->eraseFromParent();
return;
@@ -423,7 +430,8 @@
auto SuccessBB = OldDest == CBI->getSuccessBB() ? NewDest : CBI->getSuccessBB();
auto FailureBB = OldDest == CBI->getFailureBB() ? NewDest : CBI->getFailureBB();
B.createCheckedCastBranch(CBI->getLoc(), CBI->isExact(), CBI->getOperand(),
- CBI->getCastType(), SuccessBB, FailureBB);
+ CBI->getCastType(), SuccessBB, FailureBB,
+ CBI->getTrueBBCount(), CBI->getFalseBBCount());
CBI->eraseFromParent();
return;
}
@@ -447,10 +455,12 @@
assert(OldDest == CBI->getSuccessBB() || OldDest == CBI->getFailureBB() && "Invalid edge index");
auto SuccessBB = OldDest == CBI->getSuccessBB() ? NewDest : CBI->getSuccessBB();
auto FailureBB = OldDest == CBI->getFailureBB() ? NewDest : CBI->getFailureBB();
+ auto TrueCount = CBI->getTrueBBCount();
+ auto FalseCount = CBI->getFalseBBCount();
B.createCheckedCastAddrBranch(CBI->getLoc(), CBI->getConsumptionKind(),
- CBI->getSrc(), CBI->getSourceType(),
- CBI->getDest(), CBI->getTargetType(),
- SuccessBB, FailureBB);
+ CBI->getSrc(), CBI->getSourceType(),
+ CBI->getDest(), CBI->getTargetType(),
+ SuccessBB, FailureBB, TrueCount, FalseCount);
CBI->eraseFromParent();
return;
}
diff --git a/lib/SILOptimizer/Utils/Devirtualize.cpp b/lib/SILOptimizer/Utils/Devirtualize.cpp
index 0af9509..b5f3410 100644
--- a/lib/SILOptimizer/Utils/Devirtualize.cpp
+++ b/lib/SILOptimizer/Utils/Devirtualize.cpp
@@ -329,8 +329,8 @@
continue;
}
// Look through strong_pin instructions.
- if (isa<StrongPinInst>(V)) {
- WorkList.push_back(cast<SILInstruction>(V)->getOperand(0));
+ if (auto pin = dyn_cast<StrongPinInst>(V)) {
+ WorkList.push_back(pin->getOperand());
continue;
}
}
@@ -621,9 +621,10 @@
SmallVector<Operand *, 4> OriginalResultUses;
if (!isa<TryApplyInst>(AI)) {
- NewAI = B.createApply(AI.getLoc(), FRI, Subs, NewArgs,
- cast<ApplyInst>(AI)->isNonThrowing());
- ResultValue = NewAI.getInstruction();
+ auto apply = B.createApply(AI.getLoc(), FRI, Subs, NewArgs,
+ cast<ApplyInst>(AI)->isNonThrowing());
+ NewAI = apply;
+ ResultValue = apply;
} else {
auto *TAI = cast<TryApplyInst>(AI);
// Create new normal and error BBs only if:
@@ -693,7 +694,6 @@
Use->set(ResultValue);
}
}
- return std::make_pair(NewAI.getInstruction(), NewAI);
}
// We need to return a pair of values here:
@@ -890,7 +890,7 @@
// Check if any casting is required for the return value.
ResultValue = castValueToABICompatibleType(&Builder, Loc, NewAI,
NewAI->getType(), AI.getType());
- SAI = ApplySite::isa(NewAI);
+ SAI = NewAI;
}
if (auto *TAI = dyn_cast<TryApplyInst>(AI))
SAI = Builder.createTryApply(Loc, FRI, NewSubs, Arguments,
@@ -905,7 +905,7 @@
// Check if any casting is required for the return value.
ResultValue = castValueToABICompatibleType(
&Builder, Loc, NewPAI, NewPAI->getType(), PAI->getType());
- SAI = ApplySite::isa(NewPAI);
+ SAI = NewPAI;
}
NumWitnessDevirt++;
diff --git a/lib/SILOptimizer/Utils/FunctionSignatureOptUtils.cpp b/lib/SILOptimizer/Utils/FunctionSignatureOptUtils.cpp
index e088889..d6b8661 100644
--- a/lib/SILOptimizer/Utils/FunctionSignatureOptUtils.cpp
+++ b/lib/SILOptimizer/Utils/FunctionSignatureOptUtils.cpp
@@ -49,8 +49,10 @@
return true;
// Otherwise add all non-debug uses of I to the worklist.
- for (Operand *I : getNonDebugUses(SILValue(U)))
- Worklist.push_back(I->getUser());
+ for (auto result : U->getResults()) {
+ for (Operand *I : getNonDebugUses(result))
+ Worklist.push_back(I->getUser());
+ }
}
return false;
}
diff --git a/lib/SILOptimizer/Utils/GenericCloner.cpp b/lib/SILOptimizer/Utils/GenericCloner.cpp
index ca214a7..1b825bc 100644
--- a/lib/SILOptimizer/Utils/GenericCloner.cpp
+++ b/lib/SILOptimizer/Utils/GenericCloner.cpp
@@ -41,8 +41,8 @@
SILFunction *NewF = Orig->getModule().createFunction(
getSpecializedLinkage(Orig, Orig->getLinkage()), NewName,
ReInfo.getSpecializedType(), ReInfo.getSpecializedGenericEnvironment(),
- Orig->getLocation(), Orig->isBare(), Orig->isTransparent(),
- Serialized, Orig->isThunk(), Orig->getClassSubclassScope(),
+ Orig->getLocation(), Orig->isBare(), Orig->isTransparent(), Serialized,
+ Orig->getEntryCount(), Orig->isThunk(), Orig->getClassSubclassScope(),
Orig->getInlineStrategy(), Orig->getEffectsKind(), Orig,
Orig->getDebugScope());
for (auto &Attr : Orig->getSemanticsAttrs()) {
diff --git a/lib/SILOptimizer/Utils/Generics.cpp b/lib/SILOptimizer/Utils/Generics.cpp
index 1bf8554..d3a2592 100644
--- a/lib/SILOptimizer/Utils/Generics.cpp
+++ b/lib/SILOptimizer/Utils/Generics.cpp
@@ -2078,9 +2078,9 @@
} // anonymous namespace
SILFunction *ReabstractionThunkGenerator::createThunk() {
- SILFunction *Thunk =
- M.getOrCreateSharedFunction(Loc, ThunkName, ReInfo.getSubstitutedType(),
- IsBare, IsTransparent, Serialized, IsThunk);
+ SILFunction *Thunk = M.getOrCreateSharedFunction(
+ Loc, ThunkName, ReInfo.getSubstitutedType(), IsBare, IsTransparent,
+ Serialized, ProfileCounter(), IsThunk);
// Re-use an existing thunk.
if (!Thunk->empty())
return Thunk;
@@ -2300,7 +2300,7 @@
continue;
auto FAS = FullApplySite::isa(User);
- if (FAS && FAS.getCallee() == Apply.getInstruction())
+ if (FAS && FAS.getCallee() == PAI)
continue;
auto *PAIUser = dyn_cast<PartialApplyInst>(User);
diff --git a/lib/SILOptimizer/Utils/LoadStoreOptUtils.cpp b/lib/SILOptimizer/Utils/LoadStoreOptUtils.cpp
index b8775da..4c26167 100644
--- a/lib/SILOptimizer/Utils/LoadStoreOptUtils.cpp
+++ b/lib/SILOptimizer/Utils/LoadStoreOptUtils.cpp
@@ -114,7 +114,7 @@
Builder.setCurrentDebugScope(InsertPt->getFunction()->getDebugScope());
// We use an auto-generated SILLocation for now.
- NullablePtr<swift::SILInstruction> AI =
+ NullablePtr<swift::SingleValueInstruction> AI =
Projection::createAggFromFirstLevelProjections(
Builder, RegularLocation::getAutoGeneratedLocation(),
Base.getType(M).getObjectType(),
diff --git a/lib/SILOptimizer/Utils/Local.cpp b/lib/SILOptimizer/Utils/Local.cpp
index fdcb153..00e2707 100644
--- a/lib/SILOptimizer/Utils/Local.cpp
+++ b/lib/SILOptimizer/Utils/Local.cpp
@@ -87,11 +87,11 @@
swift::isInstructionTriviallyDead(SILInstruction *I) {
// At Onone, consider all uses, including the debug_info.
// This way, debug_info is preserved at Onone.
- if (!I->use_empty() &&
+ if (I->hasUsesOfAnyResult() &&
I->getModule().getOptions().Optimization <= SILOptions::SILOptMode::None)
return false;
- if (!onlyHaveDebugUses(I) || isa<TermInst>(I))
+ if (!onlyHaveDebugUsesOfAllResults(I) || isa<TermInst>(I))
return false;
if (auto *BI = dyn_cast<BuiltinInst>(I)) {
@@ -192,7 +192,7 @@
// If the operand is an instruction that is only used by the instruction
// being deleted, delete it.
- if (auto *OpValInst = dyn_cast<SILInstruction>(OpVal))
+ if (auto *OpValInst = OpVal->getDefiningInstruction())
if (!DeadInsts.count(OpValInst) &&
isInstructionTriviallyDead(OpValInst))
NextInsts.insert(OpValInst);
@@ -232,29 +232,32 @@
void swift::eraseUsesOfInstruction(SILInstruction *Inst,
CallbackTy Callback) {
- while (!Inst->use_empty()) {
- auto UI = Inst->use_begin();
- auto *User = UI->getUser();
- assert(User && "User should never be NULL!");
+ for (auto result : Inst->getResults()) {
+ while (!result->use_empty()) {
+ auto UI = result->use_begin();
+ auto *User = UI->getUser();
+ assert(User && "User should never be NULL!");
- // If the instruction itself has any uses, recursively zap them so that
- // nothing uses this instruction.
- eraseUsesOfInstruction(User, Callback);
+ // If the instruction itself has any uses, recursively zap them so that
+ // nothing uses this instruction.
+ eraseUsesOfInstruction(User, Callback);
- // Walk through the operand list and delete any random instructions that
- // will become trivially dead when this instruction is removed.
+ // Walk through the operand list and delete any random instructions that
+ // will become trivially dead when this instruction is removed.
- for (auto &Op : User->getAllOperands()) {
- if (auto *OpI = dyn_cast<SILInstruction>(Op.get())) {
- // Don't recursively delete the pointer we're getting in.
- if (OpI != Inst) {
- Op.drop();
- recursivelyDeleteTriviallyDeadInstructions(OpI, false, Callback);
+ for (auto &Op : User->getAllOperands()) {
+ if (auto *OpI = Op.get()->getDefiningInstruction()) {
+ // Don't recursively delete the instruction we're working on.
+ // FIXME: what if we're being recursively invoked?
+ if (OpI != Inst) {
+ Op.drop();
+ recursivelyDeleteTriviallyDeadInstructions(OpI, false, Callback);
+ }
}
}
+ Callback(User);
+ User->eraseFromParent();
}
- Callback(User);
- User->eraseFromParent();
}
}
@@ -267,7 +270,8 @@
continue;
// Collect the users of this instruction.
- collectUsesOfValue(User, Insts);
+ for (auto result : User->getResults())
+ collectUsesOfValue(result, Insts);
}
}
@@ -280,7 +284,7 @@
// Its not safe to do recursively delete here as some of the SILInstruction
// maybe tracked by this set.
for (auto I : Insts) {
- I->replaceAllUsesWithUndef();
+ I->replaceAllUsesOfAllResultsWithUndef();
I->eraseFromParent();
}
}
@@ -288,19 +292,13 @@
// Devirtualization of functions with covariant return types produces
// a result that is not an apply, but takes an apply as an
// argument. Attempt to dig the apply out from this result.
-FullApplySite swift::findApplyFromDevirtualizedResult(SILInstruction *I) {
- if (!I)
- return FullApplySite();
-
- if (auto Apply = FullApplySite::isa(I))
+FullApplySite swift::findApplyFromDevirtualizedResult(SILValue V) {
+ if (auto Apply = FullApplySite::isa(V))
return Apply;
- if (!I->getNumOperands())
- return FullApplySite();
-
- if (isa<UpcastInst>(I) || isa<EnumInst>(I) || isa<UncheckedRefCastInst>(I))
+ if (isa<UpcastInst>(V) || isa<EnumInst>(V) || isa<UncheckedRefCastInst>(V))
return findApplyFromDevirtualizedResult(
- dyn_cast<SILInstruction>(I->getOperand(0)));
+ cast<SingleValueInstruction>(V)->getOperand(0));
return FullApplySite();
}
@@ -332,7 +330,7 @@
void swift::replaceDeadApply(ApplySite Old, ValueBase *New) {
auto *OldApply = Old.getInstruction();
if (!isa<TryApplyInst>(OldApply))
- OldApply->replaceAllUsesWith(New);
+ cast<SingleValueInstruction>(OldApply)->replaceAllUsesWith(New);
recursivelyDeleteTriviallyDeadInstructions(OldApply, true);
}
@@ -399,9 +397,7 @@
assert(FalseArgs.size() == Dest->getNumArguments());
}
- return Builder.createCondBranch(CBI->getLoc(), CBI->getCondition(),
- CBI->getTrueBB(), TrueArgs,
- CBI->getFalseBB(), FalseArgs);
+ return Builder.createCondBranch(CBI->getLoc(), CBI->getCondition(), CBI->getTrueBB(), TrueArgs, CBI->getFalseBB(), FalseArgs, CBI->getTrueBBCount(), CBI->getFalseBBCount());
}
if (auto *BI = dyn_cast<BranchInst>(Branch)) {
@@ -444,7 +440,7 @@
auto *Inst = &BB->back();
// Replace any still-remaining uses with undef values and erase.
- Inst->replaceAllUsesWithUndef();
+ Inst->replaceAllUsesOfAllResultsWithUndef();
Inst->eraseFromParent();
}
}
@@ -673,7 +669,7 @@
/// concatenation of string literals.
///
/// Returns a new instruction if optimization was possible.
- SILInstruction *optimize();
+ SingleValueInstruction *optimize();
};
} // end anonymous namespace
@@ -834,7 +830,7 @@
return IsAsciiLeft && IsAsciiRight;
}
-SILInstruction *StringConcatenationOptimizer::optimize() {
+SingleValueInstruction *StringConcatenationOptimizer::optimize() {
// Bail out if string literals concatenation optimization is
// not possible.
if (!extractStringConcatOperands())
@@ -880,7 +876,8 @@
}
/// Top level entry point
-SILInstruction *swift::tryToConcatenateStrings(ApplyInst *AI, SILBuilder &B) {
+SingleValueInstruction *
+swift::tryToConcatenateStrings(ApplyInst *AI, SILBuilder &B) {
return StringConcatenationOptimizer(AI, B).optimize();
}
@@ -890,13 +887,13 @@
static bool useDoesNotKeepClosureAlive(const SILInstruction *I) {
switch (I->getKind()) {
- case ValueKind::StrongRetainInst:
- case ValueKind::StrongReleaseInst:
- case ValueKind::CopyValueInst:
- case ValueKind::DestroyValueInst:
- case ValueKind::RetainValueInst:
- case ValueKind::ReleaseValueInst:
- case ValueKind::DebugValueInst:
+ case SILInstructionKind::StrongRetainInst:
+ case SILInstructionKind::StrongReleaseInst:
+ case SILInstructionKind::CopyValueInst:
+ case SILInstructionKind::DestroyValueInst:
+ case SILInstructionKind::RetainValueInst:
+ case SILInstructionKind::ReleaseValueInst:
+ case SILInstructionKind::DebugValueInst:
return true;
default:
return false;
@@ -1078,7 +1075,7 @@
}
/// TODO: Generalize this to general objects.
-bool swift::tryDeleteDeadClosure(SILInstruction *Closure,
+bool swift::tryDeleteDeadClosure(SingleValueInstruction *Closure,
InstModCallbacks Callbacks) {
// We currently only handle locally identified values that do not escape. We
// also assume that the partial apply does not capture any addresses.
@@ -1108,9 +1105,10 @@
// Then delete all user instructions.
for (auto *User : Tracker.getTrackedUsers()) {
- assert(!User->hasValue() && "We expect only ARC operations without "
- "results. This is true b/c of "
- "isARCOperationRemovableIfObjectIsDead");
+ assert(User->getResults().empty()
+ && "We expect only ARC operations without "
+ "results. This is true b/c of "
+ "isARCOperationRemovableIfObjectIsDead");
Callbacks.DeleteInst(User);
}
@@ -1452,9 +1450,10 @@
Builder.setInsertionPoint(CastSuccessBB);
SrcOp = CastSuccessBB->getArgument(0);
} else {
- NewI = Builder.createUnconditionalCheckedCast(Loc, Load,
- SILBridgedTy);
- SrcOp = NewI;
+ auto cast = Builder.createUnconditionalCheckedCast(Loc, Load,
+ SILBridgedTy);
+ NewI = cast;
+ SrcOp = cast;
}
} else {
SrcOp = Src;
@@ -1745,8 +1744,8 @@
&& "unsupported convention for bridging conversion");
// Need to make a copy of the source, can be changed in ObjC
auto BridgeStack = Builder.createAllocStack(Loc, Src->getType());
- Src = Builder.createCopyAddr(Loc, Src, BridgeStack, IsNotTake,
- IsInitialization);
+ Builder.createCopyAddr(Loc, Src, BridgeStack, IsNotTake,
+ IsInitialization);
break;
}
case ParameterConvention::Indirect_Inout:
@@ -1778,15 +1777,16 @@
auto ConvTy = NewAI->getType();
auto DestTy = Dest->getType().getObjectType();
SILValue CastedValue;
- if ((ConvTy == DestTy || DestTy.isExactSuperclassOf(ConvTy))) {
- CastedValue = SILValue(
- (ConvTy == DestTy) ? NewI : Builder.createUpcast(Loc, NewAI, DestTy));
+ if (ConvTy == DestTy) {
+ CastedValue = NewAI;
+ } else if (DestTy.isExactSuperclassOf(ConvTy)) {
+ CastedValue = Builder.createUpcast(Loc, NewAI, DestTy);
} else if (ConvTy.isExactSuperclassOf(DestTy)) {
// The downcast from a base class to derived class may fail.
if (isConditional) {
// In case of a conditional cast, we should handle it gracefully.
auto CondBrSuccessBB =
- NewAI->getFunction()->createBasicBlock(NewAI->getParentBlock());
+ NewAI->getFunction()->createBasicBlock(NewAI->getParent());
CondBrSuccessBB->createPHIArgument(DestTy, ValueOwnershipKind::Owned,
nullptr);
Builder.createCheckedCastBranch(Loc, /* isExact*/ false, NewAI, DestTy,
@@ -1813,7 +1813,7 @@
}
NewI = Builder.createStore(Loc, CastedValue, Dest,
StoreOwnershipQualifier::Unqualified);
- if (isConditional && NewI->getParentBlock() != NewAI->getParentBlock()) {
+ if (isConditional && NewI->getParent() != NewAI->getParent()) {
Builder.createBranch(Loc, SuccessBB);
}
}
@@ -2106,7 +2106,6 @@
Src, Dest, SourceType, TargetType, nullptr, nullptr);
if (BridgedI) {
- CastedValue = BridgedI;
llvm_unreachable(
"Bridged casts cannot be expressed by checked_cast_br yet");
} else {
@@ -2195,7 +2194,6 @@
Src, Dest, SourceType, TargetType, nullptr, nullptr);
if (BridgedI) {
- CastedValue = BridgedI;
llvm_unreachable(
"Bridged casts cannot be expressed by checked_cast_value_br yet");
} else {
@@ -2294,8 +2292,9 @@
Inst->getTargetType())) {
SILBuilderWithScope B(Inst);
auto NewI = B.createCheckedCastBranch(
- Loc, false /*isExact*/, MI,
- Dest->getType().getObjectType(), SuccessBB, FailureBB);
+ Loc, false /*isExact*/, MI, Dest->getType().getObjectType(),
+ SuccessBB, FailureBB, Inst->getTrueBBCount(),
+ Inst->getFalseBBCount());
SuccessBB->createPHIArgument(Dest->getType().getObjectType(),
ValueOwnershipKind::Owned);
B.setInsertionPoint(SuccessBB->begin());
@@ -2341,10 +2340,9 @@
if (auto *IEMI = dyn_cast<InitExistentialMetatypeInst>(Op)) {
if (auto *MI = dyn_cast<MetatypeInst>(IEMI->getOperand())) {
SILBuilderWithScope B(Inst);
- auto *NewI = B.createCheckedCastBranch(Loc, /* isExact */ false, MI,
- LoweredTargetType,
- SuccessBB,
- FailureBB);
+ auto *NewI = B.createCheckedCastBranch(
+ Loc, /* isExact */ false, MI, LoweredTargetType, SuccessBB, FailureBB,
+ Inst->getTrueBBCount(), Inst->getFalseBBCount());
EraseInstAction(Inst);
return NewI;
}
@@ -2410,10 +2408,9 @@
FoundIEI->getTypeDependentOperands());
auto *MI = B.createMetatype(FoundIEI->getLoc(), SILMetaTy);
- auto *NewI = B.createCheckedCastBranch(Loc, /* isExact */ false, MI,
- LoweredTargetType,
- SuccessBB,
- FailureBB);
+ auto *NewI = B.createCheckedCastBranch(
+ Loc, /* isExact */ false, MI, LoweredTargetType, SuccessBB,
+ FailureBB, Inst->getTrueBBCount(), Inst->getFalseBBCount());
EraseInstAction(Inst);
return NewI;
}
@@ -2470,10 +2467,9 @@
FoundIERI->getTypeDependentOperands());
auto *MI = B.createMetatype(FoundIERI->getLoc(), SILMetaTy);
- auto *NewI = B.createCheckedCastBranch(Loc, /* isExact */ false, MI,
- LoweredTargetType,
- SuccessBB,
- FailureBB);
+ auto *NewI = B.createCheckedCastBranch(
+ Loc, /* isExact */ false, MI, LoweredTargetType, SuccessBB,
+ FailureBB, Inst->getTrueBBCount(), Inst->getFalseBBCount());
EraseInstAction(Inst);
return NewI;
}
@@ -2538,10 +2534,12 @@
false, Src, SILValue(), SourceType,
TargetType, nullptr, nullptr);
if (NewI) {
- ReplaceInstUsesAction(Inst, NewI);
+ // FIXME: I'm not sure why this is true!
+ auto newValue = cast<SingleValueInstruction>(NewI);
+ ReplaceInstUsesAction(Inst, newValue);
EraseInstAction(Inst);
WillSucceedAction();
- return NewI;
+ return newValue;
}
// If the cast may succeed or fail and can't be optimized into a bridging
@@ -2571,8 +2569,6 @@
EraseInstAction(Inst);
WillSucceedAction();
return Result;
-
- return nullptr;
}
/// Deletes all instructions after \p UnreachableInst except dealloc_stack
@@ -2590,7 +2586,7 @@
DeallocStack->moveBefore(TrapInst);
continue;
}
- CurInst->replaceAllUsesWithUndef();
+ CurInst->replaceAllUsesOfAllResultsWithUndef();
EraseInstAction(CurInst);
}
}
@@ -2679,7 +2675,6 @@
}
};
- Inst->replaceAllUsesWithUndef();
return true;
}
}
@@ -2725,7 +2720,6 @@
StoreOwnershipQualifier::Unqualified);
}
auto *TrapI = Builder.createBuiltinTrap(Loc);
- Inst->replaceAllUsesWithUndef();
EraseInstAction(Inst);
Builder.setInsertionPoint(std::next(SILBasicBlock::iterator(TrapI)));
auto *UnreachableInst =
@@ -2802,7 +2796,6 @@
return nullptr;
}
- Inst->replaceAllUsesWithUndef();
EraseInstAction(Inst);
WillSucceedAction();
}
@@ -2810,21 +2803,22 @@
return nullptr;
}
-bool swift::simplifyUsers(SILInstruction *I) {
+bool swift::simplifyUsers(SingleValueInstruction *I) {
bool Changed = false;
for (auto UI = I->use_begin(), UE = I->use_end(); UI != UE; ) {
SILInstruction *User = UI->getUser();
++UI;
- if (!User->hasValue())
- continue;
- SILValue S = simplifyInstruction(User);
+ auto SVI = dyn_cast<SingleValueInstruction>(User);
+ if (!SVI) continue;
+
+ SILValue S = simplifyInstruction(SVI);
if (!S)
continue;
- User->replaceAllUsesWith(S);
- User->eraseFromParent();
+ SVI->replaceAllUsesWith(S);
+ SVI->eraseFromParent();
Changed = true;
}
@@ -2874,57 +2868,50 @@
bool
swift::analyzeStaticInitializer(SILValue V,
SmallVectorImpl<SILInstruction *> &Insns) {
- auto I = dyn_cast<SILInstruction>(V);
- if (!I)
- return false;
+ // Save every instruction we see.
+ // TODO: MultiValueInstruction?
+ if (auto I = dyn_cast<SingleValueInstruction>(V))
+ Insns.push_back(I);
- while (true) {
- if (!isa<AllocGlobalInst>(I))
- Insns.push_back(I);
- if (auto *SI = dyn_cast<StructInst>(I)) {
- // If it is not a struct which is a simple type, bail.
- if (!isSimpleType(SI->getType(), I->getModule()))
+ if (auto *SI = dyn_cast<StructInst>(V)) {
+ // If it is not a struct which is a simple type, bail.
+ if (!isSimpleType(SI->getType(), SI->getModule()))
+ return false;
+ for (auto &Op: SI->getAllOperands()) {
+ // If one of the struct instruction operands is not
+ // a simple initializer, bail.
+ if (!analyzeStaticInitializer(Op.get(), Insns))
return false;
- for (auto &Op: SI->getAllOperands()) {
- // If one of the struct instruction operands is not
- // a simple initializer, bail.
- if (!analyzeStaticInitializer(Op.get(), Insns))
- return false;
- }
- return true;
- } if (auto *TI = dyn_cast<TupleInst>(I)) {
- // If it is not a tuple which is a simple type, bail.
- if (!isSimpleType(TI->getType(), I->getModule()))
+ }
+ return true;
+ } else if (auto *TI = dyn_cast<TupleInst>(V)) {
+ // If it is not a tuple which is a simple type, bail.
+ if (!isSimpleType(TI->getType(), TI->getModule()))
+ return false;
+ for (auto &Op: TI->getAllOperands()) {
+ // If one of the struct instruction operands is not
+ // a simple initializer, bail.
+ if (!analyzeStaticInitializer(Op.get(), Insns))
return false;
- for (auto &Op: TI->getAllOperands()) {
- // If one of the struct instruction operands is not
- // a simple initializer, bail.
- if (!analyzeStaticInitializer(Op.get(), Insns))
- return false;
+ }
+ return true;
+ } else if (auto *bi = dyn_cast<BuiltinInst>(V)) {
+ switch (bi->getBuiltinInfo().ID) {
+ case BuiltinValueKind::FPTrunc:
+ if (auto *LI = dyn_cast<LiteralInst>(bi->getArguments()[0])) {
+ return analyzeStaticInitializer(LI, Insns);
}
- return true;
- } else {
- if (auto *bi = dyn_cast<BuiltinInst>(I)) {
- switch (bi->getBuiltinInfo().ID) {
- case BuiltinValueKind::FPTrunc:
- if (auto *LI = dyn_cast<LiteralInst>(bi->getArguments()[0])) {
- I = LI;
- continue;
- }
- break;
- default:
- return false;
- }
- }
-
- if (I->getKind() == ValueKind::IntegerLiteralInst
- || I->getKind() == ValueKind::FloatLiteralInst
- || I->getKind() == ValueKind::StringLiteralInst)
- return true;
+ return false;
+ default:
return false;
}
+ } else if (isa<IntegerLiteralInst>(V)
+ || isa<FloatLiteralInst>(V)
+ || isa<StringLiteralInst>(V)) {
+ return true;
+ } else {
+ return false;
}
- return false;
}
/// Replace load sequence which may contain
@@ -2933,7 +2920,7 @@
/// starting with the innermost struct_element_addr
/// Move into utils.
void swift::replaceLoadSequence(SILInstruction *I,
- SILInstruction *Value,
+ SILValue Value,
SILBuilder &B) {
if (auto *LI = dyn_cast<LoadInst>(I)) {
LI->replaceAllUsesWith(Value);
@@ -3038,7 +3025,7 @@
case ValueKind::RefElementAddrInst:
case ValueKind::RefTailAddrInst:
case ValueKind::UncheckedTakeEnumDataAddrInst: {
- auto *Inst = cast<SILInstruction>(V);
+ auto *Inst = cast<SingleValueInstruction>(V);
// We are done once the current projection dominates the insert point.
if (DomTree->dominates(Inst->getParent(), InsertBefore->getParent()))
return;
diff --git a/lib/SILOptimizer/Utils/OptimizerStatsUtils.cpp b/lib/SILOptimizer/Utils/OptimizerStatsUtils.cpp
index bce9658..c702246 100644
--- a/lib/SILOptimizer/Utils/OptimizerStatsUtils.cpp
+++ b/lib/SILOptimizer/Utils/OptimizerStatsUtils.cpp
@@ -79,51 +79,79 @@
namespace {
/// The total number of different kinds of SILInstructions.
-constexpr unsigned SILInstructionsNum = int(ValueKind::Last_SILInstruction) + 1;
+constexpr unsigned NumSILInstructions =
+ unsigned(SILNodeKind::Last_SILInstruction)
+ - unsigned(SILNodeKind::First_SILInstruction)
+ + 1;
+
+static unsigned getIndexForKind(SILInstructionKind kind) {
+ return unsigned(kind) - unsigned(SILNodeKind::First_SILInstruction);
+}
/// A set of counters, one per SILInstruction kind.
-using InstructionCounts = SmallVector<int, SILInstructionsNum>;
+class InstructionCounts {
+ unsigned Counts[NumSILInstructions] = {};
+
+public:
+ constexpr InstructionCounts() {}
+
+ unsigned &operator[](SILInstructionKind kind) {
+ return Counts[getIndexForKind(kind)];
+ }
+
+ void addAll(const InstructionCounts &other) {
+ for (unsigned i = 0; i != NumSILInstructions; ++i) {
+ Counts[i] += other.Counts[i];
+ }
+ }
+
+ void subAll(const InstructionCounts &other) {
+ for (unsigned i = 0; i != NumSILInstructions; ++i) {
+ Counts[i] -= other.Counts[i];
+ }
+ }
+};
/// A helper type to parse a comma separated list of SIL instruction names
/// provided as argument of the -sil-stats-only-instructions options.
class StatsOnlyInstructionsOpt {
- /// If ComputeInstCounts[i] is non-zero, this kind of SILInstruction should be
- /// tracked.
- InstructionCounts ComputeInstCounts;
+ bool ShouldComputeInstCounts[NumSILInstructions] = {};
+
/// The number of different kinds of SILInstructions to be tracked.
- int InstCountsNum = 0;
+ unsigned NumInstCounts = 0;
public:
- StatsOnlyInstructionsOpt() : ComputeInstCounts(SILInstructionsNum) {}
+ constexpr StatsOnlyInstructionsOpt() {}
- void operator=(const std::string &Val) {
- if (Val.empty())
+ void operator=(StringRef val) {
+ if (val.empty())
return;
- if (Val == "all") {
- for (auto &Inst : ComputeInstCounts) {
- Inst = 1;
+ if (val == "all") {
+ for (auto &inst : ShouldComputeInstCounts) {
+ inst = true;
}
- InstCountsNum = ComputeInstCounts.size();
+ NumInstCounts = NumSILInstructions;
return;
}
SmallVector<StringRef, 8> statsInstNames;
- StringRef(Val).split(statsInstNames, ',', -1, false);
+ val.split(statsInstNames, ',', -1, false);
for (auto instName : statsInstNames) {
// Check if it is a known instruction.
- auto Kind = getSILInstructionKind(instName);
- if (!ComputeInstCounts[int(Kind)] ){
- ComputeInstCounts[int(Kind)] = 1;
- InstCountsNum++;
+ auto kind = getSILInstructionKind(instName);
+ unsigned index = getIndexForKind(kind);
+ if (!ShouldComputeInstCounts[index]) {
+ ShouldComputeInstCounts[index] = true;
+ NumInstCounts++;
}
}
}
- bool shouldComputeInstCount(SILInstructionKind Kind) const {
- return ComputeInstCounts[int(Kind)] != 0;
+ bool shouldComputeInstCount(SILInstructionKind kind) const {
+ return ShouldComputeInstCounts[getIndexForKind(kind)];
}
int getInstCountsNum() const {
- return InstCountsNum;
+ return NumInstCounts;
}
};
@@ -245,7 +273,7 @@
InstructionCounts InstCounts;
FunctionStat(SILFunction *F);
- FunctionStat() : InstCounts(SILInstructionsNum) {}
+ FunctionStat() {}
void print(llvm::raw_ostream &stream) const {
stream << "FunctionStat("
@@ -280,7 +308,7 @@
/// Instruction counts per SILInstruction kind.
InstructionCounts InstCounts;
- ModuleStat() : InstCounts(SILInstructionsNum) {}
+ ModuleStat() {}
/// Add the stats for a given function to the total module stats.
void addFunctionStat(FunctionStat &Stat) {
@@ -289,9 +317,7 @@
++FunctionCount;
if (!StatsOnlyInstructionsOptLoc.getInstCountsNum())
return;
- for (unsigned i : indices(InstCounts)) {
- InstCounts[i] += Stat.InstCounts[i];
- }
+ InstCounts.addAll(Stat.InstCounts);
}
/// Subtract the stats for a given function from total module stats.
@@ -301,9 +327,7 @@
--FunctionCount;
if (!StatsOnlyInstructionsOptLoc.getInstCountsNum())
return;
- for (unsigned i : indices(InstCounts)) {
- InstCounts[i] -= Stat.InstCounts[i];
- }
+ InstCounts.subAll(Stat.InstCounts);
}
/// Add the stats about current memory usage.
@@ -338,7 +362,7 @@
// A helper type to collect the stats about the number of instructions and basic
// blocks.
-struct InstCountVisitor : SILVisitor<InstCountVisitor> {
+struct InstCountVisitor : SILInstructionVisitor<InstCountVisitor> {
int BlockCount = 0;
int InstCount = 0;
InstructionCounts &InstCounts;
@@ -355,21 +379,13 @@
void visitSILBasicBlock(SILBasicBlock *BB) {
++BlockCount;
- SILVisitor<InstCountVisitor>::visitSILBasicBlock(BB);
+ SILInstructionVisitor<InstCountVisitor>::visitSILBasicBlock(BB);
}
- void visitSILFunction(SILFunction *F) {
- SILVisitor<InstCountVisitor>::visitSILFunction(F);
+ void visit(SILInstruction *I) {
+ ++InstCount;
+ ++InstCounts[I->getKind()];
}
-
- void visitValueBase(ValueBase *V) {}
-
-#define INST(Id, Parent, TextualName, MemBehavior, ReleasingBehavior) \
- void visit##Id(Id *I) { \
- ++InstCount; \
- ++InstCounts[int(I->getKind())]; \
- }
-#include "swift/SIL/SILNodes.def"
};
/// A helper type to store different parameters related to the current transform.
@@ -673,15 +689,14 @@
if (!StatsOnlyInstructionsOptLoc.getInstCountsNum())
return;
- for (int i = 0, e = SILInstructionsNum; i < e; ++i) {
- if (!Stat.InstCounts[i])
+ for (auto kind : allSILInstructionKinds()) {
+ if (!Stat.InstCounts[kind])
continue;
- SILInstructionKind Kind = SILInstructionKind(i);
- if (!StatsOnlyInstructionsOptLoc.shouldComputeInstCount(Kind))
+ if (!StatsOnlyInstructionsOptLoc.shouldComputeInstCount(kind))
continue;
std::string CounterName = "inst_";
- CounterName += getSILInstructionName(Kind);
- printCounterValue("function_history", CounterName, Stat.InstCounts[i],
+ CounterName += getSILInstructionName(kind);
+ printCounterValue("function_history", CounterName, Stat.InstCounts[kind],
F->getName(), Ctx);
}
}
@@ -822,19 +837,18 @@
if (!StatsOnlyInstructionsOptLoc.getInstCountsNum())
return;
- for (int i = 0, e = SILInstructionsNum; i < e; ++i) {
+ for (auto kind : allSILInstructionKinds()) {
// Do not print anything, if there is no change.
- if (OldStat.InstCounts[i] == NewStat.InstCounts[i])
+ if (OldStat.InstCounts[kind] == NewStat.InstCounts[kind])
continue;
- SILInstructionKind Kind = SILInstructionKind(i);
- if (!StatsOnlyInstructionsOptLoc.shouldComputeInstCount(Kind))
+ if (!StatsOnlyInstructionsOptLoc.shouldComputeInstCount(kind))
continue;
SmallString<64> CounterName("inst_");
- CounterName += getSILInstructionName(Kind);
+ CounterName += getSILInstructionName(kind);
auto DeltaCounterKindCount =
- computeDelta(OldStat.InstCounts[i], NewStat.InstCounts[i]);
+ computeDelta(OldStat.InstCounts[kind], NewStat.InstCounts[kind]);
printCounterChange("module", CounterName, DeltaCounterKindCount,
- OldStat.InstCounts[i], NewStat.InstCounts[i], Ctx);
+ OldStat.InstCounts[kind], NewStat.InstCounts[kind], Ctx);
}
}
@@ -925,7 +939,7 @@
ModStat = NewModStat;
}
-FunctionStat::FunctionStat(SILFunction *F) : InstCounts(SILInstructionsNum) {
+FunctionStat::FunctionStat(SILFunction *F) {
InstCountVisitor V(InstCounts);
V.visitSILFunction(F);
BlockCount = V.getBlockCount();
diff --git a/lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp b/lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp
index bb78605..810f970 100644
--- a/lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp
+++ b/lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp
@@ -41,8 +41,7 @@
SILValue ConstantTracker::scanProjections(SILValue addr,
SmallVectorImpl<Projection> *Result) {
for (;;) {
- if (Projection::isAddressProjection(addr)) {
- SILInstruction *I = cast<SILInstruction>(addr);
+ if (auto *I = Projection::isAddressProjection(addr)) {
if (Result) {
Result->push_back(Projection(I));
}
@@ -110,11 +109,11 @@
// Track the value up the dominator tree.
for (;;) {
- if (auto *inst = dyn_cast<SILInstruction>(val)) {
- if (Projection::isObjectProjection(inst)) {
+ if (auto *inst = dyn_cast<SingleValueInstruction>(val)) {
+ if (auto pi = Projection::isObjectProjection(val)) {
// Extract a member from a struct/tuple/enum.
- projStack.push_back(Projection(inst));
- val = inst->getOperand(0);
+ projStack.push_back(Projection(pi));
+ val = pi->getOperand(0);
continue;
} else if (SILValue member = getMember(inst, projStack)) {
// The opposite of a projection instruction: composing a struct/tuple.
@@ -125,8 +124,8 @@
// A value loaded from memory.
val = loadedVal;
continue;
- } else if (isa<ThinToThickFunctionInst>(inst)) {
- val = inst->getOperand(0);
+ } else if (auto ti = dyn_cast<ThinToThickFunctionInst>(inst)) {
+ val = ti->getOperand();
continue;
}
return inst;
diff --git a/lib/SILOptimizer/Utils/SILInliner.cpp b/lib/SILOptimizer/Utils/SILInliner.cpp
index ba5db27..997ba40 100644
--- a/lib/SILOptimizer/Utils/SILInliner.cpp
+++ b/lib/SILOptimizer/Utils/SILInliner.cpp
@@ -98,7 +98,6 @@
for (auto AI = Args.begin(), AE = Args.end(); AI != AE; ++AI, ++BAI)
ValueMap.insert(std::make_pair(*BAI, *AI));
- InstructionMap.clear();
BBMap.clear();
// Do not allow the entry block to be cloned again
SILBasicBlock::iterator InsertPoint =
@@ -140,10 +139,11 @@
SILFunction::iterator(ReturnToBB));
// Create an argument on the return-to BB representing the returned value.
- auto *RetArg = ReturnToBB->createPHIArgument(AI.getInstruction()->getType(),
+ auto apply = cast<ApplyInst>(AI.getInstruction());
+ auto *RetArg = ReturnToBB->createPHIArgument(apply->getType(),
ValueOwnershipKind::Owned);
// Replace all uses of the ApplyInst with the new argument.
- AI.getInstruction()->replaceAllUsesWith(RetArg);
+ apply->replaceAllUsesWith(RetArg);
}
// Now iterate over the callee BBs and fix up the terminators.
@@ -236,235 +236,230 @@
/// instruction. This is of course very much so not true.
InlineCost swift::instructionInlineCost(SILInstruction &I) {
switch (I.getKind()) {
- case ValueKind::IntegerLiteralInst:
- case ValueKind::FloatLiteralInst:
- case ValueKind::DebugValueInst:
- case ValueKind::DebugValueAddrInst:
- case ValueKind::StringLiteralInst:
- case ValueKind::ConstStringLiteralInst:
- case ValueKind::FixLifetimeInst:
- case ValueKind::EndBorrowInst:
- case ValueKind::EndBorrowArgumentInst:
- case ValueKind::BeginBorrowInst:
- case ValueKind::MarkDependenceInst:
- case ValueKind::FunctionRefInst:
- case ValueKind::AllocGlobalInst:
- case ValueKind::GlobalAddrInst:
- case ValueKind::EndLifetimeInst:
- case ValueKind::UncheckedOwnershipConversionInst:
+ case SILInstructionKind::IntegerLiteralInst:
+ case SILInstructionKind::FloatLiteralInst:
+ case SILInstructionKind::DebugValueInst:
+ case SILInstructionKind::DebugValueAddrInst:
+ case SILInstructionKind::StringLiteralInst:
+ case SILInstructionKind::ConstStringLiteralInst:
+ case SILInstructionKind::FixLifetimeInst:
+ case SILInstructionKind::EndBorrowInst:
+ case SILInstructionKind::EndBorrowArgumentInst:
+ case SILInstructionKind::BeginBorrowInst:
+ case SILInstructionKind::MarkDependenceInst:
+ case SILInstructionKind::FunctionRefInst:
+ case SILInstructionKind::AllocGlobalInst:
+ case SILInstructionKind::GlobalAddrInst:
+ case SILInstructionKind::EndLifetimeInst:
+ case SILInstructionKind::UncheckedOwnershipConversionInst:
+ return InlineCost::Free;
+
+ // Typed GEPs are free.
+ case SILInstructionKind::TupleElementAddrInst:
+ case SILInstructionKind::StructElementAddrInst:
+ case SILInstructionKind::ProjectBlockStorageInst:
+ return InlineCost::Free;
+
+ // Aggregates are exploded at the IR level; these are effectively no-ops.
+ case SILInstructionKind::TupleInst:
+ case SILInstructionKind::StructInst:
+ case SILInstructionKind::StructExtractInst:
+ case SILInstructionKind::TupleExtractInst:
+ return InlineCost::Free;
+
+ // Unchecked casts are free.
+ case SILInstructionKind::AddressToPointerInst:
+ case SILInstructionKind::PointerToAddressInst:
+
+ case SILInstructionKind::UncheckedRefCastInst:
+ case SILInstructionKind::UncheckedRefCastAddrInst:
+ case SILInstructionKind::UncheckedAddrCastInst:
+ case SILInstructionKind::UncheckedTrivialBitCastInst:
+ case SILInstructionKind::UncheckedBitwiseCastInst:
+
+ case SILInstructionKind::RawPointerToRefInst:
+ case SILInstructionKind::RefToRawPointerInst:
+
+ case SILInstructionKind::UpcastInst:
+
+ case SILInstructionKind::ThinToThickFunctionInst:
+ case SILInstructionKind::ThinFunctionToPointerInst:
+ case SILInstructionKind::PointerToThinFunctionInst:
+ case SILInstructionKind::ConvertFunctionInst:
+
+ case SILInstructionKind::BridgeObjectToWordInst:
+ return InlineCost::Free;
+
+ // Access instructions are free unless we're dynamically enforcing them.
+ case SILInstructionKind::BeginAccessInst:
+ return getEnforcementCost(cast<BeginAccessInst>(I).getEnforcement());
+ case SILInstructionKind::EndAccessInst:
+ return getEnforcementCost(cast<EndAccessInst>(I).getBeginAccess()
+ ->getEnforcement());
+ case SILInstructionKind::BeginUnpairedAccessInst:
+ return getEnforcementCost(cast<BeginUnpairedAccessInst>(I)
+ .getEnforcement());
+ case SILInstructionKind::EndUnpairedAccessInst:
+ return getEnforcementCost(cast<EndUnpairedAccessInst>(I)
+ .getEnforcement());
+
+ // TODO: These are free if the metatype is for a Swift class.
+ case SILInstructionKind::ThickToObjCMetatypeInst:
+ case SILInstructionKind::ObjCToThickMetatypeInst:
+ return InlineCost::Expensive;
+
+ // TODO: Bridge object conversions imply a masking operation that should be
+ // "hella cheap" but not really expensive
+ case SILInstructionKind::BridgeObjectToRefInst:
+ case SILInstructionKind::RefToBridgeObjectInst:
+ return InlineCost::Expensive;
+
+ case SILInstructionKind::MetatypeInst:
+ // Thin metatypes are always free.
+ if (cast<MetatypeInst>(I).getType().castTo<MetatypeType>()
+ ->getRepresentation() == MetatypeRepresentation::Thin)
+ return InlineCost::Free;
+ // TODO: Thick metatypes are free if they don't require generic or lazy
+ // instantiation.
+ return InlineCost::Expensive;
+
+ // Protocol descriptor references are free.
+ case SILInstructionKind::ObjCProtocolInst:
+ return InlineCost::Free;
+
+ // Metatype-to-object conversions are free.
+ case SILInstructionKind::ObjCExistentialMetatypeToObjectInst:
+ case SILInstructionKind::ObjCMetatypeToObjectInst:
+ return InlineCost::Free;
+
+ // Return and unreachable are free.
+ case SILInstructionKind::UnreachableInst:
+ case SILInstructionKind::ReturnInst:
+ case SILInstructionKind::ThrowInst:
+ return InlineCost::Free;
+
+ case SILInstructionKind::ApplyInst:
+ case SILInstructionKind::TryApplyInst:
+ case SILInstructionKind::AllocBoxInst:
+ case SILInstructionKind::AllocExistentialBoxInst:
+ case SILInstructionKind::AllocRefInst:
+ case SILInstructionKind::AllocRefDynamicInst:
+ case SILInstructionKind::AllocStackInst:
+ case SILInstructionKind::AllocValueBufferInst:
+ case SILInstructionKind::BindMemoryInst:
+ case SILInstructionKind::ValueMetatypeInst:
+ case SILInstructionKind::WitnessMethodInst:
+ case SILInstructionKind::AssignInst:
+ case SILInstructionKind::BranchInst:
+ case SILInstructionKind::CheckedCastBranchInst:
+ case SILInstructionKind::CheckedCastValueBranchInst:
+ case SILInstructionKind::CheckedCastAddrBranchInst:
+ case SILInstructionKind::ClassMethodInst:
+ case SILInstructionKind::CondBranchInst:
+ case SILInstructionKind::CondFailInst:
+ case SILInstructionKind::CopyBlockInst:
+ case SILInstructionKind::CopyAddrInst:
+ case SILInstructionKind::RetainValueInst:
+ case SILInstructionKind::RetainValueAddrInst:
+ case SILInstructionKind::UnmanagedRetainValueInst:
+ case SILInstructionKind::CopyValueInst:
+ case SILInstructionKind::CopyUnownedValueInst:
+ case SILInstructionKind::DeallocBoxInst:
+ case SILInstructionKind::DeallocExistentialBoxInst:
+ case SILInstructionKind::DeallocRefInst:
+ case SILInstructionKind::DeallocPartialRefInst:
+ case SILInstructionKind::DeallocStackInst:
+ case SILInstructionKind::DeallocValueBufferInst:
+ case SILInstructionKind::DeinitExistentialAddrInst:
+ case SILInstructionKind::DeinitExistentialValueInst:
+ case SILInstructionKind::DestroyAddrInst:
+ case SILInstructionKind::ProjectValueBufferInst:
+ case SILInstructionKind::ProjectBoxInst:
+ case SILInstructionKind::ProjectExistentialBoxInst:
+ case SILInstructionKind::ReleaseValueInst:
+ case SILInstructionKind::ReleaseValueAddrInst:
+ case SILInstructionKind::UnmanagedReleaseValueInst:
+ case SILInstructionKind::DestroyValueInst:
+ case SILInstructionKind::AutoreleaseValueInst:
+ case SILInstructionKind::UnmanagedAutoreleaseValueInst:
+ case SILInstructionKind::DynamicMethodBranchInst:
+ case SILInstructionKind::DynamicMethodInst:
+ case SILInstructionKind::EnumInst:
+ case SILInstructionKind::IndexAddrInst:
+ case SILInstructionKind::TailAddrInst:
+ case SILInstructionKind::IndexRawPointerInst:
+ case SILInstructionKind::InitEnumDataAddrInst:
+ case SILInstructionKind::InitExistentialAddrInst:
+ case SILInstructionKind::InitExistentialValueInst:
+ case SILInstructionKind::InitExistentialMetatypeInst:
+ case SILInstructionKind::InitExistentialRefInst:
+ case SILInstructionKind::InjectEnumAddrInst:
+ case SILInstructionKind::IsNonnullInst:
+ case SILInstructionKind::LoadInst:
+ case SILInstructionKind::LoadBorrowInst:
+ case SILInstructionKind::LoadUnownedInst:
+ case SILInstructionKind::LoadWeakInst:
+ case SILInstructionKind::OpenExistentialAddrInst:
+ case SILInstructionKind::OpenExistentialBoxInst:
+ case SILInstructionKind::OpenExistentialBoxValueInst:
+ case SILInstructionKind::OpenExistentialMetatypeInst:
+ case SILInstructionKind::OpenExistentialRefInst:
+ case SILInstructionKind::OpenExistentialValueInst:
+ case SILInstructionKind::PartialApplyInst:
+ case SILInstructionKind::ExistentialMetatypeInst:
+ case SILInstructionKind::RefElementAddrInst:
+ case SILInstructionKind::RefTailAddrInst:
+ case SILInstructionKind::RefToUnmanagedInst:
+ case SILInstructionKind::RefToUnownedInst:
+ case SILInstructionKind::StoreInst:
+ case SILInstructionKind::StoreBorrowInst:
+ case SILInstructionKind::StoreUnownedInst:
+ case SILInstructionKind::StoreWeakInst:
+ case SILInstructionKind::StrongPinInst:
+ case SILInstructionKind::StrongReleaseInst:
+ case SILInstructionKind::SetDeallocatingInst:
+ case SILInstructionKind::StrongRetainInst:
+ case SILInstructionKind::StrongRetainUnownedInst:
+ case SILInstructionKind::StrongUnpinInst:
+ case SILInstructionKind::SuperMethodInst:
+ case SILInstructionKind::SwitchEnumAddrInst:
+ case SILInstructionKind::SwitchEnumInst:
+ case SILInstructionKind::SwitchValueInst:
+ case SILInstructionKind::UncheckedEnumDataInst:
+ case SILInstructionKind::UncheckedTakeEnumDataAddrInst:
+ case SILInstructionKind::UnconditionalCheckedCastInst:
+ case SILInstructionKind::UnconditionalCheckedCastAddrInst:
+ case SILInstructionKind::UnconditionalCheckedCastValueInst:
+ case SILInstructionKind::UnmanagedToRefInst:
+ case SILInstructionKind::UnownedReleaseInst:
+ case SILInstructionKind::UnownedRetainInst:
+ case SILInstructionKind::IsUniqueInst:
+ case SILInstructionKind::IsUniqueOrPinnedInst:
+ case SILInstructionKind::UnownedToRefInst:
+ case SILInstructionKind::InitBlockStorageHeaderInst:
+ case SILInstructionKind::SelectEnumAddrInst:
+ case SILInstructionKind::SelectEnumInst:
+ case SILInstructionKind::SelectValueInst:
+ case SILInstructionKind::KeyPathInst:
+ case SILInstructionKind::GlobalValueInst:
+ return InlineCost::Expensive;
+
+ case SILInstructionKind::BuiltinInst: {
+ auto *BI = cast<BuiltinInst>(&I);
+ // Expect intrinsics are 'free' instructions.
+ if (BI->getIntrinsicInfo().ID == llvm::Intrinsic::expect)
+ return InlineCost::Free;
+ if (BI->getBuiltinInfo().ID == BuiltinValueKind::OnFastPath)
return InlineCost::Free;
- // Typed GEPs are free.
- case ValueKind::TupleElementAddrInst:
- case ValueKind::StructElementAddrInst:
- case ValueKind::ProjectBlockStorageInst:
- return InlineCost::Free;
-
- // Aggregates are exploded at the IR level; these are effectively no-ops.
- case ValueKind::TupleInst:
- case ValueKind::StructInst:
- case ValueKind::StructExtractInst:
- case ValueKind::TupleExtractInst:
- return InlineCost::Free;
-
- // Unchecked casts are free.
- case ValueKind::AddressToPointerInst:
- case ValueKind::PointerToAddressInst:
-
- case ValueKind::UncheckedRefCastInst:
- case ValueKind::UncheckedRefCastAddrInst:
- case ValueKind::UncheckedAddrCastInst:
- case ValueKind::UncheckedTrivialBitCastInst:
- case ValueKind::UncheckedBitwiseCastInst:
-
- case ValueKind::RawPointerToRefInst:
- case ValueKind::RefToRawPointerInst:
-
- case ValueKind::UpcastInst:
-
- case ValueKind::ThinToThickFunctionInst:
- case ValueKind::ThinFunctionToPointerInst:
- case ValueKind::PointerToThinFunctionInst:
- case ValueKind::ConvertFunctionInst:
-
- case ValueKind::BridgeObjectToWordInst:
- return InlineCost::Free;
-
- // Access instructions are free unless we're dynamically enforcing them.
- case ValueKind::BeginAccessInst:
- return getEnforcementCost(cast<BeginAccessInst>(I).getEnforcement());
- case ValueKind::EndAccessInst:
- return getEnforcementCost(cast<EndAccessInst>(I).getBeginAccess()
- ->getEnforcement());
- case ValueKind::BeginUnpairedAccessInst:
- return getEnforcementCost(cast<BeginUnpairedAccessInst>(I)
- .getEnforcement());
- case ValueKind::EndUnpairedAccessInst:
- return getEnforcementCost(cast<EndUnpairedAccessInst>(I)
- .getEnforcement());
-
- // TODO: These are free if the metatype is for a Swift class.
- case ValueKind::ThickToObjCMetatypeInst:
- case ValueKind::ObjCToThickMetatypeInst:
- return InlineCost::Expensive;
-
- // TODO: Bridge object conversions imply a masking operation that should be
- // "hella cheap" but not really expensive
- case ValueKind::BridgeObjectToRefInst:
- case ValueKind::RefToBridgeObjectInst:
- return InlineCost::Expensive;
-
- case ValueKind::MetatypeInst:
- // Thin metatypes are always free.
- if (I.getType().castTo<MetatypeType>()->getRepresentation()
- == MetatypeRepresentation::Thin)
- return InlineCost::Free;
- // TODO: Thick metatypes are free if they don't require generic or lazy
- // instantiation.
- return InlineCost::Expensive;
-
- // Protocol descriptor references are free.
- case ValueKind::ObjCProtocolInst:
- return InlineCost::Free;
-
- // Metatype-to-object conversions are free.
- case ValueKind::ObjCExistentialMetatypeToObjectInst:
- case ValueKind::ObjCMetatypeToObjectInst:
- return InlineCost::Free;
-
- // Return and unreachable are free.
- case ValueKind::UnreachableInst:
- case ValueKind::ReturnInst:
- case ValueKind::ThrowInst:
- return InlineCost::Free;
-
- case ValueKind::ApplyInst:
- case ValueKind::TryApplyInst:
- case ValueKind::AllocBoxInst:
- case ValueKind::AllocExistentialBoxInst:
- case ValueKind::AllocRefInst:
- case ValueKind::AllocRefDynamicInst:
- case ValueKind::AllocStackInst:
- case ValueKind::AllocValueBufferInst:
- case ValueKind::BindMemoryInst:
- case ValueKind::ValueMetatypeInst:
- case ValueKind::WitnessMethodInst:
- case ValueKind::AssignInst:
- case ValueKind::BranchInst:
- case ValueKind::CheckedCastBranchInst:
- case ValueKind::CheckedCastValueBranchInst:
- case ValueKind::CheckedCastAddrBranchInst:
- case ValueKind::ClassMethodInst:
- case ValueKind::CondBranchInst:
- case ValueKind::CondFailInst:
- case ValueKind::CopyBlockInst:
- case ValueKind::CopyAddrInst:
- case ValueKind::RetainValueInst:
- case ValueKind::RetainValueAddrInst:
- case ValueKind::UnmanagedRetainValueInst:
- case ValueKind::CopyValueInst:
- case ValueKind::CopyUnownedValueInst:
- case ValueKind::DeallocBoxInst:
- case ValueKind::DeallocExistentialBoxInst:
- case ValueKind::DeallocRefInst:
- case ValueKind::DeallocPartialRefInst:
- case ValueKind::DeallocStackInst:
- case ValueKind::DeallocValueBufferInst:
- case ValueKind::DeinitExistentialAddrInst:
- case ValueKind::DeinitExistentialValueInst:
- case ValueKind::DestroyAddrInst:
- case ValueKind::ProjectValueBufferInst:
- case ValueKind::ProjectBoxInst:
- case ValueKind::ProjectExistentialBoxInst:
- case ValueKind::ReleaseValueInst:
- case ValueKind::ReleaseValueAddrInst:
- case ValueKind::UnmanagedReleaseValueInst:
- case ValueKind::DestroyValueInst:
- case ValueKind::AutoreleaseValueInst:
- case ValueKind::UnmanagedAutoreleaseValueInst:
- case ValueKind::DynamicMethodBranchInst:
- case ValueKind::DynamicMethodInst:
- case ValueKind::EnumInst:
- case ValueKind::IndexAddrInst:
- case ValueKind::TailAddrInst:
- case ValueKind::IndexRawPointerInst:
- case ValueKind::InitEnumDataAddrInst:
- case ValueKind::InitExistentialAddrInst:
- case ValueKind::InitExistentialValueInst:
- case ValueKind::InitExistentialMetatypeInst:
- case ValueKind::InitExistentialRefInst:
- case ValueKind::InjectEnumAddrInst:
- case ValueKind::IsNonnullInst:
- case ValueKind::LoadInst:
- case ValueKind::LoadBorrowInst:
- case ValueKind::LoadUnownedInst:
- case ValueKind::LoadWeakInst:
- case ValueKind::OpenExistentialAddrInst:
- case ValueKind::OpenExistentialBoxInst:
- case ValueKind::OpenExistentialBoxValueInst:
- case ValueKind::OpenExistentialMetatypeInst:
- case ValueKind::OpenExistentialRefInst:
- case ValueKind::OpenExistentialValueInst:
- case ValueKind::PartialApplyInst:
- case ValueKind::ExistentialMetatypeInst:
- case ValueKind::RefElementAddrInst:
- case ValueKind::RefTailAddrInst:
- case ValueKind::RefToUnmanagedInst:
- case ValueKind::RefToUnownedInst:
- case ValueKind::StoreInst:
- case ValueKind::StoreBorrowInst:
- case ValueKind::StoreUnownedInst:
- case ValueKind::StoreWeakInst:
- case ValueKind::StrongPinInst:
- case ValueKind::StrongReleaseInst:
- case ValueKind::SetDeallocatingInst:
- case ValueKind::StrongRetainInst:
- case ValueKind::StrongRetainUnownedInst:
- case ValueKind::StrongUnpinInst:
- case ValueKind::SuperMethodInst:
- case ValueKind::SwitchEnumAddrInst:
- case ValueKind::SwitchEnumInst:
- case ValueKind::SwitchValueInst:
- case ValueKind::UncheckedEnumDataInst:
- case ValueKind::UncheckedTakeEnumDataAddrInst:
- case ValueKind::UnconditionalCheckedCastInst:
- case ValueKind::UnconditionalCheckedCastAddrInst:
- case ValueKind::UnconditionalCheckedCastValueInst:
- case ValueKind::UnmanagedToRefInst:
- case ValueKind::UnownedReleaseInst:
- case ValueKind::UnownedRetainInst:
- case ValueKind::IsUniqueInst:
- case ValueKind::IsUniqueOrPinnedInst:
- case ValueKind::UnownedToRefInst:
- case ValueKind::InitBlockStorageHeaderInst:
- case ValueKind::SelectEnumAddrInst:
- case ValueKind::SelectEnumInst:
- case ValueKind::SelectValueInst:
- case ValueKind::KeyPathInst:
- case ValueKind::GlobalValueInst:
- return InlineCost::Expensive;
-
- case ValueKind::BuiltinInst: {
- auto *BI = cast<BuiltinInst>(&I);
- // Expect intrinsics are 'free' instructions.
- if (BI->getIntrinsicInfo().ID == llvm::Intrinsic::expect)
- return InlineCost::Free;
- if (BI->getBuiltinInfo().ID == BuiltinValueKind::OnFastPath)
- return InlineCost::Free;
-
- return InlineCost::Expensive;
- }
- case ValueKind::SILPHIArgument:
- case ValueKind::SILFunctionArgument:
- case ValueKind::SILUndef:
- llvm_unreachable("Only instructions should be passed into this "
- "function.");
- case ValueKind::MarkFunctionEscapeInst:
- case ValueKind::MarkUninitializedInst:
- case ValueKind::MarkUninitializedBehaviorInst:
- llvm_unreachable("not valid in canonical sil");
- case ValueKind::ObjectInst:
- llvm_unreachable("not valid in a function");
+ return InlineCost::Expensive;
+ }
+ case SILInstructionKind::MarkFunctionEscapeInst:
+ case SILInstructionKind::MarkUninitializedInst:
+ case SILInstructionKind::MarkUninitializedBehaviorInst:
+ llvm_unreachable("not valid in canonical sil");
+ case SILInstructionKind::ObjectInst:
+ llvm_unreachable("not valid in a function");
}
llvm_unreachable("Unhandled ValueKind in switch.");
diff --git a/lib/SILOptimizer/Utils/SILSSAUpdater.cpp b/lib/SILOptimizer/Utils/SILSSAUpdater.cpp
index 4cbcc34..75fe849 100644
--- a/lib/SILOptimizer/Utils/SILSSAUpdater.cpp
+++ b/lib/SILOptimizer/Utils/SILSSAUpdater.cpp
@@ -78,11 +78,12 @@
/// Are all available values identicalTo each other.
bool areIdentical(AvailableValsTy &Avails) {
- auto *First = dyn_cast<SILInstruction>(Avails.begin()->second);
+ // TODO: MultiValueInstruction
+ auto *First = dyn_cast<SingleValueInstruction>(Avails.begin()->second);
if (!First)
return false;
for (auto Avail : Avails) {
- auto *Inst = dyn_cast<SILInstruction>(Avail.second);
+ auto *Inst = dyn_cast<SingleValueInstruction>(Avail.second);
if (!Inst)
return false;
if (!Inst->isIdenticalTo(First))
@@ -100,7 +101,7 @@
assert(areIdentical(getAvailVals(AV)) &&
"The function_refs need to have the same value");
SILInstruction *User = Op.getUser();
- auto *NewFR = FR->clone(User);
+ auto *NewFR = cast<FunctionRefInst>(FR->clone(User));
Op.set(NewFR);
return;
} else if (auto *IL = dyn_cast<IntegerLiteralInst>(Op.get()))
@@ -108,7 +109,7 @@
// Some llvm intrinsics don't like phi nodes as their constant inputs (e.g
// ctlz).
SILInstruction *User = Op.getUser();
- auto *NewIL = IL->clone(User);
+ auto *NewIL = cast<IntegerLiteralInst>(IL->clone(User));
Op.set(NewIL);
return;
}
@@ -531,7 +532,7 @@
/// detection like induction variable analysis to succeed.
///
/// If Arg is replaced, return the cast instruction. Otherwise return nullptr.
-SILInstruction *swift::replaceBBArgWithCast(SILPHIArgument *Arg) {
+SILValue swift::replaceBBArgWithCast(SILPHIArgument *Arg) {
SmallVector<SILValue, 4> ArgValues;
Arg->getIncomingValues(ArgValues);
if (isa<StructInst>(ArgValues[0]))
diff --git a/lib/SILOptimizer/Utils/SpecializationMangler.cpp b/lib/SILOptimizer/Utils/SpecializationMangler.cpp
index 7134e4b..8dc7219 100644
--- a/lib/SILOptimizer/Utils/SpecializationMangler.cpp
+++ b/lib/SILOptimizer/Utils/SpecializationMangler.cpp
@@ -183,29 +183,29 @@
switch (LI->getKind()) {
default:
llvm_unreachable("unknown literal");
- case ValueKind::FunctionRefInst: {
+ case SILInstructionKind::FunctionRefInst: {
SILFunction *F = cast<FunctionRefInst>(LI)->getReferencedFunction();
ArgOpBuffer << 'f';
appendIdentifier(F->getName());
break;
}
- case ValueKind::GlobalAddrInst: {
+ case SILInstructionKind::GlobalAddrInst: {
SILGlobalVariable *G = cast<GlobalAddrInst>(LI)->getReferencedGlobal();
ArgOpBuffer << 'g';
appendIdentifier(G->getName());
break;
}
- case ValueKind::IntegerLiteralInst: {
+ case SILInstructionKind::IntegerLiteralInst: {
APInt apint = cast<IntegerLiteralInst>(LI)->getValue();
ArgOpBuffer << 'i' << apint;
break;
}
- case ValueKind::FloatLiteralInst: {
+ case SILInstructionKind::FloatLiteralInst: {
APInt apint = cast<FloatLiteralInst>(LI)->getBits();
ArgOpBuffer << 'd' << apint;
break;
}
- case ValueKind::StringLiteralInst: {
+ case SILInstructionKind::StringLiteralInst: {
StringLiteralInst *SLI = cast<StringLiteralInst>(LI);
StringRef V = SLI->getValue();
assert(V.size() <= 32 && "Cannot encode string of length > 32");
diff --git a/lib/SILOptimizer/Utils/StackNesting.cpp b/lib/SILOptimizer/Utils/StackNesting.cpp
index 143bc3d..56a38f7 100644
--- a/lib/SILOptimizer/Utils/StackNesting.cpp
+++ b/lib/SILOptimizer/Utils/StackNesting.cpp
@@ -41,15 +41,16 @@
BlockInfo *BI = WorkList.pop_back_val();
for (SILInstruction &I : *BI->Block) {
if (I.isAllocatingStack()) {
+ auto Alloc = cast<AllocationInst>(&I);
// Register this stack location.
unsigned CurrentBitNumber = StackLocs.size();
- StackLoc2BitNumbers[&I] = CurrentBitNumber;
- StackLocs.push_back(StackLoc(&I));
+ StackLoc2BitNumbers[Alloc] = CurrentBitNumber;
+ StackLocs.push_back(StackLoc(Alloc));
- BI->StackInsts.push_back(&I);
+ BI->StackInsts.push_back(Alloc);
} else if (I.isDeallocatingStack()) {
- auto *AllocInst = cast<SILInstruction>(I.getOperand(0));
+ auto *AllocInst = cast<SingleValueInstruction>(I.getOperand(0));
if (!BI->StackInsts.empty() && BI->StackInsts.back() == AllocInst) {
// As an optimization, we ignore perfectly nested alloc-dealloc pairs
// inside a basic block.
@@ -114,7 +115,8 @@
}
for (SILInstruction *StackInst : reversed(BI.StackInsts)) {
if (StackInst->isAllocatingStack()) {
- int BitNr = StackLoc2BitNumbers[StackInst];
+ auto AllocInst = cast<SingleValueInstruction>(StackInst);
+ int BitNr = StackLoc2BitNumbers[AllocInst];
if (Bits != StackLocs[BitNr].AliveLocs) {
// More locations are alive around the StackInst's location.
// Update the AlivaLocs bitset, which contains all those alive
@@ -132,7 +134,8 @@
// A stack deallocation begins the lifetime of its location (in
// reverse order). And it also begins the lifetime of all other
// locations which are alive at the allocation point.
- auto *AllocInst = cast<SILInstruction>(StackInst->getOperand(0));
+ auto *AllocInst =
+ cast<SingleValueInstruction>(StackInst->getOperand(0));
int BitNr = StackLoc2BitNumbers[AllocInst];
Bits |= StackLocs[BitNr].AliveLocs;
}
@@ -147,14 +150,14 @@
return isNested;
}
-static SILInstruction *createDealloc(SILInstruction *Alloc,
+static SILInstruction *createDealloc(AllocationInst *Alloc,
SILInstruction *InsertionPoint,
SILLocation Location) {
SILBuilder B(InsertionPoint);
switch (Alloc->getKind()) {
- case ValueKind::AllocStackInst:
+ case SILInstructionKind::AllocStackInst:
return B.createDeallocStack(Location, Alloc);
- case ValueKind::AllocRefInst:
+ case SILInstructionKind::AllocRefInst:
assert(cast<AllocRefInst>(Alloc)->canAllocOnStack());
return B.createDeallocRef(Location, Alloc, /*canBeOnStack*/true);
default:
@@ -176,7 +179,7 @@
for (int LocNr = AliveBefore.find_first(); LocNr >= 0;
LocNr = AliveBefore.find_next(LocNr)) {
if (!AliveAfter.test(LocNr)) {
- SILInstruction *Alloc = StackLocs[LocNr].Alloc;
+ AllocationInst *Alloc = StackLocs[LocNr].Alloc;
InsertionPoint = createDealloc(Alloc, InsertionPoint,
Location.hasValue() ? Location.getValue() : Alloc->getLoc());
changesMade = true;
@@ -244,13 +247,14 @@
for (SILInstruction *StackInst : reversed(BI.StackInsts)) {
if (StackInst->isAllocatingStack()) {
// For allocations we just update the bit-set.
- int BitNr = StackLoc2BitNumbers.lookup(StackInst);
+ auto AllocInst = cast<SingleValueInstruction>(StackInst);
+ int BitNr = StackLoc2BitNumbers.lookup(AllocInst);
assert(Bits == StackLocs[BitNr].AliveLocs &&
"dataflow didn't converge");
Bits.reset(BitNr);
} else if (StackInst->isDeallocatingStack()) {
// Handle deallocations.
- auto *AllocInst = cast<SILInstruction>(StackInst->getOperand(0));
+ auto *AllocInst = cast<SingleValueInstruction>(StackInst->getOperand(0));
SILLocation Loc = StackInst->getLoc();
int BitNr = StackLoc2BitNumbers.lookup(AllocInst);
SILInstruction *InsertionPoint = &*std::next(StackInst->getIterator());
@@ -301,12 +305,13 @@
dumpBits(BI.AliveStackLocsAtEntry);
for (SILInstruction *StackInst : BI.StackInsts) {
if (StackInst->isAllocatingStack()) {
- int BitNr = StackLoc2BitNumbers.lookup(StackInst);
+ auto AllocInst = cast<AllocationInst>(StackInst);
+ int BitNr = StackLoc2BitNumbers.lookup(AllocInst);
llvm::dbgs() << " alloc #" << BitNr << ": alive=";
dumpBits(StackLocs[BitNr].AliveLocs);
llvm::dbgs() << " " << *StackInst;
} else if (StackInst->isDeallocatingStack()) {
- auto *AllocInst = cast<SILInstruction>(StackInst->getOperand(0));
+ auto *AllocInst = cast<AllocationInst>(StackInst->getOperand(0));
int BitNr = StackLoc2BitNumbers.lookup(AllocInst);
llvm::dbgs() << " dealloc for #" << BitNr << "\n"
" " << *StackInst;
diff --git a/lib/Sema/CSBindings.cpp b/lib/Sema/CSBindings.cpp
index a175413..3ca3f74 100644
--- a/lib/Sema/CSBindings.cpp
+++ b/lib/Sema/CSBindings.cpp
@@ -123,6 +123,40 @@
llvm_unreachable("Unhandled ConstraintKind in switch.");
}
+void ConstraintSystem::PotentialBindings::addPotentialBinding(
+ PotentialBinding binding, bool allowJoinMeet) {
+ assert(!binding.BindingType->is<ErrorType>());
+
+ // If this is a non-defaulted supertype binding,
+ // check whether we can combine it with another
+ // supertype binding by computing the 'join' of the types.
+ if (binding.Kind == AllowedBindingKind::Supertypes &&
+ !binding.BindingType->hasTypeVariable() && !binding.DefaultedProtocol &&
+ !binding.isDefaultableBinding() && allowJoinMeet) {
+ if (lastSupertypeIndex) {
+ // Can we compute a join?
+ auto &lastBinding = Bindings[*lastSupertypeIndex];
+ auto lastType = lastBinding.BindingType->getWithoutSpecifierType();
+ auto bindingType = binding.BindingType->getWithoutSpecifierType();
+ auto join = Type::join(lastType, bindingType);
+ if (join) {
+ auto anyType = join->getASTContext().TheAnyType;
+ if (!join->isEqual(anyType) || lastType->isEqual(anyType) ||
+ bindingType->isEqual(anyType)) {
+ // Replace the last supertype binding with the join. We're done.
+ lastBinding.BindingType = join;
+ return;
+ }
+ }
+ }
+
+ // Record this as the most recent supertype index.
+ lastSupertypeIndex = Bindings.size();
+ }
+
+ Bindings.push_back(std::move(binding));
+}
+
/// \brief Retrieve the set of potential type bindings for the given
/// representative type variable, along with flags indicating whether
/// those types should be opened.
@@ -154,16 +188,9 @@
continue;
switch (constraint->getKind()) {
- case ConstraintKind::BindParam:
- if (simplifyType(constraint->getSecondType())
- ->getAs<TypeVariableType>() == typeVar) {
- result.IsRHSOfBindParam = true;
- }
-
- LLVM_FALLTHROUGH;
-
case ConstraintKind::Bind:
case ConstraintKind::Equal:
+ case ConstraintKind::BindParam:
case ConstraintKind::BindToPointerType:
case ConstraintKind::Subtype:
case ConstraintKind::Conversion:
diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp
index bea32ae..d2b84a8 100644
--- a/lib/Sema/CSDiag.cpp
+++ b/lib/Sema/CSDiag.cpp
@@ -3289,18 +3289,42 @@
patternElt.first->setType(patternElt.second);
for (auto paramDeclElt : ParamDeclTypes)
- if (!paramDeclElt.first->hasType())
- paramDeclElt.first->setType(paramDeclElt.second);
+ if (!paramDeclElt.first->hasType()) {
+ paramDeclElt.first->setType(getParamBaseType(paramDeclElt));
+ }
for (auto paramDeclIfaceElt : ParamDeclInterfaceTypes)
- if (!paramDeclIfaceElt.first->hasInterfaceType())
- paramDeclIfaceElt.first->setInterfaceType(paramDeclIfaceElt.second);
+ if (!paramDeclIfaceElt.first->hasInterfaceType()) {
+ paramDeclIfaceElt.first->setInterfaceType(
+ getParamBaseType(paramDeclIfaceElt));
+ }
if (!PossiblyInvalidDecls.empty())
for (auto D : PossiblyInvalidDecls)
if (D->hasInterfaceType())
D->setInvalid(D->getInterfaceType()->hasError());
}
+
+ private:
+ static Type getParamBaseType(std::pair<ParamDecl *, Type> &storedParam) {
+ ParamDecl *param;
+ Type storedType;
+
+ std::tie(param, storedType) = storedParam;
+
+ // FIXME: We are currently in process of removing `InOutType`
+ // so `VarDecl::get{Interface}Type` is going to wrap base
+ // type into `InOutType` if its flag indicates that it's
+ // an `inout` parameter declaration. But such type can't
+ // be restored directly using `VarDecl::set{Interface}Type`
+ // caller needs additional logic to extract base type.
+ if (auto *IOT = storedType->getAs<InOutType>()) {
+ assert(param->isInOut());
+ return IOT->getObjectType();
+ }
+
+ return storedType;
+ }
};
} // end anonymous namespace
diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp
index 68813f8..1d97b74 100644
--- a/lib/Sema/CSSimplify.cpp
+++ b/lib/Sema/CSSimplify.cpp
@@ -1681,11 +1681,27 @@
if (!isBindable(typeVar1, type2))
return formUnsolvedResult();
+ // If the right-hand side of the BindParam constraint
+ // is `lvalue` type, we'll have to make sure that
+ // left-hand side is bound to type variable which
+ // is wrapped in `inout` type to preserve inout/lvalue pairing.
if (auto *lvt = type2->getAs<LValueType>()) {
- assignFixedType(typeVar1, InOutType::get(lvt->getObjectType()));
- } else {
- assignFixedType(typeVar1, type2);
+ auto *tv = createTypeVariable(typeVar1->getImpl().getLocator(),
+ /*options=*/0);
+ assignFixedType(typeVar1, InOutType::get(tv));
+
+ typeVar1 = tv;
+ type2 = lvt->getObjectType();
}
+
+ // If we have a binding for the right-hand side
+ // (argument type) don't try to bind it to the left-hand
+ // side (parameter type) directly, because their
+ // relationship is contravariant and the actual
+ // binding can only come from the left-hand side.
+ addUnsolvedConstraint(
+ Constraint::create(*this, ConstraintKind::ArgumentConversion, type2,
+ typeVar1, getConstraintLocator(locator)));
return SolutionKind::Solved;
}
diff --git a/lib/Sema/CSSolver.cpp b/lib/Sema/CSSolver.cpp
index a01baec..2055c66 100644
--- a/lib/Sema/CSSolver.cpp
+++ b/lib/Sema/CSSolver.cpp
@@ -75,6 +75,17 @@
if (count(referencedTypeVars, typeVar))
return None;
+ // If type variable is not allowed to bind to `lvalue`,
+ // let's check if type of potential binding has any
+ // type variables, which are allowed to bind to `lvalue`,
+ // and postpone such type from consideration.
+ if (!typeVar->getImpl().canBindToLValue()) {
+ for (auto *typeVar : referencedTypeVars) {
+ if (typeVar->getImpl().canBindToLValue())
+ return None;
+ }
+ }
+
// If the type is a type variable itself, don't permit the binding.
if (auto bindingTypeVar = type->getRValueType()->getAs<TypeVariableType>()) {
if (isNilLiteral) {
diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp
index 727f365..24c5854 100644
--- a/lib/Sema/CodeSynthesis.cpp
+++ b/lib/Sema/CodeSynthesis.cpp
@@ -2118,6 +2118,12 @@
ctor->getAttrs().add(clonedAttr);
}
+ // Inherit the @_inlineable attribute.
+ if (superclassCtor->getAttrs().hasAttribute<InlineableAttr>()) {
+ auto *clonedAttr = new (ctx) InlineableAttr(/*implicit=*/true);
+ ctor->getAttrs().add(clonedAttr);
+ }
+
// Make sure the constructor is only as available as its superclass's
// constructor.
AvailabilityInference::applyInferredAvailableAttrs(ctor, superclassCtor, ctx);
diff --git a/lib/Sema/ConstraintGraph.cpp b/lib/Sema/ConstraintGraph.cpp
index 789f640..3698f76 100644
--- a/lib/Sema/ConstraintGraph.cpp
+++ b/lib/Sema/ConstraintGraph.cpp
@@ -648,25 +648,6 @@
}
}
-/// We use this function to determine if a subtype constraint is set
-/// between two (possibly sugared) type variables, one of which is wrapped
-/// in an inout type.
-static bool isStrictInoutSubtypeConstraint(Constraint *constraint) {
- if (constraint->getKind() != ConstraintKind::Subtype)
- return false;
-
- auto t1 = constraint->getFirstType()->getDesugaredType();
-
- if (auto tt = t1->getAs<TupleType>()) {
- if (tt->getNumElements() != 1)
- return false;
-
- t1 = tt->getElementType(0).getPointer();
- }
-
- return t1->is<InOutType>();
-}
-
bool ConstraintGraph::contractEdges() {
llvm::SetVector<std::pair<TypeVariableType *,
TypeVariableType *>> contractions;
@@ -694,20 +675,13 @@
auto isParamBindingConstraint = kind == ConstraintKind::BindParam;
- // We need to take special care not to directly contract parameter
- // binding constraints if there is an inout subtype constraint on the
- // type variable. The constraint solver depends on multiple constraints
- // being present in this case, so it can generate the appropriate lvalue
- // wrapper for the argument type.
- if (isParamBindingConstraint) {
- auto *node = tyvar1->getImpl().getGraphNode();
- auto constraints = node->getConstraints();
- if (llvm::any_of(constraints, [](Constraint *constraint) {
- return isStrictInoutSubtypeConstraint(constraint);
- })) {
- continue;
- }
- }
+ // If the parameter is allowed to bind to `inout` let's not
+ // try to contract the edge connecting parameter declaration to
+ // it's use in the body. If parameter declaration is bound to
+ // `inout` it's use has to be bound to `l-value`, which can't
+ // happen once equivalence classes of parameter and argument are merged.
+ if (isParamBindingConstraint && tyvar1->getImpl().canBindToInOut())
+ continue;
auto rep1 = CS.getRepresentative(tyvar1);
auto rep2 = CS.getRepresentative(tyvar2);
@@ -740,10 +714,12 @@
}
void ConstraintGraph::removeEdge(Constraint *constraint) {
+ bool isExistingConstraint = false;
for (auto &active : CS.ActiveConstraints) {
if (&active == constraint) {
CS.ActiveConstraints.erase(constraint);
+ isExistingConstraint = true;
break;
}
}
@@ -751,12 +727,17 @@
for (auto &inactive : CS.InactiveConstraints) {
if (&inactive == constraint) {
CS.InactiveConstraints.erase(constraint);
+ isExistingConstraint = true;
break;
}
}
- if (CS.solverState)
- CS.solverState->removeGeneratedConstraint(constraint);
+ if (CS.solverState) {
+ if (isExistingConstraint)
+ CS.solverState->retireConstraint(constraint);
+ else
+ CS.solverState->removeGeneratedConstraint(constraint);
+ }
removeConstraint(constraint);
}
diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h
index c106aa4..296a099 100644
--- a/lib/Sema/ConstraintSystem.h
+++ b/lib/Sema/ConstraintSystem.h
@@ -2551,8 +2551,8 @@
};
struct PotentialBindings {
- typedef std::tuple<bool, bool, bool, bool, bool,
- unsigned char, unsigned int> BindingScore;
+ typedef std::tuple<bool, bool, bool, bool, unsigned char, unsigned int>
+ BindingScore;
TypeVariableType *TypeVar;
@@ -2574,9 +2574,6 @@
/// The number of defaultable bindings.
unsigned NumDefaultableBindings = 0;
- /// Is this type variable on the RHS of a BindParam constraint?
- bool IsRHSOfBindParam = false;
-
/// Tracks the position of the last known supertype in the group.
Optional<unsigned> lastSupertypeIndex;
@@ -2593,7 +2590,6 @@
static BindingScore formBindingScore(const PotentialBindings &b) {
return std::make_tuple(!b.hasNonDefaultableBindings(),
b.FullyBound,
- b.IsRHSOfBindParam,
b.SubtypeOfExistentialType,
b.InvolvesTypeVariables,
static_cast<unsigned char>(b.LiteralBinding),
@@ -2629,39 +2625,7 @@
/// \brief Add a potential binding to the list of bindings,
/// coalescing supertype bounds when we are able to compute the meet.
void addPotentialBinding(PotentialBinding binding,
- bool allowJoinMeet = true) {
- assert(!binding.BindingType->is<ErrorType>());
-
- // If this is a non-defaulted supertype binding,
- // check whether we can combine it with another
- // supertype binding by computing the 'join' of the types.
- if (binding.Kind == AllowedBindingKind::Supertypes &&
- !binding.BindingType->hasTypeVariable() &&
- !binding.DefaultedProtocol && !binding.isDefaultableBinding() &&
- allowJoinMeet) {
- if (lastSupertypeIndex) {
- // Can we compute a join?
- auto &lastBinding = Bindings[*lastSupertypeIndex];
- auto lastType = lastBinding.BindingType->getWithoutSpecifierType();
- auto bindingType = binding.BindingType->getWithoutSpecifierType();
- auto join = Type::join(lastType, bindingType);
- if (join) {
- auto anyType = join->getASTContext().TheAnyType;
- if (!join->isEqual(anyType) || lastType->isEqual(anyType) ||
- bindingType->isEqual(anyType)) {
- // Replace the last supertype binding with the join. We're done.
- lastBinding.BindingType = join;
- return;
- }
- }
- }
-
- // Record this as the most recent supertype index.
- lastSupertypeIndex = Bindings.size();
- }
-
- Bindings.push_back(std::move(binding));
- }
+ bool allowJoinMeet = true);
void dump(llvm::raw_ostream &out,
unsigned indent = 0) const LLVM_ATTRIBUTE_USED {
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index a9db914..afa22bd 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -7117,8 +7117,11 @@
}
void visitDestructorDecl(DestructorDecl *DD) {
- if (DD->isInvalid()) {
+ auto enclosingClass = dyn_cast<ClassDecl>(DD->getDeclContext());
+ if (DD->isInvalid() ||
+ enclosingClass == nullptr) {
DD->setInterfaceType(ErrorType::get(TC.Context));
+ DD->setInvalid();
return;
}
@@ -7140,10 +7143,13 @@
TC.checkDeclAttributesEarly(DD);
if (!DD->hasAccess()) {
- auto enclosingClass = cast<ClassDecl>(DD->getParent());
DD->setAccess(enclosingClass->getFormalAccess());
}
+ if (enclosingClass->getAttrs().hasAttribute<VersionedAttr>()) {
+ DD->getAttrs().add(new (TC.Context) VersionedAttr(/*implicit=*/true));
+ }
+
configureImplicitSelf(TC, DD);
if (DD->getDeclContext()->getGenericSignatureOfContext()) {
@@ -7664,25 +7670,13 @@
break;
}
-
- case DeclKind::Func: {
- typeCheckDecl(D, true);
- break;
- }
+ case DeclKind::Func:
case DeclKind::Subscript:
case DeclKind::Constructor:
- typeCheckDecl(D, true);
- break;
-
case DeclKind::Destructor:
case DeclKind::EnumElement: {
- if (auto container = dyn_cast<NominalTypeDecl>(D->getDeclContext())) {
- validateDecl(container);
- typeCheckDecl(D, true);
- } else {
- D->setInterfaceType(ErrorType::get(Context));
- }
+ typeCheckDecl(D, true);
break;
}
}
@@ -8036,8 +8030,7 @@
// Local function used to infer requirements from the extended type.
auto inferExtendedTypeReqs = [&](GenericSignatureBuilder &builder) {
auto source =
- GenericSignatureBuilder::FloatingRequirementSource::forInferred(
- nullptr, /*quietly=*/false);
+ GenericSignatureBuilder::FloatingRequirementSource::forInferred(nullptr);
builder.inferRequirements(*ext->getModuleContext(),
TypeLoc::withoutLoc(extInterfaceType),
diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp
index 949f618..c81fb27 100644
--- a/lib/Sema/TypeCheckGeneric.cpp
+++ b/lib/Sema/TypeCheckGeneric.cpp
@@ -480,8 +480,7 @@
fn->getBodyResultTypeLoc().getTypeRepr()) {
auto source =
GenericSignatureBuilder::FloatingRequirementSource::forInferred(
- fn->getBodyResultTypeLoc().getTypeRepr(),
- /*quietly=*/true);
+ fn->getBodyResultTypeLoc().getTypeRepr());
builder->inferRequirements(*func->getParentModule(),
fn->getBodyResultTypeLoc(),
source);
@@ -497,8 +496,7 @@
if (auto *subscriptDecl = dyn_cast<SubscriptDecl>(storage)) {
auto source =
GenericSignatureBuilder::FloatingRequirementSource::forInferred(
- subscriptDecl->getElementTypeLoc().getTypeRepr(),
- /*quietly=*/true);
+ subscriptDecl->getElementTypeLoc().getTypeRepr());
TypeLoc type(nullptr, subscriptDecl->getElementInterfaceType());
assert(type.getType());
@@ -945,8 +943,7 @@
if (genericParams && builder) {
auto source =
GenericSignatureBuilder::FloatingRequirementSource::forInferred(
- subscript->getElementTypeLoc().getTypeRepr(),
- /*quietly=*/true);
+ subscript->getElementTypeLoc().getTypeRepr());
builder->inferRequirements(*subscript->getParentModule(),
subscript->getElementTypeLoc(),
diff --git a/lib/Serialization/DeserializeSIL.cpp b/lib/Serialization/DeserializeSIL.cpp
index 4000929..19c5080 100644
--- a/lib/Serialization/DeserializeSIL.cpp
+++ b/lib/Serialization/DeserializeSIL.cpp
@@ -318,7 +318,7 @@
return M.createFunction(
SILLinkage::Private, name, type.castTo<SILFunctionType>(), nullptr,
RegularLocation(loc), IsNotBare, IsNotTransparent, IsNotSerialized,
- IsNotThunk, SubclassScope::NotApplicable);
+ ProfileCounter(), IsNotThunk, SubclassScope::NotApplicable);
}
/// Helper function to find a SILFunction, given its name and type.
@@ -470,7 +470,7 @@
fn = SILMod.createFunction(
linkage.getValue(), name, ty.castTo<SILFunctionType>(), nullptr, loc,
IsNotBare, IsTransparent_t(isTransparent == 1),
- IsSerialized_t(isSerialized), IsThunk_t(isThunk),
+ IsSerialized_t(isSerialized), ProfileCounter(), IsThunk_t(isThunk),
SubclassScope::NotApplicable, (Inline_t)inlineStrategy);
fn->setGlobalInit(isGlobal == 1);
fn->setEffectsKind((EffectsKind)effect);
@@ -725,7 +725,7 @@
Builder.setInsertionPoint(BB);
Builder.setCurrentDebugScope(Fn->getDebugScope());
- unsigned OpCode = 0, TyCategory = 0, TyCategory2 = 0, TyCategory3 = 0,
+ unsigned RawOpCode = 0, TyCategory = 0, TyCategory2 = 0, TyCategory3 = 0,
Attr = 0, NumSubs = 0, NumConformances = 0, IsNonThrowingApply = 0;
ValueID ValID, ValID2, ValID3;
TypeID TyID, TyID2, TyID3;
@@ -739,25 +739,25 @@
default:
llvm_unreachable("Record kind for a SIL instruction is not supported.");
case SIL_ONE_VALUE_ONE_OPERAND:
- SILOneValueOneOperandLayout::readRecord(scratch, OpCode, Attr,
+ SILOneValueOneOperandLayout::readRecord(scratch, RawOpCode, Attr,
ValID, TyID, TyCategory,
ValID2);
break;
case SIL_ONE_TYPE:
- SILOneTypeLayout::readRecord(scratch, OpCode, TyID, TyCategory);
+ SILOneTypeLayout::readRecord(scratch, RawOpCode, TyID, TyCategory);
break;
case SIL_ONE_OPERAND:
- SILOneOperandLayout::readRecord(scratch, OpCode, Attr,
+ SILOneOperandLayout::readRecord(scratch, RawOpCode, Attr,
TyID, TyCategory, ValID);
break;
case SIL_ONE_TYPE_ONE_OPERAND:
- SILOneTypeOneOperandLayout::readRecord(scratch, OpCode, Attr,
+ SILOneTypeOneOperandLayout::readRecord(scratch, RawOpCode, Attr,
TyID, TyCategory,
TyID2, TyCategory2,
ValID);
break;
case SIL_INIT_EXISTENTIAL:
- SILInitExistentialLayout::readRecord(scratch, OpCode,
+ SILInitExistentialLayout::readRecord(scratch, RawOpCode,
TyID, TyCategory,
TyID2, TyCategory2,
ValID,
@@ -765,22 +765,22 @@
NumConformances);
break;
case SIL_INST_CAST:
- SILInstCastLayout::readRecord(scratch, OpCode, Attr,
+ SILInstCastLayout::readRecord(scratch, RawOpCode, Attr,
TyID, TyCategory,
TyID2, TyCategory2,
ValID);
break;
case SIL_ONE_TYPE_VALUES:
- SILOneTypeValuesLayout::readRecord(scratch, OpCode, TyID, TyCategory,
+ SILOneTypeValuesLayout::readRecord(scratch, RawOpCode, TyID, TyCategory,
ListOfValues);
break;
case SIL_TWO_OPERANDS:
- SILTwoOperandsLayout::readRecord(scratch, OpCode, Attr,
+ SILTwoOperandsLayout::readRecord(scratch, RawOpCode, Attr,
TyID, TyCategory, ValID,
TyID2, TyCategory2, ValID2);
break;
case SIL_TAIL_ADDR:
- SILTailAddrLayout::readRecord(scratch, OpCode,
+ SILTailAddrLayout::readRecord(scratch, RawOpCode,
TyID, ValID,
TyID2, ValID2,
TyID3);
@@ -791,19 +791,19 @@
TyID, TyID2, ValID, ListOfValues);
switch (IsPartial) {
case SIL_APPLY:
- OpCode = (unsigned)ValueKind::ApplyInst;
+ RawOpCode = (unsigned)SILInstructionKind::ApplyInst;
break;
case SIL_PARTIAL_APPLY:
- OpCode = (unsigned)ValueKind::PartialApplyInst;
+ RawOpCode = (unsigned)SILInstructionKind::PartialApplyInst;
break;
case SIL_BUILTIN:
- OpCode = (unsigned)ValueKind::BuiltinInst;
+ RawOpCode = (unsigned)SILInstructionKind::BuiltinInst;
break;
case SIL_TRY_APPLY:
- OpCode = (unsigned)ValueKind::TryApplyInst;
+ RawOpCode = (unsigned)SILInstructionKind::TryApplyInst;
break;
case SIL_NON_THROWING_APPLY:
- OpCode = (unsigned)ValueKind::ApplyInst;
+ RawOpCode = (unsigned)SILInstructionKind::ApplyInst;
IsNonThrowingApply = true;
break;
@@ -813,35 +813,33 @@
break;
}
case SIL_INST_NO_OPERAND:
- SILInstNoOperandLayout::readRecord(scratch, OpCode);
+ SILInstNoOperandLayout::readRecord(scratch, RawOpCode);
break;
case SIL_INST_WITNESS_METHOD:
SILInstWitnessMethodLayout::readRecord(
scratch, TyID, TyCategory, Attr, TyID2, TyCategory2, TyID3,
TyCategory3, ValID3, ListOfValues);
- OpCode = (unsigned)ValueKind::WitnessMethodInst;
+ RawOpCode = (unsigned)SILInstructionKind::WitnessMethodInst;
break;
}
- SILInstruction *ResultVal;
- switch ((ValueKind)OpCode) {
- case ValueKind::SILPHIArgument:
- case ValueKind::SILFunctionArgument:
- case ValueKind::SILUndef:
- llvm_unreachable("not an instruction");
+ // FIXME: validate
+ SILInstructionKind OpCode = (SILInstructionKind) RawOpCode;
- case ValueKind::DebugValueInst:
- case ValueKind::DebugValueAddrInst:
+ SILInstruction *ResultVal;
+ switch (OpCode) {
+ case SILInstructionKind::DebugValueInst:
+ case SILInstructionKind::DebugValueAddrInst:
llvm_unreachable("not supported");
- case ValueKind::AllocBoxInst:
+ case SILInstructionKind::AllocBoxInst:
assert(RecordKind == SIL_ONE_TYPE && "Layout should be OneType.");
ResultVal = Builder.createAllocBox(Loc,
cast<SILBoxType>(MF->getType(TyID)->getCanonicalType()));
break;
#define ONETYPE_INST(ID) \
- case ValueKind::ID##Inst: \
+ case SILInstructionKind::ID##Inst: \
assert(RecordKind == SIL_ONE_TYPE && "Layout should be OneType."); \
ResultVal = Builder.create##ID(Loc, \
getSILType(MF->getType(TyID), (SILValueCategory)TyCategory));\
@@ -850,7 +848,7 @@
ONETYPE_INST(Metatype)
#undef ONETYPE_INST
#define ONETYPE_ONEOPERAND_INST(ID) \
- case ValueKind::ID##Inst: \
+ case SILInstructionKind::ID##Inst: \
assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND && \
"Layout should be OneTypeOneOperand."); \
ResultVal = Builder.create##ID(Loc, \
@@ -866,7 +864,7 @@
ONETYPE_ONEOPERAND_INST(ProjectExistentialBox)
ONETYPE_ONEOPERAND_INST(DeallocValueBuffer)
#undef ONETYPE_ONEOPERAND_INST
- case ValueKind::DeallocBoxInst:
+ case SILInstructionKind::DeallocBoxInst:
assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND &&
"Layout should be OneTypeOneOperand.");
ResultVal = Builder.createDeallocBox(Loc,
@@ -874,7 +872,7 @@
getSILType(MF->getType(TyID2),
(SILValueCategory)TyCategory2)));
break;
- case ValueKind::OpenExistentialAddrInst:
+ case SILInstructionKind::OpenExistentialAddrInst:
assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND &&
"Layout should be OneTypeOneOperand.");
ResultVal = Builder.createOpenExistentialAddr(
@@ -886,7 +884,7 @@
break;
#define ONEOPERAND_ONETYPE_INST(ID) \
- case ValueKind::ID##Inst: \
+ case SILInstructionKind::ID##Inst: \
assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND && \
"Layout should be OneTypeOneOperand."); \
ResultVal = Builder.create##ID(Loc, \
@@ -926,7 +924,7 @@
ONEOPERAND_ONETYPE_INST(ProjectBlockStorage)
#undef ONEOPERAND_ONETYPE_INST
- case ValueKind::ProjectBoxInst: {
+ case SILInstructionKind::ProjectBoxInst: {
assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND &&
"Layout should be OneTypeOneOperand.");
ResultVal = Builder.createProjectBox(Loc,
@@ -937,7 +935,7 @@
break;
}
- case ValueKind::PointerToAddressInst: {
+ case SILInstructionKind::PointerToAddressInst: {
assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND &&
"Layout should be OneTypeOneOperand.");
bool isStrict = Attr & 0x01;
@@ -950,7 +948,7 @@
isStrict, isInvariant);
break;
}
- case ValueKind::DeallocExistentialBoxInst: {
+ case SILInstructionKind::DeallocExistentialBoxInst: {
assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND &&
"Layout should be OneTypeOneOperand.");
ResultVal = Builder.createDeallocExistentialBox(Loc,
@@ -962,7 +960,7 @@
}
- case ValueKind::RefToBridgeObjectInst: {
+ case SILInstructionKind::RefToBridgeObjectInst: {
auto RefTy = getSILType(MF->getType(TyID), (SILValueCategory)TyCategory);
auto Ref = getLocalValue(ValID, RefTy);
auto BitsTy = getSILType(MF->getType(TyID2), (SILValueCategory)TyCategory2);
@@ -972,26 +970,26 @@
break;
}
- case ValueKind::ObjCProtocolInst: {
+ case SILInstructionKind::ObjCProtocolInst: {
auto Ty = getSILType(MF->getType(TyID), (SILValueCategory)TyCategory);
auto Proto = MF->getDecl(ValID);
ResultVal = Builder.createObjCProtocol(Loc, cast<ProtocolDecl>(Proto), Ty);
break;
}
- case ValueKind::InitExistentialAddrInst:
- case ValueKind::InitExistentialValueInst:
- case ValueKind::InitExistentialMetatypeInst:
- case ValueKind::InitExistentialRefInst:
- case ValueKind::AllocExistentialBoxInst: {
+ case SILInstructionKind::InitExistentialAddrInst:
+ case SILInstructionKind::InitExistentialValueInst:
+ case SILInstructionKind::InitExistentialMetatypeInst:
+ case SILInstructionKind::InitExistentialRefInst:
+ case SILInstructionKind::AllocExistentialBoxInst: {
auto Ty = getSILType(MF->getType(TyID), (SILValueCategory)TyCategory);
auto Ty2 = MF->getType(TyID2);
CanType ConcreteTy;
- if ((ValueKind) OpCode != ValueKind::InitExistentialMetatypeInst)
+ if (OpCode != SILInstructionKind::InitExistentialMetatypeInst)
ConcreteTy = MF->getType(ConcreteTyID)->getCanonicalType();
SILValue operand;
- if ((ValueKind) OpCode != ValueKind::AllocExistentialBoxInst)
+ if (OpCode != SILInstructionKind::AllocExistentialBoxInst)
operand = getLocalValue(ValID,
getSILType(Ty2, (SILValueCategory)TyCategory2));
@@ -1003,37 +1001,37 @@
auto ctxConformances = MF->getContext().AllocateCopy(conformances);
- switch ((ValueKind)OpCode) {
+ switch (OpCode) {
default: llvm_unreachable("Out of sync with parent switch");
- case ValueKind::InitExistentialAddrInst:
+ case SILInstructionKind::InitExistentialAddrInst:
ResultVal = Builder.createInitExistentialAddr(Loc, operand,
ConcreteTy,
Ty,
ctxConformances);
break;
- case ValueKind::InitExistentialValueInst:
+ case SILInstructionKind::InitExistentialValueInst:
ResultVal = Builder.createInitExistentialValue(Loc, Ty, ConcreteTy,
operand, ctxConformances);
break;
- case ValueKind::InitExistentialMetatypeInst:
+ case SILInstructionKind::InitExistentialMetatypeInst:
ResultVal = Builder.createInitExistentialMetatype(Loc, operand, Ty,
ctxConformances);
break;
- case ValueKind::InitExistentialRefInst:
+ case SILInstructionKind::InitExistentialRefInst:
ResultVal = Builder.createInitExistentialRef(Loc, Ty,
ConcreteTy,
operand,
ctxConformances);
break;
- case ValueKind::AllocExistentialBoxInst:
+ case SILInstructionKind::AllocExistentialBoxInst:
ResultVal = Builder.createAllocExistentialBox(Loc, Ty, ConcreteTy,
ctxConformances);
break;
}
break;
}
- case ValueKind::AllocRefInst:
- case ValueKind::AllocRefDynamicInst: {
+ case SILInstructionKind::AllocRefInst:
+ case SILInstructionKind::AllocRefDynamicInst: {
assert(RecordKind == SIL_ONE_TYPE_VALUES &&
"Layout should be OneTypeValues.");
unsigned NumVals = ListOfValues.size();
@@ -1054,7 +1052,7 @@
SILValue CountVal = getLocalValue(ListOfValues[i+1], CountType);
Counts.push_back(CountVal);
}
- if ((ValueKind)OpCode == ValueKind::AllocRefDynamicInst) {
+ if (OpCode == SILInstructionKind::AllocRefDynamicInst) {
assert(i + 2 == NumVals);
assert(!canAllocOnStack);
SILType MetadataType = getSILType(MF->getType(ListOfValues[i+1]),
@@ -1069,7 +1067,7 @@
}
break;
}
- case ValueKind::ApplyInst: {
+ case SILInstructionKind::ApplyInst: {
// Format: attributes such as transparent, the callee's type, a value for
// the callee and a list of values for the arguments. Each value in the list
// is represented with 2 IDs: ValueID and ValueResultNumber.
@@ -1099,7 +1097,7 @@
IsNonThrowingApply != 0);
break;
}
- case ValueKind::TryApplyInst: {
+ case SILInstructionKind::TryApplyInst: {
// Format: attributes such as transparent, the callee's type, a value for
// the callee and a list of values for the arguments. Each value in the list
// is represented with 2 IDs: ValueID and ValueResultNumber. The final
@@ -1135,7 +1133,7 @@
Substitutions, Args, normalBB, errorBB);
break;
}
- case ValueKind::PartialApplyInst: {
+ case SILInstructionKind::PartialApplyInst: {
auto Ty = MF->getType(TyID);
auto Ty2 = MF->getType(TyID2);
SILType FnTy = getSILType(Ty, SILValueCategory::Object);
@@ -1172,7 +1170,7 @@
closureTy.getAs<SILFunctionType>()->getCalleeConvention());
break;
}
- case ValueKind::BuiltinInst: {
+ case SILInstructionKind::BuiltinInst: {
auto ASTTy = MF->getType(TyID);
auto ResultTy = getSILType(ASTTy, (SILValueCategory)(unsigned)TyID2);
SmallVector<SILValue, 4> Args;
@@ -1195,7 +1193,7 @@
Args);
break;
}
- case ValueKind::AllocGlobalInst: {
+ case SILInstructionKind::AllocGlobalInst: {
// Format: Name and type. Use SILOneOperandLayout.
Identifier Name = MF->getIdentifier(ValID);
@@ -1206,8 +1204,8 @@
ResultVal = Builder.createAllocGlobal(Loc, g);
break;
}
- case ValueKind::GlobalAddrInst:
- case ValueKind::GlobalValueInst: {
+ case SILInstructionKind::GlobalAddrInst:
+ case SILInstructionKind::GlobalValueInst: {
// Format: Name and type. Use SILOneOperandLayout.
auto Ty = MF->getType(TyID);
Identifier Name = MF->getIdentifier(ValID);
@@ -1215,27 +1213,27 @@
// Find the global variable.
SILGlobalVariable *g = getGlobalForReference(Name.str());
assert(g && "Can't deserialize global variable");
- SILType expectedType = ((ValueKind)OpCode == ValueKind::GlobalAddrInst ?
+ SILType expectedType = (OpCode == SILInstructionKind::GlobalAddrInst ?
g->getLoweredType().getAddressType() :
g->getLoweredType());
assert(expectedType == getSILType(Ty, (SILValueCategory)TyCategory) &&
"Type of a global variable does not match GlobalAddr.");
(void)Ty;
- if ((ValueKind)OpCode == ValueKind::GlobalAddrInst) {
+ if (OpCode == SILInstructionKind::GlobalAddrInst) {
ResultVal = Builder.createGlobalAddr(Loc, g);
} else {
ResultVal = Builder.createGlobalValue(Loc, g);
}
break;
}
- case ValueKind::DeallocStackInst: {
+ case SILInstructionKind::DeallocStackInst: {
auto Ty = MF->getType(TyID);
ResultVal = Builder.createDeallocStack(Loc,
getLocalValue(ValID,
getSILType(Ty, (SILValueCategory)TyCategory)));
break;
}
- case ValueKind::DeallocRefInst: {
+ case SILInstructionKind::DeallocRefInst: {
auto Ty = MF->getType(TyID);
bool OnStack = (bool)Attr;
ResultVal = Builder.createDeallocRef(Loc,
@@ -1243,7 +1241,7 @@
getSILType(Ty, (SILValueCategory)TyCategory)), OnStack);
break;
}
- case ValueKind::DeallocPartialRefInst: {
+ case SILInstructionKind::DeallocPartialRefInst: {
auto Ty = MF->getType(TyID);
auto Ty2 = MF->getType(TyID2);
ResultVal = Builder.createDeallocPartialRef(Loc,
@@ -1253,7 +1251,7 @@
getSILType(Ty2, (SILValueCategory)TyCategory2)));
break;
}
- case ValueKind::FunctionRefInst: {
+ case SILInstructionKind::FunctionRefInst: {
auto Ty = MF->getType(TyID);
Identifier FuncName = MF->getIdentifier(ValID);
ResultVal = Builder.createFunctionRef(Loc,
@@ -1261,7 +1259,7 @@
getSILType(Ty, (SILValueCategory)TyCategory)));
break;
}
- case ValueKind::MarkDependenceInst: {
+ case SILInstructionKind::MarkDependenceInst: {
auto Ty = MF->getType(TyID);
auto Ty2 = MF->getType(TyID2);
ResultVal = Builder.createMarkDependence(Loc,
@@ -1271,7 +1269,7 @@
getSILType(Ty2, (SILValueCategory)TyCategory2)));
break;
}
- case ValueKind::IndexAddrInst: {
+ case SILInstructionKind::IndexAddrInst: {
auto Ty = MF->getType(TyID);
auto Ty2 = MF->getType(TyID2);
ResultVal = Builder.createIndexAddr(Loc,
@@ -1281,7 +1279,7 @@
getSILType(Ty2, (SILValueCategory)TyCategory2)));
break;
}
- case ValueKind::TailAddrInst: {
+ case SILInstructionKind::TailAddrInst: {
auto Ty = MF->getType(TyID);
auto Ty2 = MF->getType(TyID2);
auto ResultTy = MF->getType(TyID3);
@@ -1291,7 +1289,7 @@
getSILType(ResultTy, SILValueCategory::Address));
break;
}
- case ValueKind::IndexRawPointerInst: {
+ case SILInstructionKind::IndexRawPointerInst: {
auto Ty = MF->getType(TyID);
auto Ty2 = MF->getType(TyID2);
ResultVal = Builder.createIndexRawPointer(Loc,
@@ -1301,7 +1299,7 @@
getSILType(Ty2, (SILValueCategory)TyCategory2)));
break;
}
- case ValueKind::IntegerLiteralInst: {
+ case SILInstructionKind::IntegerLiteralInst: {
auto Ty = MF->getType(TyID);
auto intTy = Ty->getAs<BuiltinIntegerType>();
Identifier StringVal = MF->getIdentifier(ValID);
@@ -1312,7 +1310,7 @@
value);
break;
}
- case ValueKind::FloatLiteralInst: {
+ case SILInstructionKind::FloatLiteralInst: {
auto Ty = MF->getType(TyID);
auto floatTy = Ty->getAs<BuiltinFloatType>();
Identifier StringVal = MF->getIdentifier(ValID);
@@ -1328,7 +1326,7 @@
value);
break;
}
- case ValueKind::StringLiteralInst: {
+ case SILInstructionKind::StringLiteralInst: {
Identifier StringVal = MF->getIdentifier(ValID);
auto encoding = fromStableStringEncoding(Attr);
if (!encoding) return true;
@@ -1336,7 +1334,7 @@
encoding.getValue());
break;
}
- case ValueKind::ConstStringLiteralInst: {
+ case SILInstructionKind::ConstStringLiteralInst: {
Identifier StringVal = MF->getIdentifier(ValID);
auto encoding = fromStableConstStringEncoding(Attr);
if (!encoding)
@@ -1345,7 +1343,7 @@
encoding.getValue());
break;
}
- case ValueKind::MarkFunctionEscapeInst: {
+ case SILInstructionKind::MarkFunctionEscapeInst: {
// Format: a list of typed values. A typed value is expressed by 4 IDs:
// TypeID, TypeCategory, ValueID, ValueResultNumber.
SmallVector<SILValue, 4> OpList;
@@ -1359,7 +1357,7 @@
break;
}
// Checked Conversion instructions.
- case ValueKind::UnconditionalCheckedCastInst: {
+ case SILInstructionKind::UnconditionalCheckedCastInst: {
SILValue Val = getLocalValue(ValID,
getSILType(MF->getType(TyID2), (SILValueCategory)TyCategory2));
SILType Ty = getSILType(MF->getType(TyID), (SILValueCategory)TyCategory);
@@ -1368,7 +1366,7 @@
}
#define UNARY_INSTRUCTION(ID) \
- case ValueKind::ID##Inst: \
+ case SILInstructionKind::ID##Inst: \
assert(RecordKind == SIL_ONE_OPERAND && \
"Layout should be OneOperand."); \
ResultVal = Builder.create##ID(Loc, getLocalValue(ValID, \
@@ -1377,7 +1375,7 @@
break;
#define REFCOUNTING_INSTRUCTION(ID) \
- case ValueKind::ID##Inst: \
+ case SILInstructionKind::ID##Inst: \
assert(RecordKind == SIL_ONE_OPERAND && \
"Layout should be OneOperand."); \
ResultVal = Builder.create##ID(Loc, getLocalValue(ValID, \
@@ -1423,7 +1421,7 @@
#undef UNARY_INSTRUCTION
#undef REFCOUNTING_INSTRUCTION
- case ValueKind::UncheckedOwnershipConversionInst: {
+ case SILInstructionKind::UncheckedOwnershipConversionInst: {
auto Ty = MF->getType(TyID);
auto ResultKind = ValueOwnershipKind(Attr);
ResultVal = Builder.createUncheckedOwnershipConversion(
@@ -1432,7 +1430,7 @@
break;
}
- case ValueKind::LoadInst: {
+ case SILInstructionKind::LoadInst: {
auto Ty = MF->getType(TyID);
auto Qualifier = LoadOwnershipQualifier(Attr);
ResultVal = Builder.createLoad(
@@ -1441,7 +1439,7 @@
break;
}
- case ValueKind::LoadUnownedInst: {
+ case SILInstructionKind::LoadUnownedInst: {
auto Ty = MF->getType(TyID);
bool isTake = (Attr > 0);
ResultVal = Builder.createLoadUnowned(Loc,
@@ -1450,7 +1448,7 @@
IsTake_t(isTake));
break;
}
- case ValueKind::LoadWeakInst: {
+ case SILInstructionKind::LoadWeakInst: {
auto Ty = MF->getType(TyID);
bool isTake = (Attr > 0);
ResultVal = Builder.createLoadWeak(Loc,
@@ -1459,14 +1457,14 @@
IsTake_t(isTake));
break;
}
- case ValueKind::MarkUninitializedInst: {
+ case SILInstructionKind::MarkUninitializedInst: {
auto Ty = getSILType(MF->getType(TyID), (SILValueCategory)TyCategory);
auto Kind = (MarkUninitializedInst::Kind)Attr;
auto Val = getLocalValue(ValID, Ty);
ResultVal = Builder.createMarkUninitialized(Loc, Val, Kind);
break;
}
- case ValueKind::StoreInst: {
+ case SILInstructionKind::StoreInst: {
auto Ty = MF->getType(TyID);
SILType addrType = getSILType(Ty, (SILValueCategory)TyCategory);
SILType ValType = addrType.getObjectType();
@@ -1475,7 +1473,7 @@
getLocalValue(ValID2, addrType), Qualifier);
break;
}
- case ValueKind::StoreBorrowInst: {
+ case SILInstructionKind::StoreBorrowInst: {
auto Ty = MF->getType(TyID);
SILType addrType = getSILType(Ty, (SILValueCategory)TyCategory);
SILType ValType = addrType.getObjectType();
@@ -1483,7 +1481,7 @@
getLocalValue(ValID2, addrType));
break;
}
- case ValueKind::EndBorrowInst: {
+ case SILInstructionKind::EndBorrowInst: {
SILValue BorrowSource, BorrowDest;
BorrowSource = getLocalValue(
ValID, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory));
@@ -1492,7 +1490,7 @@
ResultVal = Builder.createEndBorrow(Loc, BorrowSource, BorrowDest);
break;
}
- case ValueKind::BeginAccessInst: {
+ case SILInstructionKind::BeginAccessInst: {
SILValue op = getLocalValue(
ValID, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory));
auto accessKind = SILAccessKind(Attr & 0x3);
@@ -1500,14 +1498,14 @@
ResultVal = Builder.createBeginAccess(Loc, op, accessKind, enforcement);
break;
}
- case ValueKind::EndAccessInst: {
+ case SILInstructionKind::EndAccessInst: {
SILValue op = getLocalValue(
ValID, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory));
bool aborted = Attr & 0x1;
ResultVal = Builder.createEndAccess(Loc, op, aborted);
break;
}
- case ValueKind::BeginUnpairedAccessInst: {
+ case SILInstructionKind::BeginUnpairedAccessInst: {
SILValue source = getLocalValue(
ValID, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory));
SILValue buffer = getLocalValue(
@@ -1518,7 +1516,7 @@
accessKind, enforcement);
break;
}
- case ValueKind::EndUnpairedAccessInst: {
+ case SILInstructionKind::EndUnpairedAccessInst: {
SILValue op = getLocalValue(
ValID, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory));
bool aborted = Attr & 0x1;
@@ -1526,7 +1524,7 @@
ResultVal = Builder.createEndUnpairedAccess(Loc, op, enforcement, aborted);
break;
}
- case ValueKind::StoreUnownedInst: {
+ case SILInstructionKind::StoreUnownedInst: {
auto Ty = MF->getType(TyID);
SILType addrType = getSILType(Ty, (SILValueCategory)TyCategory);
auto refType = addrType.getAs<WeakStorageType>();
@@ -1538,7 +1536,7 @@
IsInitialization_t(isInit));
break;
}
- case ValueKind::StoreWeakInst: {
+ case SILInstructionKind::StoreWeakInst: {
auto Ty = MF->getType(TyID);
SILType addrType = getSILType(Ty, (SILValueCategory)TyCategory);
auto refType = addrType.getAs<WeakStorageType>();
@@ -1550,7 +1548,7 @@
IsInitialization_t(isInit));
break;
}
- case ValueKind::CopyAddrInst: {
+ case SILInstructionKind::CopyAddrInst: {
auto Ty = MF->getType(TyID);
SILType addrType = getSILType(Ty, (SILValueCategory)TyCategory);
bool isInit = (Attr & 0x2) > 0;
@@ -1562,7 +1560,7 @@
IsInitialization_t(isInit));
break;
}
- case ValueKind::AssignInst: {
+ case SILInstructionKind::AssignInst: {
auto Ty = MF->getType(TyID);
SILType addrType = getSILType(Ty, (SILValueCategory)TyCategory);
SILType ValType = addrType.getObjectType();
@@ -1571,7 +1569,7 @@
getLocalValue(ValID2, addrType));
break;
}
- case ValueKind::BindMemoryInst: {
+ case SILInstructionKind::BindMemoryInst: {
assert(RecordKind == SIL_ONE_TYPE_VALUES &&
"Layout should be OneTypeValues.");
auto Ty = MF->getType(TyID); // BoundTy
@@ -1586,15 +1584,15 @@
getSILType(Ty, (SILValueCategory)TyCategory));
break;
}
- case ValueKind::StructElementAddrInst:
- case ValueKind::StructExtractInst: {
+ case SILInstructionKind::StructElementAddrInst:
+ case SILInstructionKind::StructExtractInst: {
// Use SILOneValueOneOperandLayout.
VarDecl *Field = cast<VarDecl>(MF->getDecl(ValID));
auto Ty = MF->getType(TyID);
auto Val = getLocalValue(ValID2,
getSILType(Ty, (SILValueCategory)TyCategory));
auto ResultTy = Val->getType().getFieldType(Field, SILMod);
- if ((ValueKind)OpCode == ValueKind::StructElementAddrInst)
+ if (OpCode == SILInstructionKind::StructElementAddrInst)
ResultVal = Builder.createStructElementAddr(Loc, Val, Field,
ResultTy.getAddressType());
else
@@ -1602,7 +1600,7 @@
ResultTy.getObjectType());
break;
}
- case ValueKind::StructInst: {
+ case SILInstructionKind::StructInst: {
// Format: a type followed by a list of typed values. A typed value is
// expressed by 4 IDs: TypeID, TypeCategory, ValueID, ValueResultNumber.
auto Ty = MF->getType(TyID);
@@ -1618,22 +1616,22 @@
OpList);
break;
}
- case ValueKind::TupleElementAddrInst:
- case ValueKind::TupleExtractInst: {
+ case SILInstructionKind::TupleElementAddrInst:
+ case SILInstructionKind::TupleExtractInst: {
// Use OneTypeOneOperand layout where the field number is stored in TypeID.
auto Ty2 = MF->getType(TyID2);
SILType ST = getSILType(Ty2, (SILValueCategory)TyCategory2);
TupleType *TT = ST.getAs<TupleType>();
auto ResultTy = TT->getElement(TyID).getType();
- switch ((ValueKind)OpCode) {
+ switch (OpCode) {
default: llvm_unreachable("Out of sync with parent switch");
- case ValueKind::TupleElementAddrInst:
+ case SILInstructionKind::TupleElementAddrInst:
ResultVal = Builder.createTupleElementAddr(Loc,
getLocalValue(ValID, ST),
TyID, getSILType(ResultTy, SILValueCategory::Address));
break;
- case ValueKind::TupleExtractInst:
+ case SILInstructionKind::TupleExtractInst:
ResultVal = Builder.createTupleExtract(Loc,
getLocalValue(ValID,ST),
TyID,
@@ -1642,7 +1640,7 @@
}
break;
}
- case ValueKind::TupleInst: {
+ case SILInstructionKind::TupleInst: {
// Format: a type followed by a list of values. A value is expressed by
// 2 IDs: ValueID, ValueResultNumber.
auto Ty = MF->getType(TyID);
@@ -1660,10 +1658,10 @@
OpList);
break;
}
- case ValueKind::ObjectInst: {
+ case SILInstructionKind::ObjectInst: {
llvm_unreachable("Serialization of global initializers not supported");
}
- case ValueKind::BranchInst: {
+ case SILInstructionKind::BranchInst: {
SmallVector<SILValue, 4> Args;
for (unsigned I = 0, E = ListOfValues.size(); I < E; I += 3)
Args.push_back(
@@ -1675,7 +1673,7 @@
Args);
break;
}
- case ValueKind::CondBranchInst: {
+ case SILInstructionKind::CondBranchInst: {
// Format: condition, true basic block ID, a list of arguments, false basic
// block ID, a list of arguments. Use SILOneTypeValuesLayout: the type is
// for condition, the list has value for condition, true basic block ID,
@@ -1707,8 +1705,8 @@
getBBForReference(Fn, ListOfValues[2]), FalseArgs);
break;
}
- case ValueKind::SwitchEnumInst:
- case ValueKind::SwitchEnumAddrInst: {
+ case SILInstructionKind::SwitchEnumInst:
+ case SILInstructionKind::SwitchEnumAddrInst: {
// Format: condition, a list of cases (EnumElementDecl + Basic Block ID),
// default basic block ID. Use SILOneTypeValuesLayout: the type is
// for condition, the list has value for condition, hasDefault, default
@@ -1726,15 +1724,15 @@
CaseBBs.push_back( {cast<EnumElementDecl>(MF->getDecl(ListOfValues[I])),
getBBForReference(Fn, ListOfValues[I+1])} );
}
- if ((ValueKind)OpCode == ValueKind::SwitchEnumInst)
+ if (OpCode == SILInstructionKind::SwitchEnumInst)
ResultVal = Builder.createSwitchEnum(Loc, Cond, DefaultBB, CaseBBs);
else
ResultVal = Builder.createSwitchEnumAddr(Loc, Cond,
DefaultBB, CaseBBs);
break;
}
- case ValueKind::SelectEnumInst:
- case ValueKind::SelectEnumAddrInst: {
+ case SILInstructionKind::SelectEnumInst:
+ case SILInstructionKind::SelectEnumAddrInst: {
// Format: condition, a list of cases (EnumElementDecl + Value ID),
// default value ID. Use SILOneTypeValuesLayout: the type is
// for condition, the list has value for condition, result type,
@@ -1758,7 +1756,7 @@
CaseVals.push_back({cast<EnumElementDecl>(MF->getDecl(ListOfValues[I])),
Value});
}
- if ((ValueKind)OpCode == ValueKind::SelectEnumInst)
+ if (OpCode == SILInstructionKind::SelectEnumInst)
ResultVal = Builder.createSelectEnum(Loc, Cond, ResultTy,
DefaultVal, CaseVals);
else
@@ -1766,7 +1764,7 @@
DefaultVal, CaseVals);
break;
}
- case ValueKind::SwitchValueInst: {
+ case SILInstructionKind::SwitchValueInst: {
// Format: condition, a list of cases (Value ID + Basic Block ID),
// default basic block ID. Use SILOneTypeValuesLayout: the type is
// for condition, the list contains value for condition, hasDefault, default
@@ -1788,7 +1786,7 @@
ResultVal = Builder.createSwitchValue(Loc, Cond, DefaultBB, CaseBBs);
break;
}
- case ValueKind::SelectValueInst: {
+ case SILInstructionKind::SelectValueInst: {
// Format: condition, a list of cases (ValueID + Value ID),
// default value ID. Use SILOneTypeValuesLayout: the type is
// for condition, the list has value for condition, result type,
@@ -1816,7 +1814,7 @@
DefaultVal, CaseValuesAndResults);
break;
}
- case ValueKind::EnumInst: {
+ case SILInstructionKind::EnumInst: {
// Format: a type, an operand and a decl ID. Use SILTwoOperandsLayout: type,
// (DeclID + hasOperand), and an operand.
SILValue Operand;
@@ -1830,7 +1828,7 @@
(SILValueCategory)TyCategory));
break;
}
- case ValueKind::InitEnumDataAddrInst: {
+ case SILInstructionKind::InitEnumDataAddrInst: {
// Use SILOneValueOneOperandLayout.
EnumElementDecl *Elt = cast<EnumElementDecl>(MF->getDecl(ValID));
SILType OperandTy = getSILType(MF->getType(TyID),
@@ -1841,7 +1839,7 @@
Elt, ResultTy);
break;
}
- case ValueKind::UncheckedEnumDataInst: {
+ case SILInstructionKind::UncheckedEnumDataInst: {
// Use SILOneValueOneOperandLayout.
EnumElementDecl *Elt = cast<EnumElementDecl>(MF->getDecl(ValID));
SILType OperandTy = getSILType(MF->getType(TyID),
@@ -1852,7 +1850,7 @@
Elt, ResultTy);
break;
}
- case ValueKind::UncheckedTakeEnumDataAddrInst: {
+ case SILInstructionKind::UncheckedTakeEnumDataAddrInst: {
// Use SILOneValueOneOperandLayout.
EnumElementDecl *Elt = cast<EnumElementDecl>(MF->getDecl(ValID));
SILType OperandTy = getSILType(MF->getType(TyID),
@@ -1863,7 +1861,7 @@
Elt, ResultTy);
break;
}
- case ValueKind::InjectEnumAddrInst: {
+ case SILInstructionKind::InjectEnumAddrInst: {
// Use SILOneValueOneOperandLayout.
EnumElementDecl *Elt = cast<EnumElementDecl>(MF->getDecl(ValID));
auto Ty = MF->getType(TyID);
@@ -1873,7 +1871,7 @@
Elt);
break;
}
- case ValueKind::RefElementAddrInst: {
+ case SILInstructionKind::RefElementAddrInst: {
// Use SILOneValueOneOperandLayout.
VarDecl *Field = cast<VarDecl>(MF->getDecl(ValID));
auto Ty = MF->getType(TyID);
@@ -1884,7 +1882,7 @@
ResultTy);
break;
}
- case ValueKind::RefTailAddrInst: {
+ case SILInstructionKind::RefTailAddrInst: {
assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND &&
"Layout should be OneTypeOneOperand.");
assert(Attr == 0);
@@ -1896,9 +1894,9 @@
getSILType(MF->getType(TyID), SILValueCategory::Address));
break;
}
- case ValueKind::ClassMethodInst:
- case ValueKind::SuperMethodInst:
- case ValueKind::DynamicMethodInst: {
+ case SILInstructionKind::ClassMethodInst:
+ case SILInstructionKind::SuperMethodInst:
+ case SILInstructionKind::DynamicMethodInst: {
// Format: a type, an operand and a SILDeclRef. Use SILOneTypeValuesLayout:
// type, Attr, SILDeclRef (DeclID, Kind, uncurryLevel, IsObjC),
// and an operand.
@@ -1912,19 +1910,19 @@
NextValueIndex += 2;
bool IsVolatile = ListOfValues[0] > 0;
- switch ((ValueKind)OpCode) {
+ switch (OpCode) {
default: llvm_unreachable("Out of sync with parent switch");
- case ValueKind::ClassMethodInst:
+ case SILInstructionKind::ClassMethodInst:
ResultVal = Builder.createClassMethod(Loc,
getLocalValue(ListOfValues[NextValueIndex], operandTy),
DRef, Ty, IsVolatile);
break;
- case ValueKind::SuperMethodInst:
+ case SILInstructionKind::SuperMethodInst:
ResultVal = Builder.createSuperMethod(Loc,
getLocalValue(ListOfValues[NextValueIndex], operandTy),
DRef, Ty, IsVolatile);
break;
- case ValueKind::DynamicMethodInst:
+ case SILInstructionKind::DynamicMethodInst:
ResultVal = Builder.createDynamicMethod(Loc,
getLocalValue(ListOfValues[NextValueIndex], operandTy),
DRef, Ty, IsVolatile);
@@ -1932,7 +1930,7 @@
}
break;
}
- case ValueKind::WitnessMethodInst: {
+ case SILInstructionKind::WitnessMethodInst: {
unsigned NextValueIndex = 0;
SILDeclRef DRef = getSILDeclRef(MF, ListOfValues, NextValueIndex);
assert(ListOfValues.size() >= NextValueIndex &&
@@ -1955,7 +1953,7 @@
Loc, Ty, Conformance, DRef, OperandTy, Attr);
break;
}
- case ValueKind::DynamicMethodBranchInst: {
+ case SILInstructionKind::DynamicMethodBranchInst: {
// Format: a typed value, a SILDeclRef, a BasicBlock ID for method,
// a BasicBlock ID for no method. Use SILOneTypeValuesLayout.
unsigned NextValueIndex = 1;
@@ -1969,7 +1967,7 @@
getBBForReference(Fn, ListOfValues[NextValueIndex+1]));
break;
}
- case ValueKind::CheckedCastBranchInst: {
+ case SILInstructionKind::CheckedCastBranchInst: {
// Format: the cast kind, a typed value, a BasicBlock ID for success,
// a BasicBlock ID for failure. Uses SILOneTypeValuesLayout.
assert(ListOfValues.size() == 6 &&
@@ -1987,7 +1985,7 @@
successBB, failureBB);
break;
}
- case ValueKind::CheckedCastValueBranchInst: {
+ case SILInstructionKind::CheckedCastValueBranchInst: {
// Format: the cast kind, a typed value, a BasicBlock ID for success,
// a BasicBlock ID for failure. Uses SILOneTypeValuesLayout.
assert(ListOfValues.size() == 5 &&
@@ -2004,14 +2002,14 @@
failureBB);
break;
}
- case ValueKind::UnconditionalCheckedCastValueInst: {
+ case SILInstructionKind::UnconditionalCheckedCastValueInst: {
SILValue Val = getLocalValue(
ValID, getSILType(MF->getType(TyID2), (SILValueCategory)TyCategory2));
SILType Ty = getSILType(MF->getType(TyID), (SILValueCategory)TyCategory);
ResultVal = Builder.createUnconditionalCheckedCastValue(Loc, Val, Ty);
break;
}
- case ValueKind::UnconditionalCheckedCastAddrInst: {
+ case SILInstructionKind::UnconditionalCheckedCastAddrInst: {
// ignore attr.
CanType sourceType = MF->getType(ListOfValues[0])->getCanonicalType();
SILType srcAddrTy = getSILType(MF->getType(ListOfValues[2]),
@@ -2027,7 +2025,7 @@
dest, targetType);
break;
}
- case ValueKind::CheckedCastAddrBranchInst: {
+ case SILInstructionKind::CheckedCastAddrBranchInst: {
CastConsumptionKind consumption = getCastConsumptionKind(ListOfValues[0]);
CanType sourceType = MF->getType(ListOfValues[1])->getCanonicalType();
@@ -2048,7 +2046,7 @@
successBB, failureBB);
break;
}
- case ValueKind::UncheckedRefCastAddrInst: {
+ case SILInstructionKind::UncheckedRefCastAddrInst: {
CanType sourceType = MF->getType(ListOfValues[0])->getCanonicalType();
// ignore attr.
SILType srcAddrTy = getSILType(MF->getType(ListOfValues[2]),
@@ -2064,7 +2062,7 @@
dest, targetType);
break;
}
- case ValueKind::InitBlockStorageHeaderInst: {
+ case SILInstructionKind::InitBlockStorageHeaderInst: {
assert(ListOfValues.size() == 5 &&
"expected 5 values for InitBlockStorageHeader");
SILType blockTy
@@ -2093,11 +2091,11 @@
blockTy, Substitutions);
break;
}
- case ValueKind::UnreachableInst: {
+ case SILInstructionKind::UnreachableInst: {
ResultVal = Builder.createUnreachable(Loc);
break;
}
- case ValueKind::KeyPathInst: {
+ case SILInstructionKind::KeyPathInst: {
unsigned nextValue = 0;
SILType kpTy
= getSILType(MF->getType(TyID), (SILValueCategory)TyCategory);
@@ -2250,13 +2248,13 @@
substitutions, operands, kpTy);
break;
}
- case ValueKind::MarkUninitializedBehaviorInst:
+ case SILInstructionKind::MarkUninitializedBehaviorInst:
llvm_unreachable("todo");
}
- if (ResultVal->hasValue()) {
+ for (auto result : ResultVal->getResults()) {
LastValueID = LastValueID + 1;
- setLocalValue(ResultVal, LastValueID);
+ setLocalValue(result, LastValueID);
}
return false;
diff --git a/lib/Serialization/SerializeSIL.cpp b/lib/Serialization/SerializeSIL.cpp
index b759524..9f6a048 100644
--- a/lib/Serialization/SerializeSIL.cpp
+++ b/lib/Serialization/SerializeSIL.cpp
@@ -226,17 +226,17 @@
void writeSILBlock(const SILModule *SILMod);
void writeIndexTables();
- void writeConversionLikeInstruction(const SILInstruction *I);
- void writeOneTypeLayout(ValueKind valueKind, SILType type);
- void writeOneTypeOneOperandLayout(ValueKind valueKind,
+ void writeConversionLikeInstruction(const SingleValueInstruction *I);
+ void writeOneTypeLayout(SILInstructionKind valueKind, SILType type);
+ void writeOneTypeOneOperandLayout(SILInstructionKind valueKind,
unsigned attrs,
SILType type,
SILValue operand);
- void writeOneTypeOneOperandLayout(ValueKind valueKind,
+ void writeOneTypeOneOperandLayout(SILInstructionKind valueKind,
unsigned attrs,
CanType type,
SILValue operand);
- void writeOneOperandLayout(ValueKind valueKind,
+ void writeOneOperandLayout(SILInstructionKind valueKind,
unsigned attrs,
SILValue operand);
@@ -415,8 +415,8 @@
ValueIDs[static_cast<const ValueBase*>(*I)] = ++ValueID;
for (const SILInstruction &SI : BB)
- if (SI.hasValue())
- ValueIDs[&SI] = ++ValueID;
+ for (auto result : SI.getResults())
+ ValueIDs[result] = ++ValueID;
}
// Write SIL basic blocks in the RPOT order
@@ -501,7 +501,7 @@
ListOfValues.push_back(addValueRef(operand));
}
-void SILSerializer::writeOneTypeLayout(ValueKind valueKind,
+void SILSerializer::writeOneTypeLayout(SILInstructionKind valueKind,
SILType type) {
unsigned abbrCode = SILAbbrCodes[SILOneTypeLayout::Code];
SILOneTypeLayout::emitRecord(Out, ScratchRecord, abbrCode,
@@ -510,7 +510,7 @@
(unsigned)type.getCategory());
}
-void SILSerializer::writeOneOperandLayout(ValueKind valueKind,
+void SILSerializer::writeOneOperandLayout(SILInstructionKind valueKind,
unsigned attrs,
SILValue operand) {
@@ -525,7 +525,7 @@
operandRef);
}
-void SILSerializer::writeOneTypeOneOperandLayout(ValueKind valueKind,
+void SILSerializer::writeOneTypeOneOperandLayout(SILInstructionKind valueKind,
unsigned attrs,
SILType type,
SILValue operand) {
@@ -541,7 +541,7 @@
operandTypeRef, unsigned(operandType.getCategory()),
operandRef);
}
-void SILSerializer::writeOneTypeOneOperandLayout(ValueKind valueKind,
+void SILSerializer::writeOneTypeOneOperandLayout(SILInstructionKind valueKind,
unsigned attrs,
CanType type,
SILValue operand) {
@@ -560,7 +560,7 @@
/// Write an instruction that looks exactly like a conversion: all
/// important information is encoded in the operand and the result type.
-void SILSerializer::writeConversionLikeInstruction(const SILInstruction *I) {
+void SILSerializer::writeConversionLikeInstruction(const SingleValueInstruction *I) {
assert(I->getNumOperands() - I->getTypeDependentOperands().size() == 1);
writeOneTypeOneOperandLayout(I->getKind(), 0, I->getType(),
I->getOperand(0));
@@ -568,32 +568,27 @@
void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
switch (SI.getKind()) {
- case ValueKind::SILPHIArgument:
- case ValueKind::SILFunctionArgument:
- case ValueKind::SILUndef:
- llvm_unreachable("not an instruction");
-
- case ValueKind::ObjectInst:
+ case SILInstructionKind::ObjectInst:
llvm_unreachable("static initializers of sil_global are not serialized");
- case ValueKind::DebugValueInst:
- case ValueKind::DebugValueAddrInst:
+ case SILInstructionKind::DebugValueInst:
+ case SILInstructionKind::DebugValueAddrInst:
// Currently we don't serialize debug variable infos, so it doesn't make
// sense to write the instruction at all.
// TODO: decide if we want to serialize those instructions.
return;
- case ValueKind::UnreachableInst: {
+ case SILInstructionKind::UnreachableInst: {
unsigned abbrCode = SILAbbrCodes[SILInstNoOperandLayout::Code];
SILInstNoOperandLayout::emitRecord(Out, ScratchRecord, abbrCode,
(unsigned)SI.getKind());
break;
}
- case ValueKind::AllocExistentialBoxInst:
- case ValueKind::InitExistentialAddrInst:
- case ValueKind::InitExistentialValueInst:
- case ValueKind::InitExistentialMetatypeInst:
- case ValueKind::InitExistentialRefInst: {
+ case SILInstructionKind::AllocExistentialBoxInst:
+ case SILInstructionKind::InitExistentialAddrInst:
+ case SILInstructionKind::InitExistentialValueInst:
+ case SILInstructionKind::InitExistentialMetatypeInst:
+ case SILInstructionKind::InitExistentialRefInst: {
SILValue operand;
SILType Ty;
CanType FormalConcreteType;
@@ -601,7 +596,7 @@
switch (SI.getKind()) {
default: llvm_unreachable("out of sync with parent");
- case ValueKind::InitExistentialAddrInst: {
+ case SILInstructionKind::InitExistentialAddrInst: {
auto &IEI = cast<InitExistentialAddrInst>(SI);
operand = IEI.getOperand();
Ty = IEI.getLoweredConcreteType();
@@ -609,7 +604,7 @@
conformances = IEI.getConformances();
break;
}
- case ValueKind::InitExistentialValueInst: {
+ case SILInstructionKind::InitExistentialValueInst: {
auto &IEOI = cast<InitExistentialValueInst>(SI);
operand = IEOI.getOperand();
Ty = IEOI.getType();
@@ -617,7 +612,7 @@
conformances = IEOI.getConformances();
break;
}
- case ValueKind::InitExistentialRefInst: {
+ case SILInstructionKind::InitExistentialRefInst: {
auto &IERI = cast<InitExistentialRefInst>(SI);
operand = IERI.getOperand();
Ty = IERI.getType();
@@ -625,14 +620,14 @@
conformances = IERI.getConformances();
break;
}
- case ValueKind::InitExistentialMetatypeInst: {
+ case SILInstructionKind::InitExistentialMetatypeInst: {
auto &IEMI = cast<InitExistentialMetatypeInst>(SI);
operand = IEMI.getOperand();
Ty = IEMI.getType();
conformances = IEMI.getConformances();
break;
}
- case ValueKind::AllocExistentialBoxInst: {
+ case SILInstructionKind::AllocExistentialBoxInst: {
auto &AEBI = cast<AllocExistentialBoxInst>(SI);
Ty = AEBI.getExistentialType();
FormalConcreteType = AEBI.getFormalConcreteType();
@@ -666,55 +661,55 @@
}
break;
}
- case ValueKind::DeallocValueBufferInst: {
+ case SILInstructionKind::DeallocValueBufferInst: {
auto DVBI = cast<DeallocValueBufferInst>(&SI);
writeOneTypeOneOperandLayout(DVBI->getKind(), 0,
DVBI->getValueType(),
DVBI->getOperand());
break;
}
- case ValueKind::DeallocBoxInst: {
+ case SILInstructionKind::DeallocBoxInst: {
auto DBI = cast<DeallocBoxInst>(&SI);
writeOneTypeOneOperandLayout(DBI->getKind(), 0,
DBI->getOperand()->getType(),
DBI->getOperand());
break;
}
- case ValueKind::DeallocExistentialBoxInst: {
+ case SILInstructionKind::DeallocExistentialBoxInst: {
auto DBI = cast<DeallocExistentialBoxInst>(&SI);
writeOneTypeOneOperandLayout(DBI->getKind(), 0,
DBI->getConcreteType(),
DBI->getOperand());
break;
}
- case ValueKind::ValueMetatypeInst: {
+ case SILInstructionKind::ValueMetatypeInst: {
auto VMI = cast<ValueMetatypeInst>(&SI);
writeOneTypeOneOperandLayout(VMI->getKind(), 0,
VMI->getType(),
VMI->getOperand());
break;
}
- case ValueKind::ExistentialMetatypeInst: {
+ case SILInstructionKind::ExistentialMetatypeInst: {
auto EMI = cast<ExistentialMetatypeInst>(&SI);
writeOneTypeOneOperandLayout(EMI->getKind(), 0,
EMI->getType(),
EMI->getOperand());
break;
}
- case ValueKind::AllocValueBufferInst: {
+ case SILInstructionKind::AllocValueBufferInst: {
auto AVBI = cast<AllocValueBufferInst>(&SI);
writeOneTypeOneOperandLayout(AVBI->getKind(), 0,
AVBI->getValueType(),
AVBI->getOperand());
break;
}
- case ValueKind::AllocBoxInst: {
+ case SILInstructionKind::AllocBoxInst: {
const AllocBoxInst *ABI = cast<AllocBoxInst>(&SI);
writeOneTypeLayout(ABI->getKind(), ABI->getType());
break;
}
- case ValueKind::AllocRefInst:
- case ValueKind::AllocRefDynamicInst: {
+ case SILInstructionKind::AllocRefInst:
+ case SILInstructionKind::AllocRefDynamicInst: {
const AllocRefInstBase *ARI = cast<AllocRefInstBase>(&SI);
unsigned abbrCode = SILAbbrCodes[SILOneTypeValuesLayout::Code];
SmallVector<ValueID, 4> Args;
@@ -724,7 +719,7 @@
ArrayRef<Operand> AllOps = ARI->getAllOperands();
unsigned NumTailAllocs = TailTypes.size();
unsigned NumOpsToWrite = NumTailAllocs;
- if (SI.getKind() == ValueKind::AllocRefDynamicInst)
+ if (SI.getKind() == SILInstructionKind::AllocRefDynamicInst)
++NumOpsToWrite;
for (unsigned Idx = 0; Idx < NumOpsToWrite; ++Idx) {
if (Idx < NumTailAllocs) {
@@ -745,19 +740,19 @@
Args);
break;
}
- case ValueKind::AllocStackInst: {
+ case SILInstructionKind::AllocStackInst: {
const AllocStackInst *ASI = cast<AllocStackInst>(&SI);
writeOneTypeLayout(ASI->getKind(), ASI->getElementType());
break;
}
- case ValueKind::ProjectValueBufferInst: {
+ case SILInstructionKind::ProjectValueBufferInst: {
auto PVBI = cast<ProjectValueBufferInst>(&SI);
writeOneTypeOneOperandLayout(PVBI->getKind(), 0,
PVBI->getType(),
PVBI->getOperand());
break;
}
- case ValueKind::ProjectBoxInst: {
+ case SILInstructionKind::ProjectBoxInst: {
auto PBI = cast<ProjectBoxInst>(&SI);
// Use SILOneTypeOneOperandLayout with the field index crammed in the TypeID
@@ -774,14 +769,14 @@
boxRef);
break;
}
- case ValueKind::ProjectExistentialBoxInst: {
+ case SILInstructionKind::ProjectExistentialBoxInst: {
auto PEBI = cast<ProjectExistentialBoxInst>(&SI);
writeOneTypeOneOperandLayout(PEBI->getKind(), 0,
PEBI->getType(),
PEBI->getOperand());
break;
}
- case ValueKind::BuiltinInst: {
+ case SILInstructionKind::BuiltinInst: {
// Format: number of substitutions, the builtin name, result type, and
// a list of values for the arguments. Each value in the list
// is represented with 4 IDs:
@@ -805,7 +800,7 @@
S.writeSubstitutions(BI->getSubstitutions(), SILAbbrCodes);
break;
}
- case ValueKind::ApplyInst: {
+ case SILInstructionKind::ApplyInst: {
// Format: attributes such as transparent and number of substitutions,
// the callee's substituted and unsubstituted types, a value for
// the callee and a list of values for the arguments. Each value in the list
@@ -827,7 +822,7 @@
S.writeSubstitutions(AI->getSubstitutions(), SILAbbrCodes);
break;
}
- case ValueKind::TryApplyInst: {
+ case SILInstructionKind::TryApplyInst: {
// Format: attributes such as transparent and number of substitutions,
// the callee's substituted and unsubstituted types, a value for
// the callee and a list of values for the arguments. Each value in the list
@@ -851,7 +846,7 @@
S.writeSubstitutions(AI->getSubstitutions(), SILAbbrCodes);
break;
}
- case ValueKind::PartialApplyInst: {
+ case SILInstructionKind::PartialApplyInst: {
const PartialApplyInst *PAI = cast<PartialApplyInst>(&SI);
SmallVector<ValueID, 4> Args;
for (auto Arg: PAI->getArguments()) {
@@ -867,7 +862,7 @@
S.writeSubstitutions(PAI->getSubstitutions(), SILAbbrCodes);
break;
}
- case ValueKind::AllocGlobalInst: {
+ case SILInstructionKind::AllocGlobalInst: {
// Format: Name and type. Use SILOneOperandLayout.
const AllocGlobalInst *AGI = cast<AllocGlobalInst>(&SI);
SILOneOperandLayout::emitRecord(Out, ScratchRecord,
@@ -877,8 +872,8 @@
Ctx.getIdentifier(AGI->getReferencedGlobal()->getName())));
break;
}
- case ValueKind::GlobalAddrInst:
- case ValueKind::GlobalValueInst: {
+ case SILInstructionKind::GlobalAddrInst:
+ case SILInstructionKind::GlobalValueInst: {
// Format: Name and type. Use SILOneOperandLayout.
const GlobalAccessInst *GI = cast<GlobalAccessInst>(&SI);
SILOneOperandLayout::emitRecord(Out, ScratchRecord,
@@ -890,7 +885,7 @@
Ctx.getIdentifier(GI->getReferencedGlobal()->getName())));
break;
}
- case ValueKind::BranchInst: {
+ case SILInstructionKind::BranchInst: {
// Format: destination basic block ID, a list of arguments. Use
// SILOneTypeValuesLayout.
const BranchInst *BrI = cast<BranchInst>(&SI);
@@ -907,7 +902,7 @@
BasicBlockMap[BrI->getDestBB()], 0, ListOfValues);
break;
}
- case ValueKind::CondBranchInst: {
+ case SILInstructionKind::CondBranchInst: {
// Format: condition, true basic block ID, a list of arguments, false basic
// block ID, a list of arguments. Use SILOneTypeValuesLayout: the type is
// for condition, the list has value for condition, true basic block ID,
@@ -938,8 +933,8 @@
ListOfValues);
break;
}
- case ValueKind::SwitchEnumInst:
- case ValueKind::SwitchEnumAddrInst: {
+ case SILInstructionKind::SwitchEnumInst:
+ case SILInstructionKind::SwitchEnumAddrInst: {
// Format: condition, a list of cases (EnumElementDecl + Basic Block ID),
// default basic block ID. Use SILOneTypeValuesLayout: the type is
// for condition, the list has value for condition, hasDefault, default
@@ -968,8 +963,8 @@
ListOfValues);
break;
}
- case ValueKind::SelectEnumInst:
- case ValueKind::SelectEnumAddrInst: {
+ case SILInstructionKind::SelectEnumInst:
+ case SILInstructionKind::SelectEnumAddrInst: {
// Format: condition, a list of cases (EnumElementDecl + Value ID),
// default value ID. Use SILOneTypeValuesLayout: the type is
// for condition, the list has value for condition, result type,
@@ -1001,7 +996,7 @@
ListOfValues);
break;
}
- case ValueKind::SwitchValueInst: {
+ case SILInstructionKind::SwitchValueInst: {
// Format: condition, a list of cases (Value ID + Basic Block ID),
// default basic block ID. Use SILOneTypeValuesLayout: the type is
// for condition, the list contains value for condition, hasDefault, default
@@ -1030,7 +1025,7 @@
ListOfValues);
break;
}
- case ValueKind::SelectValueInst: {
+ case SILInstructionKind::SelectValueInst: {
// Format: condition, a list of cases (Value ID + Value ID),
// default value ID. Use SILOneTypeValuesLayout: the type is
// for condition, the list has value for condition, result type,
@@ -1062,47 +1057,47 @@
ListOfValues);
break;
}
- case ValueKind::CondFailInst:
- case ValueKind::RetainValueInst:
- case ValueKind::RetainValueAddrInst:
- case ValueKind::UnmanagedRetainValueInst:
- case ValueKind::EndBorrowArgumentInst:
- case ValueKind::CopyValueInst:
- case ValueKind::CopyUnownedValueInst:
- case ValueKind::DestroyValueInst:
- case ValueKind::ReleaseValueInst:
- case ValueKind::ReleaseValueAddrInst:
- case ValueKind::UnmanagedReleaseValueInst:
- case ValueKind::AutoreleaseValueInst:
- case ValueKind::UnmanagedAutoreleaseValueInst:
- case ValueKind::SetDeallocatingInst:
- case ValueKind::DeallocStackInst:
- case ValueKind::DeallocRefInst:
- case ValueKind::DeinitExistentialAddrInst:
- case ValueKind::DeinitExistentialValueInst:
- case ValueKind::DestroyAddrInst:
- case ValueKind::IsNonnullInst:
- case ValueKind::LoadInst:
- case ValueKind::LoadBorrowInst:
- case ValueKind::BeginBorrowInst:
- case ValueKind::LoadUnownedInst:
- case ValueKind::LoadWeakInst:
- case ValueKind::MarkUninitializedInst:
- case ValueKind::FixLifetimeInst:
- case ValueKind::EndLifetimeInst:
- case ValueKind::CopyBlockInst:
- case ValueKind::StrongPinInst:
- case ValueKind::StrongReleaseInst:
- case ValueKind::StrongRetainInst:
- case ValueKind::StrongUnpinInst:
- case ValueKind::StrongRetainUnownedInst:
- case ValueKind::UnownedRetainInst:
- case ValueKind::UnownedReleaseInst:
- case ValueKind::IsUniqueInst:
- case ValueKind::IsUniqueOrPinnedInst:
- case ValueKind::ReturnInst:
- case ValueKind::UncheckedOwnershipConversionInst:
- case ValueKind::ThrowInst: {
+ case SILInstructionKind::CondFailInst:
+ case SILInstructionKind::RetainValueInst:
+ case SILInstructionKind::RetainValueAddrInst:
+ case SILInstructionKind::UnmanagedRetainValueInst:
+ case SILInstructionKind::EndBorrowArgumentInst:
+ case SILInstructionKind::CopyValueInst:
+ case SILInstructionKind::CopyUnownedValueInst:
+ case SILInstructionKind::DestroyValueInst:
+ case SILInstructionKind::ReleaseValueInst:
+ case SILInstructionKind::ReleaseValueAddrInst:
+ case SILInstructionKind::UnmanagedReleaseValueInst:
+ case SILInstructionKind::AutoreleaseValueInst:
+ case SILInstructionKind::UnmanagedAutoreleaseValueInst:
+ case SILInstructionKind::SetDeallocatingInst:
+ case SILInstructionKind::DeallocStackInst:
+ case SILInstructionKind::DeallocRefInst:
+ case SILInstructionKind::DeinitExistentialAddrInst:
+ case SILInstructionKind::DeinitExistentialValueInst:
+ case SILInstructionKind::DestroyAddrInst:
+ case SILInstructionKind::IsNonnullInst:
+ case SILInstructionKind::LoadInst:
+ case SILInstructionKind::LoadBorrowInst:
+ case SILInstructionKind::BeginBorrowInst:
+ case SILInstructionKind::LoadUnownedInst:
+ case SILInstructionKind::LoadWeakInst:
+ case SILInstructionKind::MarkUninitializedInst:
+ case SILInstructionKind::FixLifetimeInst:
+ case SILInstructionKind::EndLifetimeInst:
+ case SILInstructionKind::CopyBlockInst:
+ case SILInstructionKind::StrongPinInst:
+ case SILInstructionKind::StrongReleaseInst:
+ case SILInstructionKind::StrongRetainInst:
+ case SILInstructionKind::StrongUnpinInst:
+ case SILInstructionKind::StrongRetainUnownedInst:
+ case SILInstructionKind::UnownedRetainInst:
+ case SILInstructionKind::UnownedReleaseInst:
+ case SILInstructionKind::IsUniqueInst:
+ case SILInstructionKind::IsUniqueOrPinnedInst:
+ case SILInstructionKind::ReturnInst:
+ case SILInstructionKind::UncheckedOwnershipConversionInst:
+ case SILInstructionKind::ThrowInst: {
unsigned Attr = 0;
if (auto *LI = dyn_cast<LoadInst>(&SI))
Attr = unsigned(LI->getOwnershipQualifier());
@@ -1116,13 +1111,15 @@
Attr = (unsigned)DRI->canAllocOnStack();
else if (auto *RCI = dyn_cast<RefCountingInst>(&SI))
Attr = RCI->isNonAtomic();
+ else if (auto *RCI = dyn_cast<StrongPinInst>(&SI))
+ Attr = RCI->isNonAtomic();
else if (auto *UOCI = dyn_cast<UncheckedOwnershipConversionInst>(&SI)) {
Attr = unsigned(SILValue(UOCI).getOwnershipKind());
}
writeOneOperandLayout(SI.getKind(), Attr, SI.getOperand(0));
break;
}
- case ValueKind::FunctionRefInst: {
+ case SILInstructionKind::FunctionRefInst: {
// Use SILOneOperandLayout to specify the function type and the function
// name (IdentifierID).
const FunctionRefInst *FRI = cast<FunctionRefInst>(&SI);
@@ -1136,21 +1133,21 @@
break;
}
- case ValueKind::DeallocPartialRefInst:
- case ValueKind::MarkDependenceInst:
- case ValueKind::IndexAddrInst:
- case ValueKind::IndexRawPointerInst: {
+ case SILInstructionKind::DeallocPartialRefInst:
+ case SILInstructionKind::MarkDependenceInst:
+ case SILInstructionKind::IndexAddrInst:
+ case SILInstructionKind::IndexRawPointerInst: {
SILValue operand, operand2;
unsigned Attr = 0;
- if (SI.getKind() == ValueKind::DeallocPartialRefInst) {
+ if (SI.getKind() == SILInstructionKind::DeallocPartialRefInst) {
const DeallocPartialRefInst *DPRI = cast<DeallocPartialRefInst>(&SI);
operand = DPRI->getInstance();
operand2 = DPRI->getMetatype();
- } else if (SI.getKind() == ValueKind::IndexRawPointerInst) {
+ } else if (SI.getKind() == SILInstructionKind::IndexRawPointerInst) {
const IndexRawPointerInst *IRP = cast<IndexRawPointerInst>(&SI);
operand = IRP->getBase();
operand2 = IRP->getIndex();
- } else if (SI.getKind() == ValueKind::MarkDependenceInst) {
+ } else if (SI.getKind() == SILInstructionKind::MarkDependenceInst) {
const MarkDependenceInst *MDI = cast<MarkDependenceInst>(&SI);
operand = MDI->getValue();
operand2 = MDI->getBase();
@@ -1170,7 +1167,7 @@
addValueRef(operand2));
break;
}
- case ValueKind::TailAddrInst: {
+ case SILInstructionKind::TailAddrInst: {
const TailAddrInst *TAI = cast<TailAddrInst>(&SI);
SILTailAddrLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILTailAddrLayout::Code],
@@ -1182,7 +1179,7 @@
S.addTypeRef(TAI->getTailType().getSwiftRValueType()));
break;
}
- case ValueKind::StringLiteralInst: {
+ case SILInstructionKind::StringLiteralInst: {
auto SLI = cast<StringLiteralInst>(&SI);
StringRef Str = SLI->getValue();
unsigned abbrCode = SILAbbrCodes[SILOneOperandLayout::Code];
@@ -1192,7 +1189,7 @@
S.addDeclBaseNameRef(Ctx.getIdentifier(Str)));
break;
}
- case ValueKind::ConstStringLiteralInst: {
+ case SILInstructionKind::ConstStringLiteralInst: {
auto SLI = cast<ConstStringLiteralInst>(&SI);
StringRef Str = SLI->getValue();
unsigned abbrCode = SILAbbrCodes[SILOneOperandLayout::Code];
@@ -1202,18 +1199,18 @@
S.addDeclBaseNameRef(Ctx.getIdentifier(Str)));
break;
}
- case ValueKind::FloatLiteralInst:
- case ValueKind::IntegerLiteralInst: {
+ case SILInstructionKind::FloatLiteralInst:
+ case SILInstructionKind::IntegerLiteralInst: {
// Use SILOneOperandLayout to specify the type and the literal.
std::string Str;
SILType Ty;
switch (SI.getKind()) {
default: llvm_unreachable("Out of sync with parent switch");
- case ValueKind::IntegerLiteralInst:
+ case SILInstructionKind::IntegerLiteralInst:
Str = cast<IntegerLiteralInst>(&SI)->getValue().toString(10, true);
Ty = cast<IntegerLiteralInst>(&SI)->getType();
break;
- case ValueKind::FloatLiteralInst:
+ case SILInstructionKind::FloatLiteralInst:
Str = cast<FloatLiteralInst>(&SI)->getBits().toString(16,
/*Signed*/false);
Ty = cast<FloatLiteralInst>(&SI)->getType();
@@ -1227,7 +1224,7 @@
S.addDeclBaseNameRef(Ctx.getIdentifier(Str)));
break;
}
- case ValueKind::MarkFunctionEscapeInst: {
+ case SILInstructionKind::MarkFunctionEscapeInst: {
// Format: a list of typed values. A typed value is expressed by 4 IDs:
// TypeID, TypeCategory, ValueID, ValueResultNumber.
const MarkFunctionEscapeInst *MFE = cast<MarkFunctionEscapeInst>(&SI);
@@ -1243,10 +1240,12 @@
(unsigned)SI.getKind(), 0, 0, ListOfValues);
break;
}
- case ValueKind::MetatypeInst:
- writeOneTypeLayout(SI.getKind(), SI.getType());
+ case SILInstructionKind::MetatypeInst: {
+ auto &MI = cast<MetatypeInst>(SI);
+ writeOneTypeLayout(MI.getKind(), MI.getType());
break;
- case ValueKind::ObjCProtocolInst: {
+ }
+ case SILInstructionKind::ObjCProtocolInst: {
const ObjCProtocolInst *PI = cast<ObjCProtocolInst>(&SI);
unsigned abbrCode = SILAbbrCodes[SILOneOperandLayout::Code];
SILOneOperandLayout::emitRecord(Out, ScratchRecord, abbrCode,
@@ -1256,57 +1255,57 @@
S.addDeclRef(PI->getProtocol()));
break;
}
- case ValueKind::OpenExistentialAddrInst: {
- assert(SI.getNumOperands() - SI.getTypeDependentOperands().size() == 1);
- unsigned attrs = cast<OpenExistentialAddrInst>(SI).getAccessKind() ==
- OpenedExistentialAccess::Immutable
+ case SILInstructionKind::OpenExistentialAddrInst: {
+ auto &open = cast<OpenExistentialAddrInst>(SI);
+ assert(open.getNumOperands() - open.getTypeDependentOperands().size() == 1);
+ unsigned attrs = open.getAccessKind() == OpenedExistentialAccess::Immutable
? 0 : 1;
- writeOneTypeOneOperandLayout(SI.getKind(), attrs, SI.getType(),
- SI.getOperand(0));
+ writeOneTypeOneOperandLayout(open.getKind(), attrs, open.getType(),
+ open.getOperand());
break;
}
// Conversion instructions (and others of similar form).
- case ValueKind::OpenExistentialRefInst:
- case ValueKind::OpenExistentialMetatypeInst:
- case ValueKind::OpenExistentialBoxInst:
- case ValueKind::OpenExistentialValueInst:
- case ValueKind::OpenExistentialBoxValueInst:
- case ValueKind::UncheckedRefCastInst:
- case ValueKind::UncheckedAddrCastInst:
- case ValueKind::UncheckedTrivialBitCastInst:
- case ValueKind::UncheckedBitwiseCastInst:
- case ValueKind::BridgeObjectToRefInst:
- case ValueKind::BridgeObjectToWordInst:
- case ValueKind::UpcastInst:
- case ValueKind::AddressToPointerInst:
- case ValueKind::RefToRawPointerInst:
- case ValueKind::RawPointerToRefInst:
- case ValueKind::RefToUnownedInst:
- case ValueKind::UnownedToRefInst:
- case ValueKind::RefToUnmanagedInst:
- case ValueKind::UnmanagedToRefInst:
- case ValueKind::ThinToThickFunctionInst:
- case ValueKind::ThickToObjCMetatypeInst:
- case ValueKind::ObjCToThickMetatypeInst:
- case ValueKind::ConvertFunctionInst:
- case ValueKind::ThinFunctionToPointerInst:
- case ValueKind::PointerToThinFunctionInst:
- case ValueKind::ObjCMetatypeToObjectInst:
- case ValueKind::ObjCExistentialMetatypeToObjectInst:
- case ValueKind::ProjectBlockStorageInst: {
- writeConversionLikeInstruction(&SI);
+ case SILInstructionKind::OpenExistentialRefInst:
+ case SILInstructionKind::OpenExistentialMetatypeInst:
+ case SILInstructionKind::OpenExistentialBoxInst:
+ case SILInstructionKind::OpenExistentialValueInst:
+ case SILInstructionKind::OpenExistentialBoxValueInst:
+ case SILInstructionKind::UncheckedRefCastInst:
+ case SILInstructionKind::UncheckedAddrCastInst:
+ case SILInstructionKind::UncheckedTrivialBitCastInst:
+ case SILInstructionKind::UncheckedBitwiseCastInst:
+ case SILInstructionKind::BridgeObjectToRefInst:
+ case SILInstructionKind::BridgeObjectToWordInst:
+ case SILInstructionKind::UpcastInst:
+ case SILInstructionKind::AddressToPointerInst:
+ case SILInstructionKind::RefToRawPointerInst:
+ case SILInstructionKind::RawPointerToRefInst:
+ case SILInstructionKind::RefToUnownedInst:
+ case SILInstructionKind::UnownedToRefInst:
+ case SILInstructionKind::RefToUnmanagedInst:
+ case SILInstructionKind::UnmanagedToRefInst:
+ case SILInstructionKind::ThinToThickFunctionInst:
+ case SILInstructionKind::ThickToObjCMetatypeInst:
+ case SILInstructionKind::ObjCToThickMetatypeInst:
+ case SILInstructionKind::ConvertFunctionInst:
+ case SILInstructionKind::ThinFunctionToPointerInst:
+ case SILInstructionKind::PointerToThinFunctionInst:
+ case SILInstructionKind::ObjCMetatypeToObjectInst:
+ case SILInstructionKind::ObjCExistentialMetatypeToObjectInst:
+ case SILInstructionKind::ProjectBlockStorageInst: {
+ writeConversionLikeInstruction(cast<SingleValueInstruction>(&SI));
break;
}
- case ValueKind::PointerToAddressInst: {
- assert(SI.getNumOperands() - SI.getTypeDependentOperands().size() == 1);
+ case SILInstructionKind::PointerToAddressInst: {
auto &PAI = cast<PointerToAddressInst>(SI);
+ assert(PAI.getNumOperands() - PAI.getTypeDependentOperands().size() == 1);
unsigned attrs = (PAI.isStrict() ? 1 : 0)
| (PAI.isInvariant() ? 2 : 0);
- writeOneTypeOneOperandLayout(SI.getKind(), attrs, SI.getType(),
- SI.getOperand(0));
+ writeOneTypeOneOperandLayout(PAI.getKind(), attrs, PAI.getType(),
+ PAI.getOperand());
break;
}
- case ValueKind::RefToBridgeObjectInst: {
+ case SILInstructionKind::RefToBridgeObjectInst: {
auto RI = cast<RefToBridgeObjectInst>(&SI);
SILTwoOperandsLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILTwoOperandsLayout::Code], (unsigned)SI.getKind(),
@@ -1320,7 +1319,7 @@
break;
}
// Checked Conversion instructions.
- case ValueKind::UnconditionalCheckedCastInst: {
+ case SILInstructionKind::UnconditionalCheckedCastInst: {
auto CI = cast<UnconditionalCheckedCastInst>(&SI);
SILInstCastLayout::emitRecord(Out, ScratchRecord,
SILAbbrCodes[SILInstCastLayout::Code],
@@ -1332,7 +1331,7 @@
addValueRef(CI->getOperand()));
break;
}
- case ValueKind::UnconditionalCheckedCastAddrInst: {
+ case SILInstructionKind::UnconditionalCheckedCastAddrInst: {
auto CI = cast<UnconditionalCheckedCastAddrInst>(&SI);
ValueID listOfValues[] = {
S.addTypeRef(CI->getSourceType()),
@@ -1349,7 +1348,7 @@
llvm::makeArrayRef(listOfValues));
break;
}
- case ValueKind::UnconditionalCheckedCastValueInst: {
+ case SILInstructionKind::UnconditionalCheckedCastValueInst: {
auto CI = cast<UnconditionalCheckedCastValueInst>(&SI);
SILInstCastLayout::emitRecord(
Out, ScratchRecord, SILAbbrCodes[SILInstCastLayout::Code],
@@ -1362,7 +1361,7 @@
addValueRef(CI->getOperand()));
break;
}
- case ValueKind::UncheckedRefCastAddrInst: {
+ case SILInstructionKind::UncheckedRefCastAddrInst: {
auto CI = cast<UncheckedRefCastAddrInst>(&SI);
ValueID listOfValues[] = {
S.addTypeRef(CI->getSourceType()),
@@ -1380,7 +1379,7 @@
break;
}
- case ValueKind::EndBorrowInst: {
+ case SILInstructionKind::EndBorrowInst: {
unsigned abbrCode = SILAbbrCodes[SILTwoOperandsLayout::Code];
unsigned Attr = 0;
auto *EBI = cast<EndBorrowInst>(&SI);
@@ -1398,7 +1397,7 @@
break;
}
- case ValueKind::BeginAccessInst: {
+ case SILInstructionKind::BeginAccessInst: {
unsigned abbrCode = SILAbbrCodes[SILOneOperandLayout::Code];
auto *BAI = cast<BeginAccessInst>(&SI);
unsigned attr =
@@ -1414,7 +1413,7 @@
break;
}
- case ValueKind::EndAccessInst: {
+ case SILInstructionKind::EndAccessInst: {
unsigned abbrCode = SILAbbrCodes[SILOneOperandLayout::Code];
auto *EAI = cast<EndAccessInst>(&SI);
unsigned attr = unsigned(EAI->isAborting());
@@ -1428,7 +1427,7 @@
break;
}
- case ValueKind::BeginUnpairedAccessInst: {
+ case SILInstructionKind::BeginUnpairedAccessInst: {
unsigned abbrCode = SILAbbrCodes[SILTwoOperandsLayout::Code];
auto *BAI = cast<BeginUnpairedAccessInst>(&SI);
unsigned attr =
@@ -1448,7 +1447,7 @@
break;
}
- case ValueKind::EndUnpairedAccessInst: {
+ case SILInstructionKind::EndUnpairedAccessInst: {
unsigned abbrCode = SILAbbrCodes[SILOneOperandLayout::Code];
auto *EAI = cast<EndUnpairedAccessInst>(&SI);
unsigned attr = unsigned(EAI->isAborting())
@@ -1463,30 +1462,30 @@
break;
}
- case ValueKind::AssignInst:
- case ValueKind::CopyAddrInst:
- case ValueKind::StoreInst:
- case ValueKind::StoreBorrowInst:
- case ValueKind::StoreUnownedInst:
- case ValueKind::StoreWeakInst: {
+ case SILInstructionKind::AssignInst:
+ case SILInstructionKind::CopyAddrInst:
+ case SILInstructionKind::StoreInst:
+ case SILInstructionKind::StoreBorrowInst:
+ case SILInstructionKind::StoreUnownedInst:
+ case SILInstructionKind::StoreWeakInst: {
SILValue operand, value;
unsigned Attr = 0;
- if (SI.getKind() == ValueKind::StoreWeakInst) {
+ if (SI.getKind() == SILInstructionKind::StoreWeakInst) {
Attr = cast<StoreWeakInst>(&SI)->isInitializationOfDest();
operand = cast<StoreWeakInst>(&SI)->getDest();
value = cast<StoreWeakInst>(&SI)->getSrc();
- } else if (SI.getKind() == ValueKind::StoreUnownedInst) {
+ } else if (SI.getKind() == SILInstructionKind::StoreUnownedInst) {
Attr = cast<StoreUnownedInst>(&SI)->isInitializationOfDest();
operand = cast<StoreUnownedInst>(&SI)->getDest();
value = cast<StoreUnownedInst>(&SI)->getSrc();
- } else if (SI.getKind() == ValueKind::StoreInst) {
+ } else if (SI.getKind() == SILInstructionKind::StoreInst) {
Attr = unsigned(cast<StoreInst>(&SI)->getOwnershipQualifier());
operand = cast<StoreInst>(&SI)->getDest();
value = cast<StoreInst>(&SI)->getSrc();
- } else if (SI.getKind() == ValueKind::AssignInst) {
+ } else if (SI.getKind() == SILInstructionKind::AssignInst) {
operand = cast<AssignInst>(&SI)->getDest();
value = cast<AssignInst>(&SI)->getSrc();
- } else if (SI.getKind() == ValueKind::CopyAddrInst) {
+ } else if (SI.getKind() == SILInstructionKind::CopyAddrInst) {
const CopyAddrInst *CAI = cast<CopyAddrInst>(&SI);
Attr = (CAI->isInitializationOfDest() << 1) | CAI->isTakeOfSrc();
operand = cast<CopyAddrInst>(&SI)->getDest();
@@ -1506,7 +1505,7 @@
addValueRef(operand));
break;
}
- case ValueKind::BindMemoryInst: {
+ case SILInstructionKind::BindMemoryInst: {
auto *BI = cast<BindMemoryInst>(&SI);
SILValue baseOperand = BI->getBase();
SILValue indexOperand = BI->getIndex();
@@ -1531,44 +1530,44 @@
ListOfValues);
break;
}
- case ValueKind::RefElementAddrInst:
- case ValueKind::StructElementAddrInst:
- case ValueKind::StructExtractInst:
- case ValueKind::InitEnumDataAddrInst:
- case ValueKind::UncheckedEnumDataInst:
- case ValueKind::UncheckedTakeEnumDataAddrInst:
- case ValueKind::InjectEnumAddrInst: {
+ case SILInstructionKind::RefElementAddrInst:
+ case SILInstructionKind::StructElementAddrInst:
+ case SILInstructionKind::StructExtractInst:
+ case SILInstructionKind::InitEnumDataAddrInst:
+ case SILInstructionKind::UncheckedEnumDataInst:
+ case SILInstructionKind::UncheckedTakeEnumDataAddrInst:
+ case SILInstructionKind::InjectEnumAddrInst: {
// Has a typed valueref and a field decl. We use SILOneValueOneOperandLayout
// where the field decl is streamed as a ValueID.
SILValue operand;
Decl *tDecl;
switch (SI.getKind()) {
default: llvm_unreachable("Out of sync with parent switch");
- case ValueKind::RefElementAddrInst:
+ case SILInstructionKind::RefElementAddrInst:
operand = cast<RefElementAddrInst>(&SI)->getOperand();
tDecl = cast<RefElementAddrInst>(&SI)->getField();
break;
- case ValueKind::StructElementAddrInst:
+ case SILInstructionKind::StructElementAddrInst:
operand = cast<StructElementAddrInst>(&SI)->getOperand();
tDecl = cast<StructElementAddrInst>(&SI)->getField();
break;
- case ValueKind::StructExtractInst:
+ case SILInstructionKind::StructExtractInst:
operand = cast<StructExtractInst>(&SI)->getOperand();
tDecl = cast<StructExtractInst>(&SI)->getField();
break;
- case ValueKind::InitEnumDataAddrInst:
+ case SILInstructionKind::InitEnumDataAddrInst:
operand = cast<InitEnumDataAddrInst>(&SI)->getOperand();
tDecl = cast<InitEnumDataAddrInst>(&SI)->getElement();
break;
- case ValueKind::UncheckedEnumDataInst:
+ case SILInstructionKind::UncheckedEnumDataInst:
operand = cast<UncheckedEnumDataInst>(&SI)->getOperand();
tDecl = cast<UncheckedEnumDataInst>(&SI)->getElement();
break;
- case ValueKind::UncheckedTakeEnumDataAddrInst:
+ case SILInstructionKind::UncheckedTakeEnumDataAddrInst:
operand = cast<UncheckedTakeEnumDataAddrInst>(&SI)->getOperand();
tDecl = cast<UncheckedTakeEnumDataAddrInst>(&SI)->getElement();
break;
- case ValueKind::InjectEnumAddrInst:
+ case SILInstructionKind::InjectEnumAddrInst:
operand = cast<InjectEnumAddrInst>(&SI)->getOperand();
tDecl = cast<InjectEnumAddrInst>(&SI)->getElement();
break;
@@ -1581,14 +1580,14 @@
addValueRef(operand));
break;
}
- case ValueKind::RefTailAddrInst: {
+ case SILInstructionKind::RefTailAddrInst: {
auto *RTAI = cast<RefTailAddrInst>(&SI);
writeOneTypeOneOperandLayout(RTAI->getKind(), 0,
RTAI->getType(),
RTAI->getOperand());
break;
}
- case ValueKind::StructInst: {
+ case SILInstructionKind::StructInst: {
// Format: a type followed by a list of typed values. A typed value is
// expressed by 4 IDs: TypeID, TypeCategory, ValueID, ValueResultNumber.
const StructInst *StrI = cast<StructInst>(&SI);
@@ -1606,17 +1605,17 @@
(unsigned)StrI->getType().getCategory(), ListOfValues);
break;
}
- case ValueKind::TupleElementAddrInst:
- case ValueKind::TupleExtractInst: {
+ case SILInstructionKind::TupleElementAddrInst:
+ case SILInstructionKind::TupleExtractInst: {
SILValue operand;
unsigned FieldNo;
switch (SI.getKind()) {
default: llvm_unreachable("Out of sync with parent switch");
- case ValueKind::TupleElementAddrInst:
+ case SILInstructionKind::TupleElementAddrInst:
operand = cast<TupleElementAddrInst>(&SI)->getOperand();
FieldNo = cast<TupleElementAddrInst>(&SI)->getFieldNo();
break;
- case ValueKind::TupleExtractInst:
+ case SILInstructionKind::TupleExtractInst:
operand = cast<TupleExtractInst>(&SI)->getOperand();
FieldNo = cast<TupleExtractInst>(&SI)->getFieldNo();
break;
@@ -1632,7 +1631,7 @@
addValueRef(operand));
break;
}
- case ValueKind::TupleInst: {
+ case SILInstructionKind::TupleInst: {
// Format: a type followed by a list of values. A value is expressed by
// 2 IDs: ValueID, ValueResultNumber.
const TupleInst *TI = cast<TupleInst>(&SI);
@@ -1649,7 +1648,7 @@
ListOfValues);
break;
}
- case ValueKind::EnumInst: {
+ case SILInstructionKind::EnumInst: {
// Format: a type, an operand and a decl ID. Use SILTwoOperandsLayout: type,
// (DeclID + hasOperand), and an operand.
const EnumInst *UI = cast<EnumInst>(&SI);
@@ -1667,7 +1666,7 @@
UI->hasOperand() ? addValueRef(UI->getOperand()) : ValueID());
break;
}
- case ValueKind::WitnessMethodInst: {
+ case SILInstructionKind::WitnessMethodInst: {
// Format: a type, an operand and a SILDeclRef. Use SILOneTypeValuesLayout:
// type, Attr, SILDeclRef (DeclID, Kind, uncurryLevel, IsObjC), and a type.
const WitnessMethodInst *AMI = cast<WitnessMethodInst>(&SI);
@@ -1693,7 +1692,7 @@
break;
}
- case ValueKind::ClassMethodInst: {
+ case SILInstructionKind::ClassMethodInst: {
// Format: a type, an operand and a SILDeclRef. Use SILOneTypeValuesLayout:
// type, Attr, SILDeclRef (DeclID, Kind, uncurryLevel, IsObjC),
// and an operand.
@@ -1708,7 +1707,7 @@
(unsigned)Ty.getCategory(), ListOfValues);
break;
}
- case ValueKind::SuperMethodInst: {
+ case SILInstructionKind::SuperMethodInst: {
// Format: a type, an operand and a SILDeclRef. Use SILOneTypeValuesLayout:
// type, Attr, SILDeclRef (DeclID, Kind, uncurryLevel, IsObjC),
// and an operand.
@@ -1723,7 +1722,7 @@
(unsigned)Ty.getCategory(), ListOfValues);
break;
}
- case ValueKind::DynamicMethodInst: {
+ case SILInstructionKind::DynamicMethodInst: {
// Format: a type, an operand and a SILDeclRef. Use SILOneTypeValuesLayout:
// type, Attr, SILDeclRef (DeclID, Kind, uncurryLevel, IsObjC),
// and an operand.
@@ -1738,7 +1737,7 @@
(unsigned)Ty.getCategory(), ListOfValues);
break;
}
- case ValueKind::DynamicMethodBranchInst: {
+ case SILInstructionKind::DynamicMethodBranchInst: {
// Format: a typed value, a SILDeclRef, a BasicBlock ID for method,
// a BasicBlock ID for no method. Use SILOneTypeValuesLayout.
const DynamicMethodBranchInst *DMB = cast<DynamicMethodBranchInst>(&SI);
@@ -1754,7 +1753,7 @@
(unsigned)DMB->getOperand()->getType().getCategory(), ListOfValues);
break;
}
- case ValueKind::CheckedCastBranchInst: {
+ case SILInstructionKind::CheckedCastBranchInst: {
// Format: the cast kind, a typed value, a BasicBlock ID for success,
// a BasicBlock ID for failure. Uses SILOneTypeValuesLayout.
const CheckedCastBranchInst *CBI = cast<CheckedCastBranchInst>(&SI);
@@ -1774,7 +1773,7 @@
ListOfValues);
break;
}
- case ValueKind::CheckedCastValueBranchInst: {
+ case SILInstructionKind::CheckedCastValueBranchInst: {
// Format: the cast kind, a typed value, a BasicBlock ID for success,
// a BasicBlock ID for failure. Uses SILOneTypeValuesLayout.
const CheckedCastValueBranchInst *CBI =
@@ -1795,7 +1794,7 @@
(unsigned)CBI->getCastType().getCategory(), ListOfValues);
break;
}
- case ValueKind::CheckedCastAddrBranchInst: {
+ case SILInstructionKind::CheckedCastAddrBranchInst: {
// Format: the cast kind, two typed values, a BasicBlock ID for
// success, a BasicBlock ID for failure. Uses SILOneTypeValuesLayout;
// the type is the type of the second (dest) operand.
@@ -1818,7 +1817,7 @@
llvm::makeArrayRef(listOfValues));
break;
}
- case ValueKind::InitBlockStorageHeaderInst: {
+ case SILInstructionKind::InitBlockStorageHeaderInst: {
auto IBSHI = cast<InitBlockStorageHeaderInst>(&SI);
SmallVector<ValueID, 6> ListOfValues;
ListOfValues.push_back(addValueRef(IBSHI->getBlockStorage()));
@@ -1841,7 +1840,7 @@
break;
}
- case ValueKind::KeyPathInst: {
+ case SILInstructionKind::KeyPathInst: {
auto KPI = cast<KeyPathInst>(&SI);
SmallVector<ValueID, 6> ListOfValues;
@@ -1964,12 +1963,12 @@
break;
}
- case ValueKind::MarkUninitializedBehaviorInst:
+ case SILInstructionKind::MarkUninitializedBehaviorInst:
llvm_unreachable("todo");
}
// Non-void values get registered in the value table.
- if (SI.hasValue()) {
- addValueRef(&SI);
+ for (auto result : SI.getResults()) {
+ addValueRef(result);
++InstID;
}
}
diff --git a/stdlib/public/Reflection/MetadataSource.cpp b/stdlib/public/Reflection/MetadataSource.cpp
index 59c989c..7278c53 100644
--- a/stdlib/public/Reflection/MetadataSource.cpp
+++ b/stdlib/public/Reflection/MetadataSource.cpp
@@ -87,13 +87,6 @@
closeForm();
}
- void
- visitParentMetadataSource(const ParentMetadataSource *P) {
- printHeader("parent_of");
- printRec(P->getChild());
- closeForm();
- }
-
void visitSelfMetadataSource(const SelfMetadataSource *S) {
printHeader("self");
closeForm();
diff --git a/stdlib/public/core/Equatable.swift b/stdlib/public/core/Equatable.swift
index a72e3a2..a00c38d 100644
--- a/stdlib/public/core/Equatable.swift
+++ b/stdlib/public/core/Equatable.swift
@@ -236,10 +236,7 @@
public func === (lhs: AnyObject?, rhs: AnyObject?) -> Bool {
switch (lhs, rhs) {
case let (l?, r?):
- return Bool(Builtin.cmp_eq_RawPointer(
- Builtin.bridgeToRawPointer(Builtin.castToUnknownObject(l)),
- Builtin.bridgeToRawPointer(Builtin.castToUnknownObject(r))
- ))
+ return ObjectIdentifier(l) == ObjectIdentifier(r)
case (nil, nil):
return true
default:
diff --git a/stdlib/public/core/VarArgs.swift b/stdlib/public/core/VarArgs.swift
index b521f81..5a2adb8 100644
--- a/stdlib/public/core/VarArgs.swift
+++ b/stdlib/public/core/VarArgs.swift
@@ -168,6 +168,12 @@
}
}
+extension Bool : CVarArg {
+ public var _cVarArgEncoding: [Int] {
+ return _encodeBitsAsWords(Int32(self ? 1:0))
+ }
+}
+
extension Int64 : CVarArg, _CVarArgAligned {
/// Transform `self` into a series of machine words that can be
/// appropriately interpreted by C varargs.
diff --git a/stdlib/public/runtime/Demangle.cpp b/stdlib/public/runtime/Demangle.cpp
index d36c04f..423b096 100644
--- a/stdlib/public/runtime/Demangle.cpp
+++ b/stdlib/public/runtime/Demangle.cpp
@@ -30,13 +30,107 @@
swift::_swift_buildDemanglingForMetadata(const Metadata *type,
Demangle::Demangler &Dem);
+static Demangle::NodePointer
+_applyGenericArguments(const Metadata * const *genericArgs,
+ const NominalTypeDescriptor *description,
+ Demangle::NodePointer node, unsigned depth,
+ Demangle::Demangler &Dem) {
+ assert(depth > 0);
+
+ auto typeNode = node;
+ if (typeNode->getKind() == Node::Kind::Type)
+ typeNode = typeNode->getChild(0);
+
+ auto parentNode = typeNode->getChild(0);
+
+ // It might be more accurate to keep this sugar, but the old version
+ // of this function dropped it, and I want to keep things compatible.
+ if (parentNode->getKind() == Node::Kind::Extension) {
+ parentNode = parentNode->getChild(1);
+ }
+
+ switch (parentNode->getKind()) {
+ case Node::Kind::Class:
+ case Node::Kind::Structure:
+ case Node::Kind::Enum: {
+ // The parent type is a nominal type which may have its own generic
+ // arguments.
+ auto newParentNode = _applyGenericArguments(genericArgs, description,
+ parentNode, depth - 1,
+ Dem);
+ if (newParentNode == nullptr)
+ return nullptr;
+
+ auto newTypeNode = Dem.createNode(typeNode->getKind());
+ newTypeNode->addChild(newParentNode, Dem);
+ newTypeNode->addChild(typeNode->getChild(1), Dem);
+
+ typeNode = newTypeNode;
+ break;
+ }
+ default:
+ // Parent is a local context or module. Leave it as-is, and just apply
+ // generic arguments below.
+ break;
+ }
+
+ // See if we have any generic arguments at this depth.
+ unsigned numArgumentsAtDepth =
+ description->GenericParams.getContext(depth - 1).NumPrimaryParams;
+ if (numArgumentsAtDepth == 0) {
+ // No arguments here, just return the original node (except we may have
+ // replaced its parent type above).
+ return typeNode;
+ }
+
+ // Ok, we have generic arguments. Figure out where the arguments for this
+ // depth begin in the generic type metadata.
+ unsigned firstArgumentAtDepth = 0;
+ for (unsigned i = 0; i < depth - 1; i++) {
+ firstArgumentAtDepth +=
+ description->GenericParams.getContext(i).NumPrimaryParams;
+ }
+
+ // Demangle them.
+ auto typeParams = Dem.createNode(Node::Kind::TypeList);
+ for (unsigned i = firstArgumentAtDepth,
+ e = firstArgumentAtDepth + numArgumentsAtDepth;
+ i < e; ++i) {
+ auto demangling = _swift_buildDemanglingForMetadata(genericArgs[i], Dem);
+ if (demangling == nullptr)
+ return nullptr;
+ typeParams->addChild(demangling, Dem);
+ }
+
+ Node::Kind boundGenericKind;
+ switch (typeNode->getKind()) {
+ case Node::Kind::Class:
+ boundGenericKind = Node::Kind::BoundGenericClass;
+ break;
+ case Node::Kind::Structure:
+ boundGenericKind = Node::Kind::BoundGenericStructure;
+ break;
+ case Node::Kind::Enum:
+ boundGenericKind = Node::Kind::BoundGenericEnum;
+ break;
+ default:
+ return nullptr;
+ }
+
+ auto newNode = Dem.createNode(Node::Kind::Type);
+ newNode->addChild(typeNode, Dem);
+
+ auto genericNode = Dem.createNode(boundGenericKind);
+ genericNode->addChild(newNode, Dem);
+ genericNode->addChild(typeParams, Dem);
+ return genericNode;
+}
+
// Build a demangled type tree for a nominal type.
static Demangle::NodePointer
_buildDemanglingForNominalType(const Metadata *type, Demangle::Demangler &Dem) {
using namespace Demangle;
- const Metadata *parent;
- Node::Kind boundGenericKind;
const NominalTypeDescriptor *description;
// Demangle the parent type, if any.
@@ -48,23 +142,17 @@
while (classType->isTypeMetadata() && classType->isArtificialSubclass())
classType = classType->SuperClass;
#endif
- parent = classType->getParentType(classType->getDescription());
- boundGenericKind = Node::Kind::BoundGenericClass;
description = classType->getDescription();
break;
}
case MetadataKind::Enum:
case MetadataKind::Optional: {
auto enumType = static_cast<const EnumMetadata *>(type);
- parent = enumType->Parent;
- boundGenericKind = Node::Kind::BoundGenericEnum;
description = enumType->Description;
break;
}
case MetadataKind::Struct: {
auto structType = static_cast<const StructMetadata *>(type);
- parent = structType->Parent;
- boundGenericKind = Node::Kind::BoundGenericStructure;
description = structType->Description;
break;
}
@@ -76,42 +164,13 @@
auto node = Dem.demangleType(StringRef(description->Name));
assert(node->getKind() == Node::Kind::Type);
- // Demangle the parent.
- if (parent) {
- auto parentNode = _swift_buildDemanglingForMetadata(parent, Dem);
- if (parentNode->getKind() == Node::Kind::Type)
- parentNode = parentNode->getChild(0);
+ auto typeBytes = reinterpret_cast<const char *>(type);
+ auto genericArgs = reinterpret_cast<const Metadata * const *>(
+ typeBytes + sizeof(void*) * description->GenericParams.Offset);
- auto typeNode = node->getChild(0);
- auto newTypeNode = Dem.createNode(typeNode->getKind());
- newTypeNode->addChild(parentNode, Dem);
- newTypeNode->addChild(typeNode->getChild(1), Dem);
-
- auto newNode = Dem.createNode(Node::Kind::Type);
- newNode->addChild(newTypeNode, Dem);
- node = newNode;
- }
-
- // If generic, demangle the type parameters.
- if (description->GenericParams.NumPrimaryParams > 0) {
- auto typeParams = Dem.createNode(Node::Kind::TypeList);
- auto typeBytes = reinterpret_cast<const char *>(type);
- auto genericParam = reinterpret_cast<const Metadata * const *>(
- typeBytes + sizeof(void*) * description->GenericParams.Offset);
- for (unsigned i = 0, e = description->GenericParams.NumPrimaryParams;
- i < e; ++i, ++genericParam) {
- auto demangling = _swift_buildDemanglingForMetadata(*genericParam, Dem);
- if (demangling == nullptr)
- return nullptr;
- typeParams->addChild(demangling, Dem);
- }
-
- auto genericNode = Dem.createNode(boundGenericKind);
- genericNode->addChild(node, Dem);
- genericNode->addChild(typeParams, Dem);
- return genericNode;
- }
- return node;
+ return _applyGenericArguments(genericArgs, description, node,
+ description->GenericParams.NestingDepth,
+ Dem);
}
// Build a demangled type tree for a type.
diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp
index d5875ac..fbfad19 100644
--- a/stdlib/public/runtime/Metadata.cpp
+++ b/stdlib/public/runtime/Metadata.cpp
@@ -221,8 +221,7 @@
pattern->AddressPoint;
auto patternMetadata = reinterpret_cast<const ValueMetadata*>(patternBytes);
metadata->Description = patternMetadata->Description.get();
- metadata->Parent = patternMetadata->Parent;
-
+
return metadata;
}
@@ -1329,13 +1328,6 @@
auto &description = ancestor->getDescription();
auto &genericParams = description->GenericParams;
- // Copy the parent type.
- if (genericParams.Flags.hasParent()) {
- memcpy(classWords + genericParams.Offset - 1,
- superWords + genericParams.Offset - 1,
- sizeof(uintptr_t));
- }
-
// Copy the generic requirements.
if (genericParams.hasGenericRequirements()) {
unsigned numParamWords = genericParams.NumGenericRequirements;
diff --git a/stdlib/public/stubs/LibcShims.cpp b/stdlib/public/stubs/LibcShims.cpp
index 6f558e5..86cc09a 100644
--- a/stdlib/public/stubs/LibcShims.cpp
+++ b/stdlib/public/stubs/LibcShims.cpp
@@ -109,7 +109,7 @@
void _swift_stdlib_destroyTLS(void *);
static void
-#if defined(_M_X86)
+#if defined(_M_IX86)
__stdcall
#endif
_swift_stdlib_destroyTLS_CCAdjustmentThunk(void *ptr) {
diff --git a/stdlib/public/stubs/SwiftNativeNSXXXBase.mm.gyb b/stdlib/public/stubs/SwiftNativeNSXXXBase.mm.gyb
index d0c2675..ece3bbc 100644
--- a/stdlib/public/stubs/SwiftNativeNSXXXBase.mm.gyb
+++ b/stdlib/public/stubs/SwiftNativeNSXXXBase.mm.gyb
@@ -24,9 +24,9 @@
// To trick Swift into using its fast refcounting and allocation
// directly (rather than going through objc_msgSend to arrive at the
// implementations defined here), we define subclasses on the Swift
-// side but hide the inheritance relationship from the Swift compiler
-// and only establish it dynamically, in the '+ load' method of each
-// class defined here.
+// side but we establish the inheritance relationship with
+// the special @_swift_native_objc_runtime_base attribute rather
+// than directly subclassing the classes defined here.
//
//===----------------------------------------------------------------------===//
@@ -72,6 +72,10 @@
- (id)autorelease {
return _objc_rootAutorelease(self);
}
+- (NSUInteger)retainCount {
+ auto SELF = reinterpret_cast<HeapObject *>(self);
+ return swift_retainCount(SELF);
+}
- (BOOL)_tryRetain {
auto SELF = reinterpret_cast<HeapObject *>(self);
diff --git a/test/ClangImporter/Inputs/custom-modules/SubclassExistentialsExtra.h b/test/ClangImporter/Inputs/custom-modules/SubclassExistentialsExtra.h
new file mode 100644
index 0000000..0ff6e95
--- /dev/null
+++ b/test/ClangImporter/Inputs/custom-modules/SubclassExistentialsExtra.h
@@ -0,0 +1,12 @@
+@import Foundation;
+
+@interface SomeSpecificSubclass : NSObject
+@end
+
+typedef NSObject <NSCopying> CopyableNSObjectBase;
+typedef SomeSpecificSubclass <NSCopying> CopyableSpecificBase;
+
+@interface CompositionSubObject : CopyableNSObjectBase
+@end
+@interface CompositionSubSpecific : CopyableSpecificBase
+@end
diff --git a/test/ClangImporter/Inputs/custom-modules/module.map b/test/ClangImporter/Inputs/custom-modules/module.map
index 9177b5c..9b5c8c4 100644
--- a/test/ClangImporter/Inputs/custom-modules/module.map
+++ b/test/ClangImporter/Inputs/custom-modules/module.map
@@ -140,6 +140,11 @@
export *
}
+module SubclassExistentialsExtra {
+ header "SubclassExistentialsExtra.h"
+ export *
+}
+
module SwiftPrivateAttr {
header "SwiftPrivateAttr.h"
}
diff --git a/test/ClangImporter/subclass_existentials.swift b/test/ClangImporter/subclass_existentials.swift
index 690d30c..15a085f 100644
--- a/test/ClangImporter/subclass_existentials.swift
+++ b/test/ClangImporter/subclass_existentials.swift
@@ -1,8 +1,9 @@
-// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -verify -o - -primary-file %s -swift-version 4
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -verify -o - -primary-file %s -swift-version 4 -I %S/Inputs/custom-modules/
// REQUIRES: objc_interop
import Foundation
+import SubclassExistentialsExtra
class SwiftLaundryService : NSLaundry {
var g: (Garment & Coat)? = nil
@@ -39,3 +40,12 @@
// Make sure the method lookup is not ambiguous
_ = Coat.fashionStatement.wear()
+
+
+func testInheritanceFromComposition(_ object: CompositionSubObject, _ specific: CompositionSubSpecific) {
+ let _: NSObject = object
+ let _: NSCopying = object
+
+ let _: SomeSpecificSubclass = specific
+ let _: NSCopying = specific
+}
diff --git a/test/ClangImporter/subclass_existentials_swift3.swift b/test/ClangImporter/subclass_existentials_swift3.swift
index 7b1c955..4e24b33 100644
--- a/test/ClangImporter/subclass_existentials_swift3.swift
+++ b/test/ClangImporter/subclass_existentials_swift3.swift
@@ -1,8 +1,9 @@
-// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -verify -o - -primary-file %s -swift-version 3
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -verify -o - -primary-file %s -swift-version 3 -I %S/Inputs/custom-modules/
// REQUIRES: objc_interop
import Foundation
+import SubclassExistentialsExtra
// FIXME: Consider better diagnostics here.
@@ -34,3 +35,11 @@
return g!
}
}
+
+func testInheritanceFromComposition(_ object: CompositionSubObject, _ specific: CompositionSubSpecific) {
+ let _: NSObject = object
+ let _: NSCopying = object
+
+ let _: SomeSpecificSubclass = specific
+ let _: NSCopying = specific
+}
diff --git a/test/Constraints/closures.swift b/test/Constraints/closures.swift
index 3c47f49..d19b9a2 100644
--- a/test/Constraints/closures.swift
+++ b/test/Constraints/closures.swift
@@ -603,3 +603,45 @@
// SR-1976/SR-3073: Inference of inout
func sr1976<T>(_ closure: (inout T) -> Void) {}
sr1976({ $0 += 2 }) // ok
+
+// rdar://problem/33429010
+
+struct I_33429010 : IteratorProtocol {
+ func next() -> Int? {
+ fatalError()
+ }
+}
+
+extension Sequence {
+ public func rdar33429010<Result>(into initialResult: Result,
+ _ nextPartialResult: (_ partialResult: inout Result, Iterator.Element) throws -> ()
+ ) rethrows -> Result {
+ return initialResult
+ }
+}
+
+extension Int {
+ public mutating func rdar33429010_incr(_ inc: Int) {
+ self += inc
+ }
+}
+
+func rdar33429010_2() {
+ let iter = I_33429010()
+ var acc: Int = 0 // expected-warning {{}}
+ let _: Int = AnySequence { iter }.rdar33429010(into: acc, { $0 + $1 })
+ // expected-warning@-1 {{result of operator '+' is unused}}
+ let _: Int = AnySequence { iter }.rdar33429010(into: acc, { $0.rdar33429010_incr($1) })
+}
+
+class P_33429010 {
+ var name: String = "foo"
+}
+
+class C_33429010 : P_33429010 {
+}
+
+func rdar33429010_3() {
+ let arr = [C_33429010()]
+ let _ = arr.map({ ($0.name, $0 as P_33429010) }) // Ok
+}
diff --git a/test/Driver/profiling.swift b/test/Driver/profiling.swift
index ccf6aa0..0ef41d7 100644
--- a/test/Driver/profiling.swift
+++ b/test/Driver/profiling.swift
@@ -46,3 +46,13 @@
// LINUX: clang++{{"? }}
// LINUX: lib/swift/clang/lib/linux/libclang_rt.profile-x86_64.a
// LINUX: -u__llvm_profile_runtime
+
+// RUN: not %swiftc_driver -driver-print-jobs -profile-generate -profile-use=/dev/null %s 2>&1 | %FileCheck -check-prefix=MIX_GEN_USE %s
+// MIX_GEN_USE: conflicting options '-profile-generate' and '-profile-use'
+
+// RUN: not %swiftc_driver -driver-print-jobs -profile-use=%t.does_not_exist %s 2>&1 | %FileCheck -check-prefix=USE_MISSING_FILE %s
+// USE_MISSING_FILE: no profdata file exists at '{{[^']+}}.does_not_exist'
+
+// RUN: %swiftc_driver -driver-print-jobs -profile-use=/dev/null %s | %FileCheck -check-prefix=USE_DEVNULL %s
+// USE_DEVNULL: swift
+// USE_DEVNULL: -profile-use=/dev/null
diff --git a/test/Generics/requirement_inference.swift b/test/Generics/requirement_inference.swift
index ac124ae..658e1e5 100644
--- a/test/Generics/requirement_inference.swift
+++ b/test/Generics/requirement_inference.swift
@@ -76,8 +76,6 @@
// CHECK-NEXT: τ_0_0 : Canidae
func inferSuperclassRequirement1<T : Carnivora>(
_ v: V<T>) {}
-// expected-warning@-2{{redundant superclass constraint 'T' : 'Carnivora'}}
-// expected-note@-2{{superclass constraint 'T' : 'Canidae' inferred from type here}}
// CHECK-LABEL: .inferSuperclassRequirement2@
// CHECK-NEXT: Requirements:
@@ -307,8 +305,8 @@
}
struct X22<T, U> {
- func g<V>(_: V) where T: P20, // expected-warning{{redundant conformance constraint 'T': 'P20'}}
- U == X20<T> { } // expected-note{{conformance constraint 'T': 'P20' inferred from type here}}
+ func g<V>(_: V) where T: P20,
+ U == X20<T> { }
}
// CHECK: Generic signature: <Self where Self : P22>
@@ -330,8 +328,8 @@
// CHECK-NEXT: Canonical requirement signature: <τ_0_0 where τ_0_0.B : P20, τ_0_0.A == X20<τ_0_0.B>>
protocol P23 {
associatedtype A
- associatedtype B: P20 // expected-warning{{redundant conformance constraint 'Self.B': 'P20'}}
- where A == X20<B> // expected-note{{conformance constraint 'Self.B': 'P20' inferred from type here}}
+ associatedtype B: P20
+ where A == X20<B>
}
protocol P24 {
diff --git a/test/Generics/same_type_constraints.swift b/test/Generics/same_type_constraints.swift
index c30e592..381edb1 100644
--- a/test/Generics/same_type_constraints.swift
+++ b/test/Generics/same_type_constraints.swift
@@ -363,8 +363,8 @@
struct X11<T: P10> where T.A == T.B { }
-func intracomponentInferred<T>(_: X11<T>) // expected-note{{previous same-type constraint 'T.A' == 'T.B' inferred from type here}}
- where T.A == T.B { } // expected-warning{{redundant same-type constraint 'T.A' == 'T.B'}}
+func intracomponentInferred<T>(_: X11<T>)
+ where T.A == T.B { }
// Suppress redundant same-type constraint warnings from result types.
struct StructTakingP1<T: P1> { }
diff --git a/test/IDE/structure.swift b/test/IDE/structure.swift
index 336610d..4274fd2 100644
--- a/test/IDE/structure.swift
+++ b/test/IDE/structure.swift
@@ -232,3 +232,21 @@
a.b(c: d?.e?.f, g: h)
// CHECK: <call><name>a.b</name>(<arg><name>c</name>: d?.e?.f</arg>, <arg><name>g</name>: h</arg>)</call>
+
+struct Tuples {
+ var foo: (Int, String) {
+ return (1, "test")
+ // CHECK: <tuple>(<elem-expr>1</elem-expr>, <elem-expr>"test"</elem-expr>)</tuple>
+ }
+
+ func foo2() {
+ foo3(x: (1, 20))
+ // CHECK: <call><name>foo3</name>(<arg><name>x</name>: <tuple>(<elem-expr>1</elem-expr>, <elem-expr>20</elem-expr>)</tuple></arg>)</call>
+ let y = (x, foo4(a: 0))
+ // CHECK: <lvar>let <name>y</name> = <tuple>(<elem-expr>x</elem-expr>, <elem-expr><call><name>foo4</name>(<arg><name>a</name>: 0</arg>)</call></elem-expr>)</tuple></lvar>
+
+ let z = (name1: 1, name2: 2)
+ // CHECK: <lvar>let <name>z</name> = <tuple>(name1: <elem-expr>1</elem-expr>, name2: <elem-expr>2</elem-expr>)</tuple></lvar>
+ }
+}
+
diff --git a/test/IRGen/access_markers.sil b/test/IRGen/access_markers.sil
index 068e44d..f6794ac 100644
--- a/test/IRGen/access_markers.sil
+++ b/test/IRGen/access_markers.sil
@@ -33,7 +33,7 @@
// CHECK-NEXT: call void @swift_endAccess([[BUFFER]]* [[SCRATCH1]])
// CHECK-NEXT: [[T0:%.*]] = bitcast [[BUFFER]]* [[SCRATCH1]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 {{.*}}, i8* [[T0]])
- %4 = end_access %3 : $*Int
+ end_access %3 : $*Int
// CHECK-NEXT: [[T0:%.*]] = bitcast [[BUFFER]]* [[SCRATCH2]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 {{.*}}, i8* [[T0]])
@@ -44,7 +44,7 @@
// CHECK-NEXT: call void @swift_endAccess([[BUFFER]]* [[SCRATCH2]])
// CHECK-NEXT: [[T0:%.*]] = bitcast [[BUFFER]]* [[SCRATCH2]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 {{.*}}, i8* [[T0]])
- %6 = end_access %5 : $*Int
+ end_access %5 : $*Int
%20 = tuple ()
return %20 : $()
@@ -61,17 +61,17 @@
// CHECK-NEXT: [[T1:%.*]] = bitcast [[INT]]* [[PROPERTY]] to i8*
// CHECK-NEXT: call void @swift_beginAccess(i8* [[T1]], [[BUFFER]]* [[SCRATCH]], [[SIZE]] 1, i8* null)
- %3 = begin_unpaired_access [modify] [dynamic] %2 : $*Int, %1 : $*Builtin.UnsafeValueBuffer
+ begin_unpaired_access [modify] [dynamic] %2 : $*Int, %1 : $*Builtin.UnsafeValueBuffer
// CHECK-NEXT: call void @swift_endAccess([[BUFFER]]* [[SCRATCH]])
- %4 = end_unpaired_access [dynamic] %1 : $*Builtin.UnsafeValueBuffer
+ end_unpaired_access [dynamic] %1 : $*Builtin.UnsafeValueBuffer
// CHECK-NEXT: [[T1:%.*]] = bitcast [[INT]]* [[PROPERTY]] to i8*
// CHECK-NEXT: call void @swift_beginAccess(i8* [[T1]], [[BUFFER]]* [[SCRATCH]], [[SIZE]] 0, i8* null)
- %5 = begin_unpaired_access [read] [dynamic] %2 : $*Int, %1 : $*Builtin.UnsafeValueBuffer
+ begin_unpaired_access [read] [dynamic] %2 : $*Int, %1 : $*Builtin.UnsafeValueBuffer
// CHECK-NEXT: call void @swift_endAccess([[BUFFER]]* [[SCRATCH]])
- %6 = end_unpaired_access [dynamic] %1 : $*Builtin.UnsafeValueBuffer
+ end_unpaired_access [dynamic] %1 : $*Builtin.UnsafeValueBuffer
dealloc_stack %1 : $*Builtin.UnsafeValueBuffer
@@ -88,18 +88,18 @@
// CHECK-NEXT: [[T1:%.*]] = bitcast [[INT]]* [[PROPERTY]] to i8*
// CHECK-NEXT: [[PC:%.*]] = call i8* @llvm.returnaddress(i32 0)
// CHECK-NEXT: call void @swift_beginAccess(i8* [[T1]], [[BUFFER]]* [[SCRATCH:%1]], [[SIZE]] 1, i8* [[PC]])
- %3 = begin_unpaired_access [modify] [dynamic] %2 : $*Int, %1 : $*Builtin.UnsafeValueBuffer
+ begin_unpaired_access [modify] [dynamic] %2 : $*Int, %1 : $*Builtin.UnsafeValueBuffer
// CHECK-NEXT: call void @swift_endAccess([[BUFFER]]* [[SCRATCH]])
- %4 = end_unpaired_access [dynamic] %1 : $*Builtin.UnsafeValueBuffer
+ end_unpaired_access [dynamic] %1 : $*Builtin.UnsafeValueBuffer
// CHECK-NEXT: [[T1:%.*]] = bitcast [[INT]]* [[PROPERTY]] to i8*
// CHECK-NEXT: [[PC:%.*]] = call i8* @llvm.returnaddress(i32 0)
// CHECK-NEXT: call void @swift_beginAccess(i8* [[T1]], [[BUFFER]]* [[SCRATCH]], [[SIZE]] 0, i8* [[PC]])
- %5 = begin_unpaired_access [read] [dynamic] %2 : $*Int, %1 : $*Builtin.UnsafeValueBuffer
+ begin_unpaired_access [read] [dynamic] %2 : $*Int, %1 : $*Builtin.UnsafeValueBuffer
// CHECK-NEXT: call void @swift_endAccess([[BUFFER]]* [[SCRATCH]])
- %6 = end_unpaired_access [dynamic] %1 : $*Builtin.UnsafeValueBuffer
+ end_unpaired_access [dynamic] %1 : $*Builtin.UnsafeValueBuffer
%20 = tuple ()
return %20 : $()
@@ -118,13 +118,13 @@
%3 = begin_access [modify] [dynamic] %2 : $*()
%write_fn = function_ref @writeEmptyTuple : $@convention(thin) (@inout ()) -> ()
apply %write_fn(%3) : $@convention(thin) (@inout ()) -> ()
- %4 = end_access %3 : $*()
+ end_access %3 : $*()
// CHECK-NEXT: call {{.*}}void @readEmptyTuple(%swift.opaque* noalias nocapture undef)
%5 = begin_access [read] [dynamic] %2 : $*()
%read_fn = function_ref @readEmptyTuple : $@convention(thin) (@in_guaranteed ()) -> ()
apply %read_fn(%5) : $@convention(thin) (@in_guaranteed ()) -> ()
- %6 = end_access %5 : $*()
+ end_access %5 : $*()
// CHECK-NEXT: ret void
%20 = tuple ()
diff --git a/test/IRGen/associated_type_witness.swift b/test/IRGen/associated_type_witness.swift
index 47e64cf..5b1f25e 100644
--- a/test/IRGen/associated_type_witness.swift
+++ b/test/IRGen/associated_type_witness.swift
@@ -51,21 +51,21 @@
// Associated type metadata access function for Fulfilled.Assoc.
// CHECK-LABEL: define internal %swift.type* @_T023associated_type_witness9FulfilledVyxGAA8AssockedA2A1PRzAA1QRzl5AssocWt(%swift.type* %"Fulfilled<T>", i8** %"Fulfilled<T>.Assocked")
// CHECK: [[T0:%.*]] = bitcast %swift.type* %"Fulfilled<T>" to %swift.type**
-// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], i64 3
+// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], i64 2
// CHECK-NEXT: [[T2:%.*]] = load %swift.type*, %swift.type** [[T1]], align 8, !invariant.load
// CHECK-NEXT: ret %swift.type* [[T2]]
// Associated type witness table access function for Fulfilled.Assoc : P.
// CHECK-LABEL: define internal i8** @_T023associated_type_witness9FulfilledVyxGAA8AssockedA2A1PRzAA1QRzl5AssocAaFPWT(%swift.type* %"Fulfilled<T>.Assoc", %swift.type* %"Fulfilled<T>", i8** %"Fulfilled<T>.Assocked")
// CHECK: [[T0:%.*]] = bitcast %swift.type* %"Fulfilled<T>" to i8***
-// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]], i64 4
+// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]], i64 3
// CHECK-NEXT: [[T2:%.*]] = load i8**, i8*** [[T1]], align 8, !invariant.load
// CHECK-NEXT: ret i8** [[T2]]
// Associated type witness table access function for Fulfilled.Assoc : Q.
// CHECK-LABEL: define internal i8** @_T023associated_type_witness9FulfilledVyxGAA8AssockedA2A1PRzAA1QRzl5AssocAaGPWT(%swift.type* %"Fulfilled<T>.Assoc", %swift.type* %"Fulfilled<T>", i8** %"Fulfilled<T>.Assocked")
// CHECK: [[T0:%.*]] = bitcast %swift.type* %"Fulfilled<T>" to i8***
-// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]], i64 5
+// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]], i64 4
// CHECK-NEXT: [[T2:%.*]] = load i8**, i8*** [[T1]], align 8, !invariant.load
// CHECK-NEXT: ret i8** [[T2]]
@@ -108,10 +108,10 @@
// CHECK-NEXT: ret %swift.type* [[T0]]
// CHECK: fetch:
// CHECK-NEXT: [[T0:%.*]] = bitcast %swift.type* %"Computed<T, U>" to %swift.type**
-// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], i64 3
+// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], i64 2
// CHECK-NEXT: [[T:%.*]] = load %swift.type*, %swift.type** [[T1]], align 8, !invariant.load
// CHECK: [[T0:%.*]] = bitcast %swift.type* %"Computed<T, U>" to %swift.type**
-// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], i64 4
+// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], i64 3
// CHECK-NEXT: [[U:%.*]] = load %swift.type*, %swift.type** [[T1]], align 8, !invariant.load
// CHECK-NEXT: [[FETCH_RESULT]] = call %swift.type* @_T023associated_type_witness4PairVMa(%swift.type* [[T]], %swift.type* [[U]])
// CHECK-NEXT: store atomic %swift.type* [[FETCH_RESULT]], %swift.type** [[CACHE]] release, align 8
diff --git a/test/IRGen/class_bounded_generics.swift b/test/IRGen/class_bounded_generics.swift
index 184f8ae..573a13b 100644
--- a/test/IRGen/class_bounded_generics.swift
+++ b/test/IRGen/class_bounded_generics.swift
@@ -1,4 +1,4 @@
-// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -emit-ir -primary-file %s -disable-objc-attr-requires-foundation-module | %FileCheck %s
+// RUN: %target-swift-frontend -emit-ir -primary-file %s -disable-objc-attr-requires-foundation-module | %FileCheck %s
// REQUIRES: CPU=x86_64
// XFAIL: linux
@@ -9,7 +9,7 @@
protocol ClassBound2 : class {
func classBoundMethod2()
}
-protocol ClassBoundBinary : class, ClassBound {
+protocol ClassBoundBinary : ClassBound {
func classBoundBinaryMethod(_ x: Self)
}
@objc protocol ObjCClassBound {
@@ -214,7 +214,7 @@
}
// CHECK-LABEL: define hidden swiftcc { i64, %objc_object*, i64 } @_T022class_bounded_generics0A28_generic_field_struct_fields{{[_0-9a-zA-Z]*}}F(i64, %objc_object*, i64, %swift.type* %T, i8** %T.ClassBound)
-func class_generic_field_struct_fields<T : ClassBound>
+func class_generic_field_struct_fields<T>
(_ x:ClassGenericFieldStruct<T>) -> (Int, T, Int) {
return (x.x, x.y, x.z)
}
@@ -226,7 +226,7 @@
}
// CHECK-LABEL: define hidden swiftcc { i64, %objc_object*, i64 } @_T022class_bounded_generics0a15_generic_field_A7_fields{{[_0-9a-zA-Z]*}}F(%T22class_bounded_generics017ClassGenericFieldD0C*)
-func class_generic_field_class_fields<T : ClassBound>
+func class_generic_field_class_fields<T>
(_ x:ClassGenericFieldClass<T>) -> (Int, T, Int) {
return (x.x, x.y, x.z)
// CHECK: getelementptr inbounds %T22class_bounded_generics017ClassGenericFieldD0C, %T22class_bounded_generics017ClassGenericFieldD0C* %0, i32 0, i32 1
@@ -273,3 +273,36 @@
s = S.init()
}
}
+
+// CHECK-LABEL: define hidden swiftcc void @_T022class_bounded_generics14takes_metatypeyxmlF(%swift.type*, %swift.type* %T)
+func takes_metatype<T>(_: T.Type) {}
+
+// CHECK-LABEL: define hidden swiftcc void @_T022class_bounded_generics023archetype_with_generic_A11_constraintyx1t_tAA1ACyq_GRbzr0_lF(%T22class_bounded_generics1AC.2*, %swift.type* %T)
+// CHECK: [[ISA_ADDR:%.*]] = bitcast %T22class_bounded_generics1AC.2* %0 to %swift.type**
+// CHECK-NEXT: [[ISA:%.*]] = load %swift.type*, %swift.type** [[ISA_ADDR]]
+// CHECK-NEXT: call swiftcc void @_T022class_bounded_generics14takes_metatypeyxmlF(%swift.type* %T, %swift.type* %T)
+// CHECK-NEXT: [[ISA_PTR:%.*]] = bitcast %swift.type* [[ISA]] to %swift.type**
+// CHECK-NEXT: [[U_ADDR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[ISA_PTR]], i64 10
+// CHECK-NEXT: [[U:%.*]] = load %swift.type*, %swift.type** [[U_ADDR]]
+// CHECK-NEXT: call swiftcc void @_T022class_bounded_generics14takes_metatypeyxmlF(%swift.type* %U, %swift.type* %U)
+// CHECK: ret void
+
+func archetype_with_generic_class_constraint<T, U>(t: T) where T : A<U> {
+ takes_metatype(T.self)
+ takes_metatype(U.self)
+}
+
+// CHECK-LABEL: define hidden swiftcc void @_T022class_bounded_generics029calls_archetype_with_generic_A11_constraintyAA1ACyxG1a_tlF(%T22class_bounded_generics1AC*) #0 {
+// CHECK: [[ISA_ADDR:%.*]] = getelementptr inbounds %T22class_bounded_generics1AC, %T22class_bounded_generics1AC* %0, i32 0, i32 0, i32 0
+// CHECK-NEXT: [[ISA:%.*]] = load %swift.type*, %swift.type** [[ISA_ADDR]]
+// CHECK: [[SELF:%.*]] = bitcast %T22class_bounded_generics1AC* %0 to %T22class_bounded_generics1AC.2*
+// CHECK-NEXT: [[ISA_PTR:%.*]] = bitcast %swift.type* [[ISA]] to %swift.type**
+// CHECK-NEXT: [[T_ADDR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[ISA_PTR]], i64 10
+// CHECK-NEXT: [[T:%.*]] = load %swift.type*, %swift.type** [[T_ADDR]]
+// CHECK-NEXT: [[A_OF_T:%.*]] = call %swift.type* @_T022class_bounded_generics1ACMa(%swift.type* [[T]])
+// CHECK-NEXT: call swiftcc void @_T022class_bounded_generics023archetype_with_generic_A11_constraintyx1t_tAA1ACyq_GRbzr0_lF(%T22class_bounded_generics1AC.2* [[SELF]], %swift.type* [[A_OF_T]])
+// CHECK: ret void
+
+func calls_archetype_with_generic_class_constraint<T>(a: A<T>) {
+ archetype_with_generic_class_constraint(t: a)
+}
diff --git a/test/IRGen/enum.sil b/test/IRGen/enum.sil
index 6985832..e6d1f54 100644
--- a/test/IRGen/enum.sil
+++ b/test/IRGen/enum.sil
@@ -107,75 +107,86 @@
// CHECK: [[DYNAMICSINGLETON_FIELD_NAMES:@.*]] = private constant [7 x i8] c"value\00\00"
// CHECK: [[DYNAMICSINGLETON_NAME:@.*]] = private constant [25 x i8] c"4enum16DynamicSingletonO\00"
// CHECK: @_T04enum16DynamicSingletonOMn = hidden constant <{ {{.*}} i32 }> <{
-// CHECK: [25 x i8]* [[DYNAMICSINGLETON_NAME]]
+// CHECK-SAME: [25 x i8]* [[DYNAMICSINGLETON_NAME]]
// -- One payload
-// CHECK: i32 1,
+// CHECK-SAME: i32 1,
// -- No empty cases
-// CHECK: i32 0,
+// CHECK-SAME: i32 0,
// -- Case names
-// CHECK: [[DYNAMICSINGLETON_FIELD_NAMES]]
+// CHECK-SAME: [[DYNAMICSINGLETON_FIELD_NAMES]]
// -- Case type accessor
-// CHECK: @get_field_types_DynamicSingleton
+// CHECK-SAME: @get_field_types_DynamicSingleton
// -- generic parameter vector offset
-// CHECK: i32 3,
+// CHECK-SAME: i32 2,
// -- generic parameter vector length; witness table counts
-// CHECK: i32 1, i32 0
-// CHECK: }>
+// CHECK-SAME: i32 1, i32 1
+// -- nesting depth
+// CHECK-SAME: i16 1
+// -- flags
+// CHECK-SAME: i16 0
+// -- generic parameters at depth 0
+// CHECK-SAME: i32 1
+// CHECK-SAME: }>
// CHECK: @_T04enum16DynamicSingletonOMP = internal global <{ {{.*}}, [16 x i8*] }> <{
-// CHECK: %swift.type* (%swift.type_pattern*, i8**)* @create_generic_metadata_DynamicSingleton
-// CHECK: @_T04enum16DynamicSingletonOMn
-// CHECK: i8* null
-// CHECK: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_T04enum16DynamicSingletonOwxs to i8*)
-// CHECK: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_T04enum16DynamicSingletonOwxg to i8*)
+// CHECK-SAME: %swift.type* (%swift.type_pattern*, i8**)* @create_generic_metadata_DynamicSingleton
+// CHECK-SAME: @_T04enum16DynamicSingletonOMn
+// CHECK-SAME: i8* null
+// CHECK-SAME: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_T04enum16DynamicSingletonOwxs to i8*)
+// CHECK-SAME: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_T04enum16DynamicSingletonOwxg to i8*)
// -- No-payload enums have extra inhabitants in
// their value witness table.
// CHECK: @_T04enum10NoPayloadsOWV = internal constant [16 x i8*] [
// -- ...
// -- size
-// CHECK: i8* inttoptr ([[WORD:i32|i64]] 1 to i8*),
+// CHECK-SAME: i8* inttoptr ([[WORD:i32|i64]] 1 to i8*),
// -- flags 0x24_0000 - alignment 1, has extra inhabitants and enum witnesses
-// CHECK: i8* inttoptr ([[WORD]] 2359296 to i8*),
+// CHECK-SAME: i8* inttoptr ([[WORD]] 2359296 to i8*),
// -- stride
-// CHECK: i8* inttoptr ([[WORD]] 1 to i8*),
+// CHECK-SAME: i8* inttoptr ([[WORD]] 1 to i8*),
// -- num extra inhabitants (256 - 3 valid states)
-// CHECK: i8* inttoptr ([[WORD]] 253 to i8*)
+// CHECK-SAME: i8* inttoptr ([[WORD]] 253 to i8*)
// -- storeExtraInhabitant
-// CHECK: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_T04enum10NoPayloadsOwxs to i8*)
+// CHECK-SAME: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_T04enum10NoPayloadsOwxs to i8*)
// -- getExtraInhabitantIndex
-// CHECK: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_T04enum10NoPayloadsOwxg to i8*)
-// CHECK: ]
+// CHECK-SAME: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_T04enum10NoPayloadsOwxg to i8*)
+// CHECK-SAME: ]
// -- Single-payload enums take unused extra inhabitants from their payload
// as their own.
// CHECK: @_T04enum19SinglePayloadNestedOWV = internal constant [16 x i8*] [
// -- ...
// -- size
-// CHECK: i8* inttoptr ([[WORD]] 1 to i8*),
+// CHECK-SAME: i8* inttoptr ([[WORD]] 1 to i8*),
// -- flags 0x4_0000 - alignment 1, has extra inhabitants
-// CHECK: i8* inttoptr ([[WORD]] 2359296 to i8*),
+// CHECK-SAME: i8* inttoptr ([[WORD]] 2359296 to i8*),
// -- stride
-// CHECK: i8* inttoptr ([[WORD]] 1 to i8*),
+// CHECK-SAME: i8* inttoptr ([[WORD]] 1 to i8*),
// -- num extra inhabitants (253 from payload - 3 empty cases)
-// CHECK: i8* inttoptr ([[WORD]] 250 to i8*)
+// CHECK-SAME: i8* inttoptr ([[WORD]] 250 to i8*)
// -- storeExtraInhabitant
-// CHECK: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_T04enum19SinglePayloadNestedOwxs to i8*)
+// CHECK-SAME: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_T04enum19SinglePayloadNestedOwxs to i8*)
// -- getExtraInhabitantIndex
-// CHECK: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_T04enum19SinglePayloadNestedOwxg to i8*)
-// CHECK: ]
+// CHECK-SAME: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_T04enum19SinglePayloadNestedOwxg to i8*)
+// CHECK-SAME: ]
// CHECK: @_T04enum20DynamicSinglePayloadOMP = internal global <{ {{.*}}, [16 x i8*] }> <{
-// CHECK: %swift.type* (%swift.type_pattern*, i8**)* @create_generic_metadata_DynamicSinglePayload
-// CHECK: i8* null
-// CHECK: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_T04enum20DynamicSinglePayloadOwxs to i8*)
-// CHECK: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_T04enum20DynamicSinglePayloadOwxg to i8*)
+// CHECK-SAME: %swift.type* (%swift.type_pattern*, i8**)* @create_generic_metadata_DynamicSinglePayload
+// CHECK-SAME: i8* null
+// CHECK-SAME: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_T04enum20DynamicSinglePayloadOwxs to i8*)
+// CHECK-SAME: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_T04enum20DynamicSinglePayloadOwxg to i8*)
// CHECK: @_T04enum18MultiPayloadNestedOWV = internal constant [16 x i8*] [
-// CHECK: i8* inttoptr ([[WORD]] 9 to i8*),
-// CHECK: i8* inttoptr ([[WORD]] 16 to i8*)
-// CHECK: ]
+// -- size
+// CHECK-32-SAME: i8* inttoptr ([[WORD]] 5 to i8*),
+// CHECK-64-SAME: i8* inttoptr ([[WORD]] 9 to i8*),
+// -- flags 0x250003 - alignment 4
+// CHECK-32-SAME: i8* inttoptr ([[WORD]] {{2424835|2097155}} to i8*)
+// -- flags 0x200007 - alignment 8
+// CHECK-64-SAME: i8* inttoptr ([[WORD]] 2097159 to i8*)
+// CHECK-SAME: ]
enum Empty {}
@@ -2660,10 +2671,10 @@
// CHECK: [[T:%T]] = load %swift.type*, %swift.type** [[T0]],
// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericValueMetadata(%swift.type_pattern* %0, i8** %1)
// CHECK: [[METADATA_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i8**
-// CHECK: [[T1:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 3
+// CHECK: [[T1:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 2
// CHECK: [[T0:%.*]] = bitcast %swift.type* [[T]] to i8*
// CHECK: store i8* [[T0]], i8** [[T1]]
-// CHECK: [[VWT:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 5
+// CHECK: [[VWT:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 4
// CHECK: [[T0:%.*]] = bitcast i8** [[VWT]] to i8*
// CHECK: [[T1:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 -1
// CHECK: store i8* [[T0]], i8** [[T1]]
diff --git a/test/IRGen/enum_resilience.swift b/test/IRGen/enum_resilience.swift
index e58ee04..f2f4ece 100644
--- a/test/IRGen/enum_resilience.swift
+++ b/test/IRGen/enum_resilience.swift
@@ -254,7 +254,7 @@
// CHECK-LABEL: define{{( protected)?}} swiftcc %swift.type* @_T014resilient_enum32ResilientMultiPayloadGenericEnumO0B11_resilienceE16getTypeParameterxmyF(%swift.type* %"ResilientMultiPayloadGenericEnum<T>", %swift.opaque* noalias nocapture swiftself)
// CHECK: [[METADATA:%.*]] = bitcast %swift.type* %"ResilientMultiPayloadGenericEnum<T>" to %swift.type**
-// CHECK-NEXT: [[T_ADDR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[METADATA]], [[INT]] 3
+// CHECK-NEXT: [[T_ADDR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[METADATA]], [[INT]] 2
// CHECK-NEXT: [[T:%.*]] = load %swift.type*, %swift.type** [[T_ADDR]]
public func getTypeParameter() -> T.Type {
return T.self
diff --git a/test/IRGen/enum_value_semantics.sil b/test/IRGen/enum_value_semantics.sil
index 734169d..1f1800c 100644
--- a/test/IRGen/enum_value_semantics.sil
+++ b/test/IRGen/enum_value_semantics.sil
@@ -119,7 +119,6 @@
// CHECK-SAME: i8** getelementptr inbounds ([16 x i8*], [16 x i8*]* @_T020enum_value_semantics20SinglePayloadTrivialOWV, i32 0, i32 0),
// CHECK-SAME: i64 2,
// CHECK-SAME: {{.*}}* @_T020enum_value_semantics20SinglePayloadTrivialOMn
-// CHECK-SAME: %swift.type* null
// CHECK-SAME: }>
@@ -150,13 +149,12 @@
// CHECK-SAME: i8** getelementptr inbounds ([16 x i8*], [16 x i8*]* @_T020enum_value_semantics23SinglePayloadNontrivialOWV, i32 0, i32 0),
// CHECK-SAME: i64 2,
// CHECK-SAME: {{.*}}* @_T020enum_value_semantics23SinglePayloadNontrivialOMn
-// CHECK-SAME: %swift.type* null
// CHECK-SAME: }>
// CHECK-LABEL: @_T020enum_value_semantics18GenericFixedLayoutOMP = internal global <{{[{].*\* [}]}}> <{
// CHECK: %swift.type* (%swift.type_pattern*, i8**)* @create_generic_metadata_GenericFixedLayout
-// CHECK: i32 48, i16 1, i16 8,
+// CHECK: i32 40, i16 1, i16 8,
// CHECK: [16 x i8*] zeroinitializer,
// CHECK: i8** getelementptr inbounds ([16 x i8*], [16 x i8*]* @_T020enum_value_semantics18GenericFixedLayoutOWV, i32 0, i32 0),
// CHECK: i64 2,
diff --git a/test/IRGen/field_type_vectors.sil b/test/IRGen/field_type_vectors.sil
index 9908a8c..e526e07 100644
--- a/test/IRGen/field_type_vectors.sil
+++ b/test/IRGen/field_type_vectors.sil
@@ -13,9 +13,9 @@
// CHECK-LABEL: @_T018field_type_vectors3BarVMn = hidden constant
// CHECK: %swift.type** (%swift.type*)* [[BAR_TYPES_ACCESSOR:@[A-Za-z0-9_]*]]
// CHECK-LABEL: @_T018field_type_vectors3BarVMP = internal global
-// -- There should be 5 words between the address point and the field type
+// -- There should be 4 words between the address point and the field type
// vector slot, with type %swift.type**
-// CHECK: i64, i64, i64, i64, %swift.type*, %swift.type**
+// CHECK: i64, i64, i64, %swift.type*, %swift.type**
struct Bar<T> {
var y: Int
}
@@ -23,9 +23,9 @@
// CHECK-LABEL: @_T018field_type_vectors3BasVMn = hidden constant
// CHECK: %swift.type** (%swift.type*)* [[BAS_TYPES_ACCESSOR:@[A-Za-z0-9_]*]]
// CHECK-LABEL: @_T018field_type_vectors3BasVMP = internal global
-// -- There should be 7 words between the address point and the field type
+// -- There should be 6 words between the address point and the field type
// vector slot, with type %swift.type**
-// CHECK: i64, i64, i64, i64, i64, %swift.type*, %swift.type*, %swift.type**
+// CHECK: i64, i64, i64, %swift.type*, %swift.type*, %swift.type**
struct Bas<T, U> {
var foo: Foo
var bar: Bar<T>
@@ -83,8 +83,8 @@
// CHECK: define{{( protected)?}} private %swift.type** [[BAR_TYPES_ACCESSOR]](%swift.type* %"Bar<T>")
// CHECK: [[T0:%.*]] = bitcast %swift.type* %"Bar<T>" to %swift.type***
-// -- 5 words between the address point and the slot
-// CHECK: [[SLOT:%.*]] = getelementptr inbounds %swift.type**, %swift.type*** [[T0]], i32 5
+// -- 4 words between the address point and the slot
+// CHECK: [[SLOT:%.*]] = getelementptr inbounds %swift.type**, %swift.type*** [[T0]], i32 4
// CHECK: load %swift.type**, %swift.type*** [[SLOT]], align 8
// CHECK: br
// CHECK-NOT: load %swift.type*,
@@ -93,8 +93,8 @@
// CHECK: define{{( protected)?}} private %swift.type** [[BAS_TYPES_ACCESSOR]](%swift.type* %"Bas<T, U>")
// CHECK: [[T0:%.*]] = bitcast %swift.type* %"Bas<T, U>" to %swift.type***
-// -- 7 words between the address point and the slot
-// CHECK: [[SLOT:%.*]] = getelementptr inbounds %swift.type**, %swift.type*** [[T0]], i32 7
+// -- 6 words between the address point and the slot
+// CHECK: [[SLOT:%.*]] = getelementptr inbounds %swift.type**, %swift.type*** [[T0]], i32 6
// CHECK: load %swift.type**, %swift.type*** [[SLOT]], align 8
// CHECK: br
// CHECK: store {{.*}} @_T018field_type_vectors3FooVMf
diff --git a/test/IRGen/foreign_types.sil b/test/IRGen/foreign_types.sil
index b52ce5b..ac6281d 100644
--- a/test/IRGen/foreign_types.sil
+++ b/test/IRGen/foreign_types.sil
@@ -4,14 +4,12 @@
import c_layout
// CHECK-LABEL: @_T0SC14HasNestedUnionV18__Unnamed_struct_sVN = linkonce_odr hidden global
-// CHECK-SAME: void (%swift.type*)* @initialize_metadata___Unnamed_struct_s,
// CHECK-SAME: i8* getelementptr inbounds
// CHECK-SAME: %swift.type* null,
-// CHECK-SAME: [[INT:i[0-9]+]] 1,
+// CHECK-SAME: [[INT:i[0-9]+]] 0,
// CHECK-SAME: @_T0SC14HasNestedUnionV18__Unnamed_struct_sVWV
// CHECK-SAME: [[INT]] 1,
// CHECK-SAME: [[INT]] sub ({{.*}}),
-// CHECK-SAME: %swift.type* null,
// CHECK-SAME: [[INT]] 0,
// CHECK-SAME: [[INT]] 4 }
@@ -22,10 +20,3 @@
%ret = tuple ()
return %ret : $()
}
-
-// CHECK-LABEL: define private void @initialize_metadata___Unnamed_struct_s
-// CHECK: [[PARENT:%.*]] = call %swift.type* @_T0SC14HasNestedUnionVMa()
-// CHECK-NEXT: [[T0:%.]] = bitcast %swift.type* %0 to %swift.type**
-// CHECK-NEXT: [[T1:%.]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], [[INT]] 2
-// CHECK-NEXT: store %swift.type* [[PARENT]], %swift.type** [[T1]],
-// CHECK-NEXT: ret void
diff --git a/test/IRGen/generic_classes.sil b/test/IRGen/generic_classes.sil
index e3f4c6f..62ab6c6 100644
--- a/test/IRGen/generic_classes.sil
+++ b/test/IRGen/generic_classes.sil
@@ -27,8 +27,12 @@
// CHECK-SAME: i32 10,
// -- generic parameter count, primary count
// CHECK-SAME: i32 1, i32 1,
+// -- nesting depth
+// CHECK-SAME: i16 1,
// -- flags -- has vtable
-// CHECK-SAME: i32 4,
+// CHECK-SAME: i16 4,
+// -- generic parameters at depth 0
+// CHECK-SAME: i32 1,
// -- vtable offset
// CHECK-SAME: i32 11,
// -- vtable size
diff --git a/test/IRGen/generic_structs.sil b/test/IRGen/generic_structs.sil
index 4d3ee50..1796e4b 100644
--- a/test/IRGen/generic_structs.sil
+++ b/test/IRGen/generic_structs.sil
@@ -12,39 +12,45 @@
// CHECK: [[SINGLEDYNAMIC_FIELDS:@.*]] = private constant [3 x i8] c"x\00\00"
// CHECK: @_T015generic_structs13SingleDynamicVMn = hidden constant <{ {{.*}} i32 }> <{
// -- name
-// CHECK: [34 x i8]* [[SINGLEDYNAMIC_NAME]]
+// CHECK-SAME: [34 x i8]* [[SINGLEDYNAMIC_NAME]]
// -- field count
-// CHECK: i32 1,
+// CHECK-SAME: i32 1,
// -- field offset vector offset
-// CHECK: i32 3,
+// CHECK-SAME: i32 2,
// -- field names
-// CHECK: [3 x i8]* [[SINGLEDYNAMIC_FIELDS]]
+// CHECK-SAME: [3 x i8]* [[SINGLEDYNAMIC_FIELDS]]
// -- generic metadata pattern, kind 1 (struct)
-// CHECK: i32 add ({{.*}}@_T015generic_structs13SingleDynamicVMP{{.*}}, i32 1)
+// CHECK-SAME: i32 add ({{.*}}@_T015generic_structs13SingleDynamicVMP{{.*}}, i32 1)
// -- generic parameter vector offset
-// CHECK: i32 4,
-// -- generic parameter count, primary counts; generic parameter witness counts
-// CHECK: i32 1, i32 1, i32 0
-// CHECK: }>
+// CHECK-SAME: i32 3,
+// -- generic parameter count, primary count
+// CHECK-SAME: i32 1, i32 1
+// -- nesting depth
+// CHECK-SAME: i16 1,
+// -- flags
+// CHECK-SAME: i16 0,
+// -- generic parameters at depth 0
+// CHECK-SAME: i32 1
+// CHECK-SAME: }>
// CHECK: @_T015generic_structs13SingleDynamicVMP = internal global <{ {{.*}} }> <{
// -- template header
-// CHECK: %swift.type* (%swift.type_pattern*, i8**)* @create_generic_metadata_SingleDynamic,
-// CHECK: i32 160, i16 1, i16 8, [{{[0-9]+}} x i8*] zeroinitializer,
+// CHECK-SAME: %swift.type* (%swift.type_pattern*, i8**)* @create_generic_metadata_SingleDynamic,
+// CHECK-SAME: i32 152, i16 1, i16 8, [{{[0-9]+}} x i8*] zeroinitializer,
// -- placeholder for vwtable pointer
-// CHECK: i8* null,
+// CHECK-SAME: i8* null,
// -- address point
-// CHECK: i64 1, {{.*}}* @_T015generic_structs13SingleDynamicVMn
+// CHECK-SAME: i64 1, {{.*}}* @_T015generic_structs13SingleDynamicVMn
// -- field offset vector; generic parameter vector
-// CHECK: i64 0, %swift.type* null,
+// CHECK-SAME: i64 0, %swift.type* null,
// -- tail-allocated vwtable pattern
-// CHECK: i8* bitcast (%swift.opaque* ([24 x i8]*, [24 x i8]*, %swift.type*)* @_T015generic_structs13SingleDynamicVwCP to i8*),
+// CHECK-SAME: i8* bitcast (%swift.opaque* ([24 x i8]*, [24 x i8]*, %swift.type*)* @_T015generic_structs13SingleDynamicVwCP to i8*),
// -- ...
// -- placeholder for size, flags, stride
-// CHECK: i8* null, i8* null, i8* null
+// CHECK-SAME: i8* null, i8* null, i8* null
// -- extra inhabitants
-// CHECK: i8* null,
-// CHECK: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_T015generic_structs13SingleDynamicVwxs to i8*),
-// CHECK: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_T015generic_structs13SingleDynamicVwxg to i8*)] }>
+// CHECK-SAME: i8* null,
+// CHECK-SAME: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_T015generic_structs13SingleDynamicVwxs to i8*),
+// CHECK-SAME: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_T015generic_structs13SingleDynamicVwxg to i8*)] }>
// CHECK-NOT: @_T015generic_structs13SingleDynamicVWV
// -- Nominal type descriptor for generic struct with protocol requirements
@@ -57,15 +63,21 @@
// -- field count
// CHECK-SAME: i32 2,
// -- field offset vector offset
-// CHECK-SAME: i32 3,
+// CHECK-SAME: i32 2,
// -- field names
// CHECK-SAME: [5 x i8]* [[DYNAMICWITHREQUIREMENTS_FIELDS]]
// -- generic metadata pattern
// CHECK-SAME: i32 add ({{.*}}@_T015generic_structs23DynamicWithRequirementsVMP{{.*}}, i32 1)
// -- generic parameter vector offset
-// CHECK-SAME: i32 5,
-// -- generic requirements count; generic arguments count; flags; generic parameter witness counts
-// CHECK-SAME: i32 4, i32 2, i32 0
+// CHECK-SAME: i32 4,
+// -- generic requirements count; generic arguments count
+// CHECK-SAME: i32 4, i32 2
+// -- nesting depth
+// CHECK-SAME: i16 1,
+// -- flags
+// CHECK-SAME: i16 0,
+// -- generic parameters at depth 0
+// CHECK-SAME: i32 2
// CHECK-SAME: }>
// CHECK: @_T015generic_structs23DynamicWithRequirementsVMP = internal global <{ {{.*}} }> <{
@@ -75,14 +87,14 @@
// -- Fixed-layout struct metadata contains fixed field offsets
// CHECK: @_T015generic_structs6IntishVMf = internal constant <{ {{.*}} i64 }> <{
-// CHECK: i64 0
-// CHECK: }>
+// CHECK-SAME: i64 0
+// CHECK-SAME: }>
// CHECK: @_T015generic_structs7CharethVMf = internal constant <{ {{.*}} i64 }> <{
-// CHECK: i64 0
-// CHECK: }>
+// CHECK-SAME: i64 0
+// CHECK-SAME: }>
// CHECK: @_T015generic_structs8StringlyVMf = internal constant <{ {{.*}} i64, i64, i64 }> <{
-// CHECK: i64 0, i64 8, i64 16
-// CHECK: }>
+// CHECK-SAME: i64 0, i64 8, i64 16
+// CHECK-SAME: }>
struct SingleDynamic<T> {
var x : T
@@ -134,7 +146,7 @@
%a = struct_element_addr %0 : $*ComplexDynamic<A, B>, #ComplexDynamic.a2
// CHECK: [[METADATA:%.*]] = bitcast %swift.type* {{%.*}} to i64*
- // CHECK: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds i64, i64* [[METADATA]], i64 3
+ // CHECK: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds i64, i64* [[METADATA]], i64 2
// CHECK: [[FIELD_OFFSET_ADDR:%.*]] = getelementptr inbounds i64, i64* [[FIELD_OFFSET_VECTOR]], i32 2
// CHECK: [[FIELD_OFFSET:%.*]] = load i64, i64* [[FIELD_OFFSET_ADDR]], align 8
// CHECK: [[BYTES:%.*]] = bitcast %T15generic_structs14ComplexDynamicV* %0 to i8*
@@ -143,7 +155,7 @@
%b = struct_element_addr %0 : $*ComplexDynamic<A, B>, #ComplexDynamic.b
// CHECK: [[METADATA:%.*]] = bitcast %swift.type* {{%.*}} to i64*
- // CHECK: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds i64, i64* [[METADATA]], i64 3
+ // CHECK: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds i64, i64* [[METADATA]], i64 2
// CHECK: [[FIELD_OFFSET_ADDR:%.*]] = getelementptr inbounds i64, i64* [[FIELD_OFFSET_VECTOR]], i32 3
// CHECK: [[FIELD_OFFSET:%.*]] = load i64, i64* [[FIELD_OFFSET_ADDR]], align 8
// CHECK: [[BYTES:%.*]] = bitcast %T15generic_structs14ComplexDynamicV* %0 to i8*
@@ -153,7 +165,7 @@
%c = struct_element_addr %5 : $*SingleDynamic<B>, #SingleDynamic.x
// CHECK: [[METADATA:%.*]] = bitcast %swift.type* {{%.*}} to i64*
- // CHECK: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds i64, i64* [[METADATA]], i64 3
+ // CHECK: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds i64, i64* [[METADATA]], i64 2
// CHECK: [[FIELD_OFFSET_ADDR:%.*]] = getelementptr inbounds i64, i64* [[FIELD_OFFSET_VECTOR]], i32 4
// CHECK: [[FIELD_OFFSET:%.*]] = load i64, i64* [[FIELD_OFFSET_ADDR]], align 8
// CHECK: [[BYTES:%.*]] = bitcast %T15generic_structs14ComplexDynamicV* %0 to i8*
@@ -204,17 +216,17 @@
// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericValueMetadata(%swift.type_pattern* %0, i8** %1)
// CHECK: [[SELF_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i8**
// Fill type argument.
-// CHECK: [[T1:%.*]] = getelementptr inbounds i8*, i8** [[SELF_ARRAY]], i32 4
+// CHECK: [[T1:%.*]] = getelementptr inbounds i8*, i8** [[SELF_ARRAY]], i32 3
// CHECK: [[T0:%.*]] = bitcast %swift.type* %T to i8*
// CHECK: store i8* [[T0]], i8** [[T1]], align 8
// Fill vwtable reference.
-// CHECK: [[VWTABLE_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[SELF_ARRAY]], i32 6
+// CHECK: [[VWTABLE_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[SELF_ARRAY]], i32 5
// CHECK: [[VWTABLE_VAL:%.*]] = bitcast i8** [[VWTABLE_ADDR]] to i8*
// CHECK: [[VWTABLE_SLOT_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[SELF_ARRAY]], i32 -1
// CHECK: store i8* [[VWTABLE_VAL]], i8** [[VWTABLE_SLOT_ADDR]], align 8
// Lay out fields.
// CHECK: [[T0:%.*]] = bitcast %swift.type* [[METADATA]] to i64*
-// CHECK: [[T1:%.*]] = getelementptr inbounds i64, i64* [[T0]], i64 3
+// CHECK: [[T1:%.*]] = getelementptr inbounds i64, i64* [[T0]], i64 2
// CHECK: [[T2:%.*]] = getelementptr inbounds i8**, i8*** [[TYPES:%.*]], i32 0
// CHECK: call void @swift_initStructMetadata_UniversalStrategy(i64 1, i8*** [[TYPES]], i64* [[T1]], i8** [[VWTABLE_ADDR]])
// CHECK: ret %swift.type* [[METADATA]]
diff --git a/test/IRGen/generic_vtable.swift b/test/IRGen/generic_vtable.swift
index 00c3cb8..bbba876 100644
--- a/test/IRGen/generic_vtable.swift
+++ b/test/IRGen/generic_vtable.swift
@@ -21,8 +21,12 @@
//// Nominal type descriptor for 'Base' does not have any method descriptors.
// CHECK-LABEL: @_T014generic_vtable4BaseCMn = {{(protected )?}}constant
+// -- nesting depth
+// CHECK-SAME: i16 1,
// -- flags: has vtable
-// CHECK-SAME: i32 4,
+// CHECK-SAME: i16 4,
+// -- generic parameters at depth 0
+// CHECK-SAME: i32 0,
// -- vtable offset
// CHECK-SAME: i32 10,
// -- vtable size
@@ -46,8 +50,12 @@
//// Nominal type descriptor for 'Derived' has method descriptors.
// CHECK-LABEL: @_T014generic_vtable7DerivedCMn = {{(protected )?}}constant
+// -- nesting depth
+// CHECK-SAME: i16 1,
// -- flags: has vtable
-// CHECK-SAME: i32 4,
+// CHECK-SAME: i16 4,
+// -- generic parameters at depth 0
+// CHECK-SAME: i32 1,
// -- vtable offset
// CHECK-SAME: i32 14,
// -- vtable size
@@ -76,8 +84,12 @@
//// Nominal type descriptor for 'Concrete' has method descriptors.
// CHECK-LABEL: @_T014generic_vtable8ConcreteCMn = {{(protected )?}}constant
+// -- nesting depth
+// CHECK-SAME: i16 1,
// -- flags: has vtable
-// CHECK-SAME: i32 4,
+// CHECK-SAME: i16 4,
+// -- generic parameters at depth 0
+// CHECK-SAME: i32 0,
// -- vtable offset
// CHECK-SAME: i32 15,
// -- vtable size
diff --git a/test/IRGen/keypaths.sil b/test/IRGen/keypaths.sil
index b7dbb0e..8e5d64e 100644
--- a/test/IRGen/keypaths.sil
+++ b/test/IRGen/keypaths.sil
@@ -200,8 +200,8 @@
// CHECK-64-SAME: [4 x i8] zeroinitializer,
// -- struct with runtime-resolved offset
// CHECK-SAME: <i32 0x1ffffffe>,
-// CHECK-32-SAME: i32 12 }>
-// CHECK-64-SAME: i32 24 }>
+// CHECK-32-SAME: i32 8 }>
+// CHECK-64-SAME: i32 16 }>
// -- %j: Gen<A>.y
// CHECK: [[KP_J:@keypath.*]] = private global <{ {{.*}} }> <{
@@ -213,8 +213,8 @@
// CHECK-64-SAME: [4 x i8] zeroinitializer,
// -- struct with runtime-resolved offset
// CHECK-SAME: <i32 0x1ffffffe>,
-// CHECK-32-SAME: i32 16 }>
-// CHECK-64-SAME: i32 32 }>
+// CHECK-32-SAME: i32 12 }>
+// CHECK-64-SAME: i32 24 }>
// CHECK-LABEL: define{{( protected)?}} swiftcc void @stored_property_fixed_offsets()
sil @stored_property_fixed_offsets : $@convention(thin) () -> () {
diff --git a/test/IRGen/nested_generics.swift b/test/IRGen/nested_generics.swift
new file mode 100644
index 0000000..13bf3e3
--- /dev/null
+++ b/test/IRGen/nested_generics.swift
@@ -0,0 +1,81 @@
+// RUN: %target-swift-frontend %s -emit-ir | %FileCheck %s --check-prefix=CHECK
+
+// REQUIRES: CPU=x86_64
+
+func blah<T>(_: T.Type) {}
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @_T015nested_generics13makeAMetadatayyF()
+public func makeAMetadata() {
+ blah(OuterGenericStruct<Int>.InnerGenericStruct<String>.self)
+ blah(OuterGenericStruct<Int>.InnerConcreteStruct.self)
+
+ blah(OuterGenericClass<Int>.InnerGenericClass<String>.self)
+ blah(OuterGenericClass<Int>.InnerConcreteClass.self)
+}
+
+// Type constructor for OuterGenericStruct<Int>.InnerGenericStruct<String>
+// CHECK-LABEL: define linkonce_odr hidden %swift.type* @_T015nested_generics18OuterGenericStructV05InnerdE0VySi_SSGMa()
+// CHECK: call %swift.type* @_T015nested_generics18OuterGenericStructV05InnerdE0VMa(%swift.type* @_T0SiN, %swift.type* @_T0SSN)
+// CHECK: ret %swift.type
+
+// Type constructor for OuterGenericStruct<T>.InnerGenericStruct<U>
+// CHECK-LABEL: define{{( protected)?}} %swift.type* @_T015nested_generics18OuterGenericStructV05InnerdE0VMa(%swift.type*, %swift.type*)
+
+// Type constructor for OuterGenericStruct<Int>.InnerConcreteStruct
+// CHECK-LABEL: define linkonce_odr hidden %swift.type* @_T015nested_generics18OuterGenericStructV013InnerConcreteE0VySi_GMa()
+// CHECK: call %swift.type* @_T015nested_generics18OuterGenericStructV013InnerConcreteE0VMa(%swift.type* @_T0SiN)
+// CHECK: ret %swift.type
+
+// Type constructor for OuterGenericStruct<T>.InnerConcreteStruct
+// CHECK-LABEL: define{{( protected)?}} %swift.type* @_T015nested_generics18OuterGenericStructV013InnerConcreteE0VMa(%swift.type*)
+
+public struct OuterGenericStruct<T> {
+ public struct InnerGenericStruct<U> {
+ public func method() {
+ blah(T.self)
+ blah(U.self)
+ }
+ }
+
+ public struct InnerConcreteStruct {
+ public func method() {
+ blah(T.self)
+ }
+ }
+}
+
+// Type constructor for OuterGenericClass<Int>.InnerGenericClass<String>
+// CHECK-LABEL: define linkonce_odr hidden %swift.type* @_T015nested_generics17OuterGenericClassC05InnerdE0CySi_SSGMa()
+// CHECK: call %swift.type* @_T015nested_generics17OuterGenericClassC05InnerdE0CMa(%swift.type* @_T0SiN, %swift.type* @_T0SSN)
+
+// Type constructor for OuterGenericClass<T>.InnerGenericClass<U>
+// CHECK-LABEL: define{{( protected)?}} %swift.type* @_T015nested_generics17OuterGenericClassC05InnerdE0CMa(%swift.type*, %swift.type*)
+
+// Type constructor for OuterGenericClass<Int>.InnerConcreteClass
+// CHECK-LABEL: define linkonce_odr hidden %swift.type* @_T015nested_generics17OuterGenericClassC013InnerConcreteE0CySi_GMa()
+// CHECK: call %swift.type* @_T015nested_generics17OuterGenericClassC013InnerConcreteE0CMa(%swift.type* @_T0SiN)
+// CHECK: ret %swift.type
+
+// Type constructor for OuterGenericClass<T>.InnerConcreteClass
+// CHECK-LABEL: define{{( protected)?}} %swift.type* @_T015nested_generics17OuterGenericClassC013InnerConcreteE0CMa(%swift.type*)
+
+// Type constructor for OuterGenericStruct<T>
+// CHECK-LABEL: define{{( protected)?}} %swift.type* @_T015nested_generics18OuterGenericStructVMa(%swift.type*)
+
+// Type constructor for OuterGenericClass<T>
+// CHECK-LABEL: define{{( protected)?}} %swift.type* @_T015nested_generics17OuterGenericClassCMa(%swift.type*)
+
+public class OuterGenericClass<T> {
+ public class InnerGenericClass<U> {
+ public func method() {
+ blah(T.self)
+ blah(U.self)
+ }
+ }
+
+ public class InnerConcreteClass {
+ public func method() {
+ blah(T.self)
+ }
+ }
+}
diff --git a/test/IRGen/nested_types.sil b/test/IRGen/nested_types.sil
index 274a98b..f27fa25 100644
--- a/test/IRGen/nested_types.sil
+++ b/test/IRGen/nested_types.sil
@@ -32,7 +32,5 @@
// CHECK-NEXT: ret %swift.type* [[T4]]
// CHECK-LABEL: define private void @initialize_metadata_Inner
-// CHECK: [[T0:%.*]] = call %swift.type* @_T012nested_types5OuterCMa()
-// CHECK-NEXT: store %swift.type* [[T0]], %swift.type** getelementptr inbounds (%swift.type*, %swift.type** bitcast ({{.*}} @_T012nested_types5OuterC5InnerVMf{{.*}}, [[INT:i[0-9]+]] 2), align
-// CHECK-NEXT: store atomic %swift.type* bitcast ({{.*}} @_T012nested_types5OuterC5InnerVMf{{.*}} to %swift.type*), %swift.type** @_T012nested_types5OuterC5InnerVML release, align
+// CHECK: store atomic %swift.type* bitcast ({{.*}} @_T012nested_types5OuterC5InnerVMf{{.*}} to %swift.type*), %swift.type** @_T012nested_types5OuterC5InnerVML release, align
// CHECK-NEXT: ret void
diff --git a/test/IRGen/nonatomic_reference_counting.sil b/test/IRGen/nonatomic_reference_counting.sil
index 92c29ea..a38ed30 100644
--- a/test/IRGen/nonatomic_reference_counting.sil
+++ b/test/IRGen/nonatomic_reference_counting.sil
@@ -133,7 +133,7 @@
%r = apply %f () : $@convention(thin) () -> ()
unowned_release [nonatomic] %1 : $@sil_unowned C
%3 = tuple ()
- %4 = return %3 : $()
+ return %3 : $()
}
// CHECK-LABEL: define {{.*}}@test_bridged_nonatomic_rr
@@ -150,7 +150,7 @@
%r = apply %f () : $@convention(thin) () -> ()
strong_release [nonatomic] %2 : $Builtin.BridgeObject
%3 = tuple ()
- %4 = return %3 : $()
+ return %3 : $()
}
// CHECK-LABEL: define {{.*}}@test_bridged_nonatomic_rr_n
@@ -171,7 +171,7 @@
strong_release [nonatomic] %2 : $Builtin.BridgeObject
strong_release [nonatomic] %2 : $Builtin.BridgeObject
%3 = tuple ()
- %4 = return %3 : $()
+ return %3 : $()
}
// CHECK-LABEL: define {{.*}}@test_bridged_mixed_rr_n
@@ -192,7 +192,7 @@
strong_release %2 : $Builtin.BridgeObject
strong_release [nonatomic] %2 : $Builtin.BridgeObject
%3 = tuple ()
- %4 = return %3 : $()
+ return %3 : $()
}
// CHECK-LABEL: define {{.*}}@test_nonatomic_pin_unpin
@@ -208,7 +208,7 @@
%r = apply %f () : $@convention(thin) () -> ()
strong_unpin [nonatomic] %2 : $Optional<Builtin.NativeObject>
%3 = tuple ()
- %4 = return %3 : $()
+ return %3 : $()
}
// C.__deallocating_deinit
diff --git a/test/IRGen/struct_resilience.swift b/test/IRGen/struct_resilience.swift
index 7458d97..eed6368 100644
--- a/test/IRGen/struct_resilience.swift
+++ b/test/IRGen/struct_resilience.swift
@@ -59,7 +59,7 @@
// CHECK: [[METADATA:%.*]] = call %swift.type* @_T016resilient_struct9RectangleVMa()
// CHECK-NEXT: [[METADATA_ADDR:%.*]] = bitcast %swift.type* [[METADATA]] to [[INT]]*
-// CHECK-NEXT: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[METADATA_ADDR]], [[INT]] 3
+// CHECK-NEXT: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[METADATA_ADDR]], [[INT]] 2
// CHECK-NEXT: [[FIELD_OFFSET_PTR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[FIELD_OFFSET_VECTOR]], i32 2
// CHECK-NEXT: [[FIELD_OFFSET:%.*]] = load [[INT]], [[INT]]* [[FIELD_OFFSET_PTR]]
// CHECK-NEXT: [[STRUCT_ADDR:%.*]] = bitcast %T16resilient_struct9RectangleV* %0 to i8*
@@ -116,7 +116,7 @@
// CHECK-LABEL: define{{( protected)?}} swiftcc {{i32|i64}} @_T017struct_resilience26StructWithResilientStorageV1nSivg(%T17struct_resilience26StructWithResilientStorageV* {{.*}})
// CHECK: [[METADATA:%.*]] = call %swift.type* @_T017struct_resilience26StructWithResilientStorageVMa()
// CHECK-NEXT: [[METADATA_ADDR:%.*]] = bitcast %swift.type* [[METADATA]] to [[INT]]*
-// CHECK-NEXT: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[METADATA_ADDR]], [[INT]] 3
+// CHECK-NEXT: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[METADATA_ADDR]], [[INT]] 2
// CHECK-NEXT: [[FIELD_OFFSET_PTR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[FIELD_OFFSET_VECTOR]], i32 2
// CHECK-NEXT: [[FIELD_OFFSET:%.*]] = load [[INT]], [[INT]]* [[FIELD_OFFSET_PTR]]
// CHECK-NEXT: [[STRUCT_ADDR:%.*]] = bitcast %T17struct_resilience26StructWithResilientStorageV* %0 to i8*
diff --git a/test/IRGen/unowned.sil b/test/IRGen/unowned.sil
index bc12958..ab5a51a 100644
--- a/test/IRGen/unowned.sil
+++ b/test/IRGen/unowned.sil
@@ -25,10 +25,10 @@
sil @test_weak_rr_class : $@convention(thin) (@sil_unowned C) -> () {
bb0(%0 : $@sil_unowned C):
- %1 = unowned_retain %0 : $@sil_unowned C
- %2 = unowned_release %0 : $@sil_unowned C
+ unowned_retain %0 : $@sil_unowned C
+ unowned_release %0 : $@sil_unowned C
%3 = tuple ()
- %4 = return %3 : $()
+ return %3 : $()
}
// CHECK: define{{( protected)?}} swiftcc void @test_weak_rr_class([[C]]*) {{.*}} {
// CHECK: call [[C]]* bitcast ([[REF]]* ([[REF]]*)* @swift_rt_swift_unownedRetain to [[C]]* ([[C]]*)*)([[C]]* returned %0)
@@ -37,10 +37,10 @@
sil @test_weak_rr_proto : $@convention(thin) (@sil_unowned P) -> () {
bb0(%0 : $@sil_unowned P):
- %1 = unowned_retain %0 : $@sil_unowned P
- %2 = unowned_release %0 : $@sil_unowned P
+ unowned_retain %0 : $@sil_unowned P
+ unowned_release %0 : $@sil_unowned P
%3 = tuple ()
- %4 = return %3 : $()
+ return %3 : $()
}
// CHECK: define{{( protected)?}} swiftcc void @test_weak_rr_proto(%swift.refcounted*, i8**) {{.*}} {
// CHECK: call %swift.refcounted* @swift_rt_swift_unownedRetain(%swift.refcounted* returned %0)
diff --git a/test/IRGen/unowned_objc.sil b/test/IRGen/unowned_objc.sil
index 792b834..879d683 100644
--- a/test/IRGen/unowned_objc.sil
+++ b/test/IRGen/unowned_objc.sil
@@ -31,10 +31,10 @@
sil @test_weak_rr_class : $@convention(thin) (@sil_unowned C) -> () {
bb0(%0 : $@sil_unowned C):
- %1 = unowned_retain %0 : $@sil_unowned C
- %2 = unowned_release %0 : $@sil_unowned C
+ unowned_retain %0 : $@sil_unowned C
+ unowned_release %0 : $@sil_unowned C
%3 = tuple ()
- %4 = return %3 : $()
+ return %3 : $()
}
// CHECK: define{{( protected)?}} swiftcc void @test_weak_rr_class([[C]]*) {{.*}} {
// CHECK: call [[C]]* bitcast ([[REF]]* ([[REF]]*)* @swift_rt_swift_unownedRetain to [[C]]* ([[C]]*)*)([[C]]* returned %0)
diff --git a/test/Parse/errors.swift b/test/Parse/errors.swift
index 472d598..8fb0ecf 100644
--- a/test/Parse/errors.swift
+++ b/test/Parse/errors.swift
@@ -104,8 +104,7 @@
do {
_ = try genError()
- // TODO: this recovery is terrible
- } catch MSV.CarriesInt(let i) where i == genError()) { // expected-error {{call can throw, but errors cannot be thrown out of a catch guard expression}} expected-error {{expected '{'}} expected-error {{closure expression is unused}} expected-note {{did you mean to use a 'do' statement?}} {{58-58=do }}
+ } catch MSV.CarriesInt(let i) where i == genError()) { // expected-error {{call can throw, but errors cannot be thrown out of a catch guard expression}} expected-error {{expected '{'}}
}
}
diff --git a/test/Parse/recovery.swift b/test/Parse/recovery.swift
index 9ab1aaa..bd78194 100644
--- a/test/Parse/recovery.swift
+++ b/test/Parse/recovery.swift
@@ -194,7 +194,7 @@
// expected-error @+3 {{expected pattern}}
// expected-error @+2 {{expected Sequence expression for for-each loop}}
// expected-error @+1 {{expected '{' to start the body of for-each loop}}
- for for in { // expected-error {{expected pattern}} expected-error {{expected Sequence expression for for-each loop}}
+ for for in {
}
for i in { // expected-error {{expected Sequence expression for for-each loop}}
@@ -215,6 +215,15 @@
var x = 42
}
#endif
+
+ // SR-5943
+ struct User { let name: String? }
+ let users = [User]()
+ for user in users whe { // expected-error {{expected '{' to start the body of for-each loop}}
+ if let name = user.name {
+ let key = "\(name)"
+ }
+ }
}
func missingControllingExprInSwitch() {
diff --git a/test/SIL/Parser/basic.sil b/test/SIL/Parser/basic.sil
index 68afa78..368f050 100644
--- a/test/SIL/Parser/basic.sil
+++ b/test/SIL/Parser/basic.sil
@@ -98,7 +98,7 @@
sil @named_tuple : $() -> (Builtin.Word, Builtin.Word) {
%0 = integer_literal $Builtin.Word, 42 // CHECK: integer_literal $Builtin.Word, 42
%9 = tuple $(Builtin.Word, Builtin.Word) (%0, %0)
- %10 = return %9 : $(Builtin.Word, Builtin.Word)
+ return %9 : $(Builtin.Word, Builtin.Word)
}
sil @return_int : $@convention(thin) (Int) -> Int { // CHECK: $@convention(thin) (Int) -> Int {
@@ -137,7 +137,7 @@
// CHECK: apply
%4 = apply %1(%3, %2) : $@convention(thin) (Builtin.Word, @thin Int.Type) -> Int
// CHECK: return
- %5 = return %4 : $Int
+ return %4 : $Int
}
sil @_TSi25convertFromIntegerLiteralfMSiFT3valBi64__Si : $@convention(thin) (Builtin.Word, @thin Int.Type) -> Int
@@ -154,13 +154,13 @@
// CHECK: alloc_stack $Bool
%1 = alloc_stack $Bool
// CHECK: store
- %2 = store %0 to %1 : $*Bool
+ store %0 to %1 : $*Bool
// CHECK: function_ref @_TSb13getLogicValuefRSbFT_Bi1_ : $@convention(method) (@inout Bool) -> Builtin.Int1
%3 = function_ref @_TSb13getLogicValuefRSbFT_Bi1_ : $@convention(method) (@inout Bool) -> Builtin.Int1
// CHECK: apply
%4 = apply %3(%1) : $@convention(method) (@inout Bool) -> Builtin.Int1
// CHECK: cond_br
- %5 = cond_br %4, bb1, bb2
+ cond_br %4, bb1, bb2
// CHECK: bb1:
bb1:
@@ -173,7 +173,7 @@
// CHECK: apply
%9 = apply %6(%8, %7) : $@convention(thin) (Builtin.Int128, @thin Int.Type) -> Int
// CHECK: dealloc_stack
- %10 = dealloc_stack %1 : $*Bool
+ dealloc_stack %1 : $*Bool
// CHECK: br
br bb3(%9 : $Int)
@@ -188,7 +188,7 @@
// CHECK: apply
%15 = apply %12(%14, %13) : $@convention(thin) (Builtin.Int128, @thin Int.Type) -> Int
// CHECK: dealloc_stack
- %16 = dealloc_stack %1 : $*Bool
+ dealloc_stack %1 : $*Bool
// CHECK: br
br bb3(%15 : $Int)
@@ -221,8 +221,8 @@
%6 = witness_method $@opened("01234567-89ab-cdef-0123-000000000001") P, #P.doIt!1, %5 : $*@opened("01234567-89ab-cdef-0123-000000000001") P : $@convention(witness_method) <T: P> (@in_guaranteed T) -> ()
%8 = apply %6<@opened("01234567-89ab-cdef-0123-000000000001") P>(%5) : $@convention(witness_method) <T: P> (@in_guaranteed T) -> ()
- %9 = destroy_addr %0 : $*P // CHECK: destroy_addr %0 : $*P
- %10 = return %4 : $() // CHECK: return
+ destroy_addr %0 : $*P // CHECK: destroy_addr %0 : $*P
+ return %4 : $() // CHECK: return
}
@@ -258,7 +258,7 @@
%5 = unconditional_checked_cast %C : $C to $D // CHECK: unconditional_checked_cast
%6 = tuple ()
- %7 = return %6 : $()
+ return %6 : $()
}
sil @optional_upcasts : $@convention(thin) (Optional<D>) -> () {
@@ -266,7 +266,7 @@
// CHECK: upcast {{.*}} : $Optional<D> to $Optional<C>
%1 = upcast %0 : $Optional<D> to $Optional<C>
%2 = tuple ()
- %3 = return %2 : $()
+ return %2 : $()
}
@@ -295,15 +295,15 @@
// C/HECK: witness_method $*T, #Runcible.associated_method!1
%4 = witness_method $*T, #Runcible.associated_method!1 : $@cc(method) (@inout T) -> @thick T.U.Type
%5 = apply %4(%0) : $@cc(method) (@inout T) -> @thick T.U.Type
- %6 = store %5 to %3 : $*@thick T.U.Type
+ store %5 to %3 : $*@thick T.U.Type
%7 = metatype $@thick T.Type
// C/HECK: witness_method [volatile] $*T, #Runcible.static_method!1
%8 = witness_method [volatile] $*T, #Runcible.static_method!1 : $(@thick T.Type) -> ()
%9 = apply %8(%7) : $(@thick T.Type) -> ()
- %10 = dealloc_stack %3 : $*@thick T.U.Type
+ dealloc_stack %3 : $*@thick T.U.Type
%11 = tuple ()
- %12 = destroy_addr %0 : $*T
- %13 = return %11 : $()
+ destroy_addr %0 : $*T
+ return %11 : $()
}
*/
@@ -316,20 +316,20 @@
%2 = alloc_box $<τ_0_0> { var τ_0_0 } <Bendable & Runcible>
%2a = project_box %2 : $<τ_0_0> { var τ_0_0 } <Bendable & Runcible>, 0
// CHECK: copy_addr [take] {{.*}} to [initialization] {{.*}} : $*Bendable & Runcible
- %3 = copy_addr [take] %1 to [initialization] %2a : $*Bendable & Runcible
+ copy_addr [take] %1 to [initialization] %2a : $*Bendable & Runcible
// CHECK: alloc_stack
%4 = alloc_stack $Bendable & Runcible
// CHECK: copy_addr {{.*}} to [initialization] {{.*}} : $*Bendable & Runcible
- %5 = copy_addr %2a to [initialization] %4 : $*Bendable & Runcible
+ copy_addr %2a to [initialization] %4 : $*Bendable & Runcible
%7 = tuple ()
// CHECK: destroy_addr
- %8 = destroy_addr %4 : $*Bendable & Runcible
+ destroy_addr %4 : $*Bendable & Runcible
// CHECK: dealloc_stack
- %9 = dealloc_stack %4 : $*Bendable & Runcible
+ dealloc_stack %4 : $*Bendable & Runcible
// CHECK: release
- %10 = strong_release %2 : $<τ_0_0> { var τ_0_0 } <Bendable & Runcible>
+ strong_release %2 : $<τ_0_0> { var τ_0_0 } <Bendable & Runcible>
// CHECK: return
- %11 = return %7 : $()
+ return %7 : $()
}
protocol ClassBound : class {
@@ -341,17 +341,17 @@
bb0(%0 : $ClassBound):
%1 = alloc_box $<τ_0_0> { var τ_0_0 } <ClassBound> // CHECK: alloc_box
%1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <ClassBound>, 0
- %2 = store %0 to %1a : $*ClassBound // CHECK: store
+ store %0 to %1a : $*ClassBound // CHECK: store
%3 = load %1a : $*ClassBound // CHECK: load
- %4 = strong_retain %3 : $ClassBound // CHECK: strong_retain
+ strong_retain %3 : $ClassBound // CHECK: strong_retain
// CHECK: open_existential_ref {{%.*}} : $ClassBound to $@opened({{.*}}) ClassBound
%5 = open_existential_ref %3 : $ClassBound to $@opened("01234567-89ab-cdef-0123-111111111111") ClassBound
// CHECK: witness_method
%6 = witness_method $@opened("01234567-89ab-cdef-0123-111111111111") ClassBound, #ClassBound.classBoundMethod!1, %5 : $@opened("01234567-89ab-cdef-0123-111111111111") ClassBound : $@convention(witness_method) <T: ClassBound> (T) -> ()
%7 = apply %6<@opened("01234567-89ab-cdef-0123-111111111111") ClassBound>(%5) : $@convention(witness_method) <T: ClassBound> (T) -> ()
%8 = tuple ()
- %9 = strong_release %1 : $<τ_0_0> { var τ_0_0 } <ClassBound>
- %10 = return %8 : $()
+ strong_release %1 : $<τ_0_0> { var τ_0_0 } <ClassBound>
+ return %8 : $()
}
struct Val {
@@ -363,7 +363,7 @@
%1 = alloc_stack $Val // CHECK: alloc_stack
%3 = load %1 : $*Val
dealloc_stack %1 : $*Val
- %4 = return %3 : $Val
+ return %3 : $Val
}
class Ref {
@@ -378,7 +378,7 @@
bb0(%0 : $Ref, %1 : $Val, %2 : $@thin Aleph.Type):
// CHECK: struct $Aleph ({{%.*}} : $Ref, {{%.*}} : $Val)
%3 = struct $Aleph (%0 : $Ref, %1 : $Val)
- %4 = return %3 : $Aleph // CHECK: return
+ return %3 : $Aleph // CHECK: return
}
// CHECK: $@convention(thin) (@thin Aleph.Type) -> Aleph
@@ -390,13 +390,13 @@
// CHECK: struct_element_addr {{.*}} : $*Aleph, #Aleph.a
%5 = struct_element_addr %2a : $*Aleph, #Aleph.a
%6 = load %5 : $*Ref
- %8 = strong_release %6 : $Ref
+ strong_release %6 : $Ref
%14 = load %2a : $*Aleph
// CHECK: struct_extract {{%.*}} : $Aleph, #Aleph.a
%15 = struct_extract %14 : $Aleph, #Aleph.a
- %16 = strong_retain %15 : $Ref
- %17 = strong_release %2 : $<τ_0_0> { var τ_0_0 } <Aleph>
- %18 = return %14 : $Aleph
+ strong_retain %15 : $Ref
+ strong_release %2 : $<τ_0_0> { var τ_0_0 } <Aleph>
+ return %14 : $Aleph
}
enum Beth {
@@ -455,7 +455,7 @@
%2a = project_box %2 : $<τ_0_0> { var τ_0_0 } <(Int, Float)>, 0
// CHECK: tuple ({{%.*}} : $Int, {{%.*}} : $Float)
%3 = tuple (%0 : $Int, %1 : $Float)
- %4 = store %3 to %2a : $*(Int, Float)
+ store %3 to %2a : $*(Int, Float)
// CHECK: tuple_element_addr {{%.*}} : $*(Int, Float), 0
%6 = tuple_element_addr %2a : $*(Int, Float), 0
// CHECK: load
@@ -475,8 +475,8 @@
// CHECK: apply
%24 = apply %19(%17) : $@convention(thin) (Float) -> ()
%25 = tuple ()
- %26 = strong_release %2 : $<τ_0_0> { var τ_0_0 } <(Int, Float)>
- %27 = return %25 : $()
+ strong_release %2 : $<τ_0_0> { var τ_0_0 } <(Int, Float)>
+ return %25 : $()
}
class M {
@@ -489,21 +489,21 @@
bb0(%0 : $Int, %1 : $M):
%2 = alloc_box $<τ_0_0> { var τ_0_0 } <Int> // CHECK: alloc_box $<τ_0_0> { var τ_0_0 } <Int>
%2a = project_box %2 : $<τ_0_0> { var τ_0_0 } <Int>, 0
- %3 = store %0 to %2a : $*Int
+ store %0 to %2a : $*Int
%4 = alloc_box $<τ_0_0> { var τ_0_0 } <M> // CHECK: alloc_box $<τ_0_0> { var τ_0_0 } <M>
%4a = project_box %4 : $<τ_0_0> { var τ_0_0 } <M>, 0
- %5 = store %1 to %4a : $*M
+ store %1 to %4a : $*M
%6 = load %2a : $*Int // CHECK: load {{.*}} : $*Int
%7 = load %4a : $*M // CHECK: load {{.*}} : $*M
- %8 = strong_retain %7 : $M
+ strong_retain %7 : $M
// CHECK: ref_element_addr {{%.*}} : $M, #M.member
%9 = ref_element_addr %7 : $M, #M.member
- %10 = store %6 to %9 : $*Int
- %11 = strong_release %7 : $M
+ store %6 to %9 : $*Int
+ strong_release %7 : $M
%12 = tuple ()
- %13 = strong_release %4 : $<τ_0_0> { var τ_0_0 } <M>
- %14 = strong_release %2 : $<τ_0_0> { var τ_0_0 } <Int>
- %15 = return %12 : $()
+ strong_release %4 : $<τ_0_0> { var τ_0_0 } <M>
+ strong_release %2 : $<τ_0_0> { var τ_0_0 } <Int>
+ return %12 : $()
}
class GenericClass<Q> {
@@ -529,9 +529,9 @@
bb0(%0 : $B):
%1 = alloc_box $<τ_0_0> { var τ_0_0 } <B> // CHECK: alloc_box
%1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <B>, 0
- %2 = store %0 to %1a : $*B
+ store %0 to %1a : $*B
%3 = load %1a : $*B // CHECK: load
- %4 = strong_retain %3 : $B
+ strong_retain %3 : $B
checked_cast_br %3 : $B to $E, yes, no // CHECK: checked_cast_br
yes(%5 : $E):
%y = integer_literal $Builtin.Int1, 1
@@ -540,9 +540,9 @@
%n = integer_literal $Builtin.Int1, 0
br isa(%n : $Builtin.Int1)
isa(%6 : $Builtin.Int1):
- %7 = strong_release %3 : $B
- %8 = strong_release %1 : $<τ_0_0> { var τ_0_0 } <B>
- %9 = return %6 : $Builtin.Int1
+ strong_release %3 : $B
+ strong_release %1 : $<τ_0_0> { var τ_0_0 } <B>
+ return %6 : $Builtin.Int1
}
sil @_TSd31_convertFromBuiltinFloatLiteralfMSdFT5valueBf64__Sd : $@convention(thin) (Builtin.FPIEEE64, @thin Float64.Type) -> Float64
@@ -555,15 +555,15 @@
%2a = project_box %2 : $<τ_0_0> { var τ_0_0 } <Builtin.RawPointer>, 0
%3 = alloc_box $<τ_0_0> { var τ_0_0 } <Builtin.Word> // CHECK: alloc_box
%3a = project_box %3 : $<τ_0_0> { var τ_0_0 } <Builtin.Word>, 0
- %4 = store %0 to %2a : $*Builtin.RawPointer
- %5 = store %1 to %3a : $*Builtin.Word
+ store %0 to %2a : $*Builtin.RawPointer
+ store %1 to %3a : $*Builtin.Word
%7 = load %2a : $*Builtin.RawPointer // CHECK: load
%8 = load %3a : $*Builtin.Word // CHECK: load
// CHECK: index_raw_pointer {{%.*}} : $Builtin.RawPointer, {{%.*}} : $Builtin.Word
%9 = index_raw_pointer %7 : $Builtin.RawPointer, %8 : $Builtin.Word
- %10 = strong_release %3 : $<τ_0_0> { var τ_0_0 } <Builtin.Word>
- %11 = strong_release %2 : $<τ_0_0> { var τ_0_0 } <Builtin.RawPointer>
- %12 = return %9 : $Builtin.RawPointer
+ strong_release %3 : $<τ_0_0> { var τ_0_0 } <Builtin.Word>
+ strong_release %2 : $<τ_0_0> { var τ_0_0 } <Builtin.RawPointer>
+ return %9 : $Builtin.RawPointer
}
sil_global @x : $Int
@@ -589,9 +589,9 @@
%2 = metatype $@thin Int.Type
%3 = integer_literal $Builtin.Int128, 0 // CHECK: integer_literal $Builtin.Int128, 0
%4 = apply %1(%3, %2) : $@convention(thin) (Builtin.Int128, @thin Int.Type) -> Int
- %5 = store %4 to %0 : $*Int
+ store %4 to %0 : $*Int
%6 = tuple ()
- %7 = return %6 : $()
+ return %6 : $()
}
protocol SomeProtocol {
@@ -606,55 +606,55 @@
%2a = project_box %2 : $<τ_0_0> { var τ_0_0 } <SomeClass>, 0
%3 = alloc_box $<τ_0_0> { var τ_0_0 } <SomeSubclass> // CHECK: alloc_box
%3a = project_box %3 : $<τ_0_0> { var τ_0_0 } <SomeSubclass>, 0
- %4 = store %0 to %2a : $*SomeClass
- %5 = store %1 to %3a : $*SomeSubclass
+ store %0 to %2a : $*SomeClass
+ store %1 to %3a : $*SomeSubclass
%7 = load %2a : $*SomeClass // CHECK: load
- %8 = strong_retain %7 : $SomeClass
+ strong_retain %7 : $SomeClass
// CHECK: value_metatype $@thick SomeClass.Type, {{%.*}} : $SomeClass
%9 = value_metatype $@thick SomeClass.Type, %7 : $SomeClass
%11 = load %3a : $*SomeSubclass // CHECK: load
- %12 = strong_retain %11 : $SomeSubclass
+ strong_retain %11 : $SomeSubclass
// CHECK: value_metatype $@thick SomeSubclass.Type, {{%.*}} : $SomeSubclass
%13 = value_metatype $@thick SomeSubclass.Type, %11 : $SomeSubclass
%14 = upcast %13 : $@thick SomeSubclass.Type to $@thick SomeClass.Type // CHECK: upcast
%15 = tuple (%9 : $@thick SomeClass.Type, %14 : $@thick SomeClass.Type) // CHECK: tuple
- %16 = strong_release %11 : $SomeSubclass
- %17 = strong_release %7 : $SomeClass
- %18 = strong_release %3 : $<τ_0_0> { var τ_0_0 } <SomeSubclass>
- %19 = strong_release %2 : $<τ_0_0> { var τ_0_0 } <SomeClass>
- %20 = return %15 : $(@thick SomeClass.Type, @thick SomeClass.Type)
+ strong_release %11 : $SomeSubclass
+ strong_release %7 : $SomeClass
+ strong_release %3 : $<τ_0_0> { var τ_0_0 } <SomeSubclass>
+ strong_release %2 : $<τ_0_0> { var τ_0_0 } <SomeClass>
+ return %15 : $(@thick SomeClass.Type, @thick SomeClass.Type)
}
sil @test_value_metatype : $@convention(thin) <T> (@in T) -> (@thick T.Type, @thick T.Type) {
bb0(%0 : $*T):
%1 = alloc_box $<τ_0_0> { var τ_0_0 } <T> // CHECK: alloc_box
%1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <T>, 0
- %2 = copy_addr [take] %0 to [initialization] %1a : $*T
+ copy_addr [take] %0 to [initialization] %1a : $*T
%3 = metatype $@thick T.Type // CHECK: metatype
%5 = alloc_stack $T // CHECK: alloc_stack
- %6 = copy_addr %1a to [initialization] %5 : $*T
+ copy_addr %1a to [initialization] %5 : $*T
// CHECK: value_metatype $@thick T.Type, {{%.*}} : $*T
%7 = value_metatype $@thick T.Type, %5 : $*T
%8 = tuple (%3 : $@thick T.Type, %7 : $@thick T.Type) // CHECK: tuple
- %9 = destroy_addr %5 : $*T
- %10 = dealloc_stack %5 : $*T
- %11 = strong_release %1 : $<τ_0_0> { var τ_0_0 } <T>
- %12 = return %8 : $(@thick T.Type, @thick T.Type)
+ destroy_addr %5 : $*T
+ dealloc_stack %5 : $*T
+ strong_release %1 : $<τ_0_0> { var τ_0_0 } <T>
+ return %8 : $(@thick T.Type, @thick T.Type)
}
sil @test_existential_metatype : $@convention(thin) (@in SomeProtocol) -> @thick SomeProtocol.Type {
bb0(%0 : $*SomeProtocol):
%1 = alloc_box $<τ_0_0> { var τ_0_0 } <SomeProtocol> // CHECK: alloc_box
%1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <SomeProtocol>, 0
- %2 = copy_addr [take] %0 to [initialization] %1a : $*SomeProtocol
+ copy_addr [take] %0 to [initialization] %1a : $*SomeProtocol
%4 = alloc_stack $SomeProtocol // CHECK: alloc_stack
- %5 = copy_addr %1a to [initialization] %4 : $*SomeProtocol
+ copy_addr %1a to [initialization] %4 : $*SomeProtocol
// CHECK: existential_metatype $@thick SomeProtocol.Type, {{%.*}} : $*SomeProtocol
%6 = existential_metatype $@thick SomeProtocol.Type, %4 : $*SomeProtocol
- %7 = destroy_addr %4 : $*SomeProtocol
- %8 = dealloc_stack %4 : $*SomeProtocol
- %9 = strong_release %1 : $<τ_0_0> { var τ_0_0 } <SomeProtocol>
- %10 = return %6 : $@thick SomeProtocol.Type
+ destroy_addr %4 : $*SomeProtocol
+ dealloc_stack %4 : $*SomeProtocol
+ strong_release %1 : $<τ_0_0> { var τ_0_0 } <SomeProtocol>
+ return %6 : $@thick SomeProtocol.Type
}
// CHECK-LABEL: sil @test_unreachable
@@ -668,14 +668,14 @@
bb0(%0 : $SomeClass):
%1 = ref_to_unowned %0 : $SomeClass to $@sil_unowned SomeClass
// CHECK: ref_to_unowned %0 : $SomeClass to $@sil_unowned SomeClass
- %2 = unowned_retain %1 : $@sil_unowned SomeClass
+ unowned_retain %1 : $@sil_unowned SomeClass
// CHECK: unowned_retain %1 : $@sil_unowned SomeClass
- %3 = unowned_release %1 : $@sil_unowned SomeClass
+ unowned_release %1 : $@sil_unowned SomeClass
// CHECK: unowned_release %1 : $@sil_unowned SomeClass
%4 = unowned_to_ref %1 : $@sil_unowned SomeClass to $SomeClass
// CHECK: unowned_to_ref %1 : $@sil_unowned SomeClass to $SomeClass
%5 = tuple ()
- %6 = return %5 : $()
+ return %5 : $()
}
// CHECK-LABEL: sil @test_basic_block_arguments
@@ -1048,14 +1048,14 @@
// CHECK: apply %{{.*}}() : $@convention(thin) () -> ()
%1 = apply %0() : $@convention(thin) () -> ()
%2 = tuple ()
- %3 = return %2 : $()
+ return %2 : $()
}
// CHECK-LABEL: sil [thunk] @test_thunk : $@convention(thin) () -> () {
sil [thunk] @test_thunk : $@convention(thin) () -> () {
bb0:
%0 = tuple ()
- %1 = return %0 : $()
+ return %0 : $()
}
// CHECK-LABEL: sil @takes_unnamed_closure : $@convention(thin) (@callee_owned () -> Int) -> () -> () -> Int
@@ -1069,7 +1069,7 @@
%1 = function_ref @takes_int64_float32 : $@convention(thin) (Int, Float) -> ()
// CHECK: partial_apply %{{.*}}(%{{.*}}) : $@convention(thin) (Int, Float) -> ()
%2 = partial_apply %1(%0) : $@convention(thin) (Int, Float) -> ()
- %3 = return %2 : $@callee_owned Int -> ()
+ return %2 : $@callee_owned Int -> ()
}
class X {
diff --git a/test/SIL/Parser/errors.sil b/test/SIL/Parser/errors.sil
index da77db7..4875a1c 100644
--- a/test/SIL/Parser/errors.sil
+++ b/test/SIL/Parser/errors.sil
@@ -8,9 +8,9 @@
sil @block_errors : $() -> () {
bb0:
%0 = tuple ()
- %1 = return %0 : $()
+ return %0 : $()
bb0: // expected-error {{redefinition of basic block 'bb0'}}
- %3 = return %0 : $()
+ return %0 : $()
}
sil @local_value_errors : $() -> () {
@@ -27,7 +27,7 @@
%0 = function_ref @global_value_errors : $ () -> ((), ()) // expected-error {{defined with mismatching type}}
%1 = function_ref @not_defined : $ () -> () // expected-error {{use of undefined value 'not_defined'}}
%2 = tuple ()
- %3 = return %2 : $()
+ return %2 : $()
}
sil @global_value_errors : $() -> () { // expected-error {{redefinition of value 'global_value_errors'}}
diff --git a/test/SIL/Parser/indirect_enum.sil b/test/SIL/Parser/indirect_enum.sil
index 26521b5..f550c84 100644
--- a/test/SIL/Parser/indirect_enum.sil
+++ b/test/SIL/Parser/indirect_enum.sil
@@ -35,7 +35,7 @@
sil @indirect_enum_case_addr_only : $@convention(thin) <T> (@in TreeB<T>) -> () {
entry(%e : $*TreeB<T>):
%a = unchecked_take_enum_data_addr %e : $*TreeB<T>, #TreeB.Leaf!enumelt.1
- %b = destroy_addr %a : $*T
+ destroy_addr %a : $*T
%c = unchecked_take_enum_data_addr %e : $*TreeB<T>, #TreeB.Branch!enumelt.1
%d = load [take] %c : $*<τ_0_0> { var τ_0_0 } <(left: TreeB<T>, right: TreeB<T>)>
diff --git a/test/SIL/Parser/nonatomic_reference_counting.sil b/test/SIL/Parser/nonatomic_reference_counting.sil
index 2a9f743..67a3f68 100644
--- a/test/SIL/Parser/nonatomic_reference_counting.sil
+++ b/test/SIL/Parser/nonatomic_reference_counting.sil
@@ -56,7 +56,7 @@
%2 = strong_pin [nonatomic] %1 : $Builtin.NativeObject
strong_unpin [nonatomic] %2 : $Optional<Builtin.NativeObject>
%3 = tuple ()
- %4 = return %3 : $()
+ return %3 : $()
}
// CHECK-LABEL: sil @test_unowned_nonatomic_rr
@@ -70,7 +70,7 @@
unowned_retain [nonatomic] %1 : $@sil_unowned C
unowned_release [nonatomic] %1 : $@sil_unowned C
%3 = tuple ()
- %4 = return %3 : $()
+ return %3 : $()
}
// CHECK-LABEL: sil @test_set_deallocating
diff --git a/test/SIL/Parser/opaque_values_parse.sil b/test/SIL/Parser/opaque_values_parse.sil
index bda7bda..5c9578a 100644
--- a/test/SIL/Parser/opaque_values_parse.sil
+++ b/test/SIL/Parser/opaque_values_parse.sil
@@ -31,7 +31,7 @@
// CHECK-LABEL: } // end sil function 'condCastOpaque'
sil @condCastOpaque : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
- %c = checked_cast_value_br %0 : $Int to $Int, bb2, bb1
+ checked_cast_value_br %0 : $Int to $Int, bb2, bb1
bb1:
br bb3
@@ -52,7 +52,7 @@
sil @initDeinitExistentialValue : $@convention(thin) <T> (@in T) -> () {
bb0(%0 : $T):
%i = init_existential_value %0 : $T, $T, $Any
- %d = deinit_existential_value %i : $Any
+ deinit_existential_value %i : $Any
%t = tuple ()
return %t : $()
}
diff --git a/test/SIL/Serialization/opaque_values_serialize.sil b/test/SIL/Serialization/opaque_values_serialize.sil
index 6ce7f0dd..bb7ea3a 100644
--- a/test/SIL/Serialization/opaque_values_serialize.sil
+++ b/test/SIL/Serialization/opaque_values_serialize.sil
@@ -37,7 +37,7 @@
// CHECK-LABEL: } // end sil function 'condCastOpaque'
sil @condCastOpaque : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
- %c = checked_cast_value_br %0 : $Int to $Int, bb2, bb1
+ checked_cast_value_br %0 : $Int to $Int, bb2, bb1
bb1:
br bb3
@@ -58,7 +58,7 @@
sil @initDeinitExistentialValue : $@convention(thin) <T> (@in T) -> () {
bb0(%0 : $T):
%i = init_existential_value %0 : $T, $T, $Any
- %d = deinit_existential_value %i : $Any
+ deinit_existential_value %i : $Any
%t = tuple ()
return %t : $()
}
diff --git a/test/SIL/ownership-verifier/definite_init.sil b/test/SIL/ownership-verifier/definite_init.sil
index 69fa754..e322f99 100644
--- a/test/SIL/ownership-verifier/definite_init.sil
+++ b/test/SIL/ownership-verifier/definite_init.sil
@@ -35,7 +35,7 @@
%91 = alloc_box $<τ_0_0> { var τ_0_0 } <Builtin.Int32>
%91a = project_box %91 : $<τ_0_0> { var τ_0_0 } <Builtin.Int32>, 0
%1 = mark_uninitialized [var] %91a : $*Builtin.Int32
- %2 = store %0 to [trivial] %1 : $*Builtin.Int32
+ store %0 to [trivial] %1 : $*Builtin.Int32
%3 = load [trivial] %1 : $*Builtin.Int32
%5 = function_ref @takes_Int_inout : $@convention(thin) (@inout Builtin.Int32) -> ()
%6 = apply %5(%1) : $@convention(thin) (@inout Builtin.Int32) -> ()
diff --git a/test/SIL/ownership-verifier/use_verifier.sil b/test/SIL/ownership-verifier/use_verifier.sil
index 8429460..908afae 100644
--- a/test/SIL/ownership-verifier/use_verifier.sil
+++ b/test/SIL/ownership-verifier/use_verifier.sil
@@ -106,7 +106,7 @@
sil @store_borrow_result : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
bb0(%0 : @guaranteed $Builtin.NativeObject):
%1 = alloc_stack $Builtin.NativeObject
- %2 = store_borrow %0 to %1 : $*Builtin.NativeObject
+ store_borrow %0 to %1 : $*Builtin.NativeObject
dealloc_stack %1 : $*Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
@@ -324,10 +324,10 @@
%011 = begin_borrow %01 : $RefWithInt
%11 = alloc_stack $Builtin.UnsafeValueBuffer
%21 = ref_element_addr %011 : $RefWithInt, #RefWithInt.value
- %31 = begin_unpaired_access [modify] [dynamic] %21 : $*Builtin.Int32, %11 : $*Builtin.UnsafeValueBuffer
- %41 = end_unpaired_access [dynamic] %11 : $*Builtin.UnsafeValueBuffer
- %51 = begin_unpaired_access [read] [dynamic] %21 : $*Builtin.Int32, %11 : $*Builtin.UnsafeValueBuffer
- %61 = end_unpaired_access [dynamic] %11 : $*Builtin.UnsafeValueBuffer
+ begin_unpaired_access [modify] [dynamic] %21 : $*Builtin.Int32, %11 : $*Builtin.UnsafeValueBuffer
+ end_unpaired_access [dynamic] %11 : $*Builtin.UnsafeValueBuffer
+ begin_unpaired_access [read] [dynamic] %21 : $*Builtin.Int32, %11 : $*Builtin.UnsafeValueBuffer
+ end_unpaired_access [dynamic] %11 : $*Builtin.UnsafeValueBuffer
end_borrow %011 from %01 : $RefWithInt, $RefWithInt
dealloc_stack %11 : $*Builtin.UnsafeValueBuffer
destroy_value %01 : $RefWithInt
diff --git a/test/SILGen/inlineable_attribute.swift b/test/SILGen/inlineable_attribute.swift
index e747462..9150d51 100644
--- a/test/SILGen/inlineable_attribute.swift
+++ b/test/SILGen/inlineable_attribute.swift
@@ -74,3 +74,20 @@
@_inlineable public func talkAboutAHorse(h: Horse) {
_ = h.gallop
}
+
+@_versioned class Base {
+ @_versioned
+ @_inlineable
+ init(horse: Horse) {}
+}
+
+// CHECK-LABEL: sil [serialized] @_T020inlineable_attribute7DerivedCfd : $@convention(method) (@guaranteed Derived) -> @owned Builtin.NativeObject
+// CHECK-LABEL: sil [serialized] @_T020inlineable_attribute7DerivedCfD : $@convention(method) (@owned Derived) -> ()
+
+// Make sure the synthesized delegating initializer is inlineable also
+
+// CHECK-LABEL: sil [serialized] @_T020inlineable_attribute7DerivedCAcA5HorseC5horse_tcfc : $@convention(method) (@owned Horse, @owned Derived) -> @owned Derived
+@_versioned class Derived : Base {
+ // Allow @_inlineable deinits
+ @_inlineable deinit {}
+}
diff --git a/test/SILGen/pgo_checked_cast.swift b/test/SILGen/pgo_checked_cast.swift
new file mode 100644
index 0000000..6ee7a21
--- /dev/null
+++ b/test/SILGen/pgo_checked_cast.swift
@@ -0,0 +1,71 @@
+// RUN: rm -rf %t && mkdir %t
+// RUN: %target-build-swift %s -profile-generate -Xfrontend -disable-incremental-llvm-codegen -module-name pgo_checked_cast -o %t/main
+// RUN: env LLVM_PROFILE_FILE=%t/default.profraw %target-run %t/main
+// RUN: %llvm-profdata merge %t/default.profraw -o %t/default.profdata
+// RUN: %target-swift-frontend %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -emit-sorted-sil -emit-sil -module-name pgo_checked_cast -o - | %FileCheck %s --check-prefix=SIL
+// need to lower checked_cast_addr_br(addr) into IR for this
+// %target-swift-frontend %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -emit-ir -module-name pgo_checked_cast -o - | %FileCheck %s --check-prefix=IR
+// RUN: %target-swift-frontend %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -O -emit-sorted-sil -emit-sil -module-name pgo_checked_cast -o - | %FileCheck %s --check-prefix=SIL-OPT
+// need to lower checked_cast_addr_br(addr) into IR for this
+// %target-swift-frontend %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -O -emit-ir -module-name pgo_checked_cast -o - | %FileCheck %s --check-prefix=IR-OPT
+
+// REQUIRES: profile_runtime
+// REQUIRES: OS=macosx
+
+// SIL-LABEL: // pgo_checked_cast.check1<A>(Any, A) -> A
+// SIL-LABEL: sil @_T016pgo_checked_cast6check1xyp_xtlF : $@convention(thin) <T> (@in Any, @in T) -> @out T !function_entry_count(5001) {
+// IR-LABEL: define swiftcc i32 @_T06pgo_checked_cast6guess1s5Int32VAD1x_tF
+// IR-OPT-LABEL: define swiftcc i32 @_T06pgo_checked_cast6guess1s5Int32VAD1x_tF
+public func check1<T>(_ a : Any, _ t : T) -> T {
+ // SIL: checked_cast_addr_br take_always Any in {{.*}} : $*Any to T in {{.*}} : $*T, {{.*}}, {{.*}} !true_count(5000) !false_count(1)
+ // SIL-OPT: checked_cast_addr_br take_always Any in {{.*}} : $*Any to T in {{.*}} : $*T, {{.*}}, {{.*}} !true_count(5000) !false_count(1)
+ if let x = a as? T {
+ return x
+ } else {
+ return t
+ }
+}
+
+public class B {}
+public class C : B {}
+public class D : C {}
+
+// SIL-LABEL: // pgo_checked_cast.check2(pgo_checked_cast.B) -> Swift.Int32
+// SIL-LABEL: sil @_T016pgo_checked_cast6check2s5Int32VAA1BCF : $@convention(thin) (@owned B) -> Int32 !function_entry_count(5003) {
+// IR-LABEL: define swiftcc i32 @_T06pgo_checked_cast6guess1s5Int32VAD1x_tF
+// IR-OPT-LABEL: define swiftcc i32 @_T06pgo_checked_cast6guess1s5Int32VAD1x_tF
+public func check2(_ a : B) -> Int32 {
+ // SIL: checked_cast_br %0 : $B to $D, {{.*}}, {{.*}} !true_count(5000)
+ // SIL: checked_cast_br %0 : $B to $C, {{.*}}, {{.*}} !true_count(2)
+ // SIL-OPT: checked_cast_br %0 : $B to $D, {{.*}}, {{.*}} !true_count(5000)
+ // SIL-OPT: checked_cast_br %0 : $B to $C, {{.*}}, {{.*}} !true_count(2)
+ switch a {
+ case is D:
+ return 42
+ case is C:
+ return 23
+ default:
+ return 13
+ }
+}
+
+func main() {
+ let answer : Int32 = 42
+ var sum : Int32 = 0
+
+ sum += check1("The answer to the life, the universe, and everything", answer)
+
+ sum += check2(B())
+ sum += check2(C())
+ sum += check2(C())
+
+ for i : Int32 in 1...5000 {
+ sum += check1(i, answer)
+ sum += check2(D())
+ }
+}
+
+main()
+
+// IR: !{!"branch_weights", i32 5001, i32 2}
+// IR-OPT: !{!"branch_weights", i32 5001, i32 2}
diff --git a/test/SILGen/pgo_foreach.swift b/test/SILGen/pgo_foreach.swift
new file mode 100644
index 0000000..2ab281c
--- /dev/null
+++ b/test/SILGen/pgo_foreach.swift
@@ -0,0 +1,68 @@
+// RUN: rm -rf %t && mkdir %t
+// RUN: %target-build-swift %s -profile-generate -Xfrontend -disable-incremental-llvm-codegen -module-name pgo_foreach -o %t/main
+// RUN: env LLVM_PROFILE_FILE=%t/default.profraw %target-run %t/main
+// RUN: %llvm-profdata merge %t/default.profraw -o %t/default.profdata
+// need to move counts attached to expr for this
+// RUN: %target-swift-frontend %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -emit-sorted-sil -emit-sil -module-name pgo_foreach -o - | %FileCheck %s --check-prefix=SIL
+// need to lower switch_enum(addr) into IR for this
+// %target-swift-frontend %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -emit-ir -module-name pgo_foreach -o - | %FileCheck %s --check-prefix=IR
+// need to check Opt support
+// %target-swift-frontend %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -O -emit-sorted-sil -emit-sil -module-name pgo_foreach -o - | %FileCheck %s --check-prefix=SIL-OPT
+// need to lower switch_enum(addr) into IR for this
+// %target-swift-frontend %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -O -emit-ir -module-name pgo_foreach -o - | %FileCheck %s --check-prefix=IR-OPT
+
+// REQUIRES: profile_runtime
+// REQUIRES: OS=macosx
+
+// SIL-LABEL: // pgo_foreach.guessForEach1
+// SIL-LABEL: sil @_T011pgo_foreach13guessForEach1s5Int32VAD1x_tF : $@convention(thin) (Int32) -> Int32 !function_entry_count(42) {
+// IR-LABEL: define swiftcc i32 @_T09pgo_foreach10guessWhiles5Int32VAD1x_tF
+// IR-OPT-LABEL: define swiftcc i32 @_T09pgo_foreach10guessWhiles5Int32VAD1x_tF
+
+public func guessForEach1(x: Int32) -> Int32 {
+ // SIL: switch_enum {{.*}} : $Optional<Int32>, case #Optional.some!enumelt.1: {{.*}} !case_count(798), case #Optional.none!enumelt: {{.*}} !case_count(42)
+
+ var ret : Int32 = 0
+ for currVal in stride(from: 5, to: x, by: 5) {
+ ret += currVal
+ }
+ return ret
+}
+
+// SIL-LABEL: // pgo_foreach.guessForEach2
+// SIL-LABEL: sil @_T011pgo_foreach13guessForEach2s5Int32VAD1x_tF : $@convention(thin) (Int32) -> Int32 !function_entry_count(42) {
+// IR-LABEL: define swiftcc i32 @_T09pgo_foreach10guessWhiles5Int32VAD1x_tF
+// IR-OPT-LABEL: define swiftcc i32 @_T09pgo_foreach10guessWhiles5Int32VAD1x_tF
+
+public func guessForEach2(x: Int32) -> Int32 {
+ // SIL: switch_enum {{.*}} : $Optional<(String, Int32)>, case #Optional.some!enumelt.1: {{.*}} !case_count(168), case #Optional.none!enumelt: {{.*}} !case_count(42)
+
+ var ret : Int32 = 0
+ let names = ["John" : Int32(1), "Paul" : Int32(2), "George" : Int32(3), "Ringo" : Int32(x)]
+ for (name, number) in names {
+ ret += Int32(name.count)
+ ret += number
+ }
+ return ret
+}
+
+// SIL-LABEL: // pgo_foreach.main()
+// IR-LABEL: define swiftcc i32 @_T09pgo_foreach10guessWhiles5Int32VAD1x_tF
+// IR-OPT-LABEL: define swiftcc i32 @_T09pgo_foreach10guessWhiles5Int32VAD1x_tF
+
+func main() {
+ // SIL: switch_enum {{.*}} : $Optional<Int>, case #Optional.some!enumelt.1: {{.*}} !case_count(42), case #Optional.none!enumelt: {{.*}} !case_count(1)
+ var guesses : Int32 = 0;
+
+ for _ in 1...42 {
+ guesses += guessForEach1(x: 100)
+ guesses += guessForEach2(x: 100)
+ }
+}
+
+main()
+
+// IR: !{!"branch_weights", i32 421, i32 43}
+// IR: !{!"branch_weights", i32 176401, i32 421}
+// IR-OPT: !{!"branch_weights", i32 421, i32 43}
+// IR-OPT: !{!"branch_weights", i32 176401, i32 421}
diff --git a/test/SILGen/pgo_guard.swift b/test/SILGen/pgo_guard.swift
new file mode 100644
index 0000000..0b79a52
--- /dev/null
+++ b/test/SILGen/pgo_guard.swift
@@ -0,0 +1,44 @@
+// RUN: rm -rf %t && mkdir %t
+// RUN: %target-build-swift %s -profile-generate -Xfrontend -disable-incremental-llvm-codegen -module-name pgo_guard -o %t/main
+// RUN: env LLVM_PROFILE_FILE=%t/default.profraw %target-run %t/main
+// RUN: %llvm-profdata merge %t/default.profraw -o %t/default.profdata
+// RUN: %target-swift-frontend %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -emit-sorted-sil -emit-sil -module-name pgo_guard -o - | %FileCheck %s --check-prefix=SIL
+// RUN: %target-swift-frontend %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -emit-ir -module-name pgo_guard -o - | %FileCheck %s --check-prefix=IR
+// RUN: %target-swift-frontend %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -O -emit-sorted-sil -emit-sil -module-name pgo_guard -o - | %FileCheck %s --check-prefix=SIL-OPT
+// RUN: %target-swift-frontend %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -O -emit-ir -module-name pgo_guard -o - | %FileCheck %s --check-prefix=IR-OPT
+
+// REQUIRES: profile_runtime
+// REQUIRES: OS=macosx
+
+// SIL-LABEL: // pgo_guard.guess1
+// SIL-LABEL: sil @_T09pgo_guard6guess1s5Int32VAD1x_tF : $@convention(thin) (Int32) -> Int32 !function_entry_count(5002) {
+// IR-LABEL: define swiftcc i32 @_T09pgo_guard6guess1s5Int32VAD1x_tF
+// IR-OPT-LABEL: define swiftcc i32 @_T09pgo_guard6guess1s5Int32VAD1x_tF
+
+public func guess1(x: Int32) -> Int32 {
+ // SIL: cond_br {{.*}} !true_count(5000) !false_count(2)
+ // SIL-OPT: cond_br {{.*}} !true_count(5000) !false_count(2)
+
+ // IR: br {{.*}}, !prof ![[BWMD:[0-9]+]]
+ guard (x == 10) else {
+ return 30
+ }
+ return 20
+}
+
+
+func main() {
+ var guesses : Int32 = 0;
+
+ guesses += guess1(x: 0)
+ guesses += guess1(x: 42)
+
+ for _ in 1...5000 {
+ guesses += guess1(x: 10)
+ }
+}
+
+main()
+
+// IR: !{!"branch_weights", i32 5001, i32 3}
+// IR-OPT: !{!"branch_weights", i32 5001, i32 3}
diff --git a/test/SILGen/pgo_if.swift b/test/SILGen/pgo_if.swift
new file mode 100644
index 0000000..018dc62
--- /dev/null
+++ b/test/SILGen/pgo_if.swift
@@ -0,0 +1,54 @@
+// RUN: rm -rf %t && mkdir %t
+// RUN: %target-build-swift %s -profile-generate -Xfrontend -disable-incremental-llvm-codegen -module-name pgo_if -o %t/main
+// RUN: env LLVM_PROFILE_FILE=%t/default.profraw %target-run %t/main
+// RUN: %llvm-profdata merge %t/default.profraw -o %t/default.profdata
+// RUN: %target-swift-frontend %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -emit-sorted-sil -emit-sil -module-name pgo_if -o - | %FileCheck %s --check-prefix=SIL
+// RUN: %target-swift-frontend %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -emit-ir -module-name pgo_if -o - | %FileCheck %s --check-prefix=IR
+// RUN: %target-swift-frontend %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -O -emit-sorted-sil -emit-sil -module-name pgo_if -o - | %FileCheck %s --check-prefix=SIL-OPT
+// RUN: %target-swift-frontend %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -O -emit-ir -module-name pgo_if -o - | %FileCheck %s --check-prefix=IR-OPT
+
+// REQUIRES: profile_runtime
+// REQUIRES: OS=macosx
+
+// SIL-LABEL: // pgo_if.guess1
+// SIL-LABEL: sil @_T06pgo_if6guess1s5Int32VAD1x_tF : $@convention(thin) (Int32) -> Int32 !function_entry_count(5001) {
+// IR-LABEL: define swiftcc i32 @_T06pgo_if6guess1s5Int32VAD1x_tF
+// IR-OPT-LABEL: define swiftcc i32 @_T06pgo_if6guess1s5Int32VAD1x_tF
+public func guess1(x: Int32) -> Int32 {
+ // SIL: cond_br {{.*}} !true_count(5000) !false_count(1)
+ // SIL-OPT: cond_br {{.*}} !true_count(5000) !false_count(1)
+
+ // IR: br {{.*}}, !prof ![[BWMD:[0-9]+]]
+ if (x == 10) {
+ return 20
+ } else {
+ return 30
+ }
+}
+
+// SIL-LABEL: // pgo_if.guess2
+// SIL-LABEL: sil @_T06pgo_if6guess2s5Int32VAD1x_tF : $@convention(thin) (Int32) -> Int32 !function_entry_count(5001) {
+// IR-LABEL: define swiftcc i32 @_T06pgo_if6guess2s5Int32VAD1x_tF
+// IR-OPT-LABEL: define swiftcc i32 @_T06pgo_if6guess2s5Int32VAD1x_tF
+public func guess2(x: Int32) -> Int32 {
+ // SIL: cond_br {{.*}} !true_count(5000) !false_count(1)
+ // SIL-OPT: cond_br {{.*}} !true_count(5000) !false_count(1)
+
+ // IR: br {{.*}}, !prof ![[BWMD]]
+ return (x == 5) ? 10 : 15
+}
+
+func main() {
+ var guesses : Int32 = 0;
+
+ guesses += guess1(x: 0) + guess2(x: 0)
+
+ for _ in 1...5000 {
+ guesses += guess1(x: 10) + guess2(x: 5)
+ }
+}
+
+main()
+
+// IR: !{!"branch_weights", i32 5001, i32 2}
+// IR-OPT: !{!"branch_weights", i32 5001, i32 2}
diff --git a/test/SILGen/pgo_repeatwhile.swift b/test/SILGen/pgo_repeatwhile.swift
new file mode 100644
index 0000000..e55ddfa
--- /dev/null
+++ b/test/SILGen/pgo_repeatwhile.swift
@@ -0,0 +1,51 @@
+// RUN: rm -rf %t && mkdir %t
+// RUN: %target-build-swift %s -profile-generate -Xfrontend -disable-incremental-llvm-codegen -module-name pgo_repeatwhile -o %t/main
+// RUN: env LLVM_PROFILE_FILE=%t/default.profraw %target-run %t/main
+// RUN: %llvm-profdata merge %t/default.profraw -o %t/default.profdata
+// RUN: %target-swift-frontend %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -emit-sorted-sil -emit-sil -module-name pgo_repeatwhile -o - | %FileCheck %s --check-prefix=SIL
+// RUN: %target-swift-frontend %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -emit-ir -module-name pgo_repeatwhile -o - | %FileCheck %s --check-prefix=IR
+// RUN: %target-swift-frontend %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -O -emit-sorted-sil -emit-sil -module-name pgo_repeatwhile -o - | %FileCheck %s --check-prefix=SIL-OPT
+// need to check Opt support
+// %target-swift-frontend %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -O -emit-ir -module-name pgo_repeatwhile -o - | %FileCheck %s --check-prefix=IR-OPT
+
+// REQUIRES: profile_runtime
+// REQUIRES: OS=macosx
+
+// SIL-LABEL: // pgo_repeatwhile.guessWhile
+// SIL-LABEL: sil @_T015pgo_repeatwhile10guessWhiles5Int32VAD1x_tF : $@convention(thin) (Int32) -> Int32 !function_entry_count(42) {
+// IR-LABEL: define swiftcc i32 @_T015pgo_repeatwhile10guessWhiles5Int32VAD1x_tF
+// IR-OPT-LABEL: define swiftcc i32 @_T015pgo_repeatwhile10guessWhiles5Int32VAD1x_tF
+
+public func guessWhile(x: Int32) -> Int32 {
+ // SIL: cond_br {{.*}} !true_count(176400) !false_count(420)
+ // SIL: cond_br {{.*}} !true_count(420) !false_count(42)
+ // SIL-OPT: cond_br {{.*}} !true_count(176400) !false_count(420)
+ // SIL-OPT: cond_br {{.*}} !true_count(420) !false_count(42)
+
+ var ret : Int32 = 0
+ var currX : Int32 = 0
+ repeat {
+ var currInnerX : Int32 = x*42
+ repeat {
+ ret += currInnerX
+ currInnerX -= 1
+ } while (currInnerX > 0)
+ currX += 1
+ } while (currX < x)
+ return ret
+}
+
+func main() {
+ var guesses : Int32 = 0;
+
+ for _ in 1...42 {
+ guesses += guessWhile(x: 10)
+ }
+}
+
+main()
+
+// IR: !{!"branch_weights", i32 176401, i32 421}
+// IR: !{!"branch_weights", i32 421, i32 43}
+// IR-OPT: !{!"branch_weights", i32 176401, i32 421}
+// IR-OPT: !{!"branch_weights", i32 421, i32 43}
diff --git a/test/SILGen/pgo_switchenum.swift b/test/SILGen/pgo_switchenum.swift
new file mode 100644
index 0000000..079154b
--- /dev/null
+++ b/test/SILGen/pgo_switchenum.swift
@@ -0,0 +1,99 @@
+// RUN: rm -rf %t && mkdir %t
+// RUN: %target-build-swift %s -profile-generate -Xfrontend -disable-incremental-llvm-codegen -module-name pgo_switchenum -o %t/main
+// RUN: env LLVM_PROFILE_FILE=%t/default.profraw %target-run %t/main
+// RUN: %llvm-profdata merge %t/default.profraw -o %t/default.profdata
+// need to move counts attached to expr for this
+// RUN: %target-swift-frontend %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -emit-sorted-sil -emit-sil -module-name pgo_switchenum -o - | %FileCheck %s --check-prefix=SIL
+// need to lower switch_enum(addr) into IR for this
+// %target-swift-frontend %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -emit-ir -module-name pgo_switchenum -o - | %FileCheck %s --check-prefix=IR
+// need to check Opt support
+// %target-swift-frontend %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -O -emit-sorted-sil -emit-sil -module-name pgo_switchenum -o - | %FileCheck %s --check-prefix=SIL-OPT
+// need to lower switch_enum(addr) into IR for this
+// %target-swift-frontend %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -O -emit-ir -module-name pgo_switchenum -o - | %FileCheck %s --check-prefix=IR-OPT
+
+// REQUIRES: profile_runtime
+// REQUIRES: OS=macosx
+
+public enum MaybePair {
+ case Neither
+ case Left(Int32)
+ case Right(String)
+ case Both(Int32, String)
+}
+
+// SIL-LABEL: // pgo_switchenum.guess1
+// SIL-LABEL: sil @_T014pgo_switchenum6guess1s5Int32VAA9MaybePairO1x_tF : $@convention(thin) (@owned MaybePair) -> Int32 !function_entry_count(5011) {
+// IR-LABEL: define swiftcc i32 @_T09pgo_switchenum6guess1s5Int32VAD1x_tF
+// IR-OPT-LABEL: define swiftcc i32 @_T09pgo_switchenum6guess1s5Int32VAD1x_tF
+
+public func guess1(x: MaybePair) -> Int32 {
+ // SIL: switch_enum {{.*}} : $MaybePair, case #MaybePair.Neither!enumelt: {{.*}} !case_count(2), case #MaybePair.Left!enumelt.1: {{.*}} !case_count(5001), case #MaybePair.Right!enumelt.1: {{.*}} !case_count(3), case #MaybePair.Both!enumelt.1: {{.*}} !case_count(5)
+ // SIL-OPT: switch_enum {{.*}} : $MaybePair, case #MaybePair.Neither!enumelt: {{.*}} !case_count(2), case #MaybePair.Left!enumelt.1: {{.*}} !case_count(5001), case #MaybePair.Right!enumelt.1: {{.*}} !case_count(3), case #MaybePair.Both!enumelt.1: {{.*}} !case_count(5)
+ switch x {
+ case .Neither:
+ return 1
+ case let .Left(val):
+ return val*2
+ case let .Right(val):
+ return Int32(val.count)
+ case let .Both(valNum, valStr):
+ return valNum + Int32(valStr.count)
+ }
+}
+
+// SIL-LABEL: // pgo_switchenum.guess2
+// SIL-LABEL: sil @_T014pgo_switchenum6guess2s5Int32VAA9MaybePairO1x_tF : $@convention(thin) (@owned MaybePair) -> Int32 !function_entry_count(5011) {
+public func guess2(x: MaybePair) -> Int32 {
+ // SIL: switch_enum {{.*}} : $MaybePair, case #MaybePair.Neither!enumelt: {{.*}} !case_count(2), case #MaybePair.Left!enumelt.1: {{.*}} !case_count(5001), default {{.*}} !default_count(8)
+ // SIL-OPT: switch_enum {{.*}} : $MaybePair, case #MaybePair.Neither!enumelt: {{.*}} !case_count(2), case #MaybePair.Left!enumelt.1: {{.*}} !case_count(5001), default {{.*}} !default_count(8)
+ switch x {
+ case .Neither:
+ return 1
+ case let .Left(val):
+ return val*2
+ default:
+ return 42;
+ }
+}
+
+
+func main() {
+ var guesses : Int32 = 0;
+
+ guesses += guess1(x: MaybePair.Neither)
+ guesses += guess1(x: MaybePair.Neither)
+ guesses += guess1(x: MaybePair.Left(42))
+ guesses += guess1(x: MaybePair.Right("The Answer"))
+ guesses += guess1(x: MaybePair.Right("The Answer"))
+ guesses += guess1(x: MaybePair.Right("The Answer"))
+ guesses += guess1(x: MaybePair.Both(42, "The Answer"))
+ guesses += guess1(x: MaybePair.Both(42, "The Answer"))
+ guesses += guess1(x: MaybePair.Both(42, "The Answer"))
+ guesses += guess1(x: MaybePair.Both(42, "The Answer"))
+ guesses += guess1(x: MaybePair.Both(42, "The Answer"))
+
+ for _ in 1...5000 {
+ guesses += guess1(x: MaybePair.Left(10))
+ }
+
+ guesses += guess2(x: MaybePair.Neither)
+ guesses += guess2(x: MaybePair.Neither)
+ guesses += guess2(x: MaybePair.Left(42))
+ guesses += guess2(x: MaybePair.Right("The Answer"))
+ guesses += guess2(x: MaybePair.Right("The Answer"))
+ guesses += guess2(x: MaybePair.Right("The Answer"))
+ guesses += guess2(x: MaybePair.Both(42, "The Answer"))
+ guesses += guess2(x: MaybePair.Both(42, "The Answer"))
+ guesses += guess2(x: MaybePair.Both(42, "The Answer"))
+ guesses += guess2(x: MaybePair.Both(42, "The Answer"))
+ guesses += guess2(x: MaybePair.Both(42, "The Answer"))
+
+ for _ in 1...5000 {
+ guesses += guess2(x: MaybePair.Left(10))
+ }
+}
+
+main()
+
+// IR: !{!"branch_weights", i32 5001, i32 3}
+// IR-OPT: !{!"branch_weights", i32 5001, i32 3}
diff --git a/test/SILGen/pgo_while.swift b/test/SILGen/pgo_while.swift
new file mode 100644
index 0000000..20238d7
--- /dev/null
+++ b/test/SILGen/pgo_while.swift
@@ -0,0 +1,51 @@
+// RUN: rm -rf %t && mkdir %t
+// RUN: %target-build-swift %s -profile-generate -Xfrontend -disable-incremental-llvm-codegen -module-name pgo_while -o %t/main
+// RUN: env LLVM_PROFILE_FILE=%t/default.profraw %target-run %t/main
+// RUN: %llvm-profdata merge %t/default.profraw -o %t/default.profdata
+// RUN: %target-swift-frontend %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -emit-sorted-sil -emit-sil -module-name pgo_while -o - | %FileCheck %s --check-prefix=SIL
+// RUN: %target-swift-frontend %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -emit-ir -module-name pgo_while -o - | %FileCheck %s --check-prefix=IR
+// RUN: %target-swift-frontend %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -O -emit-sorted-sil -emit-sil -module-name pgo_while -o - | %FileCheck %s --check-prefix=SIL-OPT
+// need to check Opt support
+// %target-swift-frontend %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -O -emit-ir -module-name pgo_while -o - | %FileCheck %s --check-prefix=IR-OPT
+
+// REQUIRES: profile_runtime
+// REQUIRES: OS=macosx
+
+// SIL-LABEL: // pgo_while.guessWhile
+// SIL-LABEL: sil @_T09pgo_while10guessWhiles5Int32VAD1x_tF : $@convention(thin) (Int32) -> Int32 !function_entry_count(42) {
+// IR-LABEL: define swiftcc i32 @_T09pgo_while10guessWhiles5Int32VAD1x_tF
+// IR-OPT-LABEL: define swiftcc i32 @_T09pgo_while10guessWhiles5Int32VAD1x_tF
+
+public func guessWhile(x: Int32) -> Int32 {
+ // SIL: cond_br {{.*}} !true_count(420) !false_count(42)
+ // SIL: cond_br {{.*}} !true_count(176400) !false_count(420)
+ // SIL-OPT: cond_br {{.*}} !true_count(420) !false_count(42)
+ // SIL-OPT: cond_br {{.*}} !true_count(176400) !false_count(420)
+
+ var ret : Int32 = 0
+ var currX : Int32 = 0
+ while (currX < x) {
+ var currInnerX : Int32 = x*42
+ while (currInnerX > 0) {
+ ret += currInnerX
+ currInnerX -= 1
+ }
+ currX += 1
+ }
+ return ret
+}
+
+func main() {
+ var guesses : Int32 = 0;
+
+ for _ in 1...42 {
+ guesses += guessWhile(x: 10)
+ }
+}
+
+main()
+
+// IR: !{!"branch_weights", i32 421, i32 43}
+// IR: !{!"branch_weights", i32 176401, i32 421}
+// IR-OPT: !{!"branch_weights", i32 421, i32 43}
+// IR-OPT: !{!"branch_weights", i32 176401, i32 421}
diff --git a/test/SILGen/versioned_attribute.swift b/test/SILGen/versioned_attribute.swift
new file mode 100644
index 0000000..5a01525
--- /dev/null
+++ b/test/SILGen/versioned_attribute.swift
@@ -0,0 +1,17 @@
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership -emit-verbose-sil %s | %FileCheck %s
+
+@_versioned class Horse {
+ var mouth: AnyObject?
+}
+
+@_versioned class GiftHorse {
+ var mouth: AnyObject?
+
+ deinit {}
+}
+
+// CHECK-LABEL: sil @_T019versioned_attribute5HorseCfd : $@convention(method) (@guaranteed Horse) -> @owned Builtin.NativeObject
+// CHECK-LABEL: sil @_T019versioned_attribute5HorseCfD : $@convention(method) (@owned Horse) -> ()
+
+// CHEKC-LABEL: sil @_T019versioned_attribute9GiftHorseCfd : $@convention(method) (@guaranteed GiftHorse) -> @owned Builtin.NativeObject
+// CHECK-LABEL: sil @_T019versioned_attribute9GiftHorseCfD : $@convention(method) (@owned GiftHorse) -> ()
diff --git a/test/SILOptimizer/abcopts.sil b/test/SILOptimizer/abcopts.sil
index 79592b8..fb2f530 100644
--- a/test/SILOptimizer/abcopts.sil
+++ b/test/SILOptimizer/abcopts.sil
@@ -133,7 +133,7 @@
// CHECK: apply [[CHECKBOUNDS]]([[IDX4]], {{.*}}[[LD1]]
%26 = ref_to_raw_pointer %5 : $Builtin.NativeObject to $Builtin.RawPointer
%27 = pointer_to_address %26 : $Builtin.RawPointer to [strict] $*Builtin.Int32
- %29 = store %x1 to %27 : $*Builtin.Int32
+ store %x1 to %27 : $*Builtin.Int32
%l4 = load %0 : $*ArrayInt
retain_value %5 : $Builtin.NativeObject
%30 = apply %2(%i4, %102, %l4) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
@@ -141,7 +141,7 @@
// CHECK: [[LD4:%[0-9]+]] = load %0
// CHECK: apply [[CHECKBOUNDS]]([[IDX4]], {{.*}}[[LD4]]
- %98 = dealloc_stack %18 : $*Int32
+ dealloc_stack %18 : $*Int32
%99 = tuple ()
return %99 : $()
// CHECK: return
diff --git a/test/SILOptimizer/access_enforcement_selection.sil b/test/SILOptimizer/access_enforcement_selection.sil
index abb6025..dbf440e 100644
--- a/test/SILOptimizer/access_enforcement_selection.sil
+++ b/test/SILOptimizer/access_enforcement_selection.sil
@@ -61,7 +61,7 @@
end_access %39 : $*Builtin.Int64
destroy_value %2 : ${ var Builtin.Int64 }
%98 = tuple ()
- %99 = return %98 : $()
+ return %98 : $()
}
@@ -95,7 +95,7 @@
end_access %7 : $*Builtin.Int64
destroy_value %2 : ${ var Builtin.Int64 }
%9 = tuple ()
- %10 = return %9 : $()
+ return %9 : $()
}
@@ -132,7 +132,7 @@
destroy_value %16 : ${ var Builtin.Int64 }
destroy_value %2 : ${ var Builtin.Int64 }
%98 = tuple ()
- %99 = return %98 : $()
+ return %98 : $()
}
sil @closure : $@convention(thin) (@owned { var Builtin.Int64 }) -> () {
diff --git a/test/SILOptimizer/access_summary_analysis.sil b/test/SILOptimizer/access_summary_analysis.sil
index be06d6e..0f7d46b 100644
--- a/test/SILOptimizer/access_summary_analysis.sil
+++ b/test/SILOptimizer/access_summary_analysis.sil
@@ -81,10 +81,10 @@
bb0(%0 : $*StructWithStoredProperties):
%1 = begin_access [modify] [unknown] %0: $*StructWithStoredProperties
%2 = struct_element_addr %1 : $*StructWithStoredProperties, #StructWithStoredProperties.f
- %3 = end_access %1 : $*StructWithStoredProperties
+ end_access %1 : $*StructWithStoredProperties
%4 = begin_access [read] [unknown] %0: $*StructWithStoredProperties
%5 = struct_element_addr %4 : $*StructWithStoredProperties, #StructWithStoredProperties.g
- %6 = end_access %4 : $*StructWithStoredProperties
+ end_access %4 : $*StructWithStoredProperties
%7 = tuple ()
return %7 : $()
}
@@ -95,10 +95,10 @@
bb0(%0 : $*(Int, Int)):
%1 = begin_access [modify] [unknown] %0: $*(Int, Int)
%2 = tuple_element_addr %1 : $*(Int, Int), 0
- %3 = end_access %1 : $*(Int, Int)
+ end_access %1 : $*(Int, Int)
%4 = begin_access [read] [unknown] %0: $*(Int, Int)
%5 = tuple_element_addr %4 : $*(Int, Int), 1
- %6 = end_access %4 : $*(Int, Int)
+ end_access %4 : $*(Int, Int)
%7 = tuple ()
return %7 : $()
}
@@ -110,11 +110,11 @@
%1 = begin_access [modify] [unknown] %0: $*StructWithStructWithStoredProperties
%2 = struct_element_addr %1 : $*StructWithStructWithStoredProperties, #StructWithStructWithStoredProperties.a
%3 = struct_element_addr %2 : $*StructWithStoredProperties, #StructWithStoredProperties.f
- %4 = end_access %1 : $*StructWithStructWithStoredProperties
+ end_access %1 : $*StructWithStructWithStoredProperties
%5 = begin_access [modify] [unknown] %0: $*StructWithStructWithStoredProperties
%6 = struct_element_addr %5 : $*StructWithStructWithStoredProperties, #StructWithStructWithStoredProperties.b
%7 = struct_element_addr %6 : $*StructWithStoredProperties, #StructWithStoredProperties.g
- %8 = end_access %5 : $*StructWithStructWithStoredProperties
+ end_access %5 : $*StructWithStructWithStoredProperties
%9 = tuple ()
return %9 : $()
}
@@ -126,10 +126,10 @@
bb0(%0 : $*StructWithStoredProperties):
%1 = begin_access [modify] [unknown] %0: $*StructWithStoredProperties
%2 = struct_element_addr %1 : $*StructWithStoredProperties, #StructWithStoredProperties.g
- %3 = end_access %1 : $*StructWithStoredProperties
+ end_access %1 : $*StructWithStoredProperties
%4 = begin_access [read] [unknown] %0: $*StructWithStoredProperties
%5 = struct_element_addr %4 : $*StructWithStoredProperties, #StructWithStoredProperties.f
- %6 = end_access %4 : $*StructWithStoredProperties
+ end_access %4 : $*StructWithStoredProperties
%7 = tuple ()
return %7 : $()
}
@@ -139,10 +139,10 @@
sil private @accessAggregateDoesNotSubsumeAccessStoredProp : $@convention(thin) (@inout_aliasable StructWithStoredProperties) -> () {
bb0(%0 : $*StructWithStoredProperties):
%1 = begin_access [modify] [unknown] %0: $*StructWithStoredProperties
- %3 = end_access %1 : $*StructWithStoredProperties
+ end_access %1 : $*StructWithStoredProperties
%4 = begin_access [modify] [unknown] %0: $*StructWithStoredProperties
%5 = struct_element_addr %4 : $*StructWithStoredProperties, #StructWithStoredProperties.g
- %6 = end_access %4 : $*StructWithStoredProperties
+ end_access %4 : $*StructWithStoredProperties
%7 = tuple ()
return %7 : $()
}
@@ -153,9 +153,9 @@
bb0(%0 : $*StructWithStoredProperties):
%1 = begin_access [modify] [unknown] %0: $*StructWithStoredProperties
%2 = struct_element_addr %1 : $*StructWithStoredProperties, #StructWithStoredProperties.f
- %3 = end_access %1 : $*StructWithStoredProperties
+ end_access %1 : $*StructWithStoredProperties
%4 = begin_access [modify] [unknown] %0: $*StructWithStoredProperties
- %6 = end_access %4 : $*StructWithStoredProperties
+ end_access %4 : $*StructWithStoredProperties
%7 = tuple ()
return %7 : $()
}
@@ -166,10 +166,10 @@
bb0(%0 : $*StructWithStoredProperties):
%1 = begin_access [read] [unknown] %0: $*StructWithStoredProperties
%2 = struct_element_addr %1 : $*StructWithStoredProperties, #StructWithStoredProperties.f
- %3 = end_access %1 : $*StructWithStoredProperties
+ end_access %1 : $*StructWithStoredProperties
%4 = begin_access [modify] [unknown] %0: $*StructWithStoredProperties
%5 = struct_element_addr %4 : $*StructWithStoredProperties, #StructWithStoredProperties.f
- %6 = end_access %4 : $*StructWithStoredProperties
+ end_access %4 : $*StructWithStoredProperties
%7 = tuple ()
return %7 : $()
}
@@ -241,7 +241,7 @@
sil private @callThrowingClosureThatModifiesCapture : $@convention(thin) (@inout_aliasable Int) -> () {
bb0(%0 : $*Int):
%1 = function_ref @throwingClosureThatModifesCapture : $@convention(thin) (@inout_aliasable Int) -> @error Error
- %2 = try_apply %1(%0) : $@convention(thin) (@inout_aliasable Int) -> @error Error, normal bb1, error bb2
+ try_apply %1(%0) : $@convention(thin) (@inout_aliasable Int) -> @error Error, normal bb1, error bb2
bb1(%3 : $()):
%4 = tuple ()
return %4 : $()
diff --git a/test/SILOptimizer/allocbox_to_stack.sil b/test/SILOptimizer/allocbox_to_stack.sil
index 22ab57b..428caf5 100644
--- a/test/SILOptimizer/allocbox_to_stack.sil
+++ b/test/SILOptimizer/allocbox_to_stack.sil
@@ -17,10 +17,10 @@
bb0(%0 : $Int):
%1 = alloc_box ${ var Int }
%1a = project_box %1 : ${ var Int }, 0
- %2 = store %0 to %1a : $*Int
+ store %0 to %1a : $*Int
%3 = load %1a : $*Int
- %4 = strong_release %1 : ${ var Int }
- %5 = return %3 : $Int
+ strong_release %1 : ${ var Int }
+ return %3 : $Int
// CHECK: alloc_stack
// CHECK-NOT: alloc_box
@@ -33,13 +33,13 @@
bb0(%0 : $Int):
%1 = alloc_box ${ var Int }
%1a = project_box %1 : ${ var Int }, 0
- %2 = store %0 to %1a : $*Int
+ store %0 to %1a : $*Int
%3 = load %1a : $*Int
%1b = project_box %1 : ${ var Int }, 0
%3b = load %1b : $*Int
- %4 = strong_release %1 : ${ var Int }
+ strong_release %1 : ${ var Int }
%r = tuple (%3 : $Int, %3b : $Int)
- %5 = return %r : $(Int, Int)
+ return %r : $(Int, Int)
// CHECK: alloc_stack
// CHECK-NOT: alloc_box
@@ -53,8 +53,8 @@
%1 = alloc_box ${ var Int }
%1a = project_box %1 : ${ var Int }, 0
%3 = load %1a : $*Int
- %4 = strong_release %1 : ${ var Int }
- %5 = return %3 : $Int
+ strong_release %1 : ${ var Int }
+ return %3 : $Int
// CHECK: %0 = alloc_stack
// CHECK-NOT: alloc_box
@@ -71,13 +71,13 @@
%1a = mark_uninitialized [rootself] %1 : ${ var Int }
%2 = project_box %1a : ${ var Int }, 0
%3 = load %2 : $*Int
- %x = strong_retain %1a : ${ var Int }
- %y = strong_release %1a : ${ var Int }
- %b = br bb1
+ strong_retain %1a : ${ var Int }
+ strong_release %1a : ${ var Int }
+ br bb1
bb1:
- %4 = strong_release %1a : ${ var Int }
- %5 = return %3 : $Int
+ strong_release %1a : ${ var Int }
+ return %3 : $Int
// CHECK: %0 = alloc_stack
// CHECK: bb1:
@@ -100,18 +100,18 @@
%aa = project_box %a : ${ var (Int, Int) }, 0
%2 = struct_element_addr %1a : $*TestStruct, #TestStruct.Elt
- %3 = store %0 to %2 : $*Int
+ store %0 to %2 : $*Int
%b = tuple_element_addr %aa : $*(Int, Int), 0
- %c = store %0 to %b : $*Int
+ store %0 to %b : $*Int
%6 = struct_element_addr %1a : $*TestStruct, #TestStruct.Elt
%7 = load %6 : $*Int
- %x = strong_release %a : ${ var (Int, Int) }
- %8 = strong_release %1 : ${ var TestStruct }
+ strong_release %a : ${ var (Int, Int) }
+ strong_release %1 : ${ var TestStruct }
- %9 = return %7 : $Int
+ return %7 : $Int
// CHECK-DAG: dealloc_stack [[STRUCT]]
// CHECK-DAG: dealloc_stack [[TUPLE]]
@@ -132,11 +132,11 @@
%6 = function_ref @callee : $@convention(thin) (@inout Int) -> ()
%7 = apply %6(%1a) : $@convention(thin) (@inout Int) -> ()
%8 = load %1a : $*Int
- %9 = strong_release %1 : ${ var Int }
+ strong_release %1 : ${ var Int }
%10 = address_to_pointer %1a : $*Int to $Builtin.RawPointer
%11 = pointer_to_address %10 : $Builtin.RawPointer to [strict] $*Int
%12 = load %11 : $*Int
- %13 = return %8 : $Int
+ return %8 : $Int
// CHECK: return
}
@@ -154,9 +154,9 @@
%2 = alloc_box ${ var P }
%2a = project_box %2 : ${ var P }, 0
%3 = apply %1(%2a) : $@convention(thin) () -> @out P
- %5 = strong_release %2 : ${ var P }
+ strong_release %2 : ${ var P }
%0 = tuple ()
- %6 = return %0 : $()
+ return %0 : $()
// CHECK: return
}
@@ -167,10 +167,10 @@
bb0(%0 : $SomeClass):
%1 = alloc_box ${ var SomeClass }
%1a = project_box %1 : ${ var SomeClass }, 0
- %2 = store %0 to %1a : $*SomeClass
+ store %0 to %1a : $*SomeClass
%3 = load %1a : $*SomeClass
- %4 = strong_release %1 : ${ var SomeClass }
- %5 = return %3 : $SomeClass
+ strong_release %1 : ${ var SomeClass }
+ return %3 : $SomeClass
// CHECK: %1 = alloc_stack
// CHECK-NOT: alloc_box
@@ -212,7 +212,7 @@
dealloc_box %1 : $<τ_0_0> { var Generic<τ_0_0> } <T>
%0 = tuple () // CHECK: tuple ()
- %6 = return %0 : $()
+ return %0 : $()
// CHECK: return
}
@@ -779,7 +779,7 @@
bb2:
%1a = project_box %1 : ${ var Int }, 0
- %2 = store %0 to %1a : $*Int
+ store %0 to %1a : $*Int
dealloc_stack %as1 : $*Bool
%3 = load %1a : $*Int
%as2 = alloc_stack $Bool
@@ -789,7 +789,7 @@
bb3:
%r = tuple ()
- %5 = return %r : $()
+ return %r : $()
}
// CHECK-LABEL: sil @wrong_nesting_with_alloc_ref
@@ -806,12 +806,12 @@
%as1 = alloc_ref [stack] $SomeClass
%1 = alloc_box ${ var Int }
%1a = project_box %1 : ${ var Int }, 0
- %2 = store %0 to %1a : $*Int
+ store %0 to %1a : $*Int
dealloc_ref [stack] %as1 : $SomeClass
%3 = load %1a : $*Int
strong_release %1 : ${ var Int }
%r = tuple ()
- %5 = return %r : $()
+ return %r : $()
}
// CHECK-LABEL: sil @nesting_and_unreachable1
@@ -841,12 +841,12 @@
unreachable
bb2:
- %2 = store %0 to %1a : $*Int
+ store %0 to %1a : $*Int
dealloc_stack %as1 : $*Bool
%3 = load %1a : $*Int
strong_release %1 : ${ var Int }
%r = tuple ()
- %5 = return %r : $()
+ return %r : $()
}
// CHECK-LABEL: sil @nesting_and_unreachable2
@@ -879,12 +879,12 @@
unreachable
bb2:
- %2 = store %0 to %1a : $*Int
+ store %0 to %1a : $*Int
dealloc_stack %as1 : $*Bool
%3 = load %1a : $*Int
strong_release %1 : ${ var Int }
%r = tuple ()
- %5 = return %r : $()
+ return %r : $()
}
// CHECK-LABEL: sil @nesting_and_unreachable3
@@ -913,12 +913,12 @@
unreachable
bb2:
- %2 = store %0 to %1a : $*Int
+ store %0 to %1a : $*Int
%3 = load %1a : $*Int
dealloc_stack %as1 : $*Bool
strong_release %1 : ${ var Int }
%r = tuple ()
- %5 = return %r : $()
+ return %r : $()
}
// CHECK-LABEL: sil @nesting_and_unreachable4
@@ -941,11 +941,11 @@
unreachable
bb2:
- %2 = store %0 to %1a : $*Int
+ store %0 to %1a : $*Int
%3 = load %1a : $*Int
strong_release %1 : ${ var Int }
%r = tuple ()
- %5 = return %r : $()
+ return %r : $()
}
// CHECK-LABEL: sil @nesting_and_unreachable5
@@ -972,11 +972,11 @@
unreachable
bb2:
- %2 = store %0 to %1a : $*Int
+ store %0 to %1a : $*Int
%3 = load %1a : $*Int
strong_release %1 : ${ var Int }
%r = tuple ()
- %5 = return %r : $()
+ return %r : $()
}
// CHECK-LABEL: sil @nesting_and_unreachable_critical_edge
@@ -1016,13 +1016,13 @@
cond_br undef, bb2, bb3
bb2:
- %2 = store %0 to %1a : $*Int
+ store %0 to %1a : $*Int
%3 = load %1a : $*Int
dealloc_stack %as2 : $*Bool
dealloc_stack %as1 : $*Bool
strong_release %1 : ${ var Int }
%r = tuple ()
- %5 = return %r : $()
+ return %r : $()
bb3:
strong_release %1 : ${ var Int }
diff --git a/test/SILOptimizer/allocbox_to_stack_ownership.sil b/test/SILOptimizer/allocbox_to_stack_ownership.sil
index ef260ed..3511621 100644
--- a/test/SILOptimizer/allocbox_to_stack_ownership.sil
+++ b/test/SILOptimizer/allocbox_to_stack_ownership.sil
@@ -17,7 +17,7 @@
bb0(%0 : @trivial $Int):
%1 = alloc_box ${ var Int }
%1a = project_box %1 : ${ var Int }, 0
- %2 = store %0 to [trivial] %1a : $*Int
+ store %0 to [trivial] %1a : $*Int
%3 = load [trivial] %1a : $*Int
destroy_value %1 : ${ var Int }
@@ -33,7 +33,7 @@
bb0(%0 : @trivial $Int):
%1 = alloc_box ${ var Int }
%1a = project_box %1 : ${ var Int }, 0
- %2 = store %0 to [trivial] %1a : $*Int
+ store %0 to [trivial] %1a : $*Int
%3 = load [trivial] %1a : $*Int
%1b = project_box %1 : ${ var Int }, 0
@@ -54,8 +54,8 @@
%1 = alloc_box ${ var Int }
%1a = project_box %1 : ${ var Int }, 0
%3 = load [trivial] %1a : $*Int
- %4 = destroy_value %1 : ${ var Int }
- %5 = return %3 : $Int
+ destroy_value %1 : ${ var Int }
+ return %3 : $Int
// CHECK: %0 = alloc_stack
// CHECK-NOT: alloc_box
@@ -78,7 +78,7 @@
bb1:
destroy_value %x : ${ var Int }
- %5 = return %3 : $Int
+ return %3 : $Int
// CHECK: %0 = alloc_stack
// CHECK: bb1:
@@ -101,17 +101,17 @@
%aa = project_box %a : ${ var (Int, Int) }, 0
%2 = struct_element_addr %1a : $*TestStruct, #TestStruct.Elt
- %3 = store %0 to [trivial] %2 : $*Int
+ store %0 to [trivial] %2 : $*Int
%b = tuple_element_addr %aa : $*(Int, Int), 0
- %c = store %0 to [trivial] %b : $*Int
+ store %0 to [trivial] %b : $*Int
%6 = struct_element_addr %1a : $*TestStruct, #TestStruct.Elt
%7 = load [trivial] %6 : $*Int
destroy_value %a : ${ var (Int, Int) }
destroy_value %1 : ${ var TestStruct }
- %9 = return %7 : $Int
+ return %7 : $Int
// CHECK-DAG: dealloc_stack [[STRUCT]]
// CHECK-DAG: dealloc_stack [[TUPLE]]
@@ -133,7 +133,7 @@
%10 = address_to_pointer %1a : $*Int to $Builtin.RawPointer
%11 = pointer_to_address %10 : $Builtin.RawPointer to [strict] $*Int
%12 = load [trivial] %11 : $*Int
- %13 = return %8 : $Int
+ return %8 : $Int
// CHECK: return
}
@@ -152,7 +152,7 @@
%3 = apply %1(%2a) : $@convention(thin) () -> @out P
destroy_value %2 : ${ var P }
%0 = tuple ()
- %6 = return %0 : $()
+ return %0 : $()
// CHECK: return
}
@@ -208,7 +208,7 @@
dealloc_box %1 : $<τ_0_0> { var Generic<τ_0_0> } <T>
%0 = tuple () // CHECK: tuple ()
- %6 = return %0 : $()
+ return %0 : $()
// CHECK: return
}
@@ -774,7 +774,7 @@
bb2:
%1a = project_box %1 : ${ var Int }, 0
- %2 = store %0 to [trivial] %1a : $*Int
+ store %0 to [trivial] %1a : $*Int
dealloc_stack %as1 : $*Bool
%3 = load [trivial] %1a : $*Int
%as2 = alloc_stack $Bool
@@ -784,7 +784,7 @@
bb3:
%r = tuple ()
- %5 = return %r : $()
+ return %r : $()
}
// CHECK-LABEL: sil @wrong_nesting_with_alloc_ref
@@ -806,7 +806,7 @@
%3 = load [trivial] %1a : $*Int
destroy_value %1 : ${ var Int }
%r = tuple ()
- %5 = return %r : $()
+ return %r : $()
}
// CHECK-LABEL: sil @nesting_and_unreachable1
@@ -841,7 +841,7 @@
%3 = load [trivial] %1a : $*Int
destroy_value %1 : ${ var Int }
%r = tuple ()
- %5 = return %r : $()
+ return %r : $()
}
// CHECK-LABEL: sil @nesting_and_unreachable2
@@ -874,12 +874,12 @@
unreachable
bb2:
- %2 = store %0 to [trivial] %1a : $*Int
+ store %0 to [trivial] %1a : $*Int
dealloc_stack %as1 : $*Bool
%3 = load [trivial] %1a : $*Int
destroy_value %1 : ${ var Int }
%r = tuple ()
- %5 = return %r : $()
+ return %r : $()
}
// CHECK-LABEL: sil @nesting_and_unreachable3
@@ -913,7 +913,7 @@
dealloc_stack %as1 : $*Bool
destroy_value %1 : ${ var Int }
%r = tuple ()
- %5 = return %r : $()
+ return %r : $()
}
// CHECK-LABEL: sil @nesting_and_unreachable4
@@ -936,11 +936,11 @@
unreachable
bb2:
- %2 = store %0 to [trivial] %1a : $*Int
+ store %0 to [trivial] %1a : $*Int
%3 = load [trivial] %1a : $*Int
destroy_value %1 : ${ var Int }
%r = tuple ()
- %5 = return %r : $()
+ return %r : $()
}
// CHECK-LABEL: sil @nesting_and_unreachable5
@@ -967,11 +967,11 @@
unreachable
bb2:
- %2 = store %0 to [trivial] %1a : $*Int
+ store %0 to [trivial] %1a : $*Int
%3 = load [trivial] %1a : $*Int
destroy_value %1 : ${ var Int }
%r = tuple ()
- %5 = return %r : $()
+ return %r : $()
}
// CHECK-LABEL: sil @nesting_and_unreachable_critical_edge
@@ -1011,13 +1011,13 @@
cond_br undef, bb2, bb3
bb2:
- %2 = store %0 to [trivial] %1a : $*Int
+ store %0 to [trivial] %1a : $*Int
%3 = load [trivial] %1a : $*Int
dealloc_stack %as2 : $*Bool
dealloc_stack %as1 : $*Bool
destroy_value %1 : ${ var Int }
%r = tuple ()
- %5 = return %r : $()
+ return %r : $()
bb3:
destroy_value %1 : ${ var Int }
diff --git a/test/SILOptimizer/array_specialize.sil b/test/SILOptimizer/array_specialize.sil
index c39d77d..fdab0ed 100644
--- a/test/SILOptimizer/array_specialize.sil
+++ b/test/SILOptimizer/array_specialize.sil
@@ -109,3 +109,70 @@
bb5(%9 : $Error):
throw %9 : $Error
}
+
+sil @dominator_update_outside_non_exit_block : $@convention(thin) (@inout MyArray<MyClass>, @inout Builtin.Int1) -> Builtin.Int1 {
+bb0(%0 : $*MyArray<MyClass>, %1 : $*Builtin.Int1):
+ %3 = load %0 : $*MyArray<MyClass>
+ br bb1
+
+bb1:
+ %2 = function_ref @arrayPropertyIsNative : $@convention(method) (@owned MyArray<MyClass>) -> Bool
+ %4 = load %1 : $*Builtin.Int1
+ retain_value %3 : $MyArray<MyClass>
+ %5 = apply %2(%3) : $@convention(method) (@owned MyArray<MyClass>) -> Bool
+ cond_br %4, bb2, bb4
+
+bb2:
+ cond_br undef, bb3, bb5
+
+bb3:
+ %6 = integer_literal $Builtin.Int1, -1
+ cond_br %6, bb1, bb7
+
+bb4: // Exit block; b1 dom b4
+ cond_br undef, bb5, bb6
+
+bb5: // Exit Block; b1 dom b4
+ br bb6
+
+bb6: // Non-exit Dominated by bb1
+ br bb7
+
+bb7:
+ return %4 : $Builtin.Int1
+}
+
+sil @dominator_update_outside_non_exit_block_2 : $@convention(thin) (@inout MyArray<MyClass>, @inout Builtin.Int1) -> Builtin.Int1 {
+bb0(%0 : $*MyArray<MyClass>, %1 : $*Builtin.Int1):
+ %3 = load %0 : $*MyArray<MyClass>
+ br bb1
+
+bb1:
+ %2 = function_ref @arrayPropertyIsNative : $@convention(method) (@owned MyArray<MyClass>) -> Bool
+ %4 = load %1 : $*Builtin.Int1
+ retain_value %3 : $MyArray<MyClass>
+ %5 = apply %2(%3) : $@convention(method) (@owned MyArray<MyClass>) -> Bool
+ cond_br %4, bb2, bb4
+
+bb2:
+ cond_br undef, bb3, bb5
+
+bb3:
+ %6 = integer_literal $Builtin.Int1, -1
+ cond_br %6, bb1, bb7
+
+bb4: // Exit block; b1 dom b4
+ cond_br undef, bb5, bb6
+
+bb5: // Exit Block; b1 dom b4
+ br bb6
+
+bb6: // Non-exit Dominated by bb1
+ br bb8
+
+bb7: // Exit dominated by bb3
+ br bb8
+
+bb8: // Non-exit dominated by bb1
+ return %4 : $Builtin.Int1
+}
diff --git a/test/SILOptimizer/cast_foldings.sil b/test/SILOptimizer/cast_foldings.sil
index 6c45892..0a9bde5 100644
--- a/test/SILOptimizer/cast_foldings.sil
+++ b/test/SILOptimizer/cast_foldings.sil
@@ -35,7 +35,7 @@
// CHECK: store
sil @function_cast_nothrow_to_nothrow : $@convention(thin) <T> () -> () {
entry:
- %a = unconditional_checked_cast_addr () -> () in undef : $*(@in ()) -> @out () to () -> () in undef : $*(@in ()) -> @out ()
+ unconditional_checked_cast_addr () -> () in undef : $*(@in ()) -> @out () to () -> () in undef : $*(@in ()) -> @out ()
return undef : $()
}
@@ -43,7 +43,7 @@
// CHECK: unconditional_checked_cast_addr
sil @function_cast_nothrow_to_nothrow_substitutable : $@convention(thin) <T> () -> () {
entry:
- %a = unconditional_checked_cast_addr () -> () in undef : $*(@in ()) -> @out () to (T) -> T in undef : $*(@in T) -> @out T
+ unconditional_checked_cast_addr () -> () in undef : $*(@in ()) -> @out () to (T) -> T in undef : $*(@in T) -> @out T
return undef : $()
}
@@ -51,14 +51,15 @@
// CHECK: unconditional_checked_cast_addr
sil @function_cast_nothrow_substitutable_to_nothrow : $@convention(thin) <T> () -> () {
entry:
- %a = unconditional_checked_cast_addr (T) -> T in undef : $*(@in T) -> @out T to () -> () in undef : $*(@in ()) -> @out ()
+ unconditional_checked_cast_addr (T) -> T in undef : $*(@in T) -> @out T to () -> () in undef : $*(@in ()) -> @out ()
return undef : $()
}
// CHECK-LABEL: sil @function_cast_throw_to_nothrow
// CHECK: builtin "int_trap"
sil @function_cast_throw_to_nothrow : $@convention(thin) <T> () -> () {
- %b = unconditional_checked_cast_addr () throws -> () in undef : $*(@in ()) -> (@out (), @error Error) to () -> () in undef : $*(@in ()) -> @out ()
+entry:
+ unconditional_checked_cast_addr () throws -> () in undef : $*(@in ()) -> (@out (), @error Error) to () -> () in undef : $*(@in ()) -> @out ()
return undef : $()
}
@@ -66,7 +67,8 @@
// CHECK-LABEL: sil @function_cast_nothrow_to_throw
// CHECK: unconditional_checked_cast_addr
sil @function_cast_nothrow_to_throw : $@convention(thin) <T> () -> () {
- %c = unconditional_checked_cast_addr () -> () in undef : $*(@in ()) -> @out () to () throws -> () in undef : $*(@in ()) -> (@out (), @error Error)
+entry:
+ unconditional_checked_cast_addr () -> () in undef : $*(@in ()) -> @out () to () throws -> () in undef : $*(@in ()) -> (@out (), @error Error)
return undef : $()
}
@@ -74,7 +76,8 @@
// CHECK: load
// CHECK: store
sil @function_cast_throw_to_throw : $@convention(thin) <T> () -> () {
- %d = unconditional_checked_cast_addr () throws -> () in undef : $*(@in ()) -> (@out (), @error Error) to () throws -> () in undef : $*(@in ()) -> (@out (), @error Error)
+entry:
+ unconditional_checked_cast_addr () throws -> () in undef : $*(@in ()) -> (@out (), @error Error) to () throws -> () in undef : $*(@in ()) -> (@out (), @error Error)
return undef : $()
}
diff --git a/test/SILOptimizer/cse.sil b/test/SILOptimizer/cse.sil
index f101457..d098716 100644
--- a/test/SILOptimizer/cse.sil
+++ b/test/SILOptimizer/cse.sil
@@ -112,17 +112,17 @@
bb0(%0 : $B):
%1 = alloc_box $<τ_0_0> { var τ_0_0 } <B>
%1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <B>, 0
- %2 = store %0 to %1a : $*B
+ store %0 to %1a : $*B
%3 = load %1a : $*B
- %4 = strong_retain %3 : $B
+ strong_retain %3 : $B
%5 = unchecked_ref_cast %3 : $B to $Builtin.NativeObject
- %7 = strong_release %3 : $B
- %8 = strong_release %1 : $<τ_0_0> { var τ_0_0 } <B>
+ strong_release %3 : $B
+ strong_release %1 : $<τ_0_0> { var τ_0_0 } <B>
%9 = function_ref @exit : $@convention(thin) () -> Never // ret.exit : () -> ()
%10 = apply %9() : $@convention(thin) () -> Never
%6 = unchecked_ref_cast %5 : $Builtin.NativeObject to $B
%11 = tuple()
- %12 = return %11 : $()
+ return %11 : $()
}
// CHECK-LABEL: sil @removeTriviallyDeadCrossBasicBlocks
@@ -132,15 +132,15 @@
sil @removeTriviallyDeadCrossBasicBlocks : $@convention(thin) (@owned B, Builtin.Int1) -> () {
bb0(%0: $B, %1: $Builtin.Int1):
%5 = unchecked_ref_cast %0 : $B to $Builtin.NativeObject
- %13 = cond_br %1, bb1, bb2
+ cond_br %1, bb1, bb2
bb1:
- %22 = br bb2
+ br bb2
bb2:
%9 = function_ref @exit : $@convention(thin) () -> Never // ret.exit : () -> ()
%10 = apply %9() : $@convention(thin) () -> Never
%21 = unchecked_ref_cast %5 : $Builtin.NativeObject to $B
%32 = tuple ()
- %33 = return %32 : $()
+ return %32 : $()
}
// CHECK-LABEL: sil @dead_use_of_alloc_stack
@@ -710,14 +710,14 @@
bb0(%0: $B, %1: $Builtin.Int1):
%5 = unchecked_ref_cast %0 : $B to $Builtin.NativeObject
strong_release %5 : $Builtin.NativeObject
- %13 = cond_br %1, bb1, bb2
+ cond_br %1, bb1, bb2
bb1:
- %22 = br bb2
+ br bb2
bb2:
%21 = unchecked_ref_cast %0 : $B to $Builtin.NativeObject
strong_release %21 : $Builtin.NativeObject
%32 = tuple ()
- %33 = return %32 : $()
+ return %32 : $()
}
// CHECK-LABEL: sil @cse_raw_pointer_to_ref
diff --git a/test/SILOptimizer/dead_store_elim.sil b/test/SILOptimizer/dead_store_elim.sil
index 295d9ea..e4d1436 100644
--- a/test/SILOptimizer/dead_store_elim.sil
+++ b/test/SILOptimizer/dead_store_elim.sil
@@ -240,10 +240,10 @@
bb0(%0 : $B):
%1 = alloc_box $<τ_0_0> { var τ_0_0 } <B>
%1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <B>, 0
- %2 = store %0 to %1a : $*B
- %3 = store %0 to %1a : $*B
+ store %0 to %1a : $*B
+ store %0 to %1a : $*B
%4 = tuple()
- %5 = return %4 : $()
+ return %4 : $()
}
// CHECK-LABEL: sil @dead_store_elimination_over_noread_builtins
diff --git a/test/SILOptimizer/definite_init_markuninitialized_var.sil b/test/SILOptimizer/definite_init_markuninitialized_var.sil
index 7306f94..f1eef16 100644
--- a/test/SILOptimizer/definite_init_markuninitialized_var.sil
+++ b/test/SILOptimizer/definite_init_markuninitialized_var.sil
@@ -19,7 +19,7 @@
%1 = mark_uninitialized [var] %0a : $*Int // expected-note {{variable defined here}}
%4 = load [trivial] %1 : $*Int // expected-error {{variable '<unknown>' used before being initialized}}
destroy_value %0 : $<τ_0_0> { var τ_0_0 } <Int>
- %9 = return %4 : $Int
+ return %4 : $Int
}
// CHECK-LABEL: @inout_uninit
@@ -50,7 +50,7 @@
%91 = alloc_box $<τ_0_0> { var τ_0_0 } <Int>
%91a = project_box %91 : $<τ_0_0> { var τ_0_0 } <Int>, 0
%1 = mark_uninitialized [var] %91a : $*Int
- %2 = store %0 to [trivial] %1 : $*Int
+ store %0 to [trivial] %1 : $*Int
%3 = load [trivial] %1 : $*Int
%5 = function_ref @takes_Int_inout : $@convention(thin) (@inout Int) -> ()
@@ -58,7 +58,7 @@
%7 = load [trivial] %1 : $*Int
%8 = tuple (%3 : $Int, %7 : $Int)
destroy_value %91 : $<τ_0_0> { var τ_0_0 } <Int>
- %11 = return %8 : $(Int, Int)
+ return %8 : $(Int, Int)
}
struct AddressOnlyStruct {
diff --git a/test/SILOptimizer/diagnose_unreachable.sil b/test/SILOptimizer/diagnose_unreachable.sil
index 8bb789d..f857c81 100644
--- a/test/SILOptimizer/diagnose_unreachable.sil
+++ b/test/SILOptimizer/diagnose_unreachable.sil
@@ -6,12 +6,12 @@
sil private @test1 : $() -> () {
bb0:
%5 = integer_literal $Builtin.Int1, 1
- %7 = cond_br %5, bb1, bb2
+ cond_br %5, bb1, bb2
bb1: // Preds: bb0
- %8 = br bb2
+ br bb2
bb2: // Preds: bb1 bb0
%9 = tuple ()
- %10 = return %9 : $()
+ return %9 : $()
}
// CHECK-LABEL:@test1
// CHECK: bb0:
@@ -26,12 +26,12 @@
sil @test2 : $@convention(thin) () -> () {
bb0:
%11 = integer_literal $Builtin.Int1, 0
- %13 = cond_br %11, bb1, bb2
+ cond_br %11, bb1, bb2
bb1: // Preds: bb0
- %22 = br bb2
+ br bb2
bb2: // Preds: bb1 bb0
%32 = tuple ()
- %33 = return %32 : $()
+ return %32 : $()
}
// CHECK-LABEL:sil @test2
// CHECK: bb0:
@@ -49,27 +49,27 @@
//}
sil @loopWithFalse : $@convention(thin) () -> () {
bb0:
- %6 = br bb1
+ br bb1
bb1: // Preds: bb4 bb0
%12 = integer_literal $Builtin.Int1, 0
- %14 = cond_br %12, bb2, bb5
+ cond_br %12, bb2, bb5
bb2: // Preds: bb1
%20 = integer_literal $Builtin.Int1, 0
- %22 = cond_br %20, bb3, bb4
+ cond_br %20, bb3, bb4
bb3: // Preds: bb2
br bb6
bb4: // Preds: bb2
- %26 = br bb1
+ br bb1
bb5: // Preds: bb1
br bb6
bb6:
%28 = tuple ()
- %29 = return %28 : $()
+ return %28 : $()
}
// CHECK-LABEL: sil @loopWithFalse
// CHECK: bb0:
@@ -92,28 +92,28 @@
//}
sil @InfLoop : $@convention(thin) () -> () {
bb0:
- %6 = br bb1
+ br bb1
bb1: // Preds: bb4 bb0
%12 = integer_literal $Builtin.Int1, 1
- %14 = cond_br %12, bb2, bb5
+ cond_br %12, bb2, bb5
bb2: // Preds: bb1
%20 = integer_literal $Builtin.Int1, 0
- %22 = cond_br %20, bb3, bb4
+ cond_br %20, bb3, bb4
bb3: // Preds: bb2
br bb6
bb4: // Preds: bb2
- %26 = br bb1
+ br bb1
bb5: // Preds: bb1
br bb6
bb6:
%28 = tuple ()
- %29 = return %28 : $()
+ return %28 : $()
}
// CHECK-LABEL:sil @InfLoop
// CHECK: bb0:
@@ -139,17 +139,17 @@
bb0(%0 : $B):
%1 = alloc_box $<τ_0_0> { var τ_0_0 } <B>
%1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <B>, 0
- %2 = store %0 to %1a : $*B // CHECK: store
+ store %0 to %1a : $*B // CHECK: store
%3 = load %1a : $*B
- %4 = strong_retain %3 : $B // CHECK: strong_retain
+ strong_retain %3 : $B // CHECK: strong_retain
%5 = unchecked_ref_cast %3 : $B to $Builtin.NativeObject // CHECK-NOT: unchecked_ref_cast
- %7 = strong_release %3 : $B // CHECK: strong_release
- %8 = strong_release %1 : $<τ_0_0> { var τ_0_0 } <B> // CHECK-NEXT: strong_release
+ strong_release %3 : $B // CHECK: strong_release
+ strong_release %1 : $<τ_0_0> { var τ_0_0 } <B> // CHECK-NEXT: strong_release
%9 = function_ref @exit : $@convention(thin) () -> Never
%10 = apply %9() : $@convention(thin) () -> Never
%6 = unchecked_ref_cast %5 : $Builtin.NativeObject to $B // CHECK-NOT: unchecked_ref_cast
%11 = tuple()
- %12 = return %11 : $()
+ return %11 : $()
}
// CHECK-LABEL: sil @removeTriviallyDeadButUsedByUnreachableBlock
@@ -157,28 +157,28 @@
bb0(%0 : $B):
%5 = unchecked_ref_cast %0 : $B to $Builtin.NativeObject // CHECK-NOT: unchecked_ref_cast
%11 = integer_literal $Builtin.Int1, 0 // CHECK-NOT: integer_literal
- %13 = cond_br %11, bb1, bb2 // CHECK: br
+ cond_br %11, bb1, bb2 // CHECK: br
bb1:
%21 = unchecked_ref_cast %5 : $Builtin.NativeObject to $B // CHECK-NOT: unchecked_ref_cast
- %22 = br bb2
+ br bb2
bb2:
%32 = tuple ()
- %33 = return %32 : $() // CHECK: return
+ return %32 : $() // CHECK: return
} // CHECK: }
// CHECK-LABEL: sil @removeTriviallyDeadCrossBasicBlocks
sil @removeTriviallyDeadCrossBasicBlocks : $@convention(thin) (@owned B, Builtin.Int1) -> () {
bb0(%0: $B, %1: $Builtin.Int1):
%5 = unchecked_ref_cast %0 : $B to $Builtin.NativeObject // CHECK-NOT: unchecked_ref_cast
- %13 = cond_br %1, bb1, bb2 // CHECK: cond_br
+ cond_br %1, bb1, bb2 // CHECK: cond_br
bb1:
- %22 = br bb2
+ br bb2
bb2:
%9 = function_ref @exit : $@convention(thin) () -> Never
%10 = apply %9() : $@convention(thin) () -> Never
%21 = unchecked_ref_cast %5 : $Builtin.NativeObject to $B // CHECK-NOT: unchecked_ref_cast
%32 = tuple ()
- %33 = return %32 : $()
+ return %32 : $()
} // CHECK: }
sil @testCondBranchBBArgs : $@convention(thin) (Int, Int) -> Int {
@@ -204,7 +204,7 @@
sil @removePredecessorWithBBArgs : $@convention(thin) (Int, Int) -> Int {
bb0(%0 : $Int, %1 : $Int):
%2 = integer_literal $Builtin.Int1, 0
- %3 = cond_br %2, bb2(%0 : $Int), bb3(%1 : $Int)
+ cond_br %2, bb2(%0 : $Int), bb3(%1 : $Int)
bb2(%4 : $Int):
br bb4(%4 : $Int)
bb3(%5 : $Int):
diff --git a/test/SILOptimizer/earlycodemotion.sil b/test/SILOptimizer/earlycodemotion.sil
index d5f26ab..2db1ec9 100644
--- a/test/SILOptimizer/earlycodemotion.sil
+++ b/test/SILOptimizer/earlycodemotion.sil
@@ -88,11 +88,11 @@
cond_br %0, bb1, bb2
bb1:
- %2 = strong_retain %1 : $B
+ strong_retain %1 : $B
br bb3
bb2:
- %3 = strong_retain %1 : $B
+ strong_retain %1 : $B
br bb3
bb3:
@@ -133,12 +133,12 @@
cond_br %0, bb1, bb2
bb1:
- %2 = strong_retain %1 : $B
+ strong_retain %1 : $B
%3 = integer_literal $Builtin.Int32, 9
br bb3(%3 : $Builtin.Int32)
bb2:
- %4 = strong_retain %1 : $B
+ strong_retain %1 : $B
%5 = integer_literal $Builtin.Int32, 7
br bb3(%5 : $Builtin.Int32)
@@ -160,12 +160,12 @@
cond_br %0, bb1, bb2
bb1:
- %2 = strong_retain %1 : $B
+ strong_retain %1 : $B
%3 = integer_literal $Builtin.Int32, 7
br bb3(%3 : $Builtin.Int32)
bb2:
- %4 = strong_retain %1 : $B
+ strong_retain %1 : $B
%5 = integer_literal $Builtin.Int32, 7
br bb3(%5 : $Builtin.Int32)
diff --git a/test/SILOptimizer/escape_analysis.sil b/test/SILOptimizer/escape_analysis.sil
index 7befabe..a36d9ae 100644
--- a/test/SILOptimizer/escape_analysis.sil
+++ b/test/SILOptimizer/escape_analysis.sil
@@ -376,8 +376,8 @@
%2 = function_ref @copy_addr_content : $@convention(thin) (@in_guaranteed Int32) -> @out Int32
%3 = apply %2(%0, %1) : $@convention(thin) (@in_guaranteed Int32) -> @out Int32
%4 = tuple()
- %6 = dealloc_stack %1 : $*Int32
- %5 = dealloc_stack %0 : $*Int32
+ dealloc_stack %1 : $*Int32
+ dealloc_stack %0 : $*Int32
return %4 : $()
}
@@ -808,7 +808,7 @@
%f = function_ref @unknown_set_y : $@convention(thin) () -> @out Y
%a = apply %f(%0) : $@convention(thin) () -> @out Y
%r = load %0 : $*Y
- %5 = dealloc_stack %0 : $*Y
+ dealloc_stack %0 : $*Y
return %r : $Y
}
diff --git a/test/SILOptimizer/latecodemotion.sil b/test/SILOptimizer/latecodemotion.sil
index 5dfb194..1eeff4d 100644
--- a/test/SILOptimizer/latecodemotion.sil
+++ b/test/SILOptimizer/latecodemotion.sil
@@ -65,11 +65,11 @@
cond_br %0, bb1, bb2
bb1:
- %2 = strong_retain %1 : $B
+ strong_retain %1 : $B
br bb3
bb2:
- %3 = strong_retain %1 : $B
+ strong_retain %1 : $B
br bb3
bb3:
@@ -90,11 +90,11 @@
cond_br %0, bb1, bb2
bb1:
- %r1 = strong_retain %1 : $B
+ strong_retain %1 : $B
br bb3(%1 : $B)
bb2:
- %r2 = strong_retain %2 : $B
+ strong_retain %2 : $B
br bb3(%2 : $B)
bb3(%a1 : $B):
@@ -115,11 +115,11 @@
cond_br %0, bb1, bb2
bb1:
- %r1 = strong_retain %1 : $B
+ strong_retain %1 : $B
br bb3(%1 : $B)
bb2:
- %r2 = strong_retain %1 : $B
+ strong_retain %1 : $B
br bb3(%2 : $B)
bb3(%a1 : $B):
@@ -140,11 +140,11 @@
cond_br %0, bb1, bb2
bb1:
- %r1 = strong_retain %1 : $B
+ strong_retain %1 : $B
br bb3(%3 : $B, %1 : $B)
bb2:
- %r2 = strong_retain %2 : $B
+ strong_retain %2 : $B
br bb3(%3 : $B, %2 : $B)
bb3(%a1 : $B, %a2 : $B):
@@ -166,11 +166,11 @@
cond_br %0, bb1, bb2
bb1:
- %r1 = strong_retain %1 : $B
+ strong_retain %1 : $B
br bb3(%1 : $B)
bb2:
- %r2 = strong_retain %2 : $B
+ strong_retain %2 : $B
br bb3(%3 : $B)
bb3(%a1 : $B):
@@ -192,11 +192,11 @@
cond_br %0, bb1, bb2
bb1:
- %r1 = strong_retain %1 : $B
+ strong_retain %1 : $B
br bb3(%1 : $B, %3 : $B)
bb2:
- %r2 = strong_retain %2 : $B
+ strong_retain %2 : $B
br bb3(%3 : $B, %2 : $B)
bb3(%a1 : $B, %a2 : $B):
@@ -224,15 +224,15 @@
cond_br %0, bb3, bb4
bb2:
- %r1 = strong_retain %1 : $B
+ strong_retain %1 : $B
br bb5(%1 : $B)
bb3:
- %r2 = strong_retain %2 : $B
+ strong_retain %2 : $B
br bb5(%2 : $B)
bb4:
- %r3 = strong_retain %1 : $B
+ strong_retain %1 : $B
br bb5(%2 : $B)
bb5(%a1 : $B):
@@ -260,15 +260,15 @@
cond_br %0, bb3, bb4
bb2:
- %r1 = strong_retain %1 : $B
+ strong_retain %1 : $B
br bb5(%2 : $B)
bb3:
- %r2 = strong_retain %2 : $B
+ strong_retain %2 : $B
br bb5(%2 : $B)
bb4:
- %r3 = strong_retain %1 : $B
+ strong_retain %1 : $B
br bb5(%1 : $B)
bb5(%a1 : $B):
@@ -309,12 +309,12 @@
cond_br %0, bb1, bb2
bb1:
- %2 = strong_retain %1 : $B
+ strong_retain %1 : $B
%3 = integer_literal $Builtin.Int32, 9
br bb3(%3 : $Builtin.Int32)
bb2:
- %4 = strong_retain %1 : $B
+ strong_retain %1 : $B
%5 = integer_literal $Builtin.Int32, 7
br bb3(%5 : $Builtin.Int32)
@@ -336,12 +336,12 @@
cond_br %0, bb1, bb2
bb1:
- %2 = strong_retain %1 : $B
+ strong_retain %1 : $B
%3 = integer_literal $Builtin.Int32, 7
br bb3(%3 : $Builtin.Int32)
bb2:
- %4 = strong_retain %1 : $B
+ strong_retain %1 : $B
%5 = integer_literal $Builtin.Int32, 7
br bb3(%5 : $Builtin.Int32)
diff --git a/test/SILOptimizer/lslocation_expansion.sil b/test/SILOptimizer/lslocation_expansion.sil
index 0261142..22ed083 100644
--- a/test/SILOptimizer/lslocation_expansion.sil
+++ b/test/SILOptimizer/lslocation_expansion.sil
@@ -82,7 +82,7 @@
store %9 to %1 : $*Builtin.Int64
%4 = tuple()
dealloc_stack %1 : $*Builtin.Int64 // id: %13
- %5 = return %4 : $()
+ return %4 : $()
}
// CHECK-LABEL: @store_after_store
@@ -94,10 +94,10 @@
bb0(%0 : $B):
%1 = alloc_box $<τ_0_0> { var τ_0_0 } <B>
%1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <B>, 0
- %2 = store %0 to %1a : $*B
- %3 = store %0 to %1a : $*B
+ store %0 to %1a : $*B
+ store %0 to %1a : $*B
%4 = tuple()
- %5 = return %4 : $()
+ return %4 : $()
}
// CHECK-LABEL: @store_after_store_struct
@@ -120,7 +120,7 @@
store %10 to %11 : $*Int
%4 = tuple()
dealloc_stack %1 : $*S1 // id: %13
- %5 = return %4 : $()
+ return %4 : $()
}
// Make sure all the structs get expanded correctly.
diff --git a/test/SILOptimizer/lslocation_reduction.sil b/test/SILOptimizer/lslocation_reduction.sil
index 5223030..16a4e0e 100644
--- a/test/SILOptimizer/lslocation_reduction.sil
+++ b/test/SILOptimizer/lslocation_reduction.sil
@@ -82,7 +82,7 @@
store %9 to %1 : $*Builtin.Int64
%4 = tuple()
dealloc_stack %1 : $*Builtin.Int64 // id: %13
- %5 = return %4 : $()
+ return %4 : $()
}
// CHECK-LABEL: @store_after_store
@@ -94,10 +94,10 @@
bb0(%0 : $B):
%1 = alloc_box $<τ_0_0> { var τ_0_0 } <B>
%1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <B>, 0
- %2 = store %0 to %1a : $*B
- %3 = store %0 to %1a : $*B
+ store %0 to %1a : $*B
+ store %0 to %1a : $*B
%4 = tuple()
- %5 = return %4 : $()
+ return %4 : $()
}
// CHECK-LABEL: @store_after_store_struct
@@ -118,7 +118,7 @@
store %10 to %11 : $*Int
%4 = tuple()
dealloc_stack %1 : $*S1 // id: %13
- %5 = return %4 : $()
+ return %4 : $()
}
// Make sure all the structs get expanded correctly.
diff --git a/test/SILOptimizer/mandatory_inlining.sil b/test/SILOptimizer/mandatory_inlining.sil
index 4b5fd9d..72f001c 100644
--- a/test/SILOptimizer/mandatory_inlining.sil
+++ b/test/SILOptimizer/mandatory_inlining.sil
@@ -212,7 +212,7 @@
bb0(%0 : $*SomeProtocol):
%1 = function_ref @test_existential_metatype : $@convention(thin) (@in SomeProtocol) -> @thick SomeProtocol.Type
%2 = apply %1(%0) : $@convention(thin) (@in SomeProtocol) -> @thick SomeProtocol.Type
- %3 = return %2 : $@thick SomeProtocol.Type
+ return %2 : $@thick SomeProtocol.Type
}
////////////////////////
diff --git a/test/SILOptimizer/pgo_si_inlinelarge.swift b/test/SILOptimizer/pgo_si_inlinelarge.swift
new file mode 100644
index 0000000..1efb9cd
--- /dev/null
+++ b/test/SILOptimizer/pgo_si_inlinelarge.swift
@@ -0,0 +1,130 @@
+// RUN: rm -rf %t && mkdir %t
+// RUN: %target-build-swift %s -profile-generate -Xfrontend -disable-incremental-llvm-codegen -module-name pgo_si_inlinelarge -o %t/main
+// RUN: env LLVM_PROFILE_FILE=%t/default.profraw %target-run %t/main
+// RUN: %llvm-profdata merge %t/default.profraw -o %t/default.profdata
+// RUN: %target-swift-frontend %s -profile-use=%t/default.profdata -emit-sorted-sil -emit-sil -module-name pgo_si_inlinelarge -o - | %FileCheck %s --check-prefix=SIL
+// RUN: %target-swift-frontend %s -profile-use=%t/default.profdata -O -emit-sorted-sil -emit-sil -module-name pgo_si_inlinelarge -o - | %FileCheck %s --check-prefix=SIL-OPT
+
+// REQUIRES: profile_runtime
+// REQUIRES: OS=macosx
+
+public func bar(_ x: Int64) -> Int64 {
+ if (x == 0) {
+ return 42
+ }
+ if (x == 1) {
+ return 6
+ }
+ if (x == 2) {
+ return 9
+ }
+ if (x == 3) {
+ return 93
+ }
+ if (x == 4) {
+ return 94
+ }
+ if (x == 5) {
+ return 95
+ }
+ if (x == 6) {
+ return 96
+ }
+ if (x == 7) {
+ return 97
+ }
+ if (x == 8) {
+ return 98
+ }
+ if (x == 9) {
+ return 99
+ }
+ if (x == 10) {
+ return 910
+ }
+ if (x == 11) {
+ return 911
+ }
+ if (x == 11) {
+ return 911
+ }
+ if (x == 11) {
+ return 911
+ }
+ if (x == 12) {
+ return 912
+ }
+ if (x == 13) {
+ return 913
+ }
+ if (x == 14) {
+ return 914
+ }
+ if (x == 15) {
+ return 916
+ }
+ if (x == 17) {
+ return 917
+ }
+ if (x == 18) {
+ return 918
+ }
+ if (x == 19) {
+ return 919
+ }
+ if (x % 2 == 0) {
+ return 4242
+ }
+ var ret : Int64 = 0
+ for currNum in stride(from: 5, to: x, by: 5) {
+ print("in bar stride")
+ ret += currNum
+ print(ret)
+ print("in bar stride")
+ ret += currNum
+ print(ret)
+ print("in bar stride")
+ ret += currNum
+ print(ret)
+ print("in bar stride")
+ ret += currNum
+ print(ret)
+ print("in bar stride")
+ ret += currNum
+ print(ret)
+ print("in bar stride")
+ ret += currNum
+ print(ret)
+ print("in bar stride")
+ ret += currNum
+ print(ret)
+ }
+ return ret
+}
+
+// SIL-LABEL: sil @_T018pgo_si_inlinelarge3fooys5Int64VF : $@convention(thin) (Int64) -> () !function_entry_count(1) {
+// SIL-OPT-LABEL: sil @_T018pgo_si_inlinelarge3fooys5Int64VF : $@convention(thin) (Int64) -> () !function_entry_count(1) {
+public func foo(_ x: Int64) {
+ // SIL: switch_enum {{.*}} : $Optional<Int64>, case #Optional.some!enumelt.1: {{.*}} !case_count(100), case #Optional.none!enumelt: {{.*}} !case_count(1)
+ // SIL: cond_br {{.*}}, {{.*}}, {{.*}} !true_count(50)
+ // SIL: cond_br {{.*}}, {{.*}}, {{.*}} !true_count(1)
+ // SIL-OPT: integer_literal $Builtin.Int64, 93
+ // SIL-OPT: integer_literal $Builtin.Int64, 42
+ // SIL-OPT: function_ref @_T018pgo_si_inlinelarge3bars5Int64VADF : $@convention(thin) (Int64) -> Int64
+
+ var sum : Int64 = 0
+ for index in 1...x {
+ if (index % 2 == 0) {
+ sum += bar(index)
+ }
+ if (index == 50) {
+ sum += bar(index)
+ }
+ sum += 1
+ }
+ print(sum)
+}
+// SIL-LABEL: } // end sil function '_T018pgo_si_inlinelarge3fooys5Int64VF'
+// SIL-OPT-LABEL: } // end sil function '_T018pgo_si_inlinelarge3fooys5Int64VF'
+
+foo(100)
diff --git a/test/SILOptimizer/pgo_si_reduce.swift b/test/SILOptimizer/pgo_si_reduce.swift
new file mode 100644
index 0000000..0982ad0
--- /dev/null
+++ b/test/SILOptimizer/pgo_si_reduce.swift
@@ -0,0 +1,56 @@
+// RUN: rm -rf %t && mkdir %t
+// RUN: %target-build-swift %s -profile-generate -Xfrontend -disable-incremental-llvm-codegen -module-name pgo_si_reduce -o %t/main
+// RUN: env LLVM_PROFILE_FILE=%t/default.profraw %target-run %t/main
+// RUN: %llvm-profdata merge %t/default.profraw -o %t/default.profdata
+// RUN: %target-swift-frontend %s -profile-use=%t/default.profdata -emit-sorted-sil -emit-sil -module-name pgo_si_reduce -o - | %FileCheck %s --check-prefix=SIL
+// RUN: %target-swift-frontend %s -profile-use=%t/default.profdata -O -emit-sorted-sil -emit-sil -module-name pgo_si_reduce -o - | %FileCheck %s --check-prefix=SIL-OPT
+
+// REQUIRES: profile_runtime
+// REQUIRES: OS=macosx
+
+public func bar(_ x: Int32) -> Int32 {
+ if (x == 0) {
+ return 42
+ }
+ if (x == 1) {
+ return 6
+ }
+ if (x == 2) {
+ return 9
+ }
+ if (x % 2 == 0) {
+ return 4242
+ }
+ var ret : Int32 = 0
+ for currNum in stride(from: 5, to: x, by: 5) {
+ ret += currNum
+ }
+ return ret
+}
+
+// SIL-LABEL: sil @_T013pgo_si_reduce3fooys5Int32VF : $@convention(thin) (Int32) -> () !function_entry_count(1) {
+// SIL-OPT-LABEL: sil @_T013pgo_si_reduce3fooys5Int32VF : $@convention(thin) (Int32) -> () !function_entry_count(1) {
+public func foo(_ x: Int32) {
+ // SIL: switch_enum {{.*}} : $Optional<Int32>, case #Optional.some!enumelt.1: {{.*}} !case_count(100), case #Optional.none!enumelt: {{.*}} !case_count(1)
+ // SIL: cond_br {{.*}}, {{.*}}, {{.*}} !true_count(50)
+ // SIL: cond_br {{.*}}, {{.*}}, {{.*}} !true_count(1)
+ // SIL-OPT: integer_literal $Builtin.Int32, 4242
+ // SIL-OPT: integer_literal $Builtin.Int32, 42
+ // SIL-OPT: function_ref @_T013pgo_si_reduce3bars5Int32VADF : $@convention(thin) (Int32) -> Int32
+
+ var sum : Int32 = 0
+ for index in 1...x {
+ if (index % 2 == 0) {
+ sum += bar(index)
+ }
+ if (index == 50) {
+ sum += bar(index)
+ }
+ sum += 1
+ }
+ print(sum)
+}
+// SIL-LABEL: } // end sil function '_T013pgo_si_reduce3fooys5Int32VF'
+// SIL-OPT-LABEL: } // end sil function '_T013pgo_si_reduce3fooys5Int32VF'
+
+foo(100)
diff --git a/test/SILOptimizer/predictable_memopt.sil b/test/SILOptimizer/predictable_memopt.sil
index 037f07f..f798389 100644
--- a/test/SILOptimizer/predictable_memopt.sil
+++ b/test/SILOptimizer/predictable_memopt.sil
@@ -68,7 +68,7 @@
// CHECK: %1 = alloc_box $<τ_0_0> { var τ_0_0 } <Int>
%1 = alloc_box $<τ_0_0> { var τ_0_0 } <Int>
%1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <Int>, 0
- %2 = store %0 to %1a : $*Int
+ store %0 to %1a : $*Int
// This load should be eliminated.
%3 = load %1a : $*Int
@@ -83,7 +83,7 @@
// CHECK: tuple ({{.*}} : $Int, {{.*}} : $Int)
%8 = tuple (%3 : $Int, %7 : $Int)
strong_release %1 : $<τ_0_0> { var τ_0_0 } <Int>
- %11 = return %8 : $(Int, Int)
+ return %8 : $(Int, Int)
}
diff --git a/test/SILOptimizer/redundant_load_elim.sil b/test/SILOptimizer/redundant_load_elim.sil
index 6c2deca..ad61025 100644
--- a/test/SILOptimizer/redundant_load_elim.sil
+++ b/test/SILOptimizer/redundant_load_elim.sil
@@ -306,13 +306,13 @@
bb0(%0 : $B):
%1 = alloc_box $<τ_0_0> { var τ_0_0 } <B>
%1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <B>, 0
- %2 = store %0 to %1a : $*B
+ store %0 to %1a : $*B
%3 = load %1a : $*B
%4 = load %1a : $*B
- %5 = strong_retain %3 : $B
- %6 = strong_retain %4 : $B
+ strong_retain %3 : $B
+ strong_retain %4 : $B
%7 = tuple()
- %8 = return %7 : $()
+ return %7 : $()
}
// CHECK-LABEL: sil @eliminate_duplicate_loads_over_noread_builtins
@@ -433,10 +433,10 @@
bb0(%0 : $*Agg2, %1 : $*Agg1):
%2 = load %1 : $*Agg1
%3 = load %0 : $*Agg2
- %4 = store %2 to %1 : $*Agg1
- %5 = store %3 to %0 : $*Agg2
+ store %2 to %1 : $*Agg1
+ store %3 to %0 : $*Agg2
%6 = tuple()
- %7 = return %6 : $()
+ return %6 : $()
}
// Check load forwarding across strong_release in case the stored memory does
diff --git a/test/SILOptimizer/redundant_load_elim_with_casts.sil b/test/SILOptimizer/redundant_load_elim_with_casts.sil
index c176381..bb825c9 100644
--- a/test/SILOptimizer/redundant_load_elim_with_casts.sil
+++ b/test/SILOptimizer/redundant_load_elim_with_casts.sil
@@ -75,14 +75,14 @@
%2 = alloc_box $<τ_0_0> { var τ_0_0 } <B>
%2a = project_box %2 : $<τ_0_0> { var τ_0_0 } <B>, 0
%3 = load %1 : $*Agg1
- %4 = store %3 to %1 : $*Agg1
+ store %3 to %1 : $*Agg1
%5 = load %2a : $*B
- %6 = store %3 to %1 : $*Agg1
+ store %3 to %1 : $*Agg1
%7 = load %2a : $*B
- %8 = strong_retain %5 : $B //%7 and %5 should really be one load.
- %9 = strong_retain %7 : $B
+ strong_retain %5 : $B //%7 and %5 should really be one load.
+ strong_retain %7 : $B
%10 = tuple()
- %11 = return %10 : $()
+ return %10 : $()
}
// FIXME: When RLE uses TBAA it should remove the second load.
@@ -99,7 +99,7 @@
store %1 to %5 : $*A2
%20 = load %2 : $*A
%30 = tuple(%3 : $A, %20 : $A)
- %31 = return %30 : $(A, A)
+ return %30 : $(A, A)
}
// Even with TBAA, RLE should not remove the second load.
@@ -121,7 +121,7 @@
bind_memory %0 : $Builtin.RawPointer, %4 : $Builtin.Word to $A
%20 = load %2 : $*A
%30 = tuple(%3 : $A, %20 : $A)
- %31 = return %30 : $(A, A)
+ return %30 : $(A, A)
}
// *NOTE* This does not handle raw pointer since raw pointer is only layout compatible with heap references.
diff --git a/test/SILOptimizer/semantic-arc-opts.sil b/test/SILOptimizer/semantic-arc-opts.sil
index 048a283..3270931 100644
--- a/test/SILOptimizer/semantic-arc-opts.sil
+++ b/test/SILOptimizer/semantic-arc-opts.sil
@@ -70,7 +70,7 @@
%2 = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
%3 = begin_borrow %1 : $Builtin.NativeObject
apply %2(%3) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
- %4 = end_borrow %3 from %1 : $Builtin.NativeObject, $Builtin.NativeObject
+ end_borrow %3 from %1 : $Builtin.NativeObject, $Builtin.NativeObject
destroy_value %1 : $Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
diff --git a/test/SILOptimizer/sil_combine.sil b/test/SILOptimizer/sil_combine.sil
index c97f8b2..ed3e607 100644
--- a/test/SILOptimizer/sil_combine.sil
+++ b/test/SILOptimizer/sil_combine.sil
@@ -146,12 +146,12 @@
bb0(%0 : $B):
%1 = alloc_box $<τ_0_0> { var τ_0_0 } <B>
%1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <B>, 0
- %2 = store %0 to %1a : $*B
+ store %0 to %1a : $*B
%3 = load %1a : $*B
- %4 = strong_retain %3 : $B
+ strong_retain %3 : $B
%5 = unchecked_ref_cast %3 : $B to $Builtin.NativeObject
- %7 = strong_release %3 : $B
- %8 = strong_release %1 : $<τ_0_0> { var τ_0_0 } <B>
+ strong_release %3 : $B
+ strong_release %1 : $<τ_0_0> { var τ_0_0 } <B>
%9 = function_ref @exit : $@convention(thin) () -> Never // ret.exit : () -> ()
%10 = apply %9() : $@convention(thin) () -> Never
unreachable
@@ -165,9 +165,9 @@
sil @removeTriviallyDeadCrossBasicBlocks : $@convention(thin) (@owned B, Builtin.Int1) -> () {
bb0(%0: $B, %1: $Builtin.Int1):
%5 = unchecked_ref_cast %0 : $B to $Builtin.NativeObject
- %13 = cond_br %1, bb1, bb2
+ cond_br %1, bb1, bb2
bb1:
- %22 = br bb2
+ br bb2
bb2:
%9 = function_ref @exit : $@convention(thin) () -> Never // ret.exit : () -> ()
%10 = apply %9() : $@convention(thin) () -> Never
@@ -288,7 +288,7 @@
%1 = load %0 : $*UInt8
%2 = integer_literal $Builtin.Int8, 1
%3 = struct_element_addr %0 : $*UInt8, #UInt8._value
- %4 = store %2 to %3 : $*Builtin.Int8
+ store %2 to %3 : $*Builtin.Int8
%5 = struct_extract %1 : $UInt8, #UInt8._value
return %5 : $Builtin.Int8
}
@@ -306,7 +306,7 @@
%1 = load %0 : $*(Builtin.Int8, Builtin.Int8)
%2 = integer_literal $Builtin.Int8, 1
%3 = tuple_element_addr %0 : $*(Builtin.Int8, Builtin.Int8), 0
- %4 = store %2 to %3 : $*Builtin.Int8
+ store %2 to %3 : $*Builtin.Int8
%5 = tuple_extract %1 : $(Builtin.Int8, Builtin.Int8), 0
return %5 : $Builtin.Int8
}
@@ -327,7 +327,7 @@
%1 = load %0 : $*UInt8
%2 = integer_literal $Builtin.Int8, 1
%3 = struct_element_addr %0 : $*UInt8, #UInt8._value
- %4 = store %2 to %3 : $*Builtin.Int8
+ store %2 to %3 : $*Builtin.Int8
%5 = struct_extract %1 : $UInt8, #UInt8._value
%6 = tuple (%1 : $UInt8, %5 : $Builtin.Int8)
return %6 : $(UInt8, Builtin.Int8)
@@ -349,7 +349,7 @@
%1 = load %0 : $*(Builtin.Int8, Builtin.Int8)
%2 = integer_literal $Builtin.Int8, 1
%3 = tuple_element_addr %0 : $*(Builtin.Int8, Builtin.Int8), 0
- %4 = store %2 to %3 : $*Builtin.Int8
+ store %2 to %3 : $*Builtin.Int8
%5 = tuple_extract %1 : $(Builtin.Int8, Builtin.Int8), 0
%6 = tuple (%1 : $(Builtin.Int8, Builtin.Int8), %5 : $Builtin.Int8)
return %6 : $((Builtin.Int8, Builtin.Int8), Builtin.Int8)
@@ -1228,7 +1228,7 @@
// CHECK-NEXT: return
sil @unchecked_take_enum_data_addr_promotion : $@convention(thin) (@inout FakeOptional<B>) -> B {
bb0(%0 : $*FakeOptional<B>):
- %1 = switch_enum_addr %0 : $*FakeOptional<B>, case #FakeOptional.some!enumelt.1: bb1, case #FakeOptional.none!enumelt: bb2
+ switch_enum_addr %0 : $*FakeOptional<B>, case #FakeOptional.some!enumelt.1: bb1, case #FakeOptional.none!enumelt: bb2
bb1:
%2 = unchecked_take_enum_data_addr %0 : $*FakeOptional<B>, #FakeOptional.some!enumelt.1
@@ -2723,8 +2723,8 @@
bb0(%0 : $*B, %1 : $B, %2 : $Builtin.Int1):
%3 = function_ref @weird_function : $@convention(thin) (@inout E, E, Builtin.Int1) -> ()
%4 = convert_function %3 : $@convention(thin) (@inout E, E, Builtin.Int1) -> () to $@convention(thin) (@inout B, B, Builtin.Int1) -> ()
- %5 = retain_value %4: $@convention(thin) (@inout B, B, Builtin.Int1) -> ()
- %6 = release_value %4: $@convention(thin) (@inout B, B, Builtin.Int1) -> ()
+ retain_value %4: $@convention(thin) (@inout B, B, Builtin.Int1) -> ()
+ release_value %4: $@convention(thin) (@inout B, B, Builtin.Int1) -> ()
%7 = tuple()
return %7 : $()
}
diff --git a/test/SILOptimizer/sil_combine_enum_addr.sil b/test/SILOptimizer/sil_combine_enum_addr.sil
index 50bea8c..828da98 100644
--- a/test/SILOptimizer/sil_combine_enum_addr.sil
+++ b/test/SILOptimizer/sil_combine_enum_addr.sil
@@ -59,7 +59,7 @@
unconditional_checked_cast_addr Int in %5 : $*Int to CustomStringConvertible in %4 : $*CustomStringConvertible
inject_enum_addr %3 : $*Optional<CustomStringConvertible>, #Optional.some!enumelt.1
dealloc_stack %5 : $*Int
- %13 = switch_enum_addr %3 : $*Optional<CustomStringConvertible>, case #Optional.some!enumelt.1: bb3, case #Optional.none!enumelt: bb2
+ switch_enum_addr %3 : $*Optional<CustomStringConvertible>, case #Optional.some!enumelt.1: bb3, case #Optional.none!enumelt: bb2
bb1:
%15 = tuple ()
diff --git a/test/SILOptimizer/sil_combine_enums.sil b/test/SILOptimizer/sil_combine_enums.sil
index 82e660e..c6f6129 100644
--- a/test/SILOptimizer/sil_combine_enums.sil
+++ b/test/SILOptimizer/sil_combine_enums.sil
@@ -30,9 +30,9 @@
store %1 to %2 : $*SomeClass // id: %3
inject_enum_addr %0 : $*Optional<SomeClass>, #Optional.some!enumelt.1 // id: %4
%5 = load %0 : $*Optional<SomeClass> // users: %6, %8, %9, %14
- %6 = retain_value %5 : $Optional<SomeClass>
+ retain_value %5 : $Optional<SomeClass>
%7 = alloc_stack $Optional<SomeClass> // users: %9, %10, %11, %13
- %8 = retain_value %5 : $Optional<SomeClass>
+ retain_value %5 : $Optional<SomeClass>
store %5 to %7 : $*Optional<SomeClass> // id: %9
switch_enum_addr %7 : $*Optional<SomeClass>, case #Optional.some!enumelt.1: bb1, case #Optional.none!enumelt: bb2 // id: %10
@@ -65,9 +65,9 @@
store %1 to %2 : $*SomeClass
inject_enum_addr %0 : $*Optional<SomeClass>, #Optional.some!enumelt.1
%5 = load %0 : $*Optional<SomeClass>
- %6 = retain_value %5 : $Optional<SomeClass>
+ retain_value %5 : $Optional<SomeClass>
%7 = alloc_stack $Optional<SomeClass>
- %8 = retain_value %5 : $Optional<SomeClass>
+ retain_value %5 : $Optional<SomeClass>
store %5 to %7 : $*Optional<SomeClass>
%t = integer_literal $Builtin.Int1, -1
%f = integer_literal $Builtin.Int1, 0
diff --git a/test/SILOptimizer/sil_combine_opaque.sil b/test/SILOptimizer/sil_combine_opaque.sil
index e99bbf9..549fbed 100644
--- a/test/SILOptimizer/sil_combine_opaque.sil
+++ b/test/SILOptimizer/sil_combine_opaque.sil
@@ -16,10 +16,10 @@
// CHECK-LABEL: } // end sil function 'testSpecializeOpaque'
sil @testSpecializeOpaque : $@convention(thin) <T> (@in S<T>) -> () {
bb0(%0 : $S<T>):
- %retain = retain_value %0 : $S<T>
+ retain_value %0 : $S<T>
%f = function_ref @testSpecializeOpaque : $@convention(thin) <T> (@in S<T>) -> ()
%call = apply %f<T>(%0) : $@convention(thin) <τ_0_0> (@in S<τ_0_0>) -> ()
- %release = release_value %0 : $S<T>
+ release_value %0 : $S<T>
%999 = tuple ()
return %999 : $()
}
diff --git a/test/SILOptimizer/simplify_cfg.sil b/test/SILOptimizer/simplify_cfg.sil
index c9f1e41..3793559 100644
--- a/test/SILOptimizer/simplify_cfg.sil
+++ b/test/SILOptimizer/simplify_cfg.sil
@@ -2830,7 +2830,7 @@
br bb6(%15 : $Builtin.Int8)
bb4:
- %60 = debug_value %0 : $TestEnum
+ debug_value %0 : $TestEnum
%22 = alloc_existential_box $Error, $MyError2
%23 = project_existential_box $MyError2 in %22 : $Error
switch_enum %0 : $TestEnum, case #TestEnum.none!enumelt: bbnone, case #TestEnum.int64!enumelt.1: bb7, case #TestEnum.string!enumelt.1: bb10
diff --git a/test/SILOptimizer/unsafe_guaranteed_peephole.sil b/test/SILOptimizer/unsafe_guaranteed_peephole.sil
index a60b5fc..97c35cd 100644
--- a/test/SILOptimizer/unsafe_guaranteed_peephole.sil
+++ b/test/SILOptimizer/unsafe_guaranteed_peephole.sil
@@ -530,7 +530,7 @@
%5 = tuple_extract %4 : $(Foo, Builtin.Int8), 0
%6 = tuple_extract %4 : $(Foo, Builtin.Int8), 1
%7 = function_ref @beep_or_throw : $@convention(thin) () -> @error Error
- %8 = try_apply %7() : $@convention(thin) () -> @error Error, normal bb1, error bb2
+ try_apply %7() : $@convention(thin) () -> @error Error, normal bb1, error bb2
bb1(%15: $()):
strong_release %5 : $Foo
diff --git a/test/Sema/diag_type_conversion.swift b/test/Sema/diag_type_conversion.swift
index 3aa3917..9488f4b 100644
--- a/test/Sema/diag_type_conversion.swift
+++ b/test/Sema/diag_type_conversion.swift
@@ -66,3 +66,7 @@
var p: UnsafeMutablePointer<C>? = nil
_ = p =*= &o
+
+
+func rdar25963182(_ bytes: [UInt8] = nil) {}
+// expected-error@-1 {{nil default argument value cannot be converted to type}}
diff --git a/test/Sema/immutability.swift b/test/Sema/immutability.swift
index 4d2ba53..845fbfe 100644
--- a/test/Sema/immutability.swift
+++ b/test/Sema/immutability.swift
@@ -628,8 +628,7 @@
return f(x)
}
- // expected-error@+1 {{expression type '(inout MutableSubscripts) -> ()' is ambiguous without more context}}
- let closure = { val in val.x = 7 } as (inout MutableSubscripts) -> ()
+ let closure = { val in val.x = 7 } as (inout MutableSubscripts) -> () // Ok
var v = MutableSubscripts()
closure(&v)
// FIXME: This diagnostic isn't really all that much better
diff --git a/test/Serialization/Inputs/def_basic.sil b/test/Serialization/Inputs/def_basic.sil
index 6c4bc1b..4bd889a 100644
--- a/test/Serialization/Inputs/def_basic.sil
+++ b/test/Serialization/Inputs/def_basic.sil
@@ -101,7 +101,7 @@
%0 = integer_literal $Builtin.Word, 42
// CHECK: integer_literal $Builtin.Word, 42
%9 = tuple $(Builtin.Word, Builtin.Word) (%0, %0)
- %10 = return %9 : $(Builtin.Word, Builtin.Word)
+ return %9 : $(Builtin.Word, Builtin.Word)
}
sil [serialized] @return_int : $@convention(thin) (Int) -> Int { // CHECK-LABEL: $@convention(thin) (Int) -> Int {
@@ -146,7 +146,7 @@
// CHECK: apply
%4 = apply %1(%3, %2) : $@convention(thin) (Builtin.Word, @thin Int.Type) -> Int
// CHECK: return
- %5 = return %4 : $Int
+ return %4 : $Int
}
sil [serialized] @_T0Si25convertFromIntegerLiteralSiBi64_3val_tcSimF : $@convention(thin) (Builtin.Word, @thin Int.Type) -> Int
@@ -177,8 +177,8 @@
// CHECK: apply
%3 = apply %2<@opened("01234567-89ab-cdef-0123-000000000000") P>(%1) : $@convention(witness_method) <T: P> (@inout T) -> ()
%4 = tuple () // CHECK: tuple ()
- %5 = destroy_addr %0 : $*P // CHECK: destroy_addr %0 : $*P
- %6 = return %4 : $() // CHECK: return
+ destroy_addr %0 : $*P // CHECK: destroy_addr %0 : $*P
+ return %4 : $() // CHECK: return
}
@@ -214,7 +214,7 @@
// CHECK: unconditional_checked_cast {{.*}} : $C to $D
%5 = unconditional_checked_cast %C : $C to $D
%6 = tuple ()
- %7 = return %6 : $()
+ return %6 : $()
}
// Generated from:
@@ -238,14 +238,14 @@
//%3 = alloc_stack $@thick T.U.Type
//%4 = witness_method $*T, #Runcible.associated_method!1 : $@cc(method) (@inout T) -> @thick T.U.Type
//%5 = apply %4(%0) : $@cc(method) ((), @inout T) -> @thick T.U.Type
- //%6 = store %5 to %3#1 : $*@thick T.U.Type
+ //store %5 to %3#1 : $*@thick T.U.Type
//%7 = metatype $@thick T.Type
//%8 = witness_method [volatile] $*T, #Runcible.static_method!1 : $(@thick T.Type) -> ()
//%9 = apply %8(%7) : $((), @thick T.Type) -> ()
- //%10 = dealloc_stack %3#0 : $*@thick T.U.Type
+ //dealloc_stack %3#0 : $*@thick T.U.Type
//%11 = tuple ()
- //%12 = destroy_addr %0 : $*T
- //%13 = return %11 : $()
+ //destroy_addr %0 : $*T
+ //return %11 : $()
//}
protocol Bendable { }
@@ -257,19 +257,19 @@
%2 = alloc_box $<τ_0_0> { var τ_0_0 } <(Bendable & Runcible)>
%2a = project_box %2 : $<τ_0_0> { var τ_0_0 } <Bendable & Runcible>, 0
// CHECK: copy_addr [take] {{.*}} to [initialization] {{.*}} : $*Bendable & Runcible
- %3 = copy_addr [take] %1 to [initialization] %2a : $*Bendable & Runcible
+ copy_addr [take] %1 to [initialization] %2a : $*Bendable & Runcible
// CHECK: alloc_stack
%4 = alloc_stack $Bendable & Runcible
// CHECK: copy_addr {{.*}} to [initialization] {{.*}} : $*Bendable & Runcible
- %5 = copy_addr %2a to [initialization] %4 : $*Bendable & Runcible
+ copy_addr %2a to [initialization] %4 : $*Bendable & Runcible
%7 = tuple ()
// CHECK: destroy_addr
- %8 = destroy_addr %4 : $*Bendable & Runcible
+ destroy_addr %4 : $*Bendable & Runcible
// CHECK: dealloc_stack
- %9 = dealloc_stack %4 : $*Bendable & Runcible
- %10 = strong_release %2 : $<τ_0_0> { var τ_0_0 } <Bendable & Runcible>
+ dealloc_stack %4 : $*Bendable & Runcible
+ strong_release %2 : $<τ_0_0> { var τ_0_0 } <Bendable & Runcible>
// CHECK: return
- %11 = return %7 : $()
+ return %7 : $()
}
protocol ClassBound : class {
@@ -281,17 +281,17 @@
bb0(%0 : $ClassBound):
%1 = alloc_box $<τ_0_0> { var τ_0_0 } <ClassBound>
%1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <ClassBound>, 0
- %2 = store %0 to %1a : $*ClassBound
+ store %0 to %1a : $*ClassBound
%3 = load %1a : $*ClassBound
- %4 = strong_retain %3 : $ClassBound // CHECK: strong_retain
+ strong_retain %3 : $ClassBound // CHECK: strong_retain
// CHECK: open_existential_ref {{%.*}} : $ClassBound to $@opened({{.*}}) ClassBound
%5 = open_existential_ref %3 : $ClassBound to $@opened("01234567-89ab-cdef-0123-111111111111") ClassBound
// CHECK: witness_method
%6 = witness_method $@opened("01234567-89ab-cdef-0123-111111111111") ClassBound, #ClassBound.classBoundMethod!1, %5 : $@opened("01234567-89ab-cdef-0123-111111111111") ClassBound : $@convention(witness_method) <T: ClassBound> (T) -> ()
%7 = apply %6<@opened("01234567-89ab-cdef-0123-111111111111") ClassBound>(%5) : $@convention(witness_method) <T: ClassBound> (T) -> ()
%8 = tuple ()
- %9 = strong_release %1 : $<τ_0_0> { var τ_0_0 } <ClassBound>
- %10 = return %8 : $()
+ strong_release %1 : $<τ_0_0> { var τ_0_0 } <ClassBound>
+ return %8 : $()
}
struct Val {
@@ -301,7 +301,7 @@
//bb0(%0 : $@thin Val.Type):
//%1 = alloc_stack $Val
//%3 = load %1#1 : $*Val
- //%4 = return %3 : $Val
+ //return %3 : $Val
//}
class Ref {
@@ -316,7 +316,7 @@
bb0(%0 : $Ref, %1 : $Val, %2 : $@thin Aleph.Type):
// CHECK: struct $Aleph ({{%.*}} : $Ref, {{%.*}} : $Val)
%3 = struct $Aleph (%0 : $Ref, %1 : $Val)
- %4 = return %3 : $Aleph // CHECK: return
+ return %3 : $Aleph // CHECK: return
}
// CHECK-LABEL: @_T06struct5AlephVACycACmcfC : $@convention(thin) (@thin Aleph.Type) -> Aleph
@@ -328,13 +328,13 @@
// CHECK: struct_element_addr {{.*}} : $*Aleph, #Aleph.a
%5 = struct_element_addr %2a : $*Aleph, #Aleph.a
%6 = load %5 : $*Ref
- %8 = strong_release %6 : $Ref
+ strong_release %6 : $Ref
%14 = load %2a : $*Aleph
// CHECK: struct_extract {{%.*}} : $Aleph, #Aleph.a
%15 = struct_extract %14 : $Aleph, #Aleph.a
- %16 = strong_retain %15 : $Ref
- %17 = strong_release %2 : $<τ_0_0> { var τ_0_0 } <Aleph>
- %18 = return %14 : $Aleph
+ strong_retain %15 : $Ref
+ strong_release %2 : $<τ_0_0> { var τ_0_0 } <Aleph>
+ return %14 : $Aleph
}
enum Beth {
@@ -394,7 +394,7 @@
%2 = alloc_box $<τ_0_0> { var τ_0_0 } <(Int, Float32)>
%2a = project_box %2 : $<τ_0_0> { var τ_0_0 } <(Int, Float32)>, 0
%3 = tuple (%0 : $Int, %1 : $Float32)
- %4 = store %3 to %2a : $*(Int, Float32)
+ store %3 to %2a : $*(Int, Float32)
// CHECK: tuple_element_addr {{%.*}} : $*(Int, Float), 0
%6 = tuple_element_addr %2a : $*(Int, Float), 0
%7 = load %6 : $*Int
@@ -412,8 +412,8 @@
// CHECK: apply
%24 = apply %19(%17) : $@convention(thin) (Float32) -> ()
%25 = tuple ()
- %26 = strong_release %2 : $<τ_0_0> { var τ_0_0 } <(Int, Float32)>
- %27 = return %25 : $()
+ strong_release %2 : $<τ_0_0> { var τ_0_0 } <(Int, Float32)>
+ return %25 : $()
}
class M {
@@ -426,21 +426,21 @@
bb0(%0 : $Int, %1 : $M):
%2 = alloc_box $<τ_0_0> { var τ_0_0 } <Int>
%2a = project_box %2 : $<τ_0_0> { var τ_0_0 } <Int>, 0
- %3 = store %0 to %2a : $*Int
+ store %0 to %2a : $*Int
%4 = alloc_box $<τ_0_0> { var τ_0_0 } <M>
%4a = project_box %4 : $<τ_0_0> { var τ_0_0 } <M>, 0
- %5 = store %1 to %4a : $*M
+ store %1 to %4a : $*M
%6 = load %2a : $*Int
%7 = load %4a : $*M
- %8 = strong_retain %7 : $M
+ strong_retain %7 : $M
// CHECK: ref_element_addr {{%.*}} : $M, #M.member
%9 = ref_element_addr %7 : $M, #M.member
- %10 = store %6 to %9 : $*Int
- %11 = strong_release %7 : $M
+ store %6 to %9 : $*Int
+ strong_release %7 : $M
%12 = tuple ()
- %13 = strong_release %4 : $<τ_0_0> { var τ_0_0 } <M>
- %14 = strong_release %2 : $<τ_0_0> { var τ_0_0 } <Int>
- %15 = return %12 : $()
+ strong_release %4 : $<τ_0_0> { var τ_0_0 } <M>
+ strong_release %2 : $<τ_0_0> { var τ_0_0 } <Int>
+ return %12 : $()
}
class B { }
@@ -451,9 +451,9 @@
bb0(%0 : $B):
%1 = alloc_box $<τ_0_0> { var τ_0_0 } <B>
%1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <B>, 0
- %2 = store %0 to %1a : $*B
+ store %0 to %1a : $*B
%3 = load %1a : $*B
- %4 = strong_retain %3 : $B
+ strong_retain %3 : $B
checked_cast_br %3 : $B to $E, yes, no // CHECK: checked_cast_br
yes(%5 : $E):
%y = integer_literal $Builtin.Int1, 1
@@ -462,9 +462,9 @@
%n = integer_literal $Builtin.Int1, 0
br isa(%n : $Builtin.Int1)
isa(%6 : $Builtin.Int1):
- %7 = strong_release %3 : $B
- %8 = strong_release %1 : $<τ_0_0> { var τ_0_0 } <B>
- %9 = return %6 : $Builtin.Int1
+ strong_release %3 : $B
+ strong_release %1 : $<τ_0_0> { var τ_0_0 } <B>
+ return %6 : $Builtin.Int1
}
sil [serialized] @_T07literal8literalsyyF : $@convention(thin) () -> ()
@@ -479,15 +479,15 @@
%2a = project_box %2 : $<τ_0_0> { var τ_0_0 } <Builtin.RawPointer>, 0
%3 = alloc_box $<τ_0_0> { var τ_0_0 } <Builtin.Word>
%3a = project_box %3 : $<τ_0_0> { var τ_0_0 } <Builtin.Word>, 0
- %4 = store %0 to %2a : $*Builtin.RawPointer
- %5 = store %1 to %3a : $*Builtin.Word
+ store %0 to %2a : $*Builtin.RawPointer
+ store %1 to %3a : $*Builtin.Word
%7 = load %2a : $*Builtin.RawPointer
%8 = load %3a : $*Builtin.Word
// CHECK: index_raw_pointer {{%.*}} : $Builtin.RawPointer, {{%.*}} : $Builtin.Word
%9 = index_raw_pointer %7 : $Builtin.RawPointer, %8 : $Builtin.Word
- %10 = strong_release %3 : $<τ_0_0> { var τ_0_0 } <Builtin.Word>
- %11 = strong_release %2 : $<τ_0_0> { var τ_0_0 } <Builtin.RawPointer>
- %12 = return %9 : $Builtin.RawPointer
+ strong_release %3 : $<τ_0_0> { var τ_0_0 } <Builtin.Word>
+ strong_release %2 : $<τ_0_0> { var τ_0_0 } <Builtin.RawPointer>
+ return %9 : $Builtin.RawPointer
}
sil_global @x : $Int
@@ -502,9 +502,9 @@
%2 = metatype $@thin Int.Type
%3 = integer_literal $Builtin.Int128, 0 // CHECK: integer_literal $Builtin.Int128, 0
%4 = apply %1(%3, %2) : $@convention(thin) (Builtin.Int128, @thin Int.Type) -> Int
- %5 = store %4 to %0 : $*Int
+ store %4 to %0 : $*Int
%6 = tuple ()
- %7 = return %6 : $()
+ return %6 : $()
}
class GlobalObject { }
@@ -534,26 +534,26 @@
%2a = project_box %2 : $<τ_0_0> { var τ_0_0 } <SomeClass>, 0
%3 = alloc_box $<τ_0_0> { var τ_0_0 } <SomeSubclass>
%3a = project_box %3 : $<τ_0_0> { var τ_0_0 } <SomeSubclass>, 0
- %4 = store %0 to %2a : $*SomeClass
- %5 = store %1 to %3a : $*SomeSubclass
+ store %0 to %2a : $*SomeClass
+ store %1 to %3a : $*SomeSubclass
%7 = load %2a : $*SomeClass
// CHECK: strong_retain %{{.*}} : $SomeClass
- %8 = strong_retain %7 : $SomeClass
+ strong_retain %7 : $SomeClass
// CHECK: value_metatype $@thick SomeClass.Type, {{%.*}} : $SomeClass
%9 = value_metatype $@thick SomeClass.Type, %7 : $SomeClass
%11 = load %3a : $*SomeSubclass
- %12 = strong_retain %11 : $SomeSubclass
+ strong_retain %11 : $SomeSubclass
// CHECK: value_metatype $@thick SomeSubclass.Type, {{%.*}} : $SomeSubclass
%13 = value_metatype $@thick SomeSubclass.Type, %11 : $SomeSubclass
// CHECK: upcast %{{.*}} : $@thick SomeSubclass.Type to $@thick SomeClass.Type
%14 = upcast %13 : $@thick SomeSubclass.Type to $@thick SomeClass.Type
// CHECK: tuple (%{{.*}} : $@thick SomeClass.Type, %{{.*}} : $@thick SomeClass.Type)
%15 = tuple (%9 : $@thick SomeClass.Type, %14 : $@thick SomeClass.Type)
- %16 = strong_release %11 : $SomeSubclass
- %17 = strong_release %7 : $SomeClass
- %18 = strong_release %3 : $<τ_0_0> { var τ_0_0 } <SomeSubclass>
- %19 = strong_release %2 : $<τ_0_0> { var τ_0_0 } <SomeClass>
- %20 = return %15 : $(@thick SomeClass.Type, @thick SomeClass.Type)
+ strong_release %11 : $SomeSubclass
+ strong_release %7 : $SomeClass
+ strong_release %3 : $<τ_0_0> { var τ_0_0 } <SomeSubclass>
+ strong_release %2 : $<τ_0_0> { var τ_0_0 } <SomeClass>
+ return %15 : $(@thick SomeClass.Type, @thick SomeClass.Type)
}
// CHECK-LABEL: @test_existential_metatype : $@convention(thin) (@in SomeProtocol) -> @thick SomeProtocol.Type {
@@ -562,17 +562,17 @@
%1 = alloc_box $<τ_0_0> { var τ_0_0 } <SomeProtocol>
%1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <SomeProtocol>, 0
// CHECK: copy_addr [take] %0 to [initialization] %{{.*}} : $*SomeProtocol
- %2 = copy_addr [take] %0 to [initialization] %1a : $*SomeProtocol
+ copy_addr [take] %0 to [initialization] %1a : $*SomeProtocol
// CHECK: alloc_stack
%4 = alloc_stack $SomeProtocol
// CHECK: copy_addr %{{.*}} to [initialization] %{{.*}} : $*SomeProtocol
- %5 = copy_addr %1a to [initialization] %4 : $*SomeProtocol
+ copy_addr %1a to [initialization] %4 : $*SomeProtocol
// CHECK: existential_metatype $@thick SomeProtocol.Type, {{%.*}} : $*SomeProtocol
%6 = existential_metatype $@thick SomeProtocol.Type, %4 : $*SomeProtocol
- %7 = destroy_addr %4 : $*SomeProtocol
- %8 = dealloc_stack %4 : $*SomeProtocol
- %9 = strong_release %1 : $<τ_0_0> { var τ_0_0 } <SomeProtocol>
- %10 = return %6 : $@thick SomeProtocol.Type
+ destroy_addr %4 : $*SomeProtocol
+ dealloc_stack %4 : $*SomeProtocol
+ strong_release %1 : $<τ_0_0> { var τ_0_0 } <SomeProtocol>
+ return %6 : $@thick SomeProtocol.Type
}
// CHECK-LABEL: sil public_external [serialized] @test_unreachable
@@ -587,14 +587,14 @@
bb0(%0 : $SomeClass):
%1 = ref_to_unowned %0 : $SomeClass to $@sil_unowned SomeClass
// CHECK: ref_to_unowned %0 : $SomeClass to $@sil_unowned SomeClass
- %2 = unowned_retain %1 : $@sil_unowned SomeClass
+ unowned_retain %1 : $@sil_unowned SomeClass
// CHECK: unowned_retain %1 : $@sil_unowned SomeClass
- %3 = unowned_release %1 : $@sil_unowned SomeClass
+ unowned_release %1 : $@sil_unowned SomeClass
// CHECK: unowned_release %1 : $@sil_unowned SomeClass
%4 = unowned_to_ref %1 : $@sil_unowned SomeClass to $SomeClass
// CHECK: unowned_to_ref %1 : $@sil_unowned SomeClass to $SomeClass
%5 = tuple ()
- %6 = return %5 : $()
+ return %5 : $()
}
// CHECK-LABEL: sil public_external [serialized] @test_basic_block_arguments
@@ -883,14 +883,14 @@
%0 = function_ref @classes : $@convention(thin) () -> ()
%1 = apply %0() : $@convention(thin) () -> ()
%2 = tuple ()
- %3 = return %2 : $()
+ return %2 : $()
}
// CHECK-LABEL: sil public_external [serialized] [thunk] @test_thunk : $@convention(thin) () -> () {
sil [serialized] [thunk] @test_thunk : $@convention(thin) () -> () {
bb0:
%0 = tuple ()
- %1 = return %0 : $()
+ return %0 : $()
}
// CHECK-LABEL: [noinline] @noinline_callee
@@ -917,7 +917,7 @@
sil [serialized] [_semantics "foo"] @test_semantics : $@convention(thin) () -> () {
bb0:
%2 = tuple ()
- %3 = return %2 : $()
+ return %2 : $()
}
sil [serialized] @takes_unnamed_closure : $@convention(thin) (@callee_owned () -> Int) -> @callee_owned () -> @callee_owned () -> Int
@@ -930,7 +930,7 @@
%1 = function_ref @takes_int64_float32 : $@convention(thin) (Int, Float) -> ()
// CHECK: partial_apply %{{.*}}(%{{.*}}) : $@convention(thin) (Int, Float) -> ()
%2 = partial_apply %1(%0) : $@convention(thin) (Int, Float) -> ()
- %3 = return %2 : $@callee_owned Int -> ()
+ return %2 : $@callee_owned Int -> ()
}
class X {
diff --git a/test/SwiftSyntax/LazyCaching.swift b/test/SwiftSyntax/LazyCaching.swift
index a3e50c0..1970935 100644
--- a/test/SwiftSyntax/LazyCaching.swift
+++ b/test/SwiftSyntax/LazyCaching.swift
@@ -1,7 +1,6 @@
// RUN: %target-run-simple-swift
// REQUIRES: executable_test
// REQUIRES: OS=macosx
-// REQUIRES: rdar33888321
import StdlibUnittest
import Foundation
diff --git a/test/SwiftSyntax/ParseFile.swift b/test/SwiftSyntax/ParseFile.swift
index 23d7d37..8d9a2b9 100644
--- a/test/SwiftSyntax/ParseFile.swift
+++ b/test/SwiftSyntax/ParseFile.swift
@@ -1,7 +1,6 @@
// RUN: %target-run-simple-swift
// REQUIRES: executable_test
// REQUIRES: OS=macosx
-// REQUIRES: rdar33888321
import Foundation
import StdlibUnittest
diff --git a/test/SwiftSyntax/SyntaxFactory.swift b/test/SwiftSyntax/SyntaxFactory.swift
index 59d0cd5..6686c57 100644
--- a/test/SwiftSyntax/SyntaxFactory.swift
+++ b/test/SwiftSyntax/SyntaxFactory.swift
@@ -1,7 +1,6 @@
// RUN: %target-run-simple-swift
// REQUIRES: executable_test
// REQUIRES: OS=macosx
-// REQUIRES: rdar33888321
import Foundation
import StdlibUnittest
diff --git a/test/decl/protocol/req/recursion.swift b/test/decl/protocol/req/recursion.swift
index 4c8bd90..20bf860 100644
--- a/test/decl/protocol/req/recursion.swift
+++ b/test/decl/protocol/req/recursion.swift
@@ -97,12 +97,7 @@
struct S4<A: PI> : I where A : I {
}
-struct S5<A: PI> : I where A : I, A.T == S4<A> {
-// expected-warning@-1{{redundant conformance constraint 'A': 'I'}}
-// expected-warning@-2{{redundant conformance constraint 'A': 'PI'}}
-// expected-note@-3{{conformance constraint 'A': 'PI' inferred from type here}}
-// expected-note@-4{{conformance constraint 'A': 'I' inferred from type here}}
-}
+struct S5<A: PI> : I where A : I, A.T == S4<A> { }
// Used to hit ArchetypeBuilder assertions
struct SU<A: P> where A.T == SU {
diff --git a/test/sil-func-extractor/basic.sil b/test/sil-func-extractor/basic.sil
index 3f6f167..f4aaf96 100644
--- a/test/sil-func-extractor/basic.sil
+++ b/test/sil-func-extractor/basic.sil
@@ -26,7 +26,7 @@
%3 = function_ref @inout_uninit : $@convention(thin)() -> ()
apply %3() : $@convention(thin) () -> ()
strong_release %1 : $<τ_0_0> { var τ_0_0 } <Int64>
- %4 = return %2 : $Int64
+ return %2 : $Int64
}
// CHECK-NOT: sil @inout_uninit : $@convention(thin) () -> () {
diff --git a/test/stdlib/Inputs/SwiftNativeNSBase/SwiftNativeNSBase.m b/test/stdlib/Inputs/SwiftNativeNSBase/SwiftNativeNSBase.m
index fc52377..a4b93b2 100644
--- a/test/stdlib/Inputs/SwiftNativeNSBase/SwiftNativeNSBase.m
+++ b/test/stdlib/Inputs/SwiftNativeNSBase/SwiftNativeNSBase.m
@@ -40,8 +40,23 @@
} while (0)
-void TestSwiftNativeNSBase(void)
+BOOL TestSwiftNativeNSBase_RetainCount(id object)
{
+ Errors = 0;
+ NSUInteger rc1 = [object retainCount];
+ id object2 = [object retain];
+ expectTrue(object == object2);
+ NSUInteger rc2 = [object retainCount];
+ expectTrue(rc2 > rc1);
+ [object release];
+ NSUInteger rc3 = [object retainCount];
+ expectTrue(rc3 < rc2);
+ return Errors == 0;
+}
+
+BOOL TestSwiftNativeNSBase_UnwantedCdtors()
+{
+ Errors = 0;
printf("TestSwiftNativeNSBase\n");
unsigned int classCount;
@@ -82,5 +97,5 @@
printf("TestSwiftNativeNSBase: %d error%s\n",
Errors, Errors == 1 ? "" : "s");
- exit(Errors ? 1 : 0);
+ return Errors == 0;
}
diff --git a/test/stdlib/Inputs/VariadicBool/module.map b/test/stdlib/Inputs/VariadicBool/module.map
new file mode 100644
index 0000000..fa0bef5
--- /dev/null
+++ b/test/stdlib/Inputs/VariadicBool/module.map
@@ -0,0 +1,3 @@
+module VariadicBool {
+ header "variadicBool.h"
+}
diff --git a/test/stdlib/Inputs/VariadicBool/variadicBool.c b/test/stdlib/Inputs/VariadicBool/variadicBool.c
new file mode 100644
index 0000000..95aa6b4
--- /dev/null
+++ b/test/stdlib/Inputs/VariadicBool/variadicBool.c
@@ -0,0 +1,16 @@
+#include "variadicBool.h"
+
+int numberOfTrues(int count, va_list arguments) {
+ int i, total;
+ total = 0;
+
+ for(i = 0; i < count; i++) {
+ //we're passing int here because passing bool is actually incorrect since
+ //bool is actually promoted to int in C
+ if(va_arg(arguments, int) == true) {
+ total += 1;
+ }
+ }
+
+ return total;
+}
\ No newline at end of file
diff --git a/test/stdlib/Inputs/VariadicBool/variadicBool.h b/test/stdlib/Inputs/VariadicBool/variadicBool.h
new file mode 100644
index 0000000..7980068
--- /dev/null
+++ b/test/stdlib/Inputs/VariadicBool/variadicBool.h
@@ -0,0 +1,5 @@
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdbool.h>
+
+extern int numberOfTrues(int count, va_list arguments);
\ No newline at end of file
diff --git a/test/stdlib/TypeName.swift b/test/stdlib/TypeName.swift
index dfb93e4..496bd71 100644
--- a/test/stdlib/TypeName.swift
+++ b/test/stdlib/TypeName.swift
@@ -185,4 +185,28 @@
_typeName(SomeOuterGenericClass<String>.SomeInnerGenericStruct<Int>.self));
}
+extension SomeOuterGenericClass {
+ struct OtherInnerStruct {}
+ struct OtherInnerGenericStruct<U> {}
+}
+
+TypeNameTests.test("NestedInExtension") {
+ expectEqual("main.SomeOuterGenericClass<Swift.Int>.OtherInnerStruct",
+ _typeName(SomeOuterGenericClass<Int>.OtherInnerStruct.self));
+ expectEqual("main.SomeOuterGenericClass<Swift.Int>.OtherInnerGenericStruct<Swift.String>",
+ _typeName(SomeOuterGenericClass<Int>.OtherInnerGenericStruct<String>.self));
+}
+
+extension SomeOuterGenericClass where T == Int {
+ struct AnotherInnerStruct {}
+ struct AnotherInnerGenericStruct<U> {}
+}
+
+TypeNameTests.test("NestedInConstrainedExtension") {
+ expectEqual("main.SomeOuterGenericClass.AnotherInnerStruct",
+ _typeName(SomeOuterGenericClass<Int>.AnotherInnerStruct.self));
+ expectEqual("main.SomeOuterGenericClass.AnotherInnerGenericStruct<Swift.String>",
+ _typeName(SomeOuterGenericClass<Int>.AnotherInnerGenericStruct<String>.self));
+}
+
runAllTests()
diff --git a/test/stmt/if_while_var.swift b/test/stmt/if_while_var.swift
index c2393ff..c35399a 100644
--- a/test/stmt/if_while_var.swift
+++ b/test/stmt/if_while_var.swift
@@ -94,7 +94,7 @@
if 1 != 2, 4 == 57, let x = opt {} // expected-warning {{immutable value 'x' was never used; consider replacing with '_' or removing it}}
// Test that these don't cause the parser to crash.
-if true { if a == 0; {} } // expected-error {{expected '{' after 'if' condition}} expected-error 2{{}} expected-note 1{{}}
+if true { if a == 0; {} } // expected-error {{use of unresolved identifier 'a'}} expected-error {{expected '{' after 'if' condition}}
if a == 0, where b == 0 {} // expected-error 3{{}} expected-note {{}} {{25-25=do }}
diff --git a/tools/SourceKit/include/SourceKit/Core/ProtocolUIDs.def b/tools/SourceKit/include/SourceKit/Core/ProtocolUIDs.def
index 8f019c7..b332d41 100644
--- a/tools/SourceKit/include/SourceKit/Core/ProtocolUIDs.def
+++ b/tools/SourceKit/include/SourceKit/Core/ProtocolUIDs.def
@@ -270,6 +270,7 @@
KIND(ExprArray, "source.lang.swift.expr.array")
KIND(ExprDictionary, "source.lang.swift.expr.dictionary")
KIND(ExprObjectLiteral, "source.lang.swift.expr.object_literal")
+KIND(ExprTuple, "source.lang.swift.expr.tuple")
KIND(StructureElemId, "source.lang.swift.structure.elem.id")
KIND(StructureElemExpr, "source.lang.swift.structure.elem.expr")
KIND(StructureElemInitExpr, "source.lang.swift.structure.elem.init_expr")
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp
index 3e7ad81..dfb75c6 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp
@@ -421,6 +421,8 @@
return KindExprDictionary;
case SyntaxStructureKind::ObjectLiteralExpression:
return KindExprObjectLiteral;
+ case SyntaxStructureKind::TupleExpression:
+ return KindExprTuple;
case SyntaxStructureKind::Argument:
return KindExprArg;
}
diff --git a/tools/swift-ide-test/swift-ide-test.cpp b/tools/swift-ide-test/swift-ide-test.cpp
index e6f4d81..e2566ce 100644
--- a/tools/swift-ide-test/swift-ide-test.cpp
+++ b/tools/swift-ide-test/swift-ide-test.cpp
@@ -1090,6 +1090,7 @@
case SyntaxStructureKind::DictionaryExpression: return "dictionary";
case SyntaxStructureKind::ObjectLiteralExpression:
return "object-literal-expression";
+ case SyntaxStructureKind::TupleExpression: return "tuple";
}
llvm_unreachable("unhandled tag?");
}
diff --git a/unittests/runtime/Metadata.cpp b/unittests/runtime/Metadata.cpp
index d53b6dc..85e1beb 100644
--- a/unittests/runtime/Metadata.cpp
+++ b/unittests/runtime/Metadata.cpp
@@ -165,13 +165,14 @@
uint32_t Global3 = 0;
/// The general structure of a generic metadata.
-template <typename Instance>
+template <typename Instance, unsigned NumArguments>
struct GenericMetadataTest {
GenericMetadata Header;
Instance Template;
+ void *Storage[NumArguments];
};
-GenericMetadataTest<StructMetadata> MetadataTest1 = {
+GenericMetadataTest<StructMetadata, 1> MetadataTest1 = {
// Header
{
// allocation function
@@ -191,9 +192,11 @@
// Fields
{
MetadataKind::Struct,
- reinterpret_cast<const NominalTypeDescriptor*>(&Global1),
- nullptr
- }
+ reinterpret_cast<const NominalTypeDescriptor*>(&Global1)
+ },
+
+ // Arguments
+ {nullptr}
};
struct TestObjContainer {
diff --git a/utils/build-script b/utils/build-script
index c377d7f..0345340 100755
--- a/utils/build-script
+++ b/utils/build-script
@@ -127,7 +127,11 @@
test = (
deployment_platform not in invocation.platforms_to_skip_test)
test_host_only = None
- build_benchmark = build and deployment_target.supports_benchmark
+ dt_supports_benchmark = deployment_target.supports_benchmark
+ build_benchmarks = build and dt_supports_benchmark
+ build_external_benchmarks = all([build, dt_supports_benchmark,
+ args.build_external_benchmarks])
+
# FIXME: Note, `build-script-impl` computed a property here
# w.r.t. testing, but it was actually unused.
@@ -161,13 +165,20 @@
else:
self.swift_stdlib_build_targets.append(
"swift-test-stdlib-" + name)
- if build_benchmark:
+ if build_benchmarks:
self.swift_benchmark_build_targets.append(
"swift-benchmark-" + name)
# FIXME: This probably should respect `args.benchmark`, but
# a typo in build-script-impl meant we always would do this.
self.swift_benchmark_run_targets.append(
"check-swift-benchmark-" + name)
+
+ if build_external_benchmarks:
+ # Add support for the external benchmarks.
+ self.swift_benchmark_build_targets.append(
+ "swift-benchmark-{}-external".format(name))
+ self.swift_benchmark_run_targets.append(
+ "check-swift-benchmark-{}-external".format(name))
if test:
if test_host_only:
suffix = "-non-executable"
@@ -304,7 +315,7 @@
self.platforms_to_skip_test.add(StdlibDeploymentTarget.Cygwin)
if not args.test_osx:
self.platforms_to_skip_test.add(StdlibDeploymentTarget.OSX)
- if not args.test_ios_device:
+ if not args.test_ios_host:
self.platforms_to_skip_test.add(StdlibDeploymentTarget.iOS)
else:
exit_rejecting_arguments("error: iOS device tests are not " +
@@ -315,7 +326,7 @@
if not args.test_ios_32bit_simulator:
self.platforms_archs_to_skip_test.add(
StdlibDeploymentTarget.iOSSimulator.i386)
- if not args.test_tvos_device:
+ if not args.test_tvos_host:
self.platforms_to_skip_test.add(StdlibDeploymentTarget.AppleTV)
else:
exit_rejecting_arguments("error: tvOS device tests are not " +
@@ -323,7 +334,7 @@
if not args.test_tvos_simulator:
self.platforms_to_skip_test.add(
StdlibDeploymentTarget.AppleTVSimulator)
- if not args.test_watchos_device:
+ if not args.test_watchos_host:
self.platforms_to_skip_test.add(StdlibDeploymentTarget.AppleWatch)
else:
exit_rejecting_arguments("error: watchOS device tests are not " +
@@ -332,16 +343,16 @@
self.platforms_to_skip_test.add(
StdlibDeploymentTarget.AppleWatchSimulator)
- if not args.test_android_device:
+ if not args.test_android_host:
self.platforms_to_skip_test.add(StdlibDeploymentTarget.Android)
self.platforms_to_skip_test_host = set()
- if not args.test_ios_device:
+ if not args.test_ios_host:
self.platforms_to_skip_test_host.add(StdlibDeploymentTarget.iOS)
- if not args.test_tvos_device:
+ if not args.test_tvos_host:
self.platforms_to_skip_test_host.add(
StdlibDeploymentTarget.AppleTV)
- if not args.test_watchos_device:
+ if not args.test_watchos_host:
self.platforms_to_skip_test_host.add(
StdlibDeploymentTarget.AppleWatch)
@@ -506,6 +517,9 @@
"--skip-build-swift"]
if not args.build_benchmarks:
impl_args += ["--skip-build-benchmarks"]
+ # Currently we do not build external benchmarks by default.
+ if args.build_external_benchmarks:
+ impl_args += ["--skip-build-external-benchmarks=0"]
if not args.build_foundation:
impl_args += ["--skip-build-foundation"]
if not args.build_xctest:
@@ -579,21 +593,21 @@
impl_args += ["--skip-test-cygwin"]
if not args.test_osx:
impl_args += ["--skip-test-osx"]
- if not args.test_ios_device:
+ if not args.test_ios_host:
impl_args += ["--skip-test-ios-host"]
if not args.test_ios_simulator:
impl_args += ["--skip-test-ios-simulator"]
if not args.test_ios_32bit_simulator:
impl_args += ["--skip-test-ios-32bit-simulator"]
- if not args.test_tvos_device:
+ if not args.test_tvos_host:
impl_args += ["--skip-test-tvos-host"]
if not args.test_tvos_simulator:
impl_args += ["--skip-test-tvos-simulator"]
- if not args.test_watchos_device:
+ if not args.test_watchos_host:
impl_args += ["--skip-test-watchos-host"]
if not args.test_watchos_simulator:
impl_args += ["--skip-test-watchos-simulator"]
- if not args.test_android_device:
+ if not args.test_android_host:
impl_args += ["--skip-test-android-host"]
if args.build_runtime_with_host_compiler:
impl_args += ["--build-runtime-with-host-compiler"]
diff --git a/utils/build-script-impl b/utils/build-script-impl
index 0de5738..5a65bba 100755
--- a/utils/build-script-impl
+++ b/utils/build-script-impl
@@ -126,6 +126,7 @@
skip-build-libdispatch "" "set to skip building libdispatch"
skip-build-libicu "" "set to skip building libicu"
skip-build-benchmarks "" "set to skip building Swift Benchmark Suite"
+ skip-build-external-benchmarks "1" "set to skip building the external Swift Benchmark Suite. (skipped by default)"
skip-build-playgroundlogger "" "set to skip building PlaygroundLogger"
skip-build-playgroundsupport "" "set to skip building PlaygroundSupport"
skip-test-cmark "" "set to skip testing CommonMark"
@@ -1324,6 +1325,7 @@
local test_this_target=1
local test_host_only=
local build_benchmark_this_target=
+ local build_external_benchmark_this_target=
local test_benchmark_this_target=
case ${stdlib_deployment_target} in
@@ -1352,6 +1354,7 @@
build_for_this_target=$(not ${SKIP_BUILD_OSX})
test_this_target=$(not ${SKIP_TEST_OSX})
build_benchmark_this_target=$(not ${SKIP_BUILD_OSX})
+ build_external_benchmark_this_target=$(not ${SKIP_BUILD_OSX})
test_benchmark_this_target=$(not ${SKIP_BUILD_OSX})
;;
iphoneos-*)
@@ -1363,10 +1366,12 @@
test_this_target=
fi
build_benchmark_this_target=$(not ${SKIP_BUILD_IOS_DEVICE})
+ build_external_benchmark_this_target=$(not ${SKIP_BUILD_IOS_DEVICE})
# Never build iOS armv7s benchmarks.
if [[ "${stdlib_deployment_target}" == "iphoneos-armv7s" ]]; then
build_benchmark_this_target=
+ build_external_benchmark_this_target=
fi
;;
iphonesimulator-x86_64)
@@ -1391,6 +1396,7 @@
test_this_target=
fi
build_benchmark_this_target=$(not ${SKIP_BUILD_TVOS_DEVICE})
+ build_external_benchmark_this_target=$(not ${SKIP_BUILD_TVOS_DEVICE})
;;
appletvsimulator-*)
swift_sdk="TVOS_SIMULATOR"
@@ -1406,6 +1412,7 @@
test_this_target=
fi
build_benchmark_this_target=$(not ${SKIP_BUILD_WATCHOS_DEVICE})
+ build_external_benchmark_this_target=$(not ${SKIP_BUILD_WATCHOS_DEVICE})
;;
watchsimulator-*)
swift_sdk="WATCHOS_SIMULATOR"
@@ -1443,6 +1450,16 @@
SWIFT_RUN_BENCHMARK_TARGETS+=("check-swift-benchmark-${stdlib_deployment_target}")
fi
fi
+
+ if [[ "$(true_false ${SKIP_BUILD_EXTERNAL_BENCHMARKS})" == "FALSE" ]] &&
+ [[ "${build_external_benchmark_this_target}" ]] &&
+ [[ "${is_in_build_list}" ]] ; then
+ SWIFT_BENCHMARK_TARGETS+=("swift-benchmark-${stdlib_deployment_target}-external")
+ if [[ $(not ${SKIP_TEST_BENCHMARK}) ]] ; then
+ SWIFT_RUN_BENCHMARK_TARGETS+=("check-swift-benchmark-${stdlib_deployment_target}-external")
+ fi
+ fi
+
if [[ "${test_this_target}" ]] && [[ "${is_in_build_list}" ]]; then
test_target_suffix=""
if [[ -n "${test_host_only}" ]] ; then
@@ -2098,13 +2115,16 @@
# Don't build benchmarks and tests when building cross compiler.
build_perf_testsuite_this_time=false
+ build_external_perf_testsuite_this_time=false
build_tests_this_time=false
native_llvm_tools_path="$(build_directory "${LOCAL_HOST}" llvm)/bin"
native_clang_tools_path="$(build_directory "${LOCAL_HOST}" llvm)/bin"
native_swift_tools_path="$(build_directory "${LOCAL_HOST}" swift)/bin"
else
+ # FIXME: Why is the next line not using false_true?
build_perf_testsuite_this_time=$(true_false "$(not ${SKIP_BUILD_BENCHMARKS})")
+ build_external_perf_testsuite_this_time=$(false_true "${SKIP_BUILD_EXTERNAL_BENCHMARKS}")
build_tests_this_time=${SWIFT_INCLUDE_TESTS}
fi
@@ -2162,6 +2182,7 @@
-DSWIFT_BUILD_DYNAMIC_SDK_OVERLAY:BOOL=$(true_false "${BUILD_SWIFT_DYNAMIC_SDK_OVERLAY}")
-DSWIFT_BUILD_STATIC_SDK_OVERLAY:BOOL=$(true_false "${BUILD_SWIFT_STATIC_SDK_OVERLAY}")
-DSWIFT_BUILD_PERF_TESTSUITE:BOOL=$(true_false "${build_perf_testsuite_this_time}")
+ -DSWIFT_BUILD_EXTERNAL_PERF_TESTSUITE:BOOL=$(true_false "${build_external_perf_testsuite_this_time}")
-DSWIFT_BUILD_EXAMPLES:BOOL=$(true_false "${BUILD_SWIFT_EXAMPLES}")
-DSWIFT_INCLUDE_TESTS:BOOL=$(true_false "${build_tests_this_time}")
-DSWIFT_INSTALL_COMPONENTS:STRING="${SWIFT_INSTALL_COMPONENTS}"
diff --git a/utils/build_swift/driver_arguments.py b/utils/build_swift/driver_arguments.py
index d7c43d5..2dff6ea 100644
--- a/utils/build_swift/driver_arguments.py
+++ b/utils/build_swift/driver_arguments.py
@@ -153,6 +153,7 @@
args.build_watchos = False
args.build_android = False
args.build_benchmarks = False
+ args.build_external_benchmarks = False
args.build_lldb = False
args.build_llbuild = False
args.build_swiftpm = False
@@ -214,43 +215,43 @@
# --skip-test-ios is merely a shorthand for host and simulator tests.
if not args.test_ios:
- args.test_ios_device = False
+ args.test_ios_host = False
args.test_ios_simulator = False
# --skip-test-tvos is merely a shorthand for host and simulator tests.
if not args.test_tvos:
- args.test_tvos_device = False
+ args.test_tvos_host = False
args.test_tvos_simulator = False
# --skip-test-watchos is merely a shorthand for host and simulator
# --tests.
if not args.test_watchos:
- args.test_watchos_device = False
+ args.test_watchos_host = False
args.test_watchos_simulator = False
# --skip-build-{ios,tvos,watchos}-{device,simulator} implies
# --skip-test-{ios,tvos,watchos}-{host,simulator}
if not args.build_ios_device:
- args.test_ios_device = False
+ args.test_ios_host = False
if not args.build_ios_simulator:
args.test_ios_simulator = False
if not args.build_tvos_device:
- args.test_tvos_device = False
+ args.test_tvos_host = False
if not args.build_tvos_simulator:
args.test_tvos_simulator = False
if not args.build_watchos_device:
- args.test_watchos_device = False
+ args.test_watchos_host = False
if not args.build_watchos_simulator:
args.test_watchos_simulator = False
if not args.build_android:
- args.test_android_device = False
+ args.test_android_host = False
if not args.host_test:
- args.test_ios_device = False
- args.test_tvos_device = False
- args.test_watchos_device = False
- args.test_android_device = False
+ args.test_ios_host = False
+ args.test_tvos_host = False
+ args.test_watchos_host = False
+ args.test_android_host = False
if args.build_subdir is None:
args.build_subdir = \
@@ -771,6 +772,12 @@
action=arguments.action.optional_false,
help="skip building Swift Benchmark Suite")
+ run_build_group.add_argument(
+ "--build-external-benchmarks",
+ dest='build_external_benchmarks',
+ action=arguments.action.optional_true,
+ help="skip building Swift Benchmark Suite")
+
skip_test_group = parser.add_argument_group(
title="Skip testing specified targets")
skip_test_group.add_argument(
@@ -791,7 +798,7 @@
help="skip testing iOS 32 bit simulator targets")
skip_test_group.add_argument(
"--skip-test-ios-host",
- dest='test_ios_device',
+ dest='test_ios_host',
action=arguments.action.optional_false,
help="skip testing iOS device targets on the host machine (the phone "
"itself)")
@@ -808,7 +815,7 @@
help="skip testing tvOS simulator targets")
skip_test_group.add_argument(
"--skip-test-tvos-host",
- dest='test_tvos_device',
+ dest='test_tvos_host',
action=arguments.action.optional_false,
help="skip testing tvOS device targets on the host machine (the TV "
"itself)")
@@ -825,13 +832,13 @@
help="skip testing watchOS simulator targets")
skip_test_group.add_argument(
"--skip-test-watchos-host",
- dest='test_watchos_device',
+ dest='test_watchos_host',
action=arguments.action.optional_false,
help="skip testing watchOS device targets on the host machine (the "
"watch itself)")
skip_test_group.add_argument(
"--skip-test-android-host",
- dest='test_android_device',
+ dest='test_android_host',
action=arguments.action.optional_false,
help="skip testing Android device targets on the host machine (the "
"phone itself)")
diff --git a/utils/build_swift/tests/expected_options.py b/utils/build_swift/tests/expected_options.py
index af46936..7282eb1 100644
--- a/utils/build_swift/tests/expected_options.py
+++ b/utils/build_swift/tests/expected_options.py
@@ -45,6 +45,7 @@
'build_args': [],
'build_benchmarks': True,
'build_cygwin': True,
+ 'build_external_benchmarks': False,
'build_foundation': False,
'build_freebsd': True,
'build_ios': True,
@@ -153,12 +154,12 @@
'swift_user_visible_version': '4.1',
'symbols_package': None,
'test': None,
- 'test_android_device': False,
+ 'test_android_host': False,
'test_cygwin': False,
'test_freebsd': False,
'test_ios': False,
'test_ios_32bit_simulator': True,
- 'test_ios_device': False,
+ 'test_ios_host': False,
'test_ios_simulator': False,
'test_linux': False,
'test_optimize_for_size': None,
@@ -166,10 +167,10 @@
'test_osx': False,
'test_paths': [],
'test_tvos': False,
- 'test_tvos_device': False,
+ 'test_tvos_host': False,
'test_tvos_simulator': False,
'test_watchos': False,
- 'test_watchos_device': False,
+ 'test_watchos_host': False,
'test_watchos_simulator': False,
'tvos': False,
'tvos_all': False,
@@ -349,6 +350,8 @@
Option('-x', dest='cmake_generator', value='Xcode'),
ToggleOption('--android', dest='android'),
+ ToggleOption('--build-external-benchmarks',
+ dest='build_external_benchmarks'),
ToggleOption('--build-ninja', dest='build_ninja'),
ToggleOption('--build-runtime-with-host-compiler',
dest='build_runtime_with_host_compiler'),
@@ -393,22 +396,22 @@
dest='build_watchos_device'),
ToggleOption('--skip-build-watchos-simulator',
dest='build_watchos_simulator'),
- ToggleOption('--skip-test-android-host', dest='test_android_device'),
+ ToggleOption('--skip-test-android-host', dest='test_android_host'),
ToggleOption('--skip-test-cygwin', dest='test_cygwin'),
ToggleOption('--skip-test-freebsd', dest='test_freebsd'),
ToggleOption('--skip-test-ios', dest='test_ios'),
ToggleOption('--skip-test-ios-32bit-simulator',
dest='test_ios_32bit_simulator'),
- ToggleOption('--skip-test-ios-host', dest='test_ios_device'),
+ ToggleOption('--skip-test-ios-host', dest='test_ios_host'),
ToggleOption('--skip-test-ios-simulator', dest='test_ios_simulator'),
ToggleOption('--skip-test-linux', dest='test_linux'),
ToggleOption('--skip-test-osx', dest='test_osx'),
ToggleOption('--skip-test-tvos', dest='test_tvos'),
- ToggleOption('--skip-test-tvos-host', dest='test_tvos_device'),
+ ToggleOption('--skip-test-tvos-host', dest='test_tvos_host'),
ToggleOption('--skip-test-tvos-simulator',
dest='test_tvos_simulator'),
ToggleOption('--skip-test-watchos', dest='test_watchos'),
- ToggleOption('--skip-test-watchos-host', dest='test_watchos_device'),
+ ToggleOption('--skip-test-watchos-host', dest='test_watchos_host'),
ToggleOption('--skip-test-watchos-simulator',
dest='test_watchos_simulator'),
ToggleOption('--test', dest='test'),
diff --git a/utils/build_swift/tests/test_driver_arguments.py b/utils/build_swift/tests/test_driver_arguments.py
index f5c9b94..49ebe69 100644
--- a/utils/build_swift/tests/test_driver_arguments.py
+++ b/utils/build_swift/tests/test_driver_arguments.py
@@ -446,7 +446,7 @@
self.assertFalse(args.build_ios_simulator)
# Also implies that the tests should be skipped
- self.assertFalse(args.test_ios_device)
+ self.assertFalse(args.test_ios_host)
self.assertFalse(args.test_ios_simulator)
def test_implied_defaults_skip_build_tvos(self):
@@ -456,7 +456,7 @@
self.assertFalse(args.build_tvos_simulator)
# Also implies that the tests should be skipped
- self.assertFalse(args.test_tvos_device)
+ self.assertFalse(args.test_tvos_host)
self.assertFalse(args.test_tvos_simulator)
def test_implied_defaults_skip_build_watchos(self):
@@ -466,7 +466,7 @@
self.assertFalse(args.build_watchos_simulator)
# Also implies that the tests should be skipped
- self.assertFalse(args.test_watchos_device)
+ self.assertFalse(args.test_watchos_host)
self.assertFalse(args.test_watchos_simulator)
def test_implied_defaults_validation_test(self):
@@ -503,37 +503,37 @@
def test_implied_defaults_skip_test_ios(self):
with self.assertNotRaises(ParserError):
args = self.parse_args(['--skip-test-ios'])
- self.assertFalse(args.test_ios_device)
+ self.assertFalse(args.test_ios_host)
self.assertFalse(args.test_ios_simulator)
def test_implied_defaults_skip_test_tvos(self):
with self.assertNotRaises(ParserError):
args = self.parse_args(['--skip-test-tvos'])
- self.assertFalse(args.test_tvos_device)
+ self.assertFalse(args.test_tvos_host)
self.assertFalse(args.test_tvos_simulator)
def test_implied_defaults_skip_test_watchos(self):
with self.assertNotRaises(ParserError):
args = self.parse_args(['--skip-test-watchos'])
- self.assertFalse(args.test_watchos_device)
+ self.assertFalse(args.test_watchos_host)
self.assertFalse(args.test_watchos_simulator)
def test_implied_defaults_skip_build_android(self):
with self.assertNotRaises(ParserError):
args = self.parse_args(['--android', '0'])
- self.assertFalse(args.test_android_device)
+ self.assertFalse(args.test_android_host)
with self.assertNotRaises(ParserError):
args = self.parse_args(['--skip-build-android'])
- self.assertFalse(args.test_android_device)
+ self.assertFalse(args.test_android_host)
def test_implied_defaults_host_test(self):
with self.assertNotRaises(ParserError):
args = self.parse_args(['--host-test', '0'])
- self.assertFalse(args.test_ios_device)
- self.assertFalse(args.test_tvos_device)
- self.assertFalse(args.test_watchos_device)
- self.assertFalse(args.test_android_device)
+ self.assertFalse(args.test_ios_host)
+ self.assertFalse(args.test_tvos_host)
+ self.assertFalse(args.test_watchos_host)
+ self.assertFalse(args.test_android_host)
if __name__ == '__main__':
diff --git a/validation-test/SIL/crashers_fixed/027-swift-nominaltypedecl-getdeclaredtype.sil b/validation-test/SIL/crashers_fixed/027-swift-nominaltypedecl-getdeclaredtype.sil
index d28e59d..cfc7e25 100644
--- a/validation-test/SIL/crashers_fixed/027-swift-nominaltypedecl-getdeclaredtype.sil
+++ b/validation-test/SIL/crashers_fixed/027-swift-nominaltypedecl-getdeclaredtype.sil
@@ -40,7 +40,7 @@
}
}
bb0(thin) : AssocReqt module def_basic {}
-%12 = strong_release %5 : $*Spoon
+strong_release %5 : $*Spoon
%8 = unchecked_addr_cast %101 = tuple(%2 : $*SomeClass.Type) -> (Int, 5
sil [_semantics "foo(%2 = apply [fragile] @owned A>
%14 = alloc_box $@convention(thin) : $@owned A, bb1:
diff --git a/validation-test/Sema/type_checker_perf/fast/rdar22282851.swift b/validation-test/Sema/type_checker_perf/slow/rdar22282851.swift
similarity index 63%
rename from validation-test/Sema/type_checker_perf/fast/rdar22282851.swift
rename to validation-test/Sema/type_checker_perf/slow/rdar22282851.swift
index 9c790d7..0dfe5a8 100644
--- a/validation-test/Sema/type_checker_perf/fast/rdar22282851.swift
+++ b/validation-test/Sema/type_checker_perf/slow/rdar22282851.swift
@@ -7,5 +7,6 @@
func rdar22282851(_ a: [S]) -> [S] {
let result = a.sorted{ $0.s < $1.s || ($0.s == $1.s && $0.s < $1.s) }
+ // expected-error@-1 {{expression was too complex to be solved in reasonable time; consider breaking up the expression into distinct sub-expressions}}
return result
}
diff --git a/validation-test/compiler_crashers_2_fixed/0119-rdar33613329.swift b/validation-test/compiler_crashers_2_fixed/0119-rdar33613329.swift
new file mode 100644
index 0000000..1d251d6
--- /dev/null
+++ b/validation-test/compiler_crashers_2_fixed/0119-rdar33613329.swift
@@ -0,0 +1,45 @@
+// RUN: %target-typecheck-verify-swift %s
+
+precedencegroup BindingPrecedence {
+ higherThan: DefaultPrecedence
+}
+
+infix operator ~>
+infix operator ≈> : BindingPrecedence
+
+struct M<L : P, R> {
+ let f: L
+ let b: (inout L.B) -> R
+
+ init(f: L, b: @escaping (inout L.B) -> R) {
+ self.f = f
+ self.b = b
+ }
+}
+
+protocol P {
+ associatedtype A
+ associatedtype B
+
+ func `in`<R>(_ a: inout A, apply body: (inout B) -> R) -> R
+
+ static func ~> (_: A, _: Self) -> B
+}
+
+extension P {
+ static func ≈> <R>(f: Self, b: @escaping (inout B) -> R) -> M<Self, R> {}
+}
+
+extension WritableKeyPath : P {
+ typealias A = Root
+ typealias B = Value
+
+ func `in`<R>(_ a: inout A, apply body: (inout B) -> R) -> R {}
+
+ static func ~> (a: A, path: WritableKeyPath) -> B {}
+}
+
+struct X { var y: Int = 0 }
+var x = X()
+x ~> \X.y ≈> { a in a += 1; return 3 }
+// expected-error@-1 {{cannot convert call result type 'M<WritableKeyPath<X, Int>, _>' to expected type 'WritableKeyPath<_, _>'}}
diff --git a/validation-test/execution/crashers/rdar18157434.swift b/validation-test/execution/crashers_fixed/rdar33767511.swift
similarity index 90%
rename from validation-test/execution/crashers/rdar18157434.swift
rename to validation-test/execution/crashers_fixed/rdar33767511.swift
index 5d0bfd8..825e4b1 100644
--- a/validation-test/execution/crashers/rdar18157434.swift
+++ b/validation-test/execution/crashers_fixed/rdar33767511.swift
@@ -1,7 +1,7 @@
// RUN: rm -rf %t
// RUN: mkdir -p %t
// RUN: %target-build-swift %s -o %t/a.out
-// RUN: not --crash %target-run %t/a.out
+// RUN: %target-run %t/a.out
// REQUIRES: executable_test
// REQUIRES: OS=macosx
diff --git a/validation-test/stdlib/Bool.swift b/validation-test/stdlib/Bool.swift
new file mode 100644
index 0000000..758f155
--- /dev/null
+++ b/validation-test/stdlib/Bool.swift
@@ -0,0 +1,44 @@
+// RUN: mkdir -p %t
+// RUN: %target-clang -x c %S/Inputs/VariadicBool/variadicBool.c -c -o %t/variadicBool.o
+// RUN: %target-build-swift -I %S/Inputs/VariadicBool/ %t/variadicBool.o %s -o %t/a.out
+// RUN: %target-run %t/a.out
+// REQUIRES: executable_test
+
+
+import Swift
+import StdlibUnittest
+import StdlibCollectionUnittest
+import VariadicBool
+
+func countTrues(_ count: Int, _ bools: CVarArg...) -> Int {
+ return Int(withVaList(bools) { numberOfTrues(Int32(count), $0) })
+}
+
+var BoolTestSuite = TestSuite("Bool")
+
+BoolTestSuite.test("AllTrues") {
+ let result = countTrues(2, true, true)
+ expectEqual(2, result)
+}
+
+BoolTestSuite.test("HalfAndHalf") {
+ let result = countTrues(4, true, true, false, false)
+ expectEqual(2, result)
+}
+
+BoolTestSuite.test("AllFalse") {
+ let result = countTrues(2, false, false)
+ expectEqual(0, result)
+}
+
+BoolTestSuite.test("Interleaved") {
+ let result = countTrues(7, false, true, false, true, false, true, false)
+ expectEqual(3, result)
+}
+
+BoolTestSuite.test("FalsePositive") {
+ let result = countTrues(7, false, true, false, true, false, true, false)
+ expectNotEqual(30, result)
+}
+
+runAllTests()
\ No newline at end of file
diff --git a/validation-test/stdlib/BoolDiagnostics.swift b/validation-test/stdlib/BoolDiagnostics.swift
new file mode 100644
index 0000000..95eee5e
--- /dev/null
+++ b/validation-test/stdlib/BoolDiagnostics.swift
@@ -0,0 +1,7 @@
+// RUN: %target-swift-frontend -typecheck -verify %s
+
+func CVarArgs_withBool() {
+ func varArgFunc(_ x: Bool, _ args: CVarArg...) { }
+ let x = false
+ varArgFunc(x, x)
+}
diff --git a/validation-test/stdlib/SwiftNativeNSBase.swift b/validation-test/stdlib/SwiftNativeNSBase.swift
index bb6fc8e..288b565 100644
--- a/validation-test/stdlib/SwiftNativeNSBase.swift
+++ b/validation-test/stdlib/SwiftNativeNSBase.swift
@@ -13,16 +13,71 @@
// RUN: %empty-directory(%t)
//
// RUN: %target-clang %S/Inputs/SwiftNativeNSBase/SwiftNativeNSBase.m -c -o %t/SwiftNativeNSBase.o -g
-// RUN: %target-build-swift %s -I %S/Inputs/SwiftNativeNSBase/ -Xlinker %t/SwiftNativeNSBase.o -o %t/SwiftNativeNSBase
+// RUN: %target-clang -fobjc-arc %S/Inputs/SlurpFastEnumeration/SlurpFastEnumeration.m -c -o %t/SlurpFastEnumeration.o
+// RUN: echo '#sourceLocation(file: "%s", line: 1)' > "%t/main.swift" && cat "%s" >> "%t/main.swift" && chmod -w "%t/main.swift"
+// RUN: %target-build-swift -Xfrontend -disable-access-control %t/main.swift %S/Inputs/DictionaryKeyValueTypes.swift %S/Inputs/DictionaryKeyValueTypesObjC.swift -I %S/Inputs/SwiftNativeNSBase/ -I %S/Inputs/SlurpFastEnumeration/ -Xlinker %t/SlurpFastEnumeration.o -Xlinker %t/SwiftNativeNSBase.o -o %t/SwiftNativeNSBase
// RUN: %target-run %t/SwiftNativeNSBase
// REQUIRES: executable_test
// REQUIRES: objc_interop
import Foundation
+import StdlibUnittest
-@_silgen_name("TestSwiftNativeNSBase")
-func TestSwiftNativeNSBase()
+@_silgen_name("TestSwiftNativeNSBase_UnwantedCdtors")
+func TestSwiftNativeNSBase_UnwantedCdtors() -> Bool
+@_silgen_name("TestSwiftNativeNSBase_RetainCount")
+func TestSwiftNativeNSBase_RetainCount(_: UnsafeMutableRawPointer) -> Bool
-TestSwiftNativeNSBase()
-// does not return
+func classChain(of cls: AnyClass) -> [String] {
+ var chain: [String] = []
+ var cls: AnyClass? = cls
+ while cls != nil {
+ chain.append(NSStringFromClass(cls!))
+ cls = class_getSuperclass(cls)
+ }
+ return chain
+}
+
+var SwiftNativeNSBaseTestSuite = TestSuite("SwiftNativeNSBase")
+
+SwiftNativeNSBaseTestSuite.test("UnwantedCdtors") {
+ expectTrue(TestSwiftNativeNSBase_UnwantedCdtors())
+}
+
+SwiftNativeNSBaseTestSuite.test("_SwiftNativeNSArrayBase.retainCount") {
+ let bridged = getBridgedNSArrayOfRefTypeVerbatimBridged()
+ assert(classChain(of: type(of: bridged)).contains("_SwiftNativeNSArrayBase"))
+ expectTrue(TestSwiftNativeNSBase_RetainCount(
+ Unmanaged.passUnretained(bridged).toOpaque()))
+ _fixLifetime(bridged)
+}
+
+SwiftNativeNSBaseTestSuite.test("_SwiftNativeNSDictionaryBase.retainCount") {
+ let bridged = getBridgedNSDictionaryOfRefTypesBridgedVerbatim()
+ assert(classChain(of: type(of: bridged))
+ .contains("_SwiftNativeNSDictionaryBase"))
+ expectTrue(TestSwiftNativeNSBase_RetainCount(
+ Unmanaged.passUnretained(bridged).toOpaque()))
+ _fixLifetime(bridged)
+}
+
+SwiftNativeNSBaseTestSuite.test("_SwiftNativeNSSetBase.retainCount") {
+ let bridged = Set([10, 20, 30].map{ TestObjCKeyTy($0) })._bridgeToObjectiveC()
+ assert(classChain(of: type(of: bridged)).contains("_SwiftNativeNSSetBase"))
+ expectTrue(TestSwiftNativeNSBase_RetainCount(
+ Unmanaged.passUnretained(bridged).toOpaque()))
+ _fixLifetime(bridged)
+}
+
+SwiftNativeNSBaseTestSuite.setUp {
+ resetLeaksOfDictionaryKeysValues()
+ resetLeaksOfObjCDictionaryKeysValues()
+}
+
+SwiftNativeNSBaseTestSuite.tearDown {
+ expectNoLeaksOfDictionaryKeysValues()
+ expectNoLeaksOfObjCDictionaryKeysValues()
+}
+
+runAllTests()