mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-04 03:06:28 +00:00
[GuardWidening] Wire up a NPM version of the LoopGuardWidening pass
llvm-svn: 358704
This commit is contained in:
parent
4261828cda
commit
42442ebe63
@ -16,7 +16,9 @@
|
||||
#ifndef LLVM_TRANSFORMS_SCALAR_GUARD_WIDENING_H
|
||||
#define LLVM_TRANSFORMS_SCALAR_GUARD_WIDENING_H
|
||||
|
||||
#include "llvm/Analysis/LoopInfo.h"
|
||||
#include "llvm/IR/PassManager.h"
|
||||
#include "llvm/Transforms/Scalar/LoopPassManager.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
@ -24,6 +26,8 @@ class Function;
|
||||
|
||||
struct GuardWideningPass : public PassInfoMixin<GuardWideningPass> {
|
||||
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
|
||||
PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
|
||||
LoopStandardAnalysisResults &AR, LPMUpdater &U);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -294,4 +294,5 @@ LOOP_PASS("unswitch", SimpleLoopUnswitchPass())
|
||||
LOOP_PASS("print-access-info", LoopAccessInfoPrinterPass(dbgs()))
|
||||
LOOP_PASS("print<ivusers>", IVUsersPrinterPass(dbgs()))
|
||||
LOOP_PASS("loop-predication", LoopPredicationPass())
|
||||
LOOP_PASS("guard-widening", GuardWideningPass())
|
||||
#undef LOOP_PASS
|
||||
|
@ -817,6 +817,31 @@ PreservedAnalyses GuardWideningPass::run(Function &F,
|
||||
return PA;
|
||||
}
|
||||
|
||||
PreservedAnalyses GuardWideningPass::run(Loop &L, LoopAnalysisManager &AM,
|
||||
LoopStandardAnalysisResults &AR,
|
||||
LPMUpdater &U) {
|
||||
|
||||
const auto &FAM =
|
||||
AM.getResult<FunctionAnalysisManagerLoopProxy>(L, AR).getManager();
|
||||
Function &F = *L.getHeader()->getParent();
|
||||
BranchProbabilityInfo *BPI = nullptr;
|
||||
if (WidenFrequentBranches)
|
||||
BPI = FAM.getCachedResult<BranchProbabilityAnalysis>(F);
|
||||
|
||||
BasicBlock *RootBB = L.getLoopPredecessor();
|
||||
if (!RootBB)
|
||||
RootBB = L.getHeader();
|
||||
auto BlockFilter = [&](BasicBlock *BB) {
|
||||
return BB == RootBB || L.contains(BB);
|
||||
};
|
||||
if (!GuardWideningImpl(AR.DT, nullptr, AR.LI, BPI,
|
||||
AR.DT.getNode(RootBB),
|
||||
BlockFilter).run())
|
||||
return PreservedAnalyses::all();
|
||||
|
||||
return getLoopPassPreservedAnalyses();
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct GuardWideningLegacyPass : public FunctionPass {
|
||||
static char ID;
|
||||
|
138
test/Transforms/GuardWidening/basic-loop.ll
Normal file
138
test/Transforms/GuardWidening/basic-loop.ll
Normal file
@ -0,0 +1,138 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt -S -loop-guard-widening < %s | FileCheck %s
|
||||
; RUN: opt -S -passes="loop(guard-widening)" < %s | FileCheck %s
|
||||
|
||||
declare void @llvm.experimental.guard(i1,...)
|
||||
|
||||
@G = external global i32
|
||||
|
||||
; Show that we can widen into early checks within a loop, and in the process
|
||||
; expose optimization oppurtunities.
|
||||
define void @widen_within_loop(i1 %cond_0, i1 %cond_1, i1 %cond_2) {
|
||||
; CHECK-LABEL: @widen_within_loop(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||
; CHECK: loop:
|
||||
; CHECK-NEXT: store i32 0, i32* @G
|
||||
; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]]
|
||||
; CHECK-NEXT: [[WIDE_CHK1:%.*]] = and i1 [[WIDE_CHK]], [[COND_2:%.*]]
|
||||
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK1]]) [ "deopt"(i32 0) ]
|
||||
; CHECK-NEXT: store i32 1, i32* @G
|
||||
; CHECK-NEXT: store i32 2, i32* @G
|
||||
; CHECK-NEXT: store i32 3, i32* @G
|
||||
; CHECK-NEXT: br label [[LOOP]]
|
||||
;
|
||||
entry:
|
||||
br label %loop
|
||||
|
||||
loop:
|
||||
store i32 0, i32* @G
|
||||
call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"(i32 0) ]
|
||||
store i32 1, i32* @G
|
||||
call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"(i32 1) ]
|
||||
store i32 2, i32* @G
|
||||
call void(i1, ...) @llvm.experimental.guard(i1 %cond_2) [ "deopt"(i32 2) ]
|
||||
store i32 3, i32* @G
|
||||
br label %loop
|
||||
}
|
||||
|
||||
define void @widen_into_preheader(i1 %cond_0, i1 %cond_1, i1 %cond_2) {
|
||||
; CHECK-LABEL: @widen_into_preheader(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: store i32 0, i32* @G
|
||||
; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]]
|
||||
; CHECK-NEXT: [[WIDE_CHK1:%.*]] = and i1 [[WIDE_CHK]], [[COND_2:%.*]]
|
||||
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK1]]) [ "deopt"(i32 0) ]
|
||||
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||
; CHECK: loop:
|
||||
; CHECK-NEXT: store i32 1, i32* @G
|
||||
; CHECK-NEXT: store i32 2, i32* @G
|
||||
; CHECK-NEXT: store i32 3, i32* @G
|
||||
; CHECK-NEXT: br label [[LOOP]]
|
||||
;
|
||||
entry:
|
||||
store i32 0, i32* @G
|
||||
call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"(i32 0) ]
|
||||
br label %loop
|
||||
|
||||
loop:
|
||||
store i32 1, i32* @G
|
||||
call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"(i32 1) ]
|
||||
store i32 2, i32* @G
|
||||
call void(i1, ...) @llvm.experimental.guard(i1 %cond_2) [ "deopt"(i32 2) ]
|
||||
store i32 3, i32* @G
|
||||
br label %loop
|
||||
}
|
||||
|
||||
define void @dont_widen_over_common_exit(i1 %cond_0, i1 %cond_1, i1 %cond_2) {
|
||||
; CHECK-LABEL: @dont_widen_over_common_exit(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||
; CHECK: loop:
|
||||
; CHECK-NEXT: store i32 0, i32* @G
|
||||
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND_0:%.*]]) [ "deopt"(i32 0) ]
|
||||
; CHECK-NEXT: store i32 1, i32* @G
|
||||
; CHECK-NEXT: br i1 [[COND_1:%.*]], label [[BACKEDGE:%.*]], label [[EXIT:%.*]]
|
||||
; CHECK: backedge:
|
||||
; CHECK-NEXT: store i32 2, i32* @G
|
||||
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND_2:%.*]]) [ "deopt"(i32 2) ]
|
||||
; CHECK-NEXT: store i32 3, i32* @G
|
||||
; CHECK-NEXT: br label [[LOOP]]
|
||||
; CHECK: exit:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
br label %loop
|
||||
|
||||
loop:
|
||||
store i32 0, i32* @G
|
||||
call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"(i32 0) ]
|
||||
store i32 1, i32* @G
|
||||
br i1 %cond_1, label %backedge, label %exit
|
||||
|
||||
backedge:
|
||||
store i32 2, i32* @G
|
||||
call void(i1, ...) @llvm.experimental.guard(i1 %cond_2) [ "deopt"(i32 2) ]
|
||||
store i32 3, i32* @G
|
||||
br label %loop
|
||||
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @widen_over_common_exit_to_ph(i1 %cond_0, i1 %cond_1, i1 %cond_2) {
|
||||
; CHECK-LABEL: @widen_over_common_exit_to_ph(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: store i32 0, i32* @G
|
||||
; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_2:%.*]]
|
||||
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"(i32 0) ]
|
||||
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||
; CHECK: loop:
|
||||
; CHECK-NEXT: store i32 1, i32* @G
|
||||
; CHECK-NEXT: br i1 [[COND_1:%.*]], label [[BACKEDGE:%.*]], label [[EXIT:%.*]]
|
||||
; CHECK: backedge:
|
||||
; CHECK-NEXT: store i32 2, i32* @G
|
||||
; CHECK-NEXT: store i32 3, i32* @G
|
||||
; CHECK-NEXT: br label [[LOOP]]
|
||||
; CHECK: exit:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
store i32 0, i32* @G
|
||||
call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"(i32 0) ]
|
||||
br label %loop
|
||||
|
||||
loop:
|
||||
store i32 1, i32* @G
|
||||
br i1 %cond_1, label %backedge, label %exit
|
||||
|
||||
backedge:
|
||||
store i32 2, i32* @G
|
||||
call void(i1, ...) @llvm.experimental.guard(i1 %cond_2) [ "deopt"(i32 2) ]
|
||||
store i32 3, i32* @G
|
||||
br label %loop
|
||||
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user