Handle SHL with a constant vector in LLVMVectorIsLinear().

LLVM3.4 seems to be turning multiplies by a constant power of 2 into
the equivalent SHL, which was in turn thwarting the pattern matching
for turning gathers/scatters into vector loads/stores.
This commit is contained in:
Matt Pharr
2013-07-17 14:12:43 -07:00
parent f1cce0ef5f
commit 7454b1399c

View File

@@ -1207,6 +1207,40 @@ lCheckMulForLinear(llvm::Value *op0, llvm::Value *op1, int vectorLength,
}
/** Checks to see if (op0 << op1) is a linear vector where the result is a
vector with values that increase by stride.
*/
static bool
lCheckShlForLinear(llvm::Value *op0, llvm::Value *op1, int vectorLength,
int stride, std::vector<llvm::PHINode *> &seenPhis) {
// Is the second operand a constant integer value splatted across all of
// the lanes?
llvm::ConstantDataVector *cv = llvm::dyn_cast<llvm::ConstantDataVector>(op1);
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 (1 << 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 equivalentMul = (1 << splat->getSExtValue());
if (equivalentMul > stride || (stride % equivalentMul) != 0)
return false;
// Check to see if the first operand is a linear vector with stride
// given by stride/splatVal.
return lVectorIsLinear(op0, vectorLength, (int)(stride / equivalentMul),
seenPhis);
}
/** Given (op0 AND op1), try and see if we can determine if the result is a
linear sequence with a step of "stride" between values. Returns true
if so and false otherwise. This pattern comes up when accessing SOA
@@ -1290,6 +1324,12 @@ lVectorIsLinear(llvm::Value *v, int vectorLength, int stride,
bool m1 = lCheckMulForLinear(op1, op0, vectorLength, stride, seenPhis);
return m1;
}
else if (bop->getOpcode() == llvm::Instruction::Shl) {
// Sometimes multiplies come in as shift lefts (especially in
// LLVM 3.4+).
bool linear = lCheckShlForLinear(op0, op1, vectorLength, stride, seenPhis);
return linear;
}
else if (bop->getOpcode() == llvm::Instruction::And) {
// Special case for some AND-related patterns that come up when
// looping over SOA data