aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Sayle <roger@nextmovesoftware.com>2023-11-13 09:11:42 +0000
committerRoger Sayle <roger@nextmovesoftware.com>2023-11-13 09:11:42 +0000
commite9d59a2a5a8e8ce667847372cc480215fa862aa4 (patch)
treec7ec6f4663a575f1c94651e4bdbe34b689550fba
parent0a140730c970870a5125beb1114f6c01679a040e (diff)
downloadgcc-e9d59a2a5a8e8ce667847372cc480215fa862aa4.zip
gcc-e9d59a2a5a8e8ce667847372cc480215fa862aa4.tar.gz
gcc-e9d59a2a5a8e8ce667847372cc480215fa862aa4.tar.bz2
ARC: Provide a TARGET_FOLD_BUILTIN target hook.
This patch implements a arc_fold_builtin target hook to allow ARC builtins to be folded at the tree-level. Currently this function converts __builtin_arc_swap into a LROTATE_EXPR at the tree-level, and evaluates __builtin_arc_norm and __builtin_arc_normw of integer constant arguments at compile-time. Because ARC_BUILTIIN_SWAP is now handled at the tree-level, UNSPEC_ARC_SWAP no longer used, allowing it and the "swap" define_insn to be removed. An example benefit of folding things at compile-time is that calling __builtin_arc_swap on the result of __builtin_arc_swap now eliminates both and generates no code, and likewise calling __builtin_arc_swap of a constant integer argument is evaluated at compile-time. 2023-11-13 Roger Sayle <roger@nextmovesoftware.com> gcc/ChangeLog * config/arc/arc.cc (TARGET_FOLD_BUILTIN): Define to arc_fold_builtin. (arc_fold_builtin): New function. Convert ARC_BUILTIN_SWAP into a rotate. Evaluate ARC_BUILTIN_NORM and ARC_BUILTIN_NORMW of constant arguments. * config/arc/arc.md (UNSPEC_ARC_SWAP): Delete. (normw): Make output template/assembler whitespace consistent. (swap): Remove define_insn, only use of SWAP UNSPEC. * config/arc/builtins.def: Tweak indentation. (SWAP): Expand using rotlsi2_cnt16 instead of using swap. gcc/testsuite/ChangeLog * gcc.target/arc/builtin_norm-1.c: New test case. * gcc.target/arc/builtin_norm-2.c: Likewise. * gcc.target/arc/builtin_normw-1.c: Likewise. * gcc.target/arc/builtin_normw-2.c: Likewise. * gcc.target/arc/builtin_swap-1.c: Likewise. * gcc.target/arc/builtin_swap-2.c: Likewise. * gcc.target/arc/builtin_swap-3.c: Likewise.
-rw-r--r--gcc/config/arc/arc.cc43
-rw-r--r--gcc/config/arc/arc.md17
-rw-r--r--gcc/config/arc/builtins.def16
-rw-r--r--gcc/testsuite/gcc.target/arc/builtin_norm-1.c9
-rw-r--r--gcc/testsuite/gcc.target/arc/builtin_norm-2.c10
-rw-r--r--gcc/testsuite/gcc.target/arc/builtin_normw-1.c9
-rw-r--r--gcc/testsuite/gcc.target/arc/builtin_normw-2.c10
-rw-r--r--gcc/testsuite/gcc.target/arc/builtin_swap-1.c9
-rw-r--r--gcc/testsuite/gcc.target/arc/builtin_swap-2.c9
-rw-r--r--gcc/testsuite/gcc.target/arc/builtin_swap-3.c10
10 files changed, 119 insertions, 23 deletions
diff --git a/gcc/config/arc/arc.cc b/gcc/config/arc/arc.cc
index e209ad2..70ee410 100644
--- a/gcc/config/arc/arc.cc
+++ b/gcc/config/arc/arc.cc
@@ -643,6 +643,9 @@ static rtx arc_legitimize_address_0 (rtx, rtx, machine_mode mode);
#undef TARGET_EXPAND_BUILTIN
#define TARGET_EXPAND_BUILTIN arc_expand_builtin
+#undef TARGET_FOLD_BUILTIN
+#define TARGET_FOLD_BUILTIN arc_fold_builtin
+
#undef TARGET_BUILTIN_DECL
#define TARGET_BUILTIN_DECL arc_builtin_decl
@@ -7048,6 +7051,46 @@ arc_expand_builtin (tree exp,
return const0_rtx;
}
+/* Implement TARGET_FOLD_BUILTIN. */
+
+static tree
+arc_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *arg,
+ bool ignore ATTRIBUTE_UNUSED)
+{
+ unsigned int fcode = DECL_MD_FUNCTION_CODE (fndecl);
+
+ switch (fcode)
+ {
+ default:
+ break;
+
+ case ARC_BUILTIN_SWAP:
+ return fold_build2 (LROTATE_EXPR, integer_type_node, arg[0],
+ build_int_cst (integer_type_node, 16));
+
+ case ARC_BUILTIN_NORM:
+ if (TREE_CODE (arg[0]) == INTEGER_CST
+ && !TREE_OVERFLOW (arg[0]))
+ {
+ wide_int arg0 = wi::to_wide (arg[0], 32);
+ wide_int result = wi::shwi (wi::clrsb (arg0), 32);
+ return wide_int_to_tree (integer_type_node, result);
+ }
+ break;
+
+ case ARC_BUILTIN_NORMW:
+ if (TREE_CODE (arg[0]) == INTEGER_CST
+ && !TREE_OVERFLOW (arg[0]))
+ {
+ wide_int arg0 = wi::to_wide (arg[0], 16);
+ wide_int result = wi::shwi (wi::clrsb (arg0), 32);
+ return wide_int_to_tree (integer_type_node, result);
+ }
+ break;
+ }
+ return NULL_TREE;
+}
+
/* Returns true if the operands[opno] is a valid compile-time constant to be
used as register number in the code for builtins. Else it flags an error
and returns false. */
diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
index 7702978..8c121cd 100644
--- a/gcc/config/arc/arc.md
+++ b/gcc/config/arc/arc.md
@@ -116,7 +116,6 @@
UNSPEC_TLS_OFF
UNSPEC_ARC_NORM
UNSPEC_ARC_NORMW
- UNSPEC_ARC_SWAP
UNSPEC_ARC_DIVAW
UNSPEC_ARC_DIRECT
UNSPEC_ARC_LP
@@ -4392,8 +4391,8 @@ archs4x, archs4xd"
(clrsb:HI (match_operand:HI 1 "general_operand" "cL,Cal"))))]
"TARGET_NORM"
"@
- norm%_ \t%0, %1
- norm%_ \t%0, %1"
+ norm%_\\t%0,%1
+ norm%_\\t%0,%1"
[(set_attr "length" "4,8")
(set_attr "type" "two_cycle_core,two_cycle_core")])
@@ -4490,18 +4489,6 @@ archs4x, archs4xd"
[(set_attr "type" "unary")
(set_attr "length" "20")])
-(define_insn "swap"
- [(set (match_operand:SI 0 "dest_reg_operand" "=w,w,w")
- (unspec:SI [(match_operand:SI 1 "general_operand" "L,Cal,c")]
- UNSPEC_ARC_SWAP))]
- "TARGET_SWAP"
- "@
- swap \t%0, %1
- swap \t%0, %1
- swap \t%0, %1"
- [(set_attr "length" "4,8,4")
- (set_attr "type" "two_cycle_core,two_cycle_core,two_cycle_core")])
-
(define_insn "divaw"
[(set (match_operand:SI 0 "dest_reg_operand" "=&w,&w,&w")
(unspec:SI [(div:SI (match_operand:SI 1 "general_operand" "r,Cal,r")
diff --git a/gcc/config/arc/builtins.def b/gcc/config/arc/builtins.def
index fc5c92b..deb5f73 100644
--- a/gcc/config/arc/builtins.def
+++ b/gcc/config/arc/builtins.def
@@ -50,14 +50,14 @@ DEF_BUILTIN (CORE_WRITE, 2, void_ftype_usint_usint, core_write, 1)
DEF_BUILTIN (SETI, 1, void_ftype_int, seti, TARGET_V2)
/* Regular builtins. */
-DEF_BUILTIN (NORM, 1, int_ftype_int, clrsbsi2, TARGET_NORM)
-DEF_BUILTIN (NORMW, 1, int_ftype_short, normw, TARGET_NORM)
-DEF_BUILTIN (SWAP, 1, int_ftype_int, swap, TARGET_SWAP)
-DEF_BUILTIN (DIVAW, 2, int_ftype_int_int, divaw, TARGET_EA_SET)
-DEF_BUILTIN (CORE_READ, 1, usint_ftype_usint, core_read, 1)
-DEF_BUILTIN (LR, 1, usint_ftype_usint, lr, 1)
-DEF_BUILTIN (FFS, 1, int_ftype_int, ffs, (TARGET_EM && TARGET_NORM) || TARGET_HS)
-DEF_BUILTIN (FLS, 1, int_ftype_int, fls, (TARGET_EM && TARGET_NORM) || TARGET_HS)
+DEF_BUILTIN (NORM, 1, int_ftype_int, clrsbsi2, TARGET_NORM)
+DEF_BUILTIN (NORMW, 1, int_ftype_short, normw, TARGET_NORM)
+DEF_BUILTIN (SWAP, 1, int_ftype_int, rotlsi2_cnt16, TARGET_SWAP)
+DEF_BUILTIN (DIVAW, 2, int_ftype_int_int, divaw, TARGET_EA_SET)
+DEF_BUILTIN (CORE_READ, 1, usint_ftype_usint, core_read, 1)
+DEF_BUILTIN (LR, 1, usint_ftype_usint, lr, 1)
+DEF_BUILTIN (FFS, 1, int_ftype_int, ffs, (TARGET_EM && TARGET_NORM) || TARGET_HS)
+DEF_BUILTIN (FLS, 1, int_ftype_int, fls, (TARGET_EM && TARGET_NORM) || TARGET_HS)
/* ARC SIMD extenssion. */
/* BEGIN SIMD marker. */
diff --git a/gcc/testsuite/gcc.target/arc/builtin_norm-1.c b/gcc/testsuite/gcc.target/arc/builtin_norm-1.c
new file mode 100644
index 0000000..7cb7e98
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/builtin_norm-1.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mnorm" } */
+
+int foo(int x)
+{
+ return __builtin_arc_norm (x);
+}
+
+/* { dg-final { scan-assembler "norm\\s+r0,r0" } } */
diff --git a/gcc/testsuite/gcc.target/arc/builtin_norm-2.c b/gcc/testsuite/gcc.target/arc/builtin_norm-2.c
new file mode 100644
index 0000000..d90128b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/builtin_norm-2.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mnorm" } */
+
+int foo()
+{
+ return __builtin_arc_norm (255);
+}
+
+/* { dg-final { scan-assembler-not "norm\\s+r0,r0" } } */
+/* { dg-final { scan-assembler "mov_s\\s+r0,23" } } */
diff --git a/gcc/testsuite/gcc.target/arc/builtin_normw-1.c b/gcc/testsuite/gcc.target/arc/builtin_normw-1.c
new file mode 100644
index 0000000..f7b46f3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/builtin_normw-1.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mnorm" } */
+
+int foo(short x)
+{
+ return __builtin_arc_normw (x);
+}
+
+/* { dg-final { scan-assembler "normh\\s+r0, ?r0" } } */
diff --git a/gcc/testsuite/gcc.target/arc/builtin_normw-2.c b/gcc/testsuite/gcc.target/arc/builtin_normw-2.c
new file mode 100644
index 0000000..bb37c84
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/builtin_normw-2.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mnorm" } */
+
+int foo()
+{
+ return __builtin_arc_normw (255);
+}
+
+/* { dg-final { scan-assembler-not "normh\\s+r" } } */
+/* { dg-final { scan-assembler "mov_s\\s+r0,7" } } */
diff --git a/gcc/testsuite/gcc.target/arc/builtin_swap-1.c b/gcc/testsuite/gcc.target/arc/builtin_swap-1.c
new file mode 100644
index 0000000..5421e26
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/builtin_swap-1.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mswap" } */
+
+int foo(int x)
+{
+ return __builtin_arc_swap (x);
+}
+
+/* { dg-final { scan-assembler "swap\\s+r0,r0" } } */
diff --git a/gcc/testsuite/gcc.target/arc/builtin_swap-2.c b/gcc/testsuite/gcc.target/arc/builtin_swap-2.c
new file mode 100644
index 0000000..9c2f24a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/builtin_swap-2.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mswap" } */
+
+int foo()
+{
+ return __builtin_arc_swap (0x12345678);
+}
+
+/* { dg-final { scan-assembler-not "swap\\s+r" } } */
diff --git a/gcc/testsuite/gcc.target/arc/builtin_swap-3.c b/gcc/testsuite/gcc.target/arc/builtin_swap-3.c
new file mode 100644
index 0000000..14a3072
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/builtin_swap-3.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mswap" } */
+
+int foo(int x)
+{
+ int t = __builtin_arc_swap (x);
+ return __builtin_arc_swap (t);
+}
+
+/* { dg-final { scan-assembler-not "swap\\s+r" } } */