Generalize code to extract scales by 2/4/8 from addressing calculations.
Now, if we have a scale by 16, say, we extract out the scalar scale of 8 and leave an explicit scale by 2.
This commit is contained in:
56
opt.cpp
56
opt.cpp
@@ -1389,10 +1389,10 @@ lExtractConstantOffset(llvm::Value *vec, llvm::Value **constOffset,
|
|||||||
|
|
||||||
|
|
||||||
/* Returns true if the given value is a constant vector of integers with
|
/* Returns true if the given value is a constant vector of integers with
|
||||||
the value 2, 4, 8 in all of the elements. (Returns the splatted value
|
the same value in all of the elements. (Returns the splatted value in
|
||||||
in *splat, if so). */
|
*splat, if so). */
|
||||||
static bool
|
static bool
|
||||||
lIs248Splat(llvm::Value *v, int *splat) {
|
lIsIntegerSplat(llvm::Value *v, int *splat) {
|
||||||
#ifdef LLVM_3_1svn
|
#ifdef LLVM_3_1svn
|
||||||
llvm::ConstantDataVector *cvec =
|
llvm::ConstantDataVector *cvec =
|
||||||
llvm::dyn_cast<llvm::ConstantDataVector>(v);
|
llvm::dyn_cast<llvm::ConstantDataVector>(v);
|
||||||
@@ -1412,14 +1412,46 @@ lIs248Splat(llvm::Value *v, int *splat) {
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
int64_t splatVal = ci->getSExtValue();
|
int64_t splatVal = ci->getSExtValue();
|
||||||
if (splatVal != 2 && splatVal != 4 && splatVal != 8)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
*splat = (int)splatVal;
|
*splat = (int)splatVal;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static llvm::Value *
|
||||||
|
lExtract248Scale(llvm::Value *splatOperand, int splatValue,
|
||||||
|
llvm::Value *otherOperand, llvm::Value **result) {
|
||||||
|
if (splatValue == 2 || splatValue == 4 || splatValue == 8) {
|
||||||
|
*result = otherOperand;
|
||||||
|
return LLVMInt32(splatValue);
|
||||||
|
}
|
||||||
|
// Even if we don't have a common scale by exactly 2, 4, or 8, we'll
|
||||||
|
// see if we can pull out that much of the scale anyway; this may in
|
||||||
|
// turn allow other optimizations later.
|
||||||
|
for (int scale = 8; scale >= 2; scale /= 2) {
|
||||||
|
llvm::Instruction *insertBefore =
|
||||||
|
llvm::dyn_cast<llvm::Instruction>(*result);
|
||||||
|
Assert(insertBefore != NULL);
|
||||||
|
|
||||||
|
if ((splatValue % scale) == 0) {
|
||||||
|
// *result = otherOperand + splatOperand / splatValue;
|
||||||
|
llvm::Value *splatScaleVec =
|
||||||
|
(splatOperand->getType() == LLVMTypes::Int32VectorType) ?
|
||||||
|
LLVMInt32Vector(scale) : LLVMInt64Vector(scale);
|
||||||
|
llvm::Value *splatDiv =
|
||||||
|
llvm::BinaryOperator::Create(llvm::Instruction::SDiv,
|
||||||
|
splatOperand, splatScaleVec,
|
||||||
|
"div", insertBefore);
|
||||||
|
*result =
|
||||||
|
llvm::BinaryOperator::Create(llvm::Instruction::Add,
|
||||||
|
splatDiv, otherOperand,
|
||||||
|
"add", insertBefore);
|
||||||
|
return LLVMInt32(scale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return LLVMInt32(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Given a vector of integer offsets to a base pointer being used for a
|
/** Given a vector of integer offsets to a base pointer being used for a
|
||||||
gather or a scatter, see if its root operation is a multiply by a
|
gather or a scatter, see if its root operation is a multiply by a
|
||||||
vector of some value by all 2s/4s/8s. If not, return NULL.
|
vector of some value by all 2s/4s/8s. If not, return NULL.
|
||||||
@@ -1482,14 +1514,10 @@ lExtractOffsetVector248Scale(llvm::Value **vec) {
|
|||||||
else if (bop->getOpcode() == llvm::Instruction::Mul) {
|
else if (bop->getOpcode() == llvm::Instruction::Mul) {
|
||||||
// Check each operand for being one of the scale factors we care about.
|
// Check each operand for being one of the scale factors we care about.
|
||||||
int splat;
|
int splat;
|
||||||
if (lIs248Splat(op0, &splat)) {
|
if (lIsIntegerSplat(op0, &splat))
|
||||||
*vec = op1;
|
return lExtract248Scale(op0, splat, op1, vec);
|
||||||
return LLVMInt32(splat);
|
else if (lIsIntegerSplat(op1, &splat))
|
||||||
}
|
return lExtract248Scale(op1, splat, op0, vec);
|
||||||
else if (lIs248Splat(op1, &splat)) {
|
|
||||||
*vec = op0;
|
|
||||||
return LLVMInt32(splat);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
return LLVMInt32(1);
|
return LLVMInt32(1);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user