forked from OSchip/llvm-project
[x86] Disambiguate RET[QL] and fix aliases for 16-bit mode
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. llvm-svn: 198756
This commit is contained in:
parent
c178fbe2a2
commit
79dd505ce1
|
@ -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;
|
||||
|
|
|
@ -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).
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -21,14 +21,17 @@
|
|||
// 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",
|
||||
|
|
|
@ -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">;
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue