@@ -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. */
@@ -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
@@ -4355,8 +4354,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")])
@@ -4453,18 +4452,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")
@@ -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. */
new file mode 100644
@@ -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" } } */
new file mode 100644
@@ -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" } } */
new file mode 100644
@@ -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" } } */
new file mode 100644
@@ -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" } } */
new file mode 100644
@@ -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" } } */
new file mode 100644
@@ -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" } } */
new file mode 100644
@@ -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" } } */