aboutsummaryrefslogtreecommitdiff
path: root/lib/Target/Alpha/AlphaISelPattern.cpp
diff options
context:
space:
mode:
authorAndrew Lenharth <andrewl@lenharth.org>2005-04-06 22:03:13 +0000
committerAndrew Lenharth <andrewl@lenharth.org>2005-04-06 22:03:13 +0000
commita565c275b5ada2d3434780463d87e24448751109 (patch)
treed8e6ec86206d6565bf937e9367b9d63613dc90f3 /lib/Target/Alpha/AlphaISelPattern.cpp
parent6128690c629380291b7185f09cd82ed5244c8a41 (diff)
added sdiv by 2^k and works for neg divisors also
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@21124 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/Alpha/AlphaISelPattern.cpp')
-rw-r--r--lib/Target/Alpha/AlphaISelPattern.cpp69
1 files changed, 59 insertions, 10 deletions
diff --git a/lib/Target/Alpha/AlphaISelPattern.cpp b/lib/Target/Alpha/AlphaISelPattern.cpp
index d046ce6b4c..a4fdb26b8f 100644
--- a/lib/Target/Alpha/AlphaISelPattern.cpp
+++ b/lib/Target/Alpha/AlphaISelPattern.cpp
@@ -533,6 +533,18 @@ SDOperand ISel::BuildUDIVSequence(SDOperand N) {
return Q;
}
+//From PPC32
+/// ExactLog2 - This function solves for (Val == 1 << (N-1)) and returns N. It
+/// returns zero when the input is not exactly a power of two.
+static unsigned ExactLog2(uint64_t Val) {
+ if (Val == 0 || (Val & (Val-1))) return 0;
+ unsigned Count = 0;
+ while (Val != 1) {
+ Val >>= 1;
+ ++Count;
+ }
+ return Count;
+}
//These describe LDAx
@@ -1788,18 +1800,55 @@ unsigned ISel::SelectExpr(SDOperand N) {
}
case ISD::SDIV:
+ {
+ ConstantSDNode* CSD;
+ //check if we can convert into a shift!
+ if ((CSD = dyn_cast<ConstantSDNode>(N.getOperand(1).Val)) &&
+ (int64_t)CSD->getSignExtended() != 0 &&
+ ExactLog2(abs((int64_t)CSD->getSignExtended())) != 0)
+ {
+ unsigned k = ExactLog2(abs(CSD->getSignExtended()));
+ Tmp1 = SelectExpr(N.getOperand(0));
+ Tmp2 = MakeReg(MVT::i64);
+ if (k == 1)
+ Tmp2 = Tmp1;
+ else
+ {
+ Tmp2 = MakeReg(MVT::i64);
+ BuildMI(BB, Alpha::SRAi, 2, Tmp2).addReg(Tmp1).addImm(k - 1);
+ }
+ Tmp3 = MakeReg(MVT::i64);
+ BuildMI(BB, Alpha::SRLi, 2, Tmp3).addReg(Tmp2).addImm(64-k);
+ unsigned Tmp4 = MakeReg(MVT::i64);
+ BuildMI(BB, Alpha::ADDQ, 2, Tmp4).addReg(Tmp3).addReg(Tmp1);
+ if ((int64_t)CSD->getSignExtended() > 0)
+ BuildMI(BB, Alpha::SRAi, 2, Result).addReg(Tmp4).addImm(k);
+ else
+ {
+ unsigned Tmp5 = MakeReg(MVT::i64);
+ BuildMI(BB, Alpha::SRAi, 2, Tmp5).addReg(Tmp4).addImm(k);
+ BuildMI(BB, Alpha::SUBQ, 2, Result).addReg(Alpha::R31).addReg(Tmp5);
+ }
+ return Result;
+ }
+ }
+ //Else fall through
+
case ISD::UDIV:
- if (N.getOperand(1).getOpcode() == ISD::Constant &&
- ((int64_t)cast<ConstantSDNode>(N.getOperand(1))->getSignExtended() >= 2 ||
- (int64_t)cast<ConstantSDNode>(N.getOperand(1))->getSignExtended() <= -2))
{
- // If this is a divide by constant, we can emit code using some magic
- // constants to implement it as a multiply instead.
- ExprMap.erase(N);
- if (opcode == ISD::SDIV)
- return SelectExpr(BuildSDIVSequence(N));
- else
- return SelectExpr(BuildUDIVSequence(N));
+ ConstantSDNode* CSD;
+ if ((CSD = dyn_cast<ConstantSDNode>(N.getOperand(1).Val)) &&
+ ((int64_t)CSD->getSignExtended() >= 2 ||
+ (int64_t)CSD->getSignExtended() <= -2))
+ {
+ // If this is a divide by constant, we can emit code using some magic
+ // constants to implement it as a multiply instead.
+ ExprMap.erase(N);
+ if (opcode == ISD::SDIV)
+ return SelectExpr(BuildSDIVSequence(N));
+ else
+ return SelectExpr(BuildUDIVSequence(N));
+ }
}
//else fall though
case ISD::UREM: