|
13 | 13 |
|
14 | 14 | #include "VPlanTransforms.h" |
15 | 15 | #include "VPRecipeBuilder.h" |
| 16 | +#include "VPlan.h" |
16 | 17 | #include "VPlanAnalysis.h" |
17 | 18 | #include "VPlanCFG.h" |
18 | 19 | #include "VPlanDominatorTree.h" |
|
21 | 22 | #include "llvm/ADT/PostOrderIterator.h" |
22 | 23 | #include "llvm/ADT/STLExtras.h" |
23 | 24 | #include "llvm/ADT/SetVector.h" |
| 25 | +#include "llvm/ADT/TypeSwitch.h" |
24 | 26 | #include "llvm/Analysis/IVDescriptors.h" |
25 | 27 | #include "llvm/Analysis/VectorUtils.h" |
26 | 28 | #include "llvm/IR/Intrinsics.h" |
@@ -1316,6 +1318,63 @@ void VPlanTransforms::addActiveLaneMask( |
1316 | 1318 | HeaderMask->replaceAllUsesWith(LaneMask); |
1317 | 1319 | } |
1318 | 1320 |
|
| 1321 | +/// Replace recipes with their EVL variants. |
| 1322 | +static void transformRecipestoEVLRecipes(VPlan &Plan, VPValue &EVL) { |
| 1323 | + SmallVector<VPValue *> HeaderMasks = collectAllHeaderMasks(Plan); |
| 1324 | + for (VPValue *HeaderMask : collectAllHeaderMasks(Plan)) { |
| 1325 | + for (VPUser *U : collectUsersRecursively(HeaderMask)) { |
| 1326 | + auto *CurRecipe = dyn_cast<VPRecipeBase>(U); |
| 1327 | + if (!CurRecipe) |
| 1328 | + continue; |
| 1329 | + auto GetNewMask = [&](VPValue *OrigMask) -> VPValue * { |
| 1330 | + assert(OrigMask && "Unmasked recipe when folding tail"); |
| 1331 | + return HeaderMask == OrigMask ? nullptr : OrigMask; |
| 1332 | + }; |
| 1333 | + |
| 1334 | + VPRecipeBase *NewRecipe = |
| 1335 | + TypeSwitch<VPRecipeBase *, VPRecipeBase *>(CurRecipe) |
| 1336 | + .Case<VPWidenLoadRecipe>([&](VPWidenLoadRecipe *L) { |
| 1337 | + VPValue *NewMask = GetNewMask(L->getMask()); |
| 1338 | + return new VPWidenLoadEVLRecipe(*L, EVL, NewMask); |
| 1339 | + }) |
| 1340 | + .Case<VPWidenStoreRecipe>([&](VPWidenStoreRecipe *S) { |
| 1341 | + VPValue *NewMask = GetNewMask(S->getMask()); |
| 1342 | + return new VPWidenStoreEVLRecipe(*S, EVL, NewMask); |
| 1343 | + }) |
| 1344 | + .Case<VPWidenRecipe>([&](VPWidenRecipe *W) -> VPRecipeBase * { |
| 1345 | + unsigned Opcode = W->getOpcode(); |
| 1346 | + if (!Instruction::isBinaryOp(Opcode) && |
| 1347 | + !Instruction::isUnaryOp(Opcode)) |
| 1348 | + return nullptr; |
| 1349 | + return new VPWidenEVLRecipe(*W, EVL); |
| 1350 | + }) |
| 1351 | + .Case<VPReductionRecipe>([&](VPReductionRecipe *Red) { |
| 1352 | + VPValue *NewMask = GetNewMask(Red->getCondOp()); |
| 1353 | + return new VPReductionEVLRecipe(*Red, EVL, NewMask); |
| 1354 | + }) |
| 1355 | + .Default([&](VPRecipeBase *R) { return nullptr; }); |
| 1356 | + |
| 1357 | + if (!NewRecipe) |
| 1358 | + continue; |
| 1359 | + |
| 1360 | + [[maybe_unused]] unsigned NumDefVal = NewRecipe->getNumDefinedValues(); |
| 1361 | + assert(NumDefVal == CurRecipe->getNumDefinedValues() && |
| 1362 | + "New recipe must define the same number of values as the " |
| 1363 | + "original."); |
| 1364 | + assert( |
| 1365 | + NumDefVal <= 1 && |
| 1366 | + "Only supports recipes with a single definition or without users."); |
| 1367 | + NewRecipe->insertBefore(CurRecipe); |
| 1368 | + if (isa<VPSingleDefRecipe, VPWidenLoadEVLRecipe>(NewRecipe)) { |
| 1369 | + VPValue *CurVPV = CurRecipe->getVPSingleValue(); |
| 1370 | + CurVPV->replaceAllUsesWith(NewRecipe->getVPSingleValue()); |
| 1371 | + } |
| 1372 | + CurRecipe->eraseFromParent(); |
| 1373 | + } |
| 1374 | + recursivelyDeleteDeadRecipes(HeaderMask); |
| 1375 | + } |
| 1376 | +} |
| 1377 | + |
1319 | 1378 | /// Add a VPEVLBasedIVPHIRecipe and related recipes to \p Plan and |
1320 | 1379 | /// replaces all uses except the canonical IV increment of |
1321 | 1380 | /// VPCanonicalIVPHIRecipe with a VPEVLBasedIVPHIRecipe. VPCanonicalIVPHIRecipe |
@@ -1385,48 +1444,8 @@ bool VPlanTransforms::tryAddExplicitVectorLength(VPlan &Plan) { |
1385 | 1444 | NextEVLIV->insertBefore(CanonicalIVIncrement); |
1386 | 1445 | EVLPhi->addOperand(NextEVLIV); |
1387 | 1446 |
|
1388 | | - for (VPValue *HeaderMask : collectAllHeaderMasks(Plan)) { |
1389 | | - for (VPUser *U : collectUsersRecursively(HeaderMask)) { |
1390 | | - VPRecipeBase *NewRecipe = nullptr; |
1391 | | - auto *CurRecipe = dyn_cast<VPRecipeBase>(U); |
1392 | | - if (!CurRecipe) |
1393 | | - continue; |
1394 | | - |
1395 | | - auto GetNewMask = [&](VPValue *OrigMask) -> VPValue * { |
1396 | | - assert(OrigMask && "Unmasked recipe when folding tail"); |
1397 | | - return HeaderMask == OrigMask ? nullptr : OrigMask; |
1398 | | - }; |
1399 | | - if (auto *MemR = dyn_cast<VPWidenMemoryRecipe>(CurRecipe)) { |
1400 | | - VPValue *NewMask = GetNewMask(MemR->getMask()); |
1401 | | - if (auto *L = dyn_cast<VPWidenLoadRecipe>(MemR)) |
1402 | | - NewRecipe = new VPWidenLoadEVLRecipe(*L, *VPEVL, NewMask); |
1403 | | - else if (auto *S = dyn_cast<VPWidenStoreRecipe>(MemR)) |
1404 | | - NewRecipe = new VPWidenStoreEVLRecipe(*S, *VPEVL, NewMask); |
1405 | | - else |
1406 | | - llvm_unreachable("unsupported recipe"); |
1407 | | - } else if (auto *RedR = dyn_cast<VPReductionRecipe>(CurRecipe)) { |
1408 | | - NewRecipe = new VPReductionEVLRecipe(*RedR, *VPEVL, |
1409 | | - GetNewMask(RedR->getCondOp())); |
1410 | | - } |
| 1447 | + transformRecipestoEVLRecipes(Plan, *VPEVL); |
1411 | 1448 |
|
1412 | | - if (NewRecipe) { |
1413 | | - [[maybe_unused]] unsigned NumDefVal = NewRecipe->getNumDefinedValues(); |
1414 | | - assert(NumDefVal == CurRecipe->getNumDefinedValues() && |
1415 | | - "New recipe must define the same number of values as the " |
1416 | | - "original."); |
1417 | | - assert( |
1418 | | - NumDefVal <= 1 && |
1419 | | - "Only supports recipes with a single definition or without users."); |
1420 | | - NewRecipe->insertBefore(CurRecipe); |
1421 | | - if (isa<VPSingleDefRecipe, VPWidenLoadEVLRecipe>(NewRecipe)) { |
1422 | | - VPValue *CurVPV = CurRecipe->getVPSingleValue(); |
1423 | | - CurVPV->replaceAllUsesWith(NewRecipe->getVPSingleValue()); |
1424 | | - } |
1425 | | - CurRecipe->eraseFromParent(); |
1426 | | - } |
1427 | | - } |
1428 | | - recursivelyDeleteDeadRecipes(HeaderMask); |
1429 | | - } |
1430 | 1449 | // Replace all uses of VPCanonicalIVPHIRecipe by |
1431 | 1450 | // VPEVLBasedIVPHIRecipe except for the canonical IV increment. |
1432 | 1451 | CanonicalIVPHI->replaceAllUsesWith(EVLPhi); |
|
0 commit comments