m68k.c (post_inc_operand,pre_dec_operand): New.

* config/m68k/m68k.c (post_inc_operand,pre_dec_operand): New.
        * config/m68k/m68k.h (PREDICATE_CODES): add post_inc_operand,
        pre_dec_operand.
        * config/m68k/m68k.md (zero_extend*2): delay the splitting of the
        pattern until reload is finished to allow better code generation
        and split them completely into separate instrunctions.
        (*andsi3_split): New pattern.

From-SVN: r85631
This commit is contained in:
Roman Zippel 2004-08-06 07:14:56 +00:00 committed by Richard Henderson
parent 3589b69e2d
commit 9652c5316a
4 changed files with 158 additions and 207 deletions

View File

@ -1,3 +1,13 @@
2004-08-06 Roman Zippel <zippel@linux-m68k.org>
* config/m68k/m68k.c (post_inc_operand,pre_dec_operand): New.
* config/m68k/m68k.h (PREDICATE_CODES): add post_inc_operand,
pre_dec_operand.
* config/m68k/m68k.md (zero_extend*2): delay the splitting of the
pattern until reload is finished to allow better code generation
and split them completely into separate instrunctions.
(*andsi3_split): New pattern.
2004-08-05 Mark Mitchell <mark@codesourcery.com>
* tree.c (handle_dll_attribute): Move here from i383/winnt.c.

View File

@ -3185,6 +3185,18 @@ memory_src_operand (rtx op, enum machine_mode mode)
return memory_operand (op, mode);
}
int
post_inc_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
return MEM_P (op) && GET_CODE (XEXP (op, 0)) == POST_INC;
}
int
pre_dec_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
return MEM_P (op) && GET_CODE (XEXP (op, 0)) == PRE_DEC;
}
/* Predicate that accepts only a pc-relative address. This is needed
because pc-relative addresses don't satisfy the predicate
"general_src_operand". */

View File

@ -1271,4 +1271,6 @@ extern int m68k_last_compare_had_fp_operands;
{"valid_dbcc_comparison_p", {EQ, NE, GTU, LTU, GEU, LEU, \
GT, LT, GE, LE}}, \
{"extend_operator", {SIGN_EXTEND, ZERO_EXTEND}}, \
{"symbolic_operand", {SYMBOL_REF, LABEL_REF, CONST}},
{"symbolic_operand", {SYMBOL_REF, LABEL_REF, CONST}}, \
{"post_inc_operand", {MEM}}, \
{"pre_dec_operand", {MEM}},

View File

