[flang-commits] [flang] [flang] Implement lowering for BOZ literal arguments in BGE, BLE, BGT, BLT (PR #191874)

Caroline Newcombe via flang-commits flang-commits at lists.llvm.org
Thu Apr 23 08:54:08 PDT 2026


https://github.com/cenewcombe updated https://github.com/llvm/llvm-project/pull/191874

>From 68952c5acbab81143d09101ea66276ff9bf9f189 Mon Sep 17 00:00:00 2001
From: Caroline Newcombe <caroline.newcombe at hpe.com>
Date: Mon, 30 Mar 2026 08:56:45 -0500
Subject: [PATCH 1/2] [flang] Implement lowering for BOZ literal arguments in
 BGE, BLE, BGT, BLT

---
 flang/lib/Lower/ConvertExprToHLFIR.cpp | 14 ++++++++-
 flang/test/Lower/Intrinsics/bge.f90    | 42 ++++++++++++++++++++++++++
 flang/test/Lower/Intrinsics/bgt.f90    | 28 +++++++++++++++++
 flang/test/Lower/Intrinsics/ble.f90    | 28 +++++++++++++++++
 flang/test/Lower/Intrinsics/blt.f90    | 28 +++++++++++++++++
 5 files changed, 139 insertions(+), 1 deletion(-)

diff --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp
index 5ee409b031357..dc787dfdf8a7b 100644
--- a/flang/lib/Lower/ConvertExprToHLFIR.cpp
+++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp
@@ -1620,7 +1620,19 @@ class HlfirBuilder {
 private:
   hlfir::EntityWithAttributes
   gen(const Fortran::evaluate::BOZLiteralConstant &expr) {
-    TODO(getLoc(), "BOZ");
+    // BOZ literals reach lowering only from BGE/BGT/BLE/BLT intrinsics when at
+    // least one operand is not constant (otherwise folds). For all other
+    // intrinsics, semantics converts BOZ to the expected type before lowering.
+    Fortran::evaluate::Constant<Fortran::evaluate::LargestInt> intConstant{
+        expr};
+    mlir::Location loc{getLoc()};
+    fir::ExtendedValue exv{Fortran::lower::convertConstant(
+        getConverter(), loc, intConstant,
+        /*outlineBigConstantInReadOnlyMemory=*/false)};
+    if (const auto *scalarBox{exv.getUnboxed()})
+      if (fir::isa_trivial(scalarBox->getType()))
+        return hlfir::EntityWithAttributes(*scalarBox);
+    fir::emitFatalError(loc, "BOZ literal was lowered to unexpected format");
   }
 
   hlfir::EntityWithAttributes gen(const Fortran::evaluate::NullPointer &expr) {
diff --git a/flang/test/Lower/Intrinsics/bge.f90 b/flang/test/Lower/Intrinsics/bge.f90
index f4d05e38f6991..5daab71322525 100644
--- a/flang/test/Lower/Intrinsics/bge.f90
+++ b/flang/test/Lower/Intrinsics/bge.f90
@@ -197,3 +197,45 @@ subroutine bge_test11(c)
   ! CHECK: %[[V:.*]] = fir.convert %[[R]] : (i1) -> !fir.logical<4>
   ! CHECK: hlfir.assign %[[V]] to %[[C_DECL]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
 end subroutine bge_test11
+
+! Test BOZ literal as second argument
+! CHECK-LABEL: func.func @_QPbge_boz_second(
+subroutine bge_boz_second(a, c)
+  integer :: a
+  logical :: c
+  c = bge(a, z'FF')
+  ! CHECK: %[[BOZ:.*]] = arith.constant 255 : i128
+  ! CHECK: %[[A:.*]] = fir.load %{{.*}} : !fir.ref<i32>
+  ! CHECK: %[[EXT:.*]] = arith.extui %[[A]] : i32 to i128
+  ! CHECK: %[[CMP:.*]] = arith.cmpi uge, %[[EXT]], %[[BOZ]] : i128
+  ! CHECK: %[[RES:.*]] = fir.convert %[[CMP]] : (i1) -> !fir.logical<4>
+  ! CHECK: hlfir.assign %[[RES]] to %{{.*}}
+end subroutine bge_boz_second
+
+! Test BOZ literal as first argument
+! CHECK-LABEL: func.func @_QPbge_boz_first(
+subroutine bge_boz_first(a, c)
+  integer :: a
+  logical :: c
+  c = bge(z'FF', a)
+  ! CHECK: %[[BOZ:.*]] = arith.constant 255 : i128
+  ! CHECK: %[[A:.*]] = fir.load %{{.*}} : !fir.ref<i32>
+  ! CHECK: %[[EXT:.*]] = arith.extui %[[A]] : i32 to i128
+  ! CHECK: %[[CMP:.*]] = arith.cmpi uge, %[[BOZ]], %[[EXT]] : i128
+  ! CHECK: %[[RES:.*]] = fir.convert %[[CMP]] : (i1) -> !fir.logical<4>
+  ! CHECK: hlfir.assign %[[RES]] to %{{.*}}
+end subroutine bge_boz_first
+
+! Test BOZ literal wider than companion integer type
+! CHECK-LABEL: func.func @_QPbge_boz_wide(
+subroutine bge_boz_wide(a, c)
+  integer :: a
+  logical :: c
+  c = bge(a, z'1FFFFFFFF')
+  ! CHECK: %[[BOZ:.*]] = arith.constant 8589934591 : i128
+  ! CHECK: %[[A:.*]] = fir.load %{{.*}} : !fir.ref<i32>
+  ! CHECK: %[[EXT:.*]] = arith.extui %[[A]] : i32 to i128
+  ! CHECK: %[[CMP:.*]] = arith.cmpi uge, %[[EXT]], %[[BOZ]] : i128
+  ! CHECK: %[[RES:.*]] = fir.convert %[[CMP]] : (i1) -> !fir.logical<4>
+  ! CHECK: hlfir.assign %[[RES]] to %{{.*}}
+end subroutine bge_boz_wide
diff --git a/flang/test/Lower/Intrinsics/bgt.f90 b/flang/test/Lower/Intrinsics/bgt.f90
index 95a4a875de03e..068b73956028b 100644
--- a/flang/test/Lower/Intrinsics/bgt.f90
+++ b/flang/test/Lower/Intrinsics/bgt.f90
@@ -197,3 +197,31 @@ subroutine bgt_test11(c)
   ! CHECK: %[[V:.*]] = fir.convert %[[R]] : (i1) -> !fir.logical<4>
   ! CHECK: hlfir.assign %[[V]] to %[[C_DECL]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
 end subroutine bgt_test11
+
+! Test BOZ literal as second argument
+! CHECK-LABEL: func.func @_QPbgt_boz_second(
+subroutine bgt_boz_second(a, c)
+  integer :: a
+  logical :: c
+  c = bgt(a, z'FF')
+  ! CHECK: %[[BOZ:.*]] = arith.constant 255 : i128
+  ! CHECK: %[[A:.*]] = fir.load %{{.*}} : !fir.ref<i32>
+  ! CHECK: %[[EXT:.*]] = arith.extui %[[A]] : i32 to i128
+  ! CHECK: %[[CMP:.*]] = arith.cmpi ugt, %[[EXT]], %[[BOZ]] : i128
+  ! CHECK: %[[RES:.*]] = fir.convert %[[CMP]] : (i1) -> !fir.logical<4>
+  ! CHECK: hlfir.assign %[[RES]] to %{{.*}}
+end subroutine bgt_boz_second
+
+! Test BOZ literal as first argument
+! CHECK-LABEL: func.func @_QPbgt_boz_first(
+subroutine bgt_boz_first(a, c)
+  integer :: a
+  logical :: c
+  c = bgt(z'FF', a)
+  ! CHECK: %[[BOZ:.*]] = arith.constant 255 : i128
+  ! CHECK: %[[A:.*]] = fir.load %{{.*}} : !fir.ref<i32>
+  ! CHECK: %[[EXT:.*]] = arith.extui %[[A]] : i32 to i128
+  ! CHECK: %[[CMP:.*]] = arith.cmpi ugt, %[[BOZ]], %[[EXT]] : i128
+  ! CHECK: %[[RES:.*]] = fir.convert %[[CMP]] : (i1) -> !fir.logical<4>
+  ! CHECK: hlfir.assign %[[RES]] to %{{.*}}
+end subroutine bgt_boz_first
diff --git a/flang/test/Lower/Intrinsics/ble.f90 b/flang/test/Lower/Intrinsics/ble.f90
index 4605227710358..f54aa56b30805 100644
--- a/flang/test/Lower/Intrinsics/ble.f90
+++ b/flang/test/Lower/Intrinsics/ble.f90
@@ -197,3 +197,31 @@ subroutine ble_test11(c)
   ! CHECK: %[[V:.*]] = fir.convert %[[R]] : (i1) -> !fir.logical<4>
   ! CHECK: hlfir.assign %[[V]] to %[[C_DECL]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
 end subroutine ble_test11
+
+! Test BOZ literal as second argument
+! CHECK-LABEL: func.func @_QPble_boz_second(
+subroutine ble_boz_second(a, c)
+  integer :: a
+  logical :: c
+  c = ble(a, z'FF')
+  ! CHECK: %[[BOZ:.*]] = arith.constant 255 : i128
+  ! CHECK: %[[A:.*]] = fir.load %{{.*}} : !fir.ref<i32>
+  ! CHECK: %[[EXT:.*]] = arith.extui %[[A]] : i32 to i128
+  ! CHECK: %[[CMP:.*]] = arith.cmpi ule, %[[EXT]], %[[BOZ]] : i128
+  ! CHECK: %[[RES:.*]] = fir.convert %[[CMP]] : (i1) -> !fir.logical<4>
+  ! CHECK: hlfir.assign %[[RES]] to %{{.*}}
+end subroutine ble_boz_second
+
+! Test BOZ literal as first argument
+! CHECK-LABEL: func.func @_QPble_boz_first(
+subroutine ble_boz_first(a, c)
+  integer :: a
+  logical :: c
+  c = ble(z'FF', a)
+  ! CHECK: %[[BOZ:.*]] = arith.constant 255 : i128
+  ! CHECK: %[[A:.*]] = fir.load %{{.*}} : !fir.ref<i32>
+  ! CHECK: %[[EXT:.*]] = arith.extui %[[A]] : i32 to i128
+  ! CHECK: %[[CMP:.*]] = arith.cmpi ule, %[[BOZ]], %[[EXT]] : i128
+  ! CHECK: %[[RES:.*]] = fir.convert %[[CMP]] : (i1) -> !fir.logical<4>
+  ! CHECK: hlfir.assign %[[RES]] to %{{.*}}
+end subroutine ble_boz_first
diff --git a/flang/test/Lower/Intrinsics/blt.f90 b/flang/test/Lower/Intrinsics/blt.f90
index 89e743c64a081..b7e14800a62c0 100644
--- a/flang/test/Lower/Intrinsics/blt.f90
+++ b/flang/test/Lower/Intrinsics/blt.f90
@@ -197,3 +197,31 @@ subroutine blt_test11(c)
   ! CHECK: %[[V:.*]] = fir.convert %[[R]] : (i1) -> !fir.logical<4>
   ! CHECK: hlfir.assign %[[V]] to %[[C_DECL]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>>
 end subroutine blt_test11
+
+! Test BOZ literal as second argument
+! CHECK-LABEL: func.func @_QPblt_boz_second(
+subroutine blt_boz_second(a, c)
+  integer :: a
+  logical :: c
+  c = blt(a, z'FF')
+  ! CHECK: %[[BOZ:.*]] = arith.constant 255 : i128
+  ! CHECK: %[[A:.*]] = fir.load %{{.*}} : !fir.ref<i32>
+  ! CHECK: %[[EXT:.*]] = arith.extui %[[A]] : i32 to i128
+  ! CHECK: %[[CMP:.*]] = arith.cmpi ult, %[[EXT]], %[[BOZ]] : i128
+  ! CHECK: %[[RES:.*]] = fir.convert %[[CMP]] : (i1) -> !fir.logical<4>
+  ! CHECK: hlfir.assign %[[RES]] to %{{.*}}
+end subroutine blt_boz_second
+
+! Test BOZ literal as first argument
+! CHECK-LABEL: func.func @_QPblt_boz_first(
+subroutine blt_boz_first(a, c)
+  integer :: a
+  logical :: c
+  c = blt(z'FF', a)
+  ! CHECK: %[[BOZ:.*]] = arith.constant 255 : i128
+  ! CHECK: %[[A:.*]] = fir.load %{{.*}} : !fir.ref<i32>
+  ! CHECK: %[[EXT:.*]] = arith.extui %[[A]] : i32 to i128
+  ! CHECK: %[[CMP:.*]] = arith.cmpi ult, %[[BOZ]], %[[EXT]] : i128
+  ! CHECK: %[[RES:.*]] = fir.convert %[[CMP]] : (i1) -> !fir.logical<4>
+  ! CHECK: hlfir.assign %[[RES]] to %{{.*}}
+end subroutine blt_boz_first

>From 26668028e2ce6d8b11b2f95971242a3953bd0a6b Mon Sep 17 00:00:00 2001
From: Caroline Newcombe <caroline.newcombe at hpe.com>
Date: Thu, 23 Apr 2026 10:53:42 -0500
Subject: [PATCH 2/2] [flang] Additional tests for BOZ arguments in BGE, BLE,
 BGT, BLT

---
 flang/test/Lower/Intrinsics/bge.f90 | 10 ++++++++++
 flang/test/Lower/Intrinsics/bgt.f90 | 10 ++++++++++
 flang/test/Lower/Intrinsics/ble.f90 | 10 ++++++++++
 flang/test/Lower/Intrinsics/blt.f90 | 10 ++++++++++
 4 files changed, 40 insertions(+)

diff --git a/flang/test/Lower/Intrinsics/bge.f90 b/flang/test/Lower/Intrinsics/bge.f90
index 5daab71322525..d65797bac5ad7 100644
--- a/flang/test/Lower/Intrinsics/bge.f90
+++ b/flang/test/Lower/Intrinsics/bge.f90
@@ -239,3 +239,13 @@ subroutine bge_boz_wide(a, c)
   ! CHECK: %[[RES:.*]] = fir.convert %[[CMP]] : (i1) -> !fir.logical<4>
   ! CHECK: hlfir.assign %[[RES]] to %{{.*}}
 end subroutine bge_boz_wide
+
+! Test BOZ literal for both arguments (folded at compile time)
+! CHECK-LABEL: func.func @_QPbge_boz_both(
+subroutine bge_boz_both(c)
+  logical :: c
+  c = bge(z'FF', z'FE')
+  ! CHECK: %[[R:.*]] = arith.constant true
+  ! CHECK: %[[V:.*]] = fir.convert %[[R]] : (i1) -> !fir.logical<4>
+  ! CHECK: hlfir.assign %[[V]] to %{{.*}}
+end subroutine bge_boz_both
diff --git a/flang/test/Lower/Intrinsics/bgt.f90 b/flang/test/Lower/Intrinsics/bgt.f90
index 068b73956028b..77d6a6115417f 100644
--- a/flang/test/Lower/Intrinsics/bgt.f90
+++ b/flang/test/Lower/Intrinsics/bgt.f90
@@ -225,3 +225,13 @@ subroutine bgt_boz_first(a, c)
   ! CHECK: %[[RES:.*]] = fir.convert %[[CMP]] : (i1) -> !fir.logical<4>
   ! CHECK: hlfir.assign %[[RES]] to %{{.*}}
 end subroutine bgt_boz_first
+
+! Test BOZ literal for both arguments (folded at compile time)
+! CHECK-LABEL: func.func @_QPbgt_boz_both(
+subroutine bgt_boz_both(c)
+  logical :: c
+  c = bgt(z'FF', z'FE')
+  ! CHECK: %[[R:.*]] = arith.constant true
+  ! CHECK: %[[V:.*]] = fir.convert %[[R]] : (i1) -> !fir.logical<4>
+  ! CHECK: hlfir.assign %[[V]] to %{{.*}}
+end subroutine bgt_boz_both
diff --git a/flang/test/Lower/Intrinsics/ble.f90 b/flang/test/Lower/Intrinsics/ble.f90
index f54aa56b30805..da325d361e871 100644
--- a/flang/test/Lower/Intrinsics/ble.f90
+++ b/flang/test/Lower/Intrinsics/ble.f90
@@ -225,3 +225,13 @@ subroutine ble_boz_first(a, c)
   ! CHECK: %[[RES:.*]] = fir.convert %[[CMP]] : (i1) -> !fir.logical<4>
   ! CHECK: hlfir.assign %[[RES]] to %{{.*}}
 end subroutine ble_boz_first
+
+! Test BOZ literal for both arguments (folded at compile time)
+! CHECK-LABEL: func.func @_QPble_boz_both(
+subroutine ble_boz_both(c)
+  logical :: c
+  c = ble(z'FF', z'FE')
+  ! CHECK: %[[R:.*]] = arith.constant false
+  ! CHECK: %[[V:.*]] = fir.convert %[[R]] : (i1) -> !fir.logical<4>
+  ! CHECK: hlfir.assign %[[V]] to %{{.*}}
+end subroutine ble_boz_both
diff --git a/flang/test/Lower/Intrinsics/blt.f90 b/flang/test/Lower/Intrinsics/blt.f90
index b7e14800a62c0..c9d527fb5e396 100644
--- a/flang/test/Lower/Intrinsics/blt.f90
+++ b/flang/test/Lower/Intrinsics/blt.f90
@@ -225,3 +225,13 @@ subroutine blt_boz_first(a, c)
   ! CHECK: %[[RES:.*]] = fir.convert %[[CMP]] : (i1) -> !fir.logical<4>
   ! CHECK: hlfir.assign %[[RES]] to %{{.*}}
 end subroutine blt_boz_first
+
+! Test BOZ literal for both arguments (folded at compile time)
+! CHECK-LABEL: func.func @_QPblt_boz_both(
+subroutine blt_boz_both(c)
+  logical :: c
+  c = blt(z'FF', z'FE')
+  ! CHECK: %[[R:.*]] = arith.constant false
+  ! CHECK: %[[V:.*]] = fir.convert %[[R]] : (i1) -> !fir.logical<4>
+  ! CHECK: hlfir.assign %[[V]] to %{{.*}}
+end subroutine blt_boz_both



More information about the flang-commits mailing list