From: Michiel Derhaeg <[email protected]>
CLZ_DEFINED_VALUE_AT_ZERO and CTZ_DEFINED_VALUE_AT_ZERO advertise
clz(0) == 31 and ctz(0) == 31. When clzsi2 and ctzsi2 expand to the
ARCv2 fls and ffs instructions that holds.
Both patterns can also be emulated with norm, which currently happens
for ARCompact, in that case it returns 32 for a zero operand.
Correct the two emulation patterns. In *arc_clzsi2 only increment
the norm result when the operand is strictly positive, which leaves a
zero operand at norm's own result of 31. In arc_ctzsi2 produce 31
instead of 32 on the negative-flag path that a zero operand takes.
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
Changes since v2:
Improved commit message.
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