diff options
author | Chris Lattner <sabre@nondot.org> | 2006-12-12 02:26:09 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2006-12-12 02:26:09 +0000 |
commit | a17f03980f88f23be3298d4128b9c02ebb360f31 (patch) | |
tree | 2faa033ed7e533044f521fb324d0ed13f05ce8e5 /lib/Analysis/ScalarEvolution.cpp | |
parent | 86b89e55290e2245dc3fe72c4e084cc74179ac08 (diff) |
teach scev to analyze X*4|1 like X*4+c. This allows us to produce:
LBB1_1: #bb
movdqa (%esi), %xmm2
movaps %xmm2, %xmm3
punpcklbw %xmm0, %xmm3
movaps %xmm3, %xmm4
punpcklwd %xmm0, %xmm4
cvtdq2ps %xmm4, %xmm4
mulps %xmm1, %xmm4
movaps %xmm4, (%edi)
leal 1(,%eax,4), %ebx
shll $4, %ebx
punpckhwd %xmm0, %xmm3
cvtdq2ps %xmm3, %xmm3
mulps %xmm1, %xmm3
movaps %xmm3, (%edx,%ebx)
leal 2(,%eax,4), %ebx
shll $4, %ebx
punpckhbw %xmm0, %xmm2
movaps %xmm2, %xmm3
punpcklwd %xmm0, %xmm3
cvtdq2ps %xmm3, %xmm3
mulps %xmm1, %xmm3
movaps %xmm3, (%edx,%ebx)
leal 3(,%eax,4), %ebx
shll $4, %ebx
punpckhwd %xmm0, %xmm2
cvtdq2ps %xmm2, %xmm2
mulps %xmm1, %xmm2
movaps %xmm2, (%edx,%ebx)
addl $64, %edi
incl %eax
addl $16, %esi
cmpl %ecx, %eax
jne LBB1_1 #bb
instead of:
LBB1_1: #bb
movdqa (%esi), %xmm2
movaps %xmm2, %xmm3
punpcklbw %xmm0, %xmm3
movaps %xmm3, %xmm4
punpcklwd %xmm0, %xmm4
cvtdq2ps %xmm4, %xmm4
mulps %xmm1, %xmm4
movaps %xmm4, (%edi)
leal 1(,%eax,4), %ebx
shll $4, %ebx
punpckhwd %xmm0, %xmm3
cvtdq2ps %xmm3, %xmm3
mulps %xmm1, %xmm3
movaps %xmm3, (%edx,%ebx)
leal 2(,%eax,4), %ebx
shll $4, %ebx
punpckhbw %xmm0, %xmm2
movaps %xmm2, %xmm3
punpcklwd %xmm0, %xmm3
cvtdq2ps %xmm3, %xmm3
mulps %xmm1, %xmm3
movaps %xmm3, (%edx,%ebx)
leal 3(,%eax,4), %ebx
shll $4, %ebx
punpckhwd %xmm0, %xmm2
cvtdq2ps %xmm2, %xmm2
mulps %xmm1, %xmm2
movaps %xmm2, (%edx,%ebx)
addl $64, %edi
incl %eax
addl $16, %esi
cmpl %ecx, %eax
jne LBB1_1 #bb
for a testcase.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@32463 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/ScalarEvolution.cpp')
-rw-r--r-- | lib/Analysis/ScalarEvolution.cpp | 60 |
1 files changed, 59 insertions, 1 deletions
diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp index 710983b526..6d449d0d92 100644 --- a/lib/Analysis/ScalarEvolution.cpp +++ b/lib/Analysis/ScalarEvolution.cpp @@ -1339,6 +1339,49 @@ SCEVHandle ScalarEvolutionsImpl::createNodeForPHI(PHINode *PN) { return SCEVUnknown::get(PN); } +/// GetConstantFactor - Determine the largest constant factor that S has. For +/// example, turn {4,+,8} -> 4. (S umod result) should always equal zero. +static uint64_t GetConstantFactor(SCEVHandle S) { + if (SCEVConstant *C = dyn_cast<SCEVConstant>(S)) { + if (uint64_t V = C->getValue()->getZExtValue()) + return V; + else // Zero is a multiple of everything. + return 1ULL << (S->getType()->getPrimitiveSizeInBits()-1); + } + + if (SCEVTruncateExpr *T = dyn_cast<SCEVTruncateExpr>(S)) + return GetConstantFactor(T->getOperand()) & + T->getType()->getIntegralTypeMask(); + if (SCEVZeroExtendExpr *E = dyn_cast<SCEVZeroExtendExpr>(S)) + return GetConstantFactor(E->getOperand()); + + if (SCEVAddExpr *A = dyn_cast<SCEVAddExpr>(S)) { + // The result is the min of all operands. + uint64_t Res = GetConstantFactor(A->getOperand(0)); + for (unsigned i = 1, e = A->getNumOperands(); i != e && Res > 1; ++i) + Res = std::min(Res, GetConstantFactor(A->getOperand(i))); + return Res; + } + + if (SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(S)) { + // The result is the product of all the operands. + uint64_t Res = GetConstantFactor(M->getOperand(0)); + for (unsigned i = 1, e = M->getNumOperands(); i != e; ++i) + Res *= GetConstantFactor(M->getOperand(i)); + return Res; + } + + if (SCEVAddRecExpr *A = dyn_cast<SCEVAddRecExpr>(S)) { + // FIXME: Generalize. + if (A->getNumOperands() == 2) + return std::min(GetConstantFactor(A->getOperand(0)), + GetConstantFactor(A->getOperand(1))); + // ? + } + + // SCEVSDivExpr, SCEVUnknown. + return 1; +} /// createSCEV - We know that there is no SCEV for the specified value. /// Analyze the expression. @@ -1360,7 +1403,22 @@ SCEVHandle ScalarEvolutionsImpl::createSCEV(Value *V) { case Instruction::Sub: return SCEV::getMinusSCEV(getSCEV(I->getOperand(0)), getSCEV(I->getOperand(1))); - + case Instruction::Or: + // If the RHS of the Or is a constant, we may have something like: + // X*4+1 which got turned into X*4|1. Handle this as an add so loop + // optimizations will transparently handle this case. + if (ConstantInt *CI = dyn_cast<ConstantInt>(I->getOperand(1))) { + SCEVHandle LHS = getSCEV(I->getOperand(0)); + uint64_t CommonFact = GetConstantFactor(LHS); + assert(CommonFact && "Common factor should at least be 1!"); + if (CommonFact > CI->getZExtValue()) { + // If the LHS is a multiple that is larger than the RHS, use +. + return SCEVAddExpr::get(LHS, + getSCEV(I->getOperand(1))); + } + } + break; + case Instruction::Shl: // Turn shift left of a constant amount into a multiply. if (ConstantInt *SA = dyn_cast<ConstantInt>(I->getOperand(1))) { |