mirror of
https://github.com/RPCSX/llvm.git
synced 2025-02-26 16:05:54 +00:00
[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
This commit is contained in:
parent
ad988ad98b
commit
9cc122269f
@ -541,7 +541,40 @@ Value *PredicateInfo::materializeStack(unsigned int &Counter,
|
||||
//
|
||||
// TODO: Use this algorithm to perform fast single-variable renaming in
|
||||
// promotememtoreg and memoryssa.
|
||||
void PredicateInfo::renameUses(SmallPtrSetImpl<Value *> &OpsToRename) {
|
||||
void PredicateInfo::renameUses(SmallPtrSetImpl<Value *> &OpSet) {
|
||||
// Sort OpsToRename since we are going to iterate it.
|
||||
SmallVector<Value *, 8> OpsToRename(OpSet.begin(), OpSet.end());
|
||||
std::sort(OpsToRename.begin(), OpsToRename.end(), [&](const Value *A,
|
||||
const Value *B) {
|
||||
auto *ArgA = dyn_cast_or_null<Argument>(A);
|
||||
auto *ArgB = dyn_cast_or_null<Argument>(B);
|
||||
|
||||
// If A and B are args, order them based on their arg no.
|
||||
if (ArgA && !ArgB)
|
||||
return true;
|
||||
if (ArgB && !ArgA)
|
||||
return false;
|
||||
if (ArgA && ArgB)
|
||||
return ArgA->getArgNo() < ArgB->getArgNo();
|
||||
|
||||
// Else, A are B are instructions.
|
||||
// If they belong to different BBs, order them by the dominance of BBs.
|
||||
auto *AInst = cast<Instruction>(A);
|
||||
auto *BInst = cast<Instruction>(B);
|
||||
if (AInst->getParent() != BInst->getParent())
|
||||
return DT.dominates(AInst->getParent(), BInst->getParent());
|
||||
|
||||
// Else, A and B belong to the same BB.
|
||||
// Order A and B by their dominance.
|
||||
auto *BB = AInst->getParent();
|
||||
auto LookupResult = OBBMap.find(BB);
|
||||
if (LookupResult != OBBMap.end())
|
||||
return LookupResult->second->dominates(AInst, BInst);
|
||||
|
||||
auto Result = OBBMap.insert({BB, make_unique<OrderedBasicBlock>(BB)});
|
||||
return Result.first->second->dominates(AInst, BInst);
|
||||
});
|
||||
|
||||
ValueDFS_Compare Compare(OBBMap);
|
||||
// Compute liveness, and rename in O(uses) per Op.
|
||||
for (auto *Op : OpsToRename) {
|
||||
|
@ -1,5 +1,6 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt -print-predicateinfo -analyze < %s 2>&1 | FileCheck %s
|
||||
; RUN: opt -print-predicateinfo -analyze -reverse-iterate < %s 2>&1 | FileCheck %s
|
||||
|
||||
@a = external global i32 ; <i32*> [#uses=7]
|
||||
|
||||
@ -98,10 +99,10 @@ define void @test3(i32 %x, i32 %y) {
|
||||
; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0
|
||||
; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0
|
||||
; CHECK-NEXT: [[Z:%.*]] = and i1 [[XZ]], [[YZ]]
|
||||
; CHECK: [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XZ]])
|
||||
; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
|
||||
; CHECK: [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[YZ]])
|
||||
; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
|
||||
; CHECK: [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XZ]])
|
||||
; CHECK: [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[YZ]])
|
||||
; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[Z]])
|
||||
; CHECK-NEXT: br i1 [[Z]], label [[BOTH_ZERO:%.*]], label [[NOPE:%.*]]
|
||||
; CHECK: both_zero:
|
||||
@ -382,8 +383,8 @@ ret:
|
||||
define i32 @test10(i32 %j, i32 %i) {
|
||||
; CHECK-LABEL: @test10(
|
||||
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I:%.*]], [[J:%.*]]
|
||||
; CHECK: [[I_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[I]])
|
||||
; CHECK: [[J_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[J]])
|
||||
; CHECK: [[I_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[I]])
|
||||
; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[RET:%.*]]
|
||||
; CHECK: cond_true:
|
||||
; CHECK-NEXT: [[DIFF:%.*]] = sub i32 [[I_0]], [[J_0]]
|
||||
|
@ -1,5 +1,6 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt -print-predicateinfo < %s 2>&1 | FileCheck %s
|
||||
; RUN: opt -print-predicateinfo -reverse-iterate < %s 2>&1 | FileCheck %s
|
||||
|
||||
declare void @foo(i1)
|
||||
declare void @bar(i32)
|
||||
@ -10,10 +11,10 @@ define void @testor(i32 %x, i32 %y) {
|
||||
; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0
|
||||
; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0
|
||||
; CHECK-NEXT: [[Z:%.*]] = or i1 [[XZ]], [[YZ]]
|
||||
; CHECK: [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XZ]])
|
||||
; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
|
||||
; CHECK: [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[YZ]])
|
||||
; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
|
||||
; CHECK: [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XZ]])
|
||||
; CHECK: [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[YZ]])
|
||||
; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[Z]])
|
||||
; CHECK-NEXT: br i1 [[Z]], label [[ONEOF:%.*]], label [[NEITHER:%.*]]
|
||||
; CHECK: oneof:
|
||||
@ -54,10 +55,10 @@ define void @testand(i32 %x, i32 %y) {
|
||||
; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0
|
||||
; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0
|
||||
; CHECK-NEXT: [[Z:%.*]] = and i1 [[XZ]], [[YZ]]
|
||||
; CHECK: [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XZ]])
|
||||
; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
|
||||
; CHECK: [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[YZ]])
|
||||
; CHECK: [[Y_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
|
||||
; CHECK: [[XZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XZ]])
|
||||
; CHECK: [[YZ_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[YZ]])
|
||||
; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[Z]])
|
||||
; CHECK-NEXT: br i1 [[Z]], label [[BOTH:%.*]], label [[NOPE:%.*]]
|
||||
; CHECK: both:
|
||||
@ -98,9 +99,9 @@ define void @testandsame(i32 %x, i32 %y) {
|
||||
; CHECK-NEXT: [[XGT:%.*]] = icmp sgt i32 [[X:%.*]], 0
|
||||
; CHECK-NEXT: [[XLT:%.*]] = icmp slt i32 [[X]], 100
|
||||
; CHECK-NEXT: [[Z:%.*]] = and i1 [[XGT]], [[XLT]]
|
||||
; CHECK: [[XGT_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XGT]])
|
||||
; CHECK: [[X_0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
|
||||
; CHECK: [[X_0_1:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X_0]])
|
||||
; CHECK: [[XGT_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XGT]])
|
||||
; CHECK: [[XLT_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XLT]])
|
||||
; CHECK: [[Z_0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[Z]])
|
||||
; CHECK-NEXT: br i1 [[Z]], label [[BOTH:%.*]], label [[NOPE:%.*]]
|
||||
@ -136,23 +137,23 @@ define void @testandassume(i32 %x, i32 %y) {
|
||||
; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0
|
||||
; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0
|
||||
; CHECK-NEXT: [[Z:%.*]] = and i1 [[XZ]], [[YZ]]
|
||||
; CHECK: [[TMP1:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XZ]])
|
||||
; CHECK: [[TMP2:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
|
||||
; CHECK: [[TMP3:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[YZ]])
|
||||
; CHECK: [[TMP4:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
|
||||
; CHECK: [[TMP1:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[X]])
|
||||
; CHECK: [[TMP2:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[Y]])
|
||||
; CHECK: [[TMP3:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[XZ]])
|
||||
; CHECK: [[TMP4:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[YZ]])
|
||||
; CHECK: [[TMP5:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[Z]])
|
||||
; CHECK-NEXT: call void @llvm.assume(i1 [[TMP5]])
|
||||
; CHECK: [[DOT0:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[TMP1]])
|
||||
; CHECK: [[DOT0:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[TMP1]])
|
||||
; CHECK: [[DOT01:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[TMP2]])
|
||||
; CHECK: [[DOT02:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[TMP3]])
|
||||
; CHECK: [[DOT03:%.*]] = call i32 @llvm.ssa.copy.i32(i32 [[TMP4]])
|
||||
; CHECK: [[DOT03:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[TMP4]])
|
||||
; CHECK: [[DOT04:%.*]] = call i1 @llvm.ssa.copy.i1(i1 [[TMP5]])
|
||||
; CHECK-NEXT: br i1 [[TMP5]], label [[BOTH:%.*]], label [[NOPE:%.*]]
|
||||
; CHECK: both:
|
||||
; CHECK-NEXT: call void @foo(i1 [[DOT0]])
|
||||
; CHECK-NEXT: call void @foo(i1 [[DOT02]])
|
||||
; CHECK-NEXT: call void @foo(i1 [[DOT03]])
|
||||
; CHECK-NEXT: call void @bar(i32 [[DOT0]])
|
||||
; CHECK-NEXT: call void @bar(i32 [[DOT01]])
|
||||
; CHECK-NEXT: call void @bar(i32 [[DOT03]])
|
||||
; CHECK-NEXT: ret void
|
||||
; CHECK: nope:
|
||||
; CHECK-NEXT: call void @foo(i1 [[DOT04]])
|
||||
|
Loading…
x
Reference in New Issue
Block a user