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 /** 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 linear sequence with a step of "stride" between values. Returns true
if so and false otherwise. This pattern comes up when accessing SOA 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); bool m1 = lCheckMulForLinear(op1, op0, vectorLength, stride, seenPhis);
return m1; 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) { else if (bop->getOpcode() == llvm::Instruction::And) {
// Special case for some AND-related patterns that come up when // Special case for some AND-related patterns that come up when
// looping over SOA data // looping over SOA data