A `#ifndef NDEBUG` in the wrong place caused an error in release builds.
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
//===- Region.h -------------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_REGION_H
|
||||
#define LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_REGION_H
|
||||
|
||||
#include "llvm/ADT/SetVector.h"
|
||||
#include "llvm/ADT/iterator_range.h"
|
||||
#include "llvm/SandboxIR/SandboxIR.h"
|
||||
#include "llvm/Support/InstructionCost.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
namespace llvm::sandboxir {
|
||||
|
||||
/// The main job of the Region is to point to new instructions generated by
|
||||
/// vectorization passes. It is the unit that RegionPasses operate on with their
|
||||
/// runOnRegion() function.
|
||||
///
|
||||
/// The region allows us to stack transformations horizontally, meaning that
|
||||
/// each transformation operates on a single region and the resulting region is
|
||||
/// the input to the next transformation, as opposed to vertically, which is the
|
||||
/// common way of applying a transformation across the whole function. This
|
||||
/// enables us to check for profitability and decide whether we accept or
|
||||
/// rollback at a region granularity, which is much better than doing this at
|
||||
/// the function level.
|
||||
///
|
||||
// Traditional approach: transformations applied vertically for the whole
|
||||
// function
|
||||
// F
|
||||
// +----+
|
||||
// | |
|
||||
// | |
|
||||
// | | -> Transform1 -> ... -> TransformN -> Check Cost
|
||||
// | |
|
||||
// | |
|
||||
// +----+
|
||||
//
|
||||
// Region-based approach: transformations applied horizontally, for each Region
|
||||
// F
|
||||
// +----+
|
||||
// |Rgn1| -> Transform1 -> ... -> TransformN -> Check Cost
|
||||
// | |
|
||||
// |Rgn2| -> Transform1 -> ... -> TransformN -> Check Cost
|
||||
// | |
|
||||
// |Rgn3| -> Transform1 -> ... -> TransformN -> Check Cost
|
||||
// +----+
|
||||
|
||||
class Region {
|
||||
/// All the instructions in the Region. Only new instructions generated during
|
||||
/// vectorization are part of the Region.
|
||||
SetVector<Instruction *> Insts;
|
||||
|
||||
/// A unique ID, used for debugging.
|
||||
unsigned RegionID = 0;
|
||||
|
||||
Context &Ctx;
|
||||
|
||||
// TODO: Add cost modeling.
|
||||
// TODO: Add a way to encode/decode region info to/from metadata.
|
||||
|
||||
public:
|
||||
Region(Context &Ctx);
|
||||
~Region();
|
||||
|
||||
Context &getContext() const { return Ctx; }
|
||||
/// Returns the region's unique ID.
|
||||
unsigned getID() const { return RegionID; }
|
||||
|
||||
/// Adds I to the set.
|
||||
void add(Instruction *I);
|
||||
/// Removes I from the set.
|
||||
void remove(Instruction *I);
|
||||
/// Returns true if I is in the Region.
|
||||
bool contains(Instruction *I) const { return Insts.contains(I); }
|
||||
/// Returns true if the Region has no instructions.
|
||||
bool empty() const { return Insts.empty(); }
|
||||
|
||||
using iterator = decltype(Insts.begin());
|
||||
iterator begin() { return Insts.begin(); }
|
||||
iterator end() { return Insts.end(); }
|
||||
iterator_range<iterator> insts() { return make_range(begin(), end()); }
|
||||
|
||||
#ifndef NDEBUG
|
||||
/// This is an expensive check, meant for testing.
|
||||
bool operator==(const Region &Other) const;
|
||||
bool operator!=(const Region &other) const { return !(*this == other); }
|
||||
|
||||
void dump(raw_ostream &OS) const;
|
||||
void dump() const;
|
||||
friend raw_ostream &operator<<(raw_ostream &OS, const Region &Rgn) {
|
||||
Rgn.dump(OS);
|
||||
return OS;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace llvm::sandboxir
|
||||
|
||||
#endif // LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_REGION_H
|
||||
@@ -5,6 +5,7 @@ add_llvm_component_library(LLVMVectorize
|
||||
LoopVectorize.cpp
|
||||
SandboxVectorizer/DependencyGraph.cpp
|
||||
SandboxVectorizer/Passes/BottomUpVec.cpp
|
||||
SandboxVectorizer/Region.cpp
|
||||
SandboxVectorizer/SandboxVectorizer.cpp
|
||||
SLPVectorizer.cpp
|
||||
Vectorize.cpp
|
||||
|
||||
45
llvm/lib/Transforms/Vectorize/SandboxVectorizer/Region.cpp
Normal file
45
llvm/lib/Transforms/Vectorize/SandboxVectorizer/Region.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
//===- Region.cpp ---------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Transforms/Vectorize/SandboxVectorizer/Region.h"
|
||||
|
||||
namespace llvm::sandboxir {
|
||||
|
||||
Region::Region(Context &Ctx) : Ctx(Ctx) {
|
||||
static unsigned StaticRegionID;
|
||||
RegionID = StaticRegionID++;
|
||||
}
|
||||
|
||||
Region::~Region() {}
|
||||
|
||||
void Region::add(Instruction *I) { Insts.insert(I); }
|
||||
|
||||
void Region::remove(Instruction *I) { Insts.remove(I); }
|
||||
|
||||
#ifndef NDEBUG
|
||||
bool Region::operator==(const Region &Other) const {
|
||||
if (Insts.size() != Other.Insts.size())
|
||||
return false;
|
||||
if (!std::is_permutation(Insts.begin(), Insts.end(), Other.Insts.begin()))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Region::dump(raw_ostream &OS) const {
|
||||
OS << "RegionID: " << getID() << "\n";
|
||||
for (auto *I : Insts)
|
||||
OS << *I << "\n";
|
||||
}
|
||||
|
||||
void Region::dump() const {
|
||||
dump(dbgs());
|
||||
dbgs() << "\n";
|
||||
}
|
||||
#endif // NDEBUG
|
||||
|
||||
} // namespace llvm::sandboxir
|
||||
@@ -10,4 +10,5 @@ set(LLVM_LINK_COMPONENTS
|
||||
add_llvm_unittest(SandboxVectorizerTests
|
||||
DependencyGraphTest.cpp
|
||||
LegalityTest.cpp
|
||||
RegionTest.cpp
|
||||
)
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
//===- RegionTest.cpp -----------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Transforms/Vectorize/SandboxVectorizer/Region.h"
|
||||
#include "llvm/AsmParser/Parser.h"
|
||||
#include "llvm/SandboxIR/SandboxIR.h"
|
||||
#include "llvm/Support/SourceMgr.h"
|
||||
#include "gmock/gmock-matchers.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
struct RegionTest : public testing::Test {
|
||||
LLVMContext C;
|
||||
std::unique_ptr<Module> M;
|
||||
|
||||
void parseIR(LLVMContext &C, const char *IR) {
|
||||
SMDiagnostic Err;
|
||||
M = parseAssemblyString(IR, Err, C);
|
||||
if (!M)
|
||||
Err.print("RegionTest", errs());
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(RegionTest, Basic) {
|
||||
parseIR(C, R"IR(
|
||||
define i8 @foo(i8 %v0, i8 %v1) {
|
||||
%t0 = add i8 %v0, 1
|
||||
%t1 = add i8 %t0, %v1
|
||||
ret i8 %t1
|
||||
}
|
||||
)IR");
|
||||
llvm::Function *LLVMF = &*M->getFunction("foo");
|
||||
sandboxir::Context Ctx(C);
|
||||
auto *F = Ctx.createFunction(LLVMF);
|
||||
auto *BB = &*F->begin();
|
||||
auto It = BB->begin();
|
||||
auto *T0 = cast<sandboxir::Instruction>(&*It++);
|
||||
auto *T1 = cast<sandboxir::Instruction>(&*It++);
|
||||
auto *Ret = cast<sandboxir::Instruction>(&*It++);
|
||||
sandboxir::Region Rgn(Ctx);
|
||||
|
||||
// Check getters
|
||||
EXPECT_EQ(&Ctx, &Rgn.getContext());
|
||||
EXPECT_EQ(0U, Rgn.getID());
|
||||
|
||||
// Check add / remove / empty.
|
||||
EXPECT_TRUE(Rgn.empty());
|
||||
Rgn.add(T0);
|
||||
EXPECT_FALSE(Rgn.empty());
|
||||
Rgn.remove(T0);
|
||||
EXPECT_TRUE(Rgn.empty());
|
||||
|
||||
// Check iteration.
|
||||
Rgn.add(T0);
|
||||
Rgn.add(T1);
|
||||
Rgn.add(Ret);
|
||||
// Use an ordered matcher because we're supposed to preserve the insertion
|
||||
// order for determinism.
|
||||
EXPECT_THAT(Rgn.insts(), testing::ElementsAre(T0, T1, Ret));
|
||||
|
||||
// Check contains
|
||||
EXPECT_TRUE(Rgn.contains(T0));
|
||||
Rgn.remove(T0);
|
||||
EXPECT_FALSE(Rgn.contains(T0));
|
||||
|
||||
#ifndef NDEBUG
|
||||
// Check equality comparison. Insert in reverse order into `Other` to check
|
||||
// that comparison is order-independent.
|
||||
sandboxir::Region Other(Ctx);
|
||||
Other.add(Ret);
|
||||
EXPECT_NE(Rgn, Other);
|
||||
Other.add(T1);
|
||||
EXPECT_EQ(Rgn, Other);
|
||||
#endif
|
||||
}
|
||||
Reference in New Issue
Block a user