Commit 5e6c8b64 by Richard Henderson Committed by Richard Henderson

re PR target/21412 (ICE loading TLS address)

        PR target/21412
        * config/ia64/ia64.c (TARGET_CANNOT_FORCE_CONST_MEM): New.
        (ia64_cannot_force_const_mem): New.
        (tls_symbolic_operand_type): New.
        (ia64_legitimate_constant_p): New.
        (ia64_expand_load_address): Return true on success.  Improve
        checks for when we should not split.
        (ia64_expand_tls_address): New addend operand.  Distribute it
        as appropriate to the tls_kind.  Delay referencing gp.
        (ia64_expand_move): Split symbolic addend as necessary.  Handle
        tls symbols with addends.
        * config/ia64/ia64-protos.h: Update.
        * config/ia64/ia64.h (CALL_REALLY_USED_REGISTERS): False for r0,
        p0, f0, f1, and r13.
        (LEGITIMATE_CONSTANT_P): Move to ia64_legitimate_constant_p.
        * config/ia64/ia64.md (UNSPEC_DTPMOD): New.
        (symbolic_operand splitter): Pass everything through
        ia64_expand_load_address and FAIL or DONE as appropriate.
        (load_fptr): Only accept after reload.
        (load_fptr_internal1, gprel64_offset, load_gprel64, load_symptr_high,
        load_symptr_low, load_ltoff_dtpmod,
        (load_dtpmod): New.
        (load_dtprel): Only accept tls symbols.
        (load_dtprel64, load_dtprel22): Likewise.
        (load_tprel, load_tprel64, load_tprel22): Likewise.
        (load_dtprel_gd, load_ltoff_dtprel, load_tprel_ie): New.
        (add_dtprel): Only accept tls symbols.  Canonicalize PLUS.
        (add_dtprel14, add_dtprel22): Likewise.
        (add_tprel, add_tprel14, add_tprel22): Likewise.
        * config/ia64/predicates.md (small_addr_symbolic_operand): New.
        (any_offset_symbol_operand, aligned_offset_symbol_operand): New.
        (got_symbolic_operand): Check CONST offsets.
        (tls_symbolic_operand, ld_tls_symbolic_operand): New.
        (ie_tls_symbolic_operand, le_tls_symbolic_operand): New.
        (move_operand): Don't handle tls here.  Check CONST offsets.

From-SVN: r99596
parent b3315253
2005-05-11 Richard Henderson <rth@redhat.com>
PR target/21412
* config/ia64/ia64.c (TARGET_CANNOT_FORCE_CONST_MEM): New.
(ia64_cannot_force_const_mem): New.
(tls_symbolic_operand_type): New.
(ia64_legitimate_constant_p): New.
(ia64_expand_load_address): Return true on success. Improve
checks for when we should not split.
(ia64_expand_tls_address): New addend operand. Distribute it
as appropriate to the tls_kind. Delay referencing gp.
(ia64_expand_move): Split symbolic addend as necessary. Handle
tls symbols with addends.
* config/ia64/ia64-protos.h: Update.
* config/ia64/ia64.h (CALL_REALLY_USED_REGISTERS): False for r0,
p0, f0, f1, and r13.
(LEGITIMATE_CONSTANT_P): Move to ia64_legitimate_constant_p.
* config/ia64/ia64.md (UNSPEC_DTPMOD): New.
(symbolic_operand splitter): Pass everything through
ia64_expand_load_address and FAIL or DONE as appropriate.
(load_fptr): Only accept after reload.
(load_fptr_internal1, gprel64_offset, load_gprel64, load_symptr_high,
load_symptr_low, load_ltoff_dtpmod,
(load_dtpmod): New.
(load_dtprel): Only accept tls symbols.
(load_dtprel64, load_dtprel22): Likewise.
(load_tprel, load_tprel64, load_tprel22): Likewise.
(load_dtprel_gd, load_ltoff_dtprel, load_tprel_ie): New.
(add_dtprel): Only accept tls symbols. Canonicalize PLUS.
(add_dtprel14, add_dtprel22): Likewise.
(add_tprel, add_tprel14, add_tprel22): Likewise.
* config/ia64/predicates.md (small_addr_symbolic_operand): New.
(any_offset_symbol_operand, aligned_offset_symbol_operand): New.
(got_symbolic_operand): Check CONST offsets.
(tls_symbolic_operand, ld_tls_symbolic_operand): New.
(ie_tls_symbolic_operand, le_tls_symbolic_operand): New.
(move_operand): Don't handle tls here. Check CONST offsets.
2005-05-11 Richard Sandiford <rsandifo@redhat.com>
* config/mips/7000.md (rm7_impy_si_mult): Just match imul and imadd.
......
......@@ -37,6 +37,7 @@ extern int ia64_produce_address_p (rtx);
extern bool ia64_const_ok_for_letter_p (HOST_WIDE_INT, char);
extern bool ia64_const_double_ok_for_letter_p (rtx, char);
extern bool ia64_extra_constraint (rtx, char);
extern bool ia64_legitimate_constant_p (rtx);
extern rtx ia64_expand_move (rtx, rtx);
extern int ia64_move_ok (rtx, rtx);
......@@ -58,7 +59,7 @@ extern void ia64_expand_prologue (void);
extern void ia64_expand_epilogue (int);
extern int ia64_direct_return (void);
extern void ia64_expand_load_address (rtx, rtx);
extern bool ia64_expand_load_address (rtx, rtx);
extern int ia64_hard_regno_rename_ok (int, int);
extern void ia64_initialize_trampoline (rtx, rtx, rtx);
......
......@@ -454,7 +454,7 @@ while (0)
#define CALL_REALLY_USED_REGISTERS \
{ /* General registers. */ \
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, \
0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
......@@ -463,7 +463,7 @@ while (0)
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, \
/* Floating-point registers. */ \
1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
......@@ -472,7 +472,7 @@ while (0)
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
/* Predicate registers. */ \
1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
......@@ -1410,10 +1410,7 @@ do { \
/* A C expression that is nonzero if X is a legitimate constant for an
immediate operand on the target machine. */
#define LEGITIMATE_CONSTANT_P(X) \
(GET_CODE (X) != CONST_DOUBLE || GET_MODE (X) == VOIDmode \
|| GET_MODE (X) == DImode || CONST_DOUBLE_OK_FOR_G (X)) \
#define LEGITIMATE_CONSTANT_P(X) ia64_legitimate_constant_p (X)
/* Condition Code Status */
......
......@@ -34,42 +34,6 @@
(and (match_code "symbol_ref")
(match_test "SYMBOL_REF_FUNCTION_P (op)")))
;; True if OP refers to a symbol, and is appropriate for a GOT load.
(define_predicate "got_symbolic_operand"
(match_operand 0 "symbolic_operand" "")
{
switch (GET_CODE (op))
{
case LABEL_REF:
return true;
case SYMBOL_REF:
/* This sort of load should not be used for things in sdata. */
return !SYMBOL_REF_SMALL_ADDR_P (op);
case CONST:
/* Accept only (plus (symbol_ref) (const_int)). */
op = XEXP (op, 0);
if (GET_CODE (op) != PLUS
|| GET_CODE (XEXP (op, 0)) != SYMBOL_REF
|| GET_CODE (XEXP (op, 1)) != CONST_INT)
return false;
/* Ok if we're not using GOT entries at all. */
if (TARGET_NO_PIC || TARGET_AUTO_PIC)
return true;
/* The low 14 bits of the constant have been forced to zero
by ia64_expand_load_address, so that we do not use up so
many GOT entries. Prevent cse from undoing this. */
op = XEXP (op, 1);
return (INTVAL (op) & 0x3fff) == 0;
default:
gcc_unreachable ();
}
})
;; True if OP refers to a symbol in the sdata section.
(define_predicate "sdata_symbolic_operand"
(match_code "symbol_ref,const")
......@@ -129,6 +93,187 @@
}
})
;; True if OP refers to a symbol in the small address area.
(define_predicate "small_addr_symbolic_operand"
(match_code "symbol_ref,const")
{
switch (GET_CODE (op))
{
case CONST:
op = XEXP (op, 0);
if (GET_CODE (op) != PLUS
|| GET_CODE (XEXP (op, 0)) != SYMBOL_REF
|| GET_CODE (XEXP (op, 1)) != CONST_INT)
return false;
op = XEXP (op, 0);
/* FALLTHRU */
case SYMBOL_REF:
return SYMBOL_REF_SMALL_ADDR_P (op);
default:
gcc_unreachable ();
}
})
;; True if OP refers to a symbol with which we may use any offset.
(define_predicate "any_offset_symbol_operand"
(match_code "symbol_ref")
{
if (TARGET_NO_PIC || TARGET_AUTO_PIC)
return true;
if (SYMBOL_REF_SMALL_ADDR_P (op))
return true;
if (SYMBOL_REF_FUNCTION_P (op))
return false;
if (sdata_symbolic_operand (op, mode))
return true;
return false;
})
;; True if OP refers to a symbol with which we may use 14-bit aligned offsets.
;; False if OP refers to a symbol with which we may not use any offset at any
;; time.
(define_predicate "aligned_offset_symbol_operand"
(and (match_code "symbol_ref")
(match_test "! SYMBOL_REF_FUNCTION_P (op)")))
;; True if OP refers to a symbol, and is appropriate for a GOT load.
(define_predicate "got_symbolic_operand"
(match_operand 0 "symbolic_operand" "")
{
HOST_WIDE_INT addend = 0;
switch (GET_CODE (op))
{
case LABEL_REF:
return true;
case CONST:
/* Accept only (plus (symbol_ref) (const_int)). */
op = XEXP (op, 0);
if (GET_CODE (op) != PLUS
|| GET_CODE (XEXP (op, 0)) != SYMBOL_REF
|| GET_CODE (XEXP (op, 1)) != CONST_INT)
return false;
addend = INTVAL (XEXP (op, 1));
op = XEXP (op, 0);
/* FALLTHRU */
case SYMBOL_REF:
/* These symbols shouldn't be used with got loads. */
if (SYMBOL_REF_SMALL_ADDR_P (op))
return false;
if (SYMBOL_REF_TLS_MODEL (op) != 0)
return false;
if (any_offset_symbol_operand (op, mode))
return true;
/* The low 14 bits of the constant have been forced to zero
so that we do not use up so many GOT entries. Prevent cse
from undoing this. */
if (aligned_offset_symbol_operand (op, mode))
return (addend & 0x3fff) == 0;
return addend == 0;
default:
gcc_unreachable ();
}
})
;; Return true if OP is a valid thread local storage symbolic operand.
(define_predicate "tls_symbolic_operand"
(match_code "symbol_ref,const")
{
switch (GET_CODE (op))
{
case SYMBOL_REF:
return SYMBOL_REF_TLS_MODEL (op) != 0;
case CONST:
op = XEXP (op, 0);
if (GET_CODE (op) != PLUS
|| GET_CODE (XEXP (op, 0)) != SYMBOL_REF
|| GET_CODE (XEXP (op, 1)) != CONST_INT)
return false;
/* We only allow certain offsets for certain tls models. */
switch (SYMBOL_REF_TLS_MODEL (XEXP (op, 0)))
{
case TLS_MODEL_GLOBAL_DYNAMIC:
case TLS_MODEL_LOCAL_DYNAMIC:
return false;
case TLS_MODEL_INITIAL_EXEC:
return (INTVAL (XEXP (op, 1)) & 0x3fff) == 0;
case TLS_MODEL_LOCAL_EXEC:
return true;
default:
return false;
}
default:
gcc_unreachable ();
}
})
;; Return true if OP is a local-dynamic thread local storage symbolic operand.
(define_predicate "ld_tls_symbolic_operand"
(and (match_code "symbol_ref")
(match_test "SYMBOL_REF_TLS_MODEL (op) == TLS_MODEL_LOCAL_DYNAMIC")))
;; Return true if OP is an initial-exec thread local storage symbolic operand.
(define_predicate "ie_tls_symbolic_operand"
(match_code "symbol_ref,const")
{
switch (GET_CODE (op))
{
case CONST:
op = XEXP (op, 0);
if (GET_CODE (op) != PLUS
|| GET_CODE (XEXP (op, 0)) != SYMBOL_REF
|| GET_CODE (XEXP (op, 1)) != CONST_INT
|| (INTVAL (XEXP (op, 1)) & 0x3fff) != 0)
return false;
op = XEXP (op, 0);
/* FALLTHRU */
case SYMBOL_REF:
return SYMBOL_REF_TLS_MODEL (op) == TLS_MODEL_INITIAL_EXEC;
default:
gcc_unreachable ();
}
})
;; Return true if OP is a local-exec thread local storage symbolic operand.
(define_predicate "le_tls_symbolic_operand"
(match_code "symbol_ref,const")
{
switch (GET_CODE (op))
{
case CONST:
op = XEXP (op, 0);
if (GET_CODE (op) != PLUS
|| GET_CODE (XEXP (op, 0)) != SYMBOL_REF
|| GET_CODE (XEXP (op, 1)) != CONST_INT)
return false;
op = XEXP (op, 0);
/* FALLTHRU */
case SYMBOL_REF:
return SYMBOL_REF_TLS_MODEL (op) == TLS_MODEL_LOCAL_EXEC;
default:
gcc_unreachable ();
}
})
;; Like nonimmediate_operand, but don't allow MEMs that try to use a
;; POST_MODIFY with a REG as displacement.
(define_predicate "destination_operand"
......@@ -142,11 +287,51 @@
(and (match_operand 0 "memory_operand")
(match_test "GET_RTX_CLASS (GET_CODE (XEXP (op, 0))) != RTX_AUTOINC")))
;; True if OP is a general operand, excluding tls symbolic operands.
;; True if OP is a general operand, with some restrictions on symbols.
(define_predicate "move_operand"
(and (match_operand 0 "general_operand")
(not (match_test
"GET_CODE (op) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (op)"))))
(match_operand 0 "general_operand")
{
switch (GET_CODE (op))
{
case CONST:
{
HOST_WIDE_INT addend;
/* Accept only (plus (symbol_ref) (const_int)). */
op = XEXP (op, 0);
if (GET_CODE (op) != PLUS
|| GET_CODE (XEXP (op, 0)) != SYMBOL_REF
|| GET_CODE (XEXP (op, 1)) != CONST_INT)
return false;
addend = INTVAL (XEXP (op, 1));
op = XEXP (op, 0);
/* After reload, we want to allow any offset whatsoever. This
allows reload the opportunity to avoid spilling addresses to
the stack, and instead simply substitute in the value from a
REG_EQUIV. We'll split this up again when splitting the insn. */
if (reload_in_progress || reload_completed)
return true;
/* Some symbol types we allow to use with any offset. */
if (any_offset_symbol_operand (op, mode))
return true;
/* Some symbol types we allow offsets with the low 14 bits of the
constant forced to zero so that we do not use up so many GOT
entries. We want to prevent cse from undoing this. */
if (aligned_offset_symbol_operand (op, mode))
return (addend & 0x3fff) == 0;
/* The remaining symbol types may never be used with an offset. */
return false;
}
default:
return true;
}
})
;; True if OP is a register operand that is (or could be) a GR reg.
(define_predicate "gr_register_operand"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment