DepressedDaniel DepressedDaniel - 8 months ago 25
C Question

How to optimize "don't care" argument with gcc?

Sometimes a function doesn't use an argument (perhaps because another "flags" argument doesn't enable a specific feature).

However, you have to specify something, so usually you just put

0
. But if you do that, and the function is external,
gcc
will emit code to "really make sure" that parameter gets set to
0
.

Is there a way to tell
gcc
that a particular argument to a function doesn't matter and it can leave alone whatever value it is that happens to be in the argument register right then?

Update: Someone asked about the XY problem. The context behind this question is I want to implement a varargs function in
x86_64
without using the compiler varargs support. This is simplest when the parameters are on the stack, so I declare my functions to take 5 or 6 dummy parameters first, so that the last non-vararg parameter and all of the vararg parameters end up on the stack. This works fine, except it's clearly not optimal - when looking at the assembly code it's clear that
gcc
is initializing all those argument registers to zero in the caller.

Answer Source

Please don't take below answer seriously. The question asks for a hack so there you go.

GCC will effectively treat value of uninitialized variable as "don't care" so we can try exploiting this:

int foo(int x, int y);

int bar_1(int y) {
  int tmp = tmp;  // Suppress uninitialized warnings
  return foo(tmp, y);
}

Unfortunately my version of GCC still cowardly initializes tmp to zero but yours may be more aggressive:

bar_1:
.LFB0:
  .cfi_startproc
  movl  %edi, %esi
  xorl  %edi, %edi
  jmp   foo
  .cfi_endproc

Another option is (ab)using inline assembly to fake GCC into thinking that tmp is defined (when in fact it isn't):

int bar_2(int y) {
  int tmp;
  asm("" : "=r"(tmp));
  return foo(tmp, y);
}

With this GCC managed to get rid of parameter initializations:

bar_2:
.LFB1:
  .cfi_startproc
  movl  %edi, %esi
  jmp   foo
  .cfi_endproc

Note that inline asm must be immediately before the function call, otherwise GCC will think it has to preserve output values which would harm register allocation.