From 65c0a93631b06256ecf4668648f46975cd8559eb Mon Sep 17 00:00:00 2001 From: Robert Konicar Date: Tue, 3 Sep 2024 16:20:53 +0200 Subject: [PATCH 01/11] hl: Create a base tablegen class for conditional operator-like ops. --- include/vast/Dialect/HighLevel/HighLevelCF.td | 18 ++++++++++++++---- lib/vast/Dialect/HighLevel/HighLevelOps.cpp | 12 ------------ 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/include/vast/Dialect/HighLevel/HighLevelCF.td b/include/vast/Dialect/HighLevel/HighLevelCF.td index 9f3bb54065..3e2995ac3d 100644 --- a/include/vast/Dialect/HighLevel/HighLevelCF.td +++ b/include/vast/Dialect/HighLevel/HighLevelCF.td @@ -130,11 +130,11 @@ def HighLevel_IfOp let hasCustomAssemblyFormat = 1; } -def HighLevel_CondOp - : HighLevel_ControlFlowOp< "cond" > +class HighLevel_CondOpBase< string mnemonic, list< Trait > traits = [] > + + : HighLevel_ControlFlowOp< mnemonic, traits > , Results<(outs AnyType:$result)> { - let summary = "VAST conditional statement"; let description = [{ The operation takes builders of three regions -- condition, true branch and false branch. Builders, given the location, build a particular region. @@ -166,12 +166,22 @@ def HighLevel_CondOp "builder_callback_ref":$condBuilder, "builder_callback_ref":$thenBuilder, "builder_callback_ref":$elseBuilder - )> + ), [{ + InsertionGuard guard($_builder); + build_region($_builder, $_state, condBuilder); + build_region($_builder, $_state, thenBuilder); + build_region($_builder, $_state, elseBuilder); + $_state.addTypes(type); + }] > ]; let assemblyFormat = [{ attr-dict `:` type(results) $condRegion `?` $thenRegion `:` $elseRegion }]; } +def HighLevel_CondOp : HighLevel_CondOpBase< "cond" > { + let summary = "VAST conditional statement"; +} + def HighLevel_BinaryCondOp : HighLevel_Op< "binary_cond", diff --git a/lib/vast/Dialect/HighLevel/HighLevelOps.cpp b/lib/vast/Dialect/HighLevel/HighLevelOps.cpp index 6dfbaf48b4..9223c34180 100644 --- a/lib/vast/Dialect/HighLevel/HighLevelOps.cpp +++ b/lib/vast/Dialect/HighLevel/HighLevelOps.cpp @@ -569,18 +569,6 @@ namespace vast::hl build_region(bld, st, else_builder); } - void CondOp::build( - Builder &bld, State &st, Type type, - builder_callback_ref cond, - builder_callback_ref then_builder, - builder_callback_ref else_builder - ) { - InsertionGuard guard(bld); - build_region(bld, st, cond); - build_region(bld, st, then_builder); - build_region(bld, st, else_builder); - st.addTypes(type); - } void BinaryCondOp::build( Builder &bld, State &st, Type type, builder_callback_ref common_builder, From 389c0fba8178dd64432214ad9f5fca320e910cdb Mon Sep 17 00:00:00 2001 From: Robert Konicar Date: Tue, 3 Sep 2024 16:21:26 +0200 Subject: [PATCH 02/11] hl: Add ChooseExprOp. --- include/vast/Dialect/HighLevel/HighLevelCF.td | 7 ++++++- lib/vast/Dialect/HighLevel/HighLevelOps.cpp | 5 +++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/include/vast/Dialect/HighLevel/HighLevelCF.td b/include/vast/Dialect/HighLevel/HighLevelCF.td index 3e2995ac3d..38b8e080ed 100644 --- a/include/vast/Dialect/HighLevel/HighLevelCF.td +++ b/include/vast/Dialect/HighLevel/HighLevelCF.td @@ -20,7 +20,7 @@ class HighLevel_ControlFlowOp< string mnemonic, list< Trait > traits = [] > def HighLevel_CondYieldOp : HighLevel_Op< "cond.yield", [ // TODO(Heno): add ReturnLike trait - Terminator, ParentOneOf<["IfOp", "WhileOp", "ForOp", "DoOp", "CondOp", "BinaryCondOp"]> + Terminator, ParentOneOf<["IfOp", "WhileOp", "ForOp", "DoOp", "CondOp", "ChooseExprOp", "BinaryCondOp"]> ] > { let summary = "condition yield operation"; @@ -182,6 +182,11 @@ def HighLevel_CondOp : HighLevel_CondOpBase< "cond" > { let summary = "VAST conditional statement"; } +// TODO: Add missing methods from clang API +def HighLevel_ChooseExprOp : HighLevel_CondOpBase< "choose_expr" > { + let summary = "Representation of GNU __builtin_choose_expr"; +} + def HighLevel_BinaryCondOp : HighLevel_Op< "binary_cond", diff --git a/lib/vast/Dialect/HighLevel/HighLevelOps.cpp b/lib/vast/Dialect/HighLevel/HighLevelOps.cpp index 9223c34180..360e7c1849 100644 --- a/lib/vast/Dialect/HighLevel/HighLevelOps.cpp +++ b/lib/vast/Dialect/HighLevel/HighLevelOps.cpp @@ -621,6 +621,10 @@ namespace vast::hl return verify_condop_yields(getThenRegion(), getElseRegion(), getLoc()); } + logical_result ChooseExprOp::verifyRegions() { + return verify_condop_yields(getThenRegion(), getElseRegion(), getLoc()); + } + logical_result BinaryCondOp::verifyRegions() { return verify_condop_yields(getThenRegion(), getElseRegion(), getLoc()); } @@ -815,6 +819,7 @@ namespace vast::hl GRAPH_REGION_OP(LabelStmt); GRAPH_REGION_OP(BreakOp); GRAPH_REGION_OP(CondOp); + GRAPH_REGION_OP(ChooseExprOp); GRAPH_REGION_OP(BinaryCondOp); GRAPH_REGION_OP(ContinueOp); From 5127e68653d4a31c3f77a55a785bc203cba3834f Mon Sep 17 00:00:00 2001 From: Robert Konicar Date: Tue, 3 Sep 2024 16:21:42 +0200 Subject: [PATCH 03/11] cg: Add ChooseExpr visitor. --- include/vast/CodeGen/DefaultStmtVisitor.hpp | 1 + lib/vast/CodeGen/DefaultStmtVisitor.cpp | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/include/vast/CodeGen/DefaultStmtVisitor.hpp b/include/vast/CodeGen/DefaultStmtVisitor.hpp index fc57b4411f..24f635d1a1 100644 --- a/include/vast/CodeGen/DefaultStmtVisitor.hpp +++ b/include/vast/CodeGen/DefaultStmtVisitor.hpp @@ -196,6 +196,7 @@ namespace vast::cg { operation VisitMemberExpr(const clang::MemberExpr *expr); operation VisitConditionalOperator(const clang::ConditionalOperator *op); + operation VisitChooseExpr(const clang::ChooseExpr *expr); operation VisitBinaryConditionalOperator(const clang::BinaryConditionalOperator *op); operation VisitAddrLabelExpr(const clang::AddrLabelExpr *expr); operation VisitConstantExpr(const clang::ConstantExpr *expr); diff --git a/lib/vast/CodeGen/DefaultStmtVisitor.cpp b/lib/vast/CodeGen/DefaultStmtVisitor.cpp index 9b937d7783..e6db5ce21b 100644 --- a/lib/vast/CodeGen/DefaultStmtVisitor.cpp +++ b/lib/vast/CodeGen/DefaultStmtVisitor.cpp @@ -850,6 +850,16 @@ namespace vast::cg .freeze(); } + operation default_stmt_visitor::VisitChooseExpr(const clang::ChooseExpr *expr) { + return bld.compose< hl::ChooseExprOp >() + .bind(self.location(expr)) + .bind(self.visit(expr->getType())) + .bind_always(mk_cond_builder(expr->getCond())) + .bind_always(mk_value_builder(expr->getLHS())) + .bind_always(mk_value_builder(expr->getRHS())) + .freeze(); + } + operation default_stmt_visitor::VisitBinaryConditionalOperator(const clang::BinaryConditionalOperator *op) { auto common_type = self.visit(op->getCommon()->getType()); return bld.compose< hl::BinaryCondOp >() From 20d4a2b5bf807d781f3516b0b0d01b0016d61b30 Mon Sep 17 00:00:00 2001 From: Robert Konicar Date: Tue, 3 Sep 2024 16:32:18 +0200 Subject: [PATCH 04/11] cg: Visit ChooseExpr result type correctly. --- lib/vast/CodeGen/DefaultStmtVisitor.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/vast/CodeGen/DefaultStmtVisitor.cpp b/lib/vast/CodeGen/DefaultStmtVisitor.cpp index e6db5ce21b..5628f963a3 100644 --- a/lib/vast/CodeGen/DefaultStmtVisitor.cpp +++ b/lib/vast/CodeGen/DefaultStmtVisitor.cpp @@ -853,7 +853,8 @@ namespace vast::cg operation default_stmt_visitor::VisitChooseExpr(const clang::ChooseExpr *expr) { return bld.compose< hl::ChooseExprOp >() .bind(self.location(expr)) - .bind(self.visit(expr->getType())) + // ChooseExpr conserves everything including lvalue-ness + .bind(visit_maybe_lvalue_result_type(expr)) .bind_always(mk_cond_builder(expr->getCond())) .bind_always(mk_value_builder(expr->getLHS())) .bind_always(mk_value_builder(expr->getRHS())) From 6a5553c62b627f243fd6ea892a6347c47ecb3053 Mon Sep 17 00:00:00 2001 From: Robert Konicar Date: Tue, 3 Sep 2024 16:32:32 +0200 Subject: [PATCH 05/11] test: Add test for choose expr. --- test/vast/Dialect/HighLevel/choose-expr-a.c | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 test/vast/Dialect/HighLevel/choose-expr-a.c diff --git a/test/vast/Dialect/HighLevel/choose-expr-a.c b/test/vast/Dialect/HighLevel/choose-expr-a.c new file mode 100644 index 0000000000..b384d930b2 --- /dev/null +++ b/test/vast/Dialect/HighLevel/choose-expr-a.c @@ -0,0 +1,11 @@ +// RUN: %vast-cc1 -vast-emit-mlir=hl %s -o - | %file-check %s +// RUN: %vast-cc1 -vast-emit-mlir=hl %s -o %t && %vast-opt %t | diff -B %t - + +void fn() { + int x, y; + // CHECK: hl.choose_expr : !hl.lvalue { + // CHECK: hl.cond.yield {{%.*}} : !hl.int + // CHECK: hl.value.yield {{%.*}} : !hl.lvalue + // CHECK: hl.value.yield {{%.*}} : !hl.lvalue + int z = __builtin_choose_expr(0, x, y); +} From d1f099c144e5775fc78ecee0e72b1dcbcef36134 Mon Sep 17 00:00:00 2001 From: Robert Konicar Date: Wed, 4 Sep 2024 11:11:12 +0200 Subject: [PATCH 06/11] hl: Add information about condition result to choose expr. --- include/vast/Dialect/HighLevel/HighLevelCF.td | 43 ++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/include/vast/Dialect/HighLevel/HighLevelCF.td b/include/vast/Dialect/HighLevel/HighLevelCF.td index 38b8e080ed..e7869921c8 100644 --- a/include/vast/Dialect/HighLevel/HighLevelCF.td +++ b/include/vast/Dialect/HighLevel/HighLevelCF.td @@ -182,9 +182,50 @@ def HighLevel_CondOp : HighLevel_CondOpBase< "cond" > { let summary = "VAST conditional statement"; } -// TODO: Add missing methods from clang API def HighLevel_ChooseExprOp : HighLevel_CondOpBase< "choose_expr" > { let summary = "Representation of GNU __builtin_choose_expr"; + + let arguments = (ins OptionalAttr< BoolAttr >:$condTrue); + + let skipDefaultBuilders = 1; + let builders = [ + OpBuilder<(ins + "Type":$type, + "builder_callback_ref":$condBuilder, + "builder_callback_ref":$thenBuilder, + "builder_callback_ref":$elseBuilder, + CArg<"std::optional< bool >", "std::nullopt">:$condTrue + ), [{ + InsertionGuard guard($_builder); + build_region($_builder, $_state, condBuilder); + build_region($_builder, $_state, thenBuilder); + build_region($_builder, $_state, elseBuilder); + if (condTrue) { + $_state.addAttribute("condTrue", $_builder.getBoolAttr(condTrue.value())); + } + $_state.addTypes(type); + }] > + ]; + + let extraClassDeclaration = [{ + std::optional< bool > isConditionTrue() { + if (auto cond = getCondTrue()) { + return cond.value(); + } + return {}; + } + + bool isConditionDependent() { return (bool) getCondTrueAttr(); } + + region_ptr getChosenSubExpr() { + if (auto cond = isConditionTrue()) { + return cond.value() ? &getThenRegion() : &getElseRegion(); + } + return {}; + } + }]; + + let assemblyFormat = [{ attr-dict (`cond` $condTrue^)? `:` type(results) $condRegion `?` $thenRegion `:` $elseRegion }]; } def HighLevel_BinaryCondOp From 89a8f9bbaaf9a71a957b78e723f9d5a8ed822987 Mon Sep 17 00:00:00 2001 From: Robert Konicar Date: Wed, 4 Sep 2024 11:11:27 +0200 Subject: [PATCH 07/11] cg: Update ChooseExpr visitor. --- lib/vast/CodeGen/DefaultStmtVisitor.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/vast/CodeGen/DefaultStmtVisitor.cpp b/lib/vast/CodeGen/DefaultStmtVisitor.cpp index 5628f963a3..7094e531ff 100644 --- a/lib/vast/CodeGen/DefaultStmtVisitor.cpp +++ b/lib/vast/CodeGen/DefaultStmtVisitor.cpp @@ -858,6 +858,7 @@ namespace vast::cg .bind_always(mk_cond_builder(expr->getCond())) .bind_always(mk_value_builder(expr->getLHS())) .bind_always(mk_value_builder(expr->getRHS())) + .bind_always(expr->isConditionDependent() ? std::nullopt : std::optional(expr->isConditionTrue())) .freeze(); } From 422110979653d4dd0f752aa35367145c92c9ab8b Mon Sep 17 00:00:00 2001 From: Robert Konicar Date: Wed, 4 Sep 2024 11:15:30 +0200 Subject: [PATCH 08/11] test: Update test for choose expr. --- test/vast/Dialect/HighLevel/choose-expr-a.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/vast/Dialect/HighLevel/choose-expr-a.c b/test/vast/Dialect/HighLevel/choose-expr-a.c index b384d930b2..15536b9d3d 100644 --- a/test/vast/Dialect/HighLevel/choose-expr-a.c +++ b/test/vast/Dialect/HighLevel/choose-expr-a.c @@ -3,9 +3,11 @@ void fn() { int x, y; - // CHECK: hl.choose_expr : !hl.lvalue { + // CHECK: hl.choose_expr cond false : !hl.lvalue { // CHECK: hl.cond.yield {{%.*}} : !hl.int // CHECK: hl.value.yield {{%.*}} : !hl.lvalue // CHECK: hl.value.yield {{%.*}} : !hl.lvalue int z = __builtin_choose_expr(0, x, y); + // CHECK: hl.choose_expr cond true : !hl.lvalue { + int w = __builtin_choose_expr(1, x, y); } From d131658cb2ae640e1ffa7a1450b6b09641ec9562 Mon Sep 17 00:00:00 2001 From: Robert Konicar Date: Wed, 4 Sep 2024 11:30:24 +0200 Subject: [PATCH 09/11] hl: Remove ChooseExpr region type verifier. --- include/vast/Dialect/HighLevel/HighLevelCF.td | 4 ++++ lib/vast/Dialect/HighLevel/HighLevelOps.cpp | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/vast/Dialect/HighLevel/HighLevelCF.td b/include/vast/Dialect/HighLevel/HighLevelCF.td index e7869921c8..bde62ac1aa 100644 --- a/include/vast/Dialect/HighLevel/HighLevelCF.td +++ b/include/vast/Dialect/HighLevel/HighLevelCF.td @@ -187,6 +187,10 @@ def HighLevel_ChooseExprOp : HighLevel_CondOpBase< "choose_expr" > { let arguments = (ins OptionalAttr< BoolAttr >:$condTrue); + // ChooseExpr can have different types. + // Often used as __builtin_choose_expr(static_cond, 1, (void)0) + let hasRegionVerifier = 0; + let skipDefaultBuilders = 1; let builders = [ OpBuilder<(ins diff --git a/lib/vast/Dialect/HighLevel/HighLevelOps.cpp b/lib/vast/Dialect/HighLevel/HighLevelOps.cpp index 360e7c1849..29249df4f1 100644 --- a/lib/vast/Dialect/HighLevel/HighLevelOps.cpp +++ b/lib/vast/Dialect/HighLevel/HighLevelOps.cpp @@ -621,10 +621,6 @@ namespace vast::hl return verify_condop_yields(getThenRegion(), getElseRegion(), getLoc()); } - logical_result ChooseExprOp::verifyRegions() { - return verify_condop_yields(getThenRegion(), getElseRegion(), getLoc()); - } - logical_result BinaryCondOp::verifyRegions() { return verify_condop_yields(getThenRegion(), getElseRegion(), getLoc()); } From d062327dbd9167ed2acff2efbe59a4a40bc29a12 Mon Sep 17 00:00:00 2001 From: Robert Konicar Date: Wed, 4 Sep 2024 11:35:33 +0200 Subject: [PATCH 10/11] test: Expand choose expr test. --- test/vast/Dialect/HighLevel/choose-expr-a.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/test/vast/Dialect/HighLevel/choose-expr-a.c b/test/vast/Dialect/HighLevel/choose-expr-a.c index 15536b9d3d..0f3c36ebe3 100644 --- a/test/vast/Dialect/HighLevel/choose-expr-a.c +++ b/test/vast/Dialect/HighLevel/choose-expr-a.c @@ -9,5 +9,19 @@ void fn() { // CHECK: hl.value.yield {{%.*}} : !hl.lvalue int z = __builtin_choose_expr(0, x, y); // CHECK: hl.choose_expr cond true : !hl.lvalue { - int w = __builtin_choose_expr(1, x, y); + z = __builtin_choose_expr(1, x, y); + + // CHECK: hl.choose_expr cond true : !hl.lvalue { + // CHECK: hl.value.yield {{%.*}} : !hl.lvalue + // CHECK: hl.value.yield {{%.*}} : !hl.void + z = __builtin_choose_expr(1, x, (void) 0); + // CHECK: hl.choose_expr cond false : !hl.lvalue { + // CHECK: hl.value.yield {{%.*}} : !hl.void + // CHECK: hl.value.yield {{%.*}} : !hl.lvalue + z = __builtin_choose_expr(0, (void) 0, x); + + // CHECK: hl.choose_expr cond true : !hl.lvalue { + // CHECK: hl.value.yield {{%.*}} : !hl.lvalue + // CHECK: hl.value.yield {{%.*}} : !hl.char + z = __builtin_choose_expr(1, x, (char) 0); } From dcd99107582010301f0353a6cbf26ff76aacec58 Mon Sep 17 00:00:00 2001 From: Robert Konicar Date: Wed, 4 Sep 2024 15:55:20 +0200 Subject: [PATCH 11/11] hl: Don't use condop base for ChooseExpr. --- include/vast/Dialect/HighLevel/HighLevelCF.td | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/include/vast/Dialect/HighLevel/HighLevelCF.td b/include/vast/Dialect/HighLevel/HighLevelCF.td index bde62ac1aa..8b79c65131 100644 --- a/include/vast/Dialect/HighLevel/HighLevelCF.td +++ b/include/vast/Dialect/HighLevel/HighLevelCF.td @@ -182,14 +182,33 @@ def HighLevel_CondOp : HighLevel_CondOpBase< "cond" > { let summary = "VAST conditional statement"; } -def HighLevel_ChooseExprOp : HighLevel_CondOpBase< "choose_expr" > { +def HighLevel_ChooseExprOp : HighLevel_ControlFlowOp< "choose_expr" > + , Arguments<(ins OptionalAttr< BoolAttr >:$condTrue)> + , Results<(outs AnyType:$result)> +{ let summary = "Representation of GNU __builtin_choose_expr"; - let arguments = (ins OptionalAttr< BoolAttr >:$condTrue); + let description = [{ + The operation takes builders of three regions -- condition, true branch and false branch. + Builders, given the location, build a particular region. + + The generic form of the operation is as follows: + + hl.cond { + ... /* condition region */ + hl.cond.yield %cond : !hl.bool + } ? { + ... /* true region */ + } : { + ... /* false region */ + } + }]; - // ChooseExpr can have different types. - // Often used as __builtin_choose_expr(static_cond, 1, (void)0) - let hasRegionVerifier = 0; + let regions = (region + Core_CondRegion:$condRegion, + Core_ValueRegion:$thenRegion, + Core_ValueRegion:$elseRegion + ); let skipDefaultBuilders = 1; let builders = [