Skip to content

Commit f347eb6

Browse files
committed
[LSV] Decide the type to cast instructions into
For classes where all instructions are integers, FP or pointers, it is rather efficient to bitcast them into that type instead of a generic intN type. This commit preprocesses the equivalence classes and maintains a bitvector of 3 bits which are set if the corresponding class contains instructions of type integer, FP or pointer, respectively.
1 parent f00bc10 commit f347eb6

File tree

2 files changed

+47
-2
lines changed

2 files changed

+47
-2
lines changed

llvm/lib/Transforms/Vectorize/LoadStoreVectorizer.cpp

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
#include "llvm/Transforms/Vectorize/LoadStoreVectorizer.h"
6161
#include "llvm/ADT/APInt.h"
6262
#include "llvm/ADT/ArrayRef.h"
63+
#include "llvm/ADT/Bitset.h"
6364
#include "llvm/ADT/DenseMap.h"
6465
#include "llvm/ADT/MapVector.h"
6566
#include "llvm/ADT/PostOrderIterator.h"
@@ -1318,6 +1319,28 @@ void Vectorizer::insertCastsToMergeClasses(EquivalenceClassMap &EQClasses) {
13181319
if (EQClasses.size() < 2)
13191320
return;
13201321

1322+
// For each class, determine if all instructions are of type int, FP or ptr.
1323+
// This information will help us determine the type instructions should be
1324+
// casted into.
1325+
MapVector<EqClassKey, Bitset<3>> ClassAllTy;
1326+
for (auto C : EQClasses) {
1327+
if (all_of(EQClasses[C.first],
1328+
[](Instruction *I) {
1329+
return I->getType()->isIntOrIntVectorTy();
1330+
}))
1331+
ClassAllTy[C.first].set(0);
1332+
else if (all_of(EQClasses[C.first],
1333+
[](Instruction *I) {
1334+
return I->getType()->isFPOrFPVectorTy();
1335+
}))
1336+
ClassAllTy[C.first].set(1);
1337+
else if (all_of(EQClasses[C.first],
1338+
[](Instruction *I) {
1339+
return I->getType()->isPtrOrPtrVectorTy();
1340+
}))
1341+
ClassAllTy[C.first].set(2);
1342+
}
1343+
13211344
// Loop over all equivalence classes and try to merge them. Keep track of
13221345
// classes that are merged into others.
13231346
DenseSet<EqClassKey> ClassesToErase;
@@ -1346,8 +1369,19 @@ void Vectorizer::insertCastsToMergeClasses(EquivalenceClassMap &EQClasses) {
13461369
continue;
13471370

13481371
// Create a new type for the equivalence class.
1349-
/// TODO: NewTy should be an FP type for an all-FP equivalence class.
1350-
auto *NewTy = Type::getIntNTy(EC2.second[0]->getContext(), NewTyBits);
1372+
auto &Ctx = EC2.second[0]->getContext();
1373+
Type *NewTy = Type::getIntNTy(EC2.second[0]->getContext(), NewTyBits);
1374+
if (ClassAllTy[EC1.first].test(1) && ClassAllTy[EC2.first].test(1)) {
1375+
if (NewTyBits == 16)
1376+
NewTy = Type::getHalfTy(Ctx);
1377+
else if (NewTyBits == 32)
1378+
NewTy = Type::getFloatTy(Ctx);
1379+
else if (NewTyBits == 64)
1380+
NewTy = Type::getDoubleTy(Ctx);
1381+
} else if (ClassAllTy[EC1.first].test(2) && ClassAllTy[EC2.first].test(2)) {
1382+
NewTy = PointerType::get(Ctx, AS2);
1383+
}
1384+
13511385
for (auto *Inst : EC2.second) {
13521386
auto *Ptr = getLoadStorePointerOperand(Inst);
13531387
auto *OrigTy = Inst->getType();

llvm/test/Transforms/LoadStoreVectorizer/AMDGPU/merge-vectors.ll

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,3 +135,14 @@ define void @merge_i32_2i16_float_4i8(ptr addrspace(1) %ptr1, ptr addrspace(2) %
135135
store <4 x i8> %load4, ptr addrspace(2) %store.gep4, align 4
136136
ret void
137137
}
138+
139+
; CHECK-LABEL: @merge_fp_type(
140+
; CHECK: load <2 x float>
141+
; CHECK: bitcast float {{.*}} to <2 x half>
142+
define void @merge_fp_type(ptr addrspace(1) %ptr1, ptr addrspace(2) %ptr2) {
143+
%gep1 = getelementptr inbounds float, ptr addrspace(1) %ptr1, i64 0
144+
%load1 = load float, ptr addrspace(1) %gep1, align 4
145+
%gep2 = getelementptr inbounds <2 x half>, ptr addrspace(1) %ptr1, i64 1
146+
%load2 = load <2 x half>, ptr addrspace(1) %gep2, align 4
147+
ret void
148+
}

0 commit comments

Comments
 (0)