llvm.org GIT mirror llvm / 8697d18
PredicateInfo: Handle critical edges Summary: This adds support for placing predicateinfo such that it affects critical edges. This fixes the issues mentioned by Nuno on the mailing list. Depends on D29519 Reviewers: davide, nlopes Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D29606 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@294921 91177308-0d34-0410-b5e6-96231b3b80d8 Daniel Berlin 2 years ago
6 changed file(s) with 471 addition(s) and 114 deletion(s). Raw diff Collapse all Expand all
5252 #define LLVM_TRANSFORMS_UTILS_PREDICATEINFO_H
5353
5454 #include "llvm/ADT/DenseMap.h"
55 #include "llvm/ADT/DenseSet.h"
5556 #include "llvm/ADT/SmallPtrSet.h"
5657 #include "llvm/ADT/SmallVector.h"
5758 #include "llvm/ADT/ilist.h"
192193 typedef SmallVectorImpl ValueDFSStack;
193194 void convertUsesToDFSOrdered(Value *, SmallVectorImpl &);
194195 Value *materializeStack(unsigned int &, ValueDFSStack &, Value *);
195 bool stackIsInScope(const ValueDFSStack &, int DFSIn, int DFSOut) const;
196 void popStackUntilDFSScope(ValueDFSStack &, int DFSIn, int DFSOut);
196 bool stackIsInScope(const ValueDFSStack &, const ValueDFS &) const;
197 void popStackUntilDFSScope(ValueDFSStack &, const ValueDFS &);
197198 ValueInfo &getOrCreateValueInfo(Value *);
198199 const ValueInfo &getValueInfo(Value *) const;
199200 Function &F;
213214 DenseMap ValueInfoNums;
214215 // OrderedBasicBlocks used during sorting uses
215216 DenseMap> OBBMap;
217 // The set of edges along which we can only handle phi uses, due to critical
218 // edges.
219 DenseSet PhiUsesOnly;
216220 };
217221
218222 // This pass does eager building and then printing of PredicateInfo. It is used
6565 int DFSIn = 0;
6666 int DFSOut = 0;
6767 unsigned int LocalNum = LN_Middle;
68 PredicateBase *PInfo = nullptr;
6968 // Only one of Def or Use will be set.
7069 Value *Def = nullptr;
7170 Use *U = nullptr;
71 // Neither PInfo nor PhiOnly participate in the ordering
72 PredicateBase *PInfo = nullptr;
73 bool PhiOnly = false;
7274 };
7375
7476 // This compares ValueDFS structures, creating OrderedBasicBlocks where
8991
9092 bool SameBlock = std::tie(A.DFSIn, A.DFSOut) == std::tie(B.DFSIn, B.DFSOut);
9193
94 // We want to put the def that will get used for a given set of phi uses,
95 // before those phi uses.
96 // So we sort by edge, then by def.
97 // Note that only phi nodes uses and defs can come last.
98 if (SameBlock && A.LocalNum == LN_Last && B.LocalNum == LN_Last)
99 return comparePHIRelated(A, B);
100
92101 if (!SameBlock || A.LocalNum != LN_Middle || B.LocalNum != LN_Middle)
93102 return std::tie(A.DFSIn, A.DFSOut, A.LocalNum, A.Def, A.U) <
94103 std::tie(B.DFSIn, B.DFSOut, B.LocalNum, B.Def, B.U);
95104 return localComesBefore(A, B);
105 }
106
107 // For a phi use, or a non-materialized def, return the edge it represents.
108 const std::pair
109 getBlockEdge(const ValueDFS &VD) const {
110 if (!VD.Def && VD.U) {
111 auto *PHI = cast(VD.U->getUser());
112 return std::make_pair(PHI->getIncomingBlock(*VD.U), PHI->getParent());
113 }
114 // This is really a non-materialized def.
115 auto *PBranch = cast(VD.PInfo);
116 return std::make_pair(PBranch->BranchBB, PBranch->SplitBB);
117 }
118
119 // For two phi related values, return the ordering.
120 bool comparePHIRelated(const ValueDFS &A, const ValueDFS &B) const {
121 auto &ABlockEdge = getBlockEdge(A);
122 auto &BBlockEdge = getBlockEdge(B);
123 // Now sort by block edge and then defs before uses.
124 return std::tie(ABlockEdge, A.Def, A.U) < std::tie(BBlockEdge, B.Def, B.U);
96125 }
97126
98127 // Get the definition of an instruction that occurs in the middle of a block.
159188
160189 } // namespace PredicateInfoClasses
161190
162 bool PredicateInfo::stackIsInScope(const ValueDFSStack &Stack, int DFSIn,
163 int DFSOut) const {
191 bool PredicateInfo::stackIsInScope(const ValueDFSStack &Stack,
192 const ValueDFS &VDUse) const {
164193 if (Stack.empty())
165194 return false;
166 return DFSIn >= Stack.back().DFSIn && DFSOut <= Stack.back().DFSOut;
167 }
168
169 void PredicateInfo::popStackUntilDFSScope(ValueDFSStack &Stack, int DFSIn,
170 int DFSOut) {
171 while (!Stack.empty() && !stackIsInScope(Stack, DFSIn, DFSOut))
195 // If it's a phi only use, make sure it's for this phi node edge, and that the
196 // use is in a phi node. If it's anything else, and the top of the stack is
197 // phionly, we need to pop the stack. We deliberately sort phi uses next to
198 // the defs they must go with so that we can know it's time to pop the stack
199 // when we hit the end of the phi uses for a given def.
200 if (Stack.back().PhiOnly) {
201 if (!VDUse.U)
202 return false;
203 auto *PHI = dyn_cast(VDUse.U->getUser());
204 if (!PHI)
205 return false;
206 // The only phionly defs should be branch info.
207 auto *PBranch = dyn_cast(Stack.back().PInfo);
208 assert(PBranch && "Only branches should have PHIOnly defs");
209 // Check edge
210 BasicBlock *EdgePred = PHI->getIncomingBlock(*VDUse.U);
211 if (EdgePred != PBranch->BranchBB)
212 return false;
213 }
214
215 return (VDUse.DFSIn >= Stack.back().DFSIn &&
216 VDUse.DFSOut <= Stack.back().DFSOut);
217 }
218
219 void PredicateInfo::popStackUntilDFSScope(ValueDFSStack &Stack,
220 const ValueDFS &VD) {
221 while (!Stack.empty() && !stackIsInScope(Stack, VD))
172222 Stack.pop_back();
173223 }
174224
270320 SmallVector CmpOperands;
271321 BasicBlock *FirstBB = BI->getSuccessor(0);
272322 BasicBlock *SecondBB = BI->getSuccessor(1);
273 bool FirstSinglePred = FirstBB->getSinglePredecessor();
274 bool SecondSinglePred = SecondBB->getSinglePredecessor();
275323 SmallVector SuccsToProcess;
276324 bool isAnd = false;
277325 bool isOr = false;
278 // First make sure we have single preds for these successors, as we can't
279 // usefully propagate true/false info to them if there are multiple paths to
280 // them.
281 if (FirstSinglePred)
282 SuccsToProcess.push_back(FirstBB);
283 if (SecondSinglePred)
284 SuccsToProcess.push_back(SecondBB);
285 if (SuccsToProcess.empty())
286 return;
326 SuccsToProcess.push_back(FirstBB);
327 SuccsToProcess.push_back(SecondBB);
287328 // Second, see if we have a comparison we support
288329 SmallVector ComparisonsToProcess;
289330 CmpInst::Predicate Pred;
320361 new PredicateBranch(Op, BranchBB, Succ, Cmp, TakenEdge);
321362 AllInfos.push_back(PB);
322363 OperandInfo.Infos.push_back(PB);
364 if (!Succ->getSinglePredecessor())
365 PhiUsesOnly.insert({BranchBB, Succ});
323366 }
324367 }
325368 CmpOperands.clear();
367410 RenameIter == RenameStack.begin() ? OrigOp : (RenameIter - 1)->Def;
368411 ValueDFS &Result = *RenameIter;
369412 auto *ValInfo = Result.PInfo;
370 // For branches, we can just place the operand in the split block. For
371 // assume, we have to place it right before the assume to ensure we dominate
372 // all of our uses.
413 // For branches, we can just place the operand in the branch block before
414 // the terminator. For assume, we have to place it right before the assume
415 // to ensure we dominate all of our uses. Always insert right before the
416 // relevant instruction (terminator, assume), so that we insert in proper
417 // order in the case of multiple predicateinfo in the same block.
373418 if (isa(ValInfo)) {
374419 auto *PBranch = cast(ValInfo);
375 // It's possible we are trying to insert multiple predicateinfos in the
376 // same block at the beginning of the block. When we do this, we need to
377 // insert them one after the other, not one before the other. To see if we
378 // have already inserted predicateinfo into this block, we see if Op !=
379 // OrigOp && Op->getParent() == PBranch->SplitBB. Op must be an
380 // instruction we inserted if it's not the original op.
381 BasicBlock::iterator InsertPt;
382 if (Op == OrigOp ||
383 cast(Op)->getParent() != PBranch->SplitBB) {
384 InsertPt = PBranch->SplitBB->begin();
385 // Insert after last phi node.
386 while (isa(InsertPt))
387 ++InsertPt;
388 } else {
389 // Insert after op.
390 InsertPt = ++(cast(Op)->getIterator());
391 }
392 IRBuilder<> B(PBranch->SplitBB, InsertPt);
420 IRBuilder<> B(PBranch->BranchBB->getTerminator());
393421 Function *IF = Intrinsic::getDeclaration(
394422 F.getParent(), Intrinsic::ssa_copy, Op->getType());
395423 Value *PIC = B.CreateCall(IF, Op, Op->getName() + "." + Twine(Counter++));
399427 auto *PAssume = dyn_cast(ValInfo);
400428 assert(PAssume &&
401429 "Should not have gotten here without it being an assume");
402 // Unlike above, this should already insert in the right order when we
403 // insert multiple predicateinfos in the same block. Because we are
404 // always inserting right before the assume (instead of the beginning of a
405 // block), newer insertions will end up after older ones.
406 IRBuilder<> B(PAssume->AssumeInst->getParent(),
407 PAssume->AssumeInst->getIterator());
430 IRBuilder<> B(PAssume->AssumeInst);
408431 Function *IF = Intrinsic::getDeclaration(
409432 F.getParent(), Intrinsic::ssa_copy, Op->getType());
410433 Value *PIC = B.CreateCall(IF, Op);
446469 // created otherwise.
447470 for (auto &PossibleCopy : ValueInfo.Infos) {
448471 ValueDFS VD;
449 BasicBlock *CopyBB = nullptr;
450472 // Determine where we are going to place the copy by the copy type.
451473 // The predicate info for branches always come first, they will get
452474 // materialized in the split block at the top of the block.
453475 // The predicate info for assumes will be somewhere in the middle,
454476 // it will get materialized in front of the assume.
455 if (const auto *PBranch = dyn_cast(PossibleCopy)) {
456 CopyBB = PBranch->SplitBB;
457 VD.LocalNum = LN_First;
458 } else if (const auto *PAssume =
459 dyn_cast(PossibleCopy)) {
460 CopyBB = PAssume->AssumeInst->getParent();
477 if (const auto *PAssume = dyn_cast(PossibleCopy)) {
461478 VD.LocalNum = LN_Middle;
462 } else
463 llvm_unreachable("Unhandled predicate info type");
464 DomTreeNode *DomNode = DT.getNode(CopyBB);
465 if (!DomNode)
466 continue;
467 VD.DFSIn = DomNode->getDFSNumIn();
468 VD.DFSOut = DomNode->getDFSNumOut();
469 VD.PInfo = PossibleCopy;
470 OrderedUses.push_back(VD);
479 DomTreeNode *DomNode = DT.getNode(PAssume->AssumeInst->getParent());
480 if (!DomNode)
481 continue;
482 VD.DFSIn = DomNode->getDFSNumIn();
483 VD.DFSOut = DomNode->getDFSNumOut();
484 VD.PInfo = PossibleCopy;
485 OrderedUses.push_back(VD);
486 } else if (const auto *PBranch =
487 dyn_cast(PossibleCopy)) {
488 // If we can only do phi uses, we treat it like it's in the branch
489 // block, and handle it specially. We know that it goes last, and only
490 // dominate phi uses.
491 if (PhiUsesOnly.count({PBranch->BranchBB, PBranch->SplitBB})) {
492 VD.LocalNum = LN_Last;
493 auto *DomNode = DT.getNode(PBranch->BranchBB);
494 if (DomNode) {
495 VD.DFSIn = DomNode->getDFSNumIn();
496 VD.DFSOut = DomNode->getDFSNumOut();
497 VD.PInfo = PossibleCopy;
498 VD.PhiOnly = true;
499 OrderedUses.push_back(VD);
500 }
501 } else {
502 // Otherwise, we are in the split block (even though we perform
503 // insertion in the branch block).
504 // Insert a possible copy at the split block and before the branch.
505 VD.LocalNum = LN_First;
506 auto *DomNode = DT.getNode(PBranch->SplitBB);
507 if (DomNode) {
508 VD.DFSIn = DomNode->getDFSNumIn();
509 VD.DFSOut = DomNode->getDFSNumOut();
510 VD.PInfo = PossibleCopy;
511 OrderedUses.push_back(VD);
512 }
513 }
514 }
471515 }
472516
473517 convertUsesToDFSOrdered(Op, OrderedUses);
491535 << VD.DFSOut << ")\n");
492536
493537 bool ShouldPush = (VD.Def || PossibleCopy);
494 bool OutOfScope = !stackIsInScope(RenameStack, VD.DFSIn, VD.DFSOut);
538 bool OutOfScope = !stackIsInScope(RenameStack, VD);
495539 if (OutOfScope || ShouldPush) {
496540 // Sync to our current scope.
497 popStackUntilDFSScope(RenameStack, VD.DFSIn, VD.DFSOut);
541 popStackUntilDFSScope(RenameStack, VD);
498542 ShouldPush |= (VD.Def || PossibleCopy);
499543 if (ShouldPush) {
500544 RenameStack.push_back(VD);
9797 ; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0
9898 ; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0
9999 ; CHECK-NEXT: [[Z:%.*]] = and i1 [[XZ]], [[YZ]]
100 ; CHECK: [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XZ]])
101 ; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
102 ; CHECK: [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[YZ]])
103 ; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
100104 ; CHECK-NEXT: br i1 [[Z]], label [[BOTH_ZERO:%.*]], label [[NOPE:%.*]]
101105 ; CHECK: both_zero:
102 ; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
103 ; CHECK: [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[YZ]])
104 ; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
105 ; CHECK: [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XZ]])
106106 ; CHECK-NEXT: call void @foo(i1 [[XZ_0]])
107107 ; CHECK-NEXT: call void @foo(i1 [[YZ_0]])
108108 ; CHECK-NEXT: call void @bar(i32 [[X_0]])
177177 define i1 @test5(i32 %x, i32 %y) {
178178 ; CHECK-LABEL: @test5(
179179 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
180 ; CHECK-NEXT: br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]]
181 ; CHECK: same:
180 ; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
181 ; CHECK: [[X_1:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
182182 ; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
183 ; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
183 ; CHECK: [[Y_1:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
184 ; CHECK-NEXT: br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]]
185 ; CHECK: same:
184186 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i32 [[X_0]], [[Y_0]]
185187 ; CHECK-NEXT: ret i1 [[CMP2]]
186188 ; CHECK: different:
187 ; CHECK: [[Y_1:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
188 ; CHECK: [[X_1:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
189189 ; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i32 [[X_1]], [[Y_1]]
190190 ; CHECK-NEXT: ret i1 [[CMP3]]
191191 ;
250250 define i1 @test7(i32 %x, i32 %y) {
251251 ; CHECK-LABEL: @test7(
252252 ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], [[Y:%.*]]
253 ; CHECK-NEXT: br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]]
254 ; CHECK: same:
253 ; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
254 ; CHECK: [[X_1:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
255255 ; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
256 ; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
256 ; CHECK: [[Y_1:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
257 ; CHECK-NEXT: br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]]
258 ; CHECK: same:
257259 ; CHECK-NEXT: [[CMP2:%.*]] = icmp sle i32 [[X_0]], [[Y_0]]
258260 ; CHECK-NEXT: ret i1 [[CMP2]]
259261 ; CHECK: different:
260 ; CHECK: [[Y_1:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
261 ; CHECK: [[X_1:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
262262 ; CHECK-NEXT: [[CMP3:%.*]] = icmp sgt i32 [[X_1]], [[Y_1]]
263263 ; CHECK-NEXT: ret i1 [[CMP3]]
264264 ;
277277 define i1 @test7_fp(float %x, float %y) {
278278 ; CHECK-LABEL: @test7_fp(
279279 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[X:%.*]], [[Y:%.*]]
280 ; CHECK-NEXT: br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]]
281 ; CHECK: same:
280 ; CHECK: [[X_0:%.*]] = call float @llvm.ssa.copy.f32(float [[X]])
281 ; CHECK: [[X_1:%.*]] = call float @llvm.ssa.copy.f32(float [[X]])
282282 ; CHECK: [[Y_0:%.*]] = call float @llvm.ssa.copy.f32(float [[Y]])
283 ; CHECK: [[X_0:%.*]] = call float @llvm.ssa.copy.f32(float [[X]])
283 ; CHECK: [[Y_1:%.*]] = call float @llvm.ssa.copy.f32(float [[Y]])
284 ; CHECK-NEXT: br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]]
285 ; CHECK: same:
284286 ; CHECK-NEXT: [[CMP2:%.*]] = fcmp ule float [[X_0]], [[Y_0]]
285287 ; CHECK-NEXT: ret i1 [[CMP2]]
286288 ; CHECK: different:
287 ; CHECK: [[Y_1:%.*]] = call float @llvm.ssa.copy.f32(float [[Y]])
288 ; CHECK: [[X_1:%.*]] = call float @llvm.ssa.copy.f32(float [[X]])
289289 ; CHECK-NEXT: [[CMP3:%.*]] = fcmp ogt float [[X_1]], [[Y_1]]
290290 ; CHECK-NEXT: ret i1 [[CMP3]]
291291 ;
350350 define i32 @test9(i32 %i, i32 %j) {
351351 ; CHECK-LABEL: @test9(
352352 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I:%.*]], [[J:%.*]]
353 ; CHECK: [[I_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[I]])
354 ; CHECK: [[J_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[J]])
353355 ; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[RET:%.*]]
354356 ; CHECK: cond_true:
355 ; CHECK: [[J_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[J]])
356 ; CHECK: [[I_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[I]])
357357 ; CHECK-NEXT: [[DIFF:%.*]] = sub i32 [[I_0]], [[J_0]]
358358 ; CHECK-NEXT: ret i32 [[DIFF]]
359359 ; CHECK: ret:
373373 define i32 @test10(i32 %j, i32 %i) {
374374 ; CHECK-LABEL: @test10(
375375 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I:%.*]], [[J:%.*]]
376 ; CHECK: [[I_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[I]])
377 ; CHECK: [[J_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[J]])
376378 ; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[RET:%.*]]
377379 ; CHECK: cond_true:
378 ; CHECK: [[J_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[J]])
379 ; CHECK: [[I_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[I]])
380380 ; CHECK-NEXT: [[DIFF:%.*]] = sub i32 [[I_0]], [[J_0]]
381381 ; CHECK-NEXT: ret i32 [[DIFF]]
382382 ; CHECK: ret:
400400 ; CHECK-NEXT: [[V0:%.*]] = call i32 @yogibar()
401401 ; CHECK-NEXT: [[V1:%.*]] = call i32 @yogibar()
402402 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[V0]], [[V1]]
403 ; CHECK: [[V0_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[V0]])
404 ; CHECK: [[V1_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[V1]])
403405 ; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[NEXT:%.*]]
404406 ; CHECK: cond_true:
405 ; CHECK: [[V1_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[V1]])
406407 ; CHECK-NEXT: ret i32 [[V1_0]]
407408 ; CHECK: next:
408 ; CHECK: [[V0_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[V0]])
409409 ; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[X:%.*]], [[V0_0]]
410 ; CHECK: [[V0_0_1:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[V0_0]])
410411 ; CHECK-NEXT: br i1 [[CMP2]], label [[COND_TRUE2:%.*]], label [[NEXT2:%.*]]
411412 ; CHECK: cond_true2:
412 ; CHECK: [[V0_0_1:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[V0_0]])
413413 ; CHECK-NEXT: ret i32 [[V0_0_1]]
414414 ; CHECK: next2:
415415 ; CHECK-NEXT: ret i32 0
436436 define i32 @test12(i32 %x) {
437437 ; CHECK-LABEL: @test12(
438438 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], 0
439 ; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
440 ; CHECK: [[X_1:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
439441 ; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
440442 ; CHECK: cond_true:
441 ; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
442443 ; CHECK-NEXT: br label [[RET:%.*]]
443444 ; CHECK: cond_false:
444 ; CHECK: [[X_1:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
445445 ; CHECK-NEXT: br label [[RET]]
446446 ; CHECK: ret:
447447 ; CHECK-NEXT: [[RES:%.*]] = phi i32 [ [[X_0]], [[COND_TRUE]] ], [ [[X_1]], [[COND_FALSE]] ]
0 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
1 ; RUN: opt -print-predicateinfo < %s 2>&1 | FileCheck %s
2 define i1 @f(i32 %x, i1 %y) {
3 ; CHECK-LABEL: @f(
4 ; CHECK-NEXT: br i1 [[Y:%.*]], label [[BB0:%.*]], label [[BB1:%.*]]
5 ; CHECK: bb0:
6 ; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[X:%.*]], 0
7 ; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
8 ; CHECK-NEXT: br i1 [[CMP]], label [[BB2:%.*]], label [[BB3:%.*]]
9 ; CHECK: bb1:
10 ; CHECK-NEXT: [[X2:%.*]] = add nuw nsw i32 [[X]], 1
11 ; CHECK-NEXT: [[CMP2:%.*]] = icmp sge i32 [[X2]], 2
12 ; CHECK: [[X2_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X2]])
13 ; CHECK-NEXT: br i1 [[CMP2]], label [[BB2]], label [[BB3]]
14 ; CHECK: bb2:
15 ; CHECK-NEXT: [[X3:%.*]] = phi i32 [ [[X_0]], [[BB0]] ], [ [[X2_0]], [[BB1]] ]
16 ; CHECK-NEXT: br label [[BB3]]
17 ; CHECK: bb3:
18 ; CHECK-NEXT: ret i1 false
19 ;
20 br i1 %y, label %bb0, label %bb1
21 bb0:
22 %cmp = icmp sge i32 %x, 0 ; x > 0
23 br i1 %cmp, label %bb2, label %bb3
24 bb1:
25 %x2 = add nsw nuw i32 %x, 1
26 %cmp2 = icmp sge i32 %x2, 2 ; x+1 > 2 / x > 1
27 br i1 %cmp2, label %bb2, label %bb3
28 bb2:
29 %x3 = phi i32 [ %x, %bb0 ], [ %x2, %bb1 ]
30 br label %bb3
31 bb3:
32 ret i1 0
33 }
34
35 define i1 @g(i32 %x, i1 %y) {
36 ; CHECK-LABEL: @g(
37 ; CHECK-NEXT: br i1 [[Y:%.*]], label [[BB0:%.*]], label [[BB1:%.*]]
38 ; CHECK: bb0:
39 ; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[X:%.*]], 0
40 ; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
41 ; CHECK-NEXT: br i1 [[CMP]], label [[BB3:%.*]], label [[BB2:%.*]]
42 ; CHECK: bb1:
43 ; CHECK-NEXT: [[X2:%.*]] = add nuw nsw i32 [[X]], 1
44 ; CHECK-NEXT: [[CMP2:%.*]] = icmp sge i32 [[X2]], 2
45 ; CHECK: [[X2_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X2]])
46 ; CHECK-NEXT: br i1 [[CMP2]], label [[BB3]], label [[BB2]]
47 ; CHECK: bb2:
48 ; CHECK-NEXT: [[X3:%.*]] = phi i32 [ [[X_0]], [[BB0]] ], [ [[X2_0]], [[BB1]] ]
49 ; CHECK-NEXT: br label [[BB3]]
50 ; CHECK: bb3:
51 ; CHECK-NEXT: ret i1 false
52 ;
53 br i1 %y, label %bb0, label %bb1
54 bb0:
55 %cmp = icmp sge i32 %x, 0 ; x > 0
56 br i1 %cmp, label %bb3, label %bb2
57 bb1:
58 %x2 = add nsw nuw i32 %x, 1
59 %cmp2 = icmp sge i32 %x2, 2 ; x+1 > 2 / x > 1
60 br i1 %cmp2, label %bb3, label %bb2
61 bb2:
62 %x3 = phi i32 [ %x, %bb0 ], [ %x2, %bb1 ]
63 br label %bb3
64 bb3:
65 ret i1 0
66 }
67
0 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
1 ; RUN: opt -print-predicateinfo -analyze < %s 2>&1 | FileCheck %s
2
3 define i32 @f1(i32 %x) {
4 ; CHECK-LABEL: @f1(
5 ; CHECK-NEXT: bb0:
6 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], 0
7 ; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
8 ; CHECK-NEXT: br i1 [[CMP]], label [[BB2:%.*]], label [[BB1:%.*]]
9 ; CHECK: bb1:
10 ; CHECK-NEXT: br label [[BB2]]
11 ; CHECK: bb2:
12 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[X_0]], [[BB0:%.*]] ], [ 0, [[BB1]] ]
13 ; CHECK-NEXT: [[FOO:%.*]] = add i32 [[COND]], [[X]]
14 ; CHECK-NEXT: ret i32 [[FOO]]
15 ;
16 bb0:
17 %cmp = icmp eq i32 %x, 0
18 br i1 %cmp, label %bb2, label %bb1
19 bb1:
20 br label %bb2
21 bb2:
22 %cond = phi i32 [ %x, %bb0 ], [ 0, %bb1 ]
23 %foo = add i32 %cond, %x
24 ret i32 %foo
25 }
26
27 define i32 @f2(i32 %x) {
28 ; CHECK-LABEL: @f2(
29 ; CHECK-NEXT: bb0:
30 ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[X:%.*]], 0
31 ; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
32 ; CHECK-NEXT: br i1 [[CMP]], label [[BB1:%.*]], label [[BB2:%.*]]
33 ; CHECK: bb1:
34 ; CHECK-NEXT: br label [[BB2]]
35 ; CHECK: bb2:
36 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[X_0]], [[BB0:%.*]] ], [ 0, [[BB1]] ]
37 ; CHECK-NEXT: [[FOO:%.*]] = add i32 [[COND]], [[X]]
38 ; CHECK-NEXT: ret i32 [[FOO]]
39 ;
40 bb0:
41 %cmp = icmp ne i32 %x, 0
42 br i1 %cmp, label %bb1, label %bb2
43 bb1:
44 br label %bb2
45 bb2:
46 %cond = phi i32 [ %x, %bb0 ], [ 0, %bb1 ]
47 %foo = add i32 %cond, %x
48 ret i32 %foo
49 }
50
51 define i32 @f3(i32 %x) {
52 ; CHECK-LABEL: @f3(
53 ; CHECK-NEXT: bb0:
54 ; CHECK-NEXT: switch i32 [[X:%.*]], label [[BB1:%.*]] [
55 ; CHECK-NEXT: i32 0, label [[BB2:%.*]]
56 ; CHECK-NEXT: ]
57 ; CHECK: bb1:
58 ; CHECK-NEXT: br label [[BB2]]
59 ; CHECK: bb2:
60 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[X]], [[BB0:%.*]] ], [ 0, [[BB1]] ]
61 ; CHECK-NEXT: [[FOO:%.*]] = add i32 [[COND]], [[X]]
62 ; CHECK-NEXT: ret i32 [[FOO]]
63 ;
64 bb0:
65 switch i32 %x, label %bb1 [ i32 0, label %bb2]
66 bb1:
67 br label %bb2
68 bb2:
69 %cond = phi i32 [ %x, %bb0 ], [ 0, %bb1 ]
70 %foo = add i32 %cond, %x
71 ret i32 %foo
72 }
73
74
75 define double @fcmp_oeq_not_zero(double %x, double %y) {
76 ; CHECK-LABEL: @fcmp_oeq_not_zero(
77 ; CHECK-NEXT: entry:
78 ; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double [[Y:%.*]], 2.000000e+00
79 ; CHECK: [[Y_0:%.*]] = call double @llvm.ssa.copy.f64(double [[Y]])
80 ; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[RETURN:%.*]]
81 ; CHECK: if:
82 ; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[X:%.*]], [[Y_0]]
83 ; CHECK-NEXT: br label [[RETURN]]
84 ; CHECK: return:
85 ; CHECK-NEXT: [[RETVAL:%.*]] = phi double [ [[DIV]], [[IF]] ], [ [[X]], [[ENTRY:%.*]] ]
86 ; CHECK-NEXT: ret double [[RETVAL]]
87 ;
88 entry:
89 %cmp = fcmp oeq double %y, 2.0
90 br i1 %cmp, label %if, label %return
91
92 if:
93 %div = fdiv double %x, %y
94 br label %return
95
96 return:
97 %retval = phi double [ %div, %if ], [ %x, %entry ]
98 ret double %retval
99
100 }
101
102 define double @fcmp_une_not_zero(double %x, double %y) {
103 ; CHECK-LABEL: @fcmp_une_not_zero(
104 ; CHECK-NEXT: entry:
105 ; CHECK-NEXT: [[CMP:%.*]] = fcmp une double [[Y:%.*]], 2.000000e+00
106 ; CHECK: [[Y_0:%.*]] = call double @llvm.ssa.copy.f64(double [[Y]])
107 ; CHECK-NEXT: br i1 [[CMP]], label [[RETURN:%.*]], label [[ELSE:%.*]]
108 ; CHECK: else:
109 ; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[X:%.*]], [[Y_0]]
110 ; CHECK-NEXT: br label [[RETURN]]
111 ; CHECK: return:
112 ; CHECK-NEXT: [[RETVAL:%.*]] = phi double [ [[DIV]], [[ELSE]] ], [ [[X]], [[ENTRY:%.*]] ]
113 ; CHECK-NEXT: ret double [[RETVAL]]
114 ;
115 entry:
116 %cmp = fcmp une double %y, 2.0
117 br i1 %cmp, label %return, label %else
118
119 else:
120 %div = fdiv double %x, %y
121 br label %return
122
123 return:
124 %retval = phi double [ %div, %else ], [ %x, %entry ]
125 ret double %retval
126
127 }
128
129 define double @fcmp_oeq_zero(double %x, double %y) {
130 ; CHECK-LABEL: @fcmp_oeq_zero(
131 ; CHECK-NEXT: entry:
132 ; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double [[Y:%.*]], 0.000000e+00
133 ; CHECK: [[Y_0:%.*]] = call double @llvm.ssa.copy.f64(double [[Y]])
134 ; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[RETURN:%.*]]
135 ; CHECK: if:
136 ; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[X:%.*]], [[Y_0]]
137 ; CHECK-NEXT: br label [[RETURN]]
138 ; CHECK: return:
139 ; CHECK-NEXT: [[RETVAL:%.*]] = phi double [ [[DIV]], [[IF]] ], [ [[X]], [[ENTRY:%.*]] ]
140 ; CHECK-NEXT: ret double [[RETVAL]]
141 ;
142 entry:
143 %cmp = fcmp oeq double %y, 0.0
144 br i1 %cmp, label %if, label %return
145
146 if:
147 %div = fdiv double %x, %y
148 br label %return
149
150 return:
151 %retval = phi double [ %div, %if ], [ %x, %entry ]
152 ret double %retval
153
154 }
155
156 define double @fcmp_une_zero(double %x, double %y) {
157 ; CHECK-LABEL: @fcmp_une_zero(
158 ; CHECK-NEXT: entry:
159 ; CHECK-NEXT: [[CMP:%.*]] = fcmp une double [[Y:%.*]], -0.000000e+00
160 ; CHECK: [[Y_0:%.*]] = call double @llvm.ssa.copy.f64(double [[Y]])
161 ; CHECK-NEXT: br i1 [[CMP]], label [[RETURN:%.*]], label [[ELSE:%.*]]
162 ; CHECK: else:
163 ; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[X:%.*]], [[Y_0]]
164 ; CHECK-NEXT: br label [[RETURN]]
165 ; CHECK: return:
166 ; CHECK-NEXT: [[RETVAL:%.*]] = phi double [ [[DIV]], [[ELSE]] ], [ [[X]], [[ENTRY:%.*]] ]
167 ; CHECK-NEXT: ret double [[RETVAL]]
168 ;
169 entry:
170 %cmp = fcmp une double %y, -0.0
171 br i1 %cmp, label %return, label %else
172
173 else:
174 %div = fdiv double %x, %y
175 br label %return
176
177 return:
178 %retval = phi double [ %div, %else ], [ %x, %entry ]
179 ret double %retval
180
181 }
182
183
184 define double @fcmp_oeq_maybe_zero(double %x, double %y, double %z1, double %z2) {
185 ; CHECK-LABEL: @fcmp_oeq_maybe_zero(
186 ; CHECK-NEXT: entry:
187 ; CHECK-NEXT: [[Z:%.*]] = fadd double [[Z1:%.*]], [[Z2:%.*]]
188 ; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double [[Y:%.*]], [[Z]]
189 ; CHECK: [[Z_0:%.*]] = call double @llvm.ssa.copy.f64(double [[Z]])
190 ; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[RETURN:%.*]]
191 ; CHECK: if:
192 ; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[X:%.*]], [[Z_0]]
193 ; CHECK-NEXT: br label [[RETURN]]
194 ; CHECK: return:
195 ; CHECK-NEXT: [[RETVAL:%.*]] = phi double [ [[DIV]], [[IF]] ], [ [[X]], [[ENTRY:%.*]] ]
196 ; CHECK-NEXT: ret double [[RETVAL]]
197 ;
198 entry:
199 %z = fadd double %z1, %z2
200 %cmp = fcmp oeq double %y, %z
201 br i1 %cmp, label %if, label %return
202
203 if:
204 %div = fdiv double %x, %z
205 br label %return
206
207 return:
208 %retval = phi double [ %div, %if ], [ %x, %entry ]
209 ret double %retval
210
211 }
212
213 define double @fcmp_une_maybe_zero(double %x, double %y, double %z1, double %z2) {
214 ; CHECK-LABEL: @fcmp_une_maybe_zero(
215 ; CHECK-NEXT: entry:
216 ; CHECK-NEXT: [[Z:%.*]] = fadd double [[Z1:%.*]], [[Z2:%.*]]
217 ; CHECK-NEXT: [[CMP:%.*]] = fcmp une double [[Y:%.*]], [[Z]]
218 ; CHECK: [[Z_0:%.*]] = call double @llvm.ssa.copy.f64(double [[Z]])
219 ; CHECK-NEXT: br i1 [[CMP]], label [[RETURN:%.*]], label [[ELSE:%.*]]
220 ; CHECK: else:
221 ; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[X:%.*]], [[Z_0]]
222 ; CHECK-NEXT: br label [[RETURN]]
223 ; CHECK: return:
224 ; CHECK-NEXT: [[RETVAL:%.*]] = phi double [ [[DIV]], [[ELSE]] ], [ [[X]], [[ENTRY:%.*]] ]
225 ; CHECK-NEXT: ret double [[RETVAL]]
226 ;
227 entry:
228 %z = fadd double %z1, %z2
229 %cmp = fcmp une double %y, %z
230 br i1 %cmp, label %return, label %else
231
232 else:
233 %div = fdiv double %x, %z
234 br label %return
235
236 return:
237 %retval = phi double [ %div, %else ], [ %x, %entry ]
238 ret double %retval
239
240 }
0 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
1 ; RUN: opt -print-predicateinfo -analyze < %s 2>&1 | FileCheck %s
1 ; RUN: opt -print-predicateinfo < %s 2>&1 | FileCheck %s
22
33 declare void @foo(i1)
44 declare void @bar(i32)
99 ; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0
1010 ; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0
1111 ; CHECK-NEXT: [[Z:%.*]] = or i1 [[XZ]], [[YZ]]
12 ; CHECK: [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XZ]])
13 ; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
14 ; CHECK: [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[YZ]])
15 ; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
1216 ; CHECK-NEXT: br i1 [[Z]], label [[ONEOF:%.*]], label [[NEITHER:%.*]]
1317 ; CHECK: oneof:
1418 ; CHECK-NEXT: call void @foo(i1 [[XZ]])
1721 ; CHECK-NEXT: call void @bar(i32 [[Y]])
1822 ; CHECK-NEXT: ret void
1923 ; CHECK: neither:
20 ; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
21 ; CHECK: [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[YZ]])
22 ; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
23 ; CHECK: [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XZ]])
2424 ; CHECK-NEXT: call void @foo(i1 [[XZ_0]])
2525 ; CHECK-NEXT: call void @foo(i1 [[YZ_0]])
2626 ; CHECK-NEXT: call void @bar(i32 [[X_0]])
5252 ; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0
5353 ; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0
5454 ; CHECK-NEXT: [[Z:%.*]] = and i1 [[XZ]], [[YZ]]
55 ; CHECK-NEXT: br i1 [[Z]], label [[BOTH:%.*]], label [[NOPE:%.*]]
56 ; CHECK: both:
55 ; CHECK: [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XZ]])
56 ; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
57 ; CHECK: [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[YZ]])
5758 ; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
58 ; CHECK: [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[YZ]])
59 ; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
60 ; CHECK: [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XZ]])
59 ; CHECK-NEXT: br i1 [[Z]], label [[BOTH:%.*]], label [[NOPE:%.*]]
60 ; CHECK: both:
6161 ; CHECK-NEXT: call void @foo(i1 [[XZ_0]])
6262 ; CHECK-NEXT: call void @foo(i1 [[YZ_0]])
6363 ; CHECK-NEXT: call void @bar(i32 [[X_0]])
9595 ; CHECK-NEXT: [[XGT:%.*]] = icmp sgt i32 [[X:%.*]], 0
9696 ; CHECK-NEXT: [[XLT:%.*]] = icmp slt i32 [[X]], 100
9797 ; CHECK-NEXT: [[Z:%.*]] = and i1 [[XGT]], [[XLT]]
98 ; CHECK-NEXT: br i1 [[Z]], label [[BOTH:%.*]], label [[NOPE:%.*]]
99 ; CHECK: both:
100 ; CHECK: [[XLT_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XLT]])
98 ; CHECK: [[XGT_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XGT]])
10199 ; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
102100 ; CHECK: [[X_0_1:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X_0]])
103 ; CHECK: [[XGT_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XGT]])
101 ; CHECK: [[XLT_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XLT]])
102 ; CHECK-NEXT: br i1 [[Z]], label [[BOTH:%.*]], label [[NOPE:%.*]]
103 ; CHECK: both:
104104 ; CHECK-NEXT: call void @foo(i1 [[XGT_0]])
105105 ; CHECK-NEXT: call void @foo(i1 [[XLT_0]])
106106 ; CHECK-NEXT: call void @bar(i32 [[X_0_1]])
137137 ; CHECK: [[TMP3:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[YZ]])
138138 ; CHECK: [[TMP4:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
139139 ; CHECK-NEXT: call void @llvm.assume(i1 [[Z]])
140 ; CHECK-NEXT: br i1 [[Z]], label [[BOTH:%.*]], label [[NOPE:%.*]]
141 ; CHECK: both:
140 ; CHECK: [[DOT0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[TMP1]])
141 ; CHECK: [[DOT01:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[TMP2]])
142 ; CHECK: [[DOT02:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[TMP3]])
142143 ; CHECK: [[DOT03:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[TMP4]])
143 ; CHECK: [[DOT02:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[TMP3]])
144 ; CHECK: [[DOT01:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[TMP2]])
145 ; CHECK: [[DOT0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[TMP1]])
144 ; CHECK-NEXT: br i1 [[Z]], label [[BOTH:%.*]], label [[NOPE:%.*]]
145 ; CHECK: both:
146146 ; CHECK-NEXT: call void @foo(i1 [[DOT0]])
147147 ; CHECK-NEXT: call void @foo(i1 [[DOT02]])
148148 ; CHECK-NEXT: call void @bar(i32 [[DOT01]])