Optimize load from aggregate stores
deadal nix
deadalnix at gmail.com
Tue Feb 11 17:19:11 PST 2014
Hi Adrian. I assumed this thread was kind of dead and submitted a better
patch (you'll find it attached).
This updated patch test more in depth the struct case. I don't have an
array test case ready. I can add one if that is really necessary.
2014-02-11 15:04 GMT-08:00 Adrian Prantl <aprantl at apple.com>:
> Thanks for adding the test! It looks like this only tests the struct case?
> There are probably others more qualified to comment on the GVN-related
> changes.
>
> -- adrian
>
> On Feb 7, 2014, at 21:02, deadal nix <deadalnix at gmail.com> wrote:
>
> > Here is the updated patch with test case included:
> >
> > diff --git a/lib/Transforms/Scalar/GVN.cpp
> b/lib/Transforms/Scalar/GVN.cpp
> > index f350b9b..c8a0ec0 100644
> > --- a/lib/Transforms/Scalar/GVN.cpp
> > +++ b/lib/Transforms/Scalar/GVN.cpp
> > @@ -996,11 +996,6 @@ static int AnalyzeLoadFromClobberingWrite(Type
> *LoadTy, Value *LoadPtr,
> > static int AnalyzeLoadFromClobberingStore(Type *LoadTy, Value *LoadPtr,
> > StoreInst *DepSI,
> > const DataLayout &TD) {
> > - // Cannot handle reading from store of first-class aggregate yet.
> > - if (DepSI->getValueOperand()->getType()->isStructTy() ||
> > - DepSI->getValueOperand()->getType()->isArrayTy())
> > - return -1;
> > -
> > Value *StorePtr = DepSI->getPointerOperand();
> > uint64_t StoreSize
> =TD.getTypeSizeInBits(DepSI->getValueOperand()->getType());
> > return AnalyzeLoadFromClobberingWrite(LoadTy, LoadPtr,
> > @@ -1097,6 +1092,25 @@ static Value *GetStoreValueForLoad(Value *SrcVal,
> unsigned Offset,
> >
> > IRBuilder<> Builder(InsertPt->getParent(), InsertPt);
> >
> > + // When facing an Aggregate, we have to find the element to fetch
> from.
> > + while (SrcVal->getType()->isAggregateType()) {
> > + if (StructType *ST = dyn_cast<StructType>(SrcVal->getType())) {
> > + const StructLayout &Layout = *TD.getStructLayout(ST);
> > + unsigned i = 0;
> > + for (unsigned cd = 0, e = ST->getNumElements(); cd != e; ++cd) {
> > + if (Layout.getElementOffsetInBits(cd) > Offset) break;
> > + i = cd;
> > + }
> > +
> > + SrcVal = Builder.CreateExtractValue(SrcVal, i);
> > + Offset -= Layout.getElementOffsetInBits(i);
> > + } else if (ArrayType *AT = dyn_cast<ArrayType>(SrcVal->getType())) {
> > + uint64_t EltSize =
> TD.getTypeAllocSizeInBits(AT->getElementType());
> > + SrcVal = Builder.CreateExtractValue(SrcVal, Offset / EltSize);
> > + Offset %= EltSize;
> > + }
> > + }
> > +
> > // Compute which bits of the stored value are being used by the load.
> Convert
> > // to an integer type to start with.
> > if (SrcVal->getType()->getScalarType()->isPointerTy())
> > diff --git a/test/Transforms/GVN/aggregate_store.ll
> b/test/Transforms/GVN/aggregate_store.ll
> > new file mode 100644
> > index 0000000..fc8aab4
> > --- /dev/null
> > +++ b/test/Transforms/GVN/aggregate_store.ll
> > @@ -0,0 +1,36 @@
> > +; RUN: opt -gvn -S < %s | FileCheck %s
> > +
> > +target datalayout =
> >
> +"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-f128:128:128-n8:16:32:64"
> > +target triple = "x86_64-unknown-linux-gnu"
> > +
> > +%A__vtbl = type { i8*, i32 (%A*)* }
> > +%A = type { %A__vtbl* }
> > +
> > + at A__vtblZ = constant %A__vtbl { i8* null, i32 (%A*)* @A.foo }
> > + at A__initZ = constant %A { %A__vtbl* @A__vtblZ }
> > +
> > +declare i8* @allocmemory(i64)
> > +
> > +define i32 @f1() {
> > +body:
> > + %0 = tail call i8* @allocmemory(i64 8)
> > + %1 = bitcast i8* %0 to %A*
> > +; CHECK: store %A
> > + store %A { %A__vtbl* @A__vtblZ }, %A* %1, align 8
> > + %2 = getelementptr inbounds %A* %1, i32 0, i32 0
> > +; CHECK-NOT: load %A__vtbl*
> > + %vtbl.i = load %A__vtbl** %2, align 8
> > + %3 = getelementptr inbounds %A__vtbl* %vtbl.i, i64 0, i32 1
> > +; CHECK-NOT: load i32 (%A*)*
> > + %4 = load i32 (%A*)** %3, align 8
> > +; CHECK: tail call i32 @A.foo(%A* %1)
> > + %5 = tail call i32 %4(%A* %1)
> > + ret i32 %5
> > +}
> > +
> > +define i32 @A.foo(%A* nocapture %this) nounwind readnone {
> > +body:
> > + ret i32 42
> > +}
> > +
> >
> >
> >
> > 2014-02-07 10:01 GMT-08:00 Adrian Prantl <aprantl at apple.com>:
> >
> > On Feb 6, 2014, at 22:52, deadal nix <deadalnix at gmail.com> wrote:
> > >
> > > I have some test cases, but I'm not sure how the LLVM test suite work
> and what is the right way to add them. I'll need some directions here to
> complete the diff.Anyway, the code :
> >
> > To test a change to GVN it would be best to have a .ll file with a RUN:
> line that invokes opt (with the appropriate flags for GVN) and then CHECKs
> the output with FileCheck. You can grep for "RUN: opt" in test/ for some
> examples.
> > Assuming that you have source code for a testcase, you can extract an
> appropriate fragment from the output go -mllvm -print-after-all.
> >
> > -- adrian
> >
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140211/e0332fdc/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-Optimize-load-from-aggregate-stores-in-GVN.patch
Type: application/octet-stream
Size: 6139 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140211/e0332fdc/attachment.obj>
More information about the llvm-commits
mailing list