[flang-commits] [flang] 5eb4272 - [flang][CodeGen] Replace fir.select* FIR-to-LLVM patterns with stubs that emit conversion errors (#212978)

via flang-commits flang-commits at lists.llvm.org
Fri Jul 31 00:26:31 PDT 2026


Author: Kareem Ergawy
Date: 2026-07-31T09:26:26+02:00
New Revision: 5eb4272b04144bded2ca1819c2d93b1cd4f1a26b

URL: https://github.com/llvm/llvm-project/commit/5eb4272b04144bded2ca1819c2d93b1cd4f1a26b
DIFF: https://github.com/llvm/llvm-project/commit/5eb4272b04144bded2ca1819c2d93b1cd4f1a26b.diff

LOG: [flang][CodeGen] Replace fir.select* FIR-to-LLVM patterns with stubs that emit conversion errors (#212978)

`fir.select`, `fir.select_case`, `fir.select_rank`, and
`fir.select_type` are lowered to cf.* earlier in the pipeline
(`--fir-select-ops-conversion` and `--fir-polymorphic-op`). Their
FIR-to-LLVM conversion patterns are dead in a correct pipeline. Replace
them with a single templated stub
`SelectShouldHaveBeenConvertedStub<OP>` that emits `"'fir.<op>' op
should have already been converted"` and fails legalization, so running
`--fir-to-llvm-ir` standalone on stale IR reports a clear diagnostic
instead of "unable to legalize".

`Fir/convert-to-llvm.fir`'s six select* test blocks are removed (the
lowering no longer runs; CF-level coverage lives in
`Fir/SelectOpsConversion/`). `Fir/convert-to-llvm-invalid.fir` gains a
stub-error test per op. `Fir/Todo/select_case_with_character.fir` is
retargeted to check the equivalent diagnostic now emitted by
`--fir-select-ops-conversion`.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply at anthropic.com>

PR Stack:
* https://github.com/llvm/llvm-project/pull/212977
* ▶️ https://github.com/llvm/llvm-project/pull/212978

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply at anthropic.com>

Added: 
    

Modified: 
    flang/lib/Optimizer/CodeGen/CodeGen.cpp
    flang/test/Fir/Todo/select_case_with_character.fir
    flang/test/Fir/convert-to-llvm-invalid.fir
    flang/test/Fir/convert-to-llvm.fir

Removed: 
    


################################################################################
diff  --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
index 483f839e5b666..55c6afee45996 100644
--- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp
+++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
@@ -101,13 +101,6 @@ static inline mlir::Type getI8Type(mlir::MLIRContext *context) {
   return mlir::IntegerType::get(context, 8);
 }
 
-static mlir::Block *createBlock(mlir::ConversionPatternRewriter &rewriter,
-                                mlir::Block *insertBefore) {
-  assert(insertBefore && "expected valid insertion block");
-  return rewriter.createBlock(insertBefore->getParent(),
-                              mlir::Region::iterator(insertBefore));
-}
-
 /// Extract constant from a value that must be the result of one of the
 /// ConstantOp operations.
 static int64_t getConstantIntValue(mlir::Value val) {
@@ -3972,272 +3965,32 @@ struct ModuleDebugImportsOpConversion
   }
 };
 
