Skip to content

Commit 40549de

Browse files
author
Whitney Tsang
committed
LoopNestTutorial: Basic loop nest optimization template [STEP1]
1 parent 2c4ba3e commit 40549de

File tree

7 files changed

+142
-1
lines changed

7 files changed

+142
-1
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//===- LoopNestTutorial.h - Loop Nest Tutorial Pass -------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file contains a small loop nest pass to be used to illustrate several
10+
// aspects about writing a loop nest optimization. It was developed as part of
11+
// the "How to utilize LoopNest pass" tutorial, presented at LLVM Devepeloper's
12+
// Conference, 2021.
13+
//
14+
//===----------------------------------------------------------------------===//
15+
16+
#ifndef LLVM_TRANSFORMS_SCALAR_LOOPNESTTUTORIAL_H
17+
#define LLVM_TRANSFORMS_SCALAR_LOOPNESTTUTORIAL_H
18+
19+
#include "llvm/Transforms/Scalar/LoopPassManager.h"
20+
21+
namespace llvm {
22+
23+
class LoopNestTutorialPass : public PassInfoMixin<LoopNestTutorialPass> {
24+
public:
25+
LoopNestTutorialPass() = default;
26+
27+
PreservedAnalyses run(LoopNest &LN, LoopAnalysisManager &LAM,
28+
LoopStandardAnalysisResults &AR, LPMUpdater &U);
29+
};
30+
31+
} // end namespace llvm
32+
33+
#endif // LLVM_TRANSFORMS_SCALAR_LOOPNESTTUTORIAL_H

llvm/lib/Passes/PassBuilder.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@
171171
#include "llvm/Transforms/Scalar/LoopInstSimplify.h"
172172
#include "llvm/Transforms/Scalar/LoopInterchange.h"
173173
#include "llvm/Transforms/Scalar/LoopLoadElimination.h"
174+
#include "llvm/Transforms/Scalar/LoopNestTutorial.h"
174175
#include "llvm/Transforms/Scalar/LoopPassManager.h"
175176
#include "llvm/Transforms/Scalar/LoopPredication.h"
176177
#include "llvm/Transforms/Scalar/LoopReroll.h"

