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, ' ') << "=> "; _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits