]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Match: Optimize log (x) CMP CST and exp (x) CMP CST operations
authorSoumya AR <soumyaa@nvidia.com>
Tue, 12 Nov 2024 03:56:24 +0000 (09:26 +0530)
committerSoumya AR <soumyaa@nvidia.com>
Tue, 12 Nov 2024 04:00:33 +0000 (09:30 +0530)
This patch implements transformations for the following optimizations.

logN(x) CMP CST -> x CMP expN(CST)
expN(x) CMP CST -> x CMP logN(CST)

Where CMP expands to ge and le operations.

For example:

int
foo (float x)
{
  return __builtin_logf (x) <= 0.0f;
}

can just be:

int
foo (float x)
{
  return x <= 1.0f;
}

The patch was bootstrapped and regtested on aarch64-linux-gnu, no regression.
OK for mainline?

Signed-off-by: Soumya AR <soumyaa@nvidia.com>
gcc/ChangeLog:

* match.pd: Fold logN(x) CMP CST -> x CMP expN(CST)
and expN(x) CMP CST -> x CMP logN(CST)

gcc/testsuite/ChangeLog:

* gcc.dg/tree-ssa/log_exp.c: New test.

gcc/match.pd
gcc/testsuite/gcc.dg/tree-ssa/log_exp.c [new file with mode: 0644]

index 00988241348a43dc50ded91c9164e0ec72fa2b52..fc33b9ac3b1b33d5f488f57b49c6cf90f6a530a4 100644 (file)
@@ -8347,7 +8347,20 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
    /* Simplify logN(a)-logN(b) into logN(a/b).  */
    (simplify
     (minus (logs:s @0) (logs:s @1))
-     (logs (rdiv @0 @1)))))
+     (logs (rdiv @0 @1))))
+
+   (for cmp (le ge)
+    (for logs (LOG LOG2 LOG10)
+        exps (EXP EXP2 EXP10)
+    /* Simplify logN (x) CMP CST into x CMP expN (CST) */
+    (simplify
+    (cmp:c (logs:s @0) REAL_CST@1)
+     (cmp @0 (exps @1)))
+
+    /* Simplify expN (x) CMP CST into x CMP logN (CST) */
+    (simplify
+    (cmp:c (exps:s @0) REAL_CST@1)
+     (cmp @0 (logs @1))))))
 
  (for logs (LOG LOG2 LOG10 LOG10)
       exps (EXP EXP2 EXP10 POW10)
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/log_exp.c b/gcc/testsuite/gcc.dg/tree-ssa/log_exp.c
new file mode 100644 (file)
index 0000000..1c5d967
--- /dev/null
@@ -0,0 +1,40 @@
+/* { dg-do link } */
+/* { dg-options "-O2 -ffast-math" } */
+/* { dg-require-effective-target c99_runtime } */
+
+#include <stdbool.h>
+
+extern void link_error(void);
+
+#define T(FUNC1, FUNC2, CMP, TYPE, C_TY, ID)                       \
+void test_##FUNC1##_##FUNC2##_##ID (TYPE x)                        \
+{                                                                  \
+  TYPE a = 10.0##C_TY;                                             \
+  TYPE t1 = __builtin_##FUNC1(x);                                  \
+  bool b1 = t1 CMP a;                                              \
+  TYPE t2 = __builtin_##FUNC2(a);                                  \
+  bool b2 = x CMP t2;                                              \
+  if (b1 != b2)                                                    \
+    link_error();                                                  \
+}
+
+#define TEST(FUNC1, FUNC2, TYPE, C_TY)                             \
+  T(FUNC1, FUNC2, <=, TYPE, C_TY, 1)                               \
+  T(FUNC1, FUNC2, >=, TYPE, C_TY, 2)                               \
+
+#define TEST_ALL(TYPE, C_TY, F_TY)                                  \
+  TEST(exp##F_TY, log##F_TY, TYPE, C_TY)                             \
+  TEST(exp2##F_TY, log2##F_TY, TYPE, C_TY)                           \
+  TEST(exp10##F_TY, log10##F_TY, TYPE, C_TY)                         \
+  TEST(log##F_TY, exp##F_TY, TYPE, C_TY)                             \
+  TEST(log2##F_TY, exp2##F_TY, TYPE, C_TY)                           \
+  TEST(log10##F_TY, exp10##F_TY, TYPE, C_TY)
+
+TEST_ALL(double, , )
+TEST_ALL(float, f, f)
+TEST_ALL(long double, L, l)
+
+int main (void)
+{
+  return 0;
+}