[llvm] r228899 - [slp] Fix a nasty bug in the SLP vectorizer that Joerg pointed out.
Chandler Carruth
chandlerc at gmail.com
Wed Feb 11 19:40:05 PST 2015
On Wed, Feb 11, 2015 at 6:30 PM, Chandler Carruth <chandlerc at gmail.com>
wrote:
> Author: chandlerc
> Date: Wed Feb 11 20:30:56 2015
> New Revision: 228899
>
> URL: http://llvm.org/viewvc/llvm-project?rev=228899&view=rev
> Log:
> [slp] Fix a nasty bug in the SLP vectorizer that Joerg pointed out.
>
FYI, Joerg indicated this is at least in some cases a regression from 3.5,
so it seems good to pull into the 3.6 branch Hans.
> Apparently some code finally started to tickle this after my
> canonicalization changes to instcombine.
>
> The bug stems from trying to form a vector type out of scalars that
> aren't compatible at all. In this example, from x86_mmx values. The code
> in the vectorizer that checks for reasonable types whas checking for
> aggregates or vectors, but there are lots of other types that should
> just never reach the vectorizer.
>
> Debugging this was made more confusing by the lie in an assert in
> VectorType::get() -- it isn't that the types are *primitive*. The types
> must be integer, pointer, or floating point types. No other types are
> allowed.
>
> I've improved the assert and added a helper to the vectorizer to handle
> the element type validity checks. It now re-uses the VectorType static
> function and then further excludes weird target-specific types that we
> probably shouldn't be touching here (x86_fp80 and ppc_fp128). Neither of
> these are really reachable anyways (neither 80-bit nor 128-bit things
> will get vectorized) but it seems better to just eagerly exclude such
> nonesense.
>
> I've added a test case, but while it definitely covers two of the paths
> through this code there may be more paths that would benefit from test
> coverage. I'm not familiar enough with the SLP vectorizer to synthesize
> test cases for all of these, but was able to update the code itself by
> inspection.
>
> Added:
> llvm/trunk/test/Transforms/SLPVectorizer/X86/bad_types.ll
> Modified:
> llvm/trunk/lib/IR/Type.cpp
> llvm/trunk/lib/Transforms/Vectorize/SLPVectorizer.cpp
>
> Modified: llvm/trunk/lib/IR/Type.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Type.cpp?rev=228899&r1=228898&r2=228899&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/IR/Type.cpp (original)
> +++ llvm/trunk/lib/IR/Type.cpp Wed Feb 11 20:30:56 2015
> @@ -708,9 +708,10 @@ VectorType::VectorType(Type *ElType, uns
> VectorType *VectorType::get(Type *elementType, unsigned NumElements) {
> Type *ElementType = const_cast<Type*>(elementType);
> assert(NumElements > 0 && "#Elements of a VectorType must be greater
> than 0");
> - assert(isValidElementType(ElementType) &&
> - "Elements of a VectorType must be a primitive type");
> -
> + assert(isValidElementType(ElementType) && "Element type of a VectorType
> must "
> + "be an integer, floating
> point, or "
> + "pointer type.");
> +
> LLVMContextImpl *pImpl = ElementType->getContext().pImpl;
> VectorType *&Entry = ElementType->getContext().pImpl
> ->VectorTypes[std::make_pair(ElementType, NumElements)];
>
> Modified: llvm/trunk/lib/Transforms/Vectorize/SLPVectorizer.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Vectorize/SLPVectorizer.cpp?rev=228899&r1=228898&r2=228899&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Vectorize/SLPVectorizer.cpp (original)
> +++ llvm/trunk/lib/Transforms/Vectorize/SLPVectorizer.cpp Wed Feb 11
> 20:30:56 2015
> @@ -84,6 +84,18 @@ static const unsigned AliasedCheckLimit
> // This limit is useful for very large basic blocks.
> static const unsigned MaxMemDepDistance = 160;
>
> +/// \brief Predicate for the element types that the SLP vectorizer
> supports.
> +///
> +/// The most important thing to filter here are types which are invalid
> in LLVM
> +/// vectors. We also filter target specific types which have absolutely no
> +/// meaningful vectorization path such as x86_fp80 and ppc_f128. This just
> +/// avoids spending time checking the cost model and realizing that they
> will
> +/// be inevitably scalarized.
> +static bool isValidElementType(Type *Ty) {
> + return VectorType::isValidElementType(Ty) && !Ty->isX86_FP80Ty() &&
> + !Ty->isPPC_FP128Ty();
> +}
> +
> /// \returns the parent basic block if all of the instructions in \p VL
> /// are in the same block or null otherwise.
> static BasicBlock *getSameBlock(ArrayRef<Value *> VL) {
> @@ -1148,7 +1160,7 @@ void BoUpSLP::buildTree_rec(ArrayRef<Val
> Type *SrcTy = VL0->getOperand(0)->getType();
> for (unsigned i = 0; i < VL.size(); ++i) {
> Type *Ty = cast<Instruction>(VL[i])->getOperand(0)->getType();
> - if (Ty != SrcTy || Ty->isAggregateType() || Ty->isVectorTy()) {
> + if (Ty != SrcTy || !isValidElementType(Ty)) {
> BS.cancelScheduling(VL);
> newTreeEntry(VL, false);
> DEBUG(dbgs() << "SLP: Gathering casts with different src
> types.\n");
> @@ -3294,7 +3306,7 @@ unsigned SLPVectorizer::collectStores(Ba
>
> // Check that the pointer points to scalars.
> Type *Ty = SI->getValueOperand()->getType();
> - if (Ty->isAggregateType() || Ty->isVectorTy())
> + if (!isValidElementType(Ty))
> continue;
>
> // Find the base pointer.
> @@ -3335,7 +3347,7 @@ bool SLPVectorizer::tryToVectorizeList(A
>
> for (int i = 0, e = VL.size(); i < e; ++i) {
> Type *Ty = VL[i]->getType();
> - if (Ty->isAggregateType() || Ty->isVectorTy())
> + if (!isValidElementType(Ty))
> return false;
> Instruction *Inst = dyn_cast<Instruction>(VL[i]);
> if (!Inst || Inst->getOpcode() != Opcode0)
> @@ -3555,7 +3567,7 @@ public:
> return false;
>
> Type *Ty = B->getType();
> - if (Ty->isVectorTy())
> + if (!isValidElementType(Ty))
> return false;
>
> ReductionOpcode = B->getOpcode();
>
> Added: llvm/trunk/test/Transforms/SLPVectorizer/X86/bad_types.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SLPVectorizer/X86/bad_types.ll?rev=228899&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/Transforms/SLPVectorizer/X86/bad_types.ll (added)
> +++ llvm/trunk/test/Transforms/SLPVectorizer/X86/bad_types.ll Wed Feb 11
> 20:30:56 2015
> @@ -0,0 +1,50 @@
> +; RUN: opt < %s -basicaa -slp-vectorizer -S -mcpu=corei7-avx | FileCheck
> %s
> +
> +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
> +target triple = "x86_64-unknown-linux-gnu"
> +
> +define void @test1(x86_mmx %a, x86_mmx %b, i64* %ptr) {
> +; Ensure we can handle x86_mmx values which are primitive and can be
> bitcast
> +; with integer types but can't be put into a vector.
> +;
> +; CHECK-LABEL: @test1
> +; CHECK: store i64
> +; CHECK: store i64
> +; CHECK: ret void
> +entry:
> + %a.cast = bitcast x86_mmx %a to i64
> + %b.cast = bitcast x86_mmx %b to i64
> + %a.and = and i64 %a.cast, 42
> + %b.and = and i64 %b.cast, 42
> + %gep = getelementptr i64* %ptr, i32 1
> + store i64 %a.and, i64* %ptr
> + store i64 %b.and, i64* %gep
> + ret void
> +}
> +
> +define void @test2(x86_mmx %a, x86_mmx %b) {
> +; Same as @test1 but using phi-input vectorization instead of store
> +; vectorization.
> +;
> +; CHECK-LABEL: @test2
> +; CHECK: and i64
> +; CHECK: and i64
> +; CHECK: ret void
> +entry:
> + br i1 undef, label %if.then, label %exit
> +
> +if.then:
> + %a.cast = bitcast x86_mmx %a to i64
> + %b.cast = bitcast x86_mmx %b to i64
> + %a.and = and i64 %a.cast, 42
> + %b.and = and i64 %b.cast, 42
> + br label %exit
> +
> +exit:
> + %a.phi = phi i64 [ 0, %entry ], [ %a.and, %if.then ]
> + %b.phi = phi i64 [ 0, %entry ], [ %b.and, %if.then ]
> + tail call void @f(i64 %a.phi, i64 %b.phi)
> + ret void
> +}
> +
> +declare void @f(i64, i64)
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150211/8cf0692d/attachment.html>
More information about the llvm-commits
mailing list