Skip to content

Commit d1f4d6a

Browse files
wmi-11tstellar
authored andcommitted
Merging r370547:
------------------------------------------------------------------------ r370547 | wmi | 2019-08-30 16:01:22 -0700 (Fri, 30 Aug 2019) | 24 lines [GVN] Verify value equality before doing phi translation for call instruction This is an updated version of https://reviews.llvm.org/D66909 to fix PR42605. Basically, current phi translatation translates an old value number to an new value number for a call instruction based on the literal equality of call expression, without verifying there is no clobber in between. This is incorrect. To get a finegrain check, use MachineDependence analysis to do the job. However, this is still not ideal. Although given a call instruction, `MemoryDependenceResults::getCallDependencyFrom` returns identical call instructions without clobber in between using MemDepResult with its DepType to be `Def`. However, identical is too strict here and we want it to be relaxed a little to consider phi-translation -- callee is the same, param operands can be different. That means changing the semantic of `MemDepResult::Def` and I don't know the potential impact. So currently the patch is still conservative to only handle MemDepResult::NonFuncLocal, which means the current call has no function local clobber. If there is clobber, even if the clobber doesn't stand in between the current call and the call with the new value, we won't do phi-translate. Differential Revision: https://reviews.llvm.org/D67013 ------------------------------------------------------------------------
1 parent e5b2493 commit d1f4d6a

File tree

3 files changed

+128
-1
lines changed

3 files changed

+128
-1
lines changed

llvm/include/llvm/Transforms/Scalar/GVN.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ class GVN : public PassInfoMixin<GVN> {
120120
uint32_t lookupOrAddCall(CallInst *C);
121121
uint32_t phiTranslateImpl(const BasicBlock *BB, const BasicBlock *PhiBlock,
122122
uint32_t Num, GVN &Gvn);
123+
bool areCallValsEqual(uint32_t Num, uint32_t NewNum, const BasicBlock *Pred,
124+
const BasicBlock *PhiBlock, GVN &Gvn);
123125
std::pair<uint32_t, bool> assignExpNewValueNum(Expression &exp);
124126
bool areAllValsInBB(uint32_t num, const BasicBlock *BB, GVN &Gvn);
125127

llvm/lib/Transforms/Scalar/GVN.cpp

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1522,6 +1522,41 @@ uint32_t GVN::ValueTable::phiTranslate(const BasicBlock *Pred,
15221522
return NewNum;
15231523
}
15241524

1525+
// Return true if the value number \p Num and NewNum have equal value.
1526+
// Return false if the result is unknown.
1527+
bool GVN::ValueTable::areCallValsEqual(uint32_t Num, uint32_t NewNum,
1528+
const BasicBlock *Pred,
1529+
const BasicBlock *PhiBlock, GVN &Gvn) {
1530+
CallInst *Call = nullptr;
1531+
LeaderTableEntry *Vals = &Gvn.LeaderTable[Num];
1532+
while (Vals) {
1533+
Call = dyn_cast<CallInst>(Vals->Val);
1534+
if (Call && Call->getParent() == PhiBlock)
1535+
break;
1536+
Vals = Vals->Next;
1537+
}
1538+
1539+
if (AA->doesNotAccessMemory(Call))
1540+
return true;
1541+
1542+
if (!MD || !AA->onlyReadsMemory(Call))
1543+
return false;
1544+
1545+
MemDepResult local_dep = MD->getDependency(Call);
1546+
if (!local_dep.isNonLocal())
1547+
return false;
1548+
1549+
const MemoryDependenceResults::NonLocalDepInfo &deps =
1550+
MD->getNonLocalCallDependency(Call);
1551+
1552+
// Check to see if the Call has no function local clobber.
1553+
for (unsigned i = 0; i < deps.size(); i++) {
1554+
if (deps[i].getResult().isNonFuncLocal())
1555+
return true;
1556+
}
1557+
return false;
1558+
}
1559+
15251560
/// Translate value number \p Num using phis, so that it has the values of
15261561
/// the phis in BB.
15271562
uint32_t GVN::ValueTable::phiTranslateImpl(const BasicBlock *Pred,
@@ -1568,8 +1603,11 @@ uint32_t GVN::ValueTable::phiTranslateImpl(const BasicBlock *Pred,
15681603
}
15691604
}
15701605

1571-
if (uint32_t NewNum = expressionNumbering[Exp])
1606+
if (uint32_t NewNum = expressionNumbering[Exp]) {
1607+
if (Exp.opcode == Instruction::Call && NewNum != Num)
1608+
return areCallValsEqual(Num, NewNum, Pred, PhiBlock, Gvn) ? NewNum : Num;
15721609
return NewNum;
1610+
}
15731611
return Num;
15741612
}
15751613

