[llvm-dev] i32 vs i32 signext for C int parameters to library functions

Marcin Koƛcielnicki via llvm-dev llvm-dev at lists.llvm.org
Tue Sep 6 04:10:57 PDT 2016

I'm trying to fix a longstanding bug with library function calls on 
platforms where int is passed sign-extended in a register (it badly 
affects SystemZ, and has a chance of affecting PowerPC64, SPARC64, 
MIPS64 as well).

The problem is that, on these platforms, C int corresponds to a "i32 
signext" parameter, but all LLVM passes inserting library calls 
currently use just "i32".  This means that the high bits of the argument 
will be indeterminate instead of sign-extension.

In practice, PowerPC64, SPARC64, MIPS64 tend to get zero- or 
sign-extended data anyway (since all operations are performed on whole 
registers), and the bug is hidden.  However, SystemZ has opcodes that 
actually modify only the low half of a register, so such functions tend 
to get junk in the high halves (eg. high bits of a heap address).  As a 
practical example, the compiler-rt's profile testsuite (which is 
currently disabled on SystemZ) has multiple failures due to this problem.

In addition to int parameters, the same issue also affects unsigned int 
(which should be i32, i32 zeroext, or i32 signext depending on platform) 
and return values.

To fix this bug, I need some way to tell whether to use i32 or i32 
signext in target-independent LLVM passes - but none seems to exist at 
this moment.  I wrote a patch that adds this information to TTI ( 
https://reviews.llvm.org/D21739 ), but it doesn't fit with the current 
semantics of TTI - if the information about *ext is missing, we're going 
to have correctness problems instead of merely lowered performance.

How should I best resolve this problem?

More information about the llvm-dev mailing list