From 8a42d4b9cc038744eeb3f3276a6ecb36a32018c0 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 13 Sep 2016 00:21:32 +0000 Subject: [PATCH] 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 --- llvm/lib/Target/X86/X86InstrControl.td | 49 ++++++++++++++++--------- llvm/test/CodeGen/X86/conditional-tailcall.ll | 32 +++++++++++++++- llvm/test/CodeGen/X86/tail-call-conditional.mir | 2 +- 3 files changed, 62 insertions(+), 21 deletions(-) diff --git a/llvm/lib/Target/X86/X86InstrControl.td b/llvm/lib/Target/X86/X86InstrControl.td index f2ca000..4ea223e 100644 --- a/llvm/lib/Target/X86/X86InstrControl.td +++ b/llvm/lib/Target/X86/X86InstrControl.td @@ -239,14 +239,11 @@ let isCall = 1 in // Tail call stuff. - let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, isCodeGenOnly = 1, SchedRW = [WriteJumpLd] in let Uses = [ESP] in { def TCRETURNdi : PseudoI<(outs), (ins i32imm_pcrel:$dst, i32imm:$offset), []>; - def TCRETURNdicc : PseudoI<(outs), - (ins i32imm_pcrel:$dst, i32imm:$offset, i32imm:$cond), []>; def TCRETURNri : PseudoI<(outs), (ins ptr_rc_tailcall:$dst, i32imm:$offset), []>; let mayLoad = 1 in @@ -260,12 +257,6 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, "jmp\t$dst", [], 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), "", [], IIC_JMP_REG>; // FIXME: Remove encoding when JIT is dead. let mayLoad = 1 in @@ -273,6 +264,21 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, "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... @@ -308,9 +314,6 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, def TCRETURNdi64 : PseudoI<(outs), (ins i64i32imm_pcrel:$dst, i32imm:$offset), []>; - def TCRETURNdi64cc : PseudoI<(outs), - (ins i64i32imm_pcrel:$dst, i32imm:$offset, - i32imm:$cond), []>; def TCRETURNri64 : PseudoI<(outs), (ins ptr_rc_tailcall:$dst, i32imm:$offset), []>; 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), "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), "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>; } } + +// 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>; +} diff --git a/llvm/test/CodeGen/X86/conditional-tailcall.ll b/llvm/test/CodeGen/X86/conditional-tailcall.ll index 5dfdfd4..502643d 100644 --- a/llvm/test/CodeGen/X86/conditional-tailcall.ll +++ b/llvm/test/CodeGen/X86/conditional-tailcall.ll @@ -14,12 +14,40 @@ bb1: bb2: tail call void @bar() ret void -} ; CHECK-LABEL: f: ; CHECK: cmp ; CHECK: jne bar ; Check that the asm doesn't just look good, but uses the correct encoding. ; CHECK: encoding: [0x75,A] - ; 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 +} diff --git a/llvm/test/CodeGen/X86/tail-call-conditional.mir b/llvm/test/CodeGen/X86/tail-call-conditional.mir index 3646076..af6e95d 100644 --- a/llvm/test/CodeGen/X86/tail-call-conditional.mir +++ b/llvm/test/CodeGen/X86/tail-call-conditional.mir @@ -47,7 +47,7 @@ body: | ; CHECK-NEXT: %rdi = COPY %rsi ; CHECK-NEXT: %rsi = COPY %rax ; 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: successors: %bb.2, %bb.3 -- 2.7.4