[PATCH, ARM] Generate usat/ssat instructions

2012-02-29 Thread Ulrich Weigand
Hello,

this patch adds support for generating usat/ssat instructions to match code
along the lines of:

  if  (a  amin) return amin;
  else if (a  amax) return amax;
  else   return a;

for appropriate values of amin/amax.  This type code actually occurs in
real-life code (e.g. codecs).

Above code is already translated into a sequence of SMIN/SMAX RTX
operations by expand.  The combine pass is able to fold those into
a single RTX pattern, so we only need to make such patterns available
to match the instruction.  Note that usat/ssat may in addition shift
their input operand; this is also supported by the patch.

There are already pre-existing patterns that use usat/ssat to
implement us_truncate/ss_truncate.  Those represent special
cases of the general instructions, and are left in place by
this patch.  (However, some minor fixes e.g. to the sat_shift_operator
predicate and insn attributes apply to those patterns too.)

Tested on arm-linux-gnueabi with no regressions.

OK for 4.8?

Bye,
Ulrich


ChangeLog:

gcc/
* config/arm/arm.c (arm_sat_operator_match): New function.
* config/arm/arm-protos.h (arm_sat_operator_match): Add prototype.
* config/arm/arm.md (insn attribute): Add sat value.
(SAT, SATrev): New code iterators.
(SATlo, SAThi): New code iterator attributes.
(*satsi_SAT:code): New pattern.
(*satsi_SAT:code_shift): Likewise.
* config/arm/arm-fixed.md (arm_ssatsihi_shift): Add insn
and shift attributes.
(arm_usatsihi): Add insn attribute.
* config/arm/predicates.md (sat_shift_operator): Allow multiplication
by powers of two.  Do not allow shift by 32.

gcc/testsuite/
* gcc.target/arm/sat-1.c: New test.


Index: gcc/testsuite/gcc.target/arm/sat-1.c
===
--- gcc/testsuite/gcc.target/arm/sat-1.c(revision 0)
+++ gcc/testsuite/gcc.target/arm/sat-1.c(revision 0)
@@ -0,0 +1,64 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_arm_ok } */
+/* { dg-require-effective-target arm_arch_v6_ok } */
+/* { dg-options -O2 -marm } */
+/* { dg-add-options arm_arch_v6 } */
+
+
+static inline int sat1 (int a, int amin, int amax)
+{
+  if  (a  amin) return amin;
+  else if (a  amax) return amax;
+  else   return a;
+}
+
+static inline int sat2 (int a, int amin, int amax)
+{
+  if  (a  amax) return amax;
+  else if (a  amin) return amin;
+  else   return a;
+}
+
+int u1 (int x)
+{
+  return sat1 (x, 0, 63);
+}
+
+int us1 (int x)
+{
+  return sat1 (x  5, 0, 63);
+}
+
+int s1 (int x)
+{
+  return sat1 (x, -64, 63);
+}
+
+int ss1 (int x)
+{
+  return sat1 (x  5, -64, 63);
+}
+
+int u2 (int x)
+{
+  return sat2 (x, 0, 63);
+}
+
+int us2 (int x)
+{
+  return sat2 (x  5, 0, 63);
+}
+
+int s2 (int x)
+{
+  return sat2 (x, -64, 63);
+}
+
+int ss2 (int x)
+{
+  return sat2 (x  5, -64, 63);
+}
+
+/* { dg-final { scan-assembler-times usat 4 } } */
+/* { dg-final { scan-assembler-times ssat 4 } } */
+
Index: gcc/config/arm/arm.c
===
--- gcc/config/arm/arm.c(revision 184553)
+++ gcc/config/arm/arm.c(working copy)
@@ -10041,6 +10041,42 @@
 }
 }
 
