Skip to content

unnecessary GOT lookup when calling visibility hidden or protected function #3520

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
nlewycky opened this issue Dec 1, 2008 · 6 comments
Closed
Labels
bugzilla Issues migrated from bugzilla llvm:codegen

Comments

@nlewycky
Copy link
Contributor

nlewycky commented Dec 1, 2008

Bugzilla Link 3148
Version trunk
OS Linux
CC @asl,@sunfishcode

Extended Description

GCC elides the GOT lookup when calling a hidden or protected function. Here's a quick, silly example:

  class __attribute__((visibility("hidden"))) Foo {
  public:
    void f(void) __attribute__((noinline)) {
      for (int i = 0; i < 1000000; i += 2)
        if (i < 123) f();
      return;
    }
  };
  
  void g(void) {
    Foo foo;
    foo.f();
  }

Firstly, if f() is empty, GCC inlines it into g() despite the noinline tag. I consider that naughty, and we shouldn't follow its lead there.

Secondly, GCC generates this code for g() with -O2 -fPIC:
_Z1gv:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $24, %esp
        leal    -1(%ebp), %eax
        movl    %eax, (%esp)
        call    _ZN3Foo1fEv
        leave
        ret

while LLVM produces this:

_Z1gv:
        pushl   %ebp
        movl    %esp, %ebp
        pushl   %ebx
        subl    $12, %esp
        call    .Lllvm$1.$piclabel
.Lllvm$1.$piclabel:
        popl    %ebx
        addl    $_GLOBAL_OFFSET_TABLE_ + [.-.Lllvm$1.$piclabel], %ebx
        leal    -8(%ebp), %eax
        movl    %eax, (%esp)
        call    _ZN3Foo1fEv
        addl    $12, %esp
        popl    %ebx
        popl    %ebp
        ret

Because it's hidden, the GOT lookup is unnecessary. Please eliminate it. Same with protected.

@lattner
Copy link
Collaborator

lattner commented Dec 1, 2008

Here is a somewhat analogous case on darwin (which uses a completely different pic model than linux):

void g();

class attribute((visibility("hidden"))) Foo {
public:
static void h(void) attribute((noinline)) {
g();
}
};
void f(void) attribute((noinline,visibility("hidden")));
void f(void) {
g();
}
void test(void) {
Foo::h();
f();
}

test compiles to:

call	L__ZN3Foo1hEv$stub
call	__Z1fv

... with both GCC and llvm-gcc (the former indirecting through a darwin stub, the later not).

The difference between the two is that the Foo::h compiles to having 'linkonce hidden' visibility. The merging behavior of linkonce happens before the internalization of hidden. However, would it always be safe to call directly to __ZN3Foo1hEv?

@llvmbot
Copy link
Member

llvmbot commented Dec 5, 2008

Revision 60571 fixed a related problem that have to do with GV non-lazy pointer for Darwin.

@llvmbot
Copy link
Member

llvmbot commented Dec 5, 2008

Chris, neither gcc nor llvm-gcc generates a stub indirect for your Darwin example. Can you check again?

@llvmbot
Copy link
Member

llvmbot commented Dec 5, 2008

Nevermind my previous comments. gcc does generate a stub for Foo:h. llvm-gcc does not.

@llvmbot
Copy link
Member

llvmbot commented Dec 5, 2008

On Mac OS X 10.5 and above, function stubs are automatically synthesized by dyld. That's why llvm is not emitting the stub.

@llvmbot llvmbot transferred this issue from llvm/llvm-bugzilla-archive Dec 3, 2021
Michael137 pushed a commit to Michael137/llvm-project that referenced this issue Aug 18, 2022
Support looking up absolute symbols
@philnik777
Copy link
Contributor

Looks like this got fixed in LLVM 2.9: https://godbolt.org/z/9asYxqxGK

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugzilla Issues migrated from bugzilla llvm:codegen
Projects
None yet
Development

No branches or pull requests

4 participants