From: Roger Sayle Date: Mon, 13 Nov 2023 09:11:42 +0000 (+0000) Subject: ARC: Provide a TARGET_FOLD_BUILTIN target hook. X-Git-Tag: basepoints/gcc-15~4753 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e9d59a2a5a8e8ce667847372cc480215fa862aa4;p=thirdparty%2Fgcc.git 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 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. --- diff --git a/gcc/config/arc/arc.cc b/gcc/config/arc/arc.cc index e209ad2d327e..70ee41082887 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 77029783a2a4..8c121cddd6e6 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 fc5c92b2986f..deb5f73067c1 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 000000000000..7cb7e98ef36c --- /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 000000000000..d90128b8ed1a --- /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 000000000000..f7b46f31b4ab --- /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 000000000000..bb37c845d3da --- /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 000000000000..5421e26bbdce --- /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 000000000000..9c2f24a0300a --- /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 000000000000..14a30720b118 --- /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" } } */