Skip to content

Conversation

@NexMing
Copy link
Contributor

@NexMing NexMing commented Dec 8, 2025

The comparison depends on the sign of the step, and when step == 0 it always returns false.

…`scf.while`.

The comparison depends on the sign of the step, and when `step == 0` it always returns `false`.
@llvmbot llvmbot added flang Flang issues not falling into any other category flang:fir-hlfir labels Dec 8, 2025
@llvmbot
Copy link
Member

llvmbot commented Dec 8, 2025

@llvm/pr-subscribers-flang-fir-hlfir

Author: Ming Yan (NexMing)

Changes

The comparison depends on the sign of the step, and when step == 0 it always returns false.


Full diff: https://github.com/llvm/llvm-project/pull/171080.diff

2 Files Affected:

  • (modified) flang/lib/Optimizer/Transforms/FIRToSCF.cpp (+16-3)
  • (modified) flang/test/Fir/FirToSCF/iter-while.fir (+143-47)
diff --git a/flang/lib/Optimizer/Transforms/FIRToSCF.cpp b/flang/lib/Optimizer/Transforms/FIRToSCF.cpp
index e7e71a9f0bcb3..d38bedcf10e87 100644
--- a/flang/lib/Optimizer/Transforms/FIRToSCF.cpp
+++ b/flang/lib/Optimizer/Transforms/FIRToSCF.cpp
@@ -153,10 +153,23 @@ struct IterWhileConversion : public mlir::OpRewritePattern<fir::IterWhileOp> {
 
     rewriter.setInsertionPointToStart(&beforeBlock);
 
-    mlir::Value inductionCmp = mlir::arith::CmpIOp::create(
+    // The comparison depends on the sign of the step value. We fully expect
+    // this expression to be folded by the optimizer or LLVM. This expression
+    // is written this way so that `step == 0` always returns `false`.
+    auto zero = mlir::arith::ConstantIndexOp::create(rewriter, loc, 0);
+    auto compl0 = mlir::arith::CmpIOp::create(
+        rewriter, loc, mlir::arith::CmpIPredicate::slt, zero, step);
+    auto compl1 = mlir::arith::CmpIOp::create(
         rewriter, loc, mlir::arith::CmpIPredicate::sle, ivInBefore, upperBound);
-    mlir::Value cond = mlir::arith::AndIOp::create(rewriter, loc, inductionCmp,
-                                                   earlyExitInBefore);
+    auto compl2 = mlir::arith::CmpIOp::create(
+        rewriter, loc, mlir::arith::CmpIPredicate::slt, step, zero);
+    auto compl3 = mlir::arith::CmpIOp::create(
+        rewriter, loc, mlir::arith::CmpIPredicate::sge, ivInBefore, upperBound);
+    auto cmp0 = mlir::arith::AndIOp::create(rewriter, loc, compl0, compl1);
+    auto cmp1 = mlir::arith::AndIOp::create(rewriter, loc, compl2, compl3);
+    auto cmp2 = mlir::arith::OrIOp::create(rewriter, loc, cmp0, cmp1);
+    mlir::Value cond =
+        mlir::arith::AndIOp::create(rewriter, loc, earlyExitInBefore, cmp2);
 
     mlir::scf::ConditionOp::create(rewriter, loc, cond, argsInBefore);
 
diff --git a/flang/test/Fir/FirToSCF/iter-while.fir b/flang/test/Fir/FirToSCF/iter-while.fir
index 19cfaac1cc460..d980fa6fff93b 100644
--- a/flang/test/Fir/FirToSCF/iter-while.fir
+++ b/flang/test/Fir/FirToSCF/iter-while.fir
@@ -1,25 +1,32 @@
 // RUN: fir-opt %s --fir-to-scf --allow-unregistered-dialect | FileCheck %s
 
 // CHECK-LABEL:   func.func @test_simple_iterate_while_1() -> (index, i1, i16, i32) {
-// CHECK:           %[[VAL_0:.*]] = arith.constant 11 : index
-// CHECK:           %[[VAL_1:.*]] = arith.constant 22 : index
-// CHECK:           %[[VAL_2:.*]] = arith.constant 2 : index
-// CHECK:           %[[VAL_3:.*]] = arith.constant true
-// CHECK:           %[[VAL_4:.*]] = arith.constant 123 : i16
-// CHECK:           %[[VAL_5:.*]] = arith.constant 456 : i32
-// CHECK:           %[[VAL_6:.*]]:4 = scf.while (%[[VAL_7:.*]] = %[[VAL_0]], %[[VAL_8:.*]] = %[[VAL_3]], %[[VAL_9:.*]] = %[[VAL_4]], %[[VAL_10:.*]] = %[[VAL_5]]) : (index, i1, i16, i32) -> (index, i1, i16, i32) {
-// CHECK:             %[[VAL_11:.*]] = arith.cmpi sle, %[[VAL_7]], %[[VAL_1]] : index
-// CHECK:             %[[VAL_12:.*]] = arith.andi %[[VAL_11]], %[[VAL_8]] : i1
-// CHECK:             scf.condition(%[[VAL_12]]) %[[VAL_7]], %[[VAL_8]], %[[VAL_9]], %[[VAL_10]] : index, i1, i16, i32
+// CHECK:           %[[CONSTANT_0:.*]] = arith.constant 11 : index
+// CHECK:           %[[CONSTANT_1:.*]] = arith.constant 22 : index
+// CHECK:           %[[CONSTANT_2:.*]] = arith.constant 2 : index
+// CHECK:           %[[CONSTANT_3:.*]] = arith.constant true
+// CHECK:           %[[CONSTANT_4:.*]] = arith.constant 123 : i16
+// CHECK:           %[[CONSTANT_5:.*]] = arith.constant 456 : i32
+// CHECK:           %[[WHILE_0:.*]]:4 = scf.while (%[[VAL_0:.*]] = %[[CONSTANT_0]], %[[VAL_1:.*]] = %[[CONSTANT_3]], %[[VAL_2:.*]] = %[[CONSTANT_4]], %[[VAL_3:.*]] = %[[CONSTANT_5]]) : (index, i1, i16, i32) -> (index, i1, i16, i32) {
+// CHECK:             %[[CONSTANT_6:.*]] = arith.constant 0 : index
+// CHECK:             %[[CMPI_0:.*]] = arith.cmpi slt, %[[CONSTANT_6]], %[[CONSTANT_2]] : index
+// CHECK:             %[[CMPI_1:.*]] = arith.cmpi sle, %[[VAL_0]], %[[CONSTANT_1]] : index
+// CHECK:             %[[CMPI_2:.*]] = arith.cmpi slt, %[[CONSTANT_2]], %[[CONSTANT_6]] : index
+// CHECK:             %[[CMPI_3:.*]] = arith.cmpi sge, %[[VAL_0]], %[[CONSTANT_1]] : index
+// CHECK:             %[[ANDI_0:.*]] = arith.andi %[[CMPI_0]], %[[CMPI_1]] : i1
+// CHECK:             %[[ANDI_1:.*]] = arith.andi %[[CMPI_2]], %[[CMPI_3]] : i1
+// CHECK:             %[[ORI_0:.*]] = arith.ori %[[ANDI_0]], %[[ANDI_1]] : i1
+// CHECK:             %[[ANDI_2:.*]] = arith.andi %[[VAL_1]], %[[ORI_0]] : i1
+// CHECK:             scf.condition(%[[ANDI_2]]) %[[VAL_0]], %[[VAL_1]], %[[VAL_2]], %[[VAL_3]] : index, i1, i16, i32
 // CHECK:           } do {
-// CHECK:           ^bb0(%[[VAL_13:.*]]: index, %[[VAL_14:.*]]: i1, %[[VAL_15:.*]]: i16, %[[VAL_16:.*]]: i32):
-// CHECK:             %[[VAL_17:.*]] = arith.addi %[[VAL_13]], %[[VAL_2]] : index
-// CHECK:             %[[VAL_18:.*]] = arith.constant true
-// CHECK:             %[[VAL_19:.*]] = arith.constant 22 : i16
-// CHECK:             %[[VAL_20:.*]] = arith.constant 33 : i32
-// CHECK:             scf.yield %[[VAL_17]], %[[VAL_18]], %[[VAL_19]], %[[VAL_20]] : index, i1, i16, i32
-// CHECK:           }
-// CHECK:           return %[[VAL_21:.*]]#0, %[[VAL_21]]#1, %[[VAL_21]]#2, %[[VAL_21]]#3 : index, i1, i16, i32
+// CHECK:           ^bb0(%[[VAL_4:.*]]: index, %[[VAL_5:.*]]: i1, %[[VAL_6:.*]]: i16, %[[VAL_7:.*]]: i32):
+// CHECK:             %[[ADDI_0:.*]] = arith.addi %[[VAL_4]], %[[CONSTANT_2]] : index
+// CHECK:             %[[CONSTANT_7:.*]] = arith.constant true
+// CHECK:             %[[CONSTANT_8:.*]] = arith.constant 22 : i16
+// CHECK:             %[[CONSTANT_9:.*]] = arith.constant 33 : i32
+// CHECK:             scf.yield %[[ADDI_0]], %[[CONSTANT_7]], %[[CONSTANT_8]], %[[CONSTANT_9]] : index, i1, i16, i32
+// CHECK:           } attributes {finalValue}
+// CHECK:           return %[[VAL_8:.*]]#0, %[[VAL_8]]#1, %[[VAL_8]]#2, %[[VAL_8]]#3 : index, i1, i16, i32
 // CHECK:         }
 func.func @test_simple_iterate_while_1() -> (index, i1, i16, i32) {
   %lo = arith.constant 11 : index
@@ -41,19 +48,26 @@ func.func @test_simple_iterate_while_1() -> (index, i1, i16, i32) {
 
 // CHECK-LABEL:   func.func @test_simple_iterate_while_2(
 // CHECK-SAME:        %[[ARG0:.*]]: index, %[[ARG1:.*]]: index, %[[ARG2:.*]]: i1, %[[ARG3:.*]]: i32) -> (index, i1, i32) {
-// CHECK:           %[[VAL_0:.*]] = arith.constant 1 : index
-// CHECK:           %[[VAL_1:.*]]:3 = scf.while (%[[VAL_2:.*]] = %[[ARG0]], %[[VAL_3:.*]] = %[[ARG2]], %[[VAL_4:.*]] = %[[ARG3]]) : (index, i1, i32) -> (index, i1, i32) {
-// CHECK:             %[[VAL_5:.*]] = arith.cmpi sle, %[[VAL_2]], %[[ARG1]] : index
-// CHECK:             %[[VAL_6:.*]] = arith.andi %[[VAL_5]], %[[VAL_3]] : i1
-// CHECK:             scf.condition(%[[VAL_6]]) %[[VAL_2]], %[[VAL_3]], %[[VAL_4]] : index, i1, i32
+// CHECK:           %[[CONSTANT_0:.*]] = arith.constant 1 : index
+// CHECK:           %[[WHILE_0:.*]]:3 = scf.while (%[[VAL_0:.*]] = %[[ARG0]], %[[VAL_1:.*]] = %[[ARG2]], %[[VAL_2:.*]] = %[[ARG3]]) : (index, i1, i32) -> (index, i1, i32) {
+// CHECK:             %[[CONSTANT_1:.*]] = arith.constant 0 : index
+// CHECK:             %[[CMPI_0:.*]] = arith.cmpi slt, %[[CONSTANT_1]], %[[CONSTANT_0]] : index
+// CHECK:             %[[CMPI_1:.*]] = arith.cmpi sle, %[[VAL_0]], %[[ARG1]] : index
+// CHECK:             %[[CMPI_2:.*]] = arith.cmpi slt, %[[CONSTANT_0]], %[[CONSTANT_1]] : index
+// CHECK:             %[[CMPI_3:.*]] = arith.cmpi sge, %[[VAL_0]], %[[ARG1]] : index
+// CHECK:             %[[ANDI_0:.*]] = arith.andi %[[CMPI_0]], %[[CMPI_1]] : i1
+// CHECK:             %[[ANDI_1:.*]] = arith.andi %[[CMPI_2]], %[[CMPI_3]] : i1
+// CHECK:             %[[ORI_0:.*]] = arith.ori %[[ANDI_0]], %[[ANDI_1]] : i1
+// CHECK:             %[[ANDI_2:.*]] = arith.andi %[[VAL_1]], %[[ORI_0]] : i1
+// CHECK:             scf.condition(%[[ANDI_2]]) %[[VAL_0]], %[[VAL_1]], %[[VAL_2]] : index, i1, i32
 // CHECK:           } do {
-// CHECK:           ^bb0(%[[VAL_7:.*]]: index, %[[VAL_8:.*]]: i1, %[[VAL_9:.*]]: i32):
-// CHECK:             %[[VAL_10:.*]] = arith.addi %[[VAL_7]], %[[VAL_0]] : index
-// CHECK:             %[[VAL_11:.*]] = arith.constant 123 : i32
-// CHECK:             %[[VAL_12:.*]] = arith.constant true
-// CHECK:             scf.yield %[[VAL_10]], %[[VAL_12]], %[[VAL_11]] : index, i1, i32
-// CHECK:           }
-// CHECK:           return %[[VAL_13:.*]]#0, %[[VAL_13]]#1, %[[VAL_13]]#2 : index, i1, i32
+// CHECK:           ^bb0(%[[VAL_3:.*]]: index, %[[VAL_4:.*]]: i1, %[[VAL_5:.*]]: i32):
+// CHECK:             %[[ADDI_0:.*]] = arith.addi %[[VAL_3]], %[[CONSTANT_0]] : index
+// CHECK:             %[[CONSTANT_2:.*]] = arith.constant 123 : i32
+// CHECK:             %[[CONSTANT_3:.*]] = arith.constant true
+// CHECK:             scf.yield %[[ADDI_0]], %[[CONSTANT_3]], %[[CONSTANT_2]] : index, i1, i32
+// CHECK:           } attributes {finalValue}
+// CHECK:           return %[[VAL_6:.*]]#0, %[[VAL_6]]#1, %[[VAL_6]]#2 : index, i1, i32
 // CHECK:         }
 func.func @test_simple_iterate_while_2(%start: index, %stop: index, %cond: i1, %val: i32) -> (index, i1, i32) {
   %step = arith.constant 1 : index
@@ -67,22 +81,97 @@ func.func @test_simple_iterate_while_2(%start: index, %stop: index, %cond: i1, %
   return %res#0, %res#1, %res#2 : index, i1, i32
 }
 
+// CHECK-LABEL:   func.func @loop_with_negtive_step(
+// CHECK-SAME:      %[[ARG0:.*]]: index,
+// CHECK-SAME:      %[[ARG1:.*]]: index) -> i1 {
+// CHECK:           %[[CONSTANT_0:.*]] = arith.constant -1 : index
+// CHECK:           %[[CONSTANT_1:.*]] = arith.constant true
+// CHECK:           %[[WHILE_0:.*]]:2 = scf.while (%[[VAL_0:.*]] = %[[ARG0]], %[[VAL_1:.*]] = %[[CONSTANT_1]]) : (index, i1) -> (index, i1) {
+// CHECK:             %[[CONSTANT_2:.*]] = arith.constant 0 : index
+// CHECK:             %[[CMPI_0:.*]] = arith.cmpi slt, %[[CONSTANT_2]], %[[CONSTANT_0]] : index
+// CHECK:             %[[CMPI_1:.*]] = arith.cmpi sle, %[[VAL_0]], %[[ARG1]] : index
+// CHECK:             %[[CMPI_2:.*]] = arith.cmpi slt, %[[CONSTANT_0]], %[[CONSTANT_2]] : index
+// CHECK:             %[[CMPI_3:.*]] = arith.cmpi sge, %[[VAL_0]], %[[ARG1]] : index
+// CHECK:             %[[ANDI_0:.*]] = arith.andi %[[CMPI_0]], %[[CMPI_1]] : i1
+// CHECK:             %[[ANDI_1:.*]] = arith.andi %[[CMPI_2]], %[[CMPI_3]] : i1
+// CHECK:             %[[ORI_0:.*]] = arith.ori %[[ANDI_0]], %[[ANDI_1]] : i1
+// CHECK:             %[[ANDI_2:.*]] = arith.andi %[[VAL_1]], %[[ORI_0]] : i1
+// CHECK:             scf.condition(%[[ANDI_2]]) %[[VAL_0]], %[[VAL_1]] : index, i1
+// CHECK:           } do {
+// CHECK:           ^bb0(%[[VAL_2:.*]]: index, %[[VAL_3:.*]]: i1):
+// CHECK:             %[[ADDI_0:.*]] = arith.addi %[[VAL_2]], %[[CONSTANT_0]] : index
+// CHECK:             %[[VAL_4:.*]] = "test.get_some_value"() : () -> i1
+// CHECK:             scf.yield %[[ADDI_0]], %[[VAL_4]] : index, i1
+// CHECK:           } attributes {finalValue}
+// CHECK:           return %[[VAL_5:.*]]#1 : i1
+// CHECK:         }
+func.func @loop_with_negtive_step(%lo : index, %up : index) -> i1 {
+  %c-1 = arith.constant -1 : index
+  %ok1 = arith.constant true
+  %res:2 = fir.iterate_while (%i = %lo to %up step %c-1) and (%j = %ok1) -> (index, i1) {
+    %ok = "test.get_some_value"() : () -> i1
+    fir.result %i, %ok : index, i1
+  }
+  return %res#1 : i1
+}
+
+// CHECK-LABEL:   func.func @loop_with_zero_step(
+// CHECK-SAME:      %[[ARG0:.*]]: index,
+// CHECK-SAME:      %[[ARG1:.*]]: index) -> i1 {
+// CHECK:           %[[CONSTANT_0:.*]] = arith.constant 0 : index
+// CHECK:           %[[CONSTANT_1:.*]] = arith.constant true
+// CHECK:           %[[WHILE_0:.*]]:2 = scf.while (%[[VAL_0:.*]] = %[[ARG0]], %[[VAL_1:.*]] = %[[CONSTANT_1]]) : (index, i1) -> (index, i1) {
+// CHECK:             %[[CONSTANT_2:.*]] = arith.constant 0 : index
+// CHECK:             %[[CMPI_0:.*]] = arith.cmpi slt, %[[CONSTANT_2]], %[[CONSTANT_0]] : index
+// CHECK:             %[[CMPI_1:.*]] = arith.cmpi sle, %[[VAL_0]], %[[ARG1]] : index
+// CHECK:             %[[CMPI_2:.*]] = arith.cmpi slt, %[[CONSTANT_0]], %[[CONSTANT_2]] : index
+// CHECK:             %[[CMPI_3:.*]] = arith.cmpi sge, %[[VAL_0]], %[[ARG1]] : index
+// CHECK:             %[[ANDI_0:.*]] = arith.andi %[[CMPI_0]], %[[CMPI_1]] : i1
+// CHECK:             %[[ANDI_1:.*]] = arith.andi %[[CMPI_2]], %[[CMPI_3]] : i1
+// CHECK:             %[[ORI_0:.*]] = arith.ori %[[ANDI_0]], %[[ANDI_1]] : i1
+// CHECK:             %[[ANDI_2:.*]] = arith.andi %[[VAL_1]], %[[ORI_0]] : i1
+// CHECK:             scf.condition(%[[ANDI_2]]) %[[VAL_0]], %[[VAL_1]] : index, i1
+// CHECK:           } do {
+// CHECK:           ^bb0(%[[VAL_2:.*]]: index, %[[VAL_3:.*]]: i1):
+// CHECK:             %[[ADDI_0:.*]] = arith.addi %[[VAL_2]], %[[CONSTANT_0]] : index
+// CHECK:             %[[VAL_4:.*]] = "test.get_some_value"() : () -> i1
+// CHECK:             scf.yield %[[ADDI_0]], %[[VAL_4]] : index, i1
+// CHECK:           } attributes {finalValue}
+// CHECK:           return %[[VAL_5:.*]]#1 : i1
+// CHECK:         }
+func.func @loop_with_zero_step(%lo : index, %up : index) -> i1 {
+  %c0 = arith.constant 0 : index
+  %ok1 = arith.constant true
+  %res:2 = fir.iterate_while (%i = %lo to %up step %c0) and (%j = %ok1) -> (index, i1) {
+    %ok = "test.get_some_value"() : () -> i1
+    fir.result %i, %ok : index, i1
+  }
+  return %res#1 : i1
+}
+
 // CHECK-LABEL:   func.func @test_zero_iterations() -> (index, i1, i8) {
-// CHECK:           %[[VAL_0:.*]] = arith.constant 10 : index
-// CHECK:           %[[VAL_1:.*]] = arith.constant 5 : index
-// CHECK:           %[[VAL_2:.*]] = arith.constant 1 : index
-// CHECK:           %[[VAL_3:.*]] = arith.constant true
-// CHECK:           %[[VAL_4:.*]] = arith.constant 42 : i8
-// CHECK:           %[[VAL_5:.*]]:3 = scf.while (%[[VAL_6:.*]] = %[[VAL_0]], %[[VAL_7:.*]] = %[[VAL_3]], %[[VAL_8:.*]] = %[[VAL_4]]) : (index, i1, i8) -> (index, i1, i8) {
-// CHECK:             %[[VAL_9:.*]] = arith.cmpi sle, %[[VAL_6]], %[[VAL_1]] : index
-// CHECK:             %[[VAL_10:.*]] = arith.andi %[[VAL_9]], %[[VAL_7]] : i1
-// CHECK:             scf.condition(%[[VAL_10]]) %[[VAL_6]], %[[VAL_7]], %[[VAL_8]] : index, i1, i8
+// CHECK:           %[[CONSTANT_0:.*]] = arith.constant 10 : index
+// CHECK:           %[[CONSTANT_1:.*]] = arith.constant 5 : index
+// CHECK:           %[[CONSTANT_2:.*]] = arith.constant 1 : index
+// CHECK:           %[[CONSTANT_3:.*]] = arith.constant true
+// CHECK:           %[[CONSTANT_4:.*]] = arith.constant 42 : i8
+// CHECK:           %[[WHILE_0:.*]]:3 = scf.while (%[[VAL_0:.*]] = %[[CONSTANT_0]], %[[VAL_1:.*]] = %[[CONSTANT_3]], %[[VAL_2:.*]] = %[[CONSTANT_4]]) : (index, i1, i8) -> (index, i1, i8) {
+// CHECK:             %[[CONSTANT_5:.*]] = arith.constant 0 : index
+// CHECK:             %[[CMPI_0:.*]] = arith.cmpi slt, %[[CONSTANT_5]], %[[CONSTANT_2]] : index
+// CHECK:             %[[CMPI_1:.*]] = arith.cmpi sle, %[[VAL_0]], %[[CONSTANT_1]] : index
+// CHECK:             %[[CMPI_2:.*]] = arith.cmpi slt, %[[CONSTANT_2]], %[[CONSTANT_5]] : index
+// CHECK:             %[[CMPI_3:.*]] = arith.cmpi sge, %[[VAL_0]], %[[CONSTANT_1]] : index
+// CHECK:             %[[ANDI_0:.*]] = arith.andi %[[CMPI_0]], %[[CMPI_1]] : i1
+// CHECK:             %[[ANDI_1:.*]] = arith.andi %[[CMPI_2]], %[[CMPI_3]] : i1
+// CHECK:             %[[ORI_0:.*]] = arith.ori %[[ANDI_0]], %[[ANDI_1]] : i1
+// CHECK:             %[[ANDI_2:.*]] = arith.andi %[[VAL_1]], %[[ORI_0]] : i1
+// CHECK:             scf.condition(%[[ANDI_2]]) %[[VAL_0]], %[[VAL_1]], %[[VAL_2]] : index, i1, i8
 // CHECK:           } do {
-// CHECK:           ^bb0(%[[VAL_11:.*]]: index, %[[VAL_12:.*]]: i1, %[[VAL_13:.*]]: i8):
-// CHECK:             %[[VAL_14:.*]] = arith.addi %[[VAL_11]], %[[VAL_2]] : index
-// CHECK:             scf.yield %[[VAL_14]], %[[VAL_12]], %[[VAL_13]] : index, i1, i8
-// CHECK:           }
-// CHECK:           return %[[VAL_15:.*]]#0, %[[VAL_15]]#1, %[[VAL_15]]#2 : index, i1, i8
+// CHECK:           ^bb0(%[[VAL_3:.*]]: index, %[[VAL_4:.*]]: i1, %[[VAL_5:.*]]: i8):
+// CHECK:             %[[ADDI_0:.*]] = arith.addi %[[VAL_3]], %[[CONSTANT_2]] : index
+// CHECK:             scf.yield %[[ADDI_0]], %[[VAL_4]], %[[VAL_5]] : index, i1, i8
+// CHECK:           } attributes {finalValue}
+// CHECK:           return %[[VAL_6:.*]]#0, %[[VAL_6]]#1, %[[VAL_6]]#2 : index, i1, i8
 // CHECK:         }
 func.func @test_zero_iterations() -> (index, i1, i8) {
   %lo = arith.constant 10 : index
@@ -104,9 +193,16 @@ func.func @test_zero_iterations() -> (index, i1, i8) {
 // CHECK:           %[[CONSTANT_0:.*]] = arith.constant 1 : index
 // CHECK:           %[[CONSTANT_1:.*]] = arith.constant true
 // CHECK:           %[[WHILE_0:.*]]:2 = scf.while (%[[VAL_0:.*]] = %[[ARG0]], %[[VAL_1:.*]] = %[[CONSTANT_1]]) : (index, i1) -> (index, i1) {
-// CHECK:             %[[CMPI_0:.*]] = arith.cmpi sle, %[[VAL_0]], %[[ARG1]] : index
-// CHECK:             %[[ANDI_0:.*]] = arith.andi %[[CMPI_0]], %[[VAL_1]] : i1
-// CHECK:             scf.condition(%[[ANDI_0]]) %[[VAL_0]], %[[VAL_1]] : index, i1
+// CHECK:             %[[CONSTANT_2:.*]] = arith.constant 0 : index
+// CHECK:             %[[CMPI_0:.*]] = arith.cmpi slt, %[[CONSTANT_2]], %[[CONSTANT_0]] : index
+// CHECK:             %[[CMPI_1:.*]] = arith.cmpi sle, %[[VAL_0]], %[[ARG1]] : index
+// CHECK:             %[[CMPI_2:.*]] = arith.cmpi slt, %[[CONSTANT_0]], %[[CONSTANT_2]] : index
+// CHECK:             %[[CMPI_3:.*]] = arith.cmpi sge, %[[VAL_0]], %[[ARG1]] : index
+// CHECK:             %[[ANDI_0:.*]] = arith.andi %[[CMPI_0]], %[[CMPI_1]] : i1
+// CHECK:             %[[ANDI_1:.*]] = arith.andi %[[CMPI_2]], %[[CMPI_3]] : i1
+// CHECK:             %[[ORI_0:.*]] = arith.ori %[[ANDI_0]], %[[ANDI_1]] : i1
+// CHECK:             %[[ANDI_2:.*]] = arith.andi %[[VAL_1]], %[[ORI_0]] : i1
+// CHECK:             scf.condition(%[[ANDI_2]]) %[[VAL_0]], %[[VAL_1]] : index, i1
 // CHECK:           } do {
 // CHECK:           ^bb0(%[[VAL_2:.*]]: index, %[[VAL_3:.*]]: i1):
 // CHECK:             %[[ADDI_0:.*]] = arith.addi %[[VAL_2]], %[[CONSTANT_0]] : index

Copy link
Contributor

@vzakhari vzakhari left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@NexMing NexMing merged commit a1f9489 into llvm:main Dec 9, 2025
13 checks passed
@NexMing NexMing deleted the dev/fir-to-scf branch December 9, 2025 00:40
honeygoyal pushed a commit to honeygoyal/llvm-project that referenced this pull request Dec 9, 2025
…`scf.while`. (llvm#171080)

The comparison depends on the sign of the `step`, and when `step == 0` it always returns `false`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

flang:fir-hlfir flang Flang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants