[vm,compiler] Recalculate loops when aligning loop headers
Loop information may be outdated by the time code is generated
(for example, if flow graph is serialized/deserialized).
Recalculate loop information during code generation if it is needed
in order to align loop headers.
TEST=vm/dart/align_loops_verify_alignment_test
Change-Id: I1edd63354cee9940bbd474dc95535b4b74081830
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/401863
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Slava Egorov <vegorov@google.com>
diff --git a/runtime/tests/vm/dart/align_loops_verify_alignment_test.dart b/runtime/tests/vm/dart/align_loops_verify_alignment_test.dart
index be06e9a..d41a13c 100644
--- a/runtime/tests/vm/dart/align_loops_verify_alignment_test.dart
+++ b/runtime/tests/vm/dart/align_loops_verify_alignment_test.dart
@@ -2,6 +2,8 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+// OtherResources=align_loops_test.dart
+
import 'dart:convert';
import 'dart:io';
import 'dart:async';
@@ -21,12 +23,20 @@
}
}
-Future<void> testAOT(String dillPath, {bool useAsm = false}) async {
- await withTempDir('align-loops-test-${useAsm ? 'asm' : 'elf'}',
- (String tempDir) async {
+Future<void> testAOT(
+ String dillPath, {
+ required bool useAsm,
+ required bool testILSerialization,
+}) async {
+ await withTempDir('align-loops-test-${useAsm ? 'asm' : 'elf'}', (
+ String tempDir,
+ ) async {
// Generate the snapshot
final snapshotPath = path.join(tempDir, 'libtest.so');
- final commonSnapshotArgs = [dillPath];
+ final commonSnapshotArgs = [
+ if (testILSerialization) '--test_il_serialization',
+ dillPath,
+ ];
if (useAsm) {
final assemblyPath = path.join(tempDir, 'test.S');
@@ -68,24 +78,33 @@
await withTempDir('align_loops', (String tempDir) async {
final testProgram = path.join(
- sdkDir, 'runtime', 'tests', 'vm', 'dart', 'align_loops_test.dart');
+ sdkDir,
+ 'runtime',
+ 'tests',
+ 'vm',
+ 'dart',
+ 'align_loops_test.dart',
+ );
final aotDillPath = path.join(tempDir, 'aot_test.dill');
await run(genKernel, <String>[
'--aot',
'--platform',
platformDill,
- ...Platform.executableArguments
- .where((arg) => arg.startsWith('--enable-experiment=')),
+ ...Platform.executableArguments.where(
+ (arg) => arg.startsWith('--enable-experiment='),
+ ),
'-o',
aotDillPath,
- testProgram
+ testProgram,
]);
await Future.wait([
// Test unstripped ELF generation directly.
- testAOT(aotDillPath),
- testAOT(aotDillPath, useAsm: true),
+ testAOT(aotDillPath, useAsm: false, testILSerialization: false),
+ testAOT(aotDillPath, useAsm: true, testILSerialization: false),
+ testAOT(aotDillPath, useAsm: false, testILSerialization: true),
+ testAOT(aotDillPath, useAsm: true, testILSerialization: true),
]);
});
}
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index 2c1a3a5f..8cb2f6f 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -663,7 +663,17 @@
void FlowGraphCompiler::VisitBlocks() {
CompactBlocks();
- if (compiler::Assembler::EmittingComments()) {
+
+#if defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64)
+ const bool should_align_loops =
+ (FLAG_align_all_loops || IsMarkedWithAlignLoops(function())) &&
+ (kPreferredLoopAlignment > 1);
+#else
+ static_assert(kPreferredLoopAlignment == 1);
+ const bool should_align_loops = false;
+#endif // defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64)
+
+ if (should_align_loops || compiler::Assembler::EmittingComments()) {
// The loop_info fields were cleared, recompute.
flow_graph().ComputeLoops();
}
@@ -679,11 +689,6 @@
const auto inner_lr_state = ComputeInnerLRState(flow_graph());
#endif // defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
-#if defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64)
- const bool should_align_loops =
- FLAG_align_all_loops || IsMarkedWithAlignLoops(function());
-#endif // defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64)
-
for (intptr_t i = 0; i < block_order().length(); ++i) {
// Compile the block entry.
BlockEntryInstr* entry = block_order()[i];
@@ -720,13 +725,10 @@
}
#if defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64)
- if (should_align_loops && entry->IsLoopHeader() &&
- kPreferredLoopAlignment > 1) {
+ if (should_align_loops && entry->IsLoopHeader()) {
assembler()->mark_should_be_aligned();
assembler()->Align(kPreferredLoopAlignment, 0);
}
-#else
- static_assert(kPreferredLoopAlignment == 1);
#endif // defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64)
BeginCodeSourceRange(entry->source());