llvm/lib/Passes/PassBuilderPipelines.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@
9393
#include "llvm/Transforms/Scalar/LoopInstSimplify.h"
9494
#include "llvm/Transforms/Scalar/LoopInterchange.h"
9595
#include "llvm/Transforms/Scalar/LoopLoadElimination.h"
96+
#include "llvm/Transforms/Scalar/LoopNestTutorial.h"
9697
#include "llvm/Transforms/Scalar/LoopPassManager.h"
9798
#include "llvm/Transforms/Scalar/LoopRotation.h"
9899
#include "llvm/Transforms/Scalar/LoopSimplifyCFG.h"
@@ -293,8 +294,10 @@ PassBuilder::buildO1FunctionSimplificationPipeline(OptimizationLevel Level,
293294

294295
LPM2.addPass(LoopDeletionPass());
295296

296-
if (EnableLoopInterchange)
297+
if (EnableLoopInterchange) {
298+
LPM2.addPass(LoopNestTutorialPass());
297299
LPM2.addPass(LoopInterchangePass());
300+
}
298301

299302
// Do not enable unrolling in PreLinkThinLTO phase during sample PGO
300303
// because it changes IR to makes profile annotation in back compile

llvm/lib/Passes/PassRegistry.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,7 @@ FUNCTION_PASS_WITH_PARAMS("print<stack-lifetime>",
458458
LOOPNEST_PASS("lnicm", LNICMPass())
459459
LOOPNEST_PASS("loop-flatten", LoopFlattenPass())
460460
LOOPNEST_PASS("loop-interchange", LoopInterchangePass())
461+
LOOPNEST_PASS("loop-nest-tutorial", LoopNestTutorialPass())
461462
LOOPNEST_PASS("loop-unroll-and-jam", LoopUnrollAndJamPass())
462463
LOOPNEST_PASS("no-op-loopnest", NoOpLoopNestPass())
463464
#undef LOOPNEST_PASS

llvm/lib/Transforms/Scalar/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ add_llvm_component_library(LLVMScalarOpts
3737
LoopInterchange.cpp
3838
LoopFlatten.cpp
3939
LoopLoadElimination.cpp
40+
LoopNestTutorial.cpp
4041
LoopPassManager.cpp
4142
LoopPredication.cpp
4243
LoopRerollPass.cpp
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
//===- LoopNestTutorial.cpp - Loop Nest Tutorial Pass ---------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This pass interchanges perfect loop nest with loop depth two.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "llvm/Transforms/Scalar/LoopNestTutorial.h"
14+
#include "llvm/IR/Verifier.h"
15+
16+
using namespace llvm;
17+
18+
#define DEBUG_TYPE "loop-nest-tutorial"
19+
20+
class LoopNestTutorial {
21+
public:
22+
LoopNestTutorial(LoopInfo *LI, DominatorTree *DT) : LI(LI), DT(DT) {}
23+
24+
bool run(LoopNest &LN) const {
25+
LLVM_DEBUG(dbgs() << "Entering LoopNestTutorial::run\n");
26+
LLVM_DEBUG(
27+
dbgs() << "TODO: Need to check if LoopNest is a valid candidate\n");
28+
(void)LI;
29+
(void)DT;
30+
return false;
31+
}
32+
33+
private:
34+
LoopInfo *LI = nullptr;
35+
DominatorTree *DT = nullptr;
36+
};
37+
38+
static void verify(const LoopInfo &LI, const DominatorTree &DT) {
39+
Function &F = *(*LI.begin())->getHeader()->getParent();
40+
assert(!verifyFunction(F, &errs()) && "Incorrect Function");
41+
assert(DT.verify() && "Incorrect DT");
42+
LI.verify(DT);
43+
}
44+
45+
PreservedAnalyses LoopNestTutorialPass::run(LoopNest &LN,
46+
LoopAnalysisManager &LAM,
47+
LoopStandardAnalysisResults &AR,
48+
LPMUpdater &U) {
49+
50+
LLVM_DEBUG(dbgs() << "Entering LoopNestTutorialPass::run\n");
51+
52+
// auto *DT = &AM.getResult<DominatorTreeAnalysis>(F);
53+
// auto *LI = &AM.getResult<LoopAnalysis>(F);
54+
// auto *SE = &AM.getResult<ScalarEvolutionAnalysis>(F);
55+
// bool Simplified = false;
56+
// for (const auto *L : *LI) {
57+
// Simplified |= simplifyLoop(L, DT, LI, SE, nullptr, nullptr, true);
58+
// LoopNest LN(*L, *SE);
59+
LLVM_DEBUG(dbgs() << "LoopNest: " << LN << "\n");
60+
bool Changed = LoopNestTutorial(&AR.LI, &AR.DT).run(LN);
61+
// }
62+
63+
if (!Changed)
64+
return PreservedAnalyses::all();
65+
66+
verify(AR.LI, AR.DT);
67+
68+
return getLoopPassPreservedAnalyses();
69+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
; RUN: opt -passes='loop-nest-tutorial' -debug-only=loop-nest-tutorial -S < %s 2>&1 | FileCheck %s
2+
; REQUIRES: asserts
3+
4+
; CHECK: Entering LoopNestTutorialPass::run
5+
; CHECK-NEXT: LoopNest: IsPerfect=true, Depth=2, OutermostLoop: header.outer, Loops: ( header.outer header.inner )
6+
; CHECK-NEXT: Entering LoopNestTutorial::run
7+
; CHECK-NEXT: TODO: Need to check if LoopNest is a valid candidate
8+
9+
define void @perfectloopnest() {
10+
preheader.outer:
11+
br label %header.outer
12+
13+
header.outer:
14+
%i = phi i32 [ 0, %preheader.outer ], [ %inc.outer, %latch.outer ]
15+
br label %header.inner
16+
17+
header.inner:
18+
%j = phi i32 [ 0, %header.outer ], [ %inc.inner, %header.inner ]
19+
call void @foo(i32 %i, i32 %j)
20+
%inc.inner = add nsw i32 %j, 1
21+
%cmp.inner = icmp slt i32 %inc.inner, 100
22+
br i1 %cmp.inner, label %header.inner, label %latch.outer
23+
24+
latch.outer:
25+
%inc.outer = add nsw i32 %i, 1
26+
%cmp.outer = icmp slt i32 %inc.outer, 100
27+
br i1 %cmp.outer, label %header.outer, label %exit.outer
28+
29+
exit.outer:
30+
ret void
31+
}
32+
33+
declare void @foo(i32, i32)

0 commit comments

Comments
 (0)