-static void genCondBrOp(mlir::Location loc, mlir::Value cmp, mlir::Block *dest,
-                        std::optional<mlir::ValueRange> destOps,
-                        mlir::ConversionPatternRewriter &rewriter,
-                        mlir::Block *newBlock) {
-  if (destOps)
-    mlir::LLVM::CondBrOp::create(rewriter, loc, cmp, dest, *destOps, newBlock,
-                                 mlir::ValueRange());
-  else
-    mlir::LLVM::CondBrOp::create(rewriter, loc, cmp, dest, newBlock);
-}
-
-template <typename A, typename B>
-static void genBrOp(A caseOp, mlir::Block *dest, std::optional<B> destOps,
-                    mlir::ConversionPatternRewriter &rewriter) {
-  if (destOps)
-    rewriter.replaceOpWithNewOp<mlir::LLVM::BrOp>(caseOp, *destOps, dest);
-  else
-    rewriter.replaceOpWithNewOp<mlir::LLVM::BrOp>(caseOp, B{}, dest);
-}
-
-static void genCaseLadderStep(mlir::Location loc, mlir::Value cmp,
-                              mlir::Block *dest,
-                              std::optional<mlir::ValueRange> destOps,
-                              mlir::ConversionPatternRewriter &rewriter) {
-  auto *thisBlock = rewriter.getInsertionBlock();
-  auto *newBlock = createBlock(rewriter, dest);
-  rewriter.setInsertionPointToEnd(thisBlock);
-  genCondBrOp(loc, cmp, dest, destOps, rewriter, newBlock);
-  rewriter.setInsertionPointToEnd(newBlock);
-}
-
-/// Conversion of `fir.select_case`
-///
-/// The `fir.select_case` operation is converted to a if-then-else ladder.
-/// Depending on the case condition type, one or several comparison and
-/// conditional branching can be generated.
-///
-/// A point value case such as `case(4)`, a lower bound case such as
-/// `case(5:)` or an upper bound case such as `case(:3)` are converted to a
-/// simple comparison between the selector value and the constant value in the
-/// case. The block associated with the case condition is then executed if
-/// the comparison succeed otherwise it branch to the next block with the
-/// comparison for the next case conditon.
-///
-/// A closed interval case condition such as `case(7:10)` is converted with a
-/// first comparison and conditional branching for the lower bound. If
-/// successful, it branch to a second block with the comparison for the
-/// upper bound in the same case condition.
-///
-/// TODO: lowering of CHARACTER type cases is not handled yet.
-struct SelectCaseOpConversion : public fir::FIROpConversion<fir::SelectCaseOp> {
-  using FIROpConversion::FIROpConversion;
-
-  llvm::LogicalResult
-  matchAndRewrite(fir::SelectCaseOp caseOp, OpAdaptor adaptor,
-                  mlir::ConversionPatternRewriter &rewriter) const override {
-    unsigned conds = caseOp.getNumConditions();
-    llvm::ArrayRef<mlir::Attribute> cases = caseOp.getCases().getValue();
-    // Type can be CHARACTER, INTEGER, or LOGICAL (C1145)
-    auto ty = caseOp.getSelector().getType();
-    if (mlir::isa<fir::CharacterType>(ty)) {
-      TODO(caseOp.getLoc(), "fir.select_case codegen with character type");
-      return mlir::failure();
-    }
-    mlir::Value selector = caseOp.getSelector(adaptor.getOperands());
-    auto loc = caseOp.getLoc();
-    for (unsigned t = 0; t != conds; ++t) {
-      mlir::Block *dest = caseOp.getSuccessor(t);
-      std::optional<mlir::ValueRange> destOps =
-          caseOp.getSuccessorOperands(adaptor.getOperands(), t);
-      // Convert block signature if needed
-      if (destOps && !destOps->empty())
-        if (auto conversion = getTypeConverter()->convertBlockSignature(dest))
-          dest = rewriter.applySignatureConversion(dest, *conversion,
-                                                   getTypeConverter());
-      std::optional<mlir::ValueRange> cmpOps =
-          *caseOp.getCompareOperands(adaptor.getOperands(), t);
-      mlir::Attribute attr = cases[t];
-      assert(mlir::isa<mlir::UnitAttr>(attr) || cmpOps.has_value());
-      if (mlir::isa<fir::PointIntervalAttr>(attr)) {
-        auto cmp = mlir::LLVM::ICmpOp::create(rewriter, loc,
-                                              mlir::LLVM::ICmpPredicate::eq,
-                                              selector, cmpOps->front());
-        genCaseLadderStep(loc, cmp, dest, destOps, rewriter);
-        continue;
-      }
-      if (mlir::isa<fir::LowerBoundAttr>(attr)) {
-        auto cmp = mlir::LLVM::ICmpOp::create(rewriter, loc,
-                                              mlir::LLVM::ICmpPredicate::sle,
-                                              cmpOps->front(), selector);
-        genCaseLadderStep(loc, cmp, dest, destOps, rewriter);
-        continue;
-      }
-      if (mlir::isa<fir::UpperBoundAttr>(attr)) {
-        auto cmp = mlir::LLVM::ICmpOp::create(rewriter, loc,
-                                              mlir::LLVM::ICmpPredicate::sle,
-                                              selector, cmpOps->front());
-        genCaseLadderStep(loc, cmp, dest, destOps, rewriter);
-        continue;
-      }
-      if (mlir::isa<fir::ClosedIntervalAttr>(attr)) {
-        mlir::Value caseArg0 = *cmpOps->begin();
-        auto cmp0 = mlir::LLVM::ICmpOp::create(
-            rewriter, loc, mlir::LLVM::ICmpPredicate::sle, caseArg0, selector);
-        auto *thisBlock = rewriter.getInsertionBlock();
-        auto *newBlock1 = createBlock(rewriter, dest);
-        auto *newBlock2 = createBlock(rewriter, dest);
-        rewriter.setInsertionPointToEnd(thisBlock);
-        mlir::LLVM::CondBrOp::create(rewriter, loc, cmp0, newBlock1, newBlock2);
-        rewriter.setInsertionPointToEnd(newBlock1);
-        mlir::Value caseArg1 = *(cmpOps->begin() + 1);
-        auto cmp1 = mlir::LLVM::ICmpOp::create(
-            rewriter, loc, mlir::LLVM::ICmpPredicate::sle, selector, caseArg1);
-        genCondBrOp(loc, cmp1, dest, destOps, rewriter, newBlock2);
-        rewriter.setInsertionPointToEnd(newBlock2);
-        continue;
-      }
-      assert(mlir::isa<mlir::UnitAttr>(attr));
-      assert((t + 1 == conds) && "unit must be last");
-      genBrOp(caseOp, dest, destOps, rewriter);
-    }
-    return mlir::success();
-  }
-};
-
-/// Base class for SelectOpConversion and SelectRankOpConversion.
+/// Defensive stub. `fir.select`, `fir.select_case`, and `fir.select_rank` are
+/// lowered to `cf.switch` / `cf.cond_br` by `--fir-select-ops-conversion`
+/// earlier in the pipeline; `fir.select_type` is lowered to a cf-based
+/// if-then-else ladder by `--fir-polymorphic-op`. If any of these ops
+/// reaches FIR-to-LLVM, we emit a clear diagnostic rather than an opaque
+/// "unable to legalize" error.
 template <typename OP>
-struct SelectOpConversionBase : public fir::FIROpConversion<OP> {
+struct SelectShouldHaveBeenConvertedStub : public fir::FIROpConversion<OP> {
   using fir::FIROpConversion<OP>::FIROpConversion;
 
-private:
-  /// Helper function for converting select ops. This function converts the
-  /// signature of the given block. If the new block signature is 
diff erent from
-  /// `expectedTypes`, returns "failure".
-  llvm::FailureOr<mlir::Block *>
-  getConvertedBlock(mlir::ConversionPatternRewriter &rewriter,
-                    mlir::Operation *branchOp, mlir::Block *block,
-                    mlir::TypeRange expectedTypes) const {
-    const mlir::TypeConverter *converter = this->getTypeConverter();
-    assert(converter && "expected non-null type converter");
-    assert(!block->isEntryBlock() && "entry blocks have no predecessors");
-
-    // There is nothing to do if the types already match.
-    if (block->getArgumentTypes() == expectedTypes)
-      return block;
-
-    // Compute the new block argument types and convert the block.
-    std::optional<mlir::TypeConverter::SignatureConversion> conversion =
-        converter->convertBlockSignature(block);
-    if (!conversion)
-      return rewriter.notifyMatchFailure(branchOp,
-                                         "could not compute block signature");
-    if (expectedTypes != conversion->getConvertedTypes())
-      return rewriter.notifyMatchFailure(branchOp,
-                                         "mismatch between adaptor operand "
-                                         "types and computed block signature");
-    return rewriter.applySignatureConversion(block, *conversion, converter);
-  }
-
-protected:
-  llvm::LogicalResult
-  selectMatchAndRewrite(OP select, typename OP::Adaptor adaptor,
-                        mlir::ConversionPatternRewriter &rewriter) const {
-    unsigned conds = select.getNumConditions();
-    auto cases = select.getCases().getValue();
-    mlir::Value selector = adaptor.getSelector();
-    auto loc = select.getLoc();
-    assert(conds > 0 && "select must have cases");
-
-    llvm::SmallVector<mlir::Block *> destinations;
-    llvm::SmallVector<mlir::ValueRange> destinationsOperands;
-    mlir::Block *defaultDestination;
-    mlir::ValueRange defaultOperands;
-    // LLVM::SwitchOp selector type and the case values types
-    // must have the same bit width, so cast the selector to i64,
-    // and use i64 for the case values. It is hard to imagine
-    // a computed GO TO with the number of labels in the label-list
-    // bigger than INT_MAX, but let's use i64 to be on the safe side.
-    // Moreover, fir.select operation is more relaxed than
-    // a Fortran computed GO TO, so it may specify such a case value
-    // even if there is just a single label/case.
-    llvm::SmallVector<int64_t> caseValues;
-
-    for (unsigned t = 0; t != conds; ++t) {
-      mlir::Block *dest = select.getSuccessor(t);
-      auto destOps = select.getSuccessorOperands(adaptor.getOperands(), t);
-      const mlir::Attribute &attr = cases[t];
-      if (auto intAttr = mlir::dyn_cast<mlir::IntegerAttr>(attr)) {
-        destinationsOperands.push_back(destOps ? *destOps : mlir::ValueRange{});
-        auto convertedBlock =
-            getConvertedBlock(rewriter, select, dest,
-                              mlir::TypeRange(destinationsOperands.back()));
-        if (mlir::failed(convertedBlock))
-          return mlir::failure();
-        destinations.push_back(*convertedBlock);
-        caseValues.push_back(intAttr.getInt());
-        continue;
-      }
-      assert(mlir::dyn_cast_or_null<mlir::UnitAttr>(attr));
-      assert((t + 1 == conds) && "unit must be last");
-      defaultOperands = destOps ? *destOps : mlir::ValueRange{};
-      auto convertedBlock = getConvertedBlock(rewriter, select, dest,
-                                              mlir::TypeRange(defaultOperands));
-      if (mlir::failed(convertedBlock))
-        return mlir::failure();
-      defaultDestination = *convertedBlock;
-    }
-
-    // Deal with the case where there is only a default destination.  Handle it
-    // now because emitting empty case values is not legal.
-    if (caseValues.empty()) {
-      rewriter.replaceOpWithNewOp<mlir::LLVM::BrOp>(select, defaultOperands,
-                                                    defaultDestination);
-      return mlir::success();
-    }
-
-    selector =
-        this->integerCast(loc, rewriter, rewriter.getI64Type(), selector);
-
-    rewriter.replaceOpWithNewOp<mlir::LLVM::SwitchOp>(
-        select, selector,
-        /*defaultDestination=*/defaultDestination,
-        /*defaultOperands=*/defaultOperands,
-        /*caseValues=*/rewriter.getI64VectorAttr(caseValues),
-        /*caseDestinations=*/destinations,
-        /*caseOperands=*/destinationsOperands,
-        /*branchWeights=*/llvm::ArrayRef<std::int32_t>());
-    return mlir::success();
-  }
-};
-/// conversion of fir::SelectOp to an if-then-else ladder
-struct SelectOpConversion : public SelectOpConversionBase<fir::SelectOp> {
-  using SelectOpConversionBase::SelectOpConversionBase;
-
-  llvm::LogicalResult
-  matchAndRewrite(fir::SelectOp op, OpAdaptor adaptor,
-                  mlir::ConversionPatternRewriter &rewriter) const override {
-    return this->selectMatchAndRewrite(op, adaptor, rewriter);
-  }
-};
-
-/// conversion of fir::SelectRankOp to an if-then-else ladder
-struct SelectRankOpConversion
-    : public SelectOpConversionBase<fir::SelectRankOp> {
-  using SelectOpConversionBase::SelectOpConversionBase;
-
-  llvm::LogicalResult
-  matchAndRewrite(fir::SelectRankOp op, OpAdaptor adaptor,
-                  mlir::ConversionPatternRewriter &rewriter) const override {
-    return this->selectMatchAndRewrite(op, adaptor, rewriter);
-  }
-};
-
-/// Lower `fir.select_type` to LLVM IR dialect.
-struct SelectTypeOpConversion : public fir::FIROpConversion<fir::SelectTypeOp> {
-  using FIROpConversion::FIROpConversion;
-
-  llvm::LogicalResult
-  matchAndRewrite(fir::SelectTypeOp select, OpAdaptor adaptor,
-                  mlir::ConversionPatternRewriter &rewriter) const override {
-    mlir::emitError(select.getLoc(),
-                    "fir.select_type should have already been converted");
+  llvm::LogicalResult matchAndRewrite(
+      OP op, typename OP::Adaptor /*adaptor*/,
+      mlir::ConversionPatternRewriter & /*rewriter*/) const override {
+    op.emitOpError("should have already been converted");
     return mlir::failure();
   }
 };
 
+using SelectOpConversion = SelectShouldHaveBeenConvertedStub<fir::SelectOp>;
+using SelectCaseOpConversion =
+    SelectShouldHaveBeenConvertedStub<fir::SelectCaseOp>;
+using SelectRankOpConversion =
+    SelectShouldHaveBeenConvertedStub<fir::SelectRankOp>;
+using SelectTypeOpConversion =
+    SelectShouldHaveBeenConvertedStub<fir::SelectTypeOp>;
+
 /// `fir.store` --> `llvm.store`
 struct StoreOpConversion : public fir::FIROpConversion<fir::StoreOp> {
   using FIROpConversion::FIROpConversion;

diff  --git a/flang/test/Fir/Todo/select_case_with_character.fir b/flang/test/Fir/Todo/select_case_with_character.fir
index bddcb1e18a1b3..9d3231e74df7a 100644
--- a/flang/test/Fir/Todo/select_case_with_character.fir
+++ b/flang/test/Fir/Todo/select_case_with_character.fir
@@ -1,4 +1,4 @@
-// RUN: %not_todo_cmd fir-opt --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" %s 2>&1 | FileCheck %s
+// RUN: %not_todo_cmd fir-opt --fir-select-ops-conversion %s 2>&1 | FileCheck %s
 
 // Test `fir.select_case` conversion to llvm with character type.
 // Not implemented yet.

diff  --git a/flang/test/Fir/convert-to-llvm-invalid.fir b/flang/test/Fir/convert-to-llvm-invalid.fir
index b0c66e283bf5a..c7249eed0b4b3 100644
--- a/flang/test/Fir/convert-to-llvm-invalid.fir
+++ b/flang/test/Fir/convert-to-llvm-invalid.fir
@@ -27,13 +27,50 @@ func.func @shift_not_dead(%arg0: !fir.box<!fir.array<?xf32>>, %i: index) {
 
 // -----
 
-// Test `fir.select_type` conversion to llvm.
-// Should have been converted.
+// The four fir.select* terminators are lowered to cf.* earlier in the
+// pipeline (--fir-select-ops-conversion for select/select_case/select_rank,
+// --fir-polymorphic-op for select_type). Any that reach FIR-to-LLVM hit a
+// defensive stub that emits a clear "should have already been converted"
+// diagnostic.
 
-func.func @bar_select_type(%arg : !fir.class<!fir.type<derivedst{a:f32}>>) -> i32 {
+func.func @select_should_have_been_converted(%arg: i32) -> i32 {
+  %0 = arith.constant 1 : i32
+  // expected-error at +2{{'fir.select' op should have already been converted}}
+  // expected-error at +1{{failed to legalize operation 'fir.select'}}
+  fir.select %arg : i32 [1, ^bb1(%0:i32), unit, ^bb1(%0:i32)]
+^bb1(%a: i32):
+  return %a : i32
+}
+
+// -----
+
+func.func @select_case_should_have_been_converted(%arg: !fir.ref<i32>) -> i32 {
+  %v = fir.load %arg : !fir.ref<i32>
+  %c1 = arith.constant 1 : i32
+  // expected-error at +2{{'fir.select_case' op should have already been converted}}
+  // expected-error at +1{{failed to legalize operation 'fir.select_case'}}
+  fir.select_case %v : i32 [#fir.point, %c1, ^bb1, unit, ^bb1]
+^bb1:
+  return %v : i32
+}
+
+// -----
+
+func.func @select_rank_should_have_been_converted(%arg: i32) -> i32 {
+  %0 = arith.constant 1 : i32
+  // expected-error at +2{{'fir.select_rank' op should have already been converted}}
+  // expected-error at +1{{failed to legalize operation 'fir.select_rank'}}
+  fir.select_rank %arg : i32 [1, ^bb1(%0:i32), unit, ^bb1(%0:i32)]
+^bb1(%a: i32):
+  return %a : i32
+}
+
+// -----
+
+func.func @select_type_should_have_been_converted(%arg: !fir.class<!fir.type<derivedst{a:f32}>>) -> i32 {
   %0 = arith.constant 1 : i32
   %2 = arith.constant 3 : i32
-  // expected-error at +2{{fir.select_type should have already been converted}}
+  // expected-error at +2{{'fir.select_type' op should have already been converted}}
   // expected-error at +1{{failed to legalize operation 'fir.select_type'}}
   fir.select_type %arg : !fir.class<!fir.type<derivedst{a:f32}>> [
     #fir.type_is<!fir.int<4>>,^bb1(%0:i32),

diff  --git a/flang/test/Fir/convert-to-llvm.fir b/flang/test/Fir/convert-to-llvm.fir
index 8d67b43ffd338..6af50b963130e 100644
--- a/flang/test/Fir/convert-to-llvm.fir
+++ b/flang/test/Fir/convert-to-llvm.fir
@@ -326,98 +326,6 @@ func.func @test_unreachable() {
 
 // -----
 
-// Test `fir.select` operation conversion pattern.
-// Check that the if-then-else ladder is correctly constructed and that we
-// branch to the correct block.
-
-func.func @select(%arg : index, %arg2 : i32) -> i32 {
-  %0 = arith.constant 1 : i32
-  %1 = arith.constant 2 : i32
-  %2 = arith.constant 3 : i32
-  %3 = arith.constant 4 : i32
-  fir.select %arg:index [ 1, ^bb1(%0:i32),
-                          2, ^bb2(%2,%arg,%arg2:i32,index,i32),
-                          3, ^bb3(%arg2,%2:i32,i32),
-                          4, ^bb4(%1:i32),
-                          unit, ^bb5 ]
-  ^bb1(%a : i32) :
-    return %a : i32
-  ^bb2(%b : i32, %b2 : index, %b3:i32) :
-    %castidx = arith.index_cast %b2 : index to i32
-    %4 = arith.addi %b, %castidx : i32
-    %5 = arith.addi %4, %b3 : i32
-    return %5 : i32
-  ^bb3(%c:i32, %c2:i32) :
-    %6 = arith.addi %c, %c2 : i32
-    return %6 : i32
-  ^bb4(%d : i32) :
-    return %d : i32
-  ^bb5 :
-    %zero = arith.constant 0 : i32
-    return %zero : i32
-}
-
-// CHECK-LABEL: func @select(
-// CHECK-SAME:               %[[SELECTVALUE:.*]]: [[IDX:.*]],
-// CHECK-SAME:               %[[ARG1:.*]]: i32)
-// CHECK:         %[[C0:.*]] = llvm.mlir.constant(1 : i32) : i32
-// CHECK:         %[[C1:.*]] = llvm.mlir.constant(2 : i32) : i32
-// CHECK:         %[[C2:.*]] = llvm.mlir.constant(3 : i32) : i32
-// CHECK:         llvm.switch %[[SELECTVALUE]] : i64, ^bb5 [
-// CHECK:           1: ^bb1(%[[C0]] : i32),
-// CHECK:           2: ^bb2(%[[C2]], %[[SELECTVALUE]], %[[ARG1]] : i32, [[IDX]], i32),
-// CHECK:           3: ^bb3(%[[ARG1]], %[[C2]] : i32, i32),
-// CHECK:           4: ^bb4(%[[C1]] : i32)
-// CHECK:         ]
-
-// -----
-
-// Test `fir.select_rank` operation conversion pattern.
-// Check that the if-then-else ladder is correctly constructed and that we
-// branch to the correct block.
-
-func.func @select_rank(%arg : i32, %arg2 : i32) -> i32 {
-  %0 = arith.constant 1 : i32
-  %1 = arith.constant 2 : i32
-  %2 = arith.constant 3 : i32
-  %3 = arith.constant 4 : i32
-  fir.select_rank %arg:i32 [ 1, ^bb1(%0:i32),
-                             2, ^bb2(%2,%arg,%arg2:i32,i32,i32),
-                             3, ^bb3(%arg2,%2:i32,i32),
-                             4, ^bb4(%1:i32),
-                             unit, ^bb5 ]
-  ^bb1(%a : i32) :
-    return %a : i32
-  ^bb2(%b : i32, %b2 : i32, %b3:i32) :
-    %4 = arith.addi %b, %b2 : i32
-    %5 = arith.addi %4, %b3 : i32
-    return %5 : i32
-  ^bb3(%c:i32, %c2:i32) :
-    %6 = arith.addi %c, %c2 : i32
-    return %6 : i32
-  ^bb4(%d : i32) :
-    return %d : i32
-  ^bb5 :
-    %zero = arith.constant 0 : i32
-    return %zero : i32
-}
-
-// CHECK-LABEL: func @select_rank(
-// CHECK-SAME:                    %[[SELECTVALUE:.*]]: i32,
-// CHECK-SAME:                    %[[ARG1:.*]]: i32)
-// CHECK:         %[[C0:.*]] = llvm.mlir.constant(1 : i32) : i32
-// CHECK:         %[[C1:.*]] = llvm.mlir.constant(2 : i32) : i32
-// CHECK:         %[[C2:.*]] = llvm.mlir.constant(3 : i32) : i32
-// CHECK:         %[[SELECTOR:.*]] = llvm.sext %[[SELECTVALUE]] : i{{.*}} to i64
-// CHECK:         llvm.switch %[[SELECTOR]] : i64, ^bb5 [
-// CHECK:           1: ^bb1(%[[C0]] : i32),
-// CHECK:           2: ^bb2(%[[C2]], %[[SELECTVALUE]], %[[ARG1]] : i32, i32, i32),
-// CHECK:           3: ^bb3(%[[ARG1]], %[[C2]] : i32, i32),
-// CHECK:           4: ^bb4(%[[C1]] : i32)
-// CHECK:         ]
-
-// -----
-
 // Test fir.extract_value operation conversion with derived type.
 
 func.func @extract_derived_type() -> f32 {
@@ -1366,159 +1274,6 @@ func.func @alloca_assumed_rank_box() -> !fir.ref<!fir.box<!fir.array<*:f32>>> {
 
 // -----
 
-// Test `fir.select_case` operation conversion with INTEGER.
-
-func.func @select_case_integer(%arg0: !fir.ref<i32>) -> i32 {
-  %2 = fir.load %arg0 : !fir.ref<i32>
-  %c1_i32 = arith.constant 1 : i32
-  %c2_i32 = arith.constant 2 : i32
-  %c4_i32 = arith.constant 4 : i32
-  %c5_i32 = arith.constant 5 : i32
-  %c7_i32 = arith.constant 7 : i32
-  %c8_i32 = arith.constant 8 : i32
-  %c15_i32 = arith.constant 15 : i32
-  %c21_i32 = arith.constant 21 : i32
-  fir.select_case %2 : i32 [#fir.upper, %c1_i32, ^bb1,
-                            #fir.point, %c2_i32, ^bb2,
-                            #fir.interval, %c4_i32, %c5_i32, ^bb4,
-                            #fir.point, %c7_i32, ^bb5,
-                            #fir.interval, %c8_i32, %c15_i32, ^bb5,
-                            #fir.lower, %c21_i32, ^bb5,
-                            unit, ^bb3]
-^bb1:  // pred: ^bb0
-  %c1_i32_0 = arith.constant 1 : i32
-  fir.store %c1_i32_0 to %arg0 : !fir.ref<i32>
-  cf.br ^bb6
-^bb2:  // pred: ^bb0
-  %c2_i32_1 = arith.constant 2 : i32
-  fir.store %c2_i32_1 to %arg0 : !fir.ref<i32>
-  cf.br ^bb6
-^bb3:  // pred: ^bb0
-  %c0_i32 = arith.constant 0 : i32
-  fir.store %c0_i32 to %arg0 : !fir.ref<i32>
-  cf.br ^bb6
-^bb4:  // pred: ^bb0
-  %c4_i32_2 = arith.constant 4 : i32
-  fir.store %c4_i32_2 to %arg0 : !fir.ref<i32>
-  cf.br ^bb6
-^bb5:  // 3 preds: ^bb0, ^bb0, ^bb0
-  %c7_i32_3 = arith.constant 7 : i32
-  fir.store %c7_i32_3 to %arg0 : !fir.ref<i32>
-  cf.br ^bb6
-^bb6:  // 5 preds: ^bb1, ^bb2, ^bb3, ^bb4, ^bb5
-  %3 = fir.load %arg0 : !fir.ref<i32>
-  return %3 : i32
-}
-
-// CHECK-LABEL: llvm.func @select_case_integer(
-// CHECK-SAME:                         %[[ARG0:.*]]: !llvm.ptr) -> i32 {
-// CHECK:         %[[SELECT_VALUE:.*]] = llvm.load %[[ARG0]] : !llvm.ptr -> i32
-// CHECK:         %[[CST1:.*]] = llvm.mlir.constant(1 : i32) : i32
-// CHECK:         %[[CST2:.*]] = llvm.mlir.constant(2 : i32) : i32
-// CHECK:         %[[CST4:.*]] = llvm.mlir.constant(4 : i32) : i32
-// CHECK:         %[[CST5:.*]] = llvm.mlir.constant(5 : i32) : i32
-// CHECK:         %[[CST7:.*]] = llvm.mlir.constant(7 : i32) : i32
-// CHECK:         %[[CST8:.*]] = llvm.mlir.constant(8 : i32) : i32
-// CHECK:         %[[CST15:.*]] = llvm.mlir.constant(15 : i32) : i32
-// CHECK:         %[[CST21:.*]] = llvm.mlir.constant(21 : i32) : i32
-// Check for upper bound `case (:1)`
-// CHECK:         %[[CMP_SLE:.*]] = llvm.icmp "sle" %[[SELECT_VALUE]], %[[CST1]] : i32
-// CHECK:         llvm.cond_br %[[CMP_SLE]], ^bb2, ^bb1
-// CHECK-LABEL: ^bb1:
-// Check for point value `case (2)`
-// CHECK:         %[[CMP_EQ:.*]] = llvm.icmp "eq" %[[SELECT_VALUE]], %[[CST2]] : i32
-// CHECK:         llvm.cond_br %[[CMP_EQ]], ^bb4, ^bb3
-// Block ^bb1 in original FIR code.
-// CHECK-LABEL: ^bb2:
-// CHECK:         llvm.br ^bb{{.*}}
-// CHECK-LABEL: ^bb3:
-// Check for the lower bound for the interval `case (4:5)`
-// CHECK:        %[[CMP_SLE:.*]] = llvm.icmp "sle" %[[CST4]], %[[SELECT_VALUE]] : i32
-// CHECK:        llvm.cond_br %[[CMP_SLE]], ^bb[[UPPERBOUND5:.*]], ^bb7
-// Block ^bb2 in original FIR code.
-// CHECK-LABEL: ^bb4:
-// CHECK:        llvm.br ^bb{{.*}}
-// Block ^bb3 in original FIR code.
-// CHECK-LABEL: ^bb5:
-// CHECK:        llvm.br ^bb{{.*}}
-// CHECK:       ^bb[[UPPERBOUND5]]:
-// Check for the upper bound for the interval `case (4:5)`
-// CHECK:        %[[CMP_SLE:.*]] = llvm.icmp "sle" %[[SELECT_VALUE]], %[[CST5]] : i32
-// CHECK:        llvm.cond_br %[[CMP_SLE]], ^bb8, ^bb7
-// CHECK-LABEL: ^bb7:
-// Check for the point value 7 in `case (7,8:15,21:)`
-// CHECK: %[[CMP_EQ:.*]] = llvm.icmp "eq" %[[SELECT_VALUE]], %[[CST7]] : i32
-// CHECK: llvm.cond_br %[[CMP_EQ]], ^bb13, ^bb9
-// Block ^bb4 in original FIR code.
-// CHECK-LABEL: ^bb8:
-// CHECK:        llvm.br ^bb{{.*}}
-// CHECK-LABEL: ^bb9:
-// Check for lower bound 8 in `case (7,8:15,21:)`
-// CHECK:        %[[CMP_SLE:.*]] = llvm.icmp "sle" %[[CST8]], %[[SELECT_VALUE]] : i32
-// CHECK:        llvm.cond_br %[[CMP_SLE]], ^bb[[INTERVAL8_15:.*]], ^bb11
-// CHECK:       ^bb[[INTERVAL8_15]]:
-// Check for upper bound 15 in `case (7,8:15,21:)`
-// CHECK:        %[[CMP_SLE:.*]] = llvm.icmp "sle" %[[SELECT_VALUE]], %[[CST15]] : i32
-// CHECK:        llvm.cond_br %[[CMP_SLE]], ^bb13, ^bb11
-// CHECK-LABEL: ^bb11:
-// Check for lower bound 21 in `case (7,8:15,21:)`
-// CHECK:        %[[CMP_SLE:.*]]  = llvm.icmp "sle" %[[CST21]], %[[SELECT_VALUE]] : i32
-// CHECK:        llvm.cond_br %[[CMP_SLE]], ^bb13, ^bb12
-// CHECK-LABEL: ^bb12:
-// CHECK:         llvm.br ^bb5
-// Block ^bb5 in original FIR code.
-// CHECK-LABEL: ^bb13:
-// CHECK:        llvm.br ^bb14
-// Block ^bb6 in original FIR code.
-// CHECK-LABEL: ^bb14:
-// CHECK:        %[[RET:.*]] = llvm.load %[[ARG0:.*]] : !llvm.ptr -> i32
-// CHECK:        llvm.return %[[RET]] : i32
-
-// -----
-
-// Test `fir.select_case` operation conversion with LOGICAL.
-
-func.func @select_case_logical(%arg0: !fir.ref<!fir.logical<4>>) {
-  %1 = fir.load %arg0 : !fir.ref<!fir.logical<4>>
-  %2 = fir.convert %1 : (!fir.logical<4>) -> i1
-  %false = arith.constant false
-  %true = arith.constant true
-  fir.select_case %2 : i1 [#fir.point, %false, ^bb1,
-                           #fir.point, %true, ^bb2,
-                            unit, ^bb3]
-^bb1:
-  %c1_i32 = arith.constant 1 : i32
-  cf.br ^bb3
-^bb2:
-  %c2_i32 = arith.constant 2 : i32
-  cf.br ^bb3
-^bb3:
-  return
-}
-
-// CHECK-LABEL: llvm.func @select_case_logical(
-// CHECK-SAME:                                 %[[ARG0:.*]]: !llvm.ptr
-// CHECK:         %[[LOAD_ARG0:.*]] = llvm.load %[[ARG0]] : !llvm.ptr -> i32
-// CHECK:         %[[CST_ZERO:.*]] = llvm.mlir.constant(0 : i32) : i32
-// CHECK:         %[[SELECT_VALUE:.*]] = llvm.icmp "ne" %[[LOAD_ARG0]], %[[CST_ZERO]] : i32
-// CHECK:         %[[CST_FALSE:.*]] = llvm.mlir.constant(false) : i1
-// CHECK:         %[[CST_TRUE:.*]] = llvm.mlir.constant(true) : i1
-// CHECK:         %[[CMPEQ:.*]] = llvm.icmp "eq" %[[SELECT_VALUE]], %[[CST_FALSE]] : i1
-// CHECK:         llvm.cond_br %[[CMPEQ]], ^bb2, ^bb1
-// CHECK-LABEL: ^bb1:
-// CHECK:         %[[CMPEQ:.*]] = llvm.icmp "eq" %[[SELECT_VALUE]], %[[CST_TRUE]] : i1
-// CHECK:         llvm.cond_br %[[CMPEQ]], ^bb4, ^bb3
-// CHECK-LABEL: ^bb2:
-// CHECK:         llvm.br ^bb5
-// CHECK-LABEL: ^bb3:
-// CHECK:         llvm.br ^bb5
-// CHECK-LABEL: ^bb4:
-// CHECK:         llvm.br ^bb5
-// CHECK-LABEL: ^bb5:
-// CHECK:        llvm.return
-
-// -----
-
 // Test `fir.is_present`
 
 func.func @test_is_present_i64(%arg0: !fir.ref<i64>) -> () {
@@ -2929,72 +2684,6 @@ func.func @test_sret(%arg0: (!fir.ref<!fir.type<t{a:!fir.array<5xf64>}>>, f64) -
 
 // -----
 
-func.func @select_with_cast(%arg1 : i8, %arg2 : i16, %arg3: i64, %arg4: index) -> () {
-  fir.select %arg1 : i8 [ 1, ^bb1, unit, ^bb1 ]
-  ^bb1:
-  fir.select %arg2 : i16 [ 1, ^bb2, unit, ^bb2 ]
-  ^bb2:
-  fir.select %arg3 : i64 [ 1, ^bb3, unit, ^bb3 ]
-  ^bb3:
-  fir.select %arg4 : index [ 1, ^bb4, unit, ^bb4 ]
-  ^bb4:
-  fir.select %arg3 : i64 [ 4294967296, ^bb5, unit, ^bb5 ]
-  ^bb5:
-  return
-}
-// CHECK-LABEL:   llvm.func @select_with_cast(
-// CHECK-SAME:      %[[ARG0:.*]]: i8,
-// CHECK-SAME:      %[[ARG1:.*]]: i16,
-// CHECK-SAME:      %[[ARG2:.*]]: i64,
-// CHECK-SAME:      %[[ARG3:.*]]: i64) {
-// CHECK:           %[[VAL_0:.*]] = llvm.sext %[[ARG0]] : i8 to i64
-// CHECK:           llvm.switch %[[VAL_0]] : i64, ^bb1 [
-// CHECK:             1: ^bb1
-// CHECK:           ]
-// CHECK:         ^bb1:
-// CHECK:           %[[VAL_1:.*]] = llvm.sext %[[ARG1]] : i16 to i64
-// CHECK:           llvm.switch %[[VAL_1]] : i64, ^bb2 [
-// CHECK:             1: ^bb2
-// CHECK:           ]
-// CHECK:         ^bb2:
-// CHECK:           llvm.switch %[[ARG2]] : i64, ^bb3 [
-// CHECK:             1: ^bb3
-// CHECK:           ]
-// CHECK:         ^bb3:
-// CHECK:           llvm.switch %[[ARG3]] : i64, ^bb4 [
-// CHECK:             1: ^bb4
-// CHECK:           ]
-// CHECK:         ^bb4:
-// CHECK:           llvm.switch %[[ARG2]] : i64, ^bb5 [
-// CHECK:             4294967296: ^bb5
-// CHECK:           ]
-// CHECK:         ^bb5:
-// CHECK:           llvm.return
-// CHECK:         }
-
-// -----
-
-// Test `fir.select_case` with block arguments requiring type conversion.
-
-func.func @select_case_block_args(%arg0: !fir.ref<i32>, %arg1: !fir.ref<!fir.array<2xi32>>, %arg2: !fir.ref<!fir.array<2xi32>>) {
-  %0 = fir.load %arg0 : !fir.ref<i32>
-  %c1 = arith.constant 1 : i32
-  %c2 = arith.constant 2 : i32
-  fir.select_case %0 : i32 [#fir.point, %c1, ^bb1(%arg1 : !fir.ref<!fir.array<2xi32>>),
-                            #fir.point, %c2, ^bb1(%arg2 : !fir.ref<!fir.array<2xi32>>),
-                            unit, ^bb2]
-^bb1(%1: !fir.ref<!fir.array<2xi32>>):
-  cf.br ^bb2
-^bb2:
-  return
-}
-
-// CHECK-LABEL: llvm.func @select_case_block_args
-// CHECK: llvm.cond_br %{{.*}}, ^{{.*}}(%{{.*}} : !llvm.ptr), ^{{.*}}
-// CHECK: ^{{.*}}(%{{.*}}: !llvm.ptr):
-
-// -----
-
 // Check memcpy alignment
 
 func.func @test_load_box_alignment(%addr : !fir.ref<!fir.box<!fir.array<10xf32>>>) {


        


More information about the flang-commits mailing list