mirror of
https://github.com/RPCSX/llvm.git
synced 2025-02-03 19:15:30 +00:00
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.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@40972 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
f2369f2042
commit
f7ef26e701
@ -221,3 +221,16 @@ we were to support medium or larger code models, we need to use the movabs
|
|||||||
instruction. We should probably introduce something like AbsoluteAddress to
|
instruction. We should probably introduce something like AbsoluteAddress to
|
||||||
distinguish it from GlobalAddress so the asm printer and JIT code emitter can
|
distinguish it from GlobalAddress so the asm printer and JIT code emitter can
|
||||||
do the right thing.
|
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).
|
||||||
|
|
||||||
|
@ -1159,7 +1159,21 @@ SDNode *X86DAGToDAGISel::Select(SDOperand N) {
|
|||||||
SDOperand(CurDAG->getTargetNode(Opc, MVT::Flag, N1, InFlag), 0);
|
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);
|
ReplaceUses(N.getValue(0), Result);
|
||||||
if (foldedLoad)
|
if (foldedLoad)
|
||||||
ReplaceUses(N1.getValue(1), Result.getValue(1));
|
ReplaceUses(N1.getValue(1), Result.getValue(1));
|
||||||
@ -1286,11 +1300,26 @@ SDNode *X86DAGToDAGISel::Select(SDOperand N) {
|
|||||||
SDOperand(CurDAG->getTargetNode(Opc, MVT::Flag, N1, InFlag), 0);
|
SDOperand(CurDAG->getTargetNode(Opc, MVT::Flag, N1, InFlag), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDOperand Result =
|
unsigned Reg = isDiv ? LoReg : HiReg;
|
||||||
CurDAG->getCopyFromReg(Chain, isDiv ? LoReg : HiReg, NVT, InFlag);
|
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);
|
ReplaceUses(N.getValue(0), Result);
|
||||||
if (foldedLoad)
|
if (foldedLoad)
|
||||||
ReplaceUses(N1.getValue(1), Result.getValue(1));
|
ReplaceUses(N1.getValue(1), Chain);
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
DOUT << std::string(Indent-2, ' ') << "=> ";
|
DOUT << std::string(Indent-2, ' ') << "=> ";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user