[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