-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[CIR] Upstream support for lowering cir.switch to LLVM #140425
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
@llvm/pr-subscribers-clang @llvm/pr-subscribers-clangir Author: None (Andres-Salamanca) ChangesThis PR adds support for lowering the Patch is 26.83 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/140425.diff 4 Files Affected:
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index c8eac87f6cdff..05c772e7c1a53 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -1038,6 +1038,37 @@ mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite(
return mlir::success();
}
+mlir::LogicalResult CIRToLLVMSwitchFlatOpLowering::matchAndRewrite(
+ cir::SwitchFlatOp op, OpAdaptor adaptor,
+ mlir::ConversionPatternRewriter &rewriter) const {
+
+ llvm::SmallVector<mlir::APInt, 8> caseValues;
+ if (op.getCaseValues()) {
+ for (mlir::Attribute val : op.getCaseValues()) {
+ auto intAttr = dyn_cast<cir::IntAttr>(val);
+ caseValues.push_back(intAttr.getValue());
+ }
+ }
+
+ llvm::SmallVector<mlir::Block *, 8> caseDestinations;
+ llvm::SmallVector<mlir::ValueRange, 8> caseOperands;
+
+ for (mlir::Block *x : op.getCaseDestinations()) {
+ caseDestinations.push_back(x);
+ }
+
+ for (mlir::OperandRange x : op.getCaseOperands()) {
+ caseOperands.push_back(x);
+ }
+
+ // Set switch op to branch to the newly created blocks.
+ rewriter.setInsertionPoint(op);
+ rewriter.replaceOpWithNewOp<mlir::LLVM::SwitchOp>(
+ op, adaptor.getCondition(), op.getDefaultDestination(),
+ op.getDefaultOperands(), caseValues, caseDestinations, caseOperands);
+ return mlir::success();
+}
+
mlir::LogicalResult CIRToLLVMUnaryOpLowering::matchAndRewrite(
cir::UnaryOp op, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const {
@@ -1641,6 +1672,7 @@ void ConvertCIRToLLVMPass::runOnOperation() {
CIRToLLVMGetGlobalOpLowering,
CIRToLLVMGetMemberOpLowering,
CIRToLLVMSelectOpLowering,
+ CIRToLLVMSwitchFlatOpLowering,
CIRToLLVMShiftOpLowering,
CIRToLLVMStackSaveOpLowering,
CIRToLLVMStackRestoreOpLowering,
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
index bd077e3d1d1e0..dde0cfcabe395 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
@@ -149,6 +149,16 @@ class CIRToLLVMFuncOpLowering : public mlir::OpConversionPattern<cir::FuncOp> {
mlir::ConversionPatternRewriter &) const override;
};
+class CIRToLLVMSwitchFlatOpLowering
+ : public mlir::OpConversionPattern<cir::SwitchFlatOp> {
+public:
+ using mlir::OpConversionPattern<cir::SwitchFlatOp>::OpConversionPattern;
+
+ mlir::LogicalResult
+ matchAndRewrite(cir::SwitchFlatOp op, OpAdaptor,
+ mlir::ConversionPatternRewriter &) const override;
+};
+
class CIRToLLVMGetGlobalOpLowering
: public mlir::OpConversionPattern<cir::GetGlobalOp> {
public:
diff --git a/clang/test/CIR/CodeGen/switch.cpp b/clang/test/CIR/CodeGen/switch.cpp
index 0bd4e0759e634..a3dbac89fb856 100644
--- a/clang/test/CIR/CodeGen/switch.cpp
+++ b/clang/test/CIR/CodeGen/switch.cpp
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
/// RUN: FileCheck --input-file=%t.cir %s --check-prefix=CIR
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefix=LLVM
// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
// RUN: FileCheck --input-file=%t.ll %s --check-prefix=OGCG
void sw1(int a) {
@@ -28,6 +30,36 @@ void sw1(int a) {
// CIR: cir.alloca !s32i, !cir.ptr<!s32i>, ["yolo", init]
// CIR: cir.break
+// LLVM: define void @_Z3sw1i
+// LLVM: store i32 1, ptr %[[B_ADDR:.*]], align 4
+// LLVM: %[[A_VAL:.*]] = load i32, ptr %[[A_ADDR:.*]], align 4
+// LLVM: br label %[[BB7:.*]]
+// LLVM: [[BB7]]:
+// LLVM: switch i32 %[[A_VAL]], label %[[EXIT:.*]] [
+// LLVM-DAG: i32 0, label %[[CASE0:.*]]
+// LLVM-DAG: i32 1, label %[[CASE1:.*]]
+// LLVM-DAG: i32 2, label %[[CASE2:.*]]
+// LLVM: ]
+// LLVM: [[CASE0]]:
+// LLVM: %[[B:.*]] = load i32, ptr %[[B_ADDR]], align 4
+// LLVM: %[[INC0:.*]] = add nsw i32 %[[B]], 1
+// LLVM: store i32 %[[INC0]], ptr %[[B_ADDR]], align 4
+// LLVM: br label %[[EXIT]]
+// LLVM: [[CASE1]]:
+// LLVM: br label %[[EXIT]]
+// LLVM: [[CASE2]]:
+// LLVM: br label %[[BB14:.*]]
+// LLVM: [[BB14]]:
+// LLVM: %[[B2:.*]] = load i32, ptr %[[B_ADDR]], align 4
+// LLVM: %[[INC2:.*]] = add nsw i32 %[[B2]], 1
+// LLVM: store i32 %[[INC2]], ptr %[[B_ADDR]], align 4
+// LLVM: store i32 100, ptr %[[YOLO:.*]], align 4
+// LLVM: br label %[[EXIT]]
+// LLVM: [[EXIT]]:
+// LLVM: br label %[[DEFAULT:.*]]
+// LLVM: [[DEFAULT]]:
+// LLVM: ret void
+
// OGCG: define dso_local void @_Z3sw1i
// OGCG: entry:
// OGCG: %[[A_ADDR:.*]] = alloca i32, align 4
@@ -74,6 +106,26 @@ void sw2(int a) {
// CIR-NEXT: %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i
// CIR-NEXT: cir.store %[[ZERO]], %[[FOMO]] : !s32i, !cir.ptr<!s32i>
+// LLVM: define void @_Z3sw2i
+// LLVM: store i32 2, ptr %[[YOLO_ADDR:.*]], align 4
+// LLVM: %[[A_VAL:.*]] = load i32, ptr %[[A_ADDR:.*]], align 4
+// LLVM: br label %[[SWITCH:.*]]
+// LLVM: [[SWITCH]]:
+// LLVM: switch i32 %[[A_VAL]], label %[[EXIT:.*]] [
+// LLVM: i32 3, label %[[CASE3:.*]]
+// LLVM: ]
+// LLVM: [[CASE3]]:
+// LLVM: store i32 0, ptr %[[FOMO_ADDR:.*]], align 4
+// LLVM: %[[YOLO_VAL:.*]] = load i32, ptr %[[YOLO_ADDR]], align 4
+// LLVM: %[[FOMO_VAL:.*]] = load i32, ptr %[[FOMO_ADDR]], align 4
+// LLVM: %[[YOLO_PLUS_FOMO:.*]] = add nsw i32 %[[YOLO_VAL]], %[[FOMO_VAL]]
+// LLVM: store i32 %[[YOLO_PLUS_FOMO]], ptr %[[YOLO_ADDR]], align 4
+// LLVM: br label %[[EXIT]]
+// LLVM: [[EXIT]]:
+// LLVM: br label %[[RET:.*]]
+// LLVM: [[RET]]:
+// LLVM: ret void
+
// OGCG: define dso_local void @_Z3sw2i
// OGCG: entry:
// OGCG: %[[A_ADDR:.*]] = alloca i32, align 4
@@ -109,6 +161,19 @@ void sw3(int a) {
// CIR-NEXT: cir.yield
// CIR-NEXT: }
+// LLVM-LABEL: define void @_Z3sw3i
+// LLVM: %[[A_VAL:.*]] = load i32, ptr %[[A_ADDR:.*]], align 4
+// LLVM: br label %[[SWITCH:.*]]
+// LLVM: [[SWITCH]]:
+// LLVM: switch i32 %[[A_VAL]], label %[[DEFAULT:.*]] [
+// LLVM: ]
+// LLVM: [[DEFAULT]]:
+// LLVM: br label %[[EXIT:.*]]
+// LLVM: [[EXIT:.*]]:
+// LLVM: br label %[[RET:.*]]
+// LLVM: [[RET]]:
+// LLVM: ret void
+
// OGCG: define dso_local void @_Z3sw3i
// OGCG: entry:
// OGCG: %[[A_ADDR:.*]] = alloca i32, align 4
@@ -150,6 +215,32 @@ int sw4(int a) {
// CIR-NEXT: cir.yield
// CIR-NEXT: }
+// LLVM: define i32 @_Z3sw4i
+// LLVM: %[[A_ADDR:.*]] = alloca i32, i64 1, align 4
+// LLVM: %[[RET_ADDR:.*]] = alloca i32, i64 1, align 4
+// LLVM: br label %[[ENTRY:.*]]
+// LLVM: [[ENTRY]]:
+// LLVM: %[[A_VAL:.*]] = load i32, ptr %[[A_ADDR]], align 4
+// LLVM: br label %[[SWITCH:.*]]
+// LLVM: [[SWITCH]]:
+// LLVM: switch i32 %[[A_VAL]], label %[[DEFAULT:.*]] [
+// LLVM-DAG: i32 42, label %[[CASE42:.*]]
+// LLVM: ]
+// LLVM: [[CASE42]]:
+// LLVM: br label %[[CASE42_BODY:.*]]
+// LLVM: [[CASE42_BODY]]:
+// LLVM: store i32 3, ptr %[[RET_ADDR]], align 4
+// LLVM: %[[RET3:.*]] = load i32, ptr %[[RET_ADDR]], align 4
+// LLVM: ret i32 %[[RET3]]
+// LLVM: [[DEFAULT]]:
+// LLVM: store i32 2, ptr %[[RET_ADDR]], align 4
+// LLVM: %[[RET2:.*]] = load i32, ptr %[[RET_ADDR]], align 4
+// LLVM: ret i32 %[[RET2]]
+// LLVM: [[EXIT_UNRE:.*]]:
+// LLVM: store i32 0, ptr %[[RET_ADDR]], align 4
+// LLVM: %[[RET0:.*]] = load i32, ptr %[[RET_ADDR]], align 4
+// LLVM: ret i32 %[[RET0]]
+
// OGCG: define dso_local noundef i32 @_Z3sw4i
// OGCG: entry:
// OGCG: %[[RETVAL:.*]] = alloca i32, align 4
@@ -180,6 +271,23 @@ void sw5(int a) {
// CIR-NEXT: cir.yield
// CIR-NEXT: }
+// LLVM-LABEL: define void @_Z3sw5i
+// LLVM: %[[A_ADDR:.*]] = alloca i32, i64 1, align 4
+// LLVM: br label %[[ENTRY:.*]]
+// LLVM: [[ENTRY]]:
+// LLVM: %[[A_VAL:.*]] = load i32, ptr %[[A_ADDR]], align 4
+// LLVM: br label %[[SWITCH:.*]]
+// LLVM: [[SWITCH]]:
+// LLVM: switch i32 %[[A_VAL]], label %[[EXIT:.*]] [
+// LLVM-DAG: i32 1, label %[[CASE1:.*]]
+// LLVM: ]
+// LLVM: [[CASE1]]:
+// LLVM: br label %[[EXIT:.*]]
+// LLVM: [[EXIT]]:
+// LLVM: br label %[[RET:.*]]
+// LLVM: [[RET]]:
+// LLVM: ret void
+
// OGCG: define dso_local void @_Z3sw5i
// OGCG: entry:
// OGCG: %[[A_ADDR:.*]] = alloca i32, align 4
@@ -226,6 +334,42 @@ void sw6(int a) {
// CIR-NEXT: cir.break
// CIR-NEXT: }
+// LLVM: define void @_Z3sw6i
+// LLVM: %[[A_VAL:.*]] = load i32, ptr %[[A_ADDR:.*]], align 4
+// LLVM: br label %[[SWITCH:.*]]
+// LLVM: [[SWITCH]]:
+// LLVM: switch i32 %[[A_VAL]], label %[[EXIT:.*]] [
+// LLVM-DAG: i32 0, label %[[CASE0:.*]]
+// LLVM-DAG: i32 1, label %[[CASE1:.*]]
+// LLVM-DAG: i32 2, label %[[CASE2:.*]]
+// LLVM-DAG: i32 3, label %[[CASE3:.*]]
+// LLVM-DAG: i32 4, label %[[CASE4:.*]]
+// LLVM-DAG: i32 5, label %[[CASE5:.*]]
+// LLVM: ]
+// LLVM: [[CASE0]]:
+// LLVM: br label %[[CASE0_CONT:.*]]
+// LLVM: [[CASE0_CONT]]:
+// LLVM: br label %[[CASE1]]
+// LLVM: [[CASE1]]:
+// LLVM: br label %[[CASE1_CONT:.*]]
+// LLVM: [[CASE1_CONT]]:
+// LLVM: br label %[[CASE2]]
+// LLVM: [[CASE2]]:
+// LLVM: br label %[[EXIT:.*]]
+// LLVM: [[CASE3]]:
+// LLVM: br label %[[CASE3_CONT:.*]]
+// LLVM: [[CASE3_CONT]]:
+// LLVM: br label %[[CASE4]]
+// LLVM: [[CASE4]]:
+// LLVM: br label %[[CASE4_CONT:.*]]
+// LLVM: [[CASE4_CONT]]:
+// LLVM: br label %[[CASE5]]
+// LLVM: [[CASE5]]:
+// LLVM: br label %[[EXIT]]
+// LLVM: [[EXIT]]:
+// LLVM: br label %[[RET:.*]]
+// LLVM: [[RET]]:
+// LLVM: ret void
// OGCG: define dso_local void @_Z3sw6i
// OGCG: entry:
@@ -284,6 +428,45 @@ void sw7(int a) {
// CIR-NEXT: cir.yield
// CIR: }
+// LLVM: define void @_Z3sw7i
+// LLVM: %[[A_VAL:.*]] = load i32, ptr %[[A_ADDR:.*]], align 4
+// LLVM: br label %[[SWITCH:.*]]
+// LLVM: [[SWITCH]]:
+// LLVM: switch i32 %[[A_VAL]], label %[[EXIT:.*]] [
+// LLVM-DAG: i32 0, label %[[CASE0:.*]]
+// LLVM-DAG: i32 1, label %[[CASE1:.*]]
+// LLVM-DAG: i32 2, label %[[CASE2:.*]]
+// LLVM-DAG: i32 3, label %[[CASE3:.*]]
+// LLVM-DAG: i32 4, label %[[CASE4:.*]]
+// LLVM-DAG: i32 5, label %[[CASE5:.*]]
+// LLVM: ]
+// LLVM: [[CASE0]]:
+// LLVM: br label %[[CASE0_CONT:.*]]
+// LLVM: [[CASE0_CONT]]:
+// LLVM: br label %[[CASE1]]
+// LLVM: [[CASE1]]:
+// LLVM: br label %[[CASE1_CONT:.*]]
+// LLVM: [[CASE1_CONT]]:
+// LLVM: br label %[[CASE2]]
+// LLVM: [[CASE2]]:
+// LLVM: br label %[[CASE2_CONT:.*]]
+// LLVM: [[CASE2_CONT]]:
+// LLVM: br label %[[CASE3]]
+// LLVM: [[CASE3]]:
+// LLVM: br label %[[CASE3_CONT:.*]]
+// LLVM: [[CASE3_CONT]]:
+// LLVM: br label %[[CASE4]]
+// LLVM: [[CASE4]]:
+// LLVM: br label %[[CASE4_CONT:.*]]
+// LLVM: [[CASE4_CONT]]:
+// LLVM: br label %[[CASE5]]
+// LLVM: [[CASE5]]:
+// LLVM: br label %[[EXIT]]
+// LLVM: [[EXIT]]:
+// LLVM: br label %[[RET:.*]]
+// LLVM: [[RET]]:
+// LLVM: ret void
+
// OGCG: define dso_local void @_Z3sw7i
// OGCG: entry:
// OGCG: %[[A_ADDR:.*]] = alloca i32, align 4
@@ -327,6 +510,23 @@ void sw8(int a) {
// CIR-NEXT: cir.break
// CIR-NEXT: }
+// LLVM: define void @_Z3sw8i
+// LLVM: switch i32 %[[COND:.*]], label %[[DEFAULT:.*]] [
+// LLVM-DAG: i32 3, label %[[CASE3:.*]]
+// LLVM-DAG: i32 4, label %[[CASE4:.*]]
+// LLVM: ]
+// LLVM: [[CASE3]]:
+// LLVM: br label %[[EXIT:.*]]
+// LLVM: [[CASE4]]:
+// LLVM: br label %[[CASE4_CONT:.*]]
+// LLVM: [[CASE4_CONT]]:
+// LLVM: br label %[[DEFAULT]]
+// LLVM: [[DEFAULT]]:
+// LLVM: br label %[[EXIT:.*]]
+// LLVM: [[EXIT]]:
+// LLVM: br label %[[RET:.*]]
+// LLVM: [[RET]]:
+// LLVM: ret void
// OGCG: define dso_local void @_Z3sw8i
// OGCG: entry:
@@ -368,6 +568,24 @@ void sw9(int a) {
// CIR-NEXT: cir.break
// CIR-NEXT: }
+// LLVM: define void @_Z3sw9i
+// LLVM: switch i32 %[[COND:.*]], label %[[DEFAULT:.*]] [
+// LLVM-DAG: i32 3, label %[[CASE3:.*]]
+// LLVM-DAG: i32 4, label %[[CASE4:.*]]
+// LLVM: ]
+// LLVM: [[CASE3]]:
+// LLVM: br label %[[EXIT:.*]]
+// LLVM: [[DEFAULT]]:
+// LLVM: br label %[[DEFAULT_CONT:.*]]
+// LLVM: [[DEFAULT_CONT]]:
+// LLVM: br label %[[CASE4]]
+// LLVM: [[CASE4]]:
+// LLVM: br label %[[EXIT:.*]]
+// LLVM: [[EXIT]]:
+// LLVM: br label %[[RET:.*]]
+// LLVM: [[RET]]:
+// LLVM: ret void
+
// OGCG: define dso_local void @_Z3sw9i
// OGCG: entry:
// OGCG: %[[A_ADDR:.*]] = alloca i32, align 4
@@ -412,6 +630,29 @@ void sw10(int a) {
// CIR-NEXT: cir.break
// CIR-NEXT: }
+// LLVM: define void @_Z4sw10i
+// LLVM: switch i32 %[[COND:.*]], label %[[DEFAULT:.*]] [
+// LLVM-DAG: i32 3, label %[[CASE_3:.*]]
+// LLVM-DAG: i32 4, label %[[CASE_4:.*]]
+// LLVM-DAG: i32 5, label %[[CASE_5:.*]]
+// LLVM: ]
+// LLVM: [[CASE_3]]:
+// LLVM: br label %[[EXIT:.*]]
+// LLVM: [[CASE_4]]:
+// LLVM: br label %[[CASE4_CONT:.*]]
+// LLVM: [[CASE4_CONT]]:
+// LLVM: br label %[[DEFAULT]]
+// LLVM: [[DEFAULT]]:
+// LLVM: br label %[[DEFAULT_CONT:.*]]
+// LLVM: [[DEFAULT_CONT]]:
+// LLVM: br label %[[CASE_5]]
+// LLVM: [[CASE_5]]:
+// LLVM: br label %[[EXIT]]
+// LLVM: [[EXIT]]:
+// LLVM: br label %[[RET:.*]]
+// LLVM: [[RET]]:
+// LLVM: ret void
+
// OGCG: define dso_local void @_Z4sw10i
// OGCG: entry:
// OGCG: %[[A_ADDR:.*]] = alloca i32, align 4
@@ -467,6 +708,39 @@ void sw11(int a) {
// CIR-NEXT: cir.break
// CIR-NEXT: }
+// LLVM: define void @_Z4sw11i
+// LLVM: switch i32 %[[COND:.*]], label %[[DEFAULT:.*]] [
+// LLVM-DAG: i32 3, label %[[CASE_3:.*]]
+// LLVM-DAG: i32 4, label %[[CASE_4:.*]]
+// LLVM-DAG: i32 5, label %[[CASE_5:.*]]
+// LLVM-DAG: i32 6, label %[[CASE_6:.*]]
+// LLVM-DAG: i32 7, label %[[CASE_7:.*]]
+// LLVM: ]
+// LLVM: [[CASE_3]]:
+// LLVM: br label %[[EXIT:.*]]
+// LLVM: [[CASE_4]]:
+// LLVM: br label %[[CASE4_CONT:.*]]
+// LLVM: [[CASE4_CONT]]:
+// LLVM: br label %[[CASE_5]]
+// LLVM: [[CASE_5]]:
+// LLVM: br label %[[CASE5_CONT:.*]]
+// LLVM: [[CASE5_CONT]]:
+// LLVM: br label %[[DEFAULT]]
+// LLVM: [[DEFAULT]]:
+// LLVM: br label %[[DEFAULT_CONT:.*]]
+// LLVM: [[DEFAULT_CONT]]:
+// LLVM: br label %[[CASE_6]]
+// LLVM: [[CASE_6]]:
+// LLVM: br label %[[CASE6_CONT:.*]]
+// LLVM: [[CASE6_CONT]]:
+// LLVM: br label %[[CASE_7]]
+// LLVM: [[CASE_7]]:
+// LLVM: br label %[[EXIT]]
+// LLVM: [[EXIT]]:
+// LLVM: br label %[[RET:.*]]
+// LLVM: [[RET]]:
+// LLVM: ret void
+
// OGCG: define dso_local void @_Z4sw11i
// OGCG: entry:
// OGCG: %[[A_ADDR:.*]] = alloca i32, align 4
@@ -507,6 +781,19 @@ void sw12(int a) {
// CIR-NEXT: cir.break
// CIR-NEXT: }
+// LLVM: define void @_Z4sw12i
+// LLVM: switch i32 %[[COND:.*]], label %[[EXIT:.*]] [
+// LLVM-DAG: i32 3, label %[[CASE_3:.*]]
+// LLVM: ]
+// LLVM: [[CASE_3]]:
+// LLVM: ret void
+// LLVM: [[UNREACHABLE:.*]]:
+// LLVM: br label %[[EXIT:.*]]
+// LLVM: [[EXIT]]:
+// LLVM: br label %[[RET:.*]]
+// LLVM: [[RET]]:
+// LLVM: ret void
+
// OGCG: define dso_local void @_Z4sw12i
// OGCG: entry:
// OGCG: %[[A_ADDR:.*]] = alloca i32, align 4
@@ -545,6 +832,32 @@ void sw13(int a, int b) {
// CIR: }
// CIR: cir.return
+// LLVM: define void @_Z4sw13ii
+// LLVM: switch i32 %[[COND:.*]], label %[[OUTER_EXIT:.*]] [
+// LLVM-DAG: i32 1, label %[[CASE_A_1:.*]]
+// LLVM: ]
+// LLVM: [[CASE_A_1]]:
+// LLVM: br label %[[LOAD_B:.*]]
+// LLVM: [[LOAD_B]]:
+// LLVM: %[[B_VAL:.*]] = load i32, ptr %[[B_ADDR:.*]], align 4
+// LLVM: br label %[[INNER_SWITCH:.*]]
+// LLVM: [[INNER_SWITCH]]:
+// LLVM: switch i32 %[[B_VAL]], label %[[INNER_EXIT:.*]] [
+// LLVM-DAG: i32 2, label %[[CASE_B_2:.*]]
+// LLVM: ]
+// LLVM: [[CASE_B_2]]:
+// LLVM: br label %[[INNER_EXIT]]
+// LLVM: [[INNER_EXIT]]:
+// LLVM: br label %[[INNER_EXIT_CONT:.*]]
+// LLVM: [[INNER_EXIT_CONT]]:
+// LLVM: br label %[[MERGE:.*]]
+// LLVM: [[MERGE]]:
+// LLVM: br label %[[OUTER_EXIT]]
+// LLVM: [[OUTER_EXIT]]:
+// LLVM: br label %[[EXIT:.*]]
+// LLVM: [[EXIT]]:
+// LLVM: ret void
+
// OGCG: define dso_local void @_Z4sw13ii
// OGCG: entry:
// OGCG: %[[A_ADDR:.*]] = alloca i32, align 4
@@ -595,12 +908,42 @@ void sw14(int x) {
// CIR-NEXT: cir.break
// CIR-NEXT: }
+// LLVM: define void @_Z4sw14i
+// LLVM: switch i32 %[[COND:.*]], label %[[DEFAULT:.*]] [
+// LLVM-DAG: i32 1, label %[[CASE1:.*]]
+// LLVM-DAG: i32 2, label %[[CASE2:.*]]
+// LLVM-DAG: i32 3, label %[[CASE3_TO_6:.*]]
+// LLVM-DAG: i32 4, label %[[CASE3_TO_6]]
+// LLVM-DAG: i32 5, label %[[CASE3_TO_6]]
+// LLVM-DAG: i32 6, label %[[CASE3_TO_6]]
+// LLVM-DAG: i32 7, label %[[CASE7:.*]]
+// LLVM: ]
+// LLVM: [[CASE1]]:
+// LLVM: br label %[[AFTER1:.*]]
+// LLVM: [[AFTER1]]:
+// LLVM: br label %[[CASE2]]
+// LLVM: [[CASE2]]:
+// LLVM: br label %[[AFTER2:.*]]
+// LLVM: [[AFTER2]]:
+// LLVM: br label %[[CASE3_TO_6]]
+// LLVM: [[CASE3_TO_6]]:
+// LLVM: br label %[[AFTER3_6:.*]]
+// LLVM: [[AFTER3_6]]:
+// LLVM: br label %[[CASE7]]
+// LLVM: [[CASE7]]:
+// LLVM: br label %[[EXIT1:.*]]
+// LLVM: [[DEFAULT]]:
+// LLVM: br label %[[EXIT1]]
+// LLVM: [[EXIT1]]:
+// LLVM: br label %[[RET:.*]]
+// LLVM: [[RET]]:
+// LLVM: ret void
+
// OGCG: define dso_local void @_Z4sw14i
// OGCG: entry:
// OGCG: %[[X_ADDR:.*]] = alloca i32, align 4
// OGCG: store i32 %x, ptr %[[X_ADDR]], align 4
// OGCG: %[[X_VAL:.*]] = load i32, ptr %[[X_ADDR]], align 4
-
// OGCG: switch i32 %[[X_VAL]], label %[[DEFAULT:.*]] [
// OGCG-DAG: i32 1, label %[[BB1:.*]]
// OGCG-DAG: i32 2, label %[[BB1]]
@@ -652,6 +995,30 @@ void sw15(int x) {
// CIR-NEXT: cir.break
// CIR-NEXT: }
+// LLVM: define void @_Z4sw15i
+// LLVM: switch i32 %[[COND:.*]], label %[[DEFAULT:.*]] [
+// LLVM-DAG: i32 1, label %[[CASE1:.*]]
+// LLVM-DAG: i32 2, label %[[CASE2:.*]]
+// LLVM-DAG: i32 3, label %[[CASE3:.*]]
+// LLVM: ]
+// LLVM: [[CASE1]]:
+// LLVM: br label %[[CASE1_CONT:.*]]
+// LLVM: [[CASE1_CONT]]:
+// LLVM: br label %[[CASE2]]
+// LLVM: [[CASE2]]:
+// LLVM: store i32 0, ptr %[[Y_ADDR:.*]], align 4
+// LLVM: br label %[[CASE2_CONT:.*]]
+// LLVM: [[CASE2_CONT]]:
+// LLVM: br label %[[CASE3]]
+// LLVM: [[CASE3]]:
+// LLVM: br label %[[EXIT:.*]]
+// LLVM: [[DEFAULT]]:
+// LLVM: br label %[[EXIT]]
+// LLVM: [[EXIT]]:
+// LLVM: br label %[[RET:.*]]
+// LLVM: [[RET]]:
+// LLVM: ret void
+
// OGCG: define dso_local void @_Z4sw15i
// OGCG: entry:
// OGCG: %[[X_ADDR:.*]] = alloca i32, align 4
@@ -714,6 +1081,61 @@ int nested_switch(int a) {
// CIR: cir.case(equal, [#cir.int<7> : !s32i]) {
// CIR: cir.return
+// LLVM: define i32 @_Z13nested_switchi
+// LLVM: %[[B_ADDR:.*]] = alloca i32, i64 1, align 4
+// LLVM: %[[A_ADDR:.*]] = alloca i32, i64 1, align 4
+// LLVM: %[[RES_ADDR:.*]] = alloca i32, i64 1, align 4
+// LLVM: store i32 %[[ARG:.*]], ptr %[[A_ADDR]], align 4
+// LLVM: br label %[[ENTRY:.*]]
+// LLVM: [[ENTRY]]:
+// LLVM: store i32 1, ptr %[[B_ADDR]], align 4
+// LLVM: %[[A_VAL:.*]] = load i32, ptr %[[A_ADDR]], align 4
+// LLVM: br label %[[SWITCH:.*]]
+// LLVM: [[SWITCH]]:
+// LLVM: switch i32 %[[A_VAL]], label %[[EXIT:.*]] [
+// LLVM-DAG: i32 0, label %[[CASE0:.*]]
+// LLVM-DAG: i32 1, label %[[CASE1:.*]]
+// LLVM-DAG: i32 2, label %[[CASE2:.*]]
+// LLVM-DAG: i32 9, label %[[CASE9:.*]]
+// LLVM-DAG: i32 7, label %[[CASE7:.*]]
+// LLVM: ]
+// LLVM: [[CASE0]]:
+// LLVM: %[[B0:.*]] = load i32, ptr %[[B_ADDR]], align 4
+// LLVM: %[[B1:.*]] = add nsw i32 %[[B0]], 1
+// LLVM: store i32 %[[B1]], ptr %[[B_ADDR]], align 4
+// LLVM: br label %[[CASE0_CONT:.*]]
+// LLVM: [[CASE0_CONT]]:
+// LLVM: br label %[[CASE1]]
+// LLVM: [[CASE1]]:
+// LLVM: %[[B1a:.*]] = load i32, ptr %[[B_ADDR]], align 4
+// LLVM: store i32 %[[B1a]], ptr %[[RES_ADDR]], align 4
+// LLVM: %[[RET1:.*]] = load i32, ptr %[[RES_ADDR]], align 4
+// LLVM: ret i32 %[[RET1]]
+// LLVM: [[CASE2]]:
+// LLVM: br label %[[CASE2_BODY:.*]]
+// LLVM: [[CASE2_BODY]]:
+// LLVM: %[[B2:.*]] = load i32, ptr %[[B_ADDR]], align 4
+// LLVM: %[[B3:.*]] = add nsw i32 %[[B2]], 1
+// LLVM: store i32 %[[B3]], ptr %[[B_ADDR]], align 4
+// LLVM: br label %[[CASE2...
[truncated]
|
andykaylor
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. Just a few nits.
| mlir::ConversionPatternRewriter &rewriter) const { | ||
|
|
||
| llvm::SmallVector<mlir::APInt, 8> caseValues; | ||
| if (op.getCaseValues()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this if necessary? I think it there are no case values we just won't enter the for loop below.
| llvm::SmallVector<mlir::APInt, 8> caseValues; | ||
| if (op.getCaseValues()) { | ||
| for (mlir::Attribute val : op.getCaseValues()) { | ||
| auto intAttr = dyn_cast<cir::IntAttr>(val); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| auto intAttr = dyn_cast<cir::IntAttr>(val); | |
| auto intAttr = cast<cir::IntAttr>(val); |
Make this assert.
| llvm::SmallVector<mlir::Block *, 8> caseDestinations; | ||
| llvm::SmallVector<mlir::ValueRange, 8> caseOperands; | ||
|
|
||
| for (mlir::Block *x : op.getCaseDestinations()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't need braces for loops with single-line bodies.
| caseDestinations.push_back(x); | ||
| } | ||
|
|
||
| for (mlir::OperandRange x : op.getCaseOperands()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No braces
bcardosolopes
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM after you address Andy's nits.
andykaylor
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
This PR adds support for lowering the
cir.switchoperation to LLVM. It includes tests for lowering from.ciras well as end-to-end source code tests.