Skip to content

Commit

Permalink
gcc/
Browse files Browse the repository at this point in the history
	* 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.


git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@184803 138bc75d-0d04-0410-961f-82ee72b054a4
  • Loading branch information
uweigand committed Mar 2, 2012
1 parent 7103ce4 commit b49e374
Show file tree
Hide file tree
Showing 8 changed files with 184 additions and 5 deletions.
15 changes: 15 additions & 0 deletions gcc/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
2012-03-02 Ulrich Weigand <ulrich.weigand@linaro.org>

* 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.

2012-03-02 Uros Bizjak <ubizjak@gmail.com>

PR target/46716
Expand Down
5 changes: 4 additions & 1 deletion gcc/config/arm/arm-fixed.md
Original file line number Diff line number Diff line change
Expand Up @@ -374,11 +374,14 @@
"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"
[(set (match_operand:HI 0 "s_register_operand" "=r")
(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")])
1 change: 1 addition & 0 deletions gcc/config/arm/arm-protos.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ extern int tls_mentioned_p (rtx);
extern int symbol_mentioned_p (rtx);
extern int label_mentioned_p (rtx);
extern RTX_CODE minmax_code (rtx);
extern bool arm_sat_operator_match (rtx, rtx, int *, bool *);
extern int adjacent_mem_locations (rtx, rtx);
extern bool gen_ldm_seq (rtx *, int, bool);
extern bool gen_stm_seq (rtx *, int);
Expand Down
36 changes: 36 additions & 0 deletions gcc/config/arm/arm.c
Original file line number Diff line number Diff line change
Expand Up @@ -10037,6 +10037,42 @@ minmax_code (rtx x)
}
}

/* 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)
Expand Down
56 changes: 55 additions & 1 deletion gcc/config/arm/arm.md
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@
;; scheduling information.

(define_attr "insn"
"mov,mvn,smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals,smlawy,smuad,smuadx,smlad,smladx,smusd,smusdx,smlsd,smlsdx,smmul,smmulr,smmla,umaal,smlald,smlsld,clz,mrs,msr,xtab,sdiv,udiv,other"
"mov,mvn,smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals,smlawy,smuad,smuadx,smlad,smladx,smusd,smusdx,smlsd,smlsdx,smmul,smmulr,smmla,umaal,smlald,smlsld,clz,mrs,msr,xtab,sdiv,udiv,sat,other"
(const_string "other"))

; TYPE attribute is used to detect floating point instructions which, if
Expand Down Expand Up @@ -3446,6 +3446,60 @@
(const_int 12)))]
)

(define_code_iterator SAT [smin smax])
(define_code_iterator SATrev [smin smax])
(define_code_attr SATlo [(smin "1") (smax "2")])
(define_code_attr SAThi [(smin "2") (smax "1")])

(define_insn "*satsi_<SAT:code>"
[(set (match_operand:SI 0 "s_register_operand" "=r")
(SAT:SI (SATrev:SI (match_operand:SI 3 "s_register_operand" "r")
(match_operand:SI 1 "const_int_operand" "i"))
(match_operand:SI 2 "const_int_operand" "i")))]
"TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
&& arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
{
int mask;
bool signed_sat;
if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
&mask, &signed_sat))
gcc_unreachable ();

operands[1] = GEN_INT (mask);
if (signed_sat)
return "ssat%?\t%0, %1, %3";
else
return "usat%?\t%0, %1, %3";
}
[(set_attr "predicable" "yes")
(set_attr "insn" "sat")])

(define_insn "*satsi_<SAT:code>_shift"
[(set (match_operand:SI 0 "s_register_operand" "=r")
(SAT:SI (SATrev:SI (match_operator:SI 3 "sat_shift_operator"
[(match_operand:SI 4 "s_register_operand" "r")
(match_operand:SI 5 "const_int_operand" "i")])
(match_operand:SI 1 "const_int_operand" "i"))
(match_operand:SI 2 "const_int_operand" "i")))]
"TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
&& arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
{
int mask;
bool signed_sat;
if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
&mask, &signed_sat))
gcc_unreachable ();

operands[1] = GEN_INT (mask);
if (signed_sat)
return "ssat%?\t%0, %1, %4%S3";
else
return "usat%?\t%0, %1, %4%S3";
}
[(set_attr "predicable" "yes")
(set_attr "insn" "sat")
(set_attr "shift" "3")
(set_attr "type" "alu_shift")])

;; Shift and rotation insns

Expand Down
8 changes: 5 additions & 3 deletions gcc/config/arm/predicates.md
Original file line number Diff line number Diff line change
Expand Up @@ -243,9 +243,11 @@

;; True for shift operators which can be used with saturation instructions.
(define_special_predicate "sat_shift_operator"
(and (match_code "ashift,ashiftrt")
(match_test "GET_CODE (XEXP (op, 1)) == CONST_INT
&& ((unsigned HOST_WIDE_INT) INTVAL (XEXP (op, 1)) <= 32)")
(and (ior (and (match_code "mult")
(match_test "power_of_two_operand (XEXP (op, 1), mode)"))
(and (match_code "ashift,ashiftrt")
(match_test "GET_CODE (XEXP (op, 1)) == CONST_INT
&& ((unsigned HOST_WIDE_INT) INTVAL (XEXP (op, 1)) < 32)")))
(match_test "mode == GET_MODE (op)")))

;; True for MULT, to identify which variant of shift_operator is in use.
Expand Down
4 changes: 4 additions & 0 deletions gcc/testsuite/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
2012-03-02 Ulrich Weigand <ulrich.weigand@linaro.org>

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

2012-03-02 Uros Bizjak <ubizjak@gmail.com>

PR target/46716
Expand Down
64 changes: 64 additions & 0 deletions gcc/testsuite/gcc.target/arm/sat-1.c
Original file line number Diff line number Diff line change
@@ -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 } } */

0 comments on commit b49e374

Please sign in to comment.