One of the things that address_to_insn_form() is used for is determining
whether a PC-relative addressing instruction could be used. In
particular predicate pcrel_external_address and function
prefixed_paddi_p() both use it for this purpose. So what emerged in
PR/94542 is that it should be looking to see if the associated
symbol_ref is a TLS symbol of some kind. TLS symbols cannot be addressed
with PC-relative. This patch fixes both places in address_to_insn_form()
where it is looking at a symbol_ref.
Regression tests passed with trunk
38e62001c576b8c6ba2e08eb4673d69ec4c5b0f9 on ppc64le power9, and
PC-relative code is now correct. OK for trunk?
Thanks!
Aaron
2020-04-10 Aaron Sawdey <acsaw...@linux.ibm.com>
PR target/94542
* config/rs6000/rs6000.c (address_to_insn_form): Do not attempt to
use PC-relative addressing for TLS references.
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 2b6613bcb7e..c77e60a718f 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -24824,15 +24824,21 @@ address_to_insn_form (rtx addr,
if (GET_RTX_CLASS (GET_CODE (addr)) == RTX_AUTOINC)
return INSN_FORM_UPDATE;
- /* Handle PC-relative symbols and labels. Check for both local and external
- symbols. Assume labels are always local. */
+ /* Handle PC-relative symbols and labels. Check for both local and
+ external symbols. Assume labels are always local. TLS symbols
+ are not PC-relative. */
if (TARGET_PCREL)
{
- if (SYMBOL_REF_P (addr) && !SYMBOL_REF_LOCAL_P (addr))
- return INSN_FORM_PCREL_EXTERNAL;
-
- if (SYMBOL_REF_P (addr) || LABEL_REF_P (addr))
+ if (LABEL_REF_P (addr))
return INSN_FORM_PCREL_LOCAL;
+
+ if (SYMBOL_REF_P (addr) && !SYMBOL_REF_TLS_MODEL (addr))
+ {
+ if (!SYMBOL_REF_LOCAL_P (addr))
+ return INSN_FORM_PCREL_EXTERNAL;
+ else
+ return INSN_FORM_PCREL_LOCAL;
+ }
}
if (GET_CODE (addr) == CONST)
@@ -24866,14 +24872,19 @@ address_to_insn_form (rtx addr,
return INSN_FORM_BAD;
/* Check for local and external PC-relative addresses. Labels are always
- local. */
+ local. TLS symbols are not PC-relative. */
if (TARGET_PCREL)
{
- if (SYMBOL_REF_P (op0) && !SYMBOL_REF_LOCAL_P (op0))
- return INSN_FORM_PCREL_EXTERNAL;
-
- if (SYMBOL_REF_P (op0) || LABEL_REF_P (op0))
+ if (LABEL_REF_P (op0))
return INSN_FORM_PCREL_LOCAL;
+
+ if (SYMBOL_REF_P (op0) && !SYMBOL_REF_TLS_MODEL (op0))
+ {
+ if (!SYMBOL_REF_LOCAL_P (op0))
+ return INSN_FORM_PCREL_EXTERNAL;
+ else
+ return INSN_FORM_PCREL_LOCAL;
+ }
}
/* If it isn't PC-relative, the address must use a base register. */