diff options
| author | Krzysztof Pszeniczny <krzysztof.pszeniczny@gmail.com> | 2018-10-19 19:02:16 +0000 |
|---|---|---|
| committer | Krzysztof Pszeniczny <krzysztof.pszeniczny@gmail.com> | 2018-10-19 19:02:16 +0000 |
| commit | 2bfe759a8d7f4e544ac0f079d447f33c0b4dcf9c (patch) | |
| tree | 67b55e22e6a7f0754d8f43626ed25679dddf4488 | |
| parent | b3d203ff7f308cc5675f095654d0cda905bf95bf (diff) | |
| download | bcm5719-llvm-2bfe759a8d7f4e544ac0f079d447f33c0b4dcf9c.tar.gz bcm5719-llvm-2bfe759a8d7f4e544ac0f079d447f33c0b4dcf9c.zip | |
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
| -rw-r--r-- | llvm/lib/CodeGen/CodeGenPrepare.cpp | 17 | ||||
| -rw-r--r-- | llvm/test/Transforms/CodeGenPrepare/AArch64/large-offset-gep.ll | 28 |
2 files changed, 42 insertions, 3 deletions
diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp index dfbfae85a86..fa5cc4dc969 100644 --- a/llvm/lib/CodeGen/CodeGenPrepare.cpp +++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp @@ -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. diff --git a/llvm/test/Transforms/CodeGenPrepare/AArch64/large-offset-gep.ll b/llvm/test/Transforms/CodeGenPrepare/AArch64/large-offset-gep.ll index a5878e00e03..5cc00b75962 100644 --- a/llvm/test/Transforms/CodeGenPrepare/AArch64/large-offset-gep.ll +++ b/llvm/test/Transforms/CodeGenPrepare/AArch64/large-offset-gep.ll @@ -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 +} + |

