aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOleg Endo <olegendo@gcc.gnu.org>2015-09-27 11:55:55 +0000
committerOleg Endo <olegendo@gcc.gnu.org>2015-09-27 11:55:55 +0000
commita981b74355fa292aafc277543f678b56b9871247 (patch)
tree4fa085f3255ae67192e23e273788e277cb1897f4
parentf11a7b6d57f6fcba1bf2e5a0403dc49120195320 (diff)
downloadgcc-a981b74355fa292aafc277543f678b56b9871247.zip
gcc-a981b74355fa292aafc277543f678b56b9871247.tar.gz
gcc-a981b74355fa292aafc277543f678b56b9871247.tar.bz2
re PR target/67391 ([SH] Convert clrt addc to normal add insn)
gcc/ PR target/67391 * config/sh/sh-protos.h (sh_lra_p): Declare. * config/sh/sh.c (sh_lra_p): Make non-static. * config/sh/sh.md (addsi3): Use arith_reg_dest for operands[0] and arith_reg_operand for operands[1]. Remove TARGET_SHMEDIA case. Expand into addsi3_scr if operands[2] if needed. (*addsi3_compact): Rename to *addsi3_compact_lra. Use arith_reg_operand for operands[1]. Allow it only when LRA is enabled. (addsi3_scr, *addsi3): New insn_and_split patterns. Co-Authored-By: Kaz Kojima <kkojima@gcc.gnu.org> From-SVN: r228176
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/config/sh/sh-protos.h1
-rw-r--r--gcc/config/sh/sh.c3
-rw-r--r--gcc/config/sh/sh.md83
4 files changed, 89 insertions, 11 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 6e4fbe4..9734b08 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,16 @@
+2015-09-27 Oleg Endo <olegendo@gcc.gnu.org>
+ Kaz Kojima <kkojima@gcc.gnu.org>
+
+ PR target/67391
+ * config/sh/sh-protos.h (sh_lra_p): Declare.
+ * config/sh/sh.c (sh_lra_p): Make non-static.
+ * config/sh/sh.md (addsi3): Use arith_reg_dest for operands[0] and
+ arith_reg_operand for operands[1]. Remove TARGET_SHMEDIA case.
+ Expand into addsi3_scr if operands[2] if needed.
+ (*addsi3_compact): Rename to *addsi3_compact_lra. Use
+ arith_reg_operand for operands[1]. Allow it only when LRA is enabled.
+ (addsi3_scr, *addsi3): New insn_and_split patterns.
+
2015-09-27 Alexandre Oliva <aoliva@redhat.com>
PR rtl-optimization/64164
diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h
index 916fe04..f94459f 100644
--- a/gcc/config/sh/sh-protos.h
+++ b/gcc/config/sh/sh-protos.h
@@ -93,6 +93,7 @@ extern rtx sh_fsca_sf2int (void);
extern rtx sh_fsca_int2sf (void);
/* Declare functions defined in sh.c and used in templates. */
+extern bool sh_lra_p (void);
extern const char *output_branch (int, rtx_insn *, rtx *);
extern const char *output_ieee_ccmpeq (rtx_insn *, rtx *);
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index 3b83dcc..1a85972 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -216,7 +216,6 @@ static int sh_mode_after (int, int, rtx_insn *);
static int sh_mode_entry (int);
static int sh_mode_exit (int);
static int sh_mode_priority (int entity, int n);
-static bool sh_lra_p (void);
static rtx mark_constant_pool_use (rtx);
static tree sh_handle_interrupt_handler_attribute (tree *, tree, tree,
@@ -14507,7 +14506,7 @@ sh_mode_priority (int entity ATTRIBUTE_UNUSED, int n)
*/
/* Return true if we use LRA instead of reload pass. */
-static bool
+bool
sh_lra_p (void)
{
return sh_lra_flag;
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index 3dcb1cd..8a388bc 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -2122,13 +2122,19 @@
})
(define_expand "addsi3"
- [(set (match_operand:SI 0 "arith_reg_operand" "")
- (plus:SI (match_operand:SI 1 "arith_operand" "")
- (match_operand:SI 2 "arith_or_int_operand" "")))]
+ [(set (match_operand:SI 0 "arith_reg_dest")
+ (plus:SI (match_operand:SI 1 "arith_reg_operand")
+ (match_operand:SI 2 "arith_or_int_operand")))]
""
{
- if (TARGET_SHMEDIA)
- operands[1] = force_reg (SImode, operands[1]);
+ if (TARGET_SH1 && !arith_operand (operands[2], SImode))
+ {
+ if (!sh_lra_p () || reg_overlap_mentioned_p (operands[0], operands[1]))
+ {
+ emit_insn (gen_addsi3_scr (operands[0], operands[1], operands[2]));
+ DONE;
+ }
+ }
})
(define_insn "addsi3_media"
@@ -2163,15 +2169,22 @@
;; copy or constant load before the actual add insn.
;; Use u constraint for that case to avoid the invalid value in the stack
;; pointer.
-(define_insn_and_split "*addsi3_compact"
+;; This also results in better code when LRA is not used. However, we have
+;; to use different sets of patterns and the order of these patterns is
+;; important.
+;; In some cases the constant zero might end up in operands[2] of the
+;; patterns. We have to accept that and convert it into a reg-reg move.
+(define_insn_and_split "*addsi3_compact_lra"
[(set (match_operand:SI 0 "arith_reg_dest" "=r,&u")
- (plus:SI (match_operand:SI 1 "arith_operand" "%0,r")
+ (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0,r")
(match_operand:SI 2 "arith_or_int_operand" "rI08,rn")))]
- "TARGET_SH1"
+ "TARGET_SH1 && sh_lra_p ()
+ && (! reg_overlap_mentioned_p (operands[0], operands[1])
+ || arith_operand (operands[2], SImode))"
"@
add %2,%0
#"
- "reload_completed
+ "&& reload_completed
&& ! reg_overlap_mentioned_p (operands[0], operands[1])"
[(set (match_dup 0) (match_dup 2))
(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
@@ -2182,6 +2195,58 @@
}
[(set_attr "type" "arith")])
+(define_insn_and_split "addsi3_scr"
+ [(set (match_operand:SI 0 "arith_reg_dest" "=r,&u,&u")
+ (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0,r,r")
+ (match_operand:SI 2 "arith_or_int_operand" "rI08,r,n")))
+ (clobber (match_scratch:SI 3 "=X,X,&u"))]
+ "TARGET_SH1"
+ "@
+ add %2,%0
+ #
+ #"
+ "&& reload_completed"
+ [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))]
+{
+ if (operands[2] == const0_rtx)
+ {
+ emit_move_insn (operands[0], operands[1]);
+ DONE;
+ }
+
+ if (CONST_INT_P (operands[2]) && !satisfies_constraint_I08 (operands[2]))
+ {
+ if (reg_overlap_mentioned_p (operands[0], operands[1]))
+ {
+ emit_move_insn (operands[3], operands[2]);
+ emit_move_insn (operands[0], operands[1]);
+ operands[2] = operands[3];
+ }
+ else
+ {
+ emit_move_insn (operands[0], operands[2]);
+ operands[2] = operands[1];
+ }
+ }
+ else if (!reg_overlap_mentioned_p (operands[0], operands[1]))
+ emit_move_insn (operands[0], operands[1]);
+}
+ [(set_attr "type" "arith")])
+
+(define_insn_and_split "*addsi3"
+ [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
+ (plus:SI (match_operand:SI 1 "arith_reg_operand" "%0,r")
+ (match_operand:SI 2 "arith_operand" "rI08,Z")))]
+ "TARGET_SH1 && !sh_lra_p ()"
+ "@
+ add %2,%0
+ #"
+ "&& operands[2] == const0_rtx"
+ [(set (match_dup 0) (match_dup 1))]
+{
+}
+ [(set_attr "type" "arith")])
+
;; -------------------------------------------------------------------------
;; Subtraction instructions
;; -------------------------------------------------------------------------