https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116333

            Bug ID: 116333
           Summary: unused result of pure function is not optimized out
           Product: gcc
           Version: 12.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: lto
          Assignee: unassigned at gcc dot gnu.org
          Reporter: pali at kernel dot org
  Target Milestone: ---

If some function is marked with __attribute__((pure)) and return value of this
function call is not used at all then gcc could optimize out and completely
drop calling this function.

This kind of optimization does not happen for example below which uses 3 source
files with LTO enabled compilation (so gcc should see inter-file calls).


$ cat pure0.c
extern int main();

__attribute__((used))
int WinMainCRTStartup(void)
{
  char * argv[] = { "argv0", (char *)0 };
  return main(1, argv);
}

__attribute__((used))
void __main(void) {}



$ cat pure1.c
#define STARTF_USESHOWWINDOW 0x00000001
#define SW_SHOWDEFAULT 10

typedef struct _STARTUPINFOA {
  unsigned int cb;
  char* lpReserved;
  char* lpDesktop;
  char* lpTitle;
  unsigned int dwX;
  unsigned int dwY;
  unsigned int dwXSize;
  unsigned int dwYSize;
  unsigned int dwXCountChars;
  unsigned int dwYCountChars;
  unsigned int dwFillAttribute;
  unsigned int dwFlags;
  unsigned short wShowWindow;
  unsigned short cbReserved2;
  unsigned char* lpReserved2;
  void* hStdInput;
  void* hStdOutput;
  void* hStdError;
} STARTUPINFOA, *LPSTARTUPINFOA;

__declspec(dllimport) extern void __stdcall GetStartupInfoA(LPSTARTUPINFOA);

__attribute__((pure))
static int _winshowcmd (void)
{
  STARTUPINFOA StartupInfo = {};

  GetStartupInfoA(&StartupInfo);

  if (StartupInfo.dwFlags & STARTF_USESHOWWINDOW)
    return StartupInfo.wShowWindow;
  else
    return SW_SHOWDEFAULT;
}

extern int __stdcall WinMain(void *, void *, char *, int);

extern unsigned char __ImageBase[];

int main()
{
  return WinMain(&__ImageBase, (void *)0, "argv0", _winshowcmd());
}



$ cat pure2.c
__declspec(dllimport) extern int __stdcall MessageBoxA(void *, const char *,
const char *, unsigned int);

int __stdcall WinMain(void *instance __attribute__((unused)), void
*prev_instance __attribute__((unused)), char *cmdln __attribute__((unused)),
int showcmd __attribute__((unused))) {
  MessageBoxA((void *)0, "Message", "Title", 0);
  return 0;
}



Two additional helper files are needed to have example self-contained without
any external dependency and also executable on windows:

$ cat kernel32.def
LIBRARY "kernel32.dll"
EXPORTS
GetStartupInfoA@4

$ cat user32.def
LIBRARY "user32.dll"
EXPORTS
MessageBoxA@16


Compile these sources as:

$ i686-w64-mingw32-dlltool -d kernel32.def -k -l libkernel32.a
$ i686-w64-mingw32-dlltool -d user32.def -k -l libuser32.a
$ i686-w64-mingw32-gcc pure0.c pure1.c pure2.c -o pure.exe -mwindows
-nostartfiles -nostdlib libkernel32.a libuser32.a
-Wl,--disable-runtime-pseudo-reloc -W -Wall -Os -flto


objdump on compiled pure.exe shows:


$ objdump -d pure.exe

pure.exe:     file format pei-i386


Disassembly of section .text:

00401000 <_WinMainCRTStartup>:
  401000:       55                      push   %ebp
  401001:       31 c0                   xor    %eax,%eax
  401003:       b9 11 00 00 00          mov    $0x11,%ecx
  401008:       89 e5                   mov    %esp,%ebp
  40100a:       57                      push   %edi
  40100b:       8d 7d b4                lea    -0x4c(%ebp),%edi
  40100e:       83 ec 64                sub    $0x64,%esp
  401011:       f3 ab                   rep stos %eax,%es:(%edi)
  401013:       8d 45 b4                lea    -0x4c(%ebp),%eax
  401016:       89 04 24                mov    %eax,(%esp)
  401019:       ff 15 4c 40 40 00       call   *0x40404c
  40101f:       31 d2                   xor    %edx,%edx
  401021:       31 c9                   xor    %ecx,%ecx
  401023:       50                      push   %eax
  401024:       89 54 24 0c             mov    %edx,0xc(%esp)
  401028:       c7 44 24 08 00 20 40    movl   $0x402000,0x8(%esp)
  40102f:       00 
  401030:       c7 44 24 04 06 20 40    movl   $0x402006,0x4(%esp)
  401037:       00 
  401038:       89 0c 24                mov    %ecx,(%esp)
  40103b:       ff 15 54 40 40 00       call   *0x404054
  401041:       8b 7d fc                mov    -0x4(%ebp),%edi
  401044:       31 c0                   xor    %eax,%eax
  401046:       83 ec 10                sub    $0x10,%esp
  401049:       c9                      leave  
  40104a:       c3                      ret    

0040104b <___main>:
  40104b:       c3                      ret    

0040104c <_GetStartupInfoA@4>:
  40104c:       ff 25 4c 40 40 00       jmp    *0x40404c
  401052:       90                      nop
  401053:       90                      nop

00401054 <_MessageBoxA@16>:
  401054:       ff 25 54 40 40 00       jmp    *0x404054
  40105a:       90                      nop
  40105b:       90                      nop

0040105c <__CTOR_LIST__>:
  40105c:       ff                      (bad)  
  40105d:       ff                      (bad)  
  40105e:       ff                      (bad)  
  40105f:       ff 00                   incl   (%eax)
  401061:       00 00                   add    %al,(%eax)
        ...

00401064 <__DTOR_LIST__>:
  401064:       ff                      (bad)  
  401065:       ff                      (bad)  
  401066:       ff                      (bad)  
  401067:       ff 00                   incl   (%eax)
  401069:       00 00                   add    %al,(%eax)
        ...



Function GetStartupInfoA() was called only in _winshowcmd() function and return
value of _winshowcmd() function is unused. So _winshowcmd() function is marked
as pure and its return value is unused then gcc could completely optimize out
_winshowcmd() function call in LTO build. But objdump on above example shows
that gcc had not dropped _winshowcmd() function and it is there.

Changing __attribute__((pure)) to __attribute__((const)) for _winshowcmd()
function does not help gcc to optimize out the _winshowcmd() function call.

Reply via email to