diff options
author | Sanjay Patel <spatel@rotateright.com> | 2018-04-18 00:36:40 +0000 |
---|---|---|
committer | Sanjay Patel <spatel@rotateright.com> | 2018-04-18 00:36:40 +0000 |
commit | aea15131dbaeae56ab2b084a25f4e184dcfeede3 (patch) | |
tree | a4c83a36d981d9b8515b378a9c37cf24f846b09b /llvm/lib/Transforms/InstCombine/InstructionCombining.cpp | |
parent | 37a9269cc75a03665ab78eeff4cead1509e1770d (diff) | |
download | bcm5719-llvm-aea15131dbaeae56ab2b084a25f4e184dcfeede3.tar.gz bcm5719-llvm-aea15131dbaeae56ab2b084a25f4e184dcfeede3.zip |
[InstCombine] peek through bitcasted vector/array pointer GEP operand
The bitcast may be interfering with other combines or vectorization
as shown in PR16739:
https://bugs.llvm.org/show_bug.cgi?id=16739
Most pointer-related optimizations are probably able to look through
this bitcast, but removing the bitcast shrinks the IR, so it's at
least a size savings.
Differential Revision: https://reviews.llvm.org/D44833
llvm-svn: 330237
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstructionCombining.cpp')
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstructionCombining.cpp | 30 |
1 files changed, 25 insertions, 5 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp index 7ec284e695d..4e836dde158 100644 --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -1945,14 +1945,34 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) { PtrOp = BC; } - /// See if we can simplify: - /// X = bitcast A* to B* - /// Y = gep X, <...constant indices...> - /// into a gep of the original struct. This is important for SROA and alias - /// analysis of unions. If "A" is also a bitcast, wait for A/X to be merged. if (auto *BCI = dyn_cast<BitCastInst>(PtrOp)) { Value *SrcOp = BCI->getOperand(0); PointerType *SrcType = cast<PointerType>(BCI->getSrcTy()); + Type *SrcEltType = SrcType->getElementType(); + + // GEP directly using the source operand if this GEP is accessing an element + // of a bitcasted pointer to vector or array of the same dimensions: + // gep (bitcast <c x ty>* X to [c x ty]*), Y, Z --> gep X, Y, Z + // gep (bitcast [c x ty]* X to <c x ty>*), Y, Z --> gep X, Y, Z + auto areMatchingArrayAndVecTypes = [](Type *ArrTy, Type *VecTy) { + return ArrTy->getArrayElementType() == VecTy->getVectorElementType() && + ArrTy->getArrayNumElements() == VecTy->getVectorNumElements(); + }; + if (GEP.getNumOperands() == 3 && + ((GEPEltType->isArrayTy() && SrcEltType->isVectorTy() && + areMatchingArrayAndVecTypes(GEPEltType, SrcEltType)) || + (GEPEltType->isVectorTy() && SrcEltType->isArrayTy() && + areMatchingArrayAndVecTypes(SrcEltType, GEPEltType)))) { + GEP.setOperand(0, SrcOp); + GEP.setSourceElementType(SrcEltType); + return &GEP; + } + + // See if we can simplify: + // X = bitcast A* to B* + // Y = gep X, <...constant indices...> + // into a gep of the original struct. This is important for SROA and alias + // analysis of unions. If "A" is also a bitcast, wait for A/X to be merged. unsigned OffsetBits = DL.getIndexTypeSizeInBits(GEPType); APInt Offset(OffsetBits, 0); if (!isa<BitCastInst>(SrcOp) && GEP.accumulateConstantOffset(DL, Offset)) { |