[x86] Disambiguate RET[QL] and fix aliases for 16-bit mode
authorDavid Woodhouse <dwmw2@infradead.org>
Wed, 8 Jan 2014 12:58:07 +0000 (12:58 +0000)
committerDavid Woodhouse <dwmw2@infradead.org>
Wed, 8 Jan 2014 12:58:07 +0000 (12:58 +0000)
I couldn't see how to do this sanely without splitting RETQ from RETL.

Eric says: "sad about the inability to roundtrip them now, but...".
I have no idea what that means, but perhaps it wants preserving in the
commit comment.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198756 91177308-0d34-0410-b5e6-96231b3b80d8

13 files changed:
lib/Target/X86/X86FastISel.cpp
lib/Target/X86/X86FloatingPoint.cpp
lib/Target/X86/X86FrameLowering.cpp
lib/Target/X86/X86InstrControl.td
lib/Target/X86/X86InstrInfo.td
lib/Target/X86/X86MCInstLower.cpp
test/CodeGen/X86/2008-08-31-EH_RETURN64.ll
test/CodeGen/X86/fast-isel-x86.ll
test/CodeGen/X86/sibcall.ll
test/CodeGen/X86/stdcall-notailcall.ll
test/CodeGen/X86/stdcall.ll
test/CodeGen/X86/win32_sret.ll
test/MC/X86/x86-16.s

index 7be2a14a44f229871031a46b0c7f0cd5cae88bdc..fd10a4a09eab0a29d8bcbe69920877ada36aeb49 100644 (file)
@@ -888,7 +888,7 @@ bool X86FastISel::X86SelectRet(const Instruction *I) {
 
   // Now emit the RET.
   MachineInstrBuilder MIB =
-    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(X86::RET));
+    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(Subtarget->is64Bit() ? X86::RETQ : X86::RETL));
   for (unsigned i = 0, e = RetRegs.size(); i != e; ++i)
     MIB.addReg(RetRegs[i], RegState::Implicit);
   return true;
index 48470da0164ab275d139641fb3bce30418493427..d6d0bbc1b5b9f107a0d8001815271c4af1a04092 100644 (file)
@@ -1671,7 +1671,8 @@ void FPS::handleSpecialFP(MachineBasicBlock::iterator &I) {
     break;
   }
 
-  case X86::RET:
+  case X86::RETQ:
+  case X86::RETL:
   case X86::RETI:
     // If RET has an FP register use operand, pass the first one in ST(0) and
     // the second one in ST(1).
