summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
diff options
context:
space:
mode:
authorSanjay Patel <spatel@rotateright.com>2018-04-18 00:36:40 +0000
committerSanjay Patel <spatel@rotateright.com>2018-04-18 00:36:40 +0000
commitaea15131dbaeae56ab2b084a25f4e184dcfeede3 (patch)
treea4c83a36d981d9b8515b378a9c37cf24f846b09b /llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
parent37a9269cc75a03665ab78eeff4cead1509e1770d (diff)
downloadbcm5719-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.cpp30
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)) {
OpenPOWER on IntegriCloud