================
@@ -428,6 +429,52 @@ mlir::LogicalResult CIRGenFunction::emitBreakStmt(const 
clang::BreakStmt &s) {
   return mlir::success();
 }
 
+const CaseStmt *CIRGenFunction::foldCaseStmt(const clang::CaseStmt &s,
+                                             mlir::Type condType,
+                                             mlir::ArrayAttr &value,
+                                             cir::CaseOpKind &kind) {
+  const CaseStmt *caseStmt = &s;
+  const CaseStmt *lastCase = &s;
+  SmallVector<mlir::Attribute, 4> caseEltValueListAttr;
+
+  // Fold cascading cases whenever possible to simplify codegen a bit.
+  while (caseStmt) {
+    lastCase = caseStmt;
+
+    auto intVal = caseStmt->getLHS()->EvaluateKnownConstInt(getContext());
+
+    if (auto *rhs = caseStmt->getRHS()) {
+      auto endVal = rhs->EvaluateKnownConstInt(getContext());
+      SmallVector<mlir::Attribute, 4> rangeCaseAttr = {
+          cir::IntAttr::get(condType, intVal),
+          cir::IntAttr::get(condType, endVal)};
+      value = builder.getArrayAttr(rangeCaseAttr);
+      kind = cir::CaseOpKind::Range;
+
+      // We may not be able to fold rangaes. Due to we can't present range case
+      // with other trivial cases now.
+      return caseStmt;
+    }
+
+    caseEltValueListAttr.push_back(cir::IntAttr::get(condType, intVal));
+
+    caseStmt = dyn_cast_or_null<CaseStmt>(caseStmt->getSubStmt());
+
+    // Break early if we found ranges. We can't fold ranges due to the same
+    // reason above.
+    if (caseStmt && caseStmt->getRHS())
+      break;
+  }
+
+  if (!caseEltValueListAttr.empty()) {
+    value = builder.getArrayAttr(caseEltValueListAttr);
+    kind = caseEltValueListAttr.size() > 1 ? cir::CaseOpKind::Anyof
----------------
Andres-Salamanca wrote:

If we're no longer folding cascading case statements, then this function could 
be simplified we wouldn’t need the while loop anymore since we're just 
extracting the kind and value from a single case. In that scenario, the 
assertion proposed by @andykaylor  would no longer be necessary, because range 
cases would only ever be processed once at the top level.
```cpp
const CaseStmt *CIRGenFunction::foldCaseStmt(const clang::CaseStmt &s,
                                             mlir::Type condType,
                                             mlir::ArrayAttr &value,
                                             cir::CaseOpKind &kind) {
  const CaseStmt *caseStmt = &s;
  SmallVector<mlir::Attribute, 1> caseEltValueListAttr;

  llvm::APSInt intVal = caseStmt->getLHS()->EvaluateKnownConstInt(getContext());

  // If the case statement has an RHS value, it is representing a GNU
  // case range statement, where LHS is the beginning of the range
  // and RHS is the end of the range.
  if (const Expr *rhs = caseStmt->getRHS()) {
    assert(caseStmt == &s && "Range case must be the first case processed");
    llvm::APSInt endVal = rhs->EvaluateKnownConstInt(getContext());
    SmallVector<mlir::Attribute, 4> rangeCaseAttr = {
        cir::IntAttr::get(condType, intVal),
        cir::IntAttr::get(condType, endVal)};
    value = builder.getArrayAttr(rangeCaseAttr);
    kind = cir::CaseOpKind::Range;

    // We don't currently fold case range statements with other case statements.
    // TODO(cir): Add this capability.
    assert(!cir::MissingFeatures::foldRangeCase());
    return caseStmt;
  }

  caseEltValueListAttr.push_back(cir::IntAttr::get(condType, intVal));

  if (!caseEltValueListAttr.empty()) {
    value = builder.getArrayAttr(caseEltValueListAttr);
    kind = cir::CaseOpKind::Equal;
  }

  return caseStmt;
}
```
We don’t need the while loop anymore because we must break as soon as we 
encounter a cascading case or default statement.
```cpp
// Break early if we found a range. We can't fold ranges.
// Also break if we found a cascading case/default.
if (caseStmt) {
  const Stmt *sub = caseStmt->getSubStmt();
  if (caseStmt->getRHS() || isa<CaseStmt>(sub) || isa<DefaultStmt>(sub))
    break;
}
```
Also, given that we're no longer folding multiple cases, I think we should 
consider renaming the function to better reflect its new behavior. Something 
like `getCaseInfo` ?
Is my approach correct ?

https://github.com/llvm/llvm-project/pull/138003
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to