Skip to content

Commit

Permalink
[LoadCombine] Avoid analysing dead basic blocks
Browse files Browse the repository at this point in the history
Summary:
Dead basic blocks may be forming a loop, for which SSA form is
fulfilled, but with a circular def-use chain. LoadCombine could
enter an infinite loop when analysing such dead code. This patch
solves the problem by simply avoiding to analyse all basic blocks
that aren't forward reachable, from function entry, in LoadCombine.

Fixes https://bugs.llvm.org/show_bug.cgi?id=27065

Reviewers: mehdi_amini, chandlerc, grosser, Bigcheese, davide

Reviewed By: davide

Subscribers: dberlin, zzheng, bjope, grandinj, Ka-Ka, materi, jholewinski, llvm-commits, mzolotukhin

Differential Revision: https://reviews.llvm.org/D31032

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@300034 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
bjope committed Apr 12, 2017
1 parent 3512d22 commit a222058
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 1 deletion.
13 changes: 12 additions & 1 deletion lib/Transforms/Scalar/LoadCombine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "llvm/Analysis/GlobalsModRef.h"
#include "llvm/Analysis/TargetFolder.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instructions.h"
Expand Down Expand Up @@ -53,18 +54,20 @@ struct LoadPOPPair {
class LoadCombine : public BasicBlockPass {
LLVMContext *C;
AliasAnalysis *AA;
DominatorTree *DT;

public:
LoadCombine() : BasicBlockPass(ID), C(nullptr), AA(nullptr) {
initializeLoadCombinePass(*PassRegistry::getPassRegistry());
}

using llvm::Pass::doInitialization;
bool doInitialization(Function &) override;
bool runOnBasicBlock(BasicBlock &BB) override;
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesCFG();
AU.addRequired<AAResultsWrapperPass>();
AU.addRequired<DominatorTreeWrapperPass>();
AU.addPreserved<GlobalsAAWrapperPass>();
}

Expand Down Expand Up @@ -234,6 +237,14 @@ bool LoadCombine::runOnBasicBlock(BasicBlock &BB) {
return false;

AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();

// Skip analysing dead blocks (not forward reachable from function entry).
if (!DT->isReachableFromEntry(&BB)) {
DEBUG(dbgs() << "LC: skipping unreachable " << BB.getName() <<
" in " << BB.getParent()->getName() << "\n");
return false;
}

IRBuilder<TargetFolder> TheBuilder(
BB.getContext(), TargetFolder(BB.getModule()->getDataLayout()));
Expand Down
39 changes: 39 additions & 0 deletions test/Transforms/LoadCombine/deadcode.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -load-combine -S < %s | FileCheck %s

; It has been detected that dead loops like the one in this test case can be
; created by -jump-threading (it was detected by a csmith generated program).
;
; According to -verify this is valid input (even if it could be discussed if
; the dead loop really satisfies SSA form).
;
; The problem found was that the -load-combine pass ends up in an infinite loop
; when analysing the 'bb1' basic block.
define void @test1() {
; CHECK-LABEL: @test1(
; CHECK-NEXT: ret void
; CHECK: bb1:
; CHECK-NEXT: [[_TMP4:%.*]] = load i16, i16* [[_TMP10:%.*]], align 1
; CHECK-NEXT: [[_TMP10]] = getelementptr i16, i16* [[_TMP10]], i16 1
; CHECK-NEXT: br label [[BB1:%.*]]
; CHECK: bb2:
; CHECK-NEXT: [[_TMP7:%.*]] = load i16, i16* [[_TMP12:%.*]], align 1
; CHECK-NEXT: [[_TMP12]] = getelementptr i16, i16* [[_TMP12]], i16 1
; CHECK-NEXT: br label [[BB2:%.*]]
;
ret void

bb1:
%_tmp4 = load i16, i16* %_tmp10, align 1
%_tmp10 = getelementptr i16, i16* %_tmp10, i16 1
br label %bb1

; A second basic block. Running the test with -debug-pass=Executions shows
; that we only run the Dominator Tree Construction one time for each function,
; also when having multiple basic blocks in the function.
bb2:
%_tmp7 = load i16, i16* %_tmp12, align 1
%_tmp12 = getelementptr i16, i16* %_tmp12, i16 1
br label %bb2

}

0 comments on commit a222058

Please sign in to comment.