From 2d24bc98fec20ee57ff1c09a334d9d19950e8706 Mon Sep 17 00:00:00 2001 From: Prithayan Barua Date: Thu, 2 Oct 2025 23:25:10 -0700 Subject: [PATCH 1/8] Add a new Comb To LLVM pass --- include/circt/Conversion/CombToLLVM.h | 6 + include/circt/Conversion/Passes.h | 2 + include/circt/Conversion/Passes.td | 18 ++ lib/Conversion/CombToLLVM/CMakeLists.txt | 10 +- lib/Conversion/CombToLLVM/CombToLLVM.cpp | 138 +++++++++++- test/Conversion/CombToLLVM/comb-to-llvm.mlir | 215 +++++++++++++++++++ 6 files changed, 387 insertions(+), 2 deletions(-) create mode 100644 test/Conversion/CombToLLVM/comb-to-llvm.mlir diff --git a/include/circt/Conversion/CombToLLVM.h b/include/circt/Conversion/CombToLLVM.h index 1b4695018ebf..afd13ff09220 100644 --- a/include/circt/Conversion/CombToLLVM.h +++ b/include/circt/Conversion/CombToLLVM.h @@ -23,10 +23,16 @@ class LLVMTypeConverter; namespace circt { +#define GEN_PASS_DECL_CONVERTCOMBTOLLVM +#include "circt/Conversion/Passes.h.inc" + /// Get the Comb to LLVM conversion patterns. void populateCombToLLVMConversionPatterns(mlir::LLVMTypeConverter &converter, RewritePatternSet &patterns); +/// Create a Comb to LLVM conversion pass. +std::unique_ptr> createConvertCombToLLVMPass(); + } // namespace circt #endif // CIRCT_CONVERSION_COMBTOLLVM_COMBTOLLVM_H diff --git a/include/circt/Conversion/Passes.h b/include/circt/Conversion/Passes.h index 60f4c159154e..bcf61e271a7a 100644 --- a/include/circt/Conversion/Passes.h +++ b/include/circt/Conversion/Passes.h @@ -21,6 +21,8 @@ #include "circt/Conversion/CalyxToHW.h" #include "circt/Conversion/CombToArith.h" #include "circt/Conversion/CombToDatapath.h" +#include "circt/Conversion/CombToLLVM.h" +#include "circt/Conversion/CombToMLIR.h" #include "circt/Conversion/CombToSMT.h" #include "circt/Conversion/CombToSynth.h" #include "circt/Conversion/ConvertToArcs.h" diff --git a/include/circt/Conversion/Passes.td b/include/circt/Conversion/Passes.td index b888223c3e71..249a72f82f2d 100644 --- a/include/circt/Conversion/Passes.td +++ b/include/circt/Conversion/Passes.td @@ -513,6 +513,24 @@ def ConvertHWToLLVM : Pass<"convert-hw-to-llvm", "mlir::ModuleOp"> { let dependentDialects = ["mlir::LLVM::LLVMDialect"]; } +//===----------------------------------------------------------------------===// +// CombToLLVM +//===----------------------------------------------------------------------===// + +def ConvertCombToLLVM : Pass<"convert-comb-to-llvm", "mlir::ModuleOp"> { + let summary = "Convert Comb and HW to LLVM"; + let description = [{ + This pass translates Comb and HW operations to LLVM IR. It combines + both HW and Comb conversion patterns to provide a complete lowering + from hardware description to LLVM IR. + }]; + let constructor = "circt::createConvertCombToLLVMPass()"; + let dependentDialects = [ + "mlir::LLVM::LLVMDialect", + "mlir::arith::ArithDialect" + ]; +} + //===----------------------------------------------------------------------===// // HWArithToHW //===----------------------------------------------------------------------===// diff --git a/lib/Conversion/CombToLLVM/CMakeLists.txt b/lib/Conversion/CombToLLVM/CMakeLists.txt index 5b1db6b700c2..6d155339d783 100644 --- a/lib/Conversion/CombToLLVM/CMakeLists.txt +++ b/lib/Conversion/CombToLLVM/CMakeLists.txt @@ -1,7 +1,6 @@ add_circt_conversion_library(CIRCTCombToLLVM CombToLLVM.cpp - DEPENDS CIRCTConversionPassIncGen @@ -10,6 +9,15 @@ add_circt_conversion_library(CIRCTCombToLLVM LINK_LIBS PUBLIC CIRCTComb + CIRCTCombToArith + CIRCTHW + CIRCTHWToLLVM + CIRCTSupport + MLIRArithToLLVM + MLIRControlFlowToLLVM + MLIRFuncToLLVM + MLIRIndexToLLVM MLIRLLVMCommonConversion + MLIRSCFToControlFlow MLIRTransforms ) diff --git a/lib/Conversion/CombToLLVM/CombToLLVM.cpp b/lib/Conversion/CombToLLVM/CombToLLVM.cpp index d5a003bd2c9a..37bcb40885f3 100644 --- a/lib/Conversion/CombToLLVM/CombToLLVM.cpp +++ b/lib/Conversion/CombToLLVM/CombToLLVM.cpp @@ -11,10 +11,19 @@ //===----------------------------------------------------------------------===// #include "circt/Conversion/CombToLLVM.h" +#include "circt/Conversion/CombToArith.h" +#include "circt/Conversion/HWToLLVM.h" #include "circt/Dialect/Comb/CombOps.h" -#include "circt/Support/LLVM.h" +#include "circt/Dialect/SV/SVOps.h" +#include "mlir/Conversion/ArithToLLVM/ArithToLLVM.h" +#include "mlir/Conversion/ControlFlowToLLVM/ControlFlowToLLVM.h" +#include "mlir/Conversion/FuncToLLVM/ConvertFuncToLLVM.h" +#include "mlir/Conversion/IndexToLLVM/IndexToLLVM.h" #include "mlir/Conversion/LLVMCommon/ConversionTarget.h" #include "mlir/Conversion/LLVMCommon/Pattern.h" +#include "mlir/Conversion/SCFToControlFlow/SCFToControlFlow.h" +#include "mlir/Dialect/Arith/IR/Arith.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/Dialect/LLVMIR/LLVMDialect.h" #include "mlir/Pass/Pass.h" #include "mlir/Transforms/DialectConversion.h" @@ -22,8 +31,19 @@ using namespace mlir; using namespace circt; +namespace circt { +#define GEN_PASS_DEF_CONVERTCOMBTOLLVM +#include "circt/Conversion/Passes.h.inc" +} // namespace circt + namespace { + +//===----------------------------------------------------------------------===// +// Comb Operation Conversion Patterns +//===----------------------------------------------------------------------===// + /// Convert a comb::ParityOp to the LLVM dialect. +/// This is the only Comb operation that doesn't have a Comb-to-Arith pattern. struct CombParityOpConversion : public ConvertToLLVMPattern { explicit CombParityOpConversion(MLIRContext *ctx, LLVMTypeConverter &typeConverter) @@ -43,9 +63,125 @@ struct CombParityOpConversion : public ConvertToLLVMPattern { return success(); } }; + +//===----------------------------------------------------------------------===// +// HW Structural Operation Conversion Patterns +//===----------------------------------------------------------------------===// + +/// Convert a hw::OutputOp to an llvm.return. +struct HWOutputOpConversion : public ConvertToLLVMPattern { + explicit HWOutputOpConversion(MLIRContext *ctx, + LLVMTypeConverter &typeConverter) + : ConvertToLLVMPattern(hw::OutputOp::getOperationName(), ctx, + typeConverter) {} + + LogicalResult + matchAndRewrite(Operation *op, ArrayRef operands, + ConversionPatternRewriter &rewriter) const override { + if (operands.empty()) { + rewriter.replaceOpWithNewOp(op, ValueRange{}); + } else if (operands.size() == 1) { + rewriter.replaceOpWithNewOp(op, operands[0]); + } else { + // Multiple outputs - pack into a struct + auto structType = LLVM::LLVMStructType::getLiteral( + rewriter.getContext(), + llvm::map_to_vector(operands, [](Value v) { return v.getType(); })); + Value structVal = + rewriter.create(op->getLoc(), structType); + for (auto [i, operand] : llvm::enumerate(operands)) { + structVal = rewriter.create(op->getLoc(), + structVal, operand, i); + } + rewriter.replaceOpWithNewOp(op, structVal); + } + return success(); + } +}; + +//===----------------------------------------------------------------------===// +// Pass Implementation +//===----------------------------------------------------------------------===// + +struct CombToLLVMLoweringPass + : public circt::impl::ConvertCombToLLVMBase { + void runOnOperation() override; + +private: + void convertFuncOp(func::FuncOp funcOp); +}; + } // namespace +//===----------------------------------------------------------------------===// +// Pattern Population Functions +//===----------------------------------------------------------------------===// + void circt::populateCombToLLVMConversionPatterns(LLVMTypeConverter &converter, RewritePatternSet &patterns) { + // Only add patterns for operations that don't have Comb-to-Arith patterns + // Most Comb operations are handled by the Comb-to-Arith + Arith-to-LLVM + // pipeline patterns.add(patterns.getContext(), converter); + + // Add HW structural operation patterns + patterns.add(patterns.getContext(), converter); +} + +void CombToLLVMLoweringPass::runOnOperation() { + // Iterate over all func.func operations in the module and convert them + getOperation().walk([&](func::FuncOp funcOp) { convertFuncOp(funcOp); }); +} + +void CombToLLVMLoweringPass::convertFuncOp(func::FuncOp funcOp) { + MLIRContext *context = &getContext(); + RewritePatternSet patterns(context); + auto converter = mlir::LLVMTypeConverter(context); + + // Add HW to LLVM type conversions + populateHWToLLVMTypeConversions(converter); + + LLVMConversionTarget target(*context); + target.addIllegalDialect(); + target.addIllegalDialect(); + + // Mark HW and SV dialects as legal - we only convert operations inside + // func.func + target.addLegalDialect(); + target.addLegalDialect(); + + // Setup the conversion patterns in the correct order: + // 1. SCF to ControlFlow (for structured control flow) + populateSCFToControlFlowConversionPatterns(patterns); + + // 2. Func to LLVM (for function operations) + populateFuncToLLVMConversionPatterns(converter, patterns); + + // 3. ControlFlow to LLVM (for control flow operations) + cf::populateControlFlowToLLVMConversionPatterns(converter, patterns); + + // 4. Comb to Arith (for most combinational operations) + populateCombToArithConversionPatterns(converter, patterns); + + // 5. Arith to LLVM (for arithmetic operations) + arith::populateArithToLLVMConversionPatterns(converter, patterns); + + // 6. Index to LLVM (for index operations) + index::populateIndexToLLVMConversionPatterns(converter, patterns); + + // 7. Any function op interface type conversion + populateAnyFunctionOpInterfaceTypeConversionPattern(patterns, converter); + + // 8. Comb to LLVM (for operations without Comb-to-Arith patterns, like + // parity) + populateCombToLLVMConversionPatterns(converter, patterns); + + // Apply the partial conversion only to this func.func operation + if (failed(applyPartialConversion(funcOp, target, std::move(patterns)))) + signalPassFailure(); +} + +/// Create a Comb to LLVM conversion pass. +std::unique_ptr> circt::createConvertCombToLLVMPass() { + return std::make_unique(); } diff --git a/test/Conversion/CombToLLVM/comb-to-llvm.mlir b/test/Conversion/CombToLLVM/comb-to-llvm.mlir new file mode 100644 index 000000000000..219a5b5c014b --- /dev/null +++ b/test/Conversion/CombToLLVM/comb-to-llvm.mlir @@ -0,0 +1,215 @@ +// RUN: circt-opt --convert-comb-to-llvm %s | FileCheck %s + +// Test that Comb operations are converted to LLVM via the comprehensive conversion pipeline +// This includes Comb->Arith->LLVM, Func->LLVM, and other dialect conversions + +// CHECK-LABEL: llvm.func @test_comb_extract +func.func @test_comb_extract(%arg0: i16) -> i2 { + // Extract from bit 0 should optimize to just truncation + // CHECK: %{{.*}} = llvm.trunc %arg0 : i16 to i2 + // CHECK: llvm.return + %0 = comb.extract %arg0 from 0 : (i16) -> i2 + return %0 : i2 +} + +// CHECK-LABEL: llvm.func @test_comb_extract_nonzero +func.func @test_comb_extract_nonzero(%arg0: i16) -> i3 { + // Extract from non-zero bit should use shift + truncate + // CHECK: %[[C5:.*]] = llvm.mlir.constant(5 : i16) : i16 + // CHECK: %[[SHIFT:.*]] = llvm.lshr %arg0, %[[C5]] : i16 + // CHECK: %[[RESULT:.*]] = llvm.trunc %[[SHIFT]] : i16 to i3 + // CHECK: llvm.return %[[RESULT]] + %0 = comb.extract %arg0 from 5 : (i16) -> i3 + return %0 : i3 +} + +// CHECK-LABEL: llvm.func @test_comb_concat +func.func @test_comb_concat(%arg0: i8, %arg1: i8) -> i16 { + // Concat should use zero-extend, shift, and or + // CHECK: %[[EXT0:.*]] = llvm.zext %arg1 : i8 to i16 + // CHECK: %[[C8:.*]] = llvm.mlir.constant(8 : i16) : i16 + // CHECK: %[[EXT1:.*]] = llvm.zext %arg0 : i8 to i16 + // CHECK: %[[SHIFT:.*]] = llvm.shl %[[EXT1]], %[[C8]] : i16 + // CHECK: %[[RESULT:.*]] = llvm.or %[[EXT0]], %[[SHIFT]] : i16 + // CHECK: llvm.return %[[RESULT]] + %0 = comb.concat %arg0, %arg1 : i8, i8 + return %0 : i16 +} + +// CHECK-LABEL: llvm.func @test_comb_add +func.func @test_comb_add(%arg0: i32, %arg1: i32) -> i32 { + // CHECK: %{{.*}} = llvm.add %arg0, %arg1 : i32 + // CHECK: llvm.return + %0 = comb.add %arg0, %arg1 : i32 + return %0 : i32 +} + +// CHECK-LABEL: llvm.func @test_comb_sub +func.func @test_comb_sub(%arg0: i32, %arg1: i32) -> i32 { + // CHECK: %{{.*}} = llvm.sub %arg0, %arg1 : i32 + // CHECK: llvm.return + %0 = comb.sub %arg0, %arg1 : i32 + return %0 : i32 +} + +// CHECK-LABEL: llvm.func @test_comb_mul +func.func @test_comb_mul(%arg0: i32, %arg1: i32) -> i32 { + // CHECK: %{{.*}} = llvm.mul %arg0, %arg1 : i32 + // CHECK: llvm.return + %0 = comb.mul %arg0, %arg1 : i32 + return %0 : i32 +} + +// CHECK-LABEL: llvm.func @test_comb_and +func.func @test_comb_and(%arg0: i32, %arg1: i32) -> i32 { + // CHECK: %{{.*}} = llvm.and %arg0, %arg1 : i32 + // CHECK: llvm.return + %0 = comb.and %arg0, %arg1 : i32 + return %0 : i32 +} + +// CHECK-LABEL: llvm.func @test_comb_or +func.func @test_comb_or(%arg0: i32, %arg1: i32) -> i32 { + // CHECK: %{{.*}} = llvm.or %arg0, %arg1 : i32 + // CHECK: llvm.return + %0 = comb.or %arg0, %arg1 : i32 + return %0 : i32 +} + +// CHECK-LABEL: llvm.func @test_comb_xor +func.func @test_comb_xor(%arg0: i32, %arg1: i32) -> i32 { + // CHECK: %{{.*}} = llvm.xor %arg0, %arg1 : i32 + // CHECK: llvm.return + %0 = comb.xor %arg0, %arg1 : i32 + return %0 : i32 +} + +// CHECK-LABEL: llvm.func @test_comb_parity +func.func @test_comb_parity(%arg0: i32) -> i1 { + // Parity should use ctpop + trunc (no Comb->Arith pattern exists) + // CHECK: %[[CTPOP:.*]] = llvm.intr.ctpop(%arg0) : (i32) -> i32 + // CHECK: %{{.*}} = llvm.trunc %[[CTPOP]] : i32 to i1 + // CHECK: llvm.return + %0 = comb.parity %arg0 : i32 + return %0 : i1 +} + +// CHECK-LABEL: llvm.func @test_comb_shifts +func.func @test_comb_shifts(%arg0: i32, %arg1: i32) -> (i32, i32, i32) { + // Test shift operations (converted via Comb->Arith->LLVM) + // CHECK: llvm.shl + // CHECK: llvm.lshr + // CHECK: llvm.ashr + // CHECK: llvm.return + %0 = comb.shl %arg0, %arg1 : i32 + %1 = comb.shru %arg0, %arg1 : i32 + %2 = comb.shrs %arg0, %arg1 : i32 + return %0, %1, %2 : i32, i32, i32 +} + +// CHECK-LABEL: llvm.func @test_comb_icmp +func.func @test_comb_icmp(%arg0: i32, %arg1: i32) -> (i1, i1, i1, i1) { + // Test comparison operations (converted via Comb->Arith->LLVM) + // CHECK: llvm.icmp "eq" + // CHECK: llvm.icmp "ne" + // CHECK: llvm.icmp "slt" + // CHECK: llvm.icmp "ult" + // CHECK: llvm.return + %0 = comb.icmp eq %arg0, %arg1 : i32 + %1 = comb.icmp ne %arg0, %arg1 : i32 + %2 = comb.icmp slt %arg0, %arg1 : i32 + %3 = comb.icmp ult %arg0, %arg1 : i32 + return %0, %1, %2, %3 : i1, i1, i1, i1 +} + +// CHECK-LABEL: llvm.func @test_comb_mux +func.func @test_comb_mux(%cond: i1, %arg0: i32, %arg1: i32) -> i32 { + // Test mux operation (converted via Comb->Arith->LLVM) + // CHECK: llvm.select + // CHECK: llvm.return + %0 = comb.mux %cond, %arg0, %arg1 : i32 + return %0 : i32 +} + +// CHECK-LABEL: llvm.func @test_comb_replicate +func.func @test_comb_replicate(%arg0: i4) -> i16 { + // Test replicate operation (converted via Comb->Arith->LLVM) + // CHECK: llvm.zext + // CHECK: llvm.or + // CHECK: llvm.return + %0 = comb.replicate %arg0 : (i4) -> i16 + return %0 : i16 +} + +// CHECK-LABEL: llvm.func @test_variadic_operations +func.func @test_variadic_operations(%arg0: i32, %arg1: i32, %arg2: i32) -> (i32, i32, i32) { + // Test variadic operations (converted via Comb->Arith->LLVM) + // CHECK: llvm.add + // CHECK: llvm.add + // CHECK: llvm.mul + // CHECK: llvm.mul + // CHECK: llvm.and + // CHECK: llvm.and + // CHECK: llvm.return + %0 = comb.add %arg0, %arg1, %arg2 : i32 + %1 = comb.mul %arg0, %arg1, %arg2 : i32 + %2 = comb.and %arg0, %arg1, %arg2 : i32 + return %0, %1, %2 : i32, i32, i32 +} + +// CHECK-LABEL: llvm.func @test_control_flow +func.func @test_control_flow(%cond: i1, %arg0: i32) -> i32 { + // Test that control flow is also converted (SCF->ControlFlow->LLVM) + // CHECK: llvm.cond_br + // CHECK: llvm.br + // CHECK: llvm.return + %result = scf.if %cond -> i32 { + %0 = comb.add %arg0, %arg0 : i32 + scf.yield %0 : i32 + } else { + %1 = comb.mul %arg0, %arg0 : i32 + scf.yield %1 : i32 + } + return %result : i32 +} + +// ----- + +// Test HW module and SV operations (should NOT be converted - only func.func operations are converted) +hw.module @test_hw_sv_module(in %scan_data : i9) { + %0 = comb.extract %scan_data from 0 : (i9) -> i8 + %top_reg_decoded = sv.wire : !hw.inout + sv.assign %top_reg_decoded, %0 : i8 + %1 = comb.extract %scan_data from 8 : (i9) -> i1 + %child.child_reg_decoded = sv.wire : !hw.inout + sv.assign %child.child_reg_decoded, %1 : i1 + %2 = comb.extract %scan_data from 8 : (i9) -> i1 + hw.instance "child_decoder" @test_child_module(scan_data: %2: i1) -> () + hw.output +} + +hw.module @test_child_module(in %scan_data : i1) { + %0 = comb.extract %scan_data from 0 : (i1) -> i1 + %SimpleChild.child_reg_decoded = sv.wire : !hw.inout + sv.assign %SimpleChild.child_reg_decoded, %0 : i1 + hw.output +} + +// CHECK-LABEL: hw.module @test_hw_sv_module +// CHECK-SAME: (in %scan_data : i9) +// CHECK: %[[EXTRACT1:.+]] = comb.extract %scan_data from 0 : (i9) -> i8 +// CHECK: %[[WIRE1:.+]] = sv.wire : !hw.inout +// CHECK: sv.assign %[[WIRE1]], %[[EXTRACT1]] : i8 +// CHECK: %[[EXTRACT2:.+]] = comb.extract %scan_data from 8 : (i9) -> i1 +// CHECK: %[[WIRE2:.+]] = sv.wire : !hw.inout +// CHECK: sv.assign %[[WIRE2]], %[[EXTRACT2]] : i1 +// CHECK: %[[EXTRACT3:.+]] = comb.extract %scan_data from 8 : (i9) -> i1 +// CHECK: hw.instance "child_decoder" @test_child_module(scan_data: %[[EXTRACT3]]: i1) +// CHECK: hw.output + +// CHECK-LABEL: hw.module @test_child_module +// CHECK-SAME: (in %scan_data : i1) +// CHECK: %[[EXTRACT:.+]] = comb.extract %scan_data from 0 : (i1) -> i1 +// CHECK: %[[WIRE:.+]] = sv.wire : !hw.inout +// CHECK: sv.assign %[[WIRE]], %[[EXTRACT]] : i1 +// CHECK: hw.output From f1f50b11fa6c234c59300dda90c981fb0863e161 Mon Sep 17 00:00:00 2001 From: Prithayan Barua Date: Fri, 17 Oct 2025 11:36:26 -0700 Subject: [PATCH 2/8] remove include --- include/circt/Conversion/Passes.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/circt/Conversion/Passes.h b/include/circt/Conversion/Passes.h index bcf61e271a7a..b4bf9b8147a7 100644 --- a/include/circt/Conversion/Passes.h +++ b/include/circt/Conversion/Passes.h @@ -22,7 +22,6 @@ #include "circt/Conversion/CombToArith.h" #include "circt/Conversion/CombToDatapath.h" #include "circt/Conversion/CombToLLVM.h" -#include "circt/Conversion/CombToMLIR.h" #include "circt/Conversion/CombToSMT.h" #include "circt/Conversion/CombToSynth.h" #include "circt/Conversion/ConvertToArcs.h" From c15535c4ba9416c8231278eb4289d88595eb0a67 Mon Sep 17 00:00:00 2001 From: Prithayan Barua Date: Thu, 30 Oct 2025 13:53:33 -0700 Subject: [PATCH 3/8] Address review comments and rename the pass --- include/circt/Conversion/CombToLLVM.h | 2 +- include/circt/Conversion/Passes.td | 2 +- lib/Conversion/CombToLLVM/CombToLLVM.cpp | 47 +++----------------- test/Conversion/CombToLLVM/comb-to-llvm.mlir | 2 +- 4 files changed, 9 insertions(+), 44 deletions(-) diff --git a/include/circt/Conversion/CombToLLVM.h b/include/circt/Conversion/CombToLLVM.h index afd13ff09220..49dcd58fb244 100644 --- a/include/circt/Conversion/CombToLLVM.h +++ b/include/circt/Conversion/CombToLLVM.h @@ -23,7 +23,7 @@ class LLVMTypeConverter; namespace circt { -#define GEN_PASS_DECL_CONVERTCOMBTOLLVM +#define GEN_PASS_DECL_CONVERTTOLLVM #include "circt/Conversion/Passes.h.inc" /// Get the Comb to LLVM conversion patterns. diff --git a/include/circt/Conversion/Passes.td b/include/circt/Conversion/Passes.td index 249a72f82f2d..1c05df7fb066 100644 --- a/include/circt/Conversion/Passes.td +++ b/include/circt/Conversion/Passes.td @@ -517,7 +517,7 @@ def ConvertHWToLLVM : Pass<"convert-hw-to-llvm", "mlir::ModuleOp"> { // CombToLLVM //===----------------------------------------------------------------------===// -def ConvertCombToLLVM : Pass<"convert-comb-to-llvm", "mlir::ModuleOp"> { +def ConvertToLLVM : Pass<"convert-to-llvm", "mlir::ModuleOp"> { let summary = "Convert Comb and HW to LLVM"; let description = [{ This pass translates Comb and HW operations to LLVM IR. It combines diff --git a/lib/Conversion/CombToLLVM/CombToLLVM.cpp b/lib/Conversion/CombToLLVM/CombToLLVM.cpp index 37bcb40885f3..c3c91225485e 100644 --- a/lib/Conversion/CombToLLVM/CombToLLVM.cpp +++ b/lib/Conversion/CombToLLVM/CombToLLVM.cpp @@ -32,7 +32,7 @@ using namespace mlir; using namespace circt; namespace circt { -#define GEN_PASS_DEF_CONVERTCOMBTOLLVM +#define GEN_PASS_DEF_CONVERTTOLLVM #include "circt/Conversion/Passes.h.inc" } // namespace circt @@ -64,47 +64,12 @@ struct CombParityOpConversion : public ConvertToLLVMPattern { } }; -//===----------------------------------------------------------------------===// -// HW Structural Operation Conversion Patterns -//===----------------------------------------------------------------------===// - -/// Convert a hw::OutputOp to an llvm.return. -struct HWOutputOpConversion : public ConvertToLLVMPattern { - explicit HWOutputOpConversion(MLIRContext *ctx, - LLVMTypeConverter &typeConverter) - : ConvertToLLVMPattern(hw::OutputOp::getOperationName(), ctx, - typeConverter) {} - - LogicalResult - matchAndRewrite(Operation *op, ArrayRef operands, - ConversionPatternRewriter &rewriter) const override { - if (operands.empty()) { - rewriter.replaceOpWithNewOp(op, ValueRange{}); - } else if (operands.size() == 1) { - rewriter.replaceOpWithNewOp(op, operands[0]); - } else { - // Multiple outputs - pack into a struct - auto structType = LLVM::LLVMStructType::getLiteral( - rewriter.getContext(), - llvm::map_to_vector(operands, [](Value v) { return v.getType(); })); - Value structVal = - rewriter.create(op->getLoc(), structType); - for (auto [i, operand] : llvm::enumerate(operands)) { - structVal = rewriter.create(op->getLoc(), - structVal, operand, i); - } - rewriter.replaceOpWithNewOp(op, structVal); - } - return success(); - } -}; - //===----------------------------------------------------------------------===// // Pass Implementation //===----------------------------------------------------------------------===// struct CombToLLVMLoweringPass - : public circt::impl::ConvertCombToLLVMBase { + : public circt::impl::ConvertToLLVMBase { void runOnOperation() override; private: @@ -123,14 +88,14 @@ void circt::populateCombToLLVMConversionPatterns(LLVMTypeConverter &converter, // Most Comb operations are handled by the Comb-to-Arith + Arith-to-LLVM // pipeline patterns.add(patterns.getContext(), converter); - - // Add HW structural operation patterns - patterns.add(patterns.getContext(), converter); } void CombToLLVMLoweringPass::runOnOperation() { // Iterate over all func.func operations in the module and convert them - getOperation().walk([&](func::FuncOp funcOp) { convertFuncOp(funcOp); }); + for (auto funcOp : + llvm::make_early_inc_range(getOperation().getOps())) { + convertFuncOp(funcOp); + } } void CombToLLVMLoweringPass::convertFuncOp(func::FuncOp funcOp) { diff --git a/test/Conversion/CombToLLVM/comb-to-llvm.mlir b/test/Conversion/CombToLLVM/comb-to-llvm.mlir index 219a5b5c014b..35bf47e969e0 100644 --- a/test/Conversion/CombToLLVM/comb-to-llvm.mlir +++ b/test/Conversion/CombToLLVM/comb-to-llvm.mlir @@ -1,4 +1,4 @@ -// RUN: circt-opt --convert-comb-to-llvm %s | FileCheck %s +// RUN: circt-opt --convert-to-llvm %s | FileCheck %s // Test that Comb operations are converted to LLVM via the comprehensive conversion pipeline // This includes Comb->Arith->LLVM, Func->LLVM, and other dialect conversions From 483df04776685a948fa3545a6182908158c8ad56 Mon Sep 17 00:00:00 2001 From: Prithayan Barua Date: Thu, 30 Oct 2025 14:43:11 -0700 Subject: [PATCH 4/8] Create a new pass ConvertToLLVM --- include/circt/Conversion/CombToLLVM.h | 2 +- include/circt/Conversion/Passes.td | 1 - lib/Conversion/CMakeLists.txt | 1 + lib/Conversion/CombToLLVM/CombToLLVM.cpp | 96 +-------------- lib/Conversion/ConvertToLLVM/CMakeLists.txt | 25 ++++ .../ConvertToLLVM/ConvertToLLVM.cpp | 114 ++++++++++++++++++ test/Conversion/CombToLLVM/comb-to-llvm.mlir | 28 ----- 7 files changed, 144 insertions(+), 123 deletions(-) create mode 100644 lib/Conversion/ConvertToLLVM/CMakeLists.txt create mode 100644 lib/Conversion/ConvertToLLVM/ConvertToLLVM.cpp diff --git a/include/circt/Conversion/CombToLLVM.h b/include/circt/Conversion/CombToLLVM.h index 49dcd58fb244..80664c1ded32 100644 --- a/include/circt/Conversion/CombToLLVM.h +++ b/include/circt/Conversion/CombToLLVM.h @@ -31,7 +31,7 @@ void populateCombToLLVMConversionPatterns(mlir::LLVMTypeConverter &converter, RewritePatternSet &patterns); /// Create a Comb to LLVM conversion pass. -std::unique_ptr> createConvertCombToLLVMPass(); +std::unique_ptr> createConvertToLLVMPass(); } // namespace circt diff --git a/include/circt/Conversion/Passes.td b/include/circt/Conversion/Passes.td index 1c05df7fb066..0f55b2888f59 100644 --- a/include/circt/Conversion/Passes.td +++ b/include/circt/Conversion/Passes.td @@ -524,7 +524,6 @@ def ConvertToLLVM : Pass<"convert-to-llvm", "mlir::ModuleOp"> { both HW and Comb conversion patterns to provide a complete lowering from hardware description to LLVM IR. }]; - let constructor = "circt::createConvertCombToLLVMPass()"; let dependentDialects = [ "mlir::LLVM::LLVMDialect", "mlir::arith::ArithDialect" diff --git a/lib/Conversion/CMakeLists.txt b/lib/Conversion/CMakeLists.txt index ab063555b567..7c73f71c1670 100644 --- a/lib/Conversion/CMakeLists.txt +++ b/lib/Conversion/CMakeLists.txt @@ -9,6 +9,7 @@ add_subdirectory(CombToLLVM) add_subdirectory(CombToSMT) add_subdirectory(CombToSynth) add_subdirectory(ConvertToArcs) +add_subdirectory(ConvertToLLVM) add_subdirectory(DatapathToComb) add_subdirectory(DatapathToSMT) add_subdirectory(DCToHW) diff --git a/lib/Conversion/CombToLLVM/CombToLLVM.cpp b/lib/Conversion/CombToLLVM/CombToLLVM.cpp index c3c91225485e..96532270e3ae 100644 --- a/lib/Conversion/CombToLLVM/CombToLLVM.cpp +++ b/lib/Conversion/CombToLLVM/CombToLLVM.cpp @@ -1,4 +1,4 @@ -//===- CombToLLVM.cpp - Comb to LLVM Conversion Pass ----------------------===// +//===- CombToLLVM.cpp - Comb to LLVM Conversion Patterns ------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,36 +6,19 @@ // //===----------------------------------------------------------------------===// // -// This is the main Comb to LLVM Conversion Pass Implementation. +// This file implements Comb to LLVM conversion patterns. // //===----------------------------------------------------------------------===// #include "circt/Conversion/CombToLLVM.h" -#include "circt/Conversion/CombToArith.h" -#include "circt/Conversion/HWToLLVM.h" #include "circt/Dialect/Comb/CombOps.h" -#include "circt/Dialect/SV/SVOps.h" -#include "mlir/Conversion/ArithToLLVM/ArithToLLVM.h" -#include "mlir/Conversion/ControlFlowToLLVM/ControlFlowToLLVM.h" -#include "mlir/Conversion/FuncToLLVM/ConvertFuncToLLVM.h" -#include "mlir/Conversion/IndexToLLVM/IndexToLLVM.h" -#include "mlir/Conversion/LLVMCommon/ConversionTarget.h" #include "mlir/Conversion/LLVMCommon/Pattern.h" -#include "mlir/Conversion/SCFToControlFlow/SCFToControlFlow.h" -#include "mlir/Dialect/Arith/IR/Arith.h" -#include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/Dialect/LLVMIR/LLVMDialect.h" -#include "mlir/Pass/Pass.h" -#include "mlir/Transforms/DialectConversion.h" +#include "mlir/IR/BuiltinTypes.h" using namespace mlir; using namespace circt; -namespace circt { -#define GEN_PASS_DEF_CONVERTTOLLVM -#include "circt/Conversion/Passes.h.inc" -} // namespace circt - namespace { //===----------------------------------------------------------------------===// @@ -64,18 +47,6 @@ struct CombParityOpConversion : public ConvertToLLVMPattern { } }; -//===----------------------------------------------------------------------===// -// Pass Implementation -//===----------------------------------------------------------------------===// - -struct CombToLLVMLoweringPass - : public circt::impl::ConvertToLLVMBase { - void runOnOperation() override; - -private: - void convertFuncOp(func::FuncOp funcOp); -}; - } // namespace //===----------------------------------------------------------------------===// @@ -89,64 +60,3 @@ void circt::populateCombToLLVMConversionPatterns(LLVMTypeConverter &converter, // pipeline patterns.add(patterns.getContext(), converter); } - -void CombToLLVMLoweringPass::runOnOperation() { - // Iterate over all func.func operations in the module and convert them - for (auto funcOp : - llvm::make_early_inc_range(getOperation().getOps())) { - convertFuncOp(funcOp); - } -} - -void CombToLLVMLoweringPass::convertFuncOp(func::FuncOp funcOp) { - MLIRContext *context = &getContext(); - RewritePatternSet patterns(context); - auto converter = mlir::LLVMTypeConverter(context); - - // Add HW to LLVM type conversions - populateHWToLLVMTypeConversions(converter); - - LLVMConversionTarget target(*context); - target.addIllegalDialect(); - target.addIllegalDialect(); - - // Mark HW and SV dialects as legal - we only convert operations inside - // func.func - target.addLegalDialect(); - target.addLegalDialect(); - - // Setup the conversion patterns in the correct order: - // 1. SCF to ControlFlow (for structured control flow) - populateSCFToControlFlowConversionPatterns(patterns); - - // 2. Func to LLVM (for function operations) - populateFuncToLLVMConversionPatterns(converter, patterns); - - // 3. ControlFlow to LLVM (for control flow operations) - cf::populateControlFlowToLLVMConversionPatterns(converter, patterns); - - // 4. Comb to Arith (for most combinational operations) - populateCombToArithConversionPatterns(converter, patterns); - - // 5. Arith to LLVM (for arithmetic operations) - arith::populateArithToLLVMConversionPatterns(converter, patterns); - - // 6. Index to LLVM (for index operations) - index::populateIndexToLLVMConversionPatterns(converter, patterns); - - // 7. Any function op interface type conversion - populateAnyFunctionOpInterfaceTypeConversionPattern(patterns, converter); - - // 8. Comb to LLVM (for operations without Comb-to-Arith patterns, like - // parity) - populateCombToLLVMConversionPatterns(converter, patterns); - - // Apply the partial conversion only to this func.func operation - if (failed(applyPartialConversion(funcOp, target, std::move(patterns)))) - signalPassFailure(); -} - -/// Create a Comb to LLVM conversion pass. -std::unique_ptr> circt::createConvertCombToLLVMPass() { - return std::make_unique(); -} diff --git a/lib/Conversion/ConvertToLLVM/CMakeLists.txt b/lib/Conversion/ConvertToLLVM/CMakeLists.txt new file mode 100644 index 000000000000..81c145e045f7 --- /dev/null +++ b/lib/Conversion/ConvertToLLVM/CMakeLists.txt @@ -0,0 +1,25 @@ +add_circt_conversion_library(CIRCTConvertToLLVM + ConvertToLLVM.cpp + + DEPENDS + CIRCTConversionPassIncGen + + LINK_COMPONENTS + Core + + LINK_LIBS PUBLIC + CIRCTComb + CIRCTCombToArith + CIRCTCombToLLVM + CIRCTHW + CIRCTHWToLLVM + CIRCTSupport + MLIRArithToLLVM + MLIRControlFlowToLLVM + MLIRFuncToLLVM + MLIRIndexToLLVM + MLIRLLVMCommonConversion + MLIRSCFToControlFlow + MLIRTransforms +) + diff --git a/lib/Conversion/ConvertToLLVM/ConvertToLLVM.cpp b/lib/Conversion/ConvertToLLVM/ConvertToLLVM.cpp new file mode 100644 index 000000000000..723bd36609af --- /dev/null +++ b/lib/Conversion/ConvertToLLVM/ConvertToLLVM.cpp @@ -0,0 +1,114 @@ +//===- ConvertToLLVM.cpp - ConvertToLLVM Pass ----------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements the ConvertToLLVM pass. +// +//===----------------------------------------------------------------------===// + +#include "circt/Conversion/CombToArith.h" +#include "circt/Conversion/CombToLLVM.h" +#include "circt/Conversion/HWToLLVM.h" +#include "circt/Dialect/Comb/CombOps.h" +#include "circt/Dialect/SV/SVOps.h" +#include "mlir/Conversion/ArithToLLVM/ArithToLLVM.h" +#include "mlir/Conversion/ControlFlowToLLVM/ControlFlowToLLVM.h" +#include "mlir/Conversion/FuncToLLVM/ConvertFuncToLLVM.h" +#include "mlir/Conversion/IndexToLLVM/IndexToLLVM.h" +#include "mlir/Conversion/LLVMCommon/ConversionTarget.h" +#include "mlir/Conversion/LLVMCommon/Pattern.h" +#include "mlir/Conversion/SCFToControlFlow/SCFToControlFlow.h" +#include "mlir/Dialect/Arith/IR/Arith.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" +#include "mlir/Dialect/LLVMIR/LLVMDialect.h" +#include "mlir/Pass/Pass.h" +#include "mlir/Transforms/DialectConversion.h" + +using namespace mlir; +using namespace circt; + +namespace circt { +#define GEN_PASS_DEF_CONVERTTOLLVM +#include "circt/Conversion/Passes.h.inc" +} // namespace circt + +namespace { + +//===----------------------------------------------------------------------===// +// Pass Implementation +//===----------------------------------------------------------------------===// + +struct ConvertToLLVMPass + : public circt::impl::ConvertToLLVMBase { + void runOnOperation() override; + +private: + void convertFuncOp(func::FuncOp funcOp); +}; + +} // namespace + +void ConvertToLLVMPass::runOnOperation() { + // Iterate over all func.func operations in the module and convert them + for (auto funcOp : + llvm::make_early_inc_range(getOperation().getOps())) { + convertFuncOp(funcOp); + } +} + +void ConvertToLLVMPass::convertFuncOp(func::FuncOp funcOp) { + MLIRContext *context = &getContext(); + RewritePatternSet patterns(context); + auto converter = mlir::LLVMTypeConverter(context); + + // Add HW to LLVM type conversions + populateHWToLLVMTypeConversions(converter); + + LLVMConversionTarget target(*context); + target.addIllegalDialect(); + target.addIllegalDialect(); + + // Mark HW and SV dialects as legal - we only convert operations inside + // func.func + target.addLegalDialect(); + target.addLegalDialect(); + + // Setup the conversion patterns in the correct order: + // 1. SCF to ControlFlow (for structured control flow) + populateSCFToControlFlowConversionPatterns(patterns); + + // 2. Func to LLVM (for function operations) + populateFuncToLLVMConversionPatterns(converter, patterns); + + // 3. ControlFlow to LLVM (for control flow operations) + cf::populateControlFlowToLLVMConversionPatterns(converter, patterns); + + // 4. Comb to Arith (for most combinational operations) + populateCombToArithConversionPatterns(converter, patterns); + + // 5. Arith to LLVM (for arithmetic operations) + arith::populateArithToLLVMConversionPatterns(converter, patterns); + + // 6. Index to LLVM (for index operations) + index::populateIndexToLLVMConversionPatterns(converter, patterns); + + // 7. Any function op interface type conversion + populateAnyFunctionOpInterfaceTypeConversionPattern(patterns, converter); + + // 8. Comb to LLVM (for operations without Comb-to-Arith patterns, like + // parity) + populateCombToLLVMConversionPatterns(converter, patterns); + + // Apply the partial conversion only to this func.func operation + if (failed(applyPartialConversion(funcOp, target, std::move(patterns)))) + signalPassFailure(); +} + +/// Create a Comb to LLVM conversion pass. +std::unique_ptr> circt::createConvertToLLVMPass() { + return std::make_unique(); +} diff --git a/test/Conversion/CombToLLVM/comb-to-llvm.mlir b/test/Conversion/CombToLLVM/comb-to-llvm.mlir index 35bf47e969e0..c0776ac89257 100644 --- a/test/Conversion/CombToLLVM/comb-to-llvm.mlir +++ b/test/Conversion/CombToLLVM/comb-to-llvm.mlir @@ -178,38 +178,10 @@ func.func @test_control_flow(%cond: i1, %arg0: i32) -> i32 { // Test HW module and SV operations (should NOT be converted - only func.func operations are converted) hw.module @test_hw_sv_module(in %scan_data : i9) { %0 = comb.extract %scan_data from 0 : (i9) -> i8 - %top_reg_decoded = sv.wire : !hw.inout - sv.assign %top_reg_decoded, %0 : i8 - %1 = comb.extract %scan_data from 8 : (i9) -> i1 - %child.child_reg_decoded = sv.wire : !hw.inout - sv.assign %child.child_reg_decoded, %1 : i1 - %2 = comb.extract %scan_data from 8 : (i9) -> i1 - hw.instance "child_decoder" @test_child_module(scan_data: %2: i1) -> () hw.output } -hw.module @test_child_module(in %scan_data : i1) { - %0 = comb.extract %scan_data from 0 : (i1) -> i1 - %SimpleChild.child_reg_decoded = sv.wire : !hw.inout - sv.assign %SimpleChild.child_reg_decoded, %0 : i1 - hw.output -} // CHECK-LABEL: hw.module @test_hw_sv_module // CHECK-SAME: (in %scan_data : i9) // CHECK: %[[EXTRACT1:.+]] = comb.extract %scan_data from 0 : (i9) -> i8 -// CHECK: %[[WIRE1:.+]] = sv.wire : !hw.inout -// CHECK: sv.assign %[[WIRE1]], %[[EXTRACT1]] : i8 -// CHECK: %[[EXTRACT2:.+]] = comb.extract %scan_data from 8 : (i9) -> i1 -// CHECK: %[[WIRE2:.+]] = sv.wire : !hw.inout -// CHECK: sv.assign %[[WIRE2]], %[[EXTRACT2]] : i1 -// CHECK: %[[EXTRACT3:.+]] = comb.extract %scan_data from 8 : (i9) -> i1 -// CHECK: hw.instance "child_decoder" @test_child_module(scan_data: %[[EXTRACT3]]: i1) -// CHECK: hw.output - -// CHECK-LABEL: hw.module @test_child_module -// CHECK-SAME: (in %scan_data : i1) -// CHECK: %[[EXTRACT:.+]] = comb.extract %scan_data from 0 : (i1) -> i1 -// CHECK: %[[WIRE:.+]] = sv.wire : !hw.inout -// CHECK: sv.assign %[[WIRE]], %[[EXTRACT]] : i1 -// CHECK: hw.output From 70b64bc9d7e3fd8246b50adb54392d658efa9275 Mon Sep 17 00:00:00 2001 From: Prithayan Barua Date: Thu, 30 Oct 2025 14:45:15 -0700 Subject: [PATCH 5/8] Create a new pass ConvertToLLVM --- include/circt/Conversion/Passes.td | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/circt/Conversion/Passes.td b/include/circt/Conversion/Passes.td index 0f55b2888f59..68064c510207 100644 --- a/include/circt/Conversion/Passes.td +++ b/include/circt/Conversion/Passes.td @@ -520,9 +520,9 @@ def ConvertHWToLLVM : Pass<"convert-hw-to-llvm", "mlir::ModuleOp"> { def ConvertToLLVM : Pass<"convert-to-llvm", "mlir::ModuleOp"> { let summary = "Convert Comb and HW to LLVM"; let description = [{ - This pass translates Comb and HW operations to LLVM IR. It combines - both HW and Comb conversion patterns to provide a complete lowering - from hardware description to LLVM IR. + This pass translates Comb and HW operations inside func.func to LLVM IR. + It combines both HW and Comb conversion patterns to provide a complete + lowering from hardware description to LLVM IR. }]; let dependentDialects = [ "mlir::LLVM::LLVMDialect", From bf04b41c08ee79fbfbe3f3640d84c2edbc7242b5 Mon Sep 17 00:00:00 2001 From: Prithayan Barua Date: Thu, 30 Oct 2025 21:42:43 -0700 Subject: [PATCH 6/8] cleanup --- include/circt/Conversion/CombToLLVM.h | 6 ------ include/circt/Conversion/Passes.h | 5 ++++- include/circt/Conversion/Passes.td | 2 +- lib/Conversion/CombToLLVM/CMakeLists.txt | 10 +--------- lib/Conversion/CombToLLVM/CombToLLVM.cpp | 5 ++++- lib/Conversion/ConvertToLLVM/ConvertToLLVM.cpp | 14 ++++---------- 6 files changed, 14 insertions(+), 28 deletions(-) diff --git a/include/circt/Conversion/CombToLLVM.h b/include/circt/Conversion/CombToLLVM.h index 80664c1ded32..1b4695018ebf 100644 --- a/include/circt/Conversion/CombToLLVM.h +++ b/include/circt/Conversion/CombToLLVM.h @@ -23,16 +23,10 @@ class LLVMTypeConverter; namespace circt { -#define GEN_PASS_DECL_CONVERTTOLLVM -#include "circt/Conversion/Passes.h.inc" - /// Get the Comb to LLVM conversion patterns. void populateCombToLLVMConversionPatterns(mlir::LLVMTypeConverter &converter, RewritePatternSet &patterns); -/// Create a Comb to LLVM conversion pass. -std::unique_ptr> createConvertToLLVMPass(); - } // namespace circt #endif // CIRCT_CONVERSION_COMBTOLLVM_COMBTOLLVM_H diff --git a/include/circt/Conversion/Passes.h b/include/circt/Conversion/Passes.h index b4bf9b8147a7..fccbe1da98b3 100644 --- a/include/circt/Conversion/Passes.h +++ b/include/circt/Conversion/Passes.h @@ -21,7 +21,6 @@ #include "circt/Conversion/CalyxToHW.h" #include "circt/Conversion/CombToArith.h" #include "circt/Conversion/CombToDatapath.h" -#include "circt/Conversion/CombToLLVM.h" #include "circt/Conversion/CombToSMT.h" #include "circt/Conversion/CombToSynth.h" #include "circt/Conversion/ConvertToArcs.h" @@ -57,6 +56,10 @@ namespace circt { +// Generate pass declarations. +#define GEN_PASS_DECL_CONVERTTOLLVM +#include "circt/Conversion/Passes.h.inc" + // Generate the code for registering conversion passes. #define GEN_PASS_REGISTRATION #include "circt/Conversion/Passes.h.inc" diff --git a/include/circt/Conversion/Passes.td b/include/circt/Conversion/Passes.td index 68064c510207..8783173080cb 100644 --- a/include/circt/Conversion/Passes.td +++ b/include/circt/Conversion/Passes.td @@ -514,7 +514,7 @@ def ConvertHWToLLVM : Pass<"convert-hw-to-llvm", "mlir::ModuleOp"> { } //===----------------------------------------------------------------------===// -// CombToLLVM +// ConvertToLLVM //===----------------------------------------------------------------------===// def ConvertToLLVM : Pass<"convert-to-llvm", "mlir::ModuleOp"> { diff --git a/lib/Conversion/CombToLLVM/CMakeLists.txt b/lib/Conversion/CombToLLVM/CMakeLists.txt index 6d155339d783..5b1db6b700c2 100644 --- a/lib/Conversion/CombToLLVM/CMakeLists.txt +++ b/lib/Conversion/CombToLLVM/CMakeLists.txt @@ -1,6 +1,7 @@ add_circt_conversion_library(CIRCTCombToLLVM CombToLLVM.cpp + DEPENDS CIRCTConversionPassIncGen @@ -9,15 +10,6 @@ add_circt_conversion_library(CIRCTCombToLLVM LINK_LIBS PUBLIC CIRCTComb - CIRCTCombToArith - CIRCTHW - CIRCTHWToLLVM - CIRCTSupport - MLIRArithToLLVM - MLIRControlFlowToLLVM - MLIRFuncToLLVM - MLIRIndexToLLVM MLIRLLVMCommonConversion - MLIRSCFToControlFlow MLIRTransforms ) diff --git a/lib/Conversion/CombToLLVM/CombToLLVM.cpp b/lib/Conversion/CombToLLVM/CombToLLVM.cpp index 96532270e3ae..75a789fe8935 100644 --- a/lib/Conversion/CombToLLVM/CombToLLVM.cpp +++ b/lib/Conversion/CombToLLVM/CombToLLVM.cpp @@ -12,9 +12,12 @@ #include "circt/Conversion/CombToLLVM.h" #include "circt/Dialect/Comb/CombOps.h" +#include "circt/Support/LLVM.h" +#include "mlir/Conversion/LLVMCommon/ConversionTarget.h" #include "mlir/Conversion/LLVMCommon/Pattern.h" #include "mlir/Dialect/LLVMIR/LLVMDialect.h" -#include "mlir/IR/BuiltinTypes.h" +#include "mlir/Pass/Pass.h" +#include "mlir/Transforms/DialectConversion.h" using namespace mlir; using namespace circt; diff --git a/lib/Conversion/ConvertToLLVM/ConvertToLLVM.cpp b/lib/Conversion/ConvertToLLVM/ConvertToLLVM.cpp index 723bd36609af..414fac008711 100644 --- a/lib/Conversion/ConvertToLLVM/ConvertToLLVM.cpp +++ b/lib/Conversion/ConvertToLLVM/ConvertToLLVM.cpp @@ -34,24 +34,20 @@ using namespace circt; namespace circt { #define GEN_PASS_DEF_CONVERTTOLLVM #include "circt/Conversion/Passes.h.inc" -} // namespace circt -namespace { +namespace impl { //===----------------------------------------------------------------------===// // Pass Implementation //===----------------------------------------------------------------------===// -struct ConvertToLLVMPass - : public circt::impl::ConvertToLLVMBase { +struct ConvertToLLVMPass : public ConvertToLLVMBase { void runOnOperation() override; private: void convertFuncOp(func::FuncOp funcOp); }; -} // namespace - void ConvertToLLVMPass::runOnOperation() { // Iterate over all func.func operations in the module and convert them for (auto funcOp : @@ -108,7 +104,5 @@ void ConvertToLLVMPass::convertFuncOp(func::FuncOp funcOp) { signalPassFailure(); } -/// Create a Comb to LLVM conversion pass. -std::unique_ptr> circt::createConvertToLLVMPass() { - return std::make_unique(); -} +} // namespace impl +} // namespace circt From 11fc955fa6130c62b7b700bf6e7ce953eb531080 Mon Sep 17 00:00:00 2001 From: Prithayan Barua Date: Mon, 3 Nov 2025 16:41:17 -0800 Subject: [PATCH 7/8] Add the header file --- include/circt/Conversion/ConvertToLLVM.h | 27 +++++++++++++++++++ include/circt/Conversion/Passes.h | 1 + .../ConvertToLLVM/ConvertToLLVM.cpp | 1 + 3 files changed, 29 insertions(+) create mode 100644 include/circt/Conversion/ConvertToLLVM.h diff --git a/include/circt/Conversion/ConvertToLLVM.h b/include/circt/Conversion/ConvertToLLVM.h new file mode 100644 index 000000000000..3a1257286086 --- /dev/null +++ b/include/circt/Conversion/ConvertToLLVM.h @@ -0,0 +1,27 @@ +//===- ConvertToLLVM.h - ConvertToLLVM pass entry point ---------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This header file defines prototypes that expose the ConvertToLLVM pass +// constructors. +// +//===----------------------------------------------------------------------===// + +#ifndef CIRCT_CONVERSION_CONVERTTOLLVM_H +#define CIRCT_CONVERSION_CONVERTTOLLVM_H + +#include "circt/Support/LLVM.h" +#include + +namespace circt { + +#define GEN_PASS_DECL_CONVERTTOLLVM +#include "circt/Conversion/Passes.h.inc" + +} // namespace circt + +#endif // CIRCT_CONVERSION_CONVERTTOLLVM_H diff --git a/include/circt/Conversion/Passes.h b/include/circt/Conversion/Passes.h index fccbe1da98b3..3d7c49ad6256 100644 --- a/include/circt/Conversion/Passes.h +++ b/include/circt/Conversion/Passes.h @@ -24,6 +24,7 @@ #include "circt/Conversion/CombToSMT.h" #include "circt/Conversion/CombToSynth.h" #include "circt/Conversion/ConvertToArcs.h" +#include "circt/Conversion/ConvertToLLVM.h" #include "circt/Conversion/DCToHW.h" #include "circt/Conversion/DatapathToComb.h" #include "circt/Conversion/DatapathToSMT.h" diff --git a/lib/Conversion/ConvertToLLVM/ConvertToLLVM.cpp b/lib/Conversion/ConvertToLLVM/ConvertToLLVM.cpp index 414fac008711..3b4531803001 100644 --- a/lib/Conversion/ConvertToLLVM/ConvertToLLVM.cpp +++ b/lib/Conversion/ConvertToLLVM/ConvertToLLVM.cpp @@ -10,6 +10,7 @@ // //===----------------------------------------------------------------------===// +#include "circt/Conversion/ConvertToLLVM.h" #include "circt/Conversion/CombToArith.h" #include "circt/Conversion/CombToLLVM.h" #include "circt/Conversion/HWToLLVM.h" From d70af9f0d86e481f91d6062f611fc10b32a9590a Mon Sep 17 00:00:00 2001 From: Prithayan Barua Date: Mon, 3 Nov 2025 19:16:04 -0800 Subject: [PATCH 8/8] Add To CMake for CAPI --- lib/CAPI/Conversion/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/CAPI/Conversion/CMakeLists.txt b/lib/CAPI/Conversion/CMakeLists.txt index 97b2bde8ab99..3b032e19d545 100644 --- a/lib/CAPI/Conversion/CMakeLists.txt +++ b/lib/CAPI/Conversion/CMakeLists.txt @@ -14,6 +14,7 @@ add_circt_public_c_api_library(CIRCTCAPIConversion CIRCTCombToLLVM CIRCTCombToSMT CIRCTConvertToArcs + CIRCTConvertToLLVM CIRCTDatapathToComb CIRCTDatapathToSMT CIRCTDCToHW