mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-18 23:31:22 +08:00
Preparing to use shifts to eliminate redundant test/compare insns on H8
* config/h8300/h8300-protos.h (output_a_shift): Make first argument an array of rtx rather than a pointer to rtx. Add code argument. (compute_a_shift_length): Similarly. * config/h8300/h8300.c (h8300_shift_costs): Adjust now that the shift itself isn't an operand. Create dummy operand[0] to carry a mode and pass a suitable rtx code to compute_a_shift_length. (get_shift_alg): Adjust operand number of clobber in output templates. (output_a_shift): Make first argument an array of rtx rather than a pointer to rtx. Add code argument for the type of shift. Adjust now that the shift itself is no longer an operand. (compute_a_shift_length): Similarly. * config/h8300/shiftrotate.md (shiftqi, shifthi, shiftsi): Use an iterator rather than nshift_operator. (shiftqi_noscratch, shifthi_noscratch, shiftsi_noscratch): Likewise. (shiftqi_clobber_flags): Adjust to API changes in output_a_shift and compute_a_shift_length. (shiftqi_noscratch_clobber_flags): Likewise. (shifthi_noscratch_clobber_flags): Likewise. (shiftsi_noscratch_clobber_flags): Likewise.
This commit is contained in:
parent
8501743106
commit
b60761baa6
@ -28,8 +28,8 @@ along with GCC; see the file COPYING3. If not see
|
||||
extern unsigned int compute_mov_length (rtx *);
|
||||
extern const char *output_plussi (rtx *, bool);
|
||||
extern unsigned int compute_plussi_length (rtx *, bool);
|
||||
extern const char *output_a_shift (rtx *);
|
||||
extern unsigned int compute_a_shift_length (rtx *);
|
||||
extern const char *output_a_shift (rtx[4], rtx_code);
|
||||
extern unsigned int compute_a_shift_length (rtx[4], rtx_code);
|
||||
extern const char *output_a_rotate (enum rtx_code, rtx *);
|
||||
extern unsigned int compute_a_rotate_length (rtx *);
|
||||
extern const char *output_simode_bld (int, rtx[]);
|
||||
|
@ -1108,18 +1108,17 @@ h8300_and_costs (rtx x)
|
||||
static int
|
||||
h8300_shift_costs (rtx x)
|
||||
{
|
||||
rtx operands[4];
|
||||
rtx operands[3];
|
||||
|
||||
if (GET_MODE (x) != QImode
|
||||
&& GET_MODE (x) != HImode
|
||||
&& GET_MODE (x) != SImode)
|
||||
return 100;
|
||||
|
||||
operands[0] = NULL;
|
||||
operands[0] = gen_rtx_REG (GET_MODE (x), 0);
|
||||
operands[1] = NULL;
|
||||
operands[2] = XEXP (x, 1);
|
||||
operands[3] = x;
|
||||
return compute_a_shift_length (operands) / 2;
|
||||
return compute_a_shift_length (operands, GET_CODE (x)) / 2;
|
||||
}
|
||||
|
||||
/* Worker function for TARGET_RTX_COSTS. */
|
||||
@ -3759,13 +3758,13 @@ get_shift_alg (enum shift_type shift_type, enum shift_mode shift_mode,
|
||||
switch (shift_type)
|
||||
{
|
||||
case SHIFT_ASHIFT:
|
||||
info->special = "mov.w\t%e0,%f4\n\tmov.b\t%s4,%t4\n\tmov.b\t%t0,%s4\n\tmov.b\t%s0,%t0\n\tsub.b\t%s0,%s0\n\tmov.w\t%f4,%e0";
|
||||
info->special = "mov.w\t%e0,%f3\n\tmov.b\t%s3,%t3\n\tmov.b\t%t0,%s3\n\tmov.b\t%s0,%t0\n\tsub.b\t%s0,%s0\n\tmov.w\t%f3,%e0";
|
||||
goto end;
|
||||
case SHIFT_LSHIFTRT:
|
||||
info->special = "mov.w\t%e0,%f4\n\tmov.b\t%t0,%s0\n\tmov.b\t%s4,%t0\n\tmov.b\t%t4,%s4\n\textu.w\t%f4\n\tmov.w\t%f4,%e0";
|
||||
info->special = "mov.w\t%e0,%f3\n\tmov.b\t%t0,%s0\n\tmov.b\t%s3,%t0\n\tmov.b\t%t3,%s3\n\textu.w\t%f3\n\tmov.w\t%f3,%e0";
|
||||
goto end;
|
||||
case SHIFT_ASHIFTRT:
|
||||
info->special = "mov.w\t%e0,%f4\n\tmov.b\t%t0,%s0\n\tmov.b\t%s4,%t0\n\tmov.b\t%t4,%s4\n\texts.w\t%f4\n\tmov.w\t%f4,%e0";
|
||||
info->special = "mov.w\t%e0,%f3\n\tmov.b\t%t0,%s0\n\tmov.b\t%s3,%t0\n\tmov.b\t%t3,%s3\n\texts.w\t%f3\n\tmov.w\t%f3,%e0";
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
@ -3985,12 +3984,10 @@ h8300_shift_needs_scratch_p (int count, machine_mode mode, enum rtx_code type)
|
||||
/* Output the assembler code for doing shifts. */
|
||||
|
||||
const char *
|
||||
output_a_shift (rtx *operands)
|
||||
output_a_shift (rtx operands[4], rtx_code code)
|
||||
{
|
||||
static int loopend_lab;
|
||||
rtx shift = operands[3];
|
||||
machine_mode mode = GET_MODE (shift);
|
||||
enum rtx_code code = GET_CODE (shift);
|
||||
machine_mode mode = GET_MODE (operands[0]);
|
||||
enum shift_type shift_type;
|
||||
enum shift_mode shift_mode;
|
||||
struct shift_info info;
|
||||
@ -4114,10 +4111,10 @@ output_a_shift (rtx *operands)
|
||||
if (info.shift2 != NULL)
|
||||
{
|
||||
fprintf (asm_out_file, "\tmov.b #%d,%sl\n", n / 2,
|
||||
names_big[REGNO (operands[4])]);
|
||||
names_big[REGNO (operands[3])]);
|
||||
fprintf (asm_out_file, ".Llt%d:\n", loopend_lab);
|
||||
output_asm_insn (info.shift2, operands);
|
||||
output_asm_insn ("add #0xff,%X4", operands);
|
||||
output_asm_insn ("add #0xff,%X3", operands);
|
||||
fprintf (asm_out_file, "\tbne .Llt%d\n", loopend_lab);
|
||||
if (n % 2)
|
||||
output_asm_insn (info.shift1, operands);
|
||||
@ -4125,10 +4122,10 @@ output_a_shift (rtx *operands)
|
||||
else
|
||||
{
|
||||
fprintf (asm_out_file, "\tmov.b #%d,%sl\n", n,
|
||||
names_big[REGNO (operands[4])]);
|
||||
names_big[REGNO (operands[3])]);
|
||||
fprintf (asm_out_file, ".Llt%d:\n", loopend_lab);
|
||||
output_asm_insn (info.shift1, operands);
|
||||
output_asm_insn ("add #0xff,%X4", operands);
|
||||
output_asm_insn ("add #0xff,%X3", operands);
|
||||
fprintf (asm_out_file, "\tbne .Llt%d\n", loopend_lab);
|
||||
}
|
||||
return "";
|
||||
@ -4155,11 +4152,9 @@ h8300_asm_insn_count (const char *templ)
|
||||
/* Compute the length of a shift insn. */
|
||||
|
||||
unsigned int
|
||||
compute_a_shift_length (rtx *operands)
|
||||
compute_a_shift_length (rtx operands[3], rtx_code code)
|
||||
{
|
||||
rtx shift = operands[3];
|
||||
machine_mode mode = GET_MODE (shift);
|
||||
enum rtx_code code = GET_CODE (shift);
|
||||
enum machine_mode mode = GET_MODE (operands[0]);
|
||||
enum shift_type shift_type;
|
||||
enum shift_mode shift_mode;
|
||||
struct shift_info info;
|
||||
|
@ -152,168 +152,163 @@
|
||||
|
||||
(define_insn_and_split "*shiftqi"
|
||||
[(set (match_operand:QI 0 "register_operand" "=r,r")
|
||||
(match_operator:QI 3 "nshift_operator"
|
||||
[(match_operand:QI 1 "register_operand" "0,0")
|
||||
(match_operand:QI 2 "nonmemory_operand" "R,rn")]))
|
||||
(clobber (match_scratch:QI 4 "=X,&r"))]
|
||||
(shifts:QI
|
||||
(match_operand:QI 1 "register_operand" "0,0")
|
||||
(match_operand:QI 2 "nonmemory_operand" "R,rn")))
|
||||
(clobber (match_scratch:QI 3 "=X,&r"))]
|
||||
""
|
||||
"#"
|
||||
"&& reload_completed"
|
||||
[(parallel [(set (match_dup 0) (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
|
||||
(clobber (match_dup 4))
|
||||
[(parallel [(set (match_dup 0) (shifts:QI (match_dup 1) (match_dup 2)))
|
||||
(clobber (match_dup 3))
|
||||
(clobber (reg:CC CC_REG))])])
|
||||
|
||||
(define_insn "*shiftqi_clobber_flags"
|
||||
[(set (match_operand:QI 0 "register_operand" "=r,r")
|
||||
(match_operator:QI 3 "nshift_operator"
|
||||
[(match_operand:QI 1 "register_operand" "0,0")
|
||||
(match_operand:QI 2 "nonmemory_operand" "R,rn")]))
|
||||
(clobber (match_scratch:QI 4 "=X,&r"))
|
||||
(shifts:QI
|
||||
(match_operand:QI 1 "register_operand" "0,0")
|
||||
(match_operand:QI 2 "nonmemory_operand" "R,rn")))
|
||||
(clobber (match_scratch:QI 3 "=X,&r"))
|
||||
(clobber (reg:CC CC_REG))]
|
||||
""
|
||||
{
|
||||
return output_a_shift (operands);
|
||||
return output_a_shift (operands, <CODE>);
|
||||
}
|
||||
[(set (attr "length")
|
||||
(symbol_ref "compute_a_shift_length (operands)"))])
|
||||
(symbol_ref "compute_a_shift_length (operands, <CODE>)"))])
|
||||
|
||||
(define_insn_and_split "*shiftqi_noscratch"
|
||||
[(set (match_operand:QI 0 "register_operand" "=r,r")
|
||||
(match_operator:QI 3 "nshift_operator"
|
||||
[(match_operand:QI 1 "register_operand" "0,0")
|
||||
(match_operand:QI 2 "nonmemory_operand" "R,rn")]))]
|
||||
(shifts:QI
|
||||
(match_operand:QI 1 "register_operand" "0,0")
|
||||
(match_operand:QI 2 "nonmemory_operand" "R,rn")))]
|
||||
"(GET_CODE (operands[2]) == CONST_INT
|
||||
&& !h8300_shift_needs_scratch_p (INTVAL (operands[2]), QImode,
|
||||
GET_CODE (operands[3])))"
|
||||
<CODE>))"
|
||||
"#"
|
||||
"&& reload_completed"
|
||||
[(parallel [(set (match_dup 0) (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
|
||||
[(parallel [(set (match_dup 0) (shifts:QI (match_dup 1) (match_dup 2)))
|
||||
(clobber (reg:CC CC_REG))])])
|
||||
|
||||
(define_insn "*shiftqi_noscratch_clobber_flags"
|
||||
[(set (match_operand:QI 0 "register_operand" "=r,r")
|
||||
(match_operator:QI 3 "nshift_operator"
|
||||
[(match_operand:QI 1 "register_operand" "0,0")
|
||||
(match_operand:QI 2 "nonmemory_operand" "R,rn")]))
|
||||
(shifts:QI
|
||||
(match_operand:QI 1 "register_operand" "0,0")
|
||||
(match_operand:QI 2 "nonmemory_operand" "R,rn")))
|
||||
(clobber (reg:CC CC_REG))]
|
||||
"(GET_CODE (operands[2]) == CONST_INT
|
||||
&& !h8300_shift_needs_scratch_p (INTVAL (operands[2]), QImode,
|
||||
GET_CODE (operands[3])))"
|
||||
&& !h8300_shift_needs_scratch_p (INTVAL (operands[2]), QImode, <CODE>))"
|
||||
{
|
||||
return output_a_shift (operands);
|
||||
return output_a_shift (operands, <CODE>);
|
||||
}
|
||||
[(set (attr "length")
|
||||
(symbol_ref "compute_a_shift_length (operands)"))])
|
||||
(symbol_ref "compute_a_shift_length (operands, <CODE>)"))])
|
||||
|
||||
(define_insn_and_split "*shifthi"
|
||||
[(set (match_operand:HI 0 "register_operand" "=r,r")
|
||||
(match_operator:HI 3 "nshift_operator"
|
||||
[(match_operand:HI 1 "register_operand" "0,0")
|
||||
(match_operand:QI 2 "nonmemory_operand" "S,rn")]))
|
||||
(clobber (match_scratch:QI 4 "=X,&r"))]
|
||||
(shifts:HI
|
||||
(match_operand:HI 1 "register_operand" "0,0")
|
||||
(match_operand:QI 2 "nonmemory_operand" "S,rn")))
|
||||
(clobber (match_scratch:QI 3 "=X,&r"))]
|
||||
""
|
||||
"#"
|
||||
"&& reload_completed"
|
||||
[(parallel [(set (match_dup 0) (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
|
||||
(clobber (match_dup 4))
|
||||
[(parallel [(set (match_dup 0) (shifts:HI (match_dup 1) (match_dup 2)))
|
||||
(clobber (match_dup 3))
|
||||
(clobber (reg:CC CC_REG))])])
|
||||
|
||||
(define_insn "*shifthi_clobber_flags"
|
||||
[(set (match_operand:HI 0 "register_operand" "=r,r")
|
||||
(match_operator:HI 3 "nshift_operator"
|
||||
[(match_operand:HI 1 "register_operand" "0,0")
|
||||
(match_operand:QI 2 "nonmemory_operand" "S,rn")]))
|
||||
(clobber (match_scratch:QI 4 "=X,&r"))
|
||||
(shifts:HI
|
||||
(match_operand:HI 1 "register_operand" "0,0")
|
||||
(match_operand:QI 2 "nonmemory_operand" "S,rn")))
|
||||
(clobber (match_scratch:QI 3 "=X,&r"))
|
||||
(clobber (reg:CC CC_REG))]
|
||||
""
|
||||
{
|
||||
return output_a_shift (operands);
|
||||
return output_a_shift (operands, <CODE>);
|
||||
}
|
||||
[(set (attr "length")
|
||||
(symbol_ref "compute_a_shift_length (operands)"))])
|
||||
(symbol_ref "compute_a_shift_length (operands, <CODE>)"))])
|
||||
|
||||
(define_insn_and_split "*shifthi_noscratch"
|
||||
[(set (match_operand:HI 0 "register_operand" "=r,r")
|
||||
(match_operator:HI 3 "nshift_operator"
|
||||
[(match_operand:HI 1 "register_operand" "0,0")
|
||||
(match_operand:HI 2 "nonmemory_operand" "S,rn")]))]
|
||||
(shifts:HI
|
||||
(match_operand:HI 1 "register_operand" "0,0")
|
||||
(match_operand:HI 2 "nonmemory_operand" "S,rn")))]
|
||||
"(GET_CODE (operands[2]) == CONST_INT
|
||||
&& !h8300_shift_needs_scratch_p (INTVAL (operands[2]), HImode,
|
||||
GET_CODE (operands[3])))"
|
||||
&& !h8300_shift_needs_scratch_p (INTVAL (operands[2]), HImode, <CODE>))"
|
||||
"#"
|
||||
"&& reload_completed"
|
||||
[(parallel [(set (match_dup 0) (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
|
||||
[(parallel [(set (match_dup 0) (shifts:HI (match_dup 1) (match_dup 2)))
|
||||
(clobber (reg:CC CC_REG))])])
|
||||
|
||||
(define_insn "*shifthi_noscratch_clobber_flags"
|
||||
[(set (match_operand:HI 0 "register_operand" "=r,r")
|
||||
(match_operator:HI 3 "nshift_operator"
|
||||
[(match_operand:HI 1 "register_operand" "0,0")
|
||||
(match_operand:HI 2 "nonmemory_operand" "S,rn")]))
|
||||
(shifts:HI
|
||||
(match_operand:HI 1 "register_operand" "0,0")
|
||||
(match_operand:HI 2 "nonmemory_operand" "S,rn")))
|
||||
(clobber (reg:CC CC_REG))]
|
||||
"(GET_CODE (operands[2]) == CONST_INT
|
||||
&& !h8300_shift_needs_scratch_p (INTVAL (operands[2]), HImode,
|
||||
GET_CODE (operands[3])))"
|
||||
&& !h8300_shift_needs_scratch_p (INTVAL (operands[2]), HImode, <CODE>))"
|
||||
{
|
||||
return output_a_shift (operands);
|
||||
return output_a_shift (operands, <CODE>);
|
||||
}
|
||||
[(set (attr "length")
|
||||
(symbol_ref "compute_a_shift_length (operands)"))])
|
||||
(symbol_ref "compute_a_shift_length (operands, <CODE>)"))])
|
||||
|
||||
(define_insn_and_split "*shiftsi"
|
||||
[(set (match_operand:SI 0 "register_operand" "=r,r")
|
||||
(match_operator:SI 3 "nshift_operator"
|
||||
[(match_operand:SI 1 "register_operand" "0,0")
|
||||
(match_operand:QI 2 "nonmemory_operand" "T,rn")]))
|
||||
(clobber (match_scratch:QI 4 "=X,&r"))]
|
||||
(shifts:SI
|
||||
(match_operand:SI 1 "register_operand" "0,0")
|
||||
(match_operand:QI 2 "nonmemory_operand" "T,rn")))
|
||||
(clobber (match_scratch:QI 3 "=X,&r"))]
|
||||
""
|
||||
"#"
|
||||
"&& reload_completed"
|
||||
[(parallel [(set (match_dup 0) (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
|
||||
(clobber (match_dup 4))
|
||||
[(parallel [(set (match_dup 0) (shifts:SI (match_dup 1) (match_dup 2)))
|
||||
(clobber (match_dup 3))
|
||||
(clobber (reg:CC CC_REG))])])
|
||||
|
||||
(define_insn "*shiftsi_clobber_flags"
|
||||
[(set (match_operand:SI 0 "register_operand" "=r,r")
|
||||
(match_operator:SI 3 "nshift_operator"
|
||||
[(match_operand:SI 1 "register_operand" "0,0")
|
||||
(match_operand:QI 2 "nonmemory_operand" "T,rn")]))
|
||||
(clobber (match_scratch:QI 4 "=X,&r"))
|
||||
(shifts:SI
|
||||
(match_operand:SI 1 "register_operand" "0,0")
|
||||
(match_operand:QI 2 "nonmemory_operand" "T,rn")))
|
||||
(clobber (match_scratch:QI 3 "=X,&r"))
|
||||
(clobber (reg:CC CC_REG))]
|
||||
""
|
||||
{
|
||||
return output_a_shift (operands);
|
||||
return output_a_shift (operands, <CODE>);
|
||||
}
|
||||
[(set (attr "length")
|
||||
(symbol_ref "compute_a_shift_length (operands)"))])
|
||||
(symbol_ref "compute_a_shift_length (operands, <CODE>)"))])
|
||||
|
||||
(define_insn_and_split "*shiftsi_noscratch"
|
||||
[(set (match_operand:SI 0 "register_operand" "=r,r")
|
||||
(match_operator:SI 3 "nshift_operator"
|
||||
[(match_operand:SI 1 "register_operand" "0,0")
|
||||
(match_operand:QI 2 "nonmemory_operand" "T,rn")]))]
|
||||
(shifts:SI
|
||||
(match_operand:SI 1 "register_operand" "0,0")
|
||||
(match_operand:QI 2 "nonmemory_operand" "T,rn")))]
|
||||
"(GET_CODE (operands[2]) == CONST_INT
|
||||
&& !h8300_shift_needs_scratch_p (INTVAL (operands[2]), SImode,
|
||||
GET_CODE (operands[3])))"
|
||||
&& !h8300_shift_needs_scratch_p (INTVAL (operands[2]), SImode, <CODE>))"
|
||||
"#"
|
||||
"&& reload_completed"
|
||||
[(parallel [(set (match_dup 0) (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
|
||||
[(parallel [(set (match_dup 0) (shifts:SI (match_dup 1) (match_dup 2)))
|
||||
(clobber (reg:CC CC_REG))])])
|
||||
|
||||
(define_insn "*shiftsi_noscratch_clobber_flags"
|
||||
[(set (match_operand:SI 0 "register_operand" "=r,r")
|
||||
(match_operator:SI 3 "nshift_operator"
|
||||
[(match_operand:SI 1 "register_operand" "0,0")
|
||||
(match_operand:SI 2 "nonmemory_operand" "T,rn")]))
|
||||
(shifts:SI
|
||||
(match_operand:SI 1 "register_operand" "0,0")
|
||||
(match_operand:SI 2 "nonmemory_operand" "T,rn")))
|
||||
(clobber (reg:CC CC_REG))]
|
||||
"(GET_CODE (operands[2]) == CONST_INT
|
||||
&& !h8300_shift_needs_scratch_p (INTVAL (operands[2]), SImode,
|
||||
GET_CODE (operands[3])))"
|
||||
&& !h8300_shift_needs_scratch_p (INTVAL (operands[2]), SImode, <CODE>))"
|
||||
{
|
||||
return output_a_shift (operands);
|
||||
return output_a_shift (operands, <CODE>);
|
||||
}
|
||||
[(set (attr "length")
|
||||
(symbol_ref "compute_a_shift_length (operands)"))])
|
||||
(symbol_ref "compute_a_shift_length (operands, <CODE>)"))])
|
||||
|
||||
;; Split a variable shift into a loop. If the register containing
|
||||
;; the shift count dies, then we just use that register.
|
||||
|
Loading…
x
Reference in New Issue
Block a user