llvm.org GIT mirror llvm / 9cc1222
[PredicateInfo] Fix non-determinism in codegen uncovered by reverse iterating SmallPtrSet Summary: Sort OpsToRename before iterating to make iteration order deterministic. Thanks to Daniel Berlin for the sorting logic. Reviewers: dberlin, RKSimon, efriedma, davide Reviewed By: dberlin, davide Subscribers: sanjoy, davide, llvm-commits Differential Revision: https://reviews.llvm.org/D33265 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@304447 91177308-0d34-0410-b5e6-96231b3b80d8 Mandeep Singh Grang 2 years ago
3 changed file(s) with 52 addition(s) and 17 deletion(s). Raw diff Collapse all Expand all
540540 //
541541 // TODO: Use this algorithm to perform fast single-variable renaming in
542542 // promotememtoreg and memoryssa.
543 void PredicateInfo::renameUses(SmallPtrSetImpl &OpsToRename) {
543 void PredicateInfo::renameUses(SmallPtrSetImpl &OpSet) {
544 // Sort OpsToRename since we are going to iterate it.
545 SmallVector OpsToRename(OpSet.begin(), OpSet.end());
546 std::sort(OpsToRename.begin(), OpsToRename.end(), [&](const Value *A,
547 const Value *B) {
548 auto *ArgA = dyn_cast_or_null(A);
549 auto *ArgB = dyn_cast_or_null(B);
550
551 // If A and B are args, order them based on their arg no.
552 if (ArgA && !ArgB)
553 return true;
554 if (ArgB && !ArgA)
555 return false;
556 if (ArgA && ArgB)
557 return ArgA->getArgNo() < ArgB->getArgNo();
558
559 // Else, A are B are instructions.
560 // If they belong to different BBs, order them by the dominance of BBs.
561 auto *AInst = cast(A);
562 auto *BInst = cast(B);
563 if (AInst->getParent() != BInst->getParent())
564 return DT.dominates(AInst->getParent(), BInst->getParent());
565
566 // Else, A and B belong to the same BB.
567 // Order A and B by their dominance.
568 auto *BB = AInst->getParent();
569 auto LookupResult = OBBMap.find(BB);
570 if (LookupResult != OBBMap.end())
571 return LookupResult->second->dominates(AInst, BInst);
572
573 auto Result = OBBMap.insert({BB, make_unique(BB)});
574 return Result.first->second->dominates(AInst, BInst);
575 });
576
544577 ValueDFS_Compare Compare(OBBMap);
545578 // Compute liveness, and rename in O(uses) per Op.
546579 for (auto *Op : OpsToRename) {
0 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
11 ; RUN: opt -print-predicateinfo -analyze < %s 2>&1 | FileCheck %s
2 ; RUN: opt -print-predicateinfo -analyze -reverse-iterate < %s 2>&1 | FileCheck %s
23
34 @a = external global i32 ; [#uses=7]
45
9798 ; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0
9899 ; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0
99100 ; CHECK-NEXT: [[Z:%.*]] = and i1 [[XZ]], [[YZ]]
101 ; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
102 ; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
100103 ; CHECK: [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XZ]])
101 ; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
102104 ; CHECK: [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[YZ]])
103 ; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
104105 ; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[Z]])
105106 ; CHECK-NEXT: br i1 [[Z]], label [[BOTH_ZERO:%.*]], label [[NOPE:%.*]]
106107 ; CHECK: both_zero:
381382 define i32 @test10(i32 %j, i32 %i) {
382383 ; CHECK-LABEL: @test10(
383384 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I:%.*]], [[J:%.*]]
385 ; CHECK: [[J_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[J]])
384386 ; CHECK: [[I_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[I]])
385 ; CHECK: [[J_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[J]])
386387 ; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[RET:%.*]]
387388 ; CHECK: cond_true:
388389 ; CHECK-NEXT: [[DIFF:%.*]] = sub i32 [[I_0]], [[J_0]]
0 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
11 ; RUN: opt -print-predicateinfo < %s 2>&1 | FileCheck %s
2 ; RUN: opt -print-predicateinfo -reverse-iterate < %s 2>&1 | FileCheck %s
23
34 declare void @foo(i1)
45 declare void @bar(i32)
910 ; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0
1011 ; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0
1112 ; CHECK-NEXT: [[Z:%.*]] = or i1 [[XZ]], [[YZ]]
13 ; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
14 ; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
1215 ; CHECK: [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XZ]])
13 ; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
1416 ; CHECK: [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[YZ]])
15 ; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
1617 ; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[Z]])
1718 ; CHECK-NEXT: br i1 [[Z]], label [[ONEOF:%.*]], label [[NEITHER:%.*]]
1819 ; CHECK: oneof:
5354 ; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0
5455 ; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0
5556 ; CHECK-NEXT: [[Z:%.*]] = and i1 [[XZ]], [[YZ]]
57 ; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
58 ; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
5659 ; CHECK: [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XZ]])
57 ; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
5860 ; CHECK: [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[YZ]])
59 ; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
6061 ; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[Z]])
6162 ; CHECK-NEXT: br i1 [[Z]], label [[BOTH:%.*]], label [[NOPE:%.*]]
6263 ; CHECK: both:
9798 ; CHECK-NEXT: [[XGT:%.*]] = icmp sgt i32 [[X:%.*]], 0
9899 ; CHECK-NEXT: [[XLT:%.*]] = icmp slt i32 [[X]], 100
99100 ; CHECK-NEXT: [[Z:%.*]] = and i1 [[XGT]], [[XLT]]
100 ; CHECK: [[XGT_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XGT]])
101101 ; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
102102 ; 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]])
103104 ; CHECK: [[XLT_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XLT]])
104105 ; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[Z]])
105106 ; CHECK-NEXT: br i1 [[Z]], label [[BOTH:%.*]], label [[NOPE:%.*]]
135136 ; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0
136137 ; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0
137138 ; CHECK-NEXT: [[Z:%.*]] = and i1 [[XZ]], [[YZ]]
138 ; CHECK: [[TMP1:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XZ]])
139 ; CHECK: [[TMP2:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
140 ; CHECK: [[TMP3:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[YZ]])
141 ; CHECK: [[TMP4:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
139 ; CHECK: [[TMP1:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
140 ; CHECK: [[TMP2:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
141 ; CHECK: [[TMP3:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XZ]])
142 ; CHECK: [[TMP4:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[YZ]])
142143 ; CHECK: [[TMP5:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[Z]])
143144 ; CHECK-NEXT: call void @llvm.assume(i1 [[TMP5]])
144 ; CHECK: [[DOT0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[TMP1]])
145 ; CHECK: [[DOT0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[TMP1]])
145146 ; CHECK: [[DOT01:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[TMP2]])
146147 ; CHECK: [[DOT02:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[TMP3]])
147 ; CHECK: [[DOT03:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[TMP4]])
148 ; CHECK: [[DOT03:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[TMP4]])
148149 ; CHECK: [[DOT04:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[TMP5]])
149150 ; CHECK-NEXT: br i1 [[TMP5]], label [[BOTH:%.*]], label [[NOPE:%.*]]
150151 ; CHECK: both:
151 ; CHECK-NEXT: call void @foo(i1 [[DOT0]])
152152 ; CHECK-NEXT: call void @foo(i1 [[DOT02]])
153 ; CHECK-NEXT: call void @foo(i1 [[DOT03]])
154 ; CHECK-NEXT: call void @bar(i32 [[DOT0]])
153155 ; CHECK-NEXT: call void @bar(i32 [[DOT01]])
154 ; CHECK-NEXT: call void @bar(i32 [[DOT03]])
155156 ; CHECK-NEXT: ret void
156157 ; CHECK: nope:
157158 ; CHECK-NEXT: call void @foo(i1 [[DOT04]])