index 0c5209cf3eed9c4f3ea48f6fbf50cd38de462d1b..5a92e7e0141ba0f6ed85f6d697702bc7f12f07b0 100644 (file)
@@ -107,7 +107,8 @@ static unsigned findDeadCallerSavedReg(MachineBasicBlock &MBB,
   unsigned Opc = MBBI->getOpcode();
   switch (Opc) {
   default: return 0;
-  case X86::RET:
+  case X86::RETL:
+  case X86::RETQ:
   case X86::RETI:
   case X86::TCRETURNdi:
   case X86::TCRETURNri:
@@ -728,7 +729,8 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF,
   switch (RetOpcode) {
   default:
     llvm_unreachable("Can only insert epilog into returning blocks");
-  case X86::RET:
+  case X86::RETQ:
+  case X86::RETL:
   case X86::RETI:
   case X86::TCRETURNdi:
   case X86::TCRETURNri:
@@ -886,8 +888,8 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF,
 
     // Delete the pseudo instruction TCRETURN.
     MBB.erase(MBBI);
-  } else if ((RetOpcode == X86::RET || RetOpcode == X86::RETI) &&
-             (X86FI->getTCReturnAddrDelta() < 0)) {
+  } else if ((RetOpcode == X86::RETQ || RetOpcode == X86::RETI ||
+              RetOpcode == X86::RETL) && (X86FI->getTCReturnAddrDelta() < 0)) {
     // Add the return addr area delta back since we are not tail calling.
     int delta = -1*X86FI->getTCReturnAddrDelta();
     MBBI = MBB.getLastNonDebugInstr();
index 4191d3fd856583a5616789d5bc261a1504a99015..1e420f8be9a9a0b3ab60915d3e534fc7f5ec9e7d 100644 (file)
 // ST1 arguments when returning values on the x87 stack.
 let isTerminator = 1, isReturn = 1, isBarrier = 1,
     hasCtrlDep = 1, FPForm = SpecialFP, SchedRW = [WriteJumpLd] in {
-  def RET    : I   <0xC3, RawFrm, (outs), (ins variable_ops),
-                    "ret",
-                    [(X86retflag 0)], IIC_RET>, OpSize16;
+  def RETL   : I   <0xC3, RawFrm, (outs), (ins variable_ops),
+                    "ret{l}",
+                    [(X86retflag 0)], IIC_RET>, OpSize16, Requires<[Not64BitMode]>;
+  def RETQ   : I   <0xC3, RawFrm, (outs), (ins variable_ops),
+                    "ret{q}",
+                    [(X86retflag 0)], IIC_RET>, Requires<[In64BitMode]>;
   def RETW   : I   <0xC3, RawFrm, (outs), (ins),
                     "ret{w}",
                     [], IIC_RET>, OpSize;
   def RETI   : Ii16<0xC2, RawFrm, (outs), (ins i16imm:$amt, variable_ops),
-                    "ret\t$amt",
+                    "ret{l}\t$amt",
                     [(X86retflag timm:$amt)], IIC_RET_IMM>, OpSize16;
   def RETIW  : Ii16<0xC2, RawFrm, (outs), (ins i16imm:$amt),
                     "ret{w}\t$amt",
index b040ee26c8a9895fbea06ad8881a17ec8dfac82b..130ead8db30684a16223aeea0fd30eb0df9534c1 100644 (file)
@@ -2140,7 +2140,8 @@ def : MnemonicAlias<"cdqe", "cltq", "att">;
 def : MnemonicAlias<"cqo",  "cqto", "att">;
 
 // lret maps to lretl, it is not ambiguous with lretq.
-def : MnemonicAlias<"lret", "lretl", "att">;
+def : MnemonicAlias<"lret", "lretw", "att">, Requires<[In16BitMode]>;
+def : MnemonicAlias<"lret", "lretl", "att">, Requires<[Not16BitMode]>;
 
 def : MnemonicAlias<"leavel", "leave", "att">, Requires<[Not64BitMode]>;
 def : MnemonicAlias<"leaveq", "leave", "att">, Requires<[In64BitMode]>;
@@ -2183,8 +2184,9 @@ def : MnemonicAlias<"repe",  "rep",   "att">;
 def : MnemonicAlias<"repz",  "rep",   "att">;
 def : MnemonicAlias<"repnz", "repne", "att">;
 
-def : MnemonicAlias<"retl", "ret", "att">, Requires<[Not64BitMode]>;
-def : MnemonicAlias<"retq", "ret", "att">, Requires<[In64BitMode]>;
+def : MnemonicAlias<"ret", "retw", "att">, Requires<[In16BitMode]>;
+def : MnemonicAlias<"ret", "retl", "att">, Requires<[In32BitMode]>;
+def : MnemonicAlias<"ret", "retq", "att">, Requires<[In64BitMode]>;
 
 def : MnemonicAlias<"salb", "shlb", "att">;
 def : MnemonicAlias<"salw", "shlw", "att">;
@@ -2200,7 +2202,8 @@ def : MnemonicAlias<"ud2a",  "ud2",  "att">;
 def : MnemonicAlias<"verrw", "verr", "att">;
 
 // System instruction aliases.
-def : MnemonicAlias<"iret",    "iretl",    "att">;
+def : MnemonicAlias<"iret",    "iretw",    "att">, Requires<[In16BitMode]>;
+def : MnemonicAlias<"iret",    "iretl",    "att">, Requires<[Not16BitMode]>;
 def : MnemonicAlias<"sysret",  "sysretl",  "att">;
 def : MnemonicAlias<"sysexit", "sysexitl", "att">;
 
index a6200103e4574dd96f10f5d1b9aea86b800c9d55..8b4195f0ee050636f833d84c1a2269976fe2c0f4 100644 (file)
@@ -334,6 +334,11 @@ static void SimplifyShortMoveForm(X86AsmPrinter &Printer, MCInst &Inst,
   Inst.addOperand(Saved);
 }
 
+static unsigned getRetOpcode(const X86Subtarget &Subtarget)
+{
+       return Subtarget.is64Bit() ? X86::RETQ : X86::RETL;
+}
+
 void X86MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
   OutMI.setOpcode(MI->getOpcode());
 
@@ -462,7 +467,7 @@ ReSimplify:
   case X86::EH_RETURN:
   case X86::EH_RETURN64: {
     OutMI = MCInst();
-    OutMI.setOpcode(X86::RET);
+    OutMI.setOpcode(getRetOpcode(AsmPrinter.getSubtarget()));
     break;
   }
 
@@ -866,12 +871,12 @@ void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) {
     return LowerPATCHPOINT(OutStreamer, SM, *MI, Subtarget->is64Bit());
 
   case X86::MORESTACK_RET:
-    OutStreamer.EmitInstruction(MCInstBuilder(X86::RET));
+    OutStreamer.EmitInstruction(MCInstBuilder(getRetOpcode(*Subtarget)));
     return;
 
   case X86::MORESTACK_RET_RESTORE_R10:
     // Return, then restore R10.
-    OutStreamer.EmitInstruction(MCInstBuilder(X86::RET));
+    OutStreamer.EmitInstruction(MCInstBuilder(getRetOpcode(*Subtarget)));
     OutStreamer.EmitInstruction(MCInstBuilder(X86::MOV64rr)
       .addReg(X86::R10)
       .addReg(X86::RAX));
index 496779c468f42cb7c4e3e598cebe0a9b17f25e12..51064f1d2173dd12217c2ff4977f0b902e831a7d 100644 (file)
@@ -9,7 +9,7 @@ target triple = "x86_64-unknown-linux-gnu"
 ; CHECK: movq %rsp, %rbp
 ; CHECK: popq %rbp
 ; CHECK: movq %rcx, %rsp
-; CHECK: ret # eh_return, addr: %rcx
+; CHECK: retq # eh_return, addr: %rcx
 define i8* @test(i64 %a, i8* %b)  {
 entry:
   call void @llvm.eh.unwind.init()
index ba86e888cdde712e86fcd0502773b1ea4204672a..a212a7c6876ea3ed09b91eee42eb541ea6838f5c 100644 (file)
@@ -3,7 +3,7 @@
 ; This should use flds to set the return value.
 ; CHECK-LABEL: test0:
 ; CHECK: flds
-; CHECK: ret
+; CHECK: retl
 @G = external global float
 define float @test0() nounwind {
   %t = load float* @G
@@ -12,7 +12,7 @@ define float @test0() nounwind {
 
 ; This should pop 4 bytes on return.
 ; CHECK-LABEL: test1:
-; CHECK: ret $4
+; CHECK: retl $4
 define void @test1({i32, i32, i32, i32}* sret %p) nounwind {
   store {i32, i32, i32, i32} zeroinitializer, {i32, i32, i32, i32}* %p
   ret void
@@ -25,7 +25,7 @@ define void @test1({i32, i32, i32, i32}* sret %p) nounwind {
 ; CHECK-NEXT: L2$pb:
 ; CHECK-NEXT: pop
 ; CHECK: HHH
-; CHECK: ret
+; CHECK: retl
 @HHH = external global i32
 define i32 @test2() nounwind {
   %t = load i32* @HHH
index 589e9ec10524c70281ab6d66959867e9da7c7f6d..28fc626afd9d6de0d16fd330867c47e7c726ccc0 100644 (file)
@@ -247,11 +247,11 @@ entry:
 define void @t15(%struct.foo* noalias sret %agg.result) nounwind  {
 ; 32-LABEL: t15:
 ; 32: calll {{_?}}f
-; 32: ret $4
+; 32: retl $4
 
 ; 64-LABEL: t15:
 ; 64: callq {{_?}}f
-; 64: ret
+; 64: retq
   tail call fastcc void @f(%struct.foo* noalias sret %agg.result) nounwind
   ret void
 }
index c847ec7b6c0864710a6e30093ef7824b66481851..448db4cda17f19e9619da35761e3144a61c450aa 100644 (file)
@@ -4,7 +4,7 @@
 define x86_stdcallcc void @bar(%struct.I* nocapture %this) ssp align 2 {
 ; CHECK-LABEL: bar:
 ; CHECK-NOT: jmp
-; CHECK: ret $4
+; CHECK: retl $4
 entry:
   tail call void @foo()
   ret void
@@ -13,7 +13,7 @@ entry:
 define x86_thiscallcc void @test2(%struct.I*  %this, i32 %a) {
 ; CHECK-LABEL: test2:
 ; CHECK: calll _foo
-; CHECK: ret $4
+; CHECK: retl $4
   tail call void @foo()
   ret void
 }
index 73826ed0b29dc794920daa6b88d991dcf1c008bd..3cefe14fe0d57095c2cb112a95f75ae4e3819582 100644 (file)
@@ -6,14 +6,14 @@
 define internal x86_stdcallcc void @MyFunc() nounwind {
 entry:
 ; CHECK: MyFunc@0:
-; CHECK: ret
+; CHECK: retl
   ret void
 }
 
 ; PR14410
 define x86_stdcallcc i32 @"\01DoNotMangle"(i32 %a) {
 ; CHECK: DoNotMangle:
-; CHECK: ret $4
+; CHECK: retl $4
 entry:
   ret i32 %a
 }
index 78f1821b1d4a28cdb5f6fa806123654fea6b0679..d8ecd44d1192d8ba74ada600ccb4f1396e567cbd 100644 (file)
@@ -16,13 +16,13 @@ entry:
 ; WIN32-LABEL:      _sret1:
 ; WIN32:      movb $42, (%eax)
 ; WIN32-NOT:  popl %eax
-; WIN32:    {{ret$}}
+; WIN32:    {{retl$}}
 
 ; MINGW_X86-LABEL:  _sret1:
-; MINGW_X86:  {{ret$}}
+; MINGW_X86:  {{retl$}}
 
 ; LINUX-LABEL:      sret1:
-; LINUX:      ret $4
+; LINUX:      retl $4
 
   store i8 42, i8* %x, align 4
   ret void
@@ -33,13 +33,13 @@ entry:
 ; WIN32-LABEL:      _sret2:
 ; WIN32:      movb {{.*}}, (%eax)
 ; WIN32-NOT:  popl %eax
-; WIN32:    {{ret$}}
+; WIN32:    {{retl$}}
 
 ; MINGW_X86-LABEL:  _sret2:
-; MINGW_X86:  {{ret$}}
+; MINGW_X86:  {{retl$}}
 
 ; LINUX-LABEL:      sret2:
-; LINUX:      ret $4
+; LINUX:      retl $4
 
   store i8 %y, i8* %x
   ret void
@@ -51,13 +51,13 @@ entry:
 ; WIN32:      movb $42, (%eax)
 ; WIN32-NOT:  movb $13, (%eax)
 ; WIN32-NOT:  popl %eax
-; WIN32:    {{ret$}}
+; WIN32:    {{retl$}}
 
 ; MINGW_X86-LABEL:  _sret3:
-; MINGW_X86:  {{ret$}}
+; MINGW_X86:  {{retl$}}
 
 ; LINUX-LABEL:      sret3:
-; LINUX:      ret $4
+; LINUX:      retl $4
 
   store i8 42, i8* %x
   store i8 13, i8* %y
@@ -72,13 +72,13 @@ entry:
 ; WIN32-LABEL:     _sret4:
 ; WIN32:     movl $42, (%eax)
 ; WIN32-NOT: popl %eax
-; WIN32:   {{ret$}}
+; WIN32:   {{retl$}}
 
 ; MINGW_X86-LABEL: _sret4:
-; MINGW_X86: {{ret$}}
+; MINGW_X86: {{retl$}}
 
 ; LINUX-LABEL:     sret4:
-; LINUX:     ret $4
+; LINUX:     retl $4
 
   %x = getelementptr inbounds %struct.S4* %agg.result, i32 0, i32 0
   store i32 42, i32* %x, align 4
@@ -105,7 +105,7 @@ entry:
 ; should match both 4(%esp) and 8(%esp).
 ; WIN32:     {{[48]}}(%esp), %eax
 ; WIN32:     movl $42, (%eax)
-; WIN32:     ret $4
+; WIN32:     retl $4
 }
 
 define void @call_foo5() {
@@ -126,7 +126,7 @@ entry:
 ; The this pointer goes to ECX.
 ; WIN32-NEXT: leal {{[0-9]+}}(%esp), %ecx
 ; WIN32-NEXT: calll "?foo@C5@@QAE?AUS5@@XZ"
-; WIN32:      ret
+; WIN32:      retl
   ret void
 }
 
index bb1aa4a207fccfddbd720d9476abf71ae8aa6a7b..9fdd8645e7add516e1adc570050508fb6efc5558 100644 (file)
@@ -71,6 +71,10 @@ int $255
 // CHECK: popfl                # encoding: [0x66,0x9d]
         popfl
 
+retl
+// CHECK: ret
+// CHECK:  encoding: [0x66,0xc3]
+
 // CHECK: cmoval       %eax, %edx
 // CHECK:  encoding: [0x66,0x0f,0x47,0xd0]
                cmoval  %eax,%edx
@@ -352,6 +356,16 @@ cmovnae    %bx,%bx
 lcalll $0x2, $0x1234
 
 
+iret
+// CHECK: iretw
+// CHECK: encoding: [0xcf]
+iretw
+// CHECK: iretw
+// CHECK: encoding: [0xcf]
+iretl
+// CHECK: iretl
+// CHECK: encoding: [0x66,0xcf]
+
 sysret
 // CHECK: sysretl
 // CHECK: encoding: [0x0f,0x07]
@@ -567,6 +581,30 @@ pshufw $90, %mm4, %mm0
 // CHECK:  encoding: [0x2f]
                das
 
+// CHECK: retw $31438
+// CHECK:  encoding: [0xc2,0xce,0x7a]
+               retw    $0x7ace
+
+// CHECK: lretw        $31438
+// CHECK:  encoding: [0xca,0xce,0x7a]
+               lretw   $0x7ace
+
+// CHECK: retw $31438
+// CHECK:  encoding: [0xc2,0xce,0x7a]
+               ret     $0x7ace
+
+// CHECK: lretw        $31438
+// CHECK:  encoding: [0xca,0xce,0x7a]
+               lret    $0x7ace
+
+// CHECK: retl $31438
+// CHECK:  encoding: [0x66,0xc2,0xce,0x7a]
+               retl    $0x7ace
+
+// CHECK: lretl        $31438
+// CHECK:  encoding: [0x66,0xca,0xce,0x7a]
+               lretl   $0x7ace
+
 // CHECK: bound        2(%eax), %bx
 // CHECK:  encoding: [0x67,0x62,0x58,0x02]
                bound   2(%eax),%bx
@@ -825,3 +863,19 @@ xchgl %ecx, %eax
 // CHECK: xchgl %ecx, %eax
 // CHECK: encoding: [0x66,0x91]
 xchgl %eax, %ecx
+
+// CHECK: retw
+// CHECK: encoding: [0xc3]
+retw
+
+// CHECK: retl
+// CHECK: encoding: [0x66,0xc3]
+retl
+
+// CHECK: lretw
+// CHECK: encoding: [0xcb]
+lretw
+
+// CHECK: lretl
+// CHECK: encoding: [0x66,0xcb]
+lretl