llvm/test/Transforms/GVN/pr42605.ll

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
; RUN: opt -gvn %s -S | FileCheck %s
2+
; PR42605. Check phi-translate won't translate the value number of a call
3+
; to the value of another call with clobber in between.
4+
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
5+
target triple = "x86_64-unknown-linux-gnu"
6+
7+
@global = dso_local local_unnamed_addr global i32 0, align 4
8+
@.str = private unnamed_addr constant [8 x i8] c"%d, %d\0A\00", align 1
9+
10+
; Function Attrs: nofree nounwind
11+
declare dso_local i32 @printf(i8* nocapture readonly, ...) local_unnamed_addr
12+
13+
; Function Attrs: noinline norecurse nounwind readonly uwtable
14+
define dso_local i32 @_Z3gooi(i32 %i) local_unnamed_addr #0 {
15+
entry:
16+
%t0 = load i32, i32* @global, align 4, !tbaa !2
17+
%add = add nsw i32 %t0, %i
18+
ret i32 %add
19+
}
20+
21+
; Function Attrs: nofree nounwind uwtable
22+
define dso_local void @noclobber() local_unnamed_addr {
23+
entry:
24+
%call = tail call i32 @_Z3gooi(i32 2)
25+
%add = add nsw i32 %call, 5
26+
%cmp = icmp sgt i32 %add, 2
27+
br i1 %cmp, label %if.then, label %if.end
28+
29+
if.then: ; preds = %entry
30+
%call1 = tail call i32 @_Z3gooi(i32 3)
31+
%add2 = add nsw i32 %call1, 5
32+
br label %if.end
33+
34+
; Check pre happens after phitranslate.
35+
; CHECK-LABEL: @noclobber
36+
; CHECK: %add4.pre-phi = phi i32 [ %add2, %if.then ], [ %add, %entry ]
37+
; CHECK: printf(i8* getelementptr inbounds {{.*}}, i32 %add4.pre-phi)
38+
39+
if.end: ; preds = %if.then, %entry
40+
%i.0 = phi i32 [ 3, %if.then ], [ 2, %entry ]
41+
%global2.0 = phi i32 [ %add2, %if.then ], [ %add, %entry ]
42+
%call3 = tail call i32 @_Z3gooi(i32 %i.0)
43+
%add4 = add nsw i32 %call3, 5
44+
%call5 = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i64 0, i64 0), i32 %global2.0, i32 %add4)
45+
ret void
46+
}
47+
48+
; Function Attrs: nofree nounwind uwtable
49+
define dso_local void @hasclobber() local_unnamed_addr {
50+
entry:
51+
%call = tail call i32 @_Z3gooi(i32 2)
52+
%add = add nsw i32 %call, 5
53+
%cmp = icmp sgt i32 %add, 2
54+
br i1 %cmp, label %if.then, label %if.end
55+
56+
if.then: ; preds = %entry
57+
%call1 = tail call i32 @_Z3gooi(i32 3)
58+
%add2 = add nsw i32 %call1, 5
59+
br label %if.end
60+
61+
; Check no pre happens.
62+
; CHECK-LABEL: @hasclobber
63+
; CHECK: %call3 = tail call i32 @_Z3gooi(i32 %i.0)
64+
; CHECK-NEXT: %add4 = add nsw i32 %call3, 5
65+
; CHECK-NEXT: printf(i8* getelementptr inbounds ({{.*}}, i32 %global2.0, i32 %add4)
66+
67+
if.end: ; preds = %if.then, %entry
68+
%i.0 = phi i32 [ 3, %if.then ], [ 2, %entry ]
69+
%global2.0 = phi i32 [ %add2, %if.then ], [ %add, %entry ]
70+
store i32 5, i32* @global, align 4, !tbaa !2
71+
%call3 = tail call i32 @_Z3gooi(i32 %i.0)
72+
%add4 = add nsw i32 %call3, 5
73+
%call5 = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i64 0, i64 0), i32 %global2.0, i32 %add4)
74+
ret void
75+
}
76+
77+
attributes #0 = { noinline norecurse nounwind readonly uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
78+
79+
!llvm.module.flags = !{!0}
80+
!llvm.ident = !{!1}
81+
82+
!0 = !{i32 1, !"wchar_size", i32 4}
83+
!1 = !{!"clang version 10.0.0 (trunk 369798)"}
84+
!2 = !{!3, !3, i64 0}
85+
!3 = !{!"int", !4, i64 0}
86+
!4 = !{!"omnipotent char", !5, i64 0}
87+
!5 = !{!"Simple C++ TBAA"}

0 commit comments

Comments
 (0)