@@ -1319,23 +1319,36 @@ void Vectorizer::insertCastsToMergeClasses(EquivalenceClassMap &EQClasses) {
1319
1319
if (EQClasses.size () < 2 )
1320
1320
return ;
1321
1321
1322
+ auto CopyMetaDataFromTo = [&](Instruction *Src, Instruction *Dst) {
1323
+ SmallVector<std::pair<unsigned , MDNode *>, 4 > MD;
1324
+ Src->getAllMetadata (MD);
1325
+ for (const auto [ID, Node] : MD) {
1326
+ Dst->setMetadata (ID, Node);
1327
+ }
1328
+ };
1329
+
1322
1330
// For each class, determine if all instructions are of type int, FP or ptr.
1323
1331
// This information will help us determine the type instructions should be
1324
1332
// casted into.
1325
1333
MapVector<EqClassKey, Bitset<3 >> ClassAllTy;
1326
- for (auto C : EQClasses) {
1327
- if (all_of (EQClasses[C.first ], [](Instruction *I) {
1328
- return I->getType ()->isIntOrIntVectorTy ();
1329
- }))
1330
- ClassAllTy[C.first ].set (0 );
1331
- else if (all_of (EQClasses[C.first ], [](Instruction *I) {
1332
- return I->getType ()->isFPOrFPVectorTy ();
1333
- }))
1334
- ClassAllTy[C.first ].set (1 );
1335
- else if (all_of (EQClasses[C.first ], [](Instruction *I) {
1336
- return I->getType ()->isPtrOrPtrVectorTy ();
1337
- }))
1338
- ClassAllTy[C.first ].set (2 );
1334
+ for (const auto &C : EQClasses) {
1335
+ auto CommonTypeKind = [](Instruction *I) {
1336
+ if (I->getType ()->isIntOrIntVectorTy ())
1337
+ return 0 ;
1338
+ if (I->getType ()->isFPOrFPVectorTy ())
1339
+ return 1 ;
1340
+ if (I->getType ()->isPtrOrPtrVectorTy ())
1341
+ return 2 ;
1342
+ return -1 ; // Invalid type kind
1343
+ };
1344
+
1345
+ int FirstTypeKind = CommonTypeKind (EQClasses[C.first ][0 ]);
1346
+ if (FirstTypeKind != -1 &&
1347
+ all_of (EQClasses[C.first ], [&](Instruction *I) {
1348
+ return CommonTypeKind (I) == FirstTypeKind;
1349
+ })) {
1350
+ ClassAllTy[C.first ].set (FirstTypeKind);
1351
+ }
1339
1352
}
1340
1353
1341
1354
// Loop over all equivalence classes and try to merge them. Keep track of
@@ -1359,6 +1372,11 @@ void Vectorizer::insertCastsToMergeClasses(EquivalenceClassMap &EQClasses) {
1359
1372
if (Ptr1 != Ptr2 || AS1 != AS2 || IsLoad1 != IsLoad2 || TySize1 < TySize2)
1360
1373
continue ;
1361
1374
1375
+ // An All-FP class should only be merged into another All-FP class.
1376
+ if ((ClassAllTy[EC1.first ].test (1 ) && !ClassAllTy[EC2.first ].test (1 )) ||
1377
+ (!ClassAllTy[EC1.first ].test (2 ) && ClassAllTy[EC2.first ].test (2 )))
1378
+ continue ;
1379
+
1362
1380
// Ensure all instructions in EC2 can be bitcasted into NewTy.
1363
1381
// / TODO: NewTyBits is needed as stuctured binded variables cannot be
1364
1382
// / captured by a lambda until C++20.
@@ -1384,8 +1402,8 @@ void Vectorizer::insertCastsToMergeClasses(EquivalenceClassMap &EQClasses) {
1384
1402
}
1385
1403
1386
1404
for (auto *Inst : EC2.second ) {
1387
- auto *Ptr = getLoadStorePointerOperand (Inst);
1388
- auto *OrigTy = Inst->getType ();
1405
+ Value *Ptr = getLoadStorePointerOperand (Inst);
1406
+ Type *OrigTy = Inst->getType ();
1389
1407
if (OrigTy == NewTy)
1390
1408
continue ;
1391
1409
if (auto *LI = dyn_cast<LoadInst>(Inst)) {
@@ -1404,6 +1422,7 @@ void Vectorizer::insertCastsToMergeClasses(EquivalenceClassMap &EQClasses) {
1404
1422
SI->getValueOperand ()->getName () + " .cast" );
1405
1423
auto *NewStore = Builder.CreateStore (
1406
1424
Cast, getLoadStorePointerOperand (SI), SI->isVolatile ());
1425
+ CopyMetaDataFromTo (SI, NewStore);
1407
1426
SI->eraseFromParent ();
1408
1427
EQClasses[EC1.first ].emplace_back (NewStore);
1409
1428
}
@@ -1413,7 +1432,7 @@ void Vectorizer::insertCastsToMergeClasses(EquivalenceClassMap &EQClasses) {
1413
1432
// basic block. This is important to ensure that the instructions are
1414
1433
// vectorized in the correct order.
1415
1434
std::sort (EQClasses[EC1.first ].begin (), EQClasses[EC1.first ].end (),
1416
- [](Instruction *A, Instruction *B) {
1435
+ [](const Instruction *A, const Instruction *B) {
1417
1436
return A && B && A->comesBefore (B);
1418
1437
});
1419
1438
ClassesToErase.insert (EC2.first );
0 commit comments