Skip to content

Commit 4b6e824

Browse files
committed
[LLHD] Use new combinational process instead of execute regions
Make deseq and process lowering use the new `llhd.combinational` op instead of the existing `scf.execute_region`. The latter is too eager to inline into the parent region, even if the region contains ops with side effects such as probes and drives. These no longer have a clear order in the parent module. The specialized LLHD op is less eager about inlining and can deal with the details of the SSACFG-to-graph region transition in more detail. This commit is basically just a whole bunch of renaming and changing comments. No change intended besides the different op.
1 parent b53a013 commit 4b6e824

File tree

6 files changed

+42
-47
lines changed

6 files changed

+42
-47
lines changed

include/circt/Dialect/LLHD/Transforms/LLHDPasses.td

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -161,18 +161,14 @@ def HoistSignalsPass : Pass<"llhd-hoist-signals"> {
161161
}
162162

163163
def LowerProcessesPass : Pass<"llhd-lower-processes", "hw::HWModuleOp"> {
164-
let summary = "Convert combinational LLHD processes to SCF execute regions";
165-
let dependentDialects = [
166-
"mlir::scf::SCFDialect",
167-
];
164+
let summary = "Convert process ops to combinational ops where possible";
168165
}
169166

170167
def DeseqPass : Pass<"llhd-deseq", "hw::HWModuleOp"> {
171168
let summary = "Convert sequential processes to registers";
172169
let dependentDialects = [
173170
"comb::CombDialect",
174171
"hw::HWDialect",
175-
"mlir::scf::SCFDialect",
176172
"seq::SeqDialect",
177173
];
178174
}

lib/Dialect/LLHD/Transforms/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,5 @@ add_circt_dialect_library(CIRCTLLHDTransforms
2424
MLIRControlFlowDialect
2525
MLIRFuncDialect
2626
MLIRIR
27-
MLIRSCFDialect
2827
MLIRTransformUtils
2928
)

lib/Dialect/LLHD/Transforms/Deseq.cpp

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@
1212
#include "circt/Dialect/LLHD/Transforms/LLHDPasses.h"
1313
#include "circt/Dialect/Seq/SeqOps.h"
1414
#include "mlir/Analysis/Liveness.h"
15+
#include "mlir/Dialect/Arith/IR/Arith.h"
1516
#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
16-
#include "mlir/Dialect/SCF/IR/SCF.h"
1717
#include "mlir/IR/Dominance.h"
18+
#include "mlir/IR/IRMapping.h"
1819
#include "mlir/IR/Matchers.h"
1920
#include "mlir/Transforms/RegionUtils.h"
2021
#include "llvm/ADT/ScopeExit.h"
@@ -1008,7 +1009,7 @@ void Deseq::implementRegisters() {
10081009
/// the analyzed clock and reset from the given `DriveInfo` and creates the
10091010
/// necessary ops outside the process represent the behavior as a register. It
10101011
/// also calls `specializeValue` and `specializeProcess` to convert the
1011-
/// sequential `llhd.process` into a purely combinational `scf.execute_region`
1012+
/// sequential `llhd.process` into a purely combinational `llhd.combinational`
10121013
/// that is simplified by assuming that the clock edge occurs.
10131014
void Deseq::implementRegister(DriveInfo &drive) {
10141015
OpBuilder builder(drive.op);
@@ -1128,9 +1129,9 @@ void Deseq::implementRegister(DriveInfo &drive) {
11281129

11291130
/// Specialize a value by assuming the values listed in `fixedValues` are at a
11301131
/// constant value in the past and the present. The function is guaranteed to
1131-
/// replace results of the process with results of a new combinational
1132-
/// `scf.execute_region` op. All other behavior is purely an optimization; the
1133-
/// function may not make use of the assignments in `fixedValues` at all.
1132+
/// replace results of the process with results of a new combinational op. All
1133+
/// other behavior is purely an optimization; the function may not make use of
1134+
/// the assignments in `fixedValues` at all.
11341135
Value Deseq::specializeValue(Value value, FixedValues fixedValues) {
11351136
auto result = dyn_cast<OpResult>(value);
11361137
if (!result || result.getOwner() != process)
@@ -1140,12 +1141,12 @@ Value Deseq::specializeValue(Value value, FixedValues fixedValues) {
11401141

11411142
/// Specialize the current process by assuming the values listed in
11421143
/// `fixedValues` are at a constant value in the past and the present. This
1143-
/// function creates a new `scf.execute_region` op with a simplified version
1144-
/// of the process where all uses of the values listed in `fixedValues` are
1145-
/// replaced with their constant counterpart. Since the clock-dependent
1146-
/// behavior of the process has been absorbed into a register, the process can
1147-
/// be replaced with a combinational representation that computes the drive
1148-
/// value and drive condition under the assumption that the clock edge occurs.
1144+
/// function creates a new combinational op with a simplified version of the
1145+
/// process where all uses of the values listed in `fixedValues` are replaced
1146+
/// with their constant counterpart. Since the clock-dependent behavior of the
1147+
/// process has been absorbed into a register, the process can be replaced with
1148+
/// a combinational representation that computes the drive value and drive
1149+
/// condition under the assumption that the clock edge occurs.
11491150
ValueRange Deseq::specializeProcess(FixedValues fixedValues) {
11501151
if (auto it = specializedProcesses.find(fixedValues);
11511152
it != specializedProcesses.end())
@@ -1161,13 +1162,13 @@ ValueRange Deseq::specializeProcess(FixedValues fixedValues) {
11611162
}
11621163
});
11631164

1164-
// Create an `scf.execute_region` with this process specialized to compute
1165+
// Create an `llhd.combinational` op with this process specialized to compute
11651166
// the result for the given fixed values. The triggers will be absorbed into
11661167
// the register operation that consumes the result of this specialized
11671168
// process, such that we can make the process purely combinational.
11681169
OpBuilder builder(process);
1169-
auto executeOp = builder.create<scf::ExecuteRegionOp>(
1170-
process.getLoc(), process.getResultTypes());
1170+
auto executeOp = builder.create<CombinationalOp>(process.getLoc(),
1171+
process.getResultTypes());
11711172

11721173
IRMapping mapping;
11731174
SmallVector<std::pair<Block *, Block *>> worklist;
@@ -1222,14 +1223,14 @@ ValueRange Deseq::specializeProcess(FixedValues fixedValues) {
12221223
auto [oldBlock, newBlock] = worklist.pop_back_val();
12231224
builder.setInsertionPointToEnd(newBlock);
12241225
for (auto &oldOp : *oldBlock) {
1225-
// Convert `llhd.wait` into `scf.yield`.
1226+
// Convert `llhd.wait` into `llhd.halt`.
12261227
if (auto waitOp = dyn_cast<WaitOp>(oldOp)) {
12271228
if (stopAtWait)
12281229
continue;
12291230
SmallVector<Value> operands;
12301231
for (auto operand : waitOp.getYieldOperands())
12311232
operands.push_back(mapping.lookupOrDefault(operand));
1232-
builder.create<scf::YieldOp>(waitOp.getLoc(), operands);
1233+
builder.create<YieldOp>(waitOp.getLoc(), operands);
12331234
continue;
12341235
}
12351236

lib/Dialect/LLHD/Transforms/LowerProcesses.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
#include "circt/Dialect/LLHD/Transforms/LLHDPasses.h"
1212
#include "mlir/Analysis/Liveness.h"
1313
#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
14-
#include "mlir/Dialect/SCF/IR/SCF.h"
1514
#include "mlir/Transforms/RegionUtils.h"
1615
#include "llvm/Support/Debug.h"
1716

@@ -56,16 +55,16 @@ void Lowering::lower() {
5655

5756
// Replace the process.
5857
OpBuilder builder(processOp);
59-
auto executeOp = builder.create<scf::ExecuteRegionOp>(
60-
processOp.getLoc(), processOp.getResultTypes());
58+
auto executeOp = builder.create<CombinationalOp>(processOp.getLoc(),
59+
processOp.getResultTypes());
6160
executeOp.getRegion().takeBody(processOp.getBody());
6261
processOp.replaceAllUsesWith(executeOp);
6362
processOp.erase();
6463
processOp = {};
6564

66-
// Replace the `llhd.wait` with an `scf.yield`.
65+
// Replace the `llhd.wait` with an `llhd.yield`.
6766
builder.setInsertionPoint(waitOp);
68-
builder.create<scf::YieldOp>(waitOp.getLoc(), waitOp.getYieldOperands());
67+
builder.create<YieldOp>(waitOp.getLoc(), waitOp.getYieldOperands());
6968
waitOp.erase();
7069

7170
// Simplify the execute op body region since disconnecting the control flow

test/Dialect/LLHD/Transforms/deseq.mlir

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,10 @@ hw.module @ClockWithEnable(in %clock: i1, in %d: i42, in %en: i1) {
112112
%c0_i42 = hw.constant 0 : i42
113113
%0 = llhd.constant_time <0ns, 1d, 0e>
114114
// CHECK-NOT: llhd.process
115-
// CHECK: [[ER:%.+]]:2 = scf.execute_region -> (i42, i1) {
115+
// CHECK: [[ER:%.+]]:2 = llhd.combinational -> i42, i1 {
116116
// CHECK: cf.cond_br %en, [[BB:\^.+]](%d, %true : i42, i1), [[BB]](%c0_i42, %false : i42, i1)
117117
// CHECK: [[BB]]([[RESULT:%.+]]: i42, [[ENABLE:%.+]]: i1):
118-
// CHECK: scf.yield [[RESULT]], [[ENABLE]] : i42, i1
118+
// CHECK: llhd.yield [[RESULT]], [[ENABLE]] : i42, i1
119119
// CHECK: }
120120
%1, %2 = llhd.process -> i42, i1 {
121121
%true = hw.constant true
@@ -142,10 +142,10 @@ hw.module @ClockWithEnableAndReset(in %clock: i1, in %reset: i1, in %d: i42, in
142142
%c0_i42 = hw.constant 0 : i42
143143
%0 = llhd.constant_time <0ns, 1d, 0e>
144144
// CHECK-NOT: llhd.process
145-
// CHECK: [[ER:%.+]]:2 = scf.execute_region -> (i42, i1) {
145+
// CHECK: [[ER:%.+]]:2 = llhd.combinational -> i42, i1 {
146146
// CHECK: cf.cond_br %en, [[BB:\^.+]](%d, %true : i42, i1), [[BB]](%c0_i42, %false : i42, i1)
147147
// CHECK: [[BB]]([[RESULT:%.+]]: i42, [[ENABLE:%.+]]: i1):
148-
// CHECK: scf.yield [[RESULT]], [[ENABLE]] : i42, i1
148+
// CHECK: llhd.yield [[RESULT]], [[ENABLE]] : i42, i1
149149
// CHECK: }
150150
%1, %2 = llhd.process -> i42, i1 {
151151
%true = hw.constant true
@@ -377,7 +377,7 @@ hw.module @ComplexControlFlow(in %clock: i1, in %d: i42) {
377377
%c0_i42 = hw.constant 0 : i42
378378
%0 = llhd.constant_time <0ns, 1d, 0e>
379379
// CHECK-NOT: llhd.process
380-
// CHECK: [[ER:%.+]]:2 = scf.execute_region -> (i42, i1) {
380+
// CHECK: [[ER:%.+]]:2 = llhd.combinational -> i42, i1 {
381381
// CHECK: cf.br ^bb1(%c0_i42, %false : i42, i1)
382382
// CHECK: ^bb1({{%.+}}: i42, {{%.+}}: i1):
383383
// CHECK: cf.br ^bb2
@@ -392,7 +392,7 @@ hw.module @ComplexControlFlow(in %clock: i1, in %d: i42) {
392392
// CHECK: [[TMP:%.+]] = comb.icmp ult
393393
// CHECK: cf.cond_br [[TMP]], ^bb3({{.+}}), ^bb4([[RESULT]], %true : i42, i1)
394394
// CHECK: ^bb4([[RESULT:%.+]]: i42, [[ENABLE:%.+]]: i1):
395-
// CHECK: scf.yield [[RESULT]], [[ENABLE]] : i42, i1
395+
// CHECK: llhd.yield [[RESULT]], [[ENABLE]] : i42, i1
396396
// CHECK: }
397397
%1, %2 = llhd.process -> i42, i1 {
398398
%true = hw.constant true
@@ -593,7 +593,7 @@ hw.module @LargeControlFlowRegression(in %clk: i1, in %rstn: i1, in %a: i6, in %
593593
%mem33 = llhd.sig %c0_i15 : i15
594594
%mem34 = llhd.sig %c0_i15 : i15
595595
// CHECK-NOT: llhd.process
596-
// CHECK: [[ER:%.+]]:70 = scf.execute_region ->
596+
// CHECK: [[ER:%.+]]:70 = llhd.combinational ->
597597
%1:70 = llhd.process -> i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1 {
598598
cf.br ^bb1(%clk, %rstn, %c0_i15, %false, %c0_i15, %false, %c0_i15, %false, %c0_i15, %false, %c0_i15, %false, %c0_i15, %false, %c0_i15, %false, %c0_i15, %false, %c0_i15, %false, %c0_i15, %false, %c0_i15, %false, %c0_i15, %false, %c0_i15, %false, %c0_i15, %false, %c0_i15, %false, %c0_i15, %false, %c0_i15, %false, %c0_i15, %false, %c0_i15, %false, %c0_i15, %false, %c0_i15, %false, %c0_i15, %false, %c0_i15, %false, %c0_i15, %false, %c0_i15, %false, %c0_i15, %false, %c0_i15, %false, %c0_i15, %false, %c0_i15, %false, %c0_i15, %false, %c0_i15, %false, %c0_i15, %false, %c0_i15, %false, %c0_i15, %false, %c0_i15, %false : i1, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1, i15, i1)
599599
^bb1(%2: i1, %3: i1, %4: i15, %5: i1, %6: i15, %7: i1, %8: i15, %9: i1, %10: i15, %11: i1, %12: i15, %13: i1, %14: i15, %15: i1, %16: i15, %17: i1, %18: i15, %19: i1, %20: i15, %21: i1, %22: i15, %23: i1, %24: i15, %25: i1, %26: i15, %27: i1, %28: i15, %29: i1, %30: i15, %31: i1, %32: i15, %33: i1, %34: i15, %35: i1, %36: i15, %37: i1, %38: i15, %39: i1, %40: i15, %41: i1, %42: i15, %43: i1, %44: i15, %45: i1, %46: i15, %47: i1, %48: i15, %49: i1, %50: i15, %51: i1, %52: i15, %53: i1, %54: i15, %55: i1, %56: i15, %57: i1, %58: i15, %59: i1, %60: i15, %61: i1, %62: i15, %63: i1, %64: i15, %65: i1, %66: i15, %67: i1, %68: i15, %69: i1, %70: i15, %71: i1, %72: i15, %73: i1):

test/Dialect/LLHD/Transforms/lower-processes.mlir

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
// CHECK-LABEL: @Trivial(
44
hw.module @Trivial() {
5-
// CHECK: scf.execute_region {
5+
// CHECK: llhd.combinational {
66
// CHECK-NEXT: cf.br ^bb1
77
// CHECK-NEXT: ^bb1:
8-
// CHECK-NEXT: scf.yield
8+
// CHECK-NEXT: llhd.yield
99
// CHECK-NEXT: }
1010
llhd.process {
1111
cf.br ^bb1
@@ -16,12 +16,12 @@ hw.module @Trivial() {
1616

1717
// CHECK-LABEL: @BlockArgs(
1818
hw.module @BlockArgs(in %a: i42, in %b: i42) {
19-
// CHECK: scf.execute_region {
19+
// CHECK: llhd.combinational {
2020
// CHECK-NEXT: cf.br ^bb1
2121
// CHECK-NEXT: ^bb1:
2222
// CHECK-NEXT: cf.br ^bb2
2323
// CHECK-NEXT: ^bb2:
24-
// CHECK-NEXT: scf.yield
24+
// CHECK-NEXT: llhd.yield
2525
// CHECK-NEXT: }
2626
llhd.process {
2727
cf.br ^bb1
@@ -38,10 +38,10 @@ hw.module @BlockArgs(in %a: i42, in %b: i42) {
3838

3939
// CHECK-LABEL: @SupportYieldOperands(
4040
hw.module @SupportYieldOperands(in %a: i42) {
41-
// CHECK: scf.execute_region -> i42 {
41+
// CHECK: llhd.combinational -> i42 {
4242
// CHECK-NEXT: cf.br ^bb1
4343
// CHECK-NEXT: ^bb1:
44-
// CHECK-NEXT: scf.yield %a : i42
44+
// CHECK-NEXT: llhd.yield %a : i42
4545
// CHECK-NEXT: }
4646
llhd.process -> i42 {
4747
cf.br ^bb1
@@ -56,7 +56,7 @@ hw.module @SupportSeparateProbesOfSameValue() {
5656
%a = llhd.sig %c0_i42 : i42
5757
%0 = llhd.prb %a : !hw.inout<i42>
5858
%1 = llhd.prb %a : !hw.inout<i42>
59-
// CHECK: scf.execute_region
59+
// CHECK: llhd.combinational
6060
llhd.process -> i42 {
6161
cf.br ^bb1
6262
^bb1:
@@ -66,7 +66,7 @@ hw.module @SupportSeparateProbesOfSameValue() {
6666

6767
// CHECK-LABEL: @SupportObservedArrays(
6868
hw.module @SupportObservedArrays(in %a: i42, in %b: i42) {
69-
// CHECK: scf.execute_region
69+
// CHECK: llhd.combinational
7070
%0 = hw.array_create %a, %b : i42
7171
llhd.process {
7272
cf.br ^bb1
@@ -78,7 +78,7 @@ hw.module @SupportObservedArrays(in %a: i42, in %b: i42) {
7878

7979
// CHECK-LABEL: @SupportObservedStructs(
8080
hw.module @SupportObservedStructs(in %a: i42, in %b: i42) {
81-
// CHECK: scf.execute_region
81+
// CHECK: llhd.combinational
8282
%0 = hw.struct_create (%a, %b) : !hw.struct<a: i42, b: i42>
8383
llhd.process {
8484
cf.br ^bb1
@@ -90,7 +90,7 @@ hw.module @SupportObservedStructs(in %a: i42, in %b: i42) {
9090

9191
// CHECK-LABEL: @SupportObservedConcats(
9292
hw.module @SupportObservedConcats(in %a: i42, in %b: i42) {
93-
// CHECK: scf.execute_region
93+
// CHECK: llhd.combinational
9494
%0 = comb.concat %a, %b : i42, i42
9595
llhd.process {
9696
cf.br ^bb1
@@ -102,7 +102,7 @@ hw.module @SupportObservedConcats(in %a: i42, in %b: i42) {
102102

103103
// CHECK-LABEL: @SupportObservedBitcasts(
104104
hw.module @SupportObservedBitcasts(in %a: i42, in %b: i42) {
105-
// CHECK: scf.execute_region
105+
// CHECK: llhd.combinational
106106
%0 = hw.bitcast %a : (i42) -> !hw.array<2xi21>
107107
%1 = hw.bitcast %b : (i42) -> !hw.array<3xi14>
108108
llhd.process {
@@ -115,12 +115,12 @@ hw.module @SupportObservedBitcasts(in %a: i42, in %b: i42) {
115115

116116
// CHECK-LABEL: @CommonPattern1(
117117
hw.module @CommonPattern1(in %a: i42, in %b: i42, in %c: i1) {
118-
// CHECK: scf.execute_region -> i42 {
118+
// CHECK: llhd.combinational -> i42 {
119119
// CHECK-NEXT: cf.br ^bb1
120120
// CHECK-NEXT: ^bb1:
121121
// CHECK-NEXT: cf.cond_br %c, ^bb2(%a : i42), ^bb2(%b : i42)
122122
// CHECK-NEXT: ^bb2([[ARG:%.+]]: i42):
123-
// CHECK-NEXT: scf.yield [[ARG]] : i42
123+
// CHECK-NEXT: llhd.yield [[ARG]] : i42
124124
// CHECK-NEXT: }
125125
%0 = llhd.process -> i42 {
126126
cf.br ^bb2(%a, %b : i42, i42)

0 commit comments

Comments
 (0)