summaryrefslogtreecommitdiffstats
path: root/lib/Target/X86/X86ISelDAGToDAG.cpp
diff options
context:
space:
mode:
authorDan Gohman <gohman@apple.com>2007-09-25 18:23:27 +0000
committerDan Gohman <gohman@apple.com>2007-09-25 18:23:27 +0000
commita37c9f7506af622b9f29a35466b33c650c75e9f7 (patch)
tree4749c09d72e3e4f7fc9c436ac321fd9cca2f5a1b /lib/Target/X86/X86ISelDAGToDAG.cpp
parent798b4afd48ebc0acc165789ab913ccd28466ef68 (diff)
downloadexternal_llvm-a37c9f7506af622b9f29a35466b33c650c75e9f7.zip
external_llvm-a37c9f7506af622b9f29a35466b33c650c75e9f7.tar.gz
external_llvm-a37c9f7506af622b9f29a35466b33c650c75e9f7.tar.bz2
When both x/y and x%y are needed (x and y both scalar integer), compute
both results with a single div or idiv instruction. This uses new X86ISD nodes for DIV and IDIV which are introduced during the legalize phase so that the SelectionDAG's CSE can automatically eliminate redundant computations. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@42308 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/X86/X86ISelDAGToDAG.cpp')
-rw-r--r--lib/Target/X86/X86ISelDAGToDAG.cpp65
1 files changed, 40 insertions, 25 deletions
diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp
index b33ced8..117d273 100644
--- a/lib/Target/X86/X86ISelDAGToDAG.cpp
+++ b/lib/Target/X86/X86ISelDAGToDAG.cpp
@@ -1162,12 +1162,9 @@ SDNode *X86DAGToDAGISel::Select(SDOperand N) {
return NULL;
}
- case ISD::SDIV:
- case ISD::UDIV:
- case ISD::SREM:
- case ISD::UREM: {
- bool isSigned = Opcode == ISD::SDIV || Opcode == ISD::SREM;
- bool isDiv = Opcode == ISD::SDIV || Opcode == ISD::UDIV;
+ case X86ISD::DIV:
+ case X86ISD::IDIV: {
+ bool isSigned = Opcode == X86ISD::IDIV;
if (!isSigned)
switch (NVT) {
default: assert(0 && "Unsupported VT!");
@@ -1275,31 +1272,49 @@ SDNode *X86DAGToDAGISel::Select(SDOperand N) {
SDOperand(CurDAG->getTargetNode(Opc, MVT::Flag, N1, InFlag), 0);
}
- unsigned Reg = isDiv ? LoReg : HiReg;
- SDOperand Result;
- if (Reg == X86::AH && Subtarget->is64Bit()) {
- // Prevent use of AH in a REX instruction by referencing AX instead.
- // Shift it down 8 bits.
- Result = CurDAG->getCopyFromReg(Chain, X86::AX, MVT::i16, InFlag);
- Chain = Result.getValue(1);
- Result = SDOperand(CurDAG->getTargetNode(X86::SHR16ri, MVT::i16, Result,
- CurDAG->getTargetConstant(8, MVT::i8)), 0);
- // Then truncate it down to i8.
- SDOperand SRIdx = CurDAG->getTargetConstant(1, MVT::i32); // SubRegSet 1
- Result = SDOperand(CurDAG->getTargetNode(X86::EXTRACT_SUBREG,
- MVT::i8, Result, SRIdx), 0);
- } else {
- Result = CurDAG->getCopyFromReg(Chain, Reg, NVT, InFlag);
+ // Copy the division (low) result, if it is needed.
+ if (!N.getValue(0).use_empty()) {
+ SDOperand Result = CurDAG->getCopyFromReg(Chain, LoReg, NVT, InFlag);
Chain = Result.getValue(1);
+ InFlag = Result.getValue(2);
+ ReplaceUses(N.getValue(0), Result);
+#ifndef NDEBUG
+ DOUT << std::string(Indent-2, ' ') << "=> ";
+ DEBUG(Result.Val->dump(CurDAG));
+ DOUT << "\n";
+#endif
+ }
+ // Copy the remainder (high) result, if it is needed.
+ if (!N.getValue(1).use_empty()) {
+ SDOperand Result;
+ if (HiReg == X86::AH && Subtarget->is64Bit()) {
+ // Prevent use of AH in a REX instruction by referencing AX instead.
+ // Shift it down 8 bits.
+ Result = CurDAG->getCopyFromReg(Chain, X86::AX, MVT::i16, InFlag);
+ Chain = Result.getValue(1);
+ InFlag = Result.getValue(2);
+ Result = SDOperand(CurDAG->getTargetNode(X86::SHR16ri, MVT::i16, Result,
+ CurDAG->getTargetConstant(8, MVT::i8)), 0);
+ // Then truncate it down to i8.
+ SDOperand SRIdx = CurDAG->getTargetConstant(1, MVT::i32); // SubRegSet 1
+ Result = SDOperand(CurDAG->getTargetNode(X86::EXTRACT_SUBREG,
+ MVT::i8, Result, SRIdx), 0);
+ } else {
+ Result = CurDAG->getCopyFromReg(Chain, HiReg, NVT, InFlag);
+ Chain = Result.getValue(1);
+ InFlag = Result.getValue(2);
+ }
+ ReplaceUses(N.getValue(1), Result);
+#ifndef NDEBUG
+ DOUT << std::string(Indent-2, ' ') << "=> ";
+ DEBUG(Result.Val->dump(CurDAG));
+ DOUT << "\n";
+#endif
}
- ReplaceUses(N.getValue(0), Result);
if (foldedLoad)
ReplaceUses(N1.getValue(1), Chain);
#ifndef NDEBUG
- DOUT << std::string(Indent-2, ' ') << "=> ";
- DEBUG(Result.Val->dump(CurDAG));
- DOUT << "\n";
Indent -= 2;
#endif