Fixed a failure in cost calculation for vector GEP

Cost calculation for vector GEP failed with due to invalid cast to GEP index operand.
The bug is fixed, added a test.

http://reviews.llvm.org/D14976



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@254408 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Elena Demikhovsky 2015-12-01 12:08:36 +00:00
parent c309d73346
commit ef5008e6d0
5 changed files with 43 additions and 17 deletions

View File

@ -22,6 +22,7 @@
#include "llvm/IR/GetElementPtrTypeIterator.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/Type.h"
#include "llvm/Analysis/VectorUtils.h"
namespace llvm {
@ -415,21 +416,28 @@ public:
(Ptr == nullptr ? 0 : Ptr->getType()->getPointerAddressSpace());
auto GTI = gep_type_begin(PointerType::get(PointeeType, AS), Operands);
for (auto I = Operands.begin(); I != Operands.end(); ++I, ++GTI) {
// We assume that the cost of Scalar GEP with constant index and the
// cost of Vector GEP with splat constant index are the same.
const ConstantInt *ConstIdx = dyn_cast<ConstantInt>(*I);
if (!ConstIdx)
if (auto Splat = getSplatValue(*I))
ConstIdx = dyn_cast<ConstantInt>(Splat);
if (isa<SequentialType>(*GTI)) {
int64_t ElementSize = DL.getTypeAllocSize(GTI.getIndexedType());
if (const ConstantInt *ConstIdx = dyn_cast<ConstantInt>(*I)) {
if (ConstIdx)
BaseOffset += ConstIdx->getSExtValue() * ElementSize;
} else {
else {
// Needs scale register.
if (Scale != 0) {
if (Scale != 0)
// No addressing mode takes two scale registers.
return TTI::TCC_Basic;
}
Scale = ElementSize;
}
} else {
StructType *STy = cast<StructType>(*GTI);
uint64_t Field = cast<ConstantInt>(*I)->getZExtValue();
// For structures the index is always splat or scalar constant
assert(ConstIdx && "Unexpected GEP index");
uint64_t Field = ConstIdx->getZExtValue();
BaseOffset += DL.getStructLayout(STy)->getElementOffset(Field);
}
}

View File

@ -86,7 +86,7 @@ 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);
const Value *getSplatValue(const Value *V);
/// \brief Compute a map of integer instructions to their minimum legal type
/// size.

View File

@ -417,9 +417,10 @@ Value *llvm::findScalarElement(Value *V, unsigned EltNo) {
/// the input value is (1) a splat constants vector or (2) a sequence
/// of instructions that broadcast a single value into a vector.
///
llvm::Value *llvm::getSplatValue(Value *V) {
if (auto *CV = dyn_cast<ConstantDataVector>(V))
return CV->getSplatValue();
const llvm::Value *llvm::getSplatValue(const Value *V) {
if (auto *C = dyn_cast<Constant>(V))
return C->getSplatValue();
auto *ShuffleInst = dyn_cast<ShuffleVectorInst>(V);
if (!ShuffleInst)

View File

@ -3301,18 +3301,18 @@ void SelectionDAGBuilder::visitMaskedStore(const CallInst &I) {
// extract the spalt value and use it as a uniform base.
// In all other cases the function returns 'false'.
//
static bool getUniformBase(Value *& Ptr, SDValue& Base, SDValue& Index,
static bool getUniformBase(const Value *& Ptr, SDValue& Base, SDValue& Index,
SelectionDAGBuilder* SDB) {
SelectionDAG& DAG = SDB->DAG;
LLVMContext &Context = *DAG.getContext();
assert(Ptr->getType()->isVectorTy() && "Uexpected pointer type");
GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Ptr);
const GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Ptr);
if (!GEP || GEP->getNumOperands() > 2)
return false;
Value *GEPPtr = GEP->getPointerOperand();
const Value *GEPPtr = GEP->getPointerOperand();
if (!GEPPtr->getType()->isVectorTy())
Ptr = GEPPtr;
else if (!(Ptr = getSplatValue(GEPPtr)))
@ -3348,7 +3348,7 @@ void SelectionDAGBuilder::visitMaskedScatter(const CallInst &I) {
SDLoc sdl = getCurSDLoc();
// llvm.masked.scatter.*(Src0, Ptrs, alignemt, Mask)
Value *Ptr = I.getArgOperand(1);
const Value *Ptr = I.getArgOperand(1);
SDValue Src0 = getValue(I.getArgOperand(0));
SDValue Mask = getValue(I.getArgOperand(3));
EVT VT = Src0.getValueType();
@ -3362,10 +3362,10 @@ void SelectionDAGBuilder::visitMaskedScatter(const CallInst &I) {
SDValue Base;
SDValue Index;
Value *BasePtr = Ptr;
const Value *BasePtr = Ptr;
bool UniformBase = getUniformBase(BasePtr, Base, Index, this);
Value *MemOpBasePtr = UniformBase ? BasePtr : nullptr;
const Value *MemOpBasePtr = UniformBase ? BasePtr : nullptr;
MachineMemOperand *MMO = DAG.getMachineFunction().
getMachineMemOperand(MachinePointerInfo(MemOpBasePtr),
MachineMemOperand::MOStore, VT.getStoreSize(),
@ -3425,7 +3425,7 @@ void SelectionDAGBuilder::visitMaskedGather(const CallInst &I) {
SDLoc sdl = getCurSDLoc();
// @llvm.masked.gather.*(Ptrs, alignment, Mask, Src0)
Value *Ptr = I.getArgOperand(0);
const Value *Ptr = I.getArgOperand(0);
SDValue Src0 = getValue(I.getArgOperand(3));
SDValue Mask = getValue(I.getArgOperand(2));
@ -3442,7 +3442,7 @@ void SelectionDAGBuilder::visitMaskedGather(const CallInst &I) {
SDValue Root = DAG.getRoot();
SDValue Base;
SDValue Index;
Value *BasePtr = Ptr;
const Value *BasePtr = Ptr;
bool UniformBase = getUniformBase(BasePtr, Base, Index, this);
bool ConstantMemory = false;
if (UniformBase &&

View File

@ -0,0 +1,17 @@
; RUN: opt < %s -cost-model -analyze -mtriple=x86_64-linux-unknown-unknown -mattr=+avx512f | FileCheck %s
%struct.S = type { [1000 x i32] }
declare <4 x i32> @llvm.masked.gather.v4i32(<4 x i32*>, i32, <4 x i1>, <4 x i32>)
define <4 x i32> @foov(<4 x %struct.S*> %s, i64 %base){
%temp = insertelement <4 x i64> undef, i64 %base, i32 0
%vector = shufflevector <4 x i64> %temp, <4 x i64> undef, <4 x i32> zeroinitializer
;CHECK: cost of 0 for instruction: {{.*}} getelementptr inbounds %struct.S
%B = getelementptr inbounds %struct.S, <4 x %struct.S*> %s, <4 x i32> zeroinitializer, <4 x i32> zeroinitializer
;CHECK: cost of 0 for instruction: {{.*}} getelementptr inbounds [1000 x i32]
%arrayidx = getelementptr inbounds [1000 x i32], <4 x [1000 x i32]*> %B, <4 x i64> zeroinitializer, <4 x i64> %vector
%res = call <4 x i32> @llvm.masked.gather.v4i32(<4 x i32*> %arrayidx, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
ret <4 x i32> %res
}