Re: [PATCH] fix casts when linearizing compound assignments

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Jun 8, 2012, at 4:16 PM, Linus Torvalds wrote:
> 
> Looking at the LLVM API docs that Xi referred to, the LLVM preference
> is actually pretty weak.
> 
> So I'd almost say continue with the current IR, and just do the
> pointer arithmetic by hand. If LLVM doesn't treat GEP *that*
> specially, doing a separate pointer arithmetic level is quite possibly
> going to just cause problems: simplification of combinations of GEP
> and arithmetic is potentially quite annoying and has problems that
> simplification of perfectly regular addition does not.

I tried a simple strategy to emit an offset:

1) cast the pointer to i8* (char*);

2) emit GEP with the offset computed by sparse;

3) cast the pointer back to its original type.

There is no pointer-integer conversion at all.  This seems to work
well with both current IR and LLVM's optimizer.

Here are some examples, using my experimental backend "splay".

  struct X { int a, b; };

  void szero(struct X *x)
  {
    x->a = 0;
    x->b = 0;
  }

splay (with opt -O2) emits:

  %0 = getelementptr inbounds %struct.X* %x, i64 0, i32 0
  store i32 0, i32* %0, align 4
  %1 = getelementptr inbounds %struct.X* %x, i64 0, i32 1
  store i32 0, i32* %1, align 4

LLVM's optimizer is even able to "recover" GEP x, 0, 1 for x->b,
from what splay (without opt) actually emits:

  %4 = bitcast %struct.X* %x to i32*
  %5 = bitcast i32* %4 to i8*
  %6 = getelementptr inbounds i8* %5, i64 4

Here's an example of variable offset.

  void izero(int *x, size_t n)
  {
    x[n] = 0;
  }

splay (with opt -O2) emits:

  %0 = shl nsw i64 %n, 2
  %1 = bitcast i32* %x to i8*
  %2 = getelementptr inbounds i8* %1, i64 %0
  %3 = bitcast i8* %2 to i32*
  store i32 0, i32* %3, align 4

This time the result doesn't look as perfect as Clang, which emits
GEP %x, %n, but the assembly code is the same:

  movl  $0, (%rdi,%rsi,4)

Here goes a more complex one.

  void azero(int *x, size_t n)
  {
    size_t i;

    for (i = 0; i != n; ++i)
      x[i] = 0;
  }

splay (with opt -O2) emits:

  ...
  %1 = bitcast i32* %x to i8*
  %2 = shl i64 %n, 2
  call void @llvm.memset.p0i8.i64(i8* %1, i8 0, i64 %2, i32 4, i1 false)
  ...

LLVM's optimizer recognizes the in-loop GEP and rewrites the whole
thing using memset.

- xi

--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Newbies FAQ]     [LKML]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Trinity Fuzzer Tool]

  Powered by Linux