On Sun, 10 May 2015, Jan Hubicka wrote: > You probably need to update comment here. I wonder what happens when we > optimize > indirect call to direct call to global function at RTL level? I suppose we are > safe here, because at RTL level we explicitly represent if we refer to PLT > entry > or the functionaddress itself and we never optimize one to the other? > > Patch is OK if you make sure that this works and update the comment.
I think we are safe: to have things break we'd have to have a GOT-relative memory load be combined with a branch on the RTL level, and GOT loads have UNSPEC_GOT. I have used the following example to try to induce failure: void foo(void); void bar() { void (*p)(void) = foo; p(); } With the following options: gcc -fPIC -m32 -O -foptimize-sibling-calls -fno-tree-ccp -fno-tree-copy-prop -fno-tree-fre -fno-tree-dominator-opts -fno-tree-ter GCC has indirect call after pass_expand. Without -fPIC it is transformed into direct call in pass_combine, with -fPIC it is kept as is. I've added a testcase. Below is what I'm checking in. Thanks! Index: testsuite/gcc.target/i386/pr65753.c =================================================================== --- testsuite/gcc.target/i386/pr65753.c (revision 0) +++ testsuite/gcc.target/i386/pr65753.c (revision 0) @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-options "-fPIC -O" } */ +/* { dg-final { scan-assembler-not "call" } } */ + +void foo(void (*bar)(void)) +{ + bar(); +} Index: config/i386/i386.c =================================================================== --- config/i386/i386.c (revision 223002) +++ config/i386/i386.c (working copy) @@ -5473,12 +5473,12 @@ rtx a, b; /* If we are generating position-independent code, we cannot sibcall - optimize any indirect call, or a direct call to a global function, - as the PLT requires %ebx be live. (Darwin does not have a PLT.) */ + optimize direct calls to global functions, as the PLT requires + %ebx be live. (Darwin does not have a PLT.) */ if (!TARGET_MACHO && !TARGET_64BIT && flag_pic - && (!decl || !targetm.binds_local_p (decl))) + && decl && !targetm.binds_local_p (decl)) return false;