bool
legitimate_constant_p (rtx x)
{
- rtx inner;
-
switch (GET_CODE (x))
{
- case SYMBOL_REF:
- /* TLS symbols are not constant. */
- if (tls_symbolic_operand (x, Pmode))
- 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
- && tls_symbolic_operand (XEXP (inner, 0), Pmode))
- return false;
+ x = XEXP (x, 0);
- if (GET_CODE (inner) == PLUS)
+ if (GET_CODE (x) == PLUS)
{
- if (GET_CODE (XEXP (inner, 1)) != CONST_INT)
+ if (GET_CODE (XEXP (x, 1)) != CONST_INT)
return false;
- inner = XEXP (inner, 0);
+ x = XEXP (x, 0);
}
- if (TARGET_MACHO && darwin_local_data_pic (inner))
+ if (TARGET_MACHO && darwin_local_data_pic (x))
return true;
- if (GET_CODE (inner) == MINUS)
- {
- if (GET_CODE (XEXP (inner, 1)) != CONST_INT)
- return false;
- inner = XEXP (inner, 0);
- }
-
/* Only some unspecs are valid as "constants". */
- if (GET_CODE (inner) == UNSPEC)
- switch (XINT (inner, 1))
+ if (GET_CODE (x) == UNSPEC)
+ switch (XINT (x, 1))
{
case UNSPEC_TPOFF:
case UNSPEC_NTPOFF:
- return local_exec_symbolic_operand (XVECEXP (inner, 0, 0), Pmode);
+ return local_exec_symbolic_operand (XVECEXP (x, 0, 0), Pmode);
case UNSPEC_DTPOFF:
- return local_dynamic_symbolic_operand (XVECEXP (inner, 0, 0), Pmode);
+ return local_dynamic_symbolic_operand (XVECEXP (x, 0, 0), Pmode);
default:
return false;
}
+
+ /* We must have drilled down to a symbol. */
+ if (!symbolic_operand (x, Pmode))
+ return false;
+ /* FALLTHRU */
+
+ case SYMBOL_REF:
+ /* TLS symbols are never valid. */
+ if (tls_symbolic_operand (x, Pmode))
+ return false;
break;
default: