diff options
author | Jann Horn <jannh@google.com> | 2021-03-04 14:39:21 +0100 |
---|---|---|
committer | Benjamin Kramer <benny.kra@googlemail.com> | 2021-03-04 14:48:26 +0100 |
commit | 91c9dee3fb6d89ab3315fac1c1419614d6874b99 (patch) | |
tree | e7516242e17bc3bb7a6ebdaac4b184a8512f50d8 /llvm/lib/CodeGen/CodeGenPrepare.cpp | |
parent | bf3ac994c4d526b74044a977176e8e07d83f2049 (diff) | |
download | llvm-91c9dee3fb6d89ab3315fac1c1419614d6874b99.zip llvm-91c9dee3fb6d89ab3315fac1c1419614d6874b99.tar.gz llvm-91c9dee3fb6d89ab3315fac1c1419614d6874b99.tar.bz2 |
[CodeGenPrepare] Eliminate llvm.expect before removing empty blocks
CodeGenPrepare currently first removes empty blocks, then in a loop
performs other optimizations. One of those optimizations is the removal
of call instructions that invoke @llvm.assume, which can create new
empty blocks.
This means that when a branch only contains a call to __builtin_assume(),
the empty branch will survive into MIR, and will then only be
half-removed by MIR-level optimizations (e.g. removing the branch but
leaving the condition intact).
Fix it by eliminating @llvm.expect builtin calls before removing empty
blocks.
Reviewed By: bkramer
Differential Revision: https://reviews.llvm.org/D97848
Diffstat (limited to 'llvm/lib/CodeGen/CodeGenPrepare.cpp')
-rw-r--r-- | llvm/lib/CodeGen/CodeGenPrepare.cpp | 42 |
1 files changed, 30 insertions, 12 deletions
diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp index 5d6c8ec..a7e1aef 100644 --- a/llvm/lib/CodeGen/CodeGenPrepare.cpp +++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp @@ -377,6 +377,7 @@ class TypePromotionTransaction; } void removeAllAssertingVHReferences(Value *V); + bool eliminateAssumptions(Function &F); bool eliminateFallThrough(Function &F); bool eliminateMostlyEmptyBlocks(Function &F); BasicBlock *findDestBlockOfMergeableEmptyBlock(BasicBlock *BB); @@ -506,6 +507,11 @@ bool CodeGenPrepare::runOnFunction(Function &F) { } } + // Get rid of @llvm.assume builtins before attempting to eliminate empty + // blocks, since there might be blocks that only contain @llvm.assume calls + // (plus arguments that we can get rid of). + EverMadeChange |= eliminateAssumptions(F); + // Eliminate blocks that contain only PHI nodes and an // unconditional branch. EverMadeChange |= eliminateMostlyEmptyBlocks(F); @@ -614,6 +620,28 @@ bool CodeGenPrepare::runOnFunction(Function &F) { return EverMadeChange; } +bool CodeGenPrepare::eliminateAssumptions(Function &F) { + bool MadeChange = false; + for (BasicBlock &BB : F) { + CurInstIterator = BB.begin(); + while (CurInstIterator != BB.end()) { + Instruction *I = &*(CurInstIterator++); + if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) { + if (II->getIntrinsicID() != Intrinsic::assume) + continue; + MadeChange = true; + Value *Operand = II->getOperand(0); + II->eraseFromParent(); + + resetIteratorIfInvalidatedWhileCalling(&BB, [&]() { + RecursivelyDeleteTriviallyDeadInstructions(Operand, TLInfo, nullptr); + }); + } + } + } + return MadeChange; +} + /// An instruction is about to be deleted, so remove all references to it in our /// GEP-tracking data strcutures. void CodeGenPrepare::removeAllAssertingVHReferences(Value *V) { @@ -2118,18 +2146,8 @@ bool CodeGenPrepare::optimizeCallInst(CallInst *CI, bool &ModifiedDT) { if (II) { switch (II->getIntrinsicID()) { default: break; - case Intrinsic::assume: { - Value *Operand = II->getOperand(0); - II->eraseFromParent(); - // Prune the operand, it's most likely dead. - resetIteratorIfInvalidatedWhileCalling(BB, [&]() { - RecursivelyDeleteTriviallyDeadInstructions( - Operand, TLInfo, nullptr, - [&](Value *V) { removeAllAssertingVHReferences(V); }); - }); - return true; - } - + case Intrinsic::assume: + llvm_unreachable("llvm.assume should have been removed already"); case Intrinsic::experimental_widenable_condition: { // Give up on future widening oppurtunties so that we can fold away dead // paths and merge blocks before going into block-local instruction |