[llvm-commits] [llvm] r40972 - in /llvm/trunk/lib/Target/X86: README-X86-64.txt X86ISelDAGToDAG.cpp
Evan Cheng
evan.cheng at apple.com
Thu Aug 9 14:59:37 PDT 2007
Author: evancheng
Date: Thu Aug 9 16:59:35 2007
New Revision: 40972
URL: http://llvm.org/viewvc/llvm-project?rev=40972&view=rev
Log:
divb / mulb outputs to ah. Under x86-64 it's not legal to read ah if the instruction requires a rex prefix (i.e. outputs to r8b, etc.). So issue shift right by 8 on AX and then truncate it to 8 bits instead.
Modified:
llvm/trunk/lib/Target/X86/README-X86-64.txt
llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp
Modified: llvm/trunk/lib/Target/X86/README-X86-64.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/README-X86-64.txt?rev=40972&r1=40971&r2=40972&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/README-X86-64.txt (original)
+++ llvm/trunk/lib/Target/X86/README-X86-64.txt Thu Aug 9 16:59:35 2007
@@ -221,3 +221,16 @@
instruction. We should probably introduce something like AbsoluteAddress to
distinguish it from GlobalAddress so the asm printer and JIT code emitter can
do the right thing.
+
+//===---------------------------------------------------------------------===//
+
+It's not possible to reference AH, BH, CH, and DH registers in an instruction
+requiring REX prefix. However, divb and mulb both produce results in AH. If isel
+emits a CopyFromReg which gets turned into a movb and that can be allocated a
+r8b - r15b.
+
+To get around this, isel emits a CopyFromReg from AX and then right shift it
+down by 8 and truncate it. It's not pretty but it works. We need some register
+allocation magic to make the hack go away (e.g. putting additional constraints
+on the result of the movb).
+
Modified: llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp?rev=40972&r1=40971&r2=40972&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp Thu Aug 9 16:59:35 2007
@@ -1159,7 +1159,21 @@
SDOperand(CurDAG->getTargetNode(Opc, MVT::Flag, N1, InFlag), 0);
}
- SDOperand Result = CurDAG->getCopyFromReg(Chain, HiReg, NVT, InFlag);
+ 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);
+ 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);
+ }
ReplaceUses(N.getValue(0), Result);
if (foldedLoad)
ReplaceUses(N1.getValue(1), Result.getValue(1));
@@ -1286,11 +1300,26 @@
SDOperand(CurDAG->getTargetNode(Opc, MVT::Flag, N1, InFlag), 0);
}
- SDOperand Result =
- CurDAG->getCopyFromReg(Chain, isDiv ? LoReg : HiReg, NVT, InFlag);
+ 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);
+ Chain = Result.getValue(1);
+ }
ReplaceUses(N.getValue(0), Result);
if (foldedLoad)
- ReplaceUses(N1.getValue(1), Result.getValue(1));
+ ReplaceUses(N1.getValue(1), Chain);
#ifndef NDEBUG
DOUT << std::string(Indent-2, ' ') << "=> ";
More information about the llvm-commits
mailing list