Index: llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp =================================================================== --- llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp +++ llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -1945,14 +1945,34 @@ 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(PtrOp)) { Value *SrcOp = BCI->getOperand(0); PointerType *SrcType = cast(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 * X to [c x ty]*), Y, Z --> gep X, Y, Z + // gep (bitcast [c x ty]* X to *), 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(SrcOp) && GEP.accumulateConstantOffset(DL, Offset)) { Index: llvm/trunk/test/Transforms/InstCombine/gep-vector.ll =================================================================== --- llvm/trunk/test/Transforms/InstCombine/gep-vector.ll +++ llvm/trunk/test/Transforms/InstCombine/gep-vector.ll @@ -27,3 +27,23 @@ ret <2 x i8*> %1 } +define i32* @bitcast_vec_to_array_gep(<7 x i32>* %x, i64 %y, i64 %z) { +; CHECK-LABEL: @bitcast_vec_to_array_gep( +; CHECK-NEXT: [[GEP:%.*]] = getelementptr <7 x i32>, <7 x i32>* [[X:%.*]], i64 [[Y:%.*]], i64 [[Z:%.*]] +; CHECK-NEXT: ret i32* [[GEP]] +; + %arr_ptr = bitcast <7 x i32>* %x to [7 x i32]* + %gep = getelementptr [7 x i32], [7 x i32]* %arr_ptr, i64 %y, i64 %z + ret i32* %gep +} + +define i32* @bitcast_array_to_vec_gep([3 x i32]* %x, i64 %y, i64 %z) { +; CHECK-LABEL: @bitcast_array_to_vec_gep( +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [3 x i32], [3 x i32]* [[X:%.*]], i64 [[Y:%.*]], i64 [[Z:%.*]] +; CHECK-NEXT: ret i32* [[GEP]] +; + %vec_ptr = bitcast [3 x i32]* %x to <3 x i32>* + %gep = getelementptr inbounds <3 x i32>, <3 x i32>* %vec_ptr, i64 %y, i64 %z + ret i32* %gep +} +