diff options
Diffstat (limited to 'gcc/config/sh/sh.md')
-rw-r--r-- | gcc/config/sh/sh.md | 75 |
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]))))); }) |