Skip to content

Commit 5ea6948

Browse files
authored
[SandboxVec][Legality] Check opcodes and types (#113741)
1 parent 39303e2 commit 5ea6948

File tree

5 files changed

+92
-5
lines changed

5 files changed

+92
-5
lines changed

llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/VecUtils.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@
1212
#ifndef LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_VECUTILS_H
1313
#define LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_VECUTILS_H
1414

15-
class Utils {
15+
#include "llvm/SandboxIR/Type.h"
16+
17+
namespace llvm::sandboxir {
18+
19+
class VecUtils {
1620
public:
1721
/// \Returns the number of elements in \p Ty. That is the number of lanes if a
1822
/// fixed vector or 1 if scalar. ScalableVectors have unknown size and
@@ -25,6 +29,8 @@ class Utils {
2529
static Type *getElementType(Type *Ty) {
2630
return Ty->isVectorTy() ? cast<FixedVectorType>(Ty)->getElementType() : Ty;
2731
}
28-
}
32+
};
33+
34+
} // namespace llvm::sandboxir
2935

30-
#endif LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_VECUTILS_H
36+
#endif // LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_VECUTILS_H

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

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "llvm/SandboxIR/Utils.h"
1212
#include "llvm/SandboxIR/Value.h"
1313
#include "llvm/Support/Debug.h"
14+
#include "llvm/Transforms/Vectorize/SandboxVectorizer/VecUtils.h"
1415

1516
namespace llvm::sandboxir {
1617

@@ -26,7 +27,24 @@ void LegalityResult::dump() const {
2627
std::optional<ResultReason>
2728
LegalityAnalysis::notVectorizableBasedOnOpcodesAndTypes(
2829
ArrayRef<Value *> Bndl) {
29-
// TODO: Unimplemented.
30+
auto *I0 = cast<Instruction>(Bndl[0]);
31+
auto Opcode = I0->getOpcode();
32+
// If they have different opcodes, then we cannot form a vector (for now).
33+
if (any_of(drop_begin(Bndl), [Opcode](Value *V) {
34+
return cast<Instruction>(V)->getOpcode() != Opcode;
35+
}))
36+
return ResultReason::DiffOpcodes;
37+
38+
// If not the same scalar type, Pack. This will accept scalars and vectors as
39+
// long as the element type is the same.
40+
Type *ElmTy0 = VecUtils::getElementType(Utils::getExpectedType(I0));
41+
if (any_of(drop_begin(Bndl), [ElmTy0](Value *V) {
42+
return VecUtils::getElementType(Utils::getExpectedType(V)) != ElmTy0;
43+
}))
44+
return ResultReason::DiffTypes;
45+
46+
// TODO: Missing checks
47+
3048
return std::nullopt;
3149
}
3250

llvm/unittests/Transforms/Vectorize/SandboxVectorizer/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@ add_llvm_unittest(SandboxVectorizerTests
1313
LegalityTest.cpp
1414
SchedulerTest.cpp
1515
SeedCollectorTest.cpp
16+
VecUtilsTest.cpp
1617
)

llvm/unittests/Transforms/Vectorize/SandboxVectorizer/LegalityTest.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,17 @@ struct LegalityTest : public testing::Test {
2929

3030
TEST_F(LegalityTest, Legality) {
3131
parseIR(C, R"IR(
32-
define void @foo(ptr %ptr) {
32+
define void @foo(ptr %ptr, <2 x float> %vec2, <3 x float> %vec3, i8 %arg) {
3333
%gep0 = getelementptr float, ptr %ptr, i32 0
3434
%gep1 = getelementptr float, ptr %ptr, i32 1
35+
%gep3 = getelementptr float, ptr %ptr, i32 3
3536
%ld0 = load float, ptr %gep0
3637
%ld1 = load float, ptr %gep0
3738
store float %ld0, ptr %gep0
3839
store float %ld1, ptr %gep1
40+
store <2 x float> %vec2, ptr %gep1
41+
store <3 x float> %vec3, ptr %gep3
42+
store i8 %arg, ptr %gep1
3943
ret void
4044
}
4145
)IR");
@@ -46,10 +50,14 @@ define void @foo(ptr %ptr) {
4650
auto It = BB->begin();
4751
[[maybe_unused]] auto *Gep0 = cast<sandboxir::GetElementPtrInst>(&*It++);
4852
[[maybe_unused]] auto *Gep1 = cast<sandboxir::GetElementPtrInst>(&*It++);
53+
[[maybe_unused]] auto *Gep3 = cast<sandboxir::GetElementPtrInst>(&*It++);
4954
[[maybe_unused]] auto *Ld0 = cast<sandboxir::LoadInst>(&*It++);
5055
[[maybe_unused]] auto *Ld1 = cast<sandboxir::LoadInst>(&*It++);
5156
auto *St0 = cast<sandboxir::StoreInst>(&*It++);
5257
auto *St1 = cast<sandboxir::StoreInst>(&*It++);
58+
auto *StVec2 = cast<sandboxir::StoreInst>(&*It++);
59+
auto *StVec3 = cast<sandboxir::StoreInst>(&*It++);
60+
auto *StI8 = cast<sandboxir::StoreInst>(&*It++);
5361

5462
sandboxir::LegalityAnalysis Legality;
5563
const auto &Result = Legality.canVectorize({St0, St1});
@@ -62,6 +70,23 @@ define void @foo(ptr %ptr) {
6270
EXPECT_EQ(cast<sandboxir::Pack>(Result).getReason(),
6371
sandboxir::ResultReason::NotInstructions);
6472
}
73+
{
74+
// Check DiffOpcodes
75+
const auto &Result = Legality.canVectorize({St0, Ld0});
76+
EXPECT_TRUE(isa<sandboxir::Pack>(Result));
77+
EXPECT_EQ(cast<sandboxir::Pack>(Result).getReason(),
78+
sandboxir::ResultReason::DiffOpcodes);
79+
}
80+
{
81+
// Check DiffTypes
82+
EXPECT_TRUE(isa<sandboxir::Widen>(Legality.canVectorize({St0, StVec2})));
83+
EXPECT_TRUE(isa<sandboxir::Widen>(Legality.canVectorize({StVec2, StVec3})));
84+
85+
const auto &Result = Legality.canVectorize({St0, StI8});
86+
EXPECT_TRUE(isa<sandboxir::Pack>(Result));
87+
EXPECT_EQ(cast<sandboxir::Pack>(Result).getReason(),
88+
sandboxir::ResultReason::DiffTypes);
89+
}
6590
}
6691

6792
#ifndef NDEBUG
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//===- VecUtilsTest.cpp --------------------------------------------------===//
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/VecUtils.h"
10+
#include "llvm/AsmParser/Parser.h"
11+
#include "llvm/SandboxIR/Context.h"
12+
#include "llvm/SandboxIR/Type.h"
13+
#include "gtest/gtest.h"
14+
15+
using namespace llvm;
16+
17+
struct VecUtilsTest : public testing::Test {
18+
LLVMContext C;
19+
};
20+
21+
TEST_F(VecUtilsTest, GetNumElements) {
22+
sandboxir::Context Ctx(C);
23+
auto *ElemTy = sandboxir::Type::getInt32Ty(Ctx);
24+
EXPECT_EQ(sandboxir::VecUtils::getNumElements(ElemTy), 1);
25+
auto *VTy = sandboxir::FixedVectorType::get(ElemTy, 2);
26+
EXPECT_EQ(sandboxir::VecUtils::getNumElements(VTy), 2);
27+
auto *VTy1 = sandboxir::FixedVectorType::get(ElemTy, 1);
28+
EXPECT_EQ(sandboxir::VecUtils::getNumElements(VTy1), 1);
29+
}
30+
31+
TEST_F(VecUtilsTest, GetElementType) {
32+
sandboxir::Context Ctx(C);
33+
auto *ElemTy = sandboxir::Type::getInt32Ty(Ctx);
34+
EXPECT_EQ(sandboxir::VecUtils::getElementType(ElemTy), ElemTy);
35+
auto *VTy = sandboxir::FixedVectorType::get(ElemTy, 2);
36+
EXPECT_EQ(sandboxir::VecUtils::getElementType(VTy), ElemTy);
37+
}

0 commit comments

Comments
 (0)