[LLVMdev] Handling of pointer difference in llvm-gcc and clang
Jack Howarth
howarth at bromo.med.uc.edu
Wed Aug 10 10:12:43 PDT 2011
On Wed, Aug 10, 2011 at 06:13:16PM +0200, Duncan Sands wrote:
> Hi Stephan,
>
> > 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?
>
> in llvm-gcc (and dragonegg) this is coming directly from GCC's gimple:
>
> f (int * p, int * q)
> {
> long int D.2718;
> long int D.2717;
> long int p.1;
> long int q.0;
> int D.2714;
>
> <bb 2>:
> q.0_2 = (long int) q_1(D);
> p.1_4 = (long int) p_3(D);
> D.2717_5 = q.0_2 - p.1_4;
> D.2718_6 = D.2717_5 /[ex] 4;
> D.2714_7 = (int) D.2718_6;
> return D.2714_7;
>
> }
>
> Signed overflow in the difference of two long int (ptrdiff_t) values results in
> undefined behaviour according to the GCC type system, which is where the nsw
> flag comes from.
>
> The C front-end generates this gimple in the pointer_diff routine. The above is
> basically a direct transcription of what pointer_diff does.
>
> In short, I don't know if this is right or wrong; but if it is wrong it seems
> to be a bug in GCC's C frontend.
Shouldn't we cc this over to the gcc mailing list for clarification then?
Jack
>
> Ciao, Duncan.
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
More information about the llvm-dev
mailing list