Index: llvm/trunk/include/llvm/Analysis/VectorUtils.h =================================================================== --- llvm/trunk/include/llvm/Analysis/VectorUtils.h +++ llvm/trunk/include/llvm/Analysis/VectorUtils.h @@ -79,6 +79,11 @@ /// from the vector. Value *findScalarElement(Value *V, unsigned EltNo); +/// \brief Get splat value if the input is a splat vector or return nullptr. +/// The value may be extracted from a splat constants vector or from +/// a sequence of instructions that broadcast a single value into a vector. +Value *getSplatValue(Value *V); + } // llvm namespace #endif Index: llvm/trunk/lib/Analysis/VectorUtils.cpp =================================================================== --- llvm/trunk/lib/Analysis/VectorUtils.cpp +++ llvm/trunk/lib/Analysis/VectorUtils.cpp @@ -18,6 +18,8 @@ #include "llvm/IR/GetElementPtrTypeIterator.h" #include "llvm/IR/PatternMatch.h" #include "llvm/IR/Value.h" +#include "llvm/IR/Constants.h" + using namespace llvm; using namespace llvm::PatternMatch; @@ -406,3 +408,27 @@ // Otherwise, we don't know. return nullptr; } + +/// \brief Get splat value if the input is a splat vector or return nullptr. +/// The value may be extracted from a splat constants vector or from +/// a sequence of instructions that broadcast a single value into a vector. +llvm::Value *llvm::getSplatValue(Value *V) { + llvm::ConstantDataVector *CV = dyn_cast(V); + if (CV) + return CV->getSplatValue(); + llvm::ShuffleVectorInst *ShuffleInst = dyn_cast(V); + if (!ShuffleInst) + return nullptr; + // All-zero (our undef) shuffle mask elements. + for (int i : ShuffleInst->getShuffleMask()) + if (i != 0 && i != -1) + return nullptr; + // The first shuffle source is 'insertelement' with index 0. + llvm::InsertElementInst *InsertEltInst = + dyn_cast(ShuffleInst->getOperand(0)); + if (!InsertEltInst || !isa(InsertEltInst->getOperand(2)) || + !cast(InsertEltInst->getOperand(2))->isNullValue()) + return nullptr; + + return InsertEltInst->getOperand(1); +} Index: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp =================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -22,6 +22,7 @@ #include "llvm/Analysis/ConstantFolding.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/ValueTracking.h" +#include "llvm/Analysis/VectorUtils.h" #include "llvm/CodeGen/FastISel.h" #include "llvm/CodeGen/FunctionLoweringInfo.h" #include "llvm/CodeGen/GCMetadata.h" @@ -3150,37 +3151,32 @@ SelectionDAGBuilder* SDB) { assert(Ptr->getType()->isVectorTy() && "Unexpected pointer type"); - GetElementPtrInst *Gep = dyn_cast(Ptr); - if (!Gep || Gep->getNumOperands() > 2) + GetElementPtrInst *GEP = dyn_cast(Ptr); + if (!GEP || GEP->getNumOperands() > 2) return false; - ShuffleVectorInst *ShuffleInst = - dyn_cast(Gep->getPointerOperand()); - if (!ShuffleInst || !ShuffleInst->getMask()->isNullValue() || - cast(ShuffleInst->getOperand(0))->getOpcode() != - Instruction::InsertElement) + Value *GEPPtrs = GEP->getPointerOperand(); + if (!(Ptr = getSplatValue(GEPPtrs))) return false; - Ptr = cast(ShuffleInst->getOperand(0))->getOperand(1); - SelectionDAG& DAG = SDB->DAG; const TargetLowering &TLI = DAG.getTargetLoweringInfo(); // Check is the Ptr is inside current basic block // If not, look for the shuffle instruction if (SDB->findValue(Ptr)) Base = SDB->getValue(Ptr); - else if (SDB->findValue(ShuffleInst)) { - SDValue ShuffleNode = SDB->getValue(ShuffleInst); - SDLoc sdl = ShuffleNode; - Base = DAG.getNode( - ISD::EXTRACT_VECTOR_ELT, sdl, - ShuffleNode.getValueType().getScalarType(), ShuffleNode, - DAG.getConstant(0, sdl, TLI.getVectorIdxTy(DAG.getDataLayout()))); + else if (SDB->findValue(GEPPtrs)) { + SDValue GEPPtrsVal = SDB->getValue(GEPPtrs); + SDLoc sdl = GEPPtrsVal; + EVT IdxVT = TLI.getVectorIdxTy(DAG.getDataLayout()); + Base = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, sdl, + GEPPtrsVal.getValueType().getScalarType(), GEPPtrsVal, + DAG.getConstant(0, sdl, IdxVT)); SDB->setValue(Ptr, Base); } else return false; - Value *IndexVal = Gep->getOperand(1); + Value *IndexVal = GEP->getOperand(1); if (SDB->findValue(IndexVal)) { Index = SDB->getValue(IndexVal);