llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clangir @llvm/pr-subscribers-clang Author: aokblast <details> <summary>Changes</summary> Switch.flat should minic llvm.switch as they are both CFG formed. Implement the same mechanism as what we have in llvm.switch and add ArrayRef<Attribute> override when we actually know the operands. Assisted-by: Claude # Tests --- Full diff: https://github.com/llvm/llvm-project/pull/230340.diff 4 Files Affected: - (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+1) - (modified) clang/lib/CIR/Dialect/IR/CIRDialect.cpp (+20) - (modified) clang/test/CIR/IR/switch-flat.cir (+4-4) - (added) clang/test/CIR/Transforms/switch-flat-sccp.cir (+70) ``````````diff diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index de805d4c642a27..259ab7fab9f0d8 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -1824,6 +1824,7 @@ def CIR_IsConstantOp : CIR_Op<"is_constant", [Pure]> { //===----------------------------------------------------------------------===// def CIR_SwitchFlatOp : CIR_Op<"switch.flat", [ + DeclareOpInterfaceMethods<BranchOpInterface, ["getSuccessorForOperands"]>, AttrSizedOperandSegments, Terminator ]> { let summary = "A flattened version of cir.switch"; diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index d5a587ff6d81ed..30c25e5b9f77ed 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -2237,6 +2237,26 @@ void cir::SwitchFlatOp::build(OpBuilder &builder, OperationState &result, defaultDestination, caseDestinations); } +SuccessorOperands cir::SwitchFlatOp::getSuccessorOperands(unsigned index) { + assert(index < getNumSuccessors() && "invalid successor index"); + if (index == 0) + return SuccessorOperands(getDefaultOperandsMutable()); + return SuccessorOperands(getCaseOperandsMutable()[index - 1]); +} + +Block * +cir::SwitchFlatOp::getSuccessorForOperands(ArrayRef<Attribute> operands) { + auto cond = dyn_cast_if_present<cir::IntAttr>(operands.front()); + if (!cond) + return nullptr; + for (auto [value, dest] : llvm::zip(getCaseValues(), getCaseDestinations())) { + const APInt &caseValue = cast<cir::IntAttr>(value).getValue(); + if (caseValue == cond.getValue()) + return dest; + } + return getDefaultDestination(); +} + /// <cases> ::= `[` (case (`,` case )* )? `]` /// <case> ::= integer `:` bb-id (`(` ssa-use-and-type-list `)`)? static ParseResult parseSwitchFlatOpCases( diff --git a/clang/test/CIR/IR/switch-flat.cir b/clang/test/CIR/IR/switch-flat.cir index d39c3e7e81215d..61a9c91c4cea23 100644 --- a/clang/test/CIR/IR/switch-flat.cir +++ b/clang/test/CIR/IR/switch-flat.cir @@ -46,10 +46,10 @@ cir.func @switchWithOperands(%arg0: !s32i, %arg1: !s32i, %arg2: !s32i) { 0: ^bb1(%arg1, %arg2 : !s32i, !s32i), 1: ^bb2(%arg2, %arg1 : !s32i, !s32i) ] -^bb1: +^bb1(%0: !s32i, %1: !s32i): cir.br ^bb3 -^bb2: +^bb2(%2: !s32i, %3: !s32i): cir.br ^bb3 ^bb3: @@ -60,9 +60,9 @@ cir.func @switchWithOperands(%arg0: !s32i, %arg1: !s32i, %arg2: !s32i) { // CHECK-NEXT: 0: ^bb1(%arg1, %arg2 : !s32i, !s32i), // CHECK-NEXT: 1: ^bb2(%arg2, %arg1 : !s32i, !s32i) // CHECK-NEXT: ] -// CHECK-NEXT: ^bb1: +// CHECK-NEXT: ^bb1(%{{.*}}: !s32i, %{{.*}}: !s32i): // CHECK-NEXT: cir.br ^bb3 -// CHECK-NEXT: ^bb2: +// CHECK-NEXT: ^bb2(%{{.*}}: !s32i, %{{.*}}: !s32i): // CHECK-NEXT: cir.br ^bb3 // CHECK-NEXT: ^bb3: // CHECK-NEXT: cir.return diff --git a/clang/test/CIR/Transforms/switch-flat-sccp.cir b/clang/test/CIR/Transforms/switch-flat-sccp.cir new file mode 100644 index 00000000000000..bee9eefc1e15d2 --- /dev/null +++ b/clang/test/CIR/Transforms/switch-flat-sccp.cir @@ -0,0 +1,70 @@ +// RUN: cir-opt %s -sccp -o - | FileCheck %s + +// cir.switch.flat implements BranchOpInterface::getSuccessorForOperands, so +// with a constant condition only the taken edge is live and SCCP can fold the +// taken successor's block argument to the constant passed along that edge. + +!s32i = !cir.int<s, 32> + +cir.func @constant_switch() -> !s32i { + %cond = cir.const #cir.int<1> : !s32i + %c10 = cir.const #cir.int<10> : !s32i + %c20 = cir.const #cir.int<20> : !s32i + %c30 = cir.const #cir.int<30> : !s32i + cir.switch.flat %cond : !s32i, ^default(%c30 : !s32i) [ + 0: ^case0(%c10 : !s32i), + 1: ^case1(%c20 : !s32i) + ] +^case0(%a: !s32i): + cir.return %a : !s32i +^case1(%b: !s32i): + cir.return %b : !s32i +^default(%d: !s32i): + cir.return %d : !s32i +} + +// CHECK-LABEL: cir.func @constant_switch +// CHECK: %[[C20:.*]] = cir.const #cir.int<20> : !s32i +// CHECK: ^bb1(%[[A:.*]]: !s32i): +// CHECK-NEXT: cir.return %[[A]] : !s32i +// CHECK: ^bb2(%{{.*}}: !s32i): +// CHECK-NEXT: cir.return %[[C20]] : !s32i +// CHECK: ^bb3(%[[D:.*]]: !s32i): +// CHECK-NEXT: cir.return %[[D]] : !s32i + +// No case matches a constant condition: the default edge is the live one. +cir.func @constant_switch_default() -> !s32i { + %cond = cir.const #cir.int<7> : !s32i + %c10 = cir.const #cir.int<10> : !s32i + %c30 = cir.const #cir.int<30> : !s32i + cir.switch.flat %cond : !s32i, ^default(%c30 : !s32i) [ + 0: ^case0(%c10 : !s32i) + ] +^case0(%a: !s32i): + cir.return %a : !s32i +^default(%d: !s32i): + cir.return %d : !s32i +} + +// CHECK-LABEL: cir.func @constant_switch_default +// CHECK: %[[C30:.*]] = cir.const #cir.int<30> : !s32i +// CHECK: ^bb1(%[[A:.*]]: !s32i): +// CHECK-NEXT: cir.return %[[A]] : !s32i +// CHECK: ^bb2(%{{.*}}: !s32i): +// CHECK-NEXT: cir.return %[[C30]] : !s32i + +// A non-constant condition keeps every edge live: the block argument joins +// two different constants and cannot fold. +cir.func @dynamic_switch(%cond: !s32i) -> !s32i { + %c10 = cir.const #cir.int<10> : !s32i + %c20 = cir.const #cir.int<20> : !s32i + cir.switch.flat %cond : !s32i, ^join(%c20 : !s32i) [ + 0: ^join(%c10 : !s32i) + ] +^join(%v: !s32i): + cir.return %v : !s32i +} + +// CHECK-LABEL: cir.func @dynamic_switch +// CHECK: ^bb1(%[[V:.*]]: !s32i): +// CHECK-NEXT: cir.return %[[V]] : !s32i `````````` </details> https://github.com/llvm/llvm-project/pull/230340 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
