Move check for linear vector to LLVMVectorIsLinear() function.
This commit is contained in:
222
llvmutil.cpp
222
llvmutil.cpp
@@ -832,6 +832,228 @@ LLVMVectorValuesAllEqual(llvm::Value *v) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
lVectorIsLinear(llvm::Value *v, int vectorLength, int stride,
|
||||||
|
std::vector<llvm::PHINode *> &seenPhis);
|
||||||
|
|
||||||
|
/** Given a vector of compile-time constant integer values, test to see if
|
||||||
|
they are a linear sequence of constant integers starting from an
|
||||||
|
arbirary value but then having a step of value "stride" between
|
||||||
|
elements.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
lVectorIsLinearConstantInts(
|
||||||
|
#ifdef LLVM_3_1svn
|
||||||
|
llvm::ConstantDataVector *cv,
|
||||||
|
#else
|
||||||
|
llvm::ConstantVector *cv,
|
||||||
|
#endif
|
||||||
|
int vectorLength,
|
||||||
|
int stride) {
|
||||||
|
// Flatten the vector out into the elements array
|
||||||
|
llvm::SmallVector<llvm::Constant *, ISPC_MAX_NVEC> elements;
|
||||||
|
#ifdef LLVM_3_1svn
|
||||||
|
for (int i = 0; i < (int)cv->getNumElements(); ++i)
|
||||||
|
elements.push_back(cv->getElementAsConstant(i));
|
||||||
|
#else
|
||||||
|
cv->getVectorElements(elements);
|
||||||
|
#endif
|
||||||
|
Assert((int)elements.size() == vectorLength);
|
||||||
|
|
||||||
|
llvm::ConstantInt *ci = llvm::dyn_cast<llvm::ConstantInt>(elements[0]);
|
||||||
|
if (ci == NULL)
|
||||||
|
// Not a vector of integers
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int64_t prevVal = ci->getSExtValue();
|
||||||
|
|
||||||
|
// For each element in the array, see if it is both a ConstantInt and
|
||||||
|
// if the difference between it and the value of the previous element
|
||||||
|
// is stride. If not, fail.
|
||||||
|
for (int i = 1; i < vectorLength; ++i) {
|
||||||
|
ci = llvm::dyn_cast<llvm::ConstantInt>(elements[i]);
|
||||||
|
if (ci == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int64_t nextVal = ci->getSExtValue();
|
||||||
|
if (prevVal + stride != nextVal)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
prevVal = nextVal;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Checks to see if (op0 * op1) is a linear vector where the result is a
|
||||||
|
vector with values that increase by stride.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
lCheckMulForLinear(llvm::Value *op0, llvm::Value *op1, int vectorLength,
|
||||||
|
int stride, std::vector<llvm::PHINode *> &seenPhis) {
|
||||||
|
// Is the first operand a constant integer value splatted across all of
|
||||||
|
// the lanes?
|
||||||
|
#ifdef LLVM_3_1svn
|
||||||
|
llvm::ConstantDataVector *cv = llvm::dyn_cast<llvm::ConstantDataVector>(op0);
|
||||||
|
#else
|
||||||
|
llvm::ConstantVector *cv = llvm::dyn_cast<llvm::ConstantVector>(op0);
|
||||||
|
#endif
|
||||||
|
if (cv == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
llvm::Constant *csplat = cv->getSplatValue();
|
||||||
|
if (csplat == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
llvm::ConstantInt *splat = llvm::dyn_cast<llvm::ConstantInt>(csplat);
|
||||||
|
if (splat == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// If the splat value doesn't evenly divide the stride we're looking
|
||||||
|
// for, there's no way that we can get the linear sequence we're
|
||||||
|
// looking or.
|
||||||
|
int64_t splatVal = splat->getSExtValue();
|
||||||
|
if (splatVal == 0 || splatVal > stride || (stride % splatVal) != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Check to see if the other operand is a linear vector with stride
|
||||||
|
// given by stride/splatVal.
|
||||||
|
return lVectorIsLinear(op1, vectorLength, (int)(stride / splatVal),
|
||||||
|
seenPhis);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
lVectorIsLinear(llvm::Value *v, int vectorLength, int stride,
|
||||||
|
std::vector<llvm::PHINode *> &seenPhis) {
|
||||||
|
// First try the easy case: if the values are all just constant
|
||||||
|
// integers and have the expected stride between them, then we're done.
|
||||||
|
#ifdef LLVM_3_1svn
|
||||||
|
llvm::ConstantDataVector *cv = llvm::dyn_cast<llvm::ConstantDataVector>(v);
|
||||||
|
#else
|
||||||
|
llvm::ConstantVector *cv = llvm::dyn_cast<llvm::ConstantVector>(v);
|
||||||
|
#endif
|
||||||
|
if (cv != NULL)
|
||||||
|
return lVectorIsLinearConstantInts(cv, vectorLength, stride);
|
||||||
|
|
||||||
|
llvm::BinaryOperator *bop = llvm::dyn_cast<llvm::BinaryOperator>(v);
|
||||||
|
if (bop != NULL) {
|
||||||
|
// FIXME: is it right to pass the seenPhis to the all equal check as well??
|
||||||
|
llvm::Value *op0 = bop->getOperand(0), *op1 = bop->getOperand(1);
|
||||||
|
|
||||||
|
if (bop->getOpcode() == llvm::Instruction::Add) {
|
||||||
|
// There are two cases to check if we have an add:
|
||||||
|
//
|
||||||
|
// programIndex + unif -> ascending linear seqeuence
|
||||||
|
// unif + programIndex -> ascending linear sequence
|
||||||
|
bool l0 = lVectorIsLinear(op0, vectorLength, stride, seenPhis);
|
||||||
|
bool e1 = lVectorValuesAllEqual(op1, vectorLength, seenPhis);
|
||||||
|
if (l0 && e1)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
bool e0 = lVectorValuesAllEqual(op0, vectorLength, seenPhis);
|
||||||
|
bool l1 = lVectorIsLinear(op1, vectorLength, stride, seenPhis);
|
||||||
|
return (e0 && l1);
|
||||||
|
}
|
||||||
|
else if (bop->getOpcode() == llvm::Instruction::Sub)
|
||||||
|
// For subtraction, we only match:
|
||||||
|
// programIndex - unif -> ascending linear seqeuence
|
||||||
|
return (lVectorIsLinear(bop->getOperand(0), vectorLength,
|
||||||
|
stride, seenPhis) &&
|
||||||
|
lVectorValuesAllEqual(bop->getOperand(1), vectorLength,
|
||||||
|
seenPhis));
|
||||||
|
else if (bop->getOpcode() == llvm::Instruction::Mul) {
|
||||||
|
// Multiplies are a bit trickier, so are handled in a separate
|
||||||
|
// function.
|
||||||
|
bool m0 = lCheckMulForLinear(op0, op1, vectorLength, stride, seenPhis);
|
||||||
|
if (m0)
|
||||||
|
return true;
|
||||||
|
bool m1 = lCheckMulForLinear(op1, op0, vectorLength, stride, seenPhis);
|
||||||
|
return m1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::CastInst *ci = llvm::dyn_cast<llvm::CastInst>(v);
|
||||||
|
if (ci != NULL)
|
||||||
|
return lVectorIsLinear(ci->getOperand(0), vectorLength,
|
||||||
|
stride, seenPhis);
|
||||||
|
|
||||||
|
if (llvm::isa<llvm::CallInst>(v) || llvm::isa<llvm::LoadInst>(v))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
llvm::PHINode *phi = llvm::dyn_cast<llvm::PHINode>(v);
|
||||||
|
if (phi != NULL) {
|
||||||
|
for (unsigned int i = 0; i < seenPhis.size(); ++i)
|
||||||
|
if (seenPhis[i] == phi)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
seenPhis.push_back(phi);
|
||||||
|
|
||||||
|
unsigned int numIncoming = phi->getNumIncomingValues();
|
||||||
|
// Check all of the incoming values: if all of them are all equal,
|
||||||
|
// then we're good.
|
||||||
|
for (unsigned int i = 0; i < numIncoming; ++i) {
|
||||||
|
if (!lVectorIsLinear(phi->getIncomingValue(i), vectorLength, stride,
|
||||||
|
seenPhis)) {
|
||||||
|
seenPhis.pop_back();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
seenPhis.pop_back();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: is any reason to worry about these?
|
||||||
|
if (llvm::isa<llvm::InsertElementInst>(v))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// TODO: we could also handle shuffles, but we haven't yet seen any
|
||||||
|
// cases where doing so would detect cases where actually have a linear
|
||||||
|
// vector.
|
||||||
|
llvm::ShuffleVectorInst *shuffle = llvm::dyn_cast<llvm::ShuffleVectorInst>(v);
|
||||||
|
if (shuffle != NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
fprintf(stderr, "linear check: ");
|
||||||
|
v->dump();
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
llvm::Instruction *inst = llvm::dyn_cast<llvm::Instruction>(v);
|
||||||
|
if (inst) {
|
||||||
|
inst->getParent()->dump();
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Given vector of integer-typed values, see if the elements of the array
|
||||||
|
have a step of 'stride' between their values. This function tries to
|
||||||
|
handle as many possibilities as possible, including things like all
|
||||||
|
elements equal to some non-constant value plus an integer offset, etc.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
LLVMVectorIsLinear(llvm::Value *v, int stride) {
|
||||||
|
LLVM_TYPE_CONST llvm::VectorType *vt =
|
||||||
|
llvm::dyn_cast<LLVM_TYPE_CONST llvm::VectorType>(v->getType());
|
||||||
|
Assert(vt != NULL);
|
||||||
|
int vectorLength = vt->getNumElements();
|
||||||
|
|
||||||
|
std::vector<llvm::PHINode *> seenPhis;
|
||||||
|
bool linear = lVectorIsLinear(v, vectorLength, stride, seenPhis);
|
||||||
|
Debug(SourcePos(), "LLVMVectorIsLinear(%s) -> %s.",
|
||||||
|
v->getName().str().c_str(), linear ? "true" : "false");
|
||||||
|
if (g->debugPrint)
|
||||||
|
LLVMDumpValue(v);
|
||||||
|
|
||||||
|
return linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
10
llvmutil.h
10
llvmutil.h
@@ -230,6 +230,16 @@ extern llvm::Constant *LLVMMaskAllOff;
|
|||||||
return false for arrays where the values are actually all equal. */
|
return false for arrays where the values are actually all equal. */
|
||||||
extern bool LLVMVectorValuesAllEqual(llvm::Value *v);
|
extern bool LLVMVectorValuesAllEqual(llvm::Value *v);
|
||||||
|
|
||||||
|
/** Given vector of integer-typed values, this function returns true if it
|
||||||
|
can determine that the elements of the vector have a step of 'stride'
|
||||||
|
between their values and false otherwise. This function tries to
|
||||||
|
handle as many possibilities as possible, including things like all
|
||||||
|
elements equal to some non-constant value plus an integer offset, etc.
|
||||||
|
Needless to say (the halting problem and all that), it may return false
|
||||||
|
for some vectors that are in fact linear.
|
||||||
|
*/
|
||||||
|
extern bool LLVMVectorIsLinear(llvm::Value *v, int stride);
|
||||||
|
|
||||||
/** Given a vector-typed value v, if the vector is a vector with constant
|
/** Given a vector-typed value v, if the vector is a vector with constant
|
||||||
element values, this function extracts those element values into the
|
element values, this function extracts those element values into the
|
||||||
ret[] array and returns the number of elements (i.e. the vector type's
|
ret[] array and returns the number of elements (i.e. the vector type's
|
||||||
|
|||||||
206
opt.cpp
206
opt.cpp
@@ -2267,208 +2267,6 @@ public:
|
|||||||
char GSToLoadStorePass::ID = 0;
|
char GSToLoadStorePass::ID = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** Given a vector of compile-time constant integer values, test to see if
|
|
||||||
they are a linear sequence of constant integers starting from an
|
|
||||||
arbirary value but then having a step of value "stride" between
|
|
||||||
elements.
|
|
||||||
*/
|
|
||||||
static bool
|
|
||||||
lVectorIsLinearConstantInts(
|
|
||||||
#ifdef LLVM_3_1svn
|
|
||||||
llvm::ConstantDataVector *cv,
|
|
||||||
#else
|
|
||||||
llvm::ConstantVector *cv,
|
|
||||||
#endif
|
|
||||||
int vectorLength,
|
|
||||||
int stride) {
|
|
||||||
// Flatten the vector out into the elements array
|
|
||||||
llvm::SmallVector<llvm::Constant *, ISPC_MAX_NVEC> elements;
|
|
||||||
#ifdef LLVM_3_1svn
|
|
||||||
for (int i = 0; i < (int)cv->getNumElements(); ++i)
|
|
||||||
elements.push_back(cv->getElementAsConstant(i));
|
|
||||||
#else
|
|
||||||
cv->getVectorElements(elements);
|
|
||||||
#endif
|
|
||||||
Assert((int)elements.size() == vectorLength);
|
|
||||||
|
|
||||||
llvm::ConstantInt *ci = llvm::dyn_cast<llvm::ConstantInt>(elements[0]);
|
|
||||||
if (ci == NULL)
|
|
||||||
// Not a vector of integers
|
|
||||||
return false;
|
|
||||||
|
|
||||||
int64_t prevVal = ci->getSExtValue();
|
|
||||||
|
|
||||||
// For each element in the array, see if it is both a ConstantInt and
|
|
||||||
// if the difference between it and the value of the previous element
|
|
||||||
// is stride. If not, fail.
|
|
||||||
for (int i = 1; i < vectorLength; ++i) {
|
|
||||||
ci = llvm::dyn_cast<llvm::ConstantInt>(elements[i]);
|
|
||||||
if (ci == NULL)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
int64_t nextVal = ci->getSExtValue();
|
|
||||||
if (prevVal + stride != nextVal)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
prevVal = nextVal;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static bool lVectorIsLinear(llvm::Value *v, int vectorLength, int stride,
|
|
||||||
std::vector<llvm::PHINode *> &seenPhis);
|
|
||||||
|
|
||||||
/** Checks to see if (op0 * op1) is a linear vector where the result is a
|
|
||||||
vector with values that increase by stride.
|
|
||||||
*/
|
|
||||||
static bool
|
|
||||||
lCheckMulForLinear(llvm::Value *op0, llvm::Value *op1, int vectorLength,
|
|
||||||
int stride, std::vector<llvm::PHINode *> &seenPhis) {
|
|
||||||
// Is the first operand a constant integer value splatted across all of
|
|
||||||
// the lanes?
|
|
||||||
#ifdef LLVM_3_1svn
|
|
||||||
llvm::ConstantDataVector *cv = llvm::dyn_cast<llvm::ConstantDataVector>(op0);
|
|
||||||
#else
|
|
||||||
llvm::ConstantVector *cv = llvm::dyn_cast<llvm::ConstantVector>(op0);
|
|
||||||
#endif
|
|
||||||
if (cv == NULL)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
llvm::Constant *csplat = cv->getSplatValue();
|
|
||||||
if (csplat == NULL)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
llvm::ConstantInt *splat = llvm::dyn_cast<llvm::ConstantInt>(csplat);
|
|
||||||
if (splat == NULL)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// If the splat value doesn't evenly divide the stride we're looking
|
|
||||||
// for, there's no way that we can get the linear sequence we're
|
|
||||||
// looking or.
|
|
||||||
int64_t splatVal = splat->getSExtValue();
|
|
||||||
if (splatVal == 0 || splatVal > stride || (stride % splatVal) != 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Check to see if the other operand is a linear vector with stride
|
|
||||||
// given by stride/splatVal.
|
|
||||||
return lVectorIsLinear(op1, vectorLength, (int)(stride / splatVal),
|
|
||||||
seenPhis);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Given vector of integer-typed values, see if the elements of the array
|
|
||||||
have a step of 'stride' between their values. This function tries to
|
|
||||||
handle as many possibilities as possible, including things like all
|
|
||||||
elements equal to some non-constant value plus an integer offset, etc.
|
|
||||||
*/
|
|
||||||
static bool
|
|
||||||
lVectorIsLinear(llvm::Value *v, int vectorLength, int stride,
|
|
||||||
std::vector<llvm::PHINode *> &seenPhis) {
|
|
||||||
// First try the easy case: if the values are all just constant
|
|
||||||
// integers and have the expected stride between them, then we're done.
|
|
||||||
#ifdef LLVM_3_1svn
|
|
||||||
llvm::ConstantDataVector *cv = llvm::dyn_cast<llvm::ConstantDataVector>(v);
|
|
||||||
#else
|
|
||||||
llvm::ConstantVector *cv = llvm::dyn_cast<llvm::ConstantVector>(v);
|
|
||||||
#endif
|
|
||||||
if (cv != NULL)
|
|
||||||
return lVectorIsLinearConstantInts(cv, vectorLength, stride);
|
|
||||||
|
|
||||||
llvm::BinaryOperator *bop = llvm::dyn_cast<llvm::BinaryOperator>(v);
|
|
||||||
if (bop != NULL) {
|
|
||||||
// FIXME: is it right to pass the seenPhis to the all equal check as well??
|
|
||||||
llvm::Value *op0 = bop->getOperand(0), *op1 = bop->getOperand(1);
|
|
||||||
|
|
||||||
if (bop->getOpcode() == llvm::Instruction::Add)
|
|
||||||
// There are two cases to check if we have an add:
|
|
||||||
//
|
|
||||||
// programIndex + unif -> ascending linear seqeuence
|
|
||||||
// unif + programIndex -> ascending linear sequence
|
|
||||||
return ((lVectorIsLinear(op0, vectorLength, stride, seenPhis) &&
|
|
||||||
LLVMVectorValuesAllEqual(op1, vectorLength, seenPhis)) ||
|
|
||||||
(lVectorIsLinear(op1, vectorLength, stride, seenPhis) &&
|
|
||||||
LLVMVectorValuesAllEqual(op0, vectorLength, seenPhis)));
|
|
||||||
else if (bop->getOpcode() == llvm::Instruction::Sub)
|
|
||||||
// For subtraction, we only match:
|
|
||||||
//
|
|
||||||
// programIndex - unif -> ascending linear seqeuence
|
|
||||||
//
|
|
||||||
// In the future, we could also look for:
|
|
||||||
// unif - programIndex -> *descending* linear seqeuence
|
|
||||||
// And generate code for that as a vector load + shuffle.
|
|
||||||
return (lVectorIsLinear(bop->getOperand(0), vectorLength,
|
|
||||||
stride, seenPhis) &&
|
|
||||||
LLVMVectorValuesAllEqual(bop->getOperand(1), vectorLength,
|
|
||||||
seenPhis));
|
|
||||||
else if (bop->getOpcode() == llvm::Instruction::Mul)
|
|
||||||
// Multiplies are a bit trickier, so are handled in a separate
|
|
||||||
// function.
|
|
||||||
return (lCheckMulForLinear(op0, op1, vectorLength, stride, seenPhis) ||
|
|
||||||
lCheckMulForLinear(op1, op0, vectorLength, stride, seenPhis));
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
llvm::CastInst *ci = llvm::dyn_cast<llvm::CastInst>(v);
|
|
||||||
if (ci != NULL)
|
|
||||||
return lVectorIsLinear(ci->getOperand(0), vectorLength,
|
|
||||||
stride, seenPhis);
|
|
||||||
|
|
||||||
if (llvm::isa<llvm::CallInst>(v) || llvm::isa<llvm::LoadInst>(v))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
llvm::PHINode *phi = llvm::dyn_cast<llvm::PHINode>(v);
|
|
||||||
if (phi != NULL) {
|
|
||||||
for (unsigned int i = 0; i < seenPhis.size(); ++i)
|
|
||||||
if (seenPhis[i] == phi)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
seenPhis.push_back(phi);
|
|
||||||
|
|
||||||
unsigned int numIncoming = phi->getNumIncomingValues();
|
|
||||||
// Check all of the incoming values: if all of them are all equal,
|
|
||||||
// then we're good.
|
|
||||||
for (unsigned int i = 0; i < numIncoming; ++i) {
|
|
||||||
if (!lVectorIsLinear(phi->getIncomingValue(i), vectorLength, stride,
|
|
||||||
seenPhis)) {
|
|
||||||
seenPhis.pop_back();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
seenPhis.pop_back();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: is any reason to worry about these?
|
|
||||||
if (llvm::isa<llvm::InsertElementInst>(v))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// TODO: we could also handle shuffles, but we haven't yet seen any
|
|
||||||
// cases where doing so would detect cases where actually have a linear
|
|
||||||
// vector.
|
|
||||||
llvm::ShuffleVectorInst *shuffle = llvm::dyn_cast<llvm::ShuffleVectorInst>(v);
|
|
||||||
if (shuffle != NULL)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
fprintf(stderr, "linear check: ");
|
|
||||||
v->dump();
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
llvm::Instruction *inst = llvm::dyn_cast<llvm::Instruction>(v);
|
|
||||||
if (inst) {
|
|
||||||
inst->getParent()->dump();
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
struct GatherImpInfo {
|
struct GatherImpInfo {
|
||||||
GatherImpInfo(const char *pName, const char *lbName, const char *lmName,
|
GatherImpInfo(const char *pName, const char *lbName, const char *lmName,
|
||||||
int a)
|
int a)
|
||||||
@@ -2665,9 +2463,7 @@ GSToLoadStorePass::runOnBasicBlock(llvm::BasicBlock &bb) {
|
|||||||
else {
|
else {
|
||||||
int step = gatherInfo ? gatherInfo->align : scatterInfo->align;
|
int step = gatherInfo ? gatherInfo->align : scatterInfo->align;
|
||||||
|
|
||||||
std::vector<llvm::PHINode *> seenPhis;
|
if (step > 0 && LLVMVectorIsLinear(fullOffsets, step)) {
|
||||||
if (step > 0 && lVectorIsLinear(fullOffsets, g->target.vectorWidth,
|
|
||||||
step, seenPhis)) {
|
|
||||||
// We have a linear sequence of memory locations being accessed
|
// We have a linear sequence of memory locations being accessed
|
||||||
// starting with the location given by the offset from
|
// starting with the location given by the offset from
|
||||||
// offsetElements[0], with stride of 4 or 8 bytes (for 32 bit
|
// offsetElements[0], with stride of 4 or 8 bytes (for 32 bit
|
||||||
|
|||||||
Reference in New Issue
Block a user