llvm.org GIT mirror llvm / 366ce55
Merging r294348: ------------------------------------------------------------------------ r294348 | hans | 2017-02-07 12:37:45 -0800 (Tue, 07 Feb 2017) | 6 lines [X86] Disable conditional tail calls (PR31257) They are currently modelled incorrectly (as calls, which clobber registers, confusing e.g. Machine Copy Propagation). Reverting until we figure out the proper solution. ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_40@294476 91177308-0d34-0410-b5e6-96231b3b80d8 Hans Wennborg 2 years ago
10 changed file(s) with 6 addition(s) and 341 deletion(s). Raw diff Collapse all Expand all
11071107 /// terminator instruction that has not been predicated.
11081108 virtual bool isUnpredicatedTerminator(const MachineInstr &MI) const;
11091109
1110 /// Returns true if MI is an unconditional tail call.
1111 virtual bool isUnconditionalTailCall(const MachineInstr &MI) const {
1112 return false;
1113 }
1114
1115 /// Returns true if the tail call can be made conditional on BranchCond.
1116 virtual bool
1117 canMakeTailCallConditional(SmallVectorImpl &Cond,
1118 const MachineInstr &TailCall) const {
1119 return false;
1120 }
1121
1122 /// Replace the conditional branch in MBB with a conditional tail call.
1123 virtual void replaceBranchWithTailCall(MachineBasicBlock &MBB,
1124 SmallVectorImpl &Cond,
1125 const MachineInstr &TailCall) const {
1126 llvm_unreachable("Target didn't implement replaceBranchWithTailCall!");
1127 }
1128
11291110 /// Convert the instruction into a predicated instruction.
11301111 /// It returns true if the operation was successful.
11311112 virtual bool PredicateInstruction(MachineInstr &MI,
4848 STATISTIC(NumBranchOpts, "Number of branches optimized");
4949 STATISTIC(NumTailMerge , "Number of block tails merged");
5050 STATISTIC(NumHoist , "Number of times common instructions are hoisted");
51 STATISTIC(NumTailCalls, "Number of tail calls optimized");
5251
5352 static cl::opt FlagEnableTailMerge("enable-tail-merge",
5453 cl::init(cl::BOU_UNSET), cl::Hidden);
13861385 }
13871386 }
13881387
1389 if (!IsEmptyBlock(MBB) && MBB->pred_size() == 1 &&
1390 MF.getFunction()->optForSize()) {
1391 // Changing "Jcc foo; foo: jmp bar;" into "Jcc bar;" might change the branch
1392 // direction, thereby defeating careful block placement and regressing
1393 // performance. Therefore, only consider this for optsize functions.
1394 MachineInstr &TailCall = *MBB->getFirstNonDebugInstr();
1395 if (TII->isUnconditionalTailCall(TailCall)) {
1396 MachineBasicBlock *Pred = *MBB->pred_begin();
1397 MachineBasicBlock *PredTBB = nullptr, *PredFBB = nullptr;
1398 SmallVector PredCond;
1399 bool PredAnalyzable =
1400 !TII->analyzeBranch(*Pred, PredTBB, PredFBB, PredCond, true);
1401
1402 if (PredAnalyzable && !PredCond.empty() && PredTBB == MBB) {
1403 // The predecessor has a conditional branch to this block which consists
1404 // of only a tail call. Try to fold the tail call into the conditional
1405 // branch.
1406 if (TII->canMakeTailCallConditional(PredCond, TailCall)) {
1407 // TODO: It would be nice if analyzeBranch() could provide a pointer
1408 // to the branch insturction so replaceBranchWithTailCall() doesn't
1409 // have to search for it.
1410 TII->replaceBranchWithTailCall(*Pred, PredCond, TailCall);
1411 ++NumTailCalls;
1412 Pred->removeSuccessor(MBB);
1413 MadeChange = true;
1414 return MadeChange;
1415 }
1416 }
1417 // If the predecessor is falling through to this block, we could reverse
1418 // the branch condition and fold the tail call into that. However, after
1419 // that we might have to re-arrange the CFG to fall through to the other
1420 // block and there is a high risk of regressing code size rather than
1421 // improving it.
1422 }
1423 }
1424
14251388 // Analyze the branch in the current block.
14261389 MachineBasicBlock *CurTBB = nullptr, *CurFBB = nullptr;
14271390 SmallVector CurCond;
7676 default:
7777 return false;
7878 case X86::TCRETURNdi:
79 case X86::TCRETURNdicc:
8079 case X86::TCRETURNri:
8180 case X86::TCRETURNmi:
8281 case X86::TCRETURNdi64:
83 case X86::TCRETURNdi64cc:
8482 case X86::TCRETURNri64:
8583 case X86::TCRETURNmi64: {
8684 bool isMem = Opcode == X86::TCRETURNmi || Opcode == X86::TCRETURNmi64;
9896 Offset = StackAdj - MaxTCDelta;
9997 assert(Offset >= 0 && "Offset should never be negative");
10098
101 if (Opcode == X86::TCRETURNdicc || Opcode == X86::TCRETURNdi64cc) {
102 assert(Offset == 0 && "Conditional tail call cannot adjust the stack.");
103 }
104
10599 if (Offset) {
106100 // Check for possible merge with preceding ADD instruction.
107101 Offset += X86FL->mergeSPUpdates(MBB, MBBI, true);
110104
111105 // Jump to label or value in register.
112106 bool IsWin64 = STI->isTargetWin64();
113 if (Opcode == X86::TCRETURNdi || Opcode == X86::TCRETURNdicc ||
114 Opcode == X86::TCRETURNdi64 || Opcode == X86::TCRETURNdi64cc) {
107 if (Opcode == X86::TCRETURNdi || Opcode == X86::TCRETURNdi64) {
115108 unsigned Op;
116109 switch (Opcode) {
117110 case X86::TCRETURNdi:
118111 Op = X86::TAILJMPd;
119 break;
120 case X86::TCRETURNdicc:
121 Op = X86::TAILJMPd_CC;
122 break;
123 case X86::TCRETURNdi64cc:
124 assert(!IsWin64 && "Conditional tail calls confuse the Win64 unwinder.");
125 // TODO: We could do it for Win64 "leaf" functions though; PR30337.
126 Op = X86::TAILJMPd64_CC;
127112 break;
128113 default:
129114 // Note: Win64 uses REX prefixes indirect jumps out of functions, but
140125 MIB.addExternalSymbol(JumpTarget.getSymbolName(),
141126 JumpTarget.getTargetFlags());
142127 }
143 if (Op == X86::TAILJMPd_CC || Op == X86::TAILJMPd64_CC) {
144 MIB.addImm(MBBI->getOperand(2).getImm());
145 }
146
147128 } else if (Opcode == X86::TCRETURNmi || Opcode == X86::TCRETURNmi64) {
148129 unsigned Op = (Opcode == X86::TCRETURNmi)
149130 ? X86::TAILJMPm
263263 "jmp{l}\t{*}$dst", [], IIC_JMP_MEM>;
264264 }
265265
266 // Conditional tail calls are similar to the above, but they are branches
267 // rather than barriers, and they use EFLAGS.
268 let isCall = 1, isTerminator = 1, isReturn = 1, isBranch = 1,
269 isCodeGenOnly = 1, SchedRW = [WriteJumpLd] in
270 let Uses = [ESP, EFLAGS] in {
271 def TCRETURNdicc : PseudoI<(outs),
272 (ins i32imm_pcrel:$dst, i32imm:$offset, i32imm:$cond), []>;
273
274 // This gets substituted to a conditional jump instruction in MC lowering.
275 def TAILJMPd_CC : Ii32PCRel<0x80, RawFrm, (outs),
276 (ins i32imm_pcrel:$dst, i32imm:$cond),
277 "",
278 [], IIC_JMP_REL>;
279 }
280
281266
282267 //===----------------------------------------------------------------------===//
283268 // Call Instructions...
339324 "rex64 jmp{q}\t{*}$dst", [], IIC_JMP_MEM>;
340325 }
341326 }
342
343 // Conditional tail calls are similar to the above, but they are branches
344 // rather than barriers, and they use EFLAGS.
345 let isCall = 1, isTerminator = 1, isReturn = 1, isBranch = 1,
346 isCodeGenOnly = 1, SchedRW = [WriteJumpLd] in
347 let Uses = [RSP, EFLAGS] in {
348 def TCRETURNdi64cc : PseudoI<(outs),
349 (ins i64i32imm_pcrel:$dst, i32imm:$offset,
350 i32imm:$cond), []>;
351
352 // This gets substituted to a conditional jump instruction in MC lowering.
353 def TAILJMPd64_CC : Ii32PCRel<0x80, RawFrm, (outs),
354 (ins i64i32imm_pcrel:$dst, i32imm:$cond),
355 "",
356 [], IIC_JMP_REL>;
357 }
51075107 return !isPredicated(MI);
51085108 }
51095109
5110 bool X86InstrInfo::isUnconditionalTailCall(const MachineInstr &MI) const {
5111 switch (MI.getOpcode()) {
5112 case X86::TCRETURNdi:
5113 case X86::TCRETURNri:
5114 case X86::TCRETURNmi:
5115 case X86::TCRETURNdi64:
5116 case X86::TCRETURNri64:
5117 case X86::TCRETURNmi64:
5118 return true;
5119 default:
5120 return false;
5121 }
5122 }
5123
5124 bool X86InstrInfo::canMakeTailCallConditional(
5125 SmallVectorImpl &BranchCond,
5126 const MachineInstr &TailCall) const {
5127 if (TailCall.getOpcode() != X86::TCRETURNdi &&
5128 TailCall.getOpcode() != X86::TCRETURNdi64) {
5129 // Only direct calls can be done with a conditional branch.
5130 return false;
5131 }
5132
5133 if (Subtarget.isTargetWin64()) {
5134 // Conditional tail calls confuse the Win64 unwinder.
5135 // TODO: Allow them for "leaf" functions; PR30337.
5136 return false;
5137 }
5138
5139 assert(BranchCond.size() == 1);
5140 if (BranchCond[0].getImm() > X86::LAST_VALID_COND) {
5141 // Can't make a conditional tail call with this condition.
5142 return false;
5143 }
5144
5145 const X86MachineFunctionInfo *X86FI =
5146 TailCall.getParent()->getParent()->getInfo();
5147 if (X86FI->getTCReturnAddrDelta() != 0 ||
5148 TailCall.getOperand(1).getImm() != 0) {
5149 // A conditional tail call cannot do any stack adjustment.
5150 return false;
5151 }
5152
5153 return true;
5154 }
5155
5156 void X86InstrInfo::replaceBranchWithTailCall(
5157 MachineBasicBlock &MBB, SmallVectorImpl &BranchCond,
5158 const MachineInstr &TailCall) const {
5159 assert(canMakeTailCallConditional(BranchCond, TailCall));
5160
5161 MachineBasicBlock::iterator I = MBB.end();
5162 while (I != MBB.begin()) {
5163 --I;
5164 if (I->isDebugValue())
5165 continue;
5166 if (!I->isBranch())
5167 assert(0 && "Can't find the branch to replace!");
5168
5169 X86::CondCode CC = getCondFromBranchOpc(I->getOpcode());
5170 assert(BranchCond.size() == 1);
5171 if (CC != BranchCond[0].getImm())
5172 continue;
5173
5174 break;
5175 }
5176
5177 unsigned Opc = TailCall.getOpcode() == X86::TCRETURNdi ? X86::TCRETURNdicc
5178 : X86::TCRETURNdi64cc;
5179
5180 auto MIB = BuildMI(MBB, I, MBB.findDebugLoc(I), get(Opc));
5181 MIB->addOperand(TailCall.getOperand(0)); // Destination.
5182 MIB.addImm(0); // Stack offset (not used).
5183 MIB->addOperand(BranchCond[0]); // Condition.
5184 MIB.copyImplicitOps(TailCall); // Regmask and (imp-used) parameters.
5185
5186 I->eraseFromParent();
5187 }
5188
51895110 // Given a MBB and its TBB, find the FBB which was a fallthrough MBB (it may
51905111 // not be a fallthrough MBB now due to layout changes). Return nullptr if the
51915112 // fallthrough MBB cannot be identified.
315315
316316 // Branch analysis.
317317 bool isUnpredicatedTerminator(const MachineInstr &MI) const override;
318 bool isUnconditionalTailCall(const MachineInstr &MI) const override;
319 bool canMakeTailCallConditional(SmallVectorImpl &Cond,
320 const MachineInstr &TailCall) const override;
321 void replaceBranchWithTailCall(MachineBasicBlock &MBB,
322 SmallVectorImpl &Cond,
323 const MachineInstr &TailCall) const override;
324
325318 bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
326319 MachineBasicBlock *&FBB,
327320 SmallVectorImpl &Cond,
497497 break;
498498 }
499499
500 // TAILJMPd, TAILJMPd64, TailJMPd_cc - Lower to the correct jump instruction.
500 // TAILJMPd, TAILJMPd64 - Lower to the correct jump instruction.
501501 { unsigned Opcode;
502502 case X86::TAILJMPr: Opcode = X86::JMP32r; goto SetTailJmpOpcode;
503503 case X86::TAILJMPd:
504504 case X86::TAILJMPd64: Opcode = X86::JMP_1; goto SetTailJmpOpcode;
505 case X86::TAILJMPd_CC:
506 case X86::TAILJMPd64_CC:
507 Opcode = X86::GetCondBranchFromCond(
508 static_cast(MI->getOperand(1).getImm()));
509 goto SetTailJmpOpcode;
510505
511506 SetTailJmpOpcode:
512507 MCOperand Saved = OutMI.getOperand(0);
12801275 case X86::TAILJMPr:
12811276 case X86::TAILJMPm:
12821277 case X86::TAILJMPd:
1283 case X86::TAILJMPd_CC:
12841278 case X86::TAILJMPr64:
12851279 case X86::TAILJMPm64:
12861280 case X86::TAILJMPd64:
1287 case X86::TAILJMPd64_CC:
12881281 case X86::TAILJMPr64_REX:
12891282 case X86::TAILJMPm64_REX:
12901283 // Lower these as normal, but add some comments.
+0
-53
test/CodeGen/X86/conditional-tailcall.ll less more
None ; RUN: llc < %s -mtriple=i686-linux -show-mc-encoding | FileCheck %s
1 ; RUN: llc < %s -mtriple=x86_64-linux -show-mc-encoding | FileCheck %s
2
3 declare void @foo()
4 declare void @bar()
5
6 define void @f(i32 %x, i32 %y) optsize {
7 entry:
8 %p = icmp eq i32 %x, %y
9 br i1 %p, label %bb1, label %bb2
10 bb1:
11 tail call void @foo()
12 ret void
13 bb2:
14 tail call void @bar()
15 ret void
16
17 ; CHECK-LABEL: f:
18 ; CHECK: cmp
19 ; CHECK: jne bar
20 ; Check that the asm doesn't just look good, but uses the correct encoding.
21 ; CHECK: encoding: [0x75,A]
22 ; CHECK: jmp foo
23 }
24
25
26 declare x86_thiscallcc zeroext i1 @baz(i8*, i32)
27 define x86_thiscallcc zeroext i1 @BlockPlacementTest(i8* %this, i32 %x) optsize {
28 entry:
29 %and = and i32 %x, 42
30 %tobool = icmp eq i32 %and, 0
31 br i1 %tobool, label %land.end, label %land.rhs
32
33 land.rhs:
34 %and6 = and i32 %x, 44
35 %tobool7 = icmp eq i32 %and6, 0
36 br i1 %tobool7, label %lor.rhs, label %land.end
37
38 lor.rhs:
39 %call = tail call x86_thiscallcc zeroext i1 @baz(i8* %this, i32 %x) #2
40 br label %land.end
41
42 land.end:
43 %0 = phi i1 [ false, %entry ], [ true, %land.rhs ], [ %call, %lor.rhs ]
44 ret i1 %0
45
46 ; Make sure machine block placement isn't confused by the conditional tail call,
47 ; but sees that it can fall through to the next block.
48 ; CHECK-LABEL: BlockPlacementTest
49 ; CHECK: je baz
50 ; CHECK-NOT: xor
51 ; CHECK: ret
52 }
9292 ; CHECK-LABEL: test2_1:
9393 ; CHECK: movzbl
9494 ; CHECK: cmpl $256
95 ; CHECK: je bar
95 ; CHECK: jne .LBB
96 ; CHECK: jmp bar
9697 define void @test2_1(i32 %X) nounwind minsize {
9798 entry:
9899 %and = and i32 %X, 255
222223 ; CHECK-LABEL: test_sext_i8_icmp_255:
223224 ; CHECK: movb $1,
224225 ; CHECK: testb
225 ; CHECK: je bar
226 ; CHECK: jne .LBB
227 ; CHECK: jmp bar
226228 define void @test_sext_i8_icmp_255(i8 %x) nounwind minsize {
227229 entry:
228230 %sext = sext i8 %x to i32
+0
-85
test/CodeGen/X86/tail-call-conditional.mir less more
None # RUN: llc -mtriple x86_64-- -verify-machineinstrs -run-pass branch-folder -o - %s | FileCheck %s
1
2 # Check the TCRETURNdi64cc optimization.
3
4 --- |
5 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
6
7 define i64 @test(i64 %arg, i8* %arg1) optsize {
8 %tmp = icmp ult i64 %arg, 100
9 br i1 %tmp, label %1, label %4
10
11 %tmp3 = icmp ult i64 %arg, 10
12 br i1 %tmp3, label %2, label %3
13
14 %tmp5 = tail call i64 @f1(i8* %arg1, i64 %arg)
15 ret i64 %tmp5
16
17 %tmp7 = tail call i64 @f2(i8* %arg1, i64 %arg)
18 ret i64 %tmp7
19
20 ret i64 123
21 }
22
23 declare i64 @f1(i8*, i64)
24 declare i64 @f2(i8*, i64)
25
26 ...
27 ---
28 name: test
29 tracksRegLiveness: true
30 liveins:
31 - { reg: '%rdi' }
32 - { reg: '%rsi' }
33 body: |
34 bb.0:
35 successors: %bb.1, %bb.4
36 liveins: %rdi, %rsi
37
38 %rax = COPY %rdi
39 CMP64ri8 %rax, 99, implicit-def %eflags
40 JA_1 %bb.4, implicit %eflags
41 JMP_1 %bb.1
42
43 ; CHECK: bb.1:
44 ; CHECK-NEXT: successors: %bb.2({{[^)]+}}){{$}}
45 ; CHECK-NEXT: liveins: %rax, %rsi
46 ; CHECK-NEXT: {{^ $}}
47 ; CHECK-NEXT: %rdi = COPY %rsi
48 ; CHECK-NEXT: %rsi = COPY %rax
49 ; CHECK-NEXT: CMP64ri8 %rax, 9, implicit-def %eflags
50 ; CHECK-NEXT: TCRETURNdi64cc @f1, 0, 3, csr_64, implicit %rsp, implicit %eflags, implicit %rsp, implicit %rdi, implicit %rsi
51
52 bb.1:
53 successors: %bb.2, %bb.3
54 liveins: %rax, %rsi
55
56 CMP64ri8 %rax, 9, implicit-def %eflags
57 JA_1 %bb.3, implicit %eflags
58 JMP_1 %bb.2
59
60 bb.2:
61 liveins: %rax, %rsi
62
63 %rdi = COPY %rsi
64 %rsi = COPY %rax
65
66 TCRETURNdi64 @f1, 0, csr_64, implicit %rsp, implicit %rdi, implicit %rsi
67
68 ; CHECK: bb.2:
69 ; CHECK-NEXT: liveins: %rax, %rdi, %rsi
70 ; CHECK-NEXT: {{^ $}}
71 ; CHECK-NEXT: TCRETURNdi64 @f2, 0, csr_64, implicit %rsp, implicit %rdi, implicit %rsi
72
73 bb.3:
74 liveins: %rax, %rsi
75
76 %rdi = COPY %rsi
77 %rsi = COPY %rax
78 TCRETURNdi64 @f2, 0, csr_64, implicit %rsp, implicit %rdi, implicit %rsi
79
80 bb.4:
81 dead %eax = MOV32ri64 123, implicit-def %rax
82 RET 0, %rax
83
84 ...