Skip to content

Commit e810a0a

Browse files
angelomatni1copybara-github
authored andcommitted
Add cycle detection to ResourceSharingPass::PerformFoldingActions.
This change modifies the PerformFoldingActions function to check that the introduction of priority_sel input selection would not introduce a cycle when the folded nodes are merged together. This is to ensure the pass does not produce an unrecoverable error that would otherwise occur when the next pass attempts to iterate nodes using DfsVisitor. This does not yet solve the underlying bug in folding action legalization or analysis that exists but surfaces that error in a more usable way. PiperOrigin-RevId: 895433062
1 parent 563c68d commit e810a0a

File tree

4 files changed

+82
-2
lines changed

4 files changed

+82
-2
lines changed

xls/passes/BUILD

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,6 +1113,7 @@ xls_pass(
11131113
"@com_google_absl//absl/random",
11141114
"@com_google_absl//absl/status",
11151115
"@com_google_absl//absl/status:statusor",
1116+
"@com_google_absl//absl/strings:str_format",
11161117
"@com_google_absl//absl/types:span",
11171118
"@cppitertools",
11181119
],
@@ -4505,9 +4506,15 @@ cc_test(
45054506
name = "resource_sharing_pass_test",
45064507
srcs = ["resource_sharing_pass_test.cc"],
45074508
deps = [
4509+
":bdd_query_engine",
4510+
":bit_provenance_analysis",
4511+
":folding_graph",
4512+
":node_dependency_analysis",
45084513
":optimization_pass",
45094514
":pass_base",
45104515
":resource_sharing_pass",
4516+
":visibility_analysis",
4517+
":visibility_expr_builder",
45114518
"//xls/common:xls_gunit_main",
45124519
"//xls/common/fuzzing:fuzztest",
45134520
"//xls/common/status:matchers",
@@ -4527,7 +4534,9 @@ cc_test(
45274534
"//xls/ir:source_location",
45284535
"//xls/ir:value",
45294536
"//xls/solvers:z3_ir_equivalence_testutils",
4537+
"@com_google_absl//absl/container:flat_hash_set",
45304538
"@com_google_absl//absl/log:check",
4539+
"@com_google_absl//absl/status",
45314540
"@com_google_absl//absl/status:status_matchers",
45324541
"@com_google_absl//absl/status:statusor",
45334542
"@com_google_absl//absl/time",

xls/passes/resource_sharing_pass.cc

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "absl/random/random.h"
3838
#include "absl/status/status.h"
3939
#include "absl/status/statusor.h"
40+
#include "absl/strings/str_format.h"
4041
#include "absl/types/span.h"
4142
#include "cppitertools/combinations.hpp"
4243
#include "cppitertools/zip.hpp"
@@ -1700,6 +1701,7 @@ ResourceSharingPass::SelectFoldingActions(
17001701
absl::StatusOr<bool> ResourceSharingPass::PerformFoldingActions(
17011702
FunctionBase* f, int64_t next_node_id,
17021703
VisibilityBuilder* visibility_builder,
1704+
const NodeBackwardDependencyAnalysis& nda,
17031705
const std::vector<std::unique_ptr<NaryFoldingAction>>&
17041706
folding_actions_to_perform) {
17051707
bool modified = !folding_actions_to_perform.empty();
@@ -1917,6 +1919,26 @@ absl::StatusOr<bool> ResourceSharingPass::PerformFoldingActions(
19171919
}
19181920
XLS_RET_CHECK_EQ(new_operands.size(), 2);
19191921

1922+
// Ensure the priority selects do not depend on any of the folded nodes.
1923+
// This is to avoid creating a cycle and producing an unrecoverable error.
1924+
for (Node* new_operand : new_operands) {
1925+
auto make_error = [&](Node* folded_node, Node* select) {
1926+
return absl::InternalError(absl::StrFormat(
1927+
"Folding action input selection would create a cycle with node "
1928+
"because selection depends on it: %s -> ... -> %s; there is a bug "
1929+
"in the legalization of folding actions or in visibility analysis",
1930+
folded_node->ToString(), select->ToString()));
1931+
};
1932+
for (const auto& [from_node, _] : froms_to_use) {
1933+
if (nda.IsDependent(from_node, new_operand)) {
1934+
return make_error(from_node, new_operand);
1935+
}
1936+
}
1937+
if (nda.IsDependent(to_node, new_operand)) {
1938+
return make_error(to_node, new_operand);
1939+
}
1940+
}
1941+
19201942
// - Step 2: Replace the operands of the @to_node to use the results of the
19211943
// new selectors computed at Step 1.
19221944
VLOG(3) << " Step 2: update the target of the folding transformation";
@@ -2090,8 +2112,9 @@ absl::StatusOr<bool> ResourceSharingPass::RunOnFunctionBaseInternal(
20902112

20912113
// Perform the folding
20922114
XLS_ASSIGN_OR_RETURN(
2093-
modified, PerformFoldingActions(f, next_node_id, &visibility_estimator,
2094-
folding_actions_to_perform));
2115+
modified,
2116+
PerformFoldingActions(f, next_node_id, &visibility_estimator,
2117+
nda_backwards, folding_actions_to_perform));
20952118

20962119
return modified;
20972120
}

xls/passes/resource_sharing_pass.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,7 @@ class ResourceSharingPass : public OptimizationFunctionBasePass {
310310
static absl::StatusOr<bool> PerformFoldingActions(
311311
FunctionBase* f, int64_t next_node_id,
312312
VisibilityBuilder* visibility_builder,
313+
const NodeBackwardDependencyAnalysis& nda,
313314
const std::vector<std::unique_ptr<NaryFoldingAction>>&
314315
folding_actions_to_perform);
315316

xls/passes/resource_sharing_pass_test.cc

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
#include "gmock/gmock.h"
2121
#include "gtest/gtest.h"
2222
#include "xls/common/fuzzing/fuzztest.h"
23+
#include "absl/container/flat_hash_set.h"
2324
#include "absl/log/check.h"
25+
#include "absl/status/status.h"
2426
#include "absl/status/status_matchers.h"
2527
#include "absl/status/statusor.h"
2628
#include "absl/time/time.h"
@@ -43,15 +45,23 @@
4345
#include "xls/ir/package.h"
4446
#include "xls/ir/source_location.h"
4547
#include "xls/ir/value.h"
48+
#include "xls/passes/bdd_query_engine.h"
49+
#include "xls/passes/bit_provenance_analysis.h"
50+
#include "xls/passes/folding_graph.h"
51+
#include "xls/passes/node_dependency_analysis.h"
4652
#include "xls/passes/optimization_pass.h"
4753
#include "xls/passes/pass_base.h"
54+
#include "xls/passes/visibility_analysis.h"
55+
#include "xls/passes/visibility_expr_builder.h"
4856
#include "xls/solvers/z3_ir_equivalence_testutils.h"
4957

5058
namespace xls {
5159

5260
namespace {
5361

5462
using ::absl_testing::IsOkAndHolds;
63+
using ::absl_testing::StatusIs;
64+
using ::testing::HasSubstr;
5565
using ::xls::solvers::z3::ScopedVerifyEquivalence;
5666

5767
class ResourceSharingPassTest : public IrTestBase {
@@ -1408,6 +1418,43 @@ TEST_F(ResourceSharingPassTest, PreventCyclesInFoldingChainsIndirect) {
14081418
EXPECT_EQ(NumberOfShifts(f), 3);
14091419
}
14101420

1421+
using VisibilityEdges =
1422+
absl::flat_hash_set<OperandVisibilityAnalysis::OperandNode>;
1423+
1424+
TEST_F(ResourceSharingPassTest, CatchesCyclesBeforeTransforming) {
1425+
auto p = CreatePackage();
1426+
FunctionBuilder fb(TestName(), p.get());
1427+
Type* u8 = p->GetBitsType(8);
1428+
BValue i = fb.Param("i", u8);
1429+
BValue X = fb.UMul(i, i, 8, SourceInfo(), "X");
1430+
BValue Y = fb.UMul(X, i, 8, SourceInfo(), "D");
1431+
XLS_ASSERT_OK_AND_ASSIGN(Function * f, fb.BuildWithReturnValue(Y));
1432+
int64_t next_node_id = 10;
1433+
1434+
BddQueryEngine bdd_engine;
1435+
XLS_ASSERT_OK(bdd_engine.Populate(f));
1436+
NodeForwardDependencyAnalysis nda;
1437+
XLS_ASSERT_OK(nda.Attach(f));
1438+
BitProvenanceAnalysis bpa;
1439+
XLS_ASSERT_OK(bpa.Populate(f));
1440+
VisibilityBuilder visibility_builder(next_node_id, &bdd_engine, nda, bpa);
1441+
1442+
std::vector<std::pair<Node*, VisibilityEdges>> from_X = {
1443+
std::make_pair(X.node(), VisibilityEdges{})};
1444+
auto fold_X_into_Y = std::make_unique<NaryFoldingAction>(
1445+
std::move(from_X), Y.node(), VisibilityEdges{});
1446+
std::vector<std::unique_ptr<NaryFoldingAction>> folding_actions_to_perform;
1447+
folding_actions_to_perform.push_back(std::move(fold_X_into_Y));
1448+
1449+
NodeBackwardDependencyAnalysis nda_backwards;
1450+
XLS_ASSERT_OK(nda_backwards.Attach(f));
1451+
EXPECT_THAT(
1452+
ResourceSharingPass::PerformFoldingActions(
1453+
f, next_node_id, &visibility_builder, nda_backwards,
1454+
folding_actions_to_perform),
1455+
StatusIs(absl::StatusCode::kInternal, HasSubstr("would create a cycle")));
1456+
}
1457+
14111458
} // namespace
14121459

14131460
} // namespace xls

0 commit comments

Comments
 (0)