Index: lib/IR/ConstantFold.cpp =================================================================== --- lib/IR/ConstantFold.cpp +++ lib/IR/ConstantFold.cpp @@ -2210,17 +2210,17 @@ SmallVector NewIdxs; Type *Ty = PointeeTy; Type *Prev = C->getType(); - bool Unknown = !isa(Idxs[0]); + bool Unknown = + !isa(Idxs[0]) && !isa(Idxs[0]); for (unsigned i = 1, e = Idxs.size(); i != e; Prev = Ty, Ty = cast(Ty)->getTypeAtIndex(Idxs[i]), ++i) { - auto *CI = dyn_cast(Idxs[i]); - if (!CI) { + if (!isa(Idxs[i]) && !isa(Idxs[i])) { // We don't know if it's in range or not. Unknown = true; continue; } - if (!isa(Idxs[i - 1])) - // FIXME: add the support of cosntant vector index. + if (!isa(Idxs[i - 1]) && !isa(Idxs[i - 1])) + // Skip if the type of the previous index is not supported. continue; if (InRangeIndex && i == *InRangeIndex + 1) { // If an index is marked inrange, we cannot apply this canonicalization to @@ -2238,46 +2238,91 @@ Unknown = true; continue; } - if (isIndexInRangeOfArrayType(STy->getNumElements(), CI)) - // It's in range, skip to the next index. - continue; + if (ConstantInt *CI = dyn_cast(Idxs[i])) { + if (isIndexInRangeOfArrayType(STy->getNumElements(), CI)) + // It's in range, skip to the next index. + continue; + if (CI->getSExtValue() < 0) { + // It's out of range and negative, don't try to factor it. + Unknown = true; + continue; + } + } + if (ConstantDataVector *CV = dyn_cast(Idxs[i])) { + bool InRange = true; + for (unsigned I = 0, E = CV->getNumElements(); I != E; ++I) { + auto *CI = cast(CV->getElementAsConstant(I)); + InRange &= isIndexInRangeOfArrayType(STy->getNumElements(), CI); + if (CI->getSExtValue() < 0) { + Unknown = true; + break; + } + } + if (InRange || Unknown) + // It's in range, skip to the next index. + // It's out of range and negative, don't try to factor it. + continue; + } if (isa(Prev)) { // It's out of range, but the prior dimension is a struct // so we can't do anything about it. Unknown = true; continue; } - if (CI->getSExtValue() < 0) { - // It's out of range and negative, don't try to factor it. - Unknown = true; - continue; - } // It's out of range, but we can factor it into the prior // dimension. NewIdxs.resize(Idxs.size()); // Determine the number of elements in our sequential type. uint64_t NumElements = STy->getArrayNumElements(); - ConstantInt *Factor = ConstantInt::get(CI->getType(), NumElements); - NewIdxs[i] = ConstantExpr::getSRem(CI, Factor); + // Expand the current index or the previous index to a vector from a scalar + // if necessary. + Constant *CurrIdx = cast(Idxs[i]); + auto *PrevIdx = + NewIdxs[i - 1] ? NewIdxs[i - 1] : cast(Idxs[i - 1]); + bool IsCurrIdxVector = CurrIdx->getType()->isVectorTy(); + bool IsPrevIdxVector = PrevIdx->getType()->isVectorTy(); + bool UseVector = IsCurrIdxVector || IsPrevIdxVector; + + if (!IsCurrIdxVector && IsPrevIdxVector) + CurrIdx = ConstantDataVector::getSplat( + PrevIdx->getType()->getVectorNumElements(), CurrIdx); + + if (!IsPrevIdxVector && IsCurrIdxVector) + PrevIdx = ConstantDataVector::getSplat( + CurrIdx->getType()->getVectorNumElements(), PrevIdx); + + Constant *Factor = + ConstantInt::get(CurrIdx->getType()->getScalarType(), NumElements); + if (UseVector) + Factor = ConstantDataVector::getSplat( + IsPrevIdxVector ? PrevIdx->getType()->getVectorNumElements() + : CurrIdx->getType()->getVectorNumElements(), + Factor); + + NewIdxs[i] = ConstantExpr::getSRem(CurrIdx, Factor); - Constant *PrevIdx = NewIdxs[i-1] ? NewIdxs[i-1] : - cast(Idxs[i - 1]); - Constant *Div = ConstantExpr::getSDiv(CI, Factor); + Constant *Div = ConstantExpr::getSDiv(CurrIdx, Factor); unsigned CommonExtendedWidth = - std::max(PrevIdx->getType()->getIntegerBitWidth(), - Div->getType()->getIntegerBitWidth()); + std::max(PrevIdx->getType()->getScalarSizeInBits(), + Div->getType()->getScalarSizeInBits()); CommonExtendedWidth = std::max(CommonExtendedWidth, 64U); // Before adding, extend both operands to i64 to avoid // overflow trouble. - if (!PrevIdx->getType()->isIntegerTy(CommonExtendedWidth)) - PrevIdx = ConstantExpr::getSExt( - PrevIdx, Type::getIntNTy(Div->getContext(), CommonExtendedWidth)); - if (!Div->getType()->isIntegerTy(CommonExtendedWidth)) - Div = ConstantExpr::getSExt( - Div, Type::getIntNTy(Div->getContext(), CommonExtendedWidth)); + Type *ExtendedTy = Type::getIntNTy(Div->getContext(), CommonExtendedWidth); + if (UseVector) + ExtendedTy = VectorType::get( + ExtendedTy, IsPrevIdxVector + ? PrevIdx->getType()->getVectorNumElements() + : CurrIdx->getType()->getVectorNumElements()); + + if (!PrevIdx->getType()->isIntOrIntVectorTy(CommonExtendedWidth)) + PrevIdx = ConstantExpr::getSExt(PrevIdx, ExtendedTy); + + if (!Div->getType()->isIntOrIntVectorTy(CommonExtendedWidth)) + Div = ConstantExpr::getSExt(Div, ExtendedTy); NewIdxs[i - 1] = ConstantExpr::getAdd(PrevIdx, Div); } Index: test/Assembler/getelementptr_vec_ce.ll =================================================================== --- test/Assembler/getelementptr_vec_ce.ll +++ test/Assembler/getelementptr_vec_ce.ll @@ -3,7 +3,7 @@ @G = global [4 x i32] zeroinitializer ; CHECK-LABEL: @foo -; CHECK: ret <4 x i32*> getelementptr ([4 x i32], [4 x i32]* @G, <4 x i32> zeroinitializer, <4 x i32> ) +; CHECK: ret <4 x i32*> getelementptr inbounds ([4 x i32], [4 x i32]* @G, <4 x i32> zeroinitializer, <4 x i32> ) define <4 x i32*> @foo() { ret <4 x i32*> getelementptr ([4 x i32], [4 x i32]* @G, i32 0, <4 x i32> ) } Index: test/Transforms/InstCombine/gep-vector.ll =================================================================== --- test/Transforms/InstCombine/gep-vector.ll +++ test/Transforms/InstCombine/gep-vector.ll @@ -16,9 +16,23 @@ @block = global [64 x [8192 x i8]] zeroinitializer, align 1 -; CHECK-LABEL:vectorindex -; CHECK-NEXT: ret <2 x i8*> getelementptr inbounds ([64 x [8192 x i8]], [64 x [8192 x i8]]* @block, <2 x i64> zeroinitializer, <2 x i64> , <2 x i64> ) -define <2 x i8*> @vectorindex() { +; CHECK-LABEL:vectorindex1 +; CHECK-NEXT: ret <2 x i8*> getelementptr inbounds ([64 x [8192 x i8]], [64 x [8192 x i8]]* @block, <2 x i64> zeroinitializer, <2 x i64> , <2 x i64> zeroinitializer) +define <2 x i8*> @vectorindex1() { %1 = getelementptr inbounds [64 x [8192 x i8]], [64 x [8192 x i8]]* @block, i64 0, <2 x i64> , i64 8192 ret <2 x i8*> %1 } + +; CHECK-LABEL:vectorindex2 +; CHECK-NEXT: ret <2 x i8*> getelementptr inbounds ([64 x [8192 x i8]], [64 x [8192 x i8]]* @block, <2 x i64> zeroinitializer, <2 x i64> , <2 x i64> ) +define <2 x i8*> @vectorindex2() { + %1 = getelementptr inbounds [64 x [8192 x i8]], [64 x [8192 x i8]]* @block, i64 0, i64 1, <2 x i64> + ret <2 x i8*> %1 +} + +; CHECK-LABEL:vectorindex3 +; CHECK-NEXT: ret <2 x i8*> getelementptr inbounds ([64 x [8192 x i8]], [64 x [8192 x i8]]* @block, <2 x i64> zeroinitializer, <2 x i64> , <2 x i64> ) +define <2 x i8*> @vectorindex3() { + %1 = getelementptr inbounds [64 x [8192 x i8]], [64 x [8192 x i8]]* @block, i64 0, <2 x i64> , <2 x i64> + ret <2 x i8*> %1 +} Index: test/Transforms/InstSimplify/vector_gep.ll =================================================================== --- test/Transforms/InstSimplify/vector_gep.ll +++ test/Transforms/InstSimplify/vector_gep.ll @@ -58,7 +58,7 @@ define <16 x i32*> @test6() { ; CHECK-LABEL: @test6 -; CHECK-NEXT: ret <16 x i32*> getelementptr ([24 x [42 x [3 x i32]]], [24 x [42 x [3 x i32]]]* @v, <16 x i64> zeroinitializer, <16 x i64> zeroinitializer, <16 x i64> , <16 x i64> zeroinitializer) +; CHECK-NEXT: ret <16 x i32*> getelementptr inbounds ([24 x [42 x [3 x i32]]], [24 x [42 x [3 x i32]]]* @v, <16 x i64> zeroinitializer, <16 x i64> zeroinitializer, <16 x i64> , <16 x i64> zeroinitializer) %VectorGep = getelementptr [24 x [42 x [3 x i32]]], [24 x [42 x [3 x i32]]]* @v, i64 0, i64 0, <16 x i64> , i64 0 ret <16 x i32*> %VectorGep }