From f20a2d2ee970c21dc508ba20a2f65230b410c81b Mon Sep 17 00:00:00 2001 From: Matt Pharr Date: Fri, 10 Feb 2012 12:35:44 -0800 Subject: [PATCH] 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. --- opt.cpp | 56 ++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/opt.cpp b/opt.cpp index 74733804..d64cdcbd 100644 --- a/opt.cpp +++ b/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 - the value 2, 4, 8 in all of the elements. (Returns the splatted value - in *splat, if so). */ + the same value in all of the elements. (Returns the splatted value in + *splat, if so). */ static bool -lIs248Splat(llvm::Value *v, int *splat) { +lIsIntegerSplat(llvm::Value *v, int *splat) { #ifdef LLVM_3_1svn llvm::ConstantDataVector *cvec = llvm::dyn_cast(v); @@ -1412,14 +1412,46 @@ lIs248Splat(llvm::Value *v, int *splat) { return false; int64_t splatVal = ci->getSExtValue(); - if (splatVal != 2 && splatVal != 4 && splatVal != 8) - return false; - *splat = (int)splatVal; 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(*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 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. @@ -1482,14 +1514,10 @@ lExtractOffsetVector248Scale(llvm::Value **vec) { else if (bop->getOpcode() == llvm::Instruction::Mul) { // Check each operand for being one of the scale factors we care about. int splat; - if (lIs248Splat(op0, &splat)) { - *vec = op1; - return LLVMInt32(splat); - } - else if (lIs248Splat(op1, &splat)) { - *vec = op0; - return LLVMInt32(splat); - } + if (lIsIntegerSplat(op0, &splat)) + return lExtract248Scale(op0, splat, op1, vec); + else if (lIsIntegerSplat(op1, &splat)) + return lExtract248Scale(op1, splat, op0, vec); else return LLVMInt32(1); }