@ -1136,236 +1136,153 @@
;; zero extension instructions
(define_insn "zero_extendqidi2"
[(set (match_operand:DI 0 "nonimmediate_operand" "=&d")
(zero_extend:DI (match_operand:QI 1 "general_operand" "dm")))]
;; two special patterns to match various post_inc/pre_dec patterns
(define_insn_and_split "*zero_extend_inc"
[(set (match_operand 0 "post_inc_operand" "")
(zero_extend (match_operand 1 "register_operand" "")))]
"GET_MODE_CLASS (GET_MODE (operands[0])) == MODE_INT &&
GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT &&
GET_MODE_SIZE (GET_MODE (operands[0])) == GET_MODE_SIZE (GET_MODE (operands[1])) * 2"
"#"
""
[(set (match_dup 0)
(const_int 0))
(set (match_dup 0)
(match_dup 1))]
{
CC_STATUS_INIT;
operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
return "moveq #0,%0\;moveq #0,%2\;move%.b %1,%2";
operands[0] = adjust_address (operands[0], GET_MODE (operands[1]), 0);
})
(define_insn "zero_extendhidi2"
[(set (match_operand:DI 0 "nonimmediate_operand" "=&d")
(zero_extend:DI (match_operand:HI 1 "general_operand" "rm")))]
(define_insn_and_split "*zero_extend_dec"
[(set (match_operand 0 "pre_dec_operand" "")
(zero_extend (match_operand 1 "register_operand" "")))]
"(GET_MODE (operands[0]) != HImode || XEXP (XEXP (operands[0], 0), 0) != stack_pointer_rtx) &&
GET_MODE_CLASS (GET_MODE (operands[0])) == MODE_INT &&
GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT &&
GET_MODE_SIZE (GET_MODE (operands[0])) == GET_MODE_SIZE (GET_MODE (operands[1])) * 2"
"#"
""
[(set (match_dup 0)
(match_dup 1))
(set (match_dup 0)
(const_int 0))]
{
CC_STATUS_INIT;
operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
return "moveq #0,%0\;moveq #0,%2\;move%.w %1,%2";
operands[0] = adjust_address (operands[0], GET_MODE (operands[1]), 0);
})
(define_insn_and_split "zero_extendqidi2"
[(set (match_operand:DI 0 "register_operand" "")
(zero_extend:DI (match_operand:QI 1 "nonimmediate_src_operand" "")))]
""
"#"
""
[(set (match_dup 2)
(zero_extend:SI (match_dup 1)))
(set (match_dup 3)
(const_int 0))]
{
operands[2] = gen_lowpart (SImode, operands[0]);
operands[3] = gen_highpart (SImode, operands[0]);
})
(define_insn_and_split "zero_extendhidi2"
[(set (match_operand:DI 0 "register_operand" "")
(zero_extend:DI (match_operand:HI 1 "nonimmediate_src_operand" "")))]
""
"#"
""
[(set (match_dup 2)
(zero_extend:SI (match_dup 1)))
(set (match_dup 3)
(const_int 0))]
{
operands[2] = gen_lowpart (SImode, operands[0]);
operands[3] = gen_highpart (SImode, operands[0]);
})
;; this is the canonical form for (lshiftrt:DI x 32)
(define_expand "zero_extendsidi2"
[(set (match_operand:DI 0 "nonimmediate_operand" "")
(zero_extend:DI (match_operand:SI 1 "general_operand" "")))]
(zero_extend:DI (match_operand:SI 1 "nonimmediate_src_operand" "")))]
""
"")
(define_insn "*zero_extendsidi2_cf"
[(set (match_operand:DI 0 "nonimmediate_operand" "=r,m")
(zero_extend:DI (match_operand:SI 1 "general_operand" "rm,r")))]
"TARGET_COLDFIRE"
{
CC_STATUS_INIT;
if (GET_CODE (operands[0]) == REG)
operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
return "move%.l %1,%0\;clr%.l %0";
else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
return "clr%.l %0\;move%.l %1,%0";
else
operands[2] = adjust_address (operands[0], SImode, 4);
if (GET_CODE (operands[1]) != REG || GET_CODE (operands[2]) != REG
|| REGNO (operands[1]) != REGNO (operands[2]))
output_asm_insn ("move%.l %1,%2", operands);
if (ADDRESS_REG_P (operands[0]))
return "sub%.l %0,%0";
else
return "clr%.l %0";
})
(define_insn "*zero_extendsidi2"
[(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
(zero_extend:DI (match_operand:SI 1 "general_operand" "rm")))]
"!TARGET_COLDFIRE"
{
CC_STATUS_INIT;
if (GET_CODE (operands[0]) == REG)
operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
return "move%.l %1,%0\;clr%.l %0";
else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
return "clr%.l %0\;move%.l %1,%0";
else
operands[2] = adjust_address (operands[0], SImode, 4);
if (GET_CODE (operands[1]) != REG || GET_CODE (operands[2]) != REG
|| REGNO (operands[1]) != REGNO (operands[2]))
output_asm_insn ("move%.l %1,%2", operands);
if (ADDRESS_REG_P (operands[0]))
return "sub%.l %0,%0";
else
return "clr%.l %0";
})
(define_expand "zero_extendhisi2"
[(set (match_operand:SI 0 "register_operand" "")
(const_int 0))
(set (strict_low_part (match_dup 2))
(match_operand:HI 1 "general_operand" ""))]
(define_insn_and_split "*zero_extendsidi2"
[(set (match_operand:DI 0 "nonimmediate_operand" "")
(zero_extend:DI (match_operand:SI 1 "nonimmediate_src_operand" "")))]
"GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
"#"
""
"
[(set (match_dup 2)
(match_dup 1))
(set (match_dup 3)
(const_int 0))]
{
operands[1] = make_safe_from (operands[1], operands[0]);
operands[2] = gen_lowpart_SUBREG (HImode, operands[0]);
}")
operands[2] = gen_lowpart (SImode, operands[0]);
operands[3] = gen_highpart (SImode, operands[0]);
})
(define_insn "*zero_extendhisi2_cf"
[(set (match_operand:SI 0 "register_operand" "=d")
(zero_extend:SI (match_operand:HI 1 "nonimmediate_src_operand" "rmS")))]
"TARGET_CFV4"
"mvz%.w %1,%0")
(define_insn "zero_extendhisi2"
[(set (match_operand:SI 0 "register_operand" "=d")
(zero_extend:SI (match_operand:HI 1 "nonimmediate_src_operand" "rmS")))]
""
"#")
(define_expand "zero_extendqihi2"
[(set (match_operand:HI 0 "register_operand" "")
(const_int 0))
(set (strict_low_part (match_dup 2))
(match_operand:QI 1 "general_operand" ""))]
""
"
{
operands[1] = make_safe_from (operands[1], operands[0]);
operands[2] = gen_lowpart_SUBREG (QImode, operands[0]);
}")
(zero_extend:HI (match_operand:QI 1 "nonimmediate_src_operand" "")))]
"!TARGET_COLDFIRE"
"")
(define_expand "zero_extendqisi2"
[(set (match_operand:SI 0 "register_operand" "")
(const_int 0))
(set (strict_low_part (match_dup 2))
(match_operand:QI 1 "general_operand" ""))]
""
"
{
operands[1] = make_safe_from (operands[1], operands[0]);
operands[2] = gen_lowpart_SUBREG (QImode, operands[0]);
}")
;; Patterns to recognize zero-extend insns produced by the combiner.
;; We don't allow both operands in memory, because of aliasing problems.
;; Explicitly disallow two memory operands via the condition since reloading
;; of this case will result in worse code than the uncombined patterns.
(define_insn "*zero_extendqihi2"
[(set (match_operand:HI 0 "register_operand" "=d")
(zero_extend:HI (match_operand:QI 1 "nonimmediate_src_operand" "dmS")))]
"!TARGET_COLDFIRE"
"#")
(define_insn ""
[(set (match_operand:SI 0 "nonimmediate_operand" "=do<>,d<")
(zero_extend:SI (match_operand:HI 1 "nonimmediate_src_operand" "r,mS")))]
"GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
(define_insn "*zero_extendqisi2_cfv4"
[(set (match_operand:SI 0 "register_operand" "=d")
(zero_extend:SI (match_operand:QI 1 "nonimmediate_src_operand" "dmS")))]
"TARGET_CFV4"
"mvz%.b %1,%0")
(define_insn "zero_extendqisi2"
[(set (match_operand:SI 0 "register_operand" "=d")
(zero_extend:SI (match_operand:QI 1 "nonimmediate_src_operand" "dmS")))]
""
"#")
;; these two pattern split everything else which isn't matched by
;; something else above
(define_split
[(set (match_operand 0 "register_operand" "")
(zero_extend (match_operand 1 "nonimmediate_src_operand" "")))]
"!TARGET_CFV4 && reload_completed && reg_mentioned_p (operands[0], operands[1])"
[(set (strict_low_part (match_dup 2))
(match_dup 1))
(set (match_dup 0)
(match_op_dup 4 [(match_dup 0) (match_dup 3)]))]
{
if (DATA_REG_P (operands[0]))
{
if (TARGET_CFV4)
return "mvz%.w %1,%0";
if (GET_CODE (operands[1]) == REG
&& REGNO (operands[0]) == REGNO (operands[1]))
return "and%.l #0xFFFF,%0";
if (reg_mentioned_p (operands[0], operands[1]))
return "move%.w %1,%0\;and%.l #0xFFFF,%0";
return "clr%.l %0\;move%.w %1,%0";
}
else if (GET_CODE (operands[0]) == MEM
&& GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
return "move%.w %1,%0\;clr%.w %0";
else if (GET_CODE (operands[0]) == MEM
&& GET_CODE (XEXP (operands[0], 0)) == POST_INC)
return "clr%.w %0\;move%.w %1,%0";
else
{
output_asm_insn ("clr%.w %0", operands);
operands[0] = adjust_address (operands[0], HImode, 2);
return "move%.w %1,%0";
}
operands[2] = gen_lowpart (GET_MODE (operands[1]), operands[0]);
operands[3] = GEN_INT (GET_MODE_MASK (GET_MODE (operands[1])));
operands[4] = gen_rtx_AND (GET_MODE (operands[0]), operands[0], operands[3]);
})
(define_insn ""
[(set (match_operand:HI 0 "nonimmediate_operand" "=do<>,d")
(zero_extend:HI (match_operand:QI 1 "nonimmediate_src_operand" "d,mS")))]
"GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
(define_split
[(set (match_operand 0 "register_operand" "")
(zero_extend (match_operand 1 "nonimmediate_src_operand" "")))]
"!TARGET_CFV4 && reload_completed"
[(set (match_dup 0)
(const_int 0))
(set (strict_low_part (match_dup 2))
(match_dup 1))]
{
if (DATA_REG_P (operands[0]))
{
if (GET_CODE (operands[1]) == REG
&& REGNO (operands[0]) == REGNO (operands[1]))
{
if (TARGET_CFV4)
return "mvz%.b %0,%0";
return (!TARGET_COLDFIRE ? "and%.w #0xFF,%0" : "and%.l #0xFF,%0");
}
if (reg_mentioned_p (operands[0], operands[1]))
{
if (TARGET_CFV4)
return "mvz%.b %1,%0";
return (!TARGET_COLDFIRE ? "move%.b %1,%0\;and%.w #0xFF,%0"
: "move%.b %1,%0\;and%.l #0xFF,%0");
}
return "clr%.w %0\;move%.b %1,%0";
}
else if (GET_CODE (operands[0]) == MEM
&& GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
{
if (REGNO (XEXP (XEXP (operands[0], 0), 0))
== STACK_POINTER_REGNUM)
{
output_asm_insn ("clr%.w %-", operands);
operands[0] = gen_rtx_MEM (GET_MODE (operands[0]),
plus_constant (stack_pointer_rtx, 1));
return "move%.b %1,%0";
}
else
return "move%.b %1,%0\;clr%.b %0";
}
else if (GET_CODE (operands[0]) == MEM
&& GET_CODE (XEXP (operands[0], 0)) == POST_INC)
return "clr%.b %0\;move%.b %1,%0";
else
{
output_asm_insn ("clr%.b %0", operands);
operands[0] = adjust_address (operands[0], QImode, 1);
return "move%.b %1,%0";
}
})
(define_insn ""
[(set (match_operand:SI 0 "nonimmediate_operand" "=do<>,d")
(zero_extend:SI (match_operand:QI 1 "nonimmediate_src_operand" "d,mS")))]
"GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
{
if (DATA_REG_P (operands[0]))
{
if (TARGET_CFV4)
return "mvz%.b %1,%0";
if (GET_CODE (operands[1]) == REG
&& REGNO (operands[0]) == REGNO (operands[1]))
return "and%.l #0xFF,%0";
if (reg_mentioned_p (operands[0], operands[1]))
return "move%.b %1,%0\;and%.l #0xFF,%0";
return "clr%.l %0\;move%.b %1,%0";
}
else if (GET_CODE (operands[0]) == MEM
&& GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
{
operands[0] = XEXP (XEXP (operands[0], 0), 0);
return MOTOROLA ?
"clr%.l -(%0)\;move%.b %1,(3,%0)" :
"clrl %0@-\;moveb %1,%0@(3)";
}
else if (GET_CODE (operands[0]) == MEM
&& GET_CODE (XEXP (operands[0], 0)) == POST_INC)
{
operands[0] = XEXP (XEXP (operands[0], 0), 0);
return MOTOROLA ?
"clr%.l (%0)+\;move%.b %1,(-1,%0)" :
"clrl %0@+\;moveb %1,%0@(-1)";
}
else
{
output_asm_insn ("clr%.l %0", operands);
operands[0] = adjust_address (operands[0], QImode, 3);
return "move%.b %1,%0";
}
operands[2] = gen_lowpart (GET_MODE (operands[1]), operands[0]);
})
;; sign extension instructions
@ -3131,6 +3048,16 @@
""
"")
;; produced by split operations after reload finished
(define_insn "*andsi3_split"
[(set (match_operand:SI 0 "register_operand" "=d")
(and:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "const_int_operand" "i")))]
"reload_completed && !TARGET_COLDFIRE"
{
return output_andsi3 (operands);
})
(define_insn "andsi3_internal"
[(set (match_operand:SI 0 "not_sp_operand" "=m,d")
(and:SI (match_operand:SI 1 "general_operand" "%0,0")