diff --git a/llvm/lib/Transforms/Scalar/SROA.cpp b/llvm/lib/Transforms/Scalar/SROA.cpp index 653bcaf335b17..74bdfda3434bc 100644 --- a/llvm/lib/Transforms/Scalar/SROA.cpp +++ b/llvm/lib/Transforms/Scalar/SROA.cpp @@ -1894,7 +1894,10 @@ static VectorType *isVectorPromotionViable(Partition &P, const DataLayout &DL) { // we have different element types. SmallVector CandidateTys; Type *CommonEltTy = nullptr; + VectorType *CommonVecPtrTy = nullptr; + bool HaveVecPtrTy = false; bool HaveCommonEltTy = true; + bool HaveCommonVecPtrTy = true; auto CheckCandidateType = [&](Type *Ty) { if (auto *VTy = dyn_cast(Ty)) { // Return if bitcast to vectors is different for total size in bits. @@ -1907,10 +1910,20 @@ static VectorType *isVectorPromotionViable(Partition &P, const DataLayout &DL) { } } CandidateTys.push_back(VTy); + Type *EltTy = VTy->getElementType(); + if (!CommonEltTy) - CommonEltTy = VTy->getElementType(); - else if (CommonEltTy != VTy->getElementType()) + CommonEltTy = EltTy; + else if (CommonEltTy != EltTy) HaveCommonEltTy = false; + + if (EltTy->isPointerTy()) { + HaveVecPtrTy = true; + if (!CommonVecPtrTy) + CommonVecPtrTy = VTy; + else if (CommonVecPtrTy != VTy) + HaveCommonVecPtrTy = false; + } } }; // Consider any loads or stores that are the exact size of the slice. @@ -1927,11 +1940,23 @@ static VectorType *isVectorPromotionViable(Partition &P, const DataLayout &DL) { if (CandidateTys.empty()) return nullptr; - // Remove non-integer vector types if we had multiple common element types. - // FIXME: It'd be nice to replace them with integer vector types, but we can't - // do that until all the backends are known to produce good code for all - // integer vector types. - if (!HaveCommonEltTy) { + // Pointer-ness is sticky, if we had a vector-of-pointers candidate type, + // then we should choose it, not some other alternative. + // But, we can't perform a no-op pointer address space change via bitcast, + // so if we didn't have a common pointer element type, bail. + if (HaveVecPtrTy && !HaveCommonVecPtrTy) + return nullptr; + + // Try to pick the "best" element type out of the choices. + if (!HaveCommonEltTy && HaveVecPtrTy) { + // If there was a pointer element type, there's really only one choice. + CandidateTys.clear(); + CandidateTys.push_back(CommonVecPtrTy); + } else if (!HaveCommonEltTy && !HaveVecPtrTy) { + // Remove non-integer vector types if we had multiple common element types. + // FIXME: It'd be nice to replace them with integer vector types, but we + // can't do that until all the backends are known to produce good code for + // all integer vector types. llvm::erase_if(CandidateTys, [](VectorType *VTy) { return !VTy->getElementType()->isIntegerTy(); }); diff --git a/llvm/test/Transforms/SROA/vector-conversion.ll b/llvm/test/Transforms/SROA/vector-conversion.ll index 397a12a15d303..3661f481326ff 100644 --- a/llvm/test/Transforms/SROA/vector-conversion.ll +++ b/llvm/test/Transforms/SROA/vector-conversion.ll @@ -68,9 +68,9 @@ define <2 x i64> @vector_ptrtointbitcast({<1 x ptr>, <1 x ptr>} %x) { define <2 x ptr> @vector_inttoptrbitcast_vector({<16 x i8>, <16 x i8>} %x) { ; CHECK-LABEL: @vector_inttoptrbitcast_vector( ; CHECK-NEXT: [[X_FCA_0_EXTRACT:%.*]] = extractvalue { <16 x i8>, <16 x i8> } [[X:%.*]], 0 -; CHECK-NEXT: [[X_FCA_1_EXTRACT:%.*]] = extractvalue { <16 x i8>, <16 x i8> } [[X]], 1 ; CHECK-NEXT: [[TMP1:%.*]] = bitcast <16 x i8> [[X_FCA_0_EXTRACT]] to <2 x i64> ; CHECK-NEXT: [[TMP2:%.*]] = inttoptr <2 x i64> [[TMP1]] to <2 x ptr> +; CHECK-NEXT: [[X_FCA_1_EXTRACT:%.*]] = extractvalue { <16 x i8>, <16 x i8> } [[X]], 1 ; CHECK-NEXT: ret <2 x ptr> [[TMP2]] ; %a = alloca {<16 x i8>, <16 x i8>} @@ -85,9 +85,9 @@ define <2 x ptr> @vector_inttoptrbitcast_vector({<16 x i8>, <16 x i8>} %x) { define <16 x i8> @vector_ptrtointbitcast_vector({<2 x ptr>, <2 x ptr>} %x) { ; CHECK-LABEL: @vector_ptrtointbitcast_vector( ; CHECK-NEXT: [[X_FCA_0_EXTRACT:%.*]] = extractvalue { <2 x ptr>, <2 x ptr> } [[X:%.*]], 0 +; CHECK-NEXT: [[X_FCA_1_EXTRACT:%.*]] = extractvalue { <2 x ptr>, <2 x ptr> } [[X]], 1 ; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint <2 x ptr> [[X_FCA_0_EXTRACT]] to <2 x i64> ; CHECK-NEXT: [[TMP2:%.*]] = bitcast <2 x i64> [[TMP1]] to <16 x i8> -; CHECK-NEXT: [[X_FCA_1_EXTRACT:%.*]] = extractvalue { <2 x ptr>, <2 x ptr> } [[X]], 1 ; CHECK-NEXT: ret <16 x i8> [[TMP2]] ; %a = alloca {<2 x ptr>, <2 x ptr>}