[LLVMdev] Handling of pointer difference in llvm-gcc and clang

Stephan Falke falke at iti.uka.de
Wed Aug 10 07:37:50 PDT 2011


Hi,

We are developing a bounded model checker for C/C++ programs 
(http://baldur.iti.kit.edu/llbmc/) that operates on LLVM's intermediate 
representation.  While checking a C++ program that uses STL containers 
we noticed that llvm-gcc and clang handle pointer differences in 
disagreeing ways.

Consider the following C function:
int f(int *p, int *q)
{
     return q - p;
}

Here's the LLVM code generated by llvm-gcc (2.9):
define i32 @f(i32* %p, i32* %q) nounwind readnone {
entry:
   %0 = ptrtoint i32* %q to i32
   %1 = ptrtoint i32* %p to i32
   %2 = sub nsw i32 %0, %1
   %3 = ashr exact i32 %2, 2
   ret i32 %3
}

And here is what clang (2.9) produces:
define i32 @f(i32* %p, i32* %q) nounwind readnone {
   %1 = ptrtoint i32* %q to i32
   %2 = ptrtoint i32* %p to i32
   %3 = sub i32 %1, %2
   %4 = ashr exact i32 %3, 2
   ret i32 %4
}

Thus, llvm-gcc added the nsw flag to the sub, whereas clang didn't.

We think that clang is right and llvm-gcc is wrong:  it could be the 
case that p and q point into the same array, that q is 0x80000000, and 
that p is 0x7FFFFFFE.  Then the sub results in a signed overflow, i.e., 
sub with nsw is a trap value.

Is this a bug in llvm-gcc?

--Stephan



More information about the llvm-dev mailing list