[llvm] r199106 - [x86] Fix retq/retl handling in 64-bit mode

David Woodhouse dwmw2 at infradead.org
Mon Jan 13 06:06:00 PST 2014


Author: dwmw2
Date: Mon Jan 13 08:05:59 2014
New Revision: 199106

URL: http://llvm.org/viewvc/llvm-project?rev=199106&view=rev
Log:
[x86] Fix retq/retl handling in 64-bit mode

This finishes the job started in r198756, and creates separate opcodes for
64-bit vs. 32-bit versions of the rest of the RET instructions too.

LRETL/LRETQ are interesting... I can't see any justification for their
existence in the SDM. There should be no 'LRETL' in 64-bit mode, and no
need for a REX.W prefix for LRETQ. But this is what GAS does, and my
Sandybridge CPU and an Opteron 6376 concur when tested as follows:

asm __volatile__("pushq $0x1234\nmovq $0x33,%rax\nsalq $32,%rax\norq $1f,%rax\npushq %rax\nlretl $8\n1:");
asm __volatile__("pushq $1234\npushq $0x33\npushq $1f\nlretq $8\n1:");
asm __volatile__("pushq $0x33\npushq $1f\nlretq\n1:");
asm __volatile__("pushq $0x1234\npushq $0x33\npushq $1f\nlretq $8\n1:");

cf. PR8592 and commit r118903, which added LRETQ. I only added LRETIQ to
match it.

I don't quite understand how the Intel syntax parsing for ret
instructions is working, despite r154468 allegedly fixing it. Aren't the
explicitly sized 'retw', 'retd' and 'retq' supposed to work? I have at
least made the 'lretq' work with (and indeed *require*) the 'q'.

Added:
    llvm/trunk/test/MC/X86/ret.s
Modified:
    llvm/trunk/lib/Target/X86/X86FloatingPoint.cpp
    llvm/trunk/lib/Target/X86/X86FrameLowering.cpp
    llvm/trunk/lib/Target/X86/X86InstrControl.td
    llvm/trunk/lib/Target/X86/X86InstrFormats.td
    llvm/trunk/lib/Target/X86/X86InstrInfo.td

