From: Michiel Derhaeg <[email protected]>

CLZ_DEFINED_VALUE_AT_ZERO and CTZ_DEFINED_VALUE_AT_ZERO advertises
clz(0) == 31 && ctz(0) == 31. This is true for ARCv2 but not for
ARCompact. The latter previously produced 32.

Updated the non-V2 fallback code to produce the same result for zero
inputs as this change does not come at any cost.

        PR target/127117

gcc/ChangeLog:

        * config/arc/arc.md (*arc_clzsi2): Produce 31 rather than 32 for
        a zero operand.
        (arc_ctzsi2): Likewise.

gcc/testsuite/ChangeLog:

        * gcc.target/arc/arc.exp (check_effective_target_norm): New.
        * gcc.target/arc/pr127117.c: New test.

Co-authored-by: Luis Silva <[email protected]>
Signed-off-by: Michiel Derhaeg <[email protected]>
---
Changes since v1:
Luis fixed the test by replacing -mnorm with dg-require-effective-target norm

 gcc/config/arc/arc.md                   |  4 +--
 gcc/testsuite/gcc.target/arc/arc.exp    |  9 +++++++
 gcc/testsuite/gcc.target/arc/pr127117.c | 35 +++++++++++++++++++++++++
 3 files changed, 46 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/arc/pr127117.c

diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
index b4b4a6a3e8e..ef1c0846f9f 100644
--- a/gcc/config/arc/arc.md
+++ b/gcc/config/arc/arc.md
@@ -4600,7 +4600,7 @@ archs4x, archs4xd"
   emit_insn
     (gen_rtx_COND_EXEC
       (VOIDmode,
-       gen_rtx_GE (VOIDmode, gen_rtx_REG (CC_ZNmode, CC_REG), const0_rtx),
+       gen_rtx_GT (VOIDmode, gen_rtx_REG (CC_ZNmode, CC_REG), const0_rtx),
        gen_rtx_SET (operands[0], plus_constant (SImode, operands[0], 1))));
   DONE;
 }
@@ -4645,7 +4645,7 @@ archs4x, archs4xd"
     (gen_rtx_COND_EXEC
       (VOIDmode,
        gen_rtx_LT (VOIDmode, gen_rtx_REG (CC_ZNmode, CC_REG), const0_rtx),
-       gen_rtx_SET (operands[0], GEN_INT (32))));
+       gen_rtx_SET (operands[0], GEN_INT (31))));
   emit_insn
     (gen_rtx_COND_EXEC
       (VOIDmode,
diff --git a/gcc/testsuite/gcc.target/arc/arc.exp 
b/gcc/testsuite/gcc.target/arc/arc.exp
index e50db2b6478..34e210b068b 100644
--- a/gcc/testsuite/gcc.target/arc/arc.exp
+++ b/gcc/testsuite/gcc.target/arc/arc.exp
@@ -94,6 +94,15 @@ proc check_effective_target_barrelshifter { } {
     }]
 }
 
+# Return 1 if norm is enabled by default.
+proc check_effective_target_norm { } {
+    return [check_no_compiler_messages norm_default assembly {
+       #if !defined(__ARC_NORM__)
+       #error No default norm instruction
+       #endif
+    }]
+}
+
 #return 1 if we have code density option on.
 proc check_effective_target_codedensity { } {
     return [check_no_compiler_messages codedensity assembly {
diff --git a/gcc/testsuite/gcc.target/arc/pr127117.c 
b/gcc/testsuite/gcc.target/arc/pr127117.c
new file mode 100644
index 00000000000..56dd4bbff28
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/pr127117.c
@@ -0,0 +1,35 @@
+/* { dg-do run } */
+/* { dg-require-effective-target norm } */
+/* { dg-options "-O2" } */
+
+unsigned __attribute__ ((noipa))
+clz (unsigned x)
+{
+  return __builtin_clz (x);
+}
+
+unsigned __attribute__ ((noipa))
+ctz (unsigned x)
+{
+  return __builtin_ctz (x);
+}
+
+int
+main (void)
+{
+  unsigned msb, lsb;
+
+  if (clz (0) != 31 || ctz (0) != 31)
+    __builtin_abort ();
+
+  for (msb = 0; msb < 32; msb++)
+    for (lsb = 0; lsb <= msb; lsb++)
+      {
+       unsigned v = (1u << msb) | (1u << lsb);
+
+       if (clz (v) != 31 - msb || ctz (v) != lsb)
+         __builtin_abort ();
+      }
+
+  return 0;
+}
-- 
2.47.3

Reply via email to