From 7cd3fe7db6c57664b47dbbaf02825caa384116ef Mon Sep 17 00:00:00 2001 From: Amaury Sechet Date: Wed, 2 Mar 2016 21:28:30 +0000 Subject: [PATCH] Unpack array of all sizes in InstCombine Summary: This is another step toward improving fca support. This unpack load of array in a series of load to array's elements. Reviewers: chandlerc, joker.eph, majnemer, reames, hfinkel Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D15890 llvm-svn: 262521 --- .../InstCombine/InstCombineLoadStoreAlloca.cpp | 43 +++++++++++++++++++--- llvm/test/Transforms/InstCombine/unpack-fca.ll | 21 +++++++++++ 2 files changed, 59 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp index 3a137a9..c559d93 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp @@ -574,13 +574,46 @@ static Instruction *unpackLoadToAggregate(InstCombiner &IC, LoadInst &LI) { } if (auto *AT = dyn_cast(T)) { - // If the array only have one element, we unpack. - if (AT->getNumElements() == 1) { - LoadInst *NewLoad = combineLoadToNewType(IC, LI, AT->getElementType(), - ".unpack"); + auto *ET = AT->getElementType(); + auto NumElements = AT->getNumElements(); + if (NumElements == 1) { + LoadInst *NewLoad = combineLoadToNewType(IC, LI, ET, ".unpack"); return IC.replaceInstUsesWith(LI, IC.Builder->CreateInsertValue( - UndefValue::get(T), NewLoad, 0, LI.getName())); + UndefValue::get(T), NewLoad, 0, Name)); } + + const DataLayout &DL = IC.getDataLayout(); + auto EltSize = DL.getTypeAllocSize(ET); + auto Align = LI.getAlignment(); + if (!Align) + Align = DL.getABITypeAlignment(T); + + SmallString<16> LoadName = Name; + LoadName += ".unpack"; + SmallString<16> EltName = Name; + EltName += ".elt"; + + auto *Addr = LI.getPointerOperand(); + auto *IdxType = Type::getInt64Ty(T->getContext()); + auto *Zero = ConstantInt::get(IdxType, 0); + + Value *V = UndefValue::get(T); + uint64_t Offset = 0; + for (uint64_t i = 0; i < NumElements; i++) { + Value *Indices[2] = { + Zero, + ConstantInt::get(IdxType, i), + }; + auto *Ptr = IC.Builder->CreateInBoundsGEP(AT, Addr, makeArrayRef(Indices), + EltName); + auto *L = IC.Builder->CreateAlignedLoad(Ptr, MinAlign(Align, Offset), + LoadName); + V = IC.Builder->CreateInsertValue(V, L, i); + Offset += EltSize; + } + + V->setName(Name); + return IC.replaceInstUsesWith(LI, V); } return nullptr; diff --git a/llvm/test/Transforms/InstCombine/unpack-fca.ll b/llvm/test/Transforms/InstCombine/unpack-fca.ll index bed3b61..cd97ce6 100644 --- a/llvm/test/Transforms/InstCombine/unpack-fca.ll +++ b/llvm/test/Transforms/InstCombine/unpack-fca.ll @@ -137,6 +137,27 @@ define %B @structB(%B* %b.ptr) { ret %B %1 } +define [2 x %B] @loadArrayOfB([2 x %B]* %ab.ptr) { +; CHECK-LABEL: loadArrayOfB +; CHECK-NEXT: [[GEP1:%[a-z0-9\.]+]] = getelementptr inbounds [2 x %B], [2 x %B]* %ab.ptr, i64 0, i64 0, i32 0 +; CHECK-NEXT: [[LOAD1:%[a-z0-9\.]+]] = load i8*, i8** [[GEP1]], align 8 +; CHECK-NEXT: [[IV1:%[a-z0-9\.]+]] = insertvalue %B undef, i8* [[LOAD1]], 0 +; CHECK-NEXT: [[GEP2:%[a-z0-9\.]+]] = getelementptr inbounds [2 x %B], [2 x %B]* %ab.ptr, i64 0, i64 0, i32 1 +; CHECK-NEXT: [[LOAD2:%[a-z0-9\.]+]] = load i64, i64* [[GEP2]], align 8 +; CHECK-NEXT: [[IV2:%[a-z0-9\.]+]] = insertvalue %B [[IV1]], i64 [[LOAD2]], 1 +; CHECK-NEXT: [[IV3:%[a-z0-9\.]+]] = insertvalue [2 x %B] undef, %B [[IV2]], 0 +; CHECK-NEXT: [[GEP3:%[a-z0-9\.]+]] = getelementptr inbounds [2 x %B], [2 x %B]* %ab.ptr, i64 0, i64 1, i32 0 +; CHECK-NEXT: [[LOAD3:%[a-z0-9\.]+]] = load i8*, i8** [[GEP3]], align 8 +; CHECK-NEXT: [[IV4:%[a-z0-9\.]+]] = insertvalue %B undef, i8* [[LOAD3]], 0 +; CHECK-NEXT: [[GEP4:%[a-z0-9\.]+]] = getelementptr inbounds [2 x %B], [2 x %B]* %ab.ptr, i64 0, i64 1, i32 1 +; CHECK-NEXT: [[LOAD4:%[a-z0-9\.]+]] = load i64, i64* [[GEP4]], align 8 +; CHECK-NEXT: [[IV5:%[a-z0-9\.]+]] = insertvalue %B [[IV4]], i64 [[LOAD4]], 1 +; CHECK-NEXT: [[IV6:%[a-z0-9\.]+]] = insertvalue [2 x %B] [[IV3]], %B [[IV5]], 1 +; CHECK-NEXT: ret [2 x %B] [[IV6]] + %1 = load [2 x %B], [2 x %B]* %ab.ptr, align 8 + ret [2 x %B] %1 +} + %struct.S = type <{ i8, %struct.T }> %struct.T = type { i32, i32 } -- 2.7.4