aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2010-01-05 22:29:18 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2010-01-05 22:29:18 +0000
commit208384fdd27fc1d15c7bc0be8c1f4d8cf8ca6637 (patch)
tree74ae2545069058553587b414ac1964dc1e6fce54
parent4396e06315f0fdd09acf6eedfa4ea913b7106e96 (diff)
downloadgcc-208384fdd27fc1d15c7bc0be8c1f4d8cf8ca6637.zip
gcc-208384fdd27fc1d15c7bc0be8c1f4d8cf8ca6637.tar.gz
gcc-208384fdd27fc1d15c7bc0be8c1f4d8cf8ca6637.tar.bz2
re PR target/42564 (unrecognizable insn with -O -fPIC)
PR target/42564 * config/sparc/sparc.h (SPARC_SYMBOL_REF_TLS_P): Delete. * config/sparc/sparc-protos.h (legitimize_pic_address): Likewise. (legitimize_tls_address): Likewise. (sparc_tls_referenced_p): Likewise. * config/sparc/sparc.c (sparc_expand_move): Use legitimize_tls_address and adjust calls to legitimize_pic_address. (legitimate_constant_p) Use sparc_tls_referenced_p. (legitimate_pic_operand_p): Likewise. (sparc_legitimate_address_p): Do not use SPARC_SYMBOL_REF_TLS_P. (sparc_tls_symbol_ref_1): Delete. (sparc_tls_referenced_p): Make static, recognize specific patterns. (legitimize_tls_address): Make static, handle CONST patterns. (legitimize_pic_address): Make static, remove unused parameter and adjust recursive calls. (sparc_legitimize_address): Make static, use sparc_tls_referenced_p and adjust call to legitimize_pic_address. (sparc_output_mi_thunk): Likewise. From-SVN: r155662
-rw-r--r--gcc/ChangeLog21
-rw-r--r--gcc/config/sparc/sparc-protos.h3
-rw-r--r--gcc/config/sparc/sparc.c122
-rw-r--r--gcc/config/sparc/sparc.h3
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/tls/opt-15.c24
6 files changed, 102 insertions, 75 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index fc334da..40a277b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,24 @@
+2010-01-05 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR target/42564
+ * config/sparc/sparc.h (SPARC_SYMBOL_REF_TLS_P): Delete.
+ * config/sparc/sparc-protos.h (legitimize_pic_address): Likewise.
+ (legitimize_tls_address): Likewise.
+ (sparc_tls_referenced_p): Likewise.
+ * config/sparc/sparc.c (sparc_expand_move): Use legitimize_tls_address
+ and adjust calls to legitimize_pic_address.
+ (legitimate_constant_p) Use sparc_tls_referenced_p.
+ (legitimate_pic_operand_p): Likewise.
+ (sparc_legitimate_address_p): Do not use SPARC_SYMBOL_REF_TLS_P.
+ (sparc_tls_symbol_ref_1): Delete.
+ (sparc_tls_referenced_p): Make static, recognize specific patterns.
+ (legitimize_tls_address): Make static, handle CONST patterns.
+ (legitimize_pic_address): Make static, remove unused parameter and
+ adjust recursive calls.
+ (sparc_legitimize_address): Make static, use sparc_tls_referenced_p
+ and adjust call to legitimize_pic_address.
+ (sparc_output_mi_thunk): Likewise.
+
2010-01-05 Paolo Bonzini <bonzinI@gnu.rg>
H.J. Lu <hongjiu.lu@intel.com>
diff --git a/gcc/config/sparc/sparc-protos.h b/gcc/config/sparc/sparc-protos.h
index 097b709..b76e45b 100644
--- a/gcc/config/sparc/sparc-protos.h
+++ b/gcc/config/sparc/sparc-protos.h
@@ -64,8 +64,6 @@ extern void emit_tfmode_cvt (enum rtx_code, rtx *);
extern bool legitimate_constant_p (rtx);
extern bool constant_address_p (rtx);
extern bool legitimate_pic_operand_p (rtx);
-extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
-extern rtx legitimize_tls_address (rtx);
extern void sparc_emit_call_insn (rtx, rtx);
extern void sparc_defer_case_vector (rtx, rtx, int);
extern bool sparc_expand_move (enum machine_mode, rtx *);
@@ -97,7 +95,6 @@ extern int emit_move_sequence (rtx, enum machine_mode);
extern int fp_sethi_p (rtx);
extern int fp_mov_p (rtx);
extern int fp_high_losum_p (rtx);
-extern bool sparc_tls_referenced_p (rtx);
extern int mem_min_alignment (rtx, int);
extern int pic_address_needs_scratch (rtx);
extern int reg_unused_after (rtx, rtx);
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 82bc7d5..4b904b4 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -411,6 +411,9 @@ static bool sparc_strict_argument_naming (CUMULATIVE_ARGS *);
static void sparc_va_start (tree, rtx);
static tree sparc_gimplify_va_arg (tree, tree, gimple_seq *, gimple_seq *);
static bool sparc_vector_mode_supported_p (enum machine_mode);
+static bool sparc_tls_referenced_p (rtx);
+static rtx legitimize_tls_address (rtx);
+static rtx legitimize_pic_address (rtx, rtx);
static rtx sparc_legitimize_address (rtx, rtx, enum machine_mode);
static bool sparc_pass_by_reference (CUMULATIVE_ARGS *,
enum machine_mode, const_tree, bool);
@@ -992,34 +995,17 @@ sparc_expand_move (enum machine_mode mode, rtx *operands)
/* Fixup TLS cases. */
if (TARGET_HAVE_TLS
&& CONSTANT_P (operands[1])
- && GET_CODE (operands[1]) != HIGH
&& sparc_tls_referenced_p (operands [1]))
{
- rtx sym = operands[1];
- rtx addend = NULL;
-
- if (GET_CODE (sym) == CONST && GET_CODE (XEXP (sym, 0)) == PLUS)
- {
- addend = XEXP (XEXP (sym, 0), 1);
- sym = XEXP (XEXP (sym, 0), 0);
- }
-
- gcc_assert (SPARC_SYMBOL_REF_TLS_P (sym));
-
- sym = legitimize_tls_address (sym);
- if (addend)
- {
- sym = gen_rtx_PLUS (mode, sym, addend);
- sym = force_operand (sym, operands[0]);
- }
- operands[1] = sym;
+ operands[1] = legitimize_tls_address (operands[1]);
+ return false;
}
/* Fixup PIC cases. */
if (flag_pic && CONSTANT_P (operands[1]))
{
if (pic_address_needs_scratch (operands[1]))
- operands[1] = legitimize_pic_address (operands[1], mode, 0);
+ operands[1] = legitimize_pic_address (operands[1], NULL_RTX);
/* VxWorks does not impose a fixed gap between segments; the run-time
gap can be different from the object-file gap. We therefore can't
@@ -1047,10 +1033,8 @@ sparc_expand_move (enum machine_mode mode, rtx *operands)
if (symbolic_operand (operands[1], mode))
{
operands[1] = legitimize_pic_address (operands[1],
- mode,
- (reload_in_progress ?
- operands[0] :
- NULL_RTX));
+ reload_in_progress
+ ? operands[0] : NULL_RTX);
return false;
}
}
@@ -2979,23 +2963,11 @@ pic_address_needs_scratch (rtx x)
bool
legitimate_constant_p (rtx x)
{
- rtx inner;
-
switch (GET_CODE (x))
{
- case SYMBOL_REF:
- /* TLS symbols are not constant. */
- if (SYMBOL_REF_TLS_MODEL (x))
- return false;
- break;
-
case CONST:
- inner = XEXP (x, 0);
-
- /* Offsets of TLS symbols are never valid.
- Discourage CSE from creating them. */
- if (GET_CODE (inner) == PLUS
- && SPARC_SYMBOL_REF_TLS_P (XEXP (inner, 0)))
+ case SYMBOL_REF:
+ if (sparc_tls_referenced_p (x))
return false;
break;
@@ -3062,10 +3034,7 @@ legitimate_pic_operand_p (rtx x)
{
if (pic_address_needs_scratch (x))
return false;
- if (SPARC_SYMBOL_REF_TLS_P (x)
- || (GET_CODE (x) == CONST
- && GET_CODE (XEXP (x, 0)) == PLUS
- && SPARC_SYMBOL_REF_TLS_P (XEXP (XEXP (x, 0), 0))))
+ if (sparc_tls_referenced_p (x))
return false;
return true;
}
@@ -3103,7 +3072,7 @@ sparc_legitimate_address_p (enum machine_mode mode, rtx addr, bool strict)
&& GET_CODE (rs2) != SUBREG
&& GET_CODE (rs2) != LO_SUM
&& GET_CODE (rs2) != MEM
- && ! SPARC_SYMBOL_REF_TLS_P (rs2)
+ && !(GET_CODE (rs2) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (rs2))
&& (! symbolic_operand (rs2, VOIDmode) || mode == Pmode)
&& (GET_CODE (rs2) != CONST_INT || SMALL_INT (rs2)))
|| ((REG_P (rs1)
@@ -3143,7 +3112,8 @@ sparc_legitimate_address_p (enum machine_mode mode, rtx addr, bool strict)
rs2 = NULL;
imm1 = XEXP (rs1, 1);
rs1 = XEXP (rs1, 0);
- if (! CONSTANT_P (imm1) || SPARC_SYMBOL_REF_TLS_P (rs1))
+ if (!CONSTANT_P (imm1)
+ || (GET_CODE (rs1) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (rs1)))
return 0;
}
}
@@ -3152,7 +3122,8 @@ sparc_legitimate_address_p (enum machine_mode mode, rtx addr, bool strict)
rs1 = XEXP (addr, 0);
imm1 = XEXP (addr, 1);
- if (! CONSTANT_P (imm1) || SPARC_SYMBOL_REF_TLS_P (rs1))
+ if (!CONSTANT_P (imm1)
+ || (GET_CODE (rs1) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (rs1)))
return 0;
/* We can't allow TFmode in 32-bit mode, because an offset greater
@@ -3228,29 +3199,28 @@ sparc_tls_got (void)
return temp;
}
-/* Return 1 if *X is a thread-local symbol. */
-
-static int
-sparc_tls_symbol_ref_1 (rtx *x, void *data ATTRIBUTE_UNUSED)
-{
- return SPARC_SYMBOL_REF_TLS_P (*x);
-}
-
-/* Return 1 if X contains a thread-local symbol. */
+/* Return true if X contains a thread-local symbol. */
-bool
+static bool
sparc_tls_referenced_p (rtx x)
{
if (!TARGET_HAVE_TLS)
return false;
- return for_each_rtx (&x, &sparc_tls_symbol_ref_1, 0);
+ if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS)
+ x = XEXP (XEXP (x, 0), 0);
+
+ if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (x))
+ return true;
+
+ /* That's all we handle in legitimize_tls_address for now. */
+ return false;
}
/* ADDR contains a thread-local SYMBOL_REF. Generate code to compute
this (thread-local) address. */
-rtx
+static rtx
legitimize_tls_address (rtx addr)
{
rtx temp1, temp2, temp3, ret, o0, got, insn;
@@ -3374,21 +3344,34 @@ legitimize_tls_address (rtx addr)
gcc_unreachable ();
}
+ else if (GET_CODE (addr) == CONST)
+ {
+ rtx base, offset;
+
+ gcc_assert (GET_CODE (XEXP (addr, 0)) == PLUS);
+
+ base = legitimize_tls_address (XEXP (XEXP (addr, 0), 0));
+ offset = XEXP (XEXP (addr, 0), 1);
+
+ base = force_operand (base, NULL_RTX);
+ if (!(GET_CODE (offset) == CONST_INT && SMALL_INT (offset)))
+ offset = force_reg (Pmode, offset);
+ ret = gen_rtx_PLUS (Pmode, base, offset);
+ }
+
else
gcc_unreachable (); /* for now ... */
return ret;
}
-
/* Legitimize PIC addresses. If the address is already position-independent,
we return ORIG. Newly generated position-independent addresses go into a
reg. This is REG if nonzero, otherwise we allocate register(s) as
necessary. */
-rtx
-legitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED,
- rtx reg)
+static rtx
+legitimize_pic_address (rtx orig, rtx reg)
{
if (GET_CODE (orig) == SYMBOL_REF
/* See the comment in sparc_expand_move. */
@@ -3455,9 +3438,9 @@ legitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED,
}
gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS);
- base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
- offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
- base == reg ? 0 : reg);
+ base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), reg);
+ offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1),
+ base == reg ? NULL_RTX : reg);
if (GET_CODE (offset) == CONST_INT)
{
@@ -3490,7 +3473,7 @@ legitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED,
On SPARC, change REG+N into REG+REG, and REG+(X*Y) into REG+REG. */
-rtx
+static rtx
sparc_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
enum machine_mode mode)
{
@@ -3512,10 +3495,10 @@ sparc_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
if (x != orig_x && sparc_legitimate_address_p (mode, x, FALSE))
return x;
- if (SPARC_SYMBOL_REF_TLS_P (x))
+ if (sparc_tls_referenced_p (x))
x = legitimize_tls_address (x);
else if (flag_pic)
- x = legitimize_pic_address (x, mode, 0);
+ x = legitimize_pic_address (x, NULL_RTX);
else if (GET_CODE (x) == PLUS && CONSTANT_ADDRESS_P (XEXP (x, 1)))
x = gen_rtx_PLUS (Pmode, XEXP (x, 0),
copy_to_mode_reg (Pmode, XEXP (x, 1)));
@@ -3524,8 +3507,9 @@ sparc_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
copy_to_mode_reg (Pmode, XEXP (x, 0)));
else if (GET_CODE (x) == SYMBOL_REF
|| GET_CODE (x) == CONST
- || GET_CODE (x) == LABEL_REF)
+ || GET_CODE (x) == LABEL_REF)
x = copy_to_suggested_reg (x, NULL_RTX, Pmode);
+
return x;
}
@@ -8899,7 +8883,7 @@ sparc_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
/* Delay emitting the PIC helper function because it needs to
change the section and we are emitting assembly code. */
load_pic_register (true); /* clobbers %o7 */
- scratch = legitimize_pic_address (funexp, Pmode, scratch);
+ scratch = legitimize_pic_address (funexp, scratch);
seq = get_insns ();
end_sequence ();
emit_and_preserve (seq, spill_reg, spill_reg2);
diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h
index 58c584e..344441e 100644
--- a/gcc/config/sparc/sparc.h
+++ b/gcc/config/sparc/sparc.h
@@ -2213,9 +2213,6 @@ extern int sparc_indent_opcode;
} \
} while (0)
-#define SPARC_SYMBOL_REF_TLS_P(RTX) \
- (GET_CODE (RTX) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (RTX) != 0)
-
#define PRINT_OPERAND_PUNCT_VALID_P(CHAR) \
((CHAR) == '#' || (CHAR) == '*' || (CHAR) == '(' \
|| (CHAR) == ')' || (CHAR) == '_' || (CHAR) == '&')
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 992f310..4f6aa65 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2010-01-05 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.dg/tls/opt-15.c: New test.
+
2010-01-05 H.J. Lu <hongjiu.lu@intel.com>
* gcc.target/i386/pr42542-1.c (res): Make it 8 elements.
diff --git a/gcc/testsuite/gcc.dg/tls/opt-15.c b/gcc/testsuite/gcc.dg/tls/opt-15.c
new file mode 100644
index 0000000..bebee8a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tls/opt-15.c
@@ -0,0 +1,24 @@
+/* PR target/42564 */
+/* This used to ICE on the SPARC because of an unrecognized TLS pattern. */
+
+/* { dg-do compile } */
+/* { dg-options "-O -fPIC" } */
+/* { dg-require-effective-target tls_native } */
+/* { dg-require-effective-target fpic } */
+
+extern void *memset(void *s, int c, __SIZE_TYPE__ n);
+
+struct S1 { int i; };
+
+struct S2
+{
+ int ver;
+ struct S1 s;
+};
+
+static __thread struct S2 m;
+
+void init(void)
+{
+ memset(&m.s, 0, sizeof(m.s));
+}