Jeff Law writes:

> On 06/23/2015 02:29 AM, Ramana Radhakrishnan wrote:
>
>>> If you try disabling the REG_EQUAL note generation [*], you'll probably 
>>> find a
>>> performance regression on arm32 (and probably on aarch64 as well?
>>> we only
>>
>> IMHO disabling the REG_EQUAL note generation is the wrong way to go about 
>> this.
> Agreed.
>
>> Irrespective of combine, as a first step we should fix the predicates
>> and the call expanders to prevent this sort of replacement in the
>> backends. Tightening the predicates in the call patterns will achieve
>> the same for you and then we can investigate the use of GOT_PREL. My
>> recollection of this is that you need to work out when it's more
>> beneficial to use GOT_PREL over GOT but it's been a while since I
>> looked in that area.
> Also agreed.  This is primarily a backend issue with the call patterns.
>
> This is similar to the situation on the PA with the 32bit SOM runtime 
> where direct and indirect calls have different calling conventions. 
> Those different calling conventions combined with the early loading of 
> the parameter registers in effect restricts us from being able to 
> transform an indirect call into a direct call (combine) or vice-versa (cse).
>
> The way we handled this was to split the calls into two patterns, one 
> for direct one for indirect and tightening their predicates appropriately.
>
> Jeff

Attachment is the patch which repair -fno-plt support for AArch64.

aarch64_is_noplt_call_p will only be true if:

  * gcc is generating position independent code.
  * function symbol has declaration.
  * either -fno-plt or "(no_plt)" attribute specified.
  * it's a external function.
  
OK for trunk?

2015-07-16  Jiong Wang  <jiong.w...@arm.com>

gcc/
  * config/aarch64/aarch64-protos.h (aarch64_is_noplt_call_p): New
  declaration.
  * config/aarch64/aarch64.c (aarch64_is_noplt_call_p): New function.
  * config/aarch64/aarch64.md (call_value_symbol): Check noplt
  scenarios.
  (call_symbol): Ditto.

gcc/testsuite/
  * gcc.target/aarch64/noplt_1.c: New testcase.
  * gcc.target/aarch64/noplt_2.c: Ditto.

diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index 4062c27..c354dc6 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -254,6 +254,7 @@ bool aarch64_gen_movmemqi (rtx *);
 bool aarch64_gimple_fold_builtin (gimple_stmt_iterator *);
 bool aarch64_is_extend_from_extract (machine_mode, rtx, rtx);
 bool aarch64_is_long_call_p (rtx);
+bool aarch64_is_noplt_call_p (rtx);
 bool aarch64_label_mentioned_p (rtx);
 bool aarch64_legitimate_pic_operand_p (rtx);
 bool aarch64_modes_tieable_p (machine_mode mode1,
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 5d4dc83..4522fc2 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -747,6 +747,24 @@ aarch64_is_long_call_p (rtx sym)
   return aarch64_decl_is_long_call_p (SYMBOL_REF_DECL (sym));
 }
 
+/* Return true if calls to symbol-ref SYM should not go through
+   plt stubs.  */
+
+bool
+aarch64_is_noplt_call_p (rtx sym)
+{
+  const_tree decl = SYMBOL_REF_DECL (sym);
+
+  if (flag_pic
+      && decl
+      && (!flag_plt
+	  || lookup_attribute ("noplt", DECL_ATTRIBUTES (decl)))
+      && !targetm.binds_local_p (decl))
+    return true;
+
+  return false;
+}
+
 /* Return true if the offsets to a zero/sign-extract operation
    represent an expression that matches an extend operation.  The
    operands represent the paramters from
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 2d56a75..b88aac2 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -603,7 +603,8 @@
    (use (match_operand 2 "" ""))
    (clobber (reg:DI LR_REGNUM))]
   "GET_CODE (operands[0]) == SYMBOL_REF
-   && !aarch64_is_long_call_p (operands[0])"
+   && !aarch64_is_long_call_p (operands[0])
+   && !aarch64_is_noplt_call_p (operands[0])"
   "bl\\t%a0"
   [(set_attr "type" "call")]
 )
@@ -665,7 +666,8 @@
    (use (match_operand 3 "" ""))
    (clobber (reg:DI LR_REGNUM))]
   "GET_CODE (operands[1]) == SYMBOL_REF
-   && !aarch64_is_long_call_p (operands[1])"
+   && !aarch64_is_long_call_p (operands[1])
+   && !aarch64_is_noplt_call_p (operands[1])"
   "bl\\t%a1"
   [(set_attr "type" "call")]
 )
diff --git a/gcc/testsuite/gcc.target/aarch64/noplt_1.c b/gcc/testsuite/gcc.target/aarch64/noplt_1.c
new file mode 100644
index 0000000..4d778a4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/noplt_1.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fpic -fno-plt" } */
+
+int* bar (void) ;
+
+int
+foo (int a)
+{
+  int *b = bar ();
+  return b[a];
+}
+
+/* { dg-final { scan-assembler "#:got_lo12:" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/noplt_2.c b/gcc/testsuite/gcc.target/aarch64/noplt_2.c
new file mode 100644
index 0000000..226737a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/noplt_2.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fpic" } */
+
+__attribute__ ((noplt))
+int* bar0 (void) ;
+int* bar1 (void) ;
+
+int
+foo (int a)
+{
+  int *b0 = bar0 ();
+  int *b1 = bar1 ();
+  return b0[a] + b1[a];
+}
+
+/* { dg-final { scan-assembler-times "#:got_lo12:" 1 } } */

Reply via email to