Skip to content

Commit 91b0b0a

Browse files
author
Vasileios Porpodas
committed
[SandboxVec][BottomUpVec] Add cost estimation and tr-accept-or-revert pass
The TransactionAcceptOrRevert pass is the final pass in the Sandbox Vectorizer's default pass pipeline. It's job is to check the cost before/after vectorization and accept or revert the IR to its original state. Since we are now starting the transaction in BottomUpVec, tests that run a custom pipeline need to accept the transaction. This is done with the help of the TransactionAlwaysAccept pass (tr-accept).
1 parent a0d86b2 commit 91b0b0a

File tree

17 files changed

+196
-12
lines changed

17 files changed

+196
-12
lines changed

llvm/include/llvm/SandboxIR/Tracker.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,8 @@ class Tracker {
473473

474474
~Tracker();
475475
Context &getContext() const { return Ctx; }
476+
/// \Returns true if there are no changes tracked.
477+
bool empty() const { return Changes.empty(); }
476478
/// Record \p Change and take ownership. This is the main function used to
477479
/// track Sandbox IR changes.
478480
void track(std::unique_ptr<IRChangeBase> &&Change) {
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//===- TransactionAcceptOrRevert.h ------------------------------*- 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 is a region pass that checks the region cost before/after vectorization
10+
// and accepts the state of Sandbox IR if the cost is better, or otherwise
11+
// reverts it.
12+
//
13+
14+
#ifndef LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_PASSES_TRANSACTIONACCEPTORREVERT_H
15+
#define LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_PASSES_TRANSACTIONACCEPTORREVERT_H
16+
17+
#include "llvm/SandboxIR/Pass.h"
18+
#include "llvm/SandboxIR/Region.h"
19+
20+
namespace llvm::sandboxir {
21+
22+
class TransactionAcceptOrRevert : public RegionPass {
23+
public:
24+
TransactionAcceptOrRevert() : RegionPass("tr-accept-or-revert") {}
25+
bool runOnRegion(Region &Rgn, const Analyses &A) final;
26+
};
27+
28+
} // namespace llvm::sandboxir
29+
30+
#endif // LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_PASSES_TRANSACTIONACCEPTORREVERT_H
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//===- TransactionAlwaysAccept.h --------------------------------*- 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 is a region pass that always accepts the transaction without checking
10+
// its cost. This is mainly used as a final pass in lit tests.
11+
//
12+
13+
#ifndef LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_PASSES_TRANSACTIONALWAYSACCEPT_H
14+
#define LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_PASSES_TRANSACTIONALWAYSACCEPT_H
15+
16+
#include "llvm/SandboxIR/Pass.h"
17+
#include "llvm/SandboxIR/Region.h"
18+
19+
namespace llvm::sandboxir {
20+
21+
class TransactionAlwaysAccept : public RegionPass {
22+
public:
23+
TransactionAlwaysAccept() : RegionPass("tr-accept") {}
24+
bool runOnRegion(Region &Rgn, const Analyses &A) final {
25+
auto &Tracker = Rgn.getContext().getTracker();
26+
bool HasChanges = !Tracker.empty();
27+
Tracker.accept();
28+
return HasChanges;
29+
}
30+
};
31+
32+
} // namespace llvm::sandboxir
33+
34+
#endif // LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_PASSES_TRANSACTIONALWAYSACCEPT_H

llvm/lib/Transforms/Vectorize/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ add_llvm_component_library(LLVMVectorize
99
SandboxVectorizer/Legality.cpp
1010
SandboxVectorizer/Passes/BottomUpVec.cpp
1111
SandboxVectorizer/Passes/RegionsFromMetadata.cpp
12+
SandboxVectorizer/Passes/TransactionAcceptOrRevert.cpp
1213
SandboxVectorizer/SandboxVectorizer.cpp
1314
SandboxVectorizer/SandboxVectorizerPassBuilder.cpp
1415
SandboxVectorizer/Scheduler.cpp

llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "llvm/SandboxIR/Function.h"
1313
#include "llvm/SandboxIR/Instruction.h"
1414
#include "llvm/SandboxIR/Module.h"
15+
#include "llvm/SandboxIR/Region.h"
1516
#include "llvm/SandboxIR/Utils.h"
1617
#include "llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerPassBuilder.h"
1718
#include "llvm/Transforms/Vectorize/SandboxVectorizer/SeedCollector.h"
@@ -448,13 +449,24 @@ bool BottomUpVec::runOnFunction(Function &F, const Analyses &A) {
448449

449450
assert(SeedSlice.size() >= 2 && "Should have been rejected!");
450451

451-
// TODO: If vectorization succeeds, run the RegionPassManager on the
452-
// resulting region.
453-
454452
// TODO: Refactor to remove the unnecessary copy to SeedSliceVals.
455453
SmallVector<Value *> SeedSliceVals(SeedSlice.begin(),
456454
SeedSlice.end());
457-
Change |= tryVectorize(SeedSliceVals);
455+
// Create an empty region. Instructions get added to the region
456+
// automatically by the callbacks.
457+
auto &Ctx = F.getContext();
458+
Region Rgn(Ctx, A.getTTI());
459+
// Save the state of the IR before we make any changes. The
460+
// transaction gets accepted/reverted by the tr-accept-or-revert pass.
461+
Ctx.save();
462+
// Try to vectorize starting from the seed slice. The returned value
463+
// is true if we found vectorizable code and generated some vector
464+
// code for it. It does not mean that the code is profitable.
465+
bool VecSuccess = tryVectorize(SeedSliceVals);
466+
if (VecSuccess)
467+
// WARNING: All passes should return false, except those that
468+
// accept/revert the state.
469+
Change |= RPM.runOnRegion(Rgn, A);
458470
}
459471
}
460472
}

llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/PassRegistry.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
REGION_PASS("null", ::llvm::sandboxir::NullPass)
2121
REGION_PASS("print-instruction-count", ::llvm::sandboxir::PrintInstructionCount)
22+
REGION_PASS("tr-accept", ::llvm::sandboxir::TransactionAlwaysAccept)
23+
REGION_PASS("tr-accept-or-revert", ::llvm::sandboxir::TransactionAcceptOrRevert)
2224

2325
#undef REGION_PASS
2426

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//===- TransactionAcceptOrRevert.cpp - Check cost and accept/revert region ===//
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+
#include "llvm/Transforms/Vectorize/SandboxVectorizer/Passes/TransactionAcceptOrRevert.h"
10+
#include "llvm/Support/CommandLine.h"
11+
#include "llvm/Support/InstructionCost.h"
12+
13+
namespace llvm {
14+
15+
static cl::opt<bool> CostThreshold("sbvec-cost-threshold", cl::init(0),
16+
cl::Hidden,
17+
cl::desc("Vectorization cost threshold."));
18+
19+
namespace sandboxir {
20+
21+
bool TransactionAcceptOrRevert::runOnRegion(Region &Rgn, const Analyses &A) {
22+
const auto &SB = Rgn.getScoreboard();
23+
InstructionCost CostAfterMinusBefore = SB.getAfterCost() - SB.getBeforeCost();
24+
// TODO: Print costs / write to remarks.
25+
auto &Tracker = Rgn.getContext().getTracker();
26+
if (CostAfterMinusBefore < -CostThreshold) {
27+
bool HasChanges = !Tracker.empty();
28+
Tracker.accept();
29+
return HasChanges;
30+
}
31+
// Revert the IR.
32+
Rgn.getContext().getTracker().revert();
33+
return false;
34+
}
35+
36+
} // namespace sandboxir
37+
} // namespace llvm

llvm/lib/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,10 @@ static cl::opt<std::string> UserDefinedPassPipeline(
3131

3232
SandboxVectorizerPass::SandboxVectorizerPass() : FPM("fpm") {
3333
if (UserDefinedPassPipeline == DefaultPipelineMagicStr) {
34-
// TODO: Add region passes to the default pipeline.
34+
// TODO: Add passes to the default pipeline. It currently contains:
35+
// - the bottom-up-vectorizer pass
3536
FPM.setPassPipeline(
36-
"bottom-up-vec<>",
37+
"bottom-up-vec<tr-accept-or-revert>",
3738
sandboxir::SandboxVectorizerPassBuilder::createFunctionPass);
3839
} else {
3940
// Create the user-defined pipeline.

llvm/lib/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizerPassBuilder.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
#include "llvm/Transforms/Vectorize/SandboxVectorizer/Passes/NullPass.h"
55
#include "llvm/Transforms/Vectorize/SandboxVectorizer/Passes/PrintInstructionCount.h"
66
#include "llvm/Transforms/Vectorize/SandboxVectorizer/Passes/RegionsFromMetadata.h"
7+
#include "llvm/Transforms/Vectorize/SandboxVectorizer/Passes/TransactionAcceptOrRevert.h"
8+
#include "llvm/Transforms/Vectorize/SandboxVectorizer/Passes/TransactionAlwaysAccept.h"
79

810
namespace llvm::sandboxir {
911

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt -passes=sandbox-vectorizer -mtriple=x86_64-- -mattr=+sse4.1 %s -S | FileCheck %s
3+
4+
define void @simple_cost_test(ptr %ptr) {
5+
; CHECK-LABEL: define void @simple_cost_test(
6+
; CHECK-SAME: ptr [[PTR:%.*]]) #[[ATTR0:[0-9]+]] {
7+
; CHECK-NEXT: [[PTR0:%.*]] = getelementptr double, ptr [[PTR]], i32 0
8+
; CHECK-NEXT: [[VECL:%.*]] = load <2 x double>, ptr [[PTR0]], align 8
9+
; CHECK-NEXT: store <2 x double> [[VECL]], ptr [[PTR0]], align 8
10+
; CHECK-NEXT: ret void
11+
;
12+
%ptr0 = getelementptr double, ptr %ptr, i32 0
13+
%ptr1 = getelementptr double, ptr %ptr, i32 1
14+
%ld0 = load double, ptr %ptr0
15+
%ld1 = load double, ptr %ptr1
16+
store double %ld0, ptr %ptr0
17+
store double %ld1, ptr %ptr1
18+
ret void
19+
}
20+
21+
define void @pack_cost_test_(ptr %ptr) {
22+
; CHECK-LABEL: define void @pack_cost_test_(
23+
; CHECK-SAME: ptr [[PTR:%.*]]) #[[ATTR0]] {
24+
; CHECK-NEXT: [[PTR0:%.*]] = getelementptr float, ptr [[PTR]], i32 0
25+
; CHECK-NEXT: [[PTR1:%.*]] = getelementptr float, ptr [[PTR]], i32 1
26+
; CHECK-NEXT: [[LD0:%.*]] = load float, ptr [[PTR0]], align 4
27+
; CHECK-NEXT: [[LD1:%.*]] = load float, ptr [[PTR1]], align 4
28+
; CHECK-NEXT: [[PACK4:%.*]] = insertelement <4 x float> poison, float [[LD0]], i32 0
29+
; CHECK-NEXT: [[PACK5:%.*]] = insertelement <4 x float> [[PACK4]], float [[LD1]], i32 1
30+
; CHECK-NEXT: [[PACK6:%.*]] = insertelement <4 x float> [[PACK5]], float [[LD0]], i32 2
31+
; CHECK-NEXT: [[PACK7:%.*]] = insertelement <4 x float> [[PACK6]], float [[LD1]], i32 3
32+
; CHECK-NEXT: [[PACK:%.*]] = insertelement <4 x float> poison, float [[LD0]], i32 0
33+
; CHECK-NEXT: [[PACK1:%.*]] = insertelement <4 x float> [[PACK]], float [[LD1]], i32 1
34+
; CHECK-NEXT: [[PACK2:%.*]] = insertelement <4 x float> [[PACK1]], float [[LD0]], i32 2
35+
; CHECK-NEXT: [[PACK3:%.*]] = insertelement <4 x float> [[PACK2]], float [[LD1]], i32 3
36+
; CHECK-NEXT: [[VEC:%.*]] = fmul <4 x float> [[PACK3]], [[PACK7]]
37+
; CHECK-NEXT: store <4 x float> [[VEC]], ptr [[PTR0]], align 4
38+
; CHECK-NEXT: ret void
39+
;
40+
%ptr0 = getelementptr float, ptr %ptr, i32 0
41+
%ptr1 = getelementptr float, ptr %ptr, i32 1
42+
%ptr2 = getelementptr float, ptr %ptr, i32 2
43+
%ptr3 = getelementptr float, ptr %ptr, i32 3
44+
%ld0 = load float, ptr %ptr0
45+
%ld1 = load float, ptr %ptr1
46+
%mul0 = fmul float %ld0, %ld0
47+
%mul1 = fmul float %ld1, %ld1
48+
%mul2 = fmul float %ld0, %ld0
49+
%mul3 = fmul float %ld1, %ld1
50+
store float %mul0, ptr %ptr0
51+
store float %mul1, ptr %ptr1
52+
store float %mul2, ptr %ptr2
53+
store float %mul3, ptr %ptr3
54+
ret void
55+
}

0 commit comments

Comments
 (0)