I've implemented the standard pattern ffs, which leads to
__builtin_ffs being generated with 4 instructions instead
of 5 instructions.
Regression tests and my new test pass.
OK to commit?
Cheers,
Ian
2012-09-14 Ian Bolton <ian.bol...@arm.com>
gcc/
* config/aarch64/aarch64.md (csinc3<mode>): Make it into a
named pattern.
* config/aarch64/aarch64.md (ffs<mode>2): New pattern.
testsuite/
* gcc.target/aarch64/ffs.c: New test.
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 5278957..dfdba42 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -2021,7 +2021,7 @@
[(set_attr "v8type" "csel")
(set_attr "mode" "<MODE>")])
-(define_insn "*csinc3<mode>_insn"
+(define_insn "csinc3<mode>_insn"
[(set (match_operand:GPI 0 "register_operand" "=r")
(if_then_else:GPI
(match_operator:GPI 1 "aarch64_comparison_operator"
@@ -2157,6 +2157,21 @@
}
)
+(define_expand "ffs<mode>2"
+ [(match_operand:GPI 0 "register_operand")
+ (match_operand:GPI 1 "register_operand")]
+ ""
+ {
+ rtx ccreg = aarch64_gen_compare_reg (EQ, operands[1], const0_rtx);
+ rtx x = gen_rtx_NE (VOIDmode, ccreg, const0_rtx);
+
+ emit_insn (gen_rbit<mode>2 (operands[0], operands[1]));
+ emit_insn (gen_clz<mode>2 (operands[0], operands[0]));
+ emit_insn (gen_csinc3<mode>_insn (operands[0], x, ccreg, operands[0],
const0_rtx));
+ DONE;
+ }
+)
+
(define_insn "*and<mode>3nr_compare0"
[(set (reg:CC CC_REGNUM)
(compare:CC
diff --git a/gcc/testsuite/gcc.target/aarch64/ffs.c
b/gcc/testsuite/gcc.target/aarch64/ffs.c
new file mode 100644
index 0000000..a344761
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/ffs.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+unsigned int functest(unsigned int x)
+{
+ return __builtin_ffs(x);
+}
+
+/* { dg-final { scan-assembler "cmp\tw" } } */
+/* { dg-final { scan-assembler "rbit\tw" } } */
+/* { dg-final { scan-assembler "clz\tw" } } */
+/* { dg-final { scan-assembler "csinc\tw" } } */