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 } } */