llvm.org GIT mirror llvm / 224eb0a
[PM/LoopUnswitch] Support partial trivial unswitching. The idea of partial unswitching is to take a *part* of a branch's condition that is loop invariant and just unswitching that part. This primarily makes sense with i1 conditions of branches as opposed to switches. When dealing with i1 conditions, we can easily extract loop invariant inputs to a a branch and unswitch them to test them entirely outside the loop. As part of this, we now create much more significant cruft in the loop body, so this relies on adding cleanup passes to the loop pipeline and revisiting unswitched loops to do that cleanup before continuing to process them. This already appears to be more powerful at unswitching than the old loop unswitch pass, and so I'd appreciate pretty careful review in case I'm just missing some correctness checks. The `LIV-loop-condition` test case is not unswitched by the old unswitch pass, but is with this pass. Thanks to Sanjoy and Fedor for the review! Differential Revision: https://reviews.llvm.org/D46706 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@335156 91177308-0d34-0410-b5e6-96231b3b80d8 Chandler Carruth 1 year, 3 months ago
3 changed file(s) with 361 addition(s) and 55 deletion(s). Raw diff Collapse all Expand all
1818 #include "llvm/Analysis/AssumptionCache.h"
1919 #include "llvm/Analysis/CFG.h"
2020 #include "llvm/Analysis/CodeMetrics.h"
21 #include "llvm/Analysis/InstructionSimplify.h"
2122 #include "llvm/Analysis/LoopAnalysisManager.h"
2223 #include "llvm/Analysis/LoopInfo.h"
2324 #include "llvm/Analysis/LoopIterator.h"
2425 #include "llvm/Analysis/LoopPass.h"
26 #include "llvm/Analysis/Utils/Local.h"
2527 #include "llvm/IR/BasicBlock.h"
2628 #include "llvm/IR/Constant.h"
2729 #include "llvm/IR/Constants.h"
6769 UnswitchThreshold("unswitch-threshold", cl::init(50), cl::Hidden,
6870 cl::desc("The cost threshold for unswitching a loop."));
6971
70 static void replaceLoopUsesWithConstant(Loop &L, Value &LIC,
71 Constant &Replacement) {
72 assert(!isa(LIC) && "Why are we unswitching on a constant?");
72 /// Collect all of the loop invariant input values transitively used by the
73 /// homogeneous instruction graph from a given root.
74 ///
75 /// This essentially walks from a root recursively through loop variant operands
76 /// which have the exact same opcode and finds all inputs which are loop
77 /// invariant. For some operations these can be re-associated and unswitched out
78 /// of the loop entirely.
79 static SmallVector
80 collectHomogenousInstGraphLoopInvariants(Loop &L, Instruction &Root,
81 LoopInfo &LI) {
82 SmallVector Invariants;
83 assert(!L.isLoopInvariant(&Root) &&
84 "Only need to walk the graph if root itself is not invariant.");
85
86 // Build a worklist and recurse through operators collecting invariants.
87 SmallVector Worklist;
88 SmallPtrSet Visited;
89 Worklist.push_back(&Root);
90 Visited.insert(&Root);
91 do {
92 Instruction &I = *Worklist.pop_back_val();
93 for (Value *OpV : I.operand_values()) {
94 // Skip constants as unswitching isn't interesting for them.
95 if (isa(OpV))
96 continue;
97
98 // Add it to our result if loop invariant.
99 if (L.isLoopInvariant(OpV)) {
100 Invariants.push_back(OpV);
101 continue;
102 }
103
104 // If not an instruction with the same opcode, nothing we can do.
105 Instruction *OpI = dyn_cast(OpV);
106 if (!OpI || OpI->getOpcode() != Root.getOpcode())
107 continue;
108
109 // Visit this operand.
110 if (Visited.insert(OpI).second)
111 Worklist.push_back(OpI);
112 }
113 } while (!Worklist.empty());
114
115 return Invariants;
116 }
117
118 static void replaceLoopInvariantUses(Loop &L, Value *Invariant,
119 Constant &Replacement) {
120 assert(!isa(Invariant) && "Why are we unswitching on a constant?");
73121
74122 // Replace uses of LIC in the loop with the given constant.
75 for (auto UI = LIC.use_begin(), UE = LIC.use_end(); UI != UE;) {
123 for (auto UI = Invariant->use_begin(), UE = Invariant->use_end(); UI != UE;) {
76124 // Grab the use and walk past it so we can clobber it in the use list.
77125 Use *U = &*UI++;
78126 Instruction *UserI = dyn_cast(U->getUser());
79 if (!UserI || !L.contains(UserI))
80 continue;
81127
82128 // Replace this use within the loop body.
83 *U = &Replacement;
129 if (UserI && L.contains(UserI))
130 U->set(&Replacement);
84131 }
85132 }
86133
134181 static void rewritePHINodesForExitAndUnswitchedBlocks(BasicBlock &ExitBB,
135182 BasicBlock &UnswitchedBB,
136183 BasicBlock &OldExitingBB,
137 BasicBlock &OldPH) {
184 BasicBlock &OldPH,
185 bool FullUnswitch) {
138186 assert(&ExitBB != &UnswitchedBB &&
139187 "Must have different loop exit and unswitched blocks!");
140188 Instruction *InsertPt = &*UnswitchedBB.begin();
155203 if (PN.getIncomingBlock(i) != &OldExitingBB)
156204 continue;
157205
158 Value *Incoming = PN.removeIncomingValue(i);
206 Value *Incoming = PN.getIncomingValue(i);
207 if (FullUnswitch)
208 // No more edge from the old exiting block to the exit block.
209 PN.removeIncomingValue(i);
210
159211 NewPN->addIncoming(Incoming, &OldPH);
160212 }
161213
185237 assert(BI.isConditional() && "Can only unswitch a conditional branch!");
186238 LLVM_DEBUG(dbgs() << " Trying to unswitch branch: " << BI << "\n");
187239
188 Value *LoopCond = BI.getCondition();
189
190 // Need a trivial loop condition to unswitch.
191 if (!L.isLoopInvariant(LoopCond))
192 return false;
193
194 // Check to see if a successor of the branch is guaranteed to
195 // exit through a unique exit block without having any
196 // side-effects. If so, determine the value of Cond that causes
197 // it to do this.
198 ConstantInt *CondVal = ConstantInt::getTrue(BI.getContext());
199 ConstantInt *Replacement = ConstantInt::getFalse(BI.getContext());
240 // The loop invariant values that we want to unswitch.
241 SmallVector Invariants;
242
243 // When true, we're fully unswitching the branch rather than just unswitching
244 // some input conditions to the branch.
245 bool FullUnswitch = false;
246
247 if (L.isLoopInvariant(BI.getCondition())) {
248 Invariants.push_back(BI.getCondition());
249 FullUnswitch = true;
250 } else {
251 if (auto *CondInst = dyn_cast(BI.getCondition()))
252 Invariants = collectHomogenousInstGraphLoopInvariants(L, *CondInst, LI);
253 if (Invariants.empty())
254 // Couldn't find invariant inputs!
255 return false;
256 }
257
258 // Check that one of the branch's successors exits, and which one.
259 bool ExitDirection = true;
200260 int LoopExitSuccIdx = 0;
201261 auto *LoopExitBB = BI.getSuccessor(0);
202262 if (L.contains(LoopExitBB)) {
203 std::swap(CondVal, Replacement);
263 ExitDirection = false;
204264 LoopExitSuccIdx = 1;
205265 LoopExitBB = BI.getSuccessor(1);
206266 if (L.contains(LoopExitBB))
211271 if (!areLoopExitPHIsLoopInvariant(L, *ParentBB, *LoopExitBB))
212272 return false;
213273
214 LLVM_DEBUG(dbgs() << " unswitching trivial branch when: " << CondVal
215 << " == " << LoopCond << "\n");
274 // When unswitching only part of the branch's condition, we need the exit
275 // block to be reached directly from the partially unswitched input. This can
276 // be done when the exit block is along the true edge and the branch condition
277 // is a graph of `or` operations, or the exit block is along the false edge
278 // and the condition is a graph of `and` operations.
279 if (!FullUnswitch) {
280 if (ExitDirection) {
281 if (cast(BI.getCondition())->getOpcode() != Instruction::Or)
282 return false;
283 } else {
284 if (cast(BI.getCondition())->getOpcode() != Instruction::And)
285 return false;
286 }
287 }
288
289 LLVM_DEBUG({
290 dbgs() << " unswitching trivial invariant conditions for: " << BI
291 << "\n";
292 for (Value *Invariant : Invariants) {
293 dbgs() << " " << *Invariant << " == true";
294 if (Invariant != Invariants.back())
295 dbgs() << " ||";
296 dbgs() << "\n";
297 }
298 });
216299
217300 // Split the preheader, so that we know that there is a safe place to insert
218301 // the conditional branch. We will change the preheader to have a conditional
225308 // unswitching. We need to split this if there are other loop predecessors.
226309 // Because the loop is in simplified form, *any* other predecessor is enough.
227310 BasicBlock *UnswitchedBB;
228 if (BasicBlock *PredBB = LoopExitBB->getUniquePredecessor()) {
229 (void)PredBB;
230 assert(PredBB == BI.getParent() &&
311 if (FullUnswitch && LoopExitBB->getUniquePredecessor()) {
312 assert(LoopExitBB->getUniquePredecessor() == BI.getParent() &&
231313 "A branch's parent isn't a predecessor!");
232314 UnswitchedBB = LoopExitBB;
233315 } else {
234316 UnswitchedBB = SplitBlock(LoopExitBB, &LoopExitBB->front(), &DT, &LI);
235317 }
236318
237 // Now splice the branch to gate reaching the new preheader and re-point its
238 // successors.
239 OldPH->getInstList().splice(std::prev(OldPH->end()),
240 BI.getParent()->getInstList(), BI);
319 // Actually move the invariant uses into the unswitched position. If possible,
320 // we do this by moving the instructions, but when doing partial unswitching
321 // we do it by building a new merge of the values in the unswitched position.
241322 OldPH->getTerminator()->eraseFromParent();
242 BI.setSuccessor(LoopExitSuccIdx, UnswitchedBB);
243 BI.setSuccessor(1 - LoopExitSuccIdx, NewPH);
244
245 // Create a new unconditional branch that will continue the loop as a new
246 // terminator.
247 BranchInst::Create(ContinueBB, ParentBB);
323 if (FullUnswitch) {
324 // If fully unswitching, we can use the existing branch instruction.
325 // Splice it into the old PH to gate reaching the new preheader and re-point
326 // its successors.
327 OldPH->getInstList().splice(OldPH->end(), BI.getParent()->getInstList(),
328 BI);
329 BI.setSuccessor(LoopExitSuccIdx, UnswitchedBB);
330 BI.setSuccessor(1 - LoopExitSuccIdx, NewPH);
331
332 // Create a new unconditional branch that will continue the loop as a new
333 // terminator.
334 BranchInst::Create(ContinueBB, ParentBB);
335 } else {
336 // Only unswitching a subset of inputs to the condition, so we will need to
337 // build a new branch that merges the invariant inputs.
338 IRBuilder<> IRB(OldPH);
339 Value *Cond = Invariants.front();
340 if (ExitDirection)
341 assert(cast(BI.getCondition())->getOpcode() ==
342 Instruction::Or &&
343 "Must have an `or` of `i1`s for the condition!");
344 else
345 assert(cast(BI.getCondition())->getOpcode() ==
346 Instruction::And &&
347 "Must have an `and` of `i1`s for the condition!");
348 for (Value *Invariant :
349 make_range(std::next(Invariants.begin()), Invariants.end()))
350 if (ExitDirection)
351 Cond = IRB.CreateOr(Cond, Invariant);
352 else
353 Cond = IRB.CreateAnd(Cond, Invariant);
354
355 BasicBlock *Succs[2];
356 Succs[LoopExitSuccIdx] = UnswitchedBB;
357 Succs[1 - LoopExitSuccIdx] = NewPH;
358 IRB.CreateCondBr(Cond, Succs[0], Succs[1]);
359 }
248360
249361 // Rewrite the relevant PHI nodes.
250362 if (UnswitchedBB == LoopExitBB)
251363 rewritePHINodesForUnswitchedExitBlock(*UnswitchedBB, *ParentBB, *OldPH);
252364 else
253365 rewritePHINodesForExitAndUnswitchedBlocks(*LoopExitBB, *UnswitchedBB,
254 *ParentBB, *OldPH);
366 *ParentBB, *OldPH, FullUnswitch);
255367
256368 // Now we need to update the dominator tree.
257 DT.applyUpdates(
258 {{DT.Delete, ParentBB, UnswitchedBB}, {DT.Insert, OldPH, UnswitchedBB}});
369 DT.insertEdge(OldPH, UnswitchedBB);
370 if (FullUnswitch)
371 DT.deleteEdge(ParentBB, UnswitchedBB);
372
373 // The constant we can replace all of our invariants with inside the loop
374 // body. If any of the invariants have a value other than this the loop won't
375 // be entered.
376 ConstantInt *Replacement = ExitDirection
377 ? ConstantInt::getFalse(BI.getContext())
378 : ConstantInt::getTrue(BI.getContext());
259379
260380 // Since this is an i1 condition we can also trivially replace uses of it
261381 // within the loop with a constant.
262 replaceLoopUsesWithConstant(L, *LoopCond, *Replacement);
382 for (Value *Invariant : Invariants)
383 replaceLoopInvariantUses(L, Invariant, *Replacement);
263384
264385 ++NumTrivial;
265386 ++NumBranches;
392513 } else {
393514 auto *SplitBB =
394515 SplitBlock(DefaultExitBB, &DefaultExitBB->front(), &DT, &LI);
395 rewritePHINodesForExitAndUnswitchedBlocks(*DefaultExitBB, *SplitBB,
396 *ParentBB, *OldPH);
516 rewritePHINodesForExitAndUnswitchedBlocks(
517 *DefaultExitBB, *SplitBB, *ParentBB, *OldPH, /*FullUnswitch*/ true);
397518 DefaultExitBB = SplitExitBBMap[DefaultExitBB] = SplitBB;
398519 }
399520 }
418539 if (!SplitExitBB) {
419540 // If this is the first time we see this, do the split and remember it.
420541 SplitExitBB = SplitBlock(ExitBB, &ExitBB->front(), &DT, &LI);
421 rewritePHINodesForExitAndUnswitchedBlocks(*ExitBB, *SplitExitBB,
422 *ParentBB, *OldPH);
542 rewritePHINodesForExitAndUnswitchedBlocks(
543 *ExitBB, *SplitExitBB, *ParentBB, *OldPH, /*FullUnswitch*/ true);
423544 }
424545 // Update the case pair to point to the split block.
425546 CasePair.second = SplitExitBB;
559680 // Mark that we managed to unswitch something.
560681 Changed = true;
561682
562 // We unswitched the branch. This should always leave us with an
563 // unconditional branch that we can follow now.
683 // If we only unswitched some of the conditions feeding the branch, we won't
684 // have collapsed it to a single successor.
564685 BI = cast(CurrentBB->getTerminator());
565 assert(!BI->isConditional() &&
566 "Cannot form a conditional branch by unswitching1");
686 if (BI->isConditional())
687 return Changed;
688
689 // Follow the newly unconditional branch into its successor.
567690 CurrentBB = BI->getSuccessor(0);
568691
569692 // When continuing, if we exit the loop or reach a previous visited block,
9551078 // matter as we're just trying to build up the map from inside-out; we use
9561079 // the map in a more stably ordered way below.
9571080 auto OrderedClonedExitsInLoops = ClonedExitsInLoops;
958 llvm::sort(OrderedClonedExitsInLoops.begin(),
959 OrderedClonedExitsInLoops.end(),
1081 llvm::sort(OrderedClonedExitsInLoops.begin(), OrderedClonedExitsInLoops.end(),
9601082 [&](BasicBlock *LHS, BasicBlock *RHS) {
9611083 return ExitLoopMap.lookup(LHS)->getLoopDepth() <
9621084 ExitLoopMap.lookup(RHS)->getLoopDepth();
33 ; itself is an LIV loop condition (not partial LIV which could occur in and/or).
44
55 define i32 @test(i1 %cond1, i32 %var1) {
6 ; CHECK-LABEL: define i32 @test(
67 entry:
78 br label %loop_begin
9 ; CHECK-NEXT: entry:
10 ; CHECK-NEXT: br i1 %cond1, label %entry.split, label %loop_exit.split
11 ;
12 ; CHECK: entry.split:
13 ; CHECK-NEXT: br label %loop_begin
814
915 loop_begin:
1016 %var3 = phi i32 [%var1, %entry], [%var2, %do_something]
1117 %cond2 = icmp eq i32 %var3, 10
1218 %cond.and = and i1 %cond1, %cond2
13
14 ; %cond.and only has %cond1 as LIV so no unswitch should happen.
15 ; CHECK: br i1 %cond.and, label %do_something, label %loop_exit
16 br i1 %cond.and, label %do_something, label %loop_exit
19 br i1 %cond.and, label %do_something, label %loop_exit
20 ; CHECK: loop_begin:
21 ; CHECK-NEXT: %[[VAR3:.*]] = phi i32
22 ; CHECK-NEXT: %[[COND2:.*]] = icmp eq i32 %[[VAR3]], 10
23 ; CHECK-NEXT: %[[COND_AND:.*]] = and i1 true, %[[COND2]]
24 ; CHECK-NEXT: br i1 %[[COND_AND]], label %do_something, label %loop_exit
1725
1826 do_something:
1927 %var2 = add i32 %var3, 1
442442 ; CHECK: cleanup:
443443 ; CHECK-NEXT: ret void
444444 }
445
446 define i32 @test_partial_condition_unswitch_and(i32* %var, i1 %cond1, i1 %cond2) {
447 ; CHECK-LABEL: @test_partial_condition_unswitch_and(
448 entry:
449 br label %loop_begin
450 ; CHECK-NEXT: entry:
451 ; CHECK-NEXT: br i1 %cond1, label %entry.split, label %loop_exit.split
452 ;
453 ; CHECK: entry.split:
454 ; CHECK-NEXT: br i1 %cond2, label %entry.split.split, label %loop_exit
455 ;
456 ; CHECK: entry.split.split:
457 ; CHECK-NEXT: br label %loop_begin
458
459 loop_begin:
460 br i1 %cond1, label %continue, label %loop_exit
461 ; CHECK: loop_begin:
462 ; CHECK-NEXT: br label %continue
463
464 continue:
465 %var_val = load i32, i32* %var
466 %var_cond = trunc i32 %var_val to i1
467 %cond_and = and i1 %var_cond, %cond2
468 br i1 %cond_and, label %do_something, label %loop_exit
469 ; CHECK: continue:
470 ; CHECK-NEXT: %[[VAR:.*]] = load i32
471 ; CHECK-NEXT: %[[VAR_COND:.*]] = trunc i32 %[[VAR]] to i1
472 ; CHECK-NEXT: %[[COND_AND:.*]] = and i1 %[[VAR_COND]], true
473 ; CHECK-NEXT: br i1 %[[COND_AND]], label %do_something, label %loop_exit
474
475 do_something:
476 call void @some_func() noreturn nounwind
477 br label %loop_begin
478 ; CHECK: do_something:
479 ; CHECK-NEXT: call
480 ; CHECK-NEXT: br label %loop_begin
481
482 loop_exit:
483 ret i32 0
484 ; CHECK: loop_exit:
485 ; CHECK-NEXT: br label %loop_exit.split
486 ;
487 ; CHECK: loop_exit.split:
488 ; CHECK-NEXT: ret
489 }
490
491 define i32 @test_partial_condition_unswitch_or(i32* %var, i1 %cond1, i1 %cond2, i1 %cond3, i1 %cond4, i1 %cond5, i1 %cond6) {
492 ; CHECK-LABEL: @test_partial_condition_unswitch_or(
493 entry:
494 br label %loop_begin
495 ; CHECK-NEXT: entry:
496 ; CHECK-NEXT: %[[INV_OR1:.*]] = or i1 %cond4, %cond2
497 ; CHECK-NEXT: %[[INV_OR2:.*]] = or i1 %[[INV_OR1]], %cond3
498 ; CHECK-NEXT: %[[INV_OR3:.*]] = or i1 %[[INV_OR2]], %cond1
499 ; CHECK-NEXT: br i1 %[[INV_OR3]], label %loop_exit.split, label %entry.split
500 ;
501 ; CHECK: entry.split:
502 ; CHECK-NEXT: br label %loop_begin
503
504 loop_begin:
505 %var_val = load i32, i32* %var
506 %var_cond = trunc i32 %var_val to i1
507 %cond_or1 = or i1 %var_cond, %cond1
508 %cond_or2 = or i1 %cond2, %cond3
509 %cond_or3 = or i1 %cond_or1, %cond_or2
510 %cond_xor1 = xor i1 %cond5, %var_cond
511 %cond_and1 = and i1 %cond6, %var_cond
512 %cond_or4 = or i1 %cond_xor1, %cond_and1
513 %cond_or5 = or i1 %cond_or3, %cond_or4
514 %cond_or6 = or i1 %cond_or5, %cond4
515 br i1 %cond_or6, label %loop_exit, label %do_something
516 ; CHECK: loop_begin:
517 ; CHECK-NEXT: %[[VAR:.*]] = load i32
518 ; CHECK-NEXT: %[[VAR_COND:.*]] = trunc i32 %[[VAR]] to i1
519 ; CHECK-NEXT: %[[COND_OR1:.*]] = or i1 %[[VAR_COND]], false
520 ; CHECK-NEXT: %[[COND_OR2:.*]] = or i1 false, false
521 ; CHECK-NEXT: %[[COND_OR3:.*]] = or i1 %[[COND_OR1]], %[[COND_OR2]]
522 ; CHECK-NEXT: %[[COND_XOR:.*]] = xor i1 %cond5, %[[VAR_COND]]
523 ; CHECK-NEXT: %[[COND_AND:.*]] = and i1 %cond6, %[[VAR_COND]]
524 ; CHECK-NEXT: %[[COND_OR4:.*]] = or i1 %[[COND_XOR]], %[[COND_AND]]
525 ; CHECK-NEXT: %[[COND_OR5:.*]] = or i1 %[[COND_OR3]], %[[COND_OR4]]
526 ; CHECK-NEXT: %[[COND_OR6:.*]] = or i1 %[[COND_OR5]], false
527 ; CHECK-NEXT: br i1 %[[COND_OR6]], label %loop_exit, label %do_something
528
529 do_something:
530 call void @some_func() noreturn nounwind
531 br label %loop_begin
532 ; CHECK: do_something:
533 ; CHECK-NEXT: call
534 ; CHECK-NEXT: br label %loop_begin
535
536 loop_exit:
537 ret i32 0
538 ; CHECK: loop_exit.split:
539 ; CHECK-NEXT: ret
540 }
541
542 define i32 @test_partial_condition_unswitch_with_lcssa_phi1(i32* %var, i1 %cond, i32 %x) {
543 ; CHECK-LABEL: @test_partial_condition_unswitch_with_lcssa_phi1(
544 entry:
545 br label %loop_begin
546 ; CHECK-NEXT: entry:
547 ; CHECK-NEXT: br i1 %cond, label %entry.split, label %loop_exit.split
548 ;
549 ; CHECK: entry.split:
550 ; CHECK-NEXT: br label %loop_begin
551
552 loop_begin:
553 %var_val = load i32, i32* %var
554 %var_cond = trunc i32 %var_val to i1
555 %cond_and = and i1 %var_cond, %cond
556 br i1 %cond_and, label %do_something, label %loop_exit
557 ; CHECK: loop_begin:
558 ; CHECK-NEXT: %[[VAR:.*]] = load i32
559 ; CHECK-NEXT: %[[VAR_COND:.*]] = trunc i32 %[[VAR]] to i1
560 ; CHECK-NEXT: %[[COND_AND:.*]] = and i1 %[[VAR_COND]], true
561 ; CHECK-NEXT: br i1 %[[COND_AND]], label %do_something, label %loop_exit
562
563 do_something:
564 call void @some_func() noreturn nounwind
565 br label %loop_begin
566 ; CHECK: do_something:
567 ; CHECK-NEXT: call
568 ; CHECK-NEXT: br label %loop_begin
569
570 loop_exit:
571 %x.lcssa = phi i32 [ %x, %loop_begin ]
572 ret i32 %x.lcssa
573 ; CHECK: loop_exit:
574 ; CHECK-NEXT: %[[LCSSA:.*]] = phi i32 [ %x, %loop_begin ]
575 ; CHECK-NEXT: br label %loop_exit.split
576 ;
577 ; CHECK: loop_exit.split:
578 ; CHECK-NEXT: %[[LCSSA_SPLIT:.*]] = phi i32 [ %x, %entry ], [ %[[LCSSA]], %loop_exit ]
579 ; CHECK-NEXT: ret i32 %[[LCSSA_SPLIT]]
580 }
581
582 define i32 @test_partial_condition_unswitch_with_lcssa_phi2(i32* %var, i1 %cond, i32 %x, i32 %y) {
583 ; CHECK-LABEL: @test_partial_condition_unswitch_with_lcssa_phi2(
584 entry:
585 br label %loop_begin
586 ; CHECK-NEXT: entry:
587 ; CHECK-NEXT: br i1 %cond, label %entry.split, label %loop_exit.split
588 ;
589 ; CHECK: entry.split:
590 ; CHECK-NEXT: br label %loop_begin
591
592 loop_begin:
593 %var_val = load i32, i32* %var
594 %var_cond = trunc i32 %var_val to i1
595 %cond_and = and i1 %var_cond, %cond
596 br i1 %cond_and, label %do_something, label %loop_exit
597 ; CHECK: loop_begin:
598 ; CHECK-NEXT: %[[VAR:.*]] = load i32
599 ; CHECK-NEXT: %[[VAR_COND:.*]] = trunc i32 %[[VAR]] to i1
600 ; CHECK-NEXT: %[[COND_AND:.*]] = and i1 %[[VAR_COND]], true
601 ; CHECK-NEXT: br i1 %[[COND_AND]], label %do_something, label %loop_exit
602
603 do_something:
604 call void @some_func() noreturn nounwind
605 br i1 %var_cond, label %loop_begin, label %loop_exit
606 ; CHECK: do_something:
607 ; CHECK-NEXT: call
608 ; CHECK-NEXT: br i1 %[[VAR_COND]], label %loop_begin, label %loop_exit
609
610 loop_exit:
611 %xy.lcssa = phi i32 [ %x, %loop_begin ], [ %y, %do_something ]
612 ret i32 %xy.lcssa
613 ; CHECK: loop_exit:
614 ; CHECK-NEXT: %[[LCSSA:.*]] = phi i32 [ %x, %loop_begin ], [ %y, %do_something ]
615 ; CHECK-NEXT: br label %loop_exit.split
616 ;
617 ; CHECK: loop_exit.split:
618 ; CHECK-NEXT: %[[LCSSA_SPLIT:.*]] = phi i32 [ %x, %entry ], [ %[[LCSSA]], %loop_exit ]
619 ; CHECK-NEXT: ret i32 %[[LCSSA_SPLIT]]
620 }