diff --git a/include/circt/Dialect/Arc/ArcInterfaces.td b/include/circt/Dialect/Arc/ArcInterfaces.td index 1de5c03a1e..7eb3e211a7 100644 --- a/include/circt/Dialect/Arc/ArcInterfaces.td +++ b/include/circt/Dialect/Arc/ArcInterfaces.td @@ -12,22 +12,6 @@ include "mlir/IR/OpBase.td" include "mlir/Interfaces/CallInterfaces.td" -def CallOpMutableInterface : OpInterface<"CallOpMutableInterface", [CallOpInterface]> { - let description = [{ - Can be implemented in addition to `CallOpInterface` to allow mutation of the - call operation. - }]; - let cppNamespace = "::circt::arc"; - - let methods = [ - InterfaceMethod<[{ - Returns the operands within this call that are used as arguments to the - callee as a mutable range. - }], - "::mlir::MutableOperandRange", "getArgOperandsMutable">, - ]; -} - def ClockedOpInterface : OpInterface<"ClockedOpInterface"> { let description = [{ This interface should be implemented by operations that have clocked diff --git a/include/circt/Dialect/Arc/ArcOps.td b/include/circt/Dialect/Arc/ArcOps.td index b76b95e5b4..4ced272211 100644 --- a/include/circt/Dialect/Arc/ArcOps.td +++ b/include/circt/Dialect/Arc/ArcOps.td @@ -132,7 +132,7 @@ def OutputOp : ArcOp<"output", [ def StateOp : ArcOp<"state", [ MemRefsNormalizable, - CallOpMutableInterface, + CallOpInterface, DeclareOpInterfaceMethods, AttrSizedOperandSegments, DeclareOpInterfaceMethods, @@ -232,7 +232,7 @@ def StateOp : ArcOp<"state", [ def CallOp : ArcOp<"call", [ MemRefsNormalizable, Pure, - CallOpMutableInterface, + CallOpInterface, DeclareOpInterfaceMethods ]> { let summary = "calls an arc"; @@ -312,7 +312,7 @@ def MemoryReadPortOp : ArcOp<"memory_read_port", [ def MemoryWritePortOp : ArcOp<"memory_write_port", [ MemoryEffects<[MemWrite]>, - CallOpMutableInterface, + CallOpInterface, DeclareOpInterfaceMethods, AttrSizedOperandSegments, ClockedOpInterface diff --git a/include/circt/Dialect/Handshake/HandshakeOps.td b/include/circt/Dialect/Handshake/HandshakeOps.td index a09645a026..6741e7141f 100644 --- a/include/circt/Dialect/Handshake/HandshakeOps.td +++ b/include/circt/Dialect/Handshake/HandshakeOps.td @@ -183,6 +183,11 @@ def InstanceOp : Handshake_Op<"instance", [ Value getControl() { return getOperands().back(); } + + MutableOperandRange getArgOperandsMutable() { + return getOpOperandsMutable(); + } + }]; let assemblyFormat = [{ diff --git a/include/circt/Dialect/Ibis/IbisOps.td b/include/circt/Dialect/Ibis/IbisOps.td index 504677457b..ca72245e1d 100644 --- a/include/circt/Dialect/Ibis/IbisOps.td +++ b/include/circt/Dialect/Ibis/IbisOps.td @@ -136,6 +136,10 @@ def CallOp : IbisOp<"call", [CallOpInterface]> { let results = (outs Variadic); let extraClassDeclaration = [{ + MutableOperandRange getArgOperandsMutable() { + return getOperandsMutable(); + } + /// Get the argument operands to the called method. operand_range getArgOperands() { return {arg_operand_begin(), arg_operand_end()}; diff --git a/include/circt/Dialect/LLHD/IR/StructureOps.td b/include/circt/Dialect/LLHD/IR/StructureOps.td index 78b882ad46..44df4f1ead 100644 --- a/include/circt/Dialect/LLHD/IR/StructureOps.td +++ b/include/circt/Dialect/LLHD/IR/StructureOps.td @@ -197,6 +197,10 @@ def LLHD_InstOp : LLHD_Op<"inst", [ let extraClassDeclaration = [{ FunctionType getCalleeType(); + MutableOperandRange getArgOperandsMutable() { + return getInputsMutable(); + } + /// Get the argument operands to the called function. operand_range getArgOperands() { return {arg_operand_begin(), arg_operand_end()}; diff --git a/include/circt/Dialect/SystemC/SystemCStatements.td b/include/circt/Dialect/SystemC/SystemCStatements.td index cf92ace118..e03eedf6a1 100644 --- a/include/circt/Dialect/SystemC/SystemCStatements.td +++ b/include/circt/Dialect/SystemC/SystemCStatements.td @@ -257,6 +257,10 @@ def CallIndirectOp : SystemCOp<"cpp.call_indirect", [ }]>]; let extraClassDeclaration = [{ + MutableOperandRange getArgOperandsMutable() { + return getCalleeOperandsMutable(); + } + /// Get the argument operands to the called function. operand_range getArgOperands() { return {arg_operand_begin(), arg_operand_end()}; @@ -329,6 +333,10 @@ def CallOp : SystemCOp<"cpp.call", [ let extraClassDeclaration = [{ FunctionType getCalleeType(); + + MutableOperandRange getArgOperandsMutable() { + return getCalleeOperandsMutable(); + } /// Get the argument operands to the called function. operand_range getArgOperands() { diff --git a/lib/Dialect/Arc/ArcOps.cpp b/lib/Dialect/Arc/ArcOps.cpp index 9432833b09..3a39e633f0 100644 --- a/lib/Dialect/Arc/ArcOps.cpp +++ b/lib/Dialect/Arc/ArcOps.cpp @@ -285,11 +285,6 @@ LogicalResult LutOp::verify() { return success(); } -Operation * -CallOpMutableInterface::resolveCallable(SymbolTableCollection *symbolTable) { - return cast(**this).resolveCallable(symbolTable); -} - #include "circt/Dialect/Arc/ArcInterfaces.cpp.inc" #define GET_OP_CLASSES diff --git a/lib/Dialect/Arc/Transforms/ArcCanonicalizer.cpp b/lib/Dialect/Arc/Transforms/ArcCanonicalizer.cpp index 7f536f28c7..896ac632d7 100644 --- a/lib/Dialect/Arc/Transforms/ArcCanonicalizer.cpp +++ b/lib/Dialect/Arc/Transforms/ArcCanonicalizer.cpp @@ -389,9 +389,9 @@ LogicalResult RemoveUnusedArcArgumentsPattern::matchAndRewrite( // Collect the mutable callers in a first iteration. If there is a user that // does not implement the interface, we have to abort the rewrite and have to // make sure that we didn't change anything so far. - SmallVector mutableUsers; + SmallVector mutableUsers; for (auto *user : symbolCache.getUsers(op)) { - auto callOpMutable = dyn_cast(user); + auto callOpMutable = dyn_cast(user); if (!callOpMutable) return failure(); mutableUsers.push_back(callOpMutable); @@ -418,14 +418,14 @@ SinkArcInputsPattern::matchAndRewrite(DefineOp op, // modify the users. auto users = symbolCache.getUsers(op); if (llvm::any_of( - users, [](auto *user) { return !isa(user); })) + users, [](auto *user) { return !isa(user); })) return failure(); // Find all arguments that use constant operands only. SmallVector stateConsts(op.getNumArguments()); bool first = true; for (auto *user : users) { - auto callOp = cast(user); + auto callOp = cast(user); for (auto [constArg, input] : llvm::zip(stateConsts, callOp.getArgOperands())) { if (auto *constOp = input.getDefiningOp(); @@ -461,7 +461,7 @@ SinkArcInputsPattern::matchAndRewrite(DefineOp op, // Rewrite all arc uses to not pass in the constant anymore. for (auto *user : users) { - auto callOp = cast(user); + auto callOp = cast(user); SmallPtrSet maybeUnusedValues; SmallVector newInputs; for (auto [index, value] : llvm::enumerate(callOp.getArgOperands())) { diff --git a/lib/Dialect/Arc/Transforms/Dedup.cpp b/lib/Dialect/Arc/Transforms/Dedup.cpp index 04b5259df6..a8a3804211 100644 --- a/lib/Dialect/Arc/Transforms/Dedup.cpp +++ b/lib/Dialect/Arc/Transforms/Dedup.cpp @@ -321,7 +321,7 @@ private: } // namespace static void addCallSiteOperands( - MutableArrayRef callSites, + MutableArrayRef callSites, ArrayRef> operandMappings) { SmallDenseMap clonedOps; SmallVector newOperands; @@ -358,7 +358,7 @@ struct DedupPass : public DedupBase { /// A mapping from arc names to arc definitions. DenseMap arcByName; /// A mapping from arc definitions to call sites. - DenseMap> callSites; + DenseMap> callSites; }; struct ArcHash { @@ -384,7 +384,7 @@ void DedupPass::runOnOperation() { } // Collect the arc call sites. - getOperation().walk([&](CallOpMutableInterface callOp) { + getOperation().walk([&](mlir::CallOpInterface callOp) { if (auto defOp = dyn_cast_or_null(callOp.resolveCallable(&symbolTable))) callSites[arcByName.lookup(callOp.getCallableForCallee() diff --git a/lib/Dialect/DC/DCOps.cpp b/lib/Dialect/DC/DCOps.cpp index d1b3d94e72..8f62ba32ad 100644 --- a/lib/Dialect/DC/DCOps.cpp +++ b/lib/Dialect/DC/DCOps.cpp @@ -38,6 +38,10 @@ OpFoldResult JoinOp::fold(FoldAdaptor adaptor) { if (auto tokens = getTokens(); tokens.size() == 1) return tokens.front(); + // These folders are disabled to work around MLIR bugs when changing + // the number of operands. https://github.com/llvm/llvm-project/issues/64280 + return {}; + // Remove operands which originate from a dc.source op (redundant). auto *op = getOperation(); for (OpOperand &operand : llvm::make_early_inc_range(op->getOpOperands())) { diff --git a/lib/Dialect/FIRRTL/Transforms/IMConstProp.cpp b/lib/Dialect/FIRRTL/Transforms/IMConstProp.cpp index 3d0bb12488..68938f0fde 100644 --- a/lib/Dialect/FIRRTL/Transforms/IMConstProp.cpp +++ b/lib/Dialect/FIRRTL/Transforms/IMConstProp.cpp @@ -839,10 +839,12 @@ void IMConstPropPass::visitOperation(Operation *op, FieldRef changedField) { logger.getOStream() << "}\n"; }); - // Fold functions in general are allowed to do in-place updates, but FIRRTL - // does not do this and supporting it costs more. - assert(!foldResults.empty() && - "FIRRTL fold functions shouldn't do in-place updates!"); + // If the folding was in-place, keep going. This is surprising, but since + // only folder that will do inplace updates is the communative folder, we + // aren't going to stop. We don't update the results, since they didn't + // change, the op just got shuffled around. + if (foldResults.empty()) + return visitOperation(op, changedField); // Merge the fold results into the lattice for this operation. assert(foldResults.size() == op->getNumResults() && "invalid result size"); @@ -860,11 +862,8 @@ void IMConstPropPass::visitOperation(Operation *op, FieldRef changedField) { latticeValues[getOrCacheFieldRefFromValue(foldResult.get())]; } - // We do not "merge" the lattice value in, we set it. This is because the - // fold functions can produce different values over time, e.g. in the - // presence of InvalidValue operands that get resolved to other constants. - setLatticeValue(getOrCacheFieldRefFromValue(op->getResult(i)), - resultLattice); + mergeLatticeValue(getOrCacheFieldRefFromValue(op->getResult(i)), + resultLattice); } } diff --git a/lib/Dialect/SV/Transforms/HWMemSimImpl.cpp b/lib/Dialect/SV/Transforms/HWMemSimImpl.cpp index 8207a38a25..180af00dbf 100644 --- a/lib/Dialect/SV/Transforms/HWMemSimImpl.cpp +++ b/lib/Dialect/SV/Transforms/HWMemSimImpl.cpp @@ -640,7 +640,7 @@ void HWMemSimImpl::generateMemory(HWModuleOp op, FirMemory mem) { // Truncate the induction variable if necessary. if (!outerIndVar.getType().isInteger( llvm::Log2_64_Ceil(mem.depth))) - iterValue = b.create( + iterValue = b.createOrFold( iterValue, 0, llvm::Log2_64_Ceil(mem.depth)); auto lhs = b.create(reg, iterValue); auto rhs = b.createOrFold( diff --git a/lib/Dialect/Seq/Transforms/LowerFirMem.cpp b/lib/Dialect/Seq/Transforms/LowerFirMem.cpp index 2be140e38d..deb6dcab3b 100644 --- a/lib/Dialect/Seq/Transforms/LowerFirMem.cpp +++ b/lib/Dialect/Seq/Transforms/LowerFirMem.cpp @@ -105,7 +105,7 @@ namespace { struct LowerFirMemPass : public impl::LowerFirMemBase { /// A vector of unique `FirMemConfig`s and all the `FirMemOp`s that use it. using UniqueConfig = std::pair>; - using UniqueConfigs = std::vector; + using UniqueConfigs = SmallVector; void runOnOperation() override; diff --git a/llvm b/llvm index 0a35ac6c2e..a133fb289a 160000 --- a/llvm +++ b/llvm @@ -1 +1 @@ -Subproject commit 0a35ac6c2e0cb0160ca2e6cc11644c263692a46d +Subproject commit a133fb289af4f3eef018ddf961f1f2ed129d0c2d diff --git a/test/Analysis/dependence-analysis.mlir b/test/Analysis/dependence-analysis.mlir index 676d6edf1c..c50620ab1d 100644 --- a/test/Analysis/dependence-analysis.mlir +++ b/test/Analysis/dependence-analysis.mlir @@ -120,6 +120,9 @@ func.func @test7(%arg0: memref) { // CHECK: affine.load %arg0[%arg1] {dependences = []} %1 = affine.load %arg0[%arg1] : memref affine.yield %1 : i32 + } else { + %1 = arith.constant 0 : i32 + affine.yield %1 : i32 } // CHECK{LITERAL}: affine.store %0, %arg0[%arg1] {dependences = [[[0, 0]]]} affine.store %0, %arg0[%arg1] : memref diff --git a/test/Analysis/scheduling-analysis.mlir b/test/Analysis/scheduling-analysis.mlir index 8a28264980..17c5700625 100644 --- a/test/Analysis/scheduling-analysis.mlir +++ b/test/Analysis/scheduling-analysis.mlir @@ -109,6 +109,9 @@ func.func @test7(%arg0: memref) { %0 = affine.if #set3(%arg1) -> i32 { %1 = affine.load %arg0[%arg1] : memref affine.yield %1 : i32 + } else { + %1 = arith.constant 0 : i32 + affine.yield %1 : i32 } // CHECK: } {dependence} // CHECK: affine.store %0, %arg0[%arg1] {dependence} diff --git a/test/Conversion/FIRRTLToHW/lower-to-hw.mlir b/test/Conversion/FIRRTLToHW/lower-to-hw.mlir index 8f204d67b1..4412a0ec5f 100644 --- a/test/Conversion/FIRRTLToHW/lower-to-hw.mlir +++ b/test/Conversion/FIRRTLToHW/lower-to-hw.mlir @@ -83,7 +83,7 @@ firrtl.circuit "Simple" attributes {annotations = [{class = firrtl.connect %out5, %tmp1 : !firrtl.uint<4>, !firrtl.uint<4> // CHECK: [[ZEXT:%.+]] = comb.concat %false, %in1 : i1, i4 - // CHECK: [[ADD:%.+]] = comb.add bin %c12_i5, [[ZEXT]] : i5 + // CHECK: [[ADD:%.+]] = comb.add bin [[ZEXT]], %c12_i5 : i5 %0 = firrtl.add %c12_ui4, %in1 : (!firrtl.uint<4>, !firrtl.uint<4>) -> !firrtl.uint<5> %1 = firrtl.asUInt %in1 : (!firrtl.uint<4>) -> !firrtl.uint<4> diff --git a/test/Conversion/FIRRTLToHW/zero-width.mlir b/test/Conversion/FIRRTLToHW/zero-width.mlir index 3e79c04cb6..080f041efd 100644 --- a/test/Conversion/FIRRTLToHW/zero-width.mlir +++ b/test/Conversion/FIRRTLToHW/zero-width.mlir @@ -25,7 +25,7 @@ firrtl.circuit "Arithmetic" { // CHECK-DAG: %c0_i4 = hw.constant 0 : i4 // CHECK-DAG: %false = hw.constant false // CHECK-NEXT: [[UIN3EXT:%.+]] = comb.concat %false, %uin3c : i1, i3 - // CHECK-NEXT: [[ADDRES:%.+]] = comb.add bin %c0_i4, [[UIN3EXT]] : i4 + // CHECK-NEXT: [[ADDRES:%.+]] = comb.add bin [[UIN3EXT]], %c0_i4 : i4 %1 = firrtl.add %uin0c, %uin3c : (!firrtl.uint<0>, !firrtl.uint<3>) -> !firrtl.uint<4> firrtl.connect %out1, %1 : !firrtl.uint<4>, !firrtl.uint<4> diff --git a/test/Dialect/DC/canonicalization.mlir b/test/Dialect/DC/canonicalization.mlir index 5bf02d5346..27314f4aeb 100644 --- a/test/Dialect/DC/canonicalization.mlir +++ b/test/Dialect/DC/canonicalization.mlir @@ -1,4 +1,6 @@ // RUN: circt-opt %s --canonicalize --cse --canonicalize | FileCheck %s +// XFAIL: * +// Waiting on: https://github.com/llvm/llvm-project/issues/64280 // CHECK-LABEL: func.func @staggeredJoin1( // CHECK-SAME: %[[VAL_0:.*]]: !dc.token, diff --git a/test/Dialect/ESI/lowering.mlir b/test/Dialect/ESI/lowering.mlir index 8bb5b9b633..e233362945 100644 --- a/test/Dialect/ESI/lowering.mlir +++ b/test/Dialect/ESI/lowering.mlir @@ -67,7 +67,7 @@ hw.module @add11(%clk: i1, %ints: !esi.channel) -> (mutatedInts: !esi.chann } // HW-LABEL: hw.module @add11(%clk: i1, %ints: i32, %ints_valid: i1, %mutatedInts_ready: i1) -> (ints_ready: i1, mutatedInts: i32, mutatedInts_valid: i1, c4: i4) { // HW: %{{.+}} = hw.constant 11 : i32 -// HW: [[RES0:%.+]] = comb.add %{{.+}}, %ints : i32 +// HW: [[RES0:%.+]] = comb.add %ints, %{{.+}} : i32 // HW: %{{.+}} = hw.constant 0 : i4 // HW: hw.output %mutatedInts_ready, [[RES0]], %ints_valid, %{{.+}} : i1, i32, i1, i4 diff --git a/test/Dialect/SV/hw-memsim.mlir b/test/Dialect/SV/hw-memsim.mlir index d7e4550380..0b3cb6ff25 100644 --- a/test/Dialect/SV/hw-memsim.mlir +++ b/test/Dialect/SV/hw-memsim.mlir @@ -97,7 +97,7 @@ hw.module.generated @FIRRTLMem_1_1_1_16_10_0_1_0_0, @FIRRTLMem(%ro_addr_0: i4, % //CHECK-NEXT: %[[rwdata2:.+]] = comb.mux %[[rwrcond]], %[[rwdata]], %[[x2]] //CHECK-NEXT: sv.assign %[[rwtmp]], %[[rwdata2:.+]] //CHECK-NEXT: sv.always posedge %rw_clock_0 { -//CHECK-NEXT: %[[rwwcondpre:.+]] = comb.and %true, %rw_wmode_0 +//CHECK-NEXT: %[[rwwcondpre:.+]] = comb.and %rw_wmode_0, %true //CHECK-NEXT: %[[rwwcond:.+]] = comb.and %rw_en_0, %[[rwwcondpre]] //CHECK-NEXT: sv.if %[[rwwcond]] { //CHECK-NEXT: %[[rwwslot:.+]] = sv.array_index_inout %Memory[%rw_addr_0] @@ -370,7 +370,7 @@ hw.module.generated @ReadWriteWithHighReadLatency, @FIRRTLMem(%rw_addr: i4, %rw_ // Write port // CHECK: sv.always -// CHECK: [[TMP:%.+]] = comb.and %true, [[WMODE_1R]] +// CHECK: [[TMP:%.+]] = comb.and [[WMODE_1R]], %true // CHECK: [[WCOND:%.+]] comb.and [[EN_1R]], [[TMP]] // CHECK: [[WPTR:%.+]] = sv.array_index_inout [[MEM]][[[ADDR_1R]]] @@ -419,6 +419,6 @@ hw.module.generated @ReadWriteWithHighWriteLatency, @FIRRTLMem(%rw_addr: i4, %rw // Write port // CHECK: sv.always -// CHECK: [[TMP:%.+]] = comb.and %true, [[WRITE_WMODE_3R]] +// CHECK: [[TMP:%.+]] = comb.and [[WRITE_WMODE_3R]], %true // CHECK: [[WCOND:%.+]] comb.and [[WRITE_EN_3R]], [[TMP]] // CHECK: [[WPTR:%.+]] = sv.array_index_inout [[MEM]][[[WRITE_ADDR_3R]]]