mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
Fix a use-after-RAUW bug in large GEP splitting
Summary: Large GEP splitting, introduced in rL332015, uses a `DenseMap<AssertingVH<Value>, ...>`. This causes an assertion to fail (in debug builds) or undefined behaviour to occur (in release builds) when a value is RAUWed. This manifested itself in the 7zip benchmark from the llvm test suite built on ARM with `-fstrict-vtable-pointers` enabled while RAUWing invariant group launders and splits in CodeGenPrepare. This patch merges the large offsets of the argument and the result of an invariant.group strip/launder intrinsic before RAUWing. Reviewers: Prazek, javed.absar, haicheng, efriedma Reviewed By: Prazek, efriedma Subscribers: kristof.beyls, hiraditya, llvm-commits Differential Revision: https://reviews.llvm.org/D51936 llvm-svn: 344802
This commit is contained in:
parent
5a23f5e279
commit
c99c915bfa
@ -1721,11 +1721,22 @@ bool CodeGenPrepare::optimizeCallInst(CallInst *CI, bool &ModifiedDT) {
|
||||
return true;
|
||||
}
|
||||
case Intrinsic::launder_invariant_group:
|
||||
case Intrinsic::strip_invariant_group:
|
||||
II->replaceAllUsesWith(II->getArgOperand(0));
|
||||
case Intrinsic::strip_invariant_group: {
|
||||
Value *ArgVal = II->getArgOperand(0);
|
||||
auto it = LargeOffsetGEPMap.find(II);
|
||||
if (it != LargeOffsetGEPMap.end()) {
|
||||
// Merge entries in LargeOffsetGEPMap to reflect the RAUW.
|
||||
// Make sure not to have to deal with iterator invalidation
|
||||
// after possibly adding ArgVal to LargeOffsetGEPMap.
|
||||
auto GEPs = std::move(it->second);
|
||||
LargeOffsetGEPMap[ArgVal].append(GEPs.begin(), GEPs.end());
|
||||
LargeOffsetGEPMap.erase(II);
|
||||
}
|
||||
|
||||
II->replaceAllUsesWith(ArgVal);
|
||||
II->eraseFromParent();
|
||||
return true;
|
||||
|
||||
}
|
||||
case Intrinsic::cttz:
|
||||
case Intrinsic::ctlz:
|
||||
// If counting zeros is expensive, try to avoid it.
|
||||
|
@ -145,3 +145,31 @@ while_body:
|
||||
while_end:
|
||||
ret void
|
||||
}
|
||||
|
||||
declare i8* @llvm.strip.invariant.group.p0i8(i8*)
|
||||
|
||||
define void @test_invariant_group(i32) {
|
||||
; CHECK-LABEL: test_invariant_group
|
||||
br i1 undef, label %8, label %7
|
||||
|
||||
; <label>:2: ; preds = %8, %2
|
||||
br i1 undef, label %2, label %7
|
||||
|
||||
; <label>:3: ; preds = %8
|
||||
%4 = getelementptr inbounds i8, i8* %9, i32 40000
|
||||
%5 = bitcast i8* %4 to i64*
|
||||
br i1 undef, label %7, label %6
|
||||
|
||||
; <label>:6: ; preds = %3
|
||||
store i64 1, i64* %5, align 8
|
||||
br label %7
|
||||
|
||||
; <label>:7: ; preds = %6, %3, %2, %1
|
||||
ret void
|
||||
|
||||
; <label>:8: ; preds = %1
|
||||
%9 = call i8* @llvm.strip.invariant.group.p0i8(i8* nonnull undef)
|
||||
%10 = icmp eq i32 %0, 0
|
||||
br i1 %10, label %3, label %2
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user