+/* Match pair of min/max operators that can be implemented via usat/ssat.  */
+
+bool
+arm_sat_operator_match (rtx lo_bound, rtx hi_bound,
+   int *mask, bool *signed_sat)
+{
+  /* The high bound must be a power of two minus one.  */
+  int log = exact_log2 (INTVAL (hi_bound) + 1);
+  if (log == -1)
+return false;
+
+  /* The low bound is either zero (for usat) or one less than the
+ negation of the high bound (for ssat).  */
+  if (INTVAL (lo_bound) == 0)
+{
+  if (mask)
+*mask = log;
+  if (signed_sat)
+*signed_sat = false;
+
+  return true;
+}
+
+  if (INTVAL (lo_bound) == -INTVAL (hi_bound) - 1)
+{
+  if (mask)
+*mask = log + 1;
+  if (signed_sat)
+*signed_sat = true;
+
+  return true;
+}
+
+  return false;
+}
+
 /* Return 1 if memory locations are adjacent.  */
 int
 adjacent_mem_locations (rtx a, rtx b)
Index: gcc/config/arm/arm-fixed.md
===
--- gcc/config/arm/arm-fixed.md (revision 184553)
+++ gcc/config/arm/arm-fixed.md (working copy)
@@ -374,6 +374,8 @@
   TARGET_32BIT  arm_arch6
   ssat%?\\t%0, #16, %2%S1
   [(set_attr predicable yes)
+   (set_attr insn sat)
+   (set_attr shift 1)
(set_attr type alu_shift)])
 
 (define_insn arm_usatsihi
@@ -381,4 +383,5 @@
(us_truncate:HI (match_operand:SI 1 s_register_operand)))]
   TARGET_INT_SIMD
   usat%?\\t%0, #16, %1
-  [(set_attr predicable yes)])
+  [(set_attr predicable yes)
+   (set_attr insn sat)])
Index: gcc/config/arm/arm-protos.h
===
--- 

Re: [PATCH, ARM] Generate usat/ssat instructions

2012-02-29 Thread Ramana Radhakrishnan
        (SAT, SATrev): New code iterators.
        (SATlo, SAThi): New code iterator attributes.
        (*satsi_SAT:code): New pattern.
        (*satsi_SAT:code_shift): Likewise.

Iterators must go into iterators.md.

Ok with that change for 4.8 if no regressions.

Ramana


Re: [PATCH, ARM] Generate usat/ssat instructions

2012-02-29 Thread Ulrich Weigand
Ramana Radhakrishnan wrote:
 (SAT, SATrev): New code iterators.
 (SATlo, SAThi): New code iterator attributes.
 (*satsi_SAT:code): New pattern.
 (*satsi_SAT:code_shift): Likewise.
 
 Iterators must go into iterators.md.

Hmm, I left them in arm.md deliberately, because they apply very
specifically only to those new patters; e.g. the SATlo / SAThi
attributes give operand numbers in the pattern, and don't make
sense for anything else ...

This is following what appeared to me to be existing precedent
e.g. FCVT in vfp.md ...

But if you prefer to have them in iterators.md anyway, I'll be
happy to move them, of course.

 Ok with that change for 4.8 if no regressions.

Thanks,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  ulrich.weig...@de.ibm.com



Re: [PATCH, ARM] Generate usat/ssat instructions

2012-02-29 Thread Ramana Radhakrishnan
On 29 February 2012 13:25, Ulrich Weigand uweig...@de.ibm.com wrote:
 Ramana Radhakrishnan wrote:
     (SAT, SATrev): New code iterators.
     (SATlo, SAThi): New code iterator attributes.
     (*satsi_SAT:code): New pattern.
     (*satsi_SAT:code_shift): Likewise.

 Iterators must go into iterators.md.

 Hmm, I left them in arm.md deliberately, because they apply very
 specifically only to those new patters; e.g. the SATlo / SAThi
 attributes give operand numbers in the pattern, and don't make
 sense for anything else ...

Might as well leave them there then as you say.

Ramana