Skip to content

Commit 09bc0ca

Browse files
vaalfrejamtsamis
authored andcommitted
Optimize out empty switch cases.
Signed-off-by: Julia Koval <c_yuliak@xsightlabs.com>
1 parent 567c0de commit 09bc0ca

File tree

2 files changed

+165
-9
lines changed

2 files changed

+165
-9
lines changed

lib/Dialect/P4HIR/P4HIR_Ops.cpp

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3686,17 +3686,53 @@ void P4HIR::SwitchOp::build(OpBuilder &builder, OperationState &result, mlir::Va
36863686
}
36873687

36883688
LogicalResult P4HIR::SwitchOp::canonicalize(P4HIR::SwitchOp op, PatternRewriter &rewriter) {
3689-
for (auto switchCase : op.cases()) {
3690-
auto &region = switchCase.getCaseRegion();
3691-
if (region.empty()) continue;
3692-
if (!region.hasOneBlock()) return failure();
3689+
auto isEmpty = [](CaseOp caseOp) {
3690+
if (!caseOp) return true;
3691+
auto &region = caseOp.getCaseRegion();
3692+
if (!region.hasOneBlock()) return false;
36933693
auto &block = region.front();
3694-
bool onlyYield =
3695-
(block.getOperations().size() == 1 && mlir::isa<P4HIR::YieldOp>(block.front()));
3696-
if (!onlyYield) return failure();
3694+
return block.getOperations().size() == 1 && mlir::isa<P4HIR::YieldOp>(block.front());
3695+
};
3696+
3697+
auto defaultCase = op.getDefaultCase();
3698+
bool isDefaultEmpty = isEmpty(defaultCase);
3699+
bool allEmpty = true;
3700+
SmallVector<Attribute> mergedValues;
3701+
SmallVector<CaseOp> toRemove;
3702+
3703+
for (auto caseOp : op.cases()) {
3704+
if (!isEmpty(caseOp)) {
3705+
allEmpty = false;
3706+
continue;
3707+
}
3708+
if (caseOp == defaultCase) continue;
3709+
if (!isDefaultEmpty) llvm::append_range(mergedValues, caseOp.getValue());
3710+
toRemove.push_back(caseOp);
3711+
}
3712+
3713+
// All cases empty -> erase switch
3714+
if (allEmpty) {
3715+
rewriter.eraseOp(op);
3716+
return success();
3717+
}
3718+
3719+
// Empty default case -> erase empty cases
3720+
// Non-empty default case -> merge empty cases
3721+
if (isDefaultEmpty) {
3722+
if (toRemove.empty()) return failure();
3723+
for (auto caseToRemove : toRemove) rewriter.eraseOp(caseToRemove);
3724+
return success();
3725+
} else {
3726+
if (toRemove.size() < 2) return failure();
3727+
3728+
rewriter.setInsertionPoint(toRemove[0]);
3729+
rewriter.create<CaseOp>(
3730+
toRemove[0].getLoc(), rewriter.getArrayAttr(mergedValues), CaseOpKind::Anyof,
3731+
[](OpBuilder &builder, Location loc) { builder.create<YieldOp>(loc); });
3732+
3733+
for (auto caseToRemove : toRemove) rewriter.eraseOp(caseToRemove);
3734+
return success();
36973735
}
3698-
rewriter.eraseOp(op);
3699-
return success();
37003736
}
37013737

37023738
//===----------------------------------------------------------------------===//
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
// RUN: p4mlir-opt --canonicalize %s | FileCheck %s
2+
3+
!b32 = !p4hir.bit<32>
4+
!ref_b32 = !p4hir.ref<!b32>
5+
#int1_b32 = #p4hir.int<1> : !b32
6+
#int2_b32 = #p4hir.int<2> : !b32
7+
#int3_b32 = #p4hir.int<3> : !b32
8+
#int4_b32 = #p4hir.int<4> : !b32
9+
#int5_b32 = #p4hir.int<5> : !b32
10+
11+
// CHECK-LABEL: @test_merge_empty_cases
12+
p4hir.func @test_merge_empty_cases(%val: !b32, %ref: !ref_b32) {
13+
// Test that empty cases with empty default are removed
14+
// CHECK: p4hir.switch
15+
// CHECK: p4hir.case(equal, [#int4_b32i])
16+
// CHECK: p4hir.assign
17+
// CHECK: p4hir.case(default
18+
p4hir.switch (%val : !b32) {
19+
p4hir.case(equal, [#int1_b32]) {
20+
p4hir.yield
21+
}
22+
p4hir.case(equal, [#int2_b32]) {
23+
p4hir.yield
24+
}
25+
p4hir.case(anyof, [#int3_b32]) {
26+
p4hir.yield
27+
}
28+
p4hir.case(equal, [#int4_b32]) {
29+
%c = p4hir.const #int5_b32
30+
p4hir.assign %c, %ref : <!b32>
31+
p4hir.yield
32+
}
33+
p4hir.case(default, []) {
34+
p4hir.yield
35+
}
36+
p4hir.yield
37+
}
38+
p4hir.return
39+
}
40+
41+
// CHECK-LABEL: @test_non_empty_default
42+
p4hir.func @test_non_empty_default(%val: !b32, %ref: !ref_b32) {
43+
// Test that empty cases ARE merged even when default is non-empty
44+
// CHECK: p4hir.switch
45+
// CHECK: p4hir.case(anyof, [#int1_b32i, #int2_b32i])
46+
// CHECK-NEXT: p4hir.yield
47+
// CHECK-NEXT: }
48+
// CHECK: p4hir.case(default
49+
p4hir.switch (%val : !b32) {
50+
p4hir.case(equal, [#int1_b32]) {
51+
p4hir.yield
52+
}
53+
p4hir.case(equal, [#int2_b32]) {
54+
p4hir.yield
55+
}
56+
p4hir.case(default, []) {
57+
%c = p4hir.const #int5_b32
58+
p4hir.assign %c, %ref : <!b32>
59+
p4hir.yield
60+
}
61+
p4hir.yield
62+
}
63+
p4hir.return
64+
}
65+
66+
// CHECK-LABEL: @test_mixed_empty_non_empty
67+
p4hir.func @test_mixed_empty_non_empty(%val: !b32, %ref: !ref_b32) {
68+
// Test with mix of empty and non-empty cases with empty default
69+
// Empty cases are removed when default is empty
70+
// CHECK: p4hir.const
71+
// CHECK: p4hir.switch
72+
// CHECK: p4hir.case(equal, [#int2_b32i])
73+
// CHECK: p4hir.assign
74+
// CHECK: p4hir.case(default
75+
p4hir.switch (%val : !b32) {
76+
p4hir.case(equal, [#int1_b32]) {
77+
p4hir.yield
78+
}
79+
p4hir.case(equal, [#int2_b32]) {
80+
%c = p4hir.const #int4_b32
81+
p4hir.assign %c, %ref : <!b32>
82+
p4hir.yield
83+
}
84+
p4hir.case(equal, [#int3_b32]) {
85+
p4hir.yield
86+
}
87+
p4hir.case(default, []) {
88+
p4hir.yield
89+
}
90+
p4hir.yield
91+
}
92+
p4hir.return
93+
}
94+
95+
// CHECK-LABEL: @test_no_default
96+
p4hir.func @test_no_default(%val: !b32, %ref: !ref_b32) {
97+
// Test with no default case - empty cases are removed
98+
// CHECK: p4hir.const
99+
// CHECK: p4hir.switch
100+
// CHECK-NOT: p4hir.case(anyof
101+
// CHECK: p4hir.case(equal, [#int2_b32i])
102+
// CHECK: p4hir.assign
103+
// CHECK-NOT: p4hir.case(equal, [#int1_b32i])
104+
// CHECK-NOT: p4hir.case(equal, [#int3_b32i])
105+
p4hir.switch (%val : !b32) {
106+
p4hir.case(equal, [#int1_b32]) {
107+
p4hir.yield
108+
}
109+
p4hir.case(equal, [#int2_b32]) {
110+
%c = p4hir.const #int4_b32
111+
p4hir.assign %c, %ref : <!b32>
112+
p4hir.yield
113+
}
114+
p4hir.case(equal, [#int3_b32]) {
115+
p4hir.yield
116+
}
117+
p4hir.yield
118+
}
119+
p4hir.return
120+
}

0 commit comments

Comments
 (0)