mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
X86: Conditional tail calls should not have isBarrier = 1
That confuses e.g. machine basic block placement, which then doesn't realize that control can fall through a block that ends with a conditional tail call. Instead, isBranch=1 should be set. Also, mark EFLAGS as used by these instructions. llvm-svn: 281281
This commit is contained in:
parent
cefa1ba100
commit
644e8a59f7
@ -239,14 +239,11 @@ let isCall = 1 in
|
|||||||
|
|
||||||
|
|
||||||
// Tail call stuff.
|
// Tail call stuff.
|
||||||
|
|
||||||
let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1,
|
let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1,
|
||||||
isCodeGenOnly = 1, SchedRW = [WriteJumpLd] in
|
isCodeGenOnly = 1, SchedRW = [WriteJumpLd] in
|
||||||
let Uses = [ESP] in {
|
let Uses = [ESP] in {
|
||||||
def TCRETURNdi : PseudoI<(outs),
|
def TCRETURNdi : PseudoI<(outs),
|
||||||
(ins i32imm_pcrel:$dst, i32imm:$offset), []>;
|
(ins i32imm_pcrel:$dst, i32imm:$offset), []>;
|
||||||
def TCRETURNdicc : PseudoI<(outs),
|
|
||||||
(ins i32imm_pcrel:$dst, i32imm:$offset, i32imm:$cond), []>;
|
|
||||||
def TCRETURNri : PseudoI<(outs),
|
def TCRETURNri : PseudoI<(outs),
|
||||||
(ins ptr_rc_tailcall:$dst, i32imm:$offset), []>;
|
(ins ptr_rc_tailcall:$dst, i32imm:$offset), []>;
|
||||||
let mayLoad = 1 in
|
let mayLoad = 1 in
|
||||||
@ -260,12 +257,6 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1,
|
|||||||
"jmp\t$dst",
|
"jmp\t$dst",
|
||||||
[], IIC_JMP_REL>;
|
[], IIC_JMP_REL>;
|
||||||
|
|
||||||
// This gets substituted to a conditional jump instruction in MC lowering.
|
|
||||||
def TAILJMPd_CC : Ii32PCRel<0x80, RawFrm, (outs),
|
|
||||||
(ins i32imm_pcrel:$dst, i32imm:$cond),
|
|
||||||
"",
|
|
||||||
[], IIC_JMP_REL>;
|
|
||||||
|
|
||||||
def TAILJMPr : I<0xFF, MRM4r, (outs), (ins ptr_rc_tailcall:$dst),
|
def TAILJMPr : I<0xFF, MRM4r, (outs), (ins ptr_rc_tailcall:$dst),
|
||||||
"", [], IIC_JMP_REG>; // FIXME: Remove encoding when JIT is dead.
|
"", [], IIC_JMP_REG>; // FIXME: Remove encoding when JIT is dead.
|
||||||
let mayLoad = 1 in
|
let mayLoad = 1 in
|
||||||
@ -273,6 +264,21 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1,
|
|||||||
"jmp{l}\t{*}$dst", [], IIC_JMP_MEM>;
|
"jmp{l}\t{*}$dst", [], IIC_JMP_MEM>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Conditional tail calls are similar to the above, but they are branches
|
||||||
|
// rather than barriers, and they use EFLAGS.
|
||||||
|
let isCall = 1, isTerminator = 1, isReturn = 1, isBranch = 1,
|
||||||
|
isCodeGenOnly = 1, SchedRW = [WriteJumpLd] in
|
||||||
|
let Uses = [ESP, EFLAGS] in {
|
||||||
|
def TCRETURNdicc : PseudoI<(outs),
|
||||||
|
(ins i32imm_pcrel:$dst, i32imm:$offset, i32imm:$cond), []>;
|
||||||
|
|
||||||
|
// This gets substituted to a conditional jump instruction in MC lowering.
|
||||||
|
def TAILJMPd_CC : Ii32PCRel<0x80, RawFrm, (outs),
|
||||||
|
(ins i32imm_pcrel:$dst, i32imm:$cond),
|
||||||
|
"",
|
||||||
|
[], IIC_JMP_REL>;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Call Instructions...
|
// Call Instructions...
|
||||||
@ -308,9 +314,6 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1,
|
|||||||
def TCRETURNdi64 : PseudoI<(outs),
|
def TCRETURNdi64 : PseudoI<(outs),
|
||||||
(ins i64i32imm_pcrel:$dst, i32imm:$offset),
|
(ins i64i32imm_pcrel:$dst, i32imm:$offset),
|
||||||
[]>;
|
[]>;
|
||||||
def TCRETURNdi64cc : PseudoI<(outs),
|
|
||||||
(ins i64i32imm_pcrel:$dst, i32imm:$offset,
|
|
||||||
i32imm:$cond), []>;
|
|
||||||
def TCRETURNri64 : PseudoI<(outs),
|
def TCRETURNri64 : PseudoI<(outs),
|
||||||
(ins ptr_rc_tailcall:$dst, i32imm:$offset), []>;
|
(ins ptr_rc_tailcall:$dst, i32imm:$offset), []>;
|
||||||
let mayLoad = 1 in
|
let mayLoad = 1 in
|
||||||
@ -320,12 +323,6 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1,
|
|||||||
def TAILJMPd64 : Ii32PCRel<0xE9, RawFrm, (outs), (ins i64i32imm_pcrel:$dst),
|
def TAILJMPd64 : Ii32PCRel<0xE9, RawFrm, (outs), (ins i64i32imm_pcrel:$dst),
|
||||||
"jmp\t$dst", [], IIC_JMP_REL>;
|
"jmp\t$dst", [], IIC_JMP_REL>;
|
||||||
|
|
||||||
// This gets substituted to a conditional jump instruction in MC lowering.
|
|
||||||
def TAILJMPd64_CC : Ii32PCRel<0x80, RawFrm, (outs),
|
|
||||||
(ins i64i32imm_pcrel:$dst, i32imm:$cond),
|
|
||||||
"",
|
|
||||||
[], IIC_JMP_REL>;
|
|
||||||
|
|
||||||
def TAILJMPr64 : I<0xFF, MRM4r, (outs), (ins ptr_rc_tailcall:$dst),
|
def TAILJMPr64 : I<0xFF, MRM4r, (outs), (ins ptr_rc_tailcall:$dst),
|
||||||
"jmp{q}\t{*}$dst", [], IIC_JMP_MEM>;
|
"jmp{q}\t{*}$dst", [], IIC_JMP_MEM>;
|
||||||
|
|
||||||
@ -343,3 +340,19 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1,
|
|||||||
"rex64 jmp{q}\t{*}$dst", [], IIC_JMP_MEM>;
|
"rex64 jmp{q}\t{*}$dst", [], IIC_JMP_MEM>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Conditional tail calls are similar to the above, but they are branches
|
||||||
|
// rather than barriers, and they use EFLAGS.
|
||||||
|
let isCall = 1, isTerminator = 1, isReturn = 1, isBranch = 1,
|
||||||
|
isCodeGenOnly = 1, SchedRW = [WriteJumpLd] in
|
||||||
|
let Uses = [RSP, EFLAGS] in {
|
||||||
|
def TCRETURNdi64cc : PseudoI<(outs),
|
||||||
|
(ins i64i32imm_pcrel:$dst, i32imm:$offset,
|
||||||
|
i32imm:$cond), []>;
|
||||||
|
|
||||||
|
// This gets substituted to a conditional jump instruction in MC lowering.
|
||||||
|
def TAILJMPd64_CC : Ii32PCRel<0x80, RawFrm, (outs),
|
||||||
|
(ins i64i32imm_pcrel:$dst, i32imm:$cond),
|
||||||
|
"",
|
||||||
|
[], IIC_JMP_REL>;
|
||||||
|
}
|
||||||
|
@ -14,12 +14,40 @@ bb1:
|
|||||||
bb2:
|
bb2:
|
||||||
tail call void @bar()
|
tail call void @bar()
|
||||||
ret void
|
ret void
|
||||||
}
|
|
||||||
|
|
||||||
; CHECK-LABEL: f:
|
; CHECK-LABEL: f:
|
||||||
; CHECK: cmp
|
; CHECK: cmp
|
||||||
; CHECK: jne bar
|
; CHECK: jne bar
|
||||||
; Check that the asm doesn't just look good, but uses the correct encoding.
|
; Check that the asm doesn't just look good, but uses the correct encoding.
|
||||||
; CHECK: encoding: [0x75,A]
|
; CHECK: encoding: [0x75,A]
|
||||||
|
|
||||||
; CHECK: jmp foo
|
; CHECK: jmp foo
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
declare x86_thiscallcc zeroext i1 @baz(i8*, i32)
|
||||||
|
define x86_thiscallcc zeroext i1 @BlockPlacementTest(i8* %this, i32 %x) optsize {
|
||||||
|
entry:
|
||||||
|
%and = and i32 %x, 42
|
||||||
|
%tobool = icmp eq i32 %and, 0
|
||||||
|
br i1 %tobool, label %land.end, label %land.rhs
|
||||||
|
|
||||||
|
land.rhs:
|
||||||
|
%and6 = and i32 %x, 44
|
||||||
|
%tobool7 = icmp eq i32 %and6, 0
|
||||||
|
br i1 %tobool7, label %lor.rhs, label %land.end
|
||||||
|
|
||||||
|
lor.rhs:
|
||||||
|
%call = tail call x86_thiscallcc zeroext i1 @baz(i8* %this, i32 %x) #2
|
||||||
|
br label %land.end
|
||||||
|
|
||||||
|
land.end:
|
||||||
|
%0 = phi i1 [ false, %entry ], [ true, %land.rhs ], [ %call, %lor.rhs ]
|
||||||
|
ret i1 %0
|
||||||
|
|
||||||
|
; Make sure machine block placement isn't confused by the conditional tail call,
|
||||||
|
; but sees that it can fall through to the next block.
|
||||||
|
; CHECK-LABEL: BlockPlacementTest
|
||||||
|
; CHECK: je baz
|
||||||
|
; CHECK-NOT: xor
|
||||||
|
; CHECK: ret
|
||||||
|
}
|
||||||
|
@ -47,7 +47,7 @@ body: |
|
|||||||
; CHECK-NEXT: %rdi = COPY %rsi
|
; CHECK-NEXT: %rdi = COPY %rsi
|
||||||
; CHECK-NEXT: %rsi = COPY %rax
|
; CHECK-NEXT: %rsi = COPY %rax
|
||||||
; CHECK-NEXT: CMP64ri8 %rax, 9, implicit-def %eflags
|
; CHECK-NEXT: CMP64ri8 %rax, 9, implicit-def %eflags
|
||||||
; CHECK-NEXT: TCRETURNdi64cc @f1, 0, 3, csr_64, implicit %rsp, implicit %rsp, implicit %rdi, implicit %rsi
|
; CHECK-NEXT: TCRETURNdi64cc @f1, 0, 3, csr_64, implicit %rsp, implicit %eflags, implicit %rsp, implicit %rdi, implicit %rsi
|
||||||
|
|
||||||
bb.1:
|
bb.1:
|
||||||
successors: %bb.2, %bb.3
|
successors: %bb.2, %bb.3
|
||||||
|
Loading…
x
Reference in New Issue
Block a user