Skip to content

Commit

Permalink
Fix a use-after-RAUW bug in large GEP splitting
Browse files Browse the repository at this point in the history
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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@344802 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
amharc committed Oct 19, 2018
1 parent 9e79a4f commit 4806c82
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 3 deletions.
17 changes: 14 additions & 3 deletions lib/CodeGen/CodeGenPrepare.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
28 changes: 28 additions & 0 deletions test/Transforms/CodeGenPrepare/AArch64/large-offset-gep.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

0 comments on commit 4806c82

Please sign in to comment.