summaryrefslogtreecommitdiff
path: root/gcc/config/sh/sh.md
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/sh/sh.md')
-rw-r--r--gcc/config/sh/sh.md75
1 files changed, 53 insertions, 22 deletions
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index 24ddc9e758..f445e73127 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -10551,12 +10551,18 @@ label:
[(set_attr "in_delay_slot" "no")
(set_attr "type" "arith")])
+;; Loads of the GOTPC relocation values must not be optimized away
+;; by e.g. any kind of CSE and must stay as they are. Although there
+;; are other various ways to ensure this, we use an artificial counter
+;; operand to generate unique symbols.
(define_expand "GOTaddr2picreg"
[(set (reg:SI R0_REG)
- (unspec:SI [(const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC))]
- UNSPEC_MOVA))
- (set (match_dup 0) (const:SI (unspec:SI [(match_dup 1)] UNSPEC_PIC)))
- (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI R0_REG)))]
+ (unspec:SI [(const:SI (unspec:SI [(match_dup 2)
+ (match_operand:SI 0 "" "")]
+ UNSPEC_PIC))] UNSPEC_MOVA))
+ (set (match_dup 1)
+ (const:SI (unspec:SI [(match_dup 2) (match_dup 0)] UNSPEC_PIC)))
+ (set (match_dup 1) (plus:SI (match_dup 1) (reg:SI R0_REG)))]
""
{
if (TARGET_VXWORKS_RTP)
@@ -10567,8 +10573,8 @@ label:
DONE;
}
- operands[0] = gen_rtx_REG (Pmode, PIC_REG);
- operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
+ operands[1] = gen_rtx_REG (Pmode, PIC_REG);
+ operands[2] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
if (TARGET_SHMEDIA)
{
@@ -10577,23 +10583,23 @@ label:
rtx lab = PATTERN (gen_call_site ());
rtx insn, equiv;
- equiv = operands[1];
- operands[1] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[1], lab),
+ equiv = operands[2];
+ operands[2] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[2], lab),
UNSPEC_PCREL_SYMOFF);
- operands[1] = gen_rtx_CONST (Pmode, operands[1]);
+ operands[2] = gen_rtx_CONST (Pmode, operands[2]);
if (Pmode == SImode)
{
- emit_insn (gen_movsi_const (pic, operands[1]));
+ emit_insn (gen_movsi_const (pic, operands[2]));
emit_insn (gen_ptrel_si (tr, pic, copy_rtx (lab)));
}
else
{
- emit_insn (gen_movdi_const (pic, operands[1]));
+ emit_insn (gen_movdi_const (pic, operands[2]));
emit_insn (gen_ptrel_di (tr, pic, copy_rtx (lab)));
}
- insn = emit_move_insn (operands[0], tr);
+ insn = emit_move_insn (operands[1], tr);
set_unique_reg_note (insn, REG_EQUAL, equiv);
@@ -10647,7 +10653,7 @@ label:
[(match_operand 0 "" "")]
"flag_pic"
{
- emit_insn (gen_GOTaddr2picreg ());
+ emit_insn (gen_GOTaddr2picreg (const0_rtx));
DONE;
})
@@ -10704,12 +10710,6 @@ label:
"__stack_chk_guard") == 0)
stack_chk_guard_p = true;
- /* Use R0 to avoid long R0 liveness which stack-protector tends to
- produce. */
- if (! sh_lra_flag
- && stack_chk_guard_p && ! reload_in_progress && ! reload_completed)
- operands[2] = gen_rtx_REG (Pmode, R0_REG);
-
if (TARGET_SHMEDIA)
{
rtx reg = operands[2];
@@ -11297,6 +11297,8 @@ label:
LABEL_NUSES (operands[2])++;
})
+;; This may be replaced with casesi_worker_2 in sh_reorg for PIC.
+;; The insn length is set to 8 for that case.
(define_insn "casesi_worker_1"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(unspec:SI [(reg:SI R0_REG)
@@ -11328,7 +11330,9 @@ label:
gcc_unreachable ();
}
}
- [(set_attr "length" "4")])
+ [(set_attr_alternative "length"
+ [(if_then_else (match_test "flag_pic") (const_int 8) (const_int 4))
+ (if_then_else (match_test "flag_pic") (const_int 8) (const_int 4))])])
(define_insn "casesi_worker_2"
[(set (match_operand:SI 0 "register_operand" "=r,r")
@@ -14683,7 +14687,22 @@ label:
|| REGNO (operands[2]) == REGNO (operands[5]))"
[(const_int 0)]
{
- sh_check_add_incdec_notes (emit_move_insn (operands[2], operands[3]));
+ if (REGNO (operands[1]) == REGNO (operands[2]))
+ operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]));
+
+ // We don't know what the new set insn will be in detail. Just make sure
+ // that it still can be recognized and the constraints are satisfied.
+ rtx_insn* i = emit_insn (gen_rtx_SET (VOIDmode, operands[2], operands[3]));
+
+ recog_data_d prev_recog_data = recog_data;
+ bool i_invalid = insn_invalid_p (i, false);
+ recog_data = prev_recog_data;
+
+ if (i_invalid)
+ FAIL;
+
+ sh_check_add_incdec_notes (i);
+
emit_insn (gen_tstsi_t (operands[2],
gen_rtx_REG (SImode, (REGNO (operands[1])))));
})
@@ -14710,7 +14729,19 @@ label:
|| REGNO (operands[2]) == REGNO (operands[5]))"
[(const_int 0)]
{
- sh_check_add_incdec_notes (emit_move_insn (operands[2], operands[3]));
+ // We don't know what the new set insn will be in detail. Just make sure
+ // that it still can be recognized and the constraints are satisfied.
+ rtx_insn* i = emit_insn (gen_rtx_SET (VOIDmode, operands[2], operands[3]));
+
+ recog_data_d prev_recog_data = recog_data;
+ bool i_invalid = insn_invalid_p (i, false);
+ recog_data = prev_recog_data;
+
+ if (i_invalid)
+ FAIL;
+
+ sh_check_add_incdec_notes (i);
+
emit_insn (gen_tstsi_t (operands[2],
gen_rtx_REG (SImode, (REGNO (operands[1])))));
})