Modified: llvm/trunk/lib/Target/X86/X86FloatingPoint.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86FloatingPoint.cpp?rev=199106&r1=199105&r2=199106&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86FloatingPoint.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86FloatingPoint.cpp Mon Jan 13 08:05:59 2014
@@ -1673,7 +1673,8 @@ void FPS::handleSpecialFP(MachineBasicBl
 
   case X86::RETQ:
   case X86::RETL:
-  case X86::RETI:
+  case X86::RETIL:
+  case X86::RETIQ:
     // If RET has an FP register use operand, pass the first one in ST(0) and
     // the second one in ST(1).
 

Modified: llvm/trunk/lib/Target/X86/X86FrameLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86FrameLowering.cpp?rev=199106&r1=199105&r2=199106&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86FrameLowering.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86FrameLowering.cpp Mon Jan 13 08:05:59 2014
@@ -109,7 +109,8 @@ static unsigned findDeadCallerSavedReg(M
   default: return 0;
   case X86::RETL:
   case X86::RETQ:
-  case X86::RETI:
+  case X86::RETIL:
+  case X86::RETIQ:
   case X86::TCRETURNdi:
   case X86::TCRETURNri:
   case X86::TCRETURNmi:
@@ -731,7 +732,8 @@ void X86FrameLowering::emitEpilogue(Mach
     llvm_unreachable("Can only insert epilog into returning blocks");
   case X86::RETQ:
   case X86::RETL:
-  case X86::RETI:
+  case X86::RETIL:
+  case X86::RETIQ:
   case X86::TCRETURNdi:
   case X86::TCRETURNri:
   case X86::TCRETURNmi:
@@ -888,8 +890,9 @@ void X86FrameLowering::emitEpilogue(Mach
 
     // Delete the pseudo instruction TCRETURN.
     MBB.erase(MBBI);
-  } else if ((RetOpcode == X86::RETQ || RetOpcode == X86::RETI ||
-              RetOpcode == X86::RETL) && (X86FI->getTCReturnAddrDelta() < 0)) {
+  } else if ((RetOpcode == X86::RETQ || RetOpcode == X86::RETL ||
+              RetOpcode == X86::RETIQ || RetOpcode == X86::RETIL) &&
+             (X86FI->getTCReturnAddrDelta() < 0)) {
     // Add the return addr area delta back since we are not tail calling.
     int delta = -1*X86FI->getTCReturnAddrDelta();
     MBBI = MBB.getLastNonDebugInstr();

Modified: llvm/trunk/lib/Target/X86/X86InstrControl.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrControl.td?rev=199106&r1=199105&r2=199106&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86InstrControl.td (original)
+++ llvm/trunk/lib/Target/X86/X86InstrControl.td Mon Jan 13 08:05:59 2014
@@ -30,20 +30,27 @@ let isTerminator = 1, isReturn = 1, isBa
   def RETW   : I   <0xC3, RawFrm, (outs), (ins),
                     "ret{w}",
                     [], IIC_RET>, OpSize;
-  def RETI   : Ii16<0xC2, RawFrm, (outs), (ins i16imm:$amt, variable_ops),
+  def RETIL  : Ii16<0xC2, RawFrm, (outs), (ins i16imm:$amt, variable_ops),
                     "ret{l}\t$amt",
-                    [(X86retflag timm:$amt)], IIC_RET_IMM>, OpSize16;
+                    [(X86retflag timm:$amt)], IIC_RET_IMM>, OpSize16,
+               Requires<[Not64BitMode]>;
+  def RETIQ  : Ii16<0xC2, RawFrm, (outs), (ins i16imm:$amt, variable_ops),
+                    "ret{q}\t$amt",
+                    [(X86retflag timm:$amt)], IIC_RET_IMM>,
+               Requires<[In64BitMode]>;
   def RETIW  : Ii16<0xC2, RawFrm, (outs), (ins i16imm:$amt),
                     "ret{w}\t$amt",
                     [], IIC_RET_IMM>, OpSize;
   def LRETL  : I   <0xCB, RawFrm, (outs), (ins),
                     "{l}ret{l|f}", [], IIC_RET>, OpSize16;
+  def LRETQ  : RI  <0xCB, RawFrm, (outs), (ins),
+                    "{l}ret{|f}q", [], IIC_RET>, Requires<[In64BitMode]>;
   def LRETW  : I   <0xCB, RawFrm, (outs), (ins),
                     "{l}ret{w|f}", [], IIC_RET>, OpSize;
-  def LRETQ  : RI  <0xCB, RawFrm, (outs), (ins),
-                    "{l}ret{q|f}", [], IIC_RET>;
-  def LRETI  : Ii16<0xCA, RawFrm, (outs), (ins i16imm:$amt),
+  def LRETIL : Ii16<0xCA, RawFrm, (outs), (ins i16imm:$amt),
                     "{l}ret{l|f}\t$amt", [], IIC_RET>, OpSize16;
+  def LRETIQ : RIi16<0xCA, RawFrm, (outs), (ins i16imm:$amt),
+                    "{l}ret{|f}q\t$amt", [], IIC_RET>, Requires<[In64BitMode]>;
   def LRETIW : Ii16<0xCA, RawFrm, (outs), (ins i16imm:$amt),
                     "{l}ret{w|f}\t$amt", [], IIC_RET>, OpSize;
 }

Modified: llvm/trunk/lib/Target/X86/X86InstrFormats.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrFormats.td?rev=199106&r1=199105&r2=199106&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86InstrFormats.td (original)
+++ llvm/trunk/lib/Target/X86/X86InstrFormats.td Mon Jan 13 08:05:59 2014
@@ -736,6 +736,9 @@ class RI<bits<8> o, Format F, dag outs,
 class RIi8 <bits<8> o, Format F, dag outs, dag ins, string asm,
             list<dag> pattern, InstrItinClass itin = NoItinerary>
       : Ii8<o, F, outs, ins, asm, pattern, itin>, REX_W;
+class RIi16 <bits<8> o, Format F, dag outs, dag ins, string asm,
+            list<dag> pattern, InstrItinClass itin = NoItinerary>
+      : Ii16<o, F, outs, ins, asm, pattern, itin>, REX_W;
 class RIi32 <bits<8> o, Format F, dag outs, dag ins, string asm,
              list<dag> pattern, InstrItinClass itin = NoItinerary>
       : Ii32<o, F, outs, ins, asm, pattern, itin>, REX_W;

Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.td?rev=199106&r1=199105&r2=199106&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86InstrInfo.td (original)
+++ llvm/trunk/lib/Target/X86/X86InstrInfo.td Mon Jan 13 08:05:59 2014
@@ -2162,7 +2162,7 @@ def : MnemonicAlias<"cdq",  "cltd", "att
 def : MnemonicAlias<"cdqe", "cltq", "att">;
 def : MnemonicAlias<"cqo",  "cqto", "att">;
 
-// lret maps to lretl, it is not ambiguous with lretq.
+// In 64-bit mode lret maps to lretl; it is not ambiguous with lretq.
 def : MnemonicAlias<"lret", "lretw", "att">, Requires<[In16BitMode]>;
 def : MnemonicAlias<"lret", "lretl", "att">, Requires<[Not16BitMode]>;
 

Added: llvm/trunk/test/MC/X86/ret.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/X86/ret.s?rev=199106&view=auto
==============================================================================
--- llvm/trunk/test/MC/X86/ret.s (added)
+++ llvm/trunk/test/MC/X86/ret.s Mon Jan 13 08:05:59 2014
@@ -0,0 +1,85 @@
+// RUN: not llvm-mc -triple x86_64-unknown-unknown --show-encoding %s 2> %t.err | FileCheck --check-prefix=64 %s
+// RUN: FileCheck --check-prefix=ERR64 < %t.err %s
+// RUN: not llvm-mc -triple i386-unknown-unknown --show-encoding %s 2> %t.err | FileCheck --check-prefix=32 %s
+// RUN: FileCheck --check-prefix=ERR32 < %t.err %s
+
+
+	ret
+// 64: retq
+// 64: encoding: [0xc3]
+// 32: retl
+// 32: encoding: [0xc3]
+	retw
+// 64: retw
+// 64: encoding: [0x66,0xc3]
+// 32: retw
+// 32: encoding: [0x66,0xc3]
+	retl
+// ERR64: error: instruction requires: Not 64-bit mode
+// 32: retl
+// 32: encoding: [0xc3]
+	retq
+// 64: retq
+// 64: encoding: [0xc3]
+// ERR32: error: instruction requires: 64-bit mode
+
+	ret $0
+// 64: retq $0
+// 64: encoding: [0xc2,0x00,0x00]
+// 32: retl $0
+// 32: encoding: [0xc2,0x00,0x00]
+	retw $0
+// 64: retw $0
+// 64: encoding: [0x66,0xc2,0x00,0x00]
+// 32: retw $0
+// 32: encoding: [0x66,0xc2,0x00,0x00]
+	retl $0
+// ERR64: error: instruction requires: Not 64-bit mode
+// 32: retl $0
+// 32: encoding: [0xc2,0x00,0x00]
+	retq $0
+// 64: retq $0
+// 64: encoding: [0xc2,0x00,0x00]
+// ERR32: error: instruction requires: 64-bit mode
+
+	lret
+// 64: lretl
+// 64: encoding: [0xcb]
+// 32: lretl
+// 32: encoding: [0xcb]
+	lretw
+// 64: lretw
+// 64: encoding: [0x66,0xcb]
+// 32: lretw
+// 32: encoding: [0x66,0xcb]
+	lretl
+// 64: lretl
+// 64: encoding: [0xcb]
+// 32: lretl
+// 32: encoding: [0xcb]
+	lretq
+// 64: lretq
+// 64: encoding: [0x48,0xcb]
+// ERR32: error: instruction requires: 64-bit mode
+
+	lret $0
+// 64: lretl $0
+// 64: encoding: [0xca,0x00,0x00]
+// 32: lretl $0
+// 32: encoding: [0xca,0x00,0x00]
+	lretw $0
+// 64: lretw $0
+// 64: encoding: [0x66,0xca,0x00,0x00]
+// 32: lretw $0
+// 32: encoding: [0x66,0xca,0x00,0x00]
+	lretl $0
+// 64: lretl $0
+// 64: encoding: [0xca,0x00,0x00]
+// 32: lretl $0
+// 32: encoding: [0xca,0x00,0x00]
+	lretq $0
+// 64: lretq $0
+// 64: encoding: [0x48,0xca,0x00,0x00]
+// ERR32: error: instruction requires: 64-bit mode
+
+





More information about the llvm-commits mailing list