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 <[email protected]>
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 } } */