[flang-commits] [flang] 6e94ad0 - [flang] Fold x + 0, 0 + x and x - 0 for INTEGER and UNSIGNED (#192479)

via flang-commits flang-commits at lists.llvm.org
Fri Apr 17 09:00:35 PDT 2026


Author: Krzysztof Parzyszek
Date: 2026-04-17T11:00:30-05:00
New Revision: 6e94ad04a118cf7113463715900b772d77247bce

URL: https://github.com/llvm/llvm-project/commit/6e94ad04a118cf7113463715900b772d77247bce
DIFF: https://github.com/llvm/llvm-project/commit/6e94ad04a118cf7113463715900b772d77247bce.diff

LOG: [flang] Fold x + 0, 0 + x and x - 0 for INTEGER and UNSIGNED (#192479)

This fixes https://github.com/llvm/llvm-project/issues/191928.

Added: 
    flang/test/Evaluate/rewrite09.f90

Modified: 
    flang/lib/Evaluate/fold-implementation.h
    flang/test/Evaluate/rewrite01.f90
    flang/test/Lower/HLFIR/array-ctor-as-elemental.f90
    flang/test/Lower/HLFIR/array-ctor-as-inlined-temp.f90
    flang/test/Lower/HLFIR/array-ctor-as-runtime-temp.f90

Removed: 
    


################################################################################
diff  --git a/flang/lib/Evaluate/fold-implementation.h b/flang/lib/Evaluate/fold-implementation.h
index d4d7f2b705b3d..2df2b9e5a300b 100644
--- a/flang/lib/Evaluate/fold-implementation.h
+++ b/flang/lib/Evaluate/fold-implementation.h
@@ -2018,6 +2018,25 @@ Expr<T> FoldOperation(FoldingContext &context, Add<T> &&x) {
       }
       return Expr<T>{Constant<T>{sum.value}};
     }
+  } else if constexpr (T::category == TypeCategory::Integer ||
+      T::category == TypeCategory::Unsigned) {
+    if (auto c{GetScalarConstantValue<T>(x.right())}) {
+      if (c->IsZero() && x.left().Rank() == 0) {
+        if (IsVariable(x.left())) {
+          return FoldOperation(context, Parentheses<T>{std::move(x.left())});
+        } else {
+          return std::move(x.left());
+        }
+      }
+    } else if (auto c{GetScalarConstantValue<T>(x.left())}) {
+      if (c->IsZero() && x.right().Rank() == 0) {
+        if (IsVariable(x.right())) {
+          return FoldOperation(context, Parentheses<T>{std::move(x.right())});
+        } else {
+          return std::move(x.right());
+        }
+      }
+    }
   }
   return Expr<T>{std::move(x)};
 }
@@ -2047,6 +2066,17 @@ Expr<T> FoldOperation(FoldingContext &context, Subtract<T> &&x) {
       }
       return Expr<T>{Constant<T>{
diff erence.value}};
     }
+  } else if constexpr (T::category == TypeCategory::Integer ||
+      T::category == TypeCategory::Unsigned) {
+    if (auto c{GetScalarConstantValue<T>(x.right())}) {
+      if (c->IsZero() && x.left().Rank() == 0) {
+        if (IsVariable(x.left())) {
+          return FoldOperation(context, Parentheses<T>{std::move(x.left())});
+        } else {
+          return std::move(x.left());
+        }
+      }
+    }
   }
   return Expr<T>{std::move(x)};
 }

diff  --git a/flang/test/Evaluate/rewrite01.f90 b/flang/test/Evaluate/rewrite01.f90
index 0fa3581a3799f..fbbf051246ffe 100644
--- a/flang/test/Evaluate/rewrite01.f90
+++ b/flang/test/Evaluate/rewrite01.f90
@@ -237,7 +237,7 @@ subroutine array_ctor_implied_do_index(x, j)
   character(10) :: c
   !CHECK: PRINT *, size([INTEGER(4)::(x(1_8:i:1_8),INTEGER(8)::i=1_8,2_8,1_8)])
   print *, size([(x(1:i), integer(8)::i=1,2)])
-  !CHECK: PRINT *, int(0_8+2_8*(0_8+max((j-1_8+1_8)/1_8,0_8)),kind=4)
+  !CHECK: PRINT *, int(2_8*max((j-1_8+1_8)/1_8,0_8),kind=4)
   print *, size([(x(1:j), integer(8)::i=1,2)])
   !CHECK: PRINT *, len([(c(i:i),INTEGER(8)::i=1_8,4_8,1_8)])
   print *, len([(c(i:i), integer(8)::i = 1,4)])

diff  --git a/flang/test/Evaluate/rewrite09.f90 b/flang/test/Evaluate/rewrite09.f90
new file mode 100644
index 0000000000000..fcc975a2d7fa1
--- /dev/null
+++ b/flang/test/Evaluate/rewrite09.f90
@@ -0,0 +1,49 @@
+!RUN: %flang_fc1 -fdebug-unparse -funsigned %s | FileCheck %s --check-prefix=UNPARSE
+
+subroutine f00(x)
+  integer :: x, y, z
+  y = x + 0
+  z = 0 + x
+end
+
+!UNPARSE: SUBROUTINE f00 (x)
+!UNPARSE:  INTEGER x, y, z
+!UNPARSE:   y=(x)
+!UNPARSE:   z=(x)
+!UNPARSE: END SUBROUTINE
+
+subroutine f01(x)
+  integer :: x, y, z
+  y = x - 0
+  z = 0 - x
+end
+
+!UNPARSE: SUBROUTINE f01 (x)
+!UNPARSE:  INTEGER x, y, z
+!UNPARSE:   y=(x)
+!UNPARSE:   z=0_4-x
+!UNPARSE: END SUBROUTINE
+
+subroutine f02(x)
+  unsigned :: x, y, z
+  y = x + 0u
+  z = 0u + x
+end
+
+!UNPARSE: SUBROUTINE f02 (x)
+!UNPARSE:  UNSIGNED x, y, z
+!UNPARSE:   y=(x)
+!UNPARSE:   z=(x)
+!UNPARSE: END SUBROUTINE
+
+subroutine f03(x)
+  unsigned :: x, y, z
+  y = x - 0u
+  z = 0u - x
+end
+
+!UNPARSE: SUBROUTINE f03 (x)
+!UNPARSE:  UNSIGNED x, y, z
+!UNPARSE:   y=(x)
+!UNPARSE:   z=0U_4-x
+!UNPARSE: END SUBROUTINE

diff  --git a/flang/test/Lower/HLFIR/array-ctor-as-elemental.f90 b/flang/test/Lower/HLFIR/array-ctor-as-elemental.f90
index f52216d2f558d..54c6fffbbda54 100644
--- a/flang/test/Lower/HLFIR/array-ctor-as-elemental.f90
+++ b/flang/test/Lower/HLFIR/array-ctor-as-elemental.f90
@@ -45,7 +45,6 @@ subroutine test_as_strided_elemental(lb, ub, stride)
 ! CHECK:           %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {uniq_name = "_QFtest_as_strided_elementalElb"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>)
 ! CHECK:           %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {uniq_name = "_QFtest_as_strided_elementalEstride"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>)
 ! CHECK:           %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[DSCOPE]] arg {{[0-9]+}} {uniq_name = "_QFtest_as_strided_elementalEub"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>)
-! CHECK:           %[[VAL_6:.*]] = arith.constant 0 : i64
 ! CHECK:           %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<i64>
 ! CHECK:           %[[VAL_8:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i64>
 ! CHECK:           %[[VAL_9:.*]] = arith.subi %[[VAL_7]], %[[VAL_8]] : i64
@@ -55,8 +54,7 @@ subroutine test_as_strided_elemental(lb, ub, stride)
 ! CHECK:           %[[VAL_13:.*]] = arith.divsi %[[VAL_11]], %[[VAL_12]] : i64
 ! CHECK:           %[[VAL_14:.*]] = arith.constant 0 : i64
 ! CHECK:           %[[VAL_16:.*]] = arith.maxsi %[[VAL_13]], %[[VAL_14]] : i64
-! CHECK:           %[[VAL_17:.*]] = arith.addi %[[VAL_6]], %[[VAL_16]] : i64
-! CHECK:           %[[VAL_18:.*]] = fir.convert %[[VAL_17]] : (i64) -> index
+! CHECK:           %[[VAL_18:.*]] = fir.convert %[[VAL_16]] : (i64) -> index
 ! CHECK:           %[[VAL_19:.*]] = fir.shape %[[VAL_18]] : (index) -> !fir.shape<1>
 ! CHECK:           %[[VAL_20:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i64>
 ! CHECK:           %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (i64) -> index

diff  --git a/flang/test/Lower/HLFIR/array-ctor-as-inlined-temp.f90 b/flang/test/Lower/HLFIR/array-ctor-as-inlined-temp.f90
index 6f300b8dfaa43..f7b3020b34717 100644
--- a/flang/test/Lower/HLFIR/array-ctor-as-inlined-temp.f90
+++ b/flang/test/Lower/HLFIR/array-ctor-as-inlined-temp.f90
@@ -115,7 +115,6 @@ subroutine test_implied_do(n)
 ! CHECK-SAME:                                  %[[VAL_0:.*]]: !fir.ref<i64> {fir.bindc_name = "n"}) {
 ! CHECK:           %[[VAL_1:.*]] = fir.alloca index
 ! CHECK:           %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_implied_doEn"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>)
-! CHECK:           %[[VAL_3:.*]] = arith.constant 0 : i64
 ! CHECK:           %[[VAL_4:.*]] = arith.constant 2 : i64
 ! CHECK:           %[[VAL_5:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<i64>
 ! CHECK:           %[[VAL_6:.*]] = arith.constant 1 : i64
@@ -127,8 +126,7 @@ subroutine test_implied_do(n)
 ! CHECK:           %[[VAL_12:.*]] = arith.constant 0 : i64
 ! CHECK:           %[[VAL_14:.*]] = arith.maxsi %[[VAL_11]], %[[VAL_12]] : i64
 ! CHECK:           %[[VAL_15:.*]] = arith.muli %[[VAL_4]], %[[VAL_14]] : i64
-! CHECK:           %[[VAL_16:.*]] = arith.addi %[[VAL_3]], %[[VAL_15]] : i64
-! CHECK:           %[[VAL_17:.*]] = fir.convert %[[VAL_16]] : (i64) -> index
+! CHECK:           %[[VAL_17:.*]] = fir.convert %[[VAL_15]] : (i64) -> index
 ! CHECK:           %[[VAL_18:.*]] = arith.constant 1 : index
 ! CHECK:           %[[VAL_18B:.*]] = arith.constant 1 : index
 ! CHECK:           fir.store %[[VAL_18]] to %[[VAL_1]] : !fir.ref<index>
@@ -178,7 +176,6 @@ subroutine test_strided_implied_do(lb, ub, stride)
 ! CHECK:           %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_strided_implied_doElb"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>)
 ! CHECK:           %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_strided_implied_doEstride"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>)
 ! CHECK:           %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_strided_implied_doEub"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>)
-! CHECK:           %[[VAL_7:.*]] = arith.constant 0 : i64
 ! CHECK:           %[[VAL_8:.*]] = arith.constant 2 : i64
 ! CHECK:           %[[VAL_9:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<i64>
 ! CHECK:           %[[VAL_10:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<i64>
@@ -190,8 +187,7 @@ subroutine test_strided_implied_do(lb, ub, stride)
 ! CHECK:           %[[VAL_16:.*]] = arith.constant 0 : i64
 ! CHECK:           %[[VAL_18:.*]] = arith.maxsi %[[VAL_15]], %[[VAL_16]] : i64
 ! CHECK:           %[[VAL_19:.*]] = arith.muli %[[VAL_8]], %[[VAL_18]] : i64
-! CHECK:           %[[VAL_20:.*]] = arith.addi %[[VAL_7]], %[[VAL_19]] : i64
-! CHECK:           %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (i64) -> index
+! CHECK:           %[[VAL_21:.*]] = fir.convert %[[VAL_19]] : (i64) -> index
 ! CHECK:           %[[VAL_22:.*]] = arith.constant 1 : index
 ! CHECK:           %[[VAL_22B:.*]] = arith.constant 1 : index
 ! CHECK:           fir.store %[[VAL_22]] to %[[VAL_3]] : !fir.ref<index>
@@ -239,8 +235,6 @@ subroutine test_nested_implied_do(n, m)
 ! CHECK:           %[[VAL_2:.*]] = fir.alloca index
 ! CHECK:           %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_nested_implied_doEm"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>)
 ! CHECK:           %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} arg {{[0-9]+}} {uniq_name = "_QFtest_nested_implied_doEn"} : (!fir.ref<i64>, !fir.dscope) -> (!fir.ref<i64>, !fir.ref<i64>)
-! CHECK:           %[[VAL_5:.*]] = arith.constant 0 : i64
-! CHECK:           %[[VAL_6:.*]] = arith.constant 0 : i64
 ! CHECK:           %[[VAL_7:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i64>
 ! CHECK:           %[[VAL_8:.*]] = arith.constant 1 : i64
 ! CHECK:           %[[VAL_9:.*]] = arith.subi %[[VAL_7]], %[[VAL_8]] : i64
@@ -250,7 +244,6 @@ subroutine test_nested_implied_do(n, m)
 ! CHECK:           %[[VAL_13:.*]] = arith.divsi %[[VAL_11]], %[[VAL_12]] : i64
 ! CHECK:           %[[VAL_14:.*]] = arith.constant 0 : i64
 ! CHECK:           %[[VAL_16:.*]] = arith.maxsi %[[VAL_13]], %[[VAL_14]] : i64
-! CHECK:           %[[VAL_17:.*]] = arith.addi %[[VAL_6]], %[[VAL_16]] : i64
 ! CHECK:           %[[VAL_18:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<i64>
 ! CHECK:           %[[VAL_19:.*]] = arith.constant 1 : i64
 ! CHECK:           %[[VAL_20:.*]] = arith.subi %[[VAL_18]], %[[VAL_19]] : i64
@@ -260,9 +253,8 @@ subroutine test_nested_implied_do(n, m)
 ! CHECK:           %[[VAL_24:.*]] = arith.divsi %[[VAL_22]], %[[VAL_23]] : i64
 ! CHECK:           %[[VAL_25:.*]] = arith.constant 0 : i64
 ! CHECK:           %[[VAL_27:.*]] = arith.maxsi %[[VAL_24]], %[[VAL_25]] : i64
-! CHECK:           %[[VAL_28:.*]] = arith.muli %[[VAL_17]], %[[VAL_27]] : i64
-! CHECK:           %[[VAL_29:.*]] = arith.addi %[[VAL_5]], %[[VAL_28]] : i64
-! CHECK:           %[[VAL_30:.*]] = fir.convert %[[VAL_29]] : (i64) -> index
+! CHECK:           %[[VAL_28:.*]] = arith.muli %[[VAL_16]], %[[VAL_27]] : i64
+! CHECK:           %[[VAL_30:.*]] = fir.convert %[[VAL_28]] : (i64) -> index
 ! CHECK:           %[[VAL_31:.*]] = arith.constant 1 : index
 ! CHECK:           %[[VAL_31B:.*]] = arith.constant 1 : index
 ! CHECK:           fir.store %[[VAL_31]] to %[[VAL_2]] : !fir.ref<index>

diff  --git a/flang/test/Lower/HLFIR/array-ctor-as-runtime-temp.f90 b/flang/test/Lower/HLFIR/array-ctor-as-runtime-temp.f90
index 704245caf3d6d..c9248a63e3863 100644
--- a/flang/test/Lower/HLFIR/array-ctor-as-runtime-temp.f90
+++ b/flang/test/Lower/HLFIR/array-ctor-as-runtime-temp.f90
@@ -66,7 +66,6 @@ subroutine test_arrays(a)
 ! CHECK:  %[[VAL_1:.*]] = fir.alloca !fir.array<10xi64> {bindc_name = ".rt.arrayctor.vector"}
 ! CHECK:  %[[VAL_2:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>> {bindc_name = ".tmp.arrayctor"}
 ! CHECK:  %[[VAL_3:.*]]:2 = hlfir.declare {{.*}}Ea"
-! CHECK:  %[[VAL_4:.*]] = arith.constant 0 : i64
 ! CHECK:  %[[VAL_5:.*]] = arith.constant 0 : index
 ! CHECK:  %[[VAL_6:.*]]:3 = fir.box_dims %[[VAL_3]]#0, %[[VAL_5]] : (!fir.box<!fir.array<?x?xi32>>, index) -> (index, index, index)
 ! CHECK:  %[[VAL_7:.*]] = fir.convert %[[VAL_6]]#1 : (index) -> i64
@@ -74,8 +73,7 @@ subroutine test_arrays(a)
 ! CHECK:  %[[VAL_9:.*]]:3 = fir.box_dims %[[VAL_3]]#0, %[[VAL_8]] : (!fir.box<!fir.array<?x?xi32>>, index) -> (index, index, index)
 ! CHECK:  %[[VAL_10:.*]] = fir.convert %[[VAL_9]]#1 : (index) -> i64
 ! CHECK:  %[[VAL_11:.*]] = arith.muli %[[VAL_7]], %[[VAL_10]] : i64
-! CHECK:  %[[VAL_12:.*]] = arith.addi %[[VAL_4]], %[[VAL_11]] : i64
-! CHECK:  %[[VAL_20:.*]] = arith.addi %[[VAL_12]], %{{.*}} : i64
+! CHECK:  %[[VAL_20:.*]] = arith.addi %[[VAL_11]], %{{.*}} : i64
 ! CHECK:  %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (i64) -> index
 ! CHECK:  %[[VAL_22:.*]] = fir.allocmem !fir.array<?xi32>, %[[VAL_21]] {bindc_name = ".tmp.arrayctor", uniq_name = ""}
 ! CHECK:  %[[VAL_23:.*]] = fir.shape %[[VAL_21]] : (index) -> !fir.shape<1>


        


More information about the flang-commits mailing list