re PR target/50447 ([avr] Better support of AND, OR, XOR and PLUS with constant integers for 16- and 32-bit values)

PR target/50447
	* config/avr/avr.md (cc): Add out_plus attribute alternative.
	(addsi3): Use it.  Adapt avr_out_plus to new prototype.  Use
	avr_out_plus for all CONST_INT addends.
	* config/avr/avr-protos.h (avr_out_plus): Change prototype.
	* config/avr/avr.c (notice_update_cc): Call avr_out_plus on
	CC_OUT_PLUS.
	(avr_out_plus_1): Change prototype and report effect on cc0.
	(avr_out_plus): Ditto.
	(adjust_insn_length): Adapt call to avr_out_plus to new prototype.

From-SVN: r179816
This commit is contained in:
Georg-Johann Lay 2011-10-11 18:28:49 +00:00 committed by Georg-Johann Lay
parent a4474a3854
commit 05058b6e31
4 changed files with 93 additions and 27 deletions

View File

@ -1,3 +1,16 @@
2011-10-11 Georg-Johann Lay <avr@gjlay.de>
PR target/50447
* config/avr/avr.md (cc): Add out_plus attribute alternative.
(addsi3): Use it. Adapt avr_out_plus to new prototype. Use
avr_out_plus for all CONST_INT addends.
* config/avr/avr-protos.h (avr_out_plus): Change prototype.
* config/avr/avr.c (notice_update_cc): Call avr_out_plus on
CC_OUT_PLUS.
(avr_out_plus_1): Change prototype and report effect on cc0.
(avr_out_plus): Ditto.
(adjust_insn_length): Adapt call to avr_out_plus to new prototype.
2011-10-11 H.J. Lu <hongjiu.lu@intel.com>
* config/i386/i386.c (ix86_expand_special_args_builtin): Remove

View File

@ -82,7 +82,7 @@ extern void avr_output_bld (rtx operands[], int bit_nr);
extern void avr_output_addr_vec_elt (FILE *stream, int value);
extern const char *avr_out_sbxx_branch (rtx insn, rtx operands[]);
extern const char* avr_out_bitop (rtx, rtx*, int*);
extern const char* avr_out_plus (rtx*, int*);
extern const char* avr_out_plus (rtx*, int*, int*);
extern const char* avr_out_addto_sp (rtx*, int*);
extern bool avr_popcount_each_byte (rtx, int, int);

View File

@ -1630,9 +1630,37 @@ void
notice_update_cc (rtx body ATTRIBUTE_UNUSED, rtx insn)
{
rtx set;
enum attr_cc cc = get_attr_cc (insn);
switch (get_attr_cc (insn))
switch (cc)
{
default:
break;
case CC_OUT_PLUS:
{
rtx *op = recog_data.operand;
int len_dummy, icc;
/* Extract insn's operands. */
extract_constrain_insn_cached (insn);
avr_out_plus (op, &len_dummy, &icc);
cc = (enum attr_cc) icc;
break;
}
}
switch (cc)
{
default:
/* Special values like CC_OUT_PLUS from above have been
mapped to "standard" CC_* values so we never come here. */
gcc_unreachable();
break;
case CC_NONE:
/* Insn does not affect CC at all. */
break;
@ -4673,10 +4701,11 @@ lshrsi3_out (rtx insn, rtx operands[], int *len)
addition; otherwise, set *PLEN to the length of the instruction sequence (in
words) printed with PLEN == NULL. XOP[3] is an 8-bit scratch register.
CODE == PLUS: perform addition by using ADD instructions.
CODE == MINUS: perform addition by using SUB instructions. */
CODE == MINUS: perform addition by using SUB instructions.
Set *PCC to effect on cc0 according to respective CC_* insn attribute. */
static void
avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code)
avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code, int *pcc)
{
/* MODE of the operation. */
enum machine_mode mode = GET_MODE (xop[0]);
@ -4700,6 +4729,10 @@ avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code)
/* Value to add. There are two ways to add VAL: R += VAL and R -= -VAL. */
rtx xval = xop[2];
/* Addition does not set cc0 in a usable way. */
*pcc = (MINUS == code) ? CC_SET_CZN : CC_CLOBBER;
if (MINUS == code)
xval = gen_int_mode (-UINTVAL (xval), mode);
@ -4722,6 +4755,11 @@ avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code)
op[0] = reg8;
op[1] = GEN_INT (val8);
/* To get usable cc0 no low-bytes must have been skipped. */
if (i && !started)
*pcc = CC_CLOBBER;
if (!started && i % 2 == 0
&& test_hard_reg_class (ADDW_REGS, reg8))
@ -4794,6 +4832,11 @@ avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code)
started = true;
} /* for all sub-bytes */
/* No output doesn't change cc0. */
if (plen && *plen == 0)
*pcc = CC_NONE;
}
@ -4803,24 +4846,35 @@ avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code)
and return "". If PLEN == NULL, print assembler instructions to perform the
addition; otherwise, set *PLEN to the length of the instruction sequence (in
words) printed with PLEN == NULL. */
words) printed with PLEN == NULL.
If PCC != 0 then set *PCC to the the instruction sequence's effect on the
condition code (with respect to XOP[0]). */
const char*
avr_out_plus (rtx *xop, int *plen)
avr_out_plus (rtx *xop, int *plen, int *pcc)
{
int len_plus, len_minus;
int cc_plus, cc_minus, cc_dummy;
if (!pcc)
pcc = &cc_dummy;
/* Work out if XOP[0] += XOP[2] is better or XOP[0] -= -XOP[2]. */
avr_out_plus_1 (xop, &len_plus, PLUS);
avr_out_plus_1 (xop, &len_minus, MINUS);
avr_out_plus_1 (xop, &len_plus, PLUS, &cc_plus);
avr_out_plus_1 (xop, &len_minus, MINUS, &cc_minus);
/* Prefer MINUS over PLUS if size is equal because it sets cc0. */
if (plen)
*plen = (len_minus <= len_plus) ? len_minus : len_plus;
{
*plen = (len_minus <= len_plus) ? len_minus : len_plus;
*pcc = (len_minus <= len_plus) ? cc_minus : cc_plus;
}
else if (len_minus <= len_plus)
avr_out_plus_1 (xop, NULL, MINUS);
avr_out_plus_1 (xop, NULL, MINUS, pcc);
else
avr_out_plus_1 (xop, NULL, PLUS);
avr_out_plus_1 (xop, NULL, PLUS, pcc);
return "";
}
@ -5209,7 +5263,7 @@ adjust_insn_length (rtx insn, int len)
case ADJUST_LEN_OUT_BITOP: avr_out_bitop (insn, op, &len); break;
case ADJUST_LEN_OUT_PLUS: avr_out_plus (op, &len); break;
case ADJUST_LEN_OUT_PLUS: avr_out_plus (op, &len, NULL); break;
case ADJUST_LEN_ADDTO_SP: avr_out_addto_sp (op, &len); break;

View File

@ -77,7 +77,8 @@
(include "constraints.md")
;; Condition code settings.
(define_attr "cc" "none,set_czn,set_zn,set_n,compare,clobber"
(define_attr "cc" "none,set_czn,set_zn,set_n,compare,clobber,
out_plus"
(const_string "none"))
(define_attr "type" "branch,branch1,arith,xcall"
@ -786,30 +787,28 @@
(set_attr "cc" "set_n,set_czn,set_czn,set_czn,set_n,set_n")])
(define_insn "addsi3"
[(set (match_operand:SI 0 "register_operand" "=r,!w,!w,d,l,l ,d,r")
(plus:SI (match_operand:SI 1 "register_operand" "%0,0 ,0 ,0,0,0 ,0,0")
(match_operand:SI 2 "nonmemory_operand" "r,I ,J ,s,P,N ,n,n")))
(clobber (match_scratch:QI 3 "=X,X ,X ,X,X,X ,X,&d"))]
[(set (match_operand:SI 0 "register_operand" "=r,d ,d,r")
(plus:SI (match_operand:SI 1 "register_operand" "%0,0 ,0,0")
(match_operand:SI 2 "nonmemory_operand" "r,s ,n,n")))
(clobber (match_scratch:QI 3 "=X,X ,X,&d"))]
""
{
static const char * const asm_code[] =
{
"add %A0,%A2\;adc %B0,%B2\;adc %C0,%C2\;adc %D0,%D2",
"adiw %0,%2\;adc %C0,__zero_reg__\;adc %D0,__zero_reg__",
"sbiw %0,%n2\;sbc %C0,__zero_reg__\;sbc %D0,__zero_reg__",
"subi %0,lo8(-(%2))\;sbci %B0,hi8(-(%2))\;sbci %C0,hlo8(-(%2))\;sbci %D0,hhi8(-(%2))",
"sec\;adc %A0,__zero_reg__\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__\;adc %D0,__zero_reg__",
"sec\;sbc %A0,__zero_reg__\;sbc %B0,__zero_reg__\;sbc %C0,__zero_reg__\;sbc %D0,__zero_reg__"
"",
""
};
if (which_alternative >= (signed) (sizeof (asm_code) / sizeof (*asm_code)))
return avr_out_plus (operands, NULL);
if (*asm_code[which_alternative])
return asm_code [which_alternative];
return asm_code [which_alternative];
return avr_out_plus (operands, NULL, NULL);
}
[(set_attr "length" "4,3,3,4,5,5,8,8")
(set_attr "adjust_len" "*,*,*,*,*,*,out_plus,out_plus")
(set_attr "cc" "set_n,set_n,set_czn,set_czn,set_n,set_n,clobber,clobber")])
[(set_attr "length" "4,4,4,8")
(set_attr "adjust_len" "*,*,out_plus,out_plus")
(set_attr "cc" "set_n,set_czn,out_plus,out_plus")])
(define_insn "*addsi3_zero_extend"
[(set (match_operand:SI 0 "register_operand" "=r")