|
18 | 18 | #include "llvm/Constants.h"
|
19 | 19 | #include "llvm/DerivedTypes.h"
|
20 | 20 | #include "llvm/Function.h"
|
| 21 | +#include "llvm/GlobalVariable.h" |
21 | 22 | #include "llvm/IRBuilder.h"
|
22 | 23 | #include "llvm/InlineAsm.h"
|
23 | 24 | #include "llvm/Instructions.h"
|
@@ -126,6 +127,7 @@ namespace {
|
126 | 127 | bool OptimizeSelectInst(SelectInst *SI);
|
127 | 128 | bool DupRetToEnableTailCallOpts(ReturnInst *RI);
|
128 | 129 | bool PlaceDbgValues(Function &F);
|
| 130 | + bool ConvertLoadToSwitch(LoadInst *LI); |
129 | 131 | };
|
130 | 132 | }
|
131 | 133 |
|
@@ -169,7 +171,7 @@ bool CodeGenPrepare::runOnFunction(Function &F) {
|
169 | 171 | bool MadeChange = true;
|
170 | 172 | while (MadeChange) {
|
171 | 173 | MadeChange = false;
|
172 |
| - for (Function::iterator I = F.begin(), E = F.end(); I != E; ) { |
| 174 | + for (Function::iterator I = F.begin(); I != F.end(); ) { |
173 | 175 | BasicBlock *BB = I++;
|
174 | 176 | MadeChange |= OptimizeBlock(*BB);
|
175 | 177 | }
|
@@ -1283,9 +1285,11 @@ bool CodeGenPrepare::OptimizeInst(Instruction *I) {
|
1283 | 1285 | return OptimizeCmpExpression(CI);
|
1284 | 1286 |
|
1285 | 1287 | if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
|
| 1288 | + bool Changed = false; |
1286 | 1289 | if (TLI)
|
1287 |
| - return OptimizeMemoryInst(I, I->getOperand(0), LI->getType()); |
1288 |
| - return false; |
| 1290 | + Changed |= OptimizeMemoryInst(I, I->getOperand(0), LI->getType()); |
| 1291 | + Changed |= ConvertLoadToSwitch(LI); |
| 1292 | + return Changed; |
1289 | 1293 | }
|
1290 | 1294 |
|
1291 | 1295 | if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
|
@@ -1329,7 +1333,7 @@ bool CodeGenPrepare::OptimizeBlock(BasicBlock &BB) {
|
1329 | 1333 | bool MadeChange = false;
|
1330 | 1334 |
|
1331 | 1335 | CurInstIterator = BB.begin();
|
1332 |
| - for (BasicBlock::iterator E = BB.end(); CurInstIterator != E; ) |
| 1336 | + while (CurInstIterator != BB.end()) |
1333 | 1337 | MadeChange |= OptimizeInst(CurInstIterator++);
|
1334 | 1338 |
|
1335 | 1339 | return MadeChange;
|
@@ -1365,3 +1369,109 @@ bool CodeGenPrepare::PlaceDbgValues(Function &F) {
|
1365 | 1369 | }
|
1366 | 1370 | return MadeChange;
|
1367 | 1371 | }
|
| 1372 | + |
| 1373 | +static bool TargetSupportsJumpTables(const TargetLowering &TLI) { |
| 1374 | + return TLI.supportJumpTables() && |
| 1375 | + (TLI.isOperationLegalOrCustom(ISD::BR_JT, MVT::Other) || |
| 1376 | + TLI.isOperationLegalOrCustom(ISD::BRIND, MVT::Other)); |
| 1377 | +} |
| 1378 | + |
| 1379 | +/// ConvertLoadToSwitch - Convert loads from constant lookup tables into |
| 1380 | +/// switches. This undos the switch-to-lookup table transformation in |
| 1381 | +/// SimplifyCFG for targets where that is inprofitable. |
| 1382 | +bool CodeGenPrepare::ConvertLoadToSwitch(LoadInst *LI) { |
| 1383 | + // This only applies to targets that don't support jump tables. |
| 1384 | + if (!TLI || TargetSupportsJumpTables(*TLI)) |
| 1385 | + return false; |
| 1386 | + |
| 1387 | + // FIXME: In the future, it would be desirable to have enough target |
| 1388 | + // information in SimplifyCFG, so we could decide at that stage whether to |
| 1389 | + // transform the switch to a lookup table or not, and this |
| 1390 | + // reverse-transformation could be removed. |
| 1391 | + |
| 1392 | + GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(LI->getPointerOperand()); |
| 1393 | + if (!GEP || !GEP->isInBounds() || GEP->getPointerAddressSpace()) |
| 1394 | + return false; |
| 1395 | + if (GEP->getNumIndices() != 2) |
| 1396 | + return false; |
| 1397 | + Value *FirstIndex = GEP->idx_begin()[0]; |
| 1398 | + ConstantInt *FirstIndexInt = dyn_cast<ConstantInt>(FirstIndex); |
| 1399 | + if (!FirstIndexInt || !FirstIndexInt->isZero()) |
| 1400 | + return false; |
| 1401 | + |
| 1402 | + Value *TableIndex = GEP->idx_begin()[1]; |
| 1403 | + IntegerType *TableIndexTy = cast<IntegerType>(TableIndex->getType()); |
| 1404 | + |
| 1405 | + GlobalVariable *GV = dyn_cast<GlobalVariable>(GEP->getPointerOperand()); |
| 1406 | + if (!GV || !GV->isConstant() || !GV->hasDefinitiveInitializer()) |
| 1407 | + return false; |
| 1408 | + |
| 1409 | + Constant *Arr = GV->getInitializer(); |
| 1410 | + uint64_t NumElements; |
| 1411 | + if (ConstantArray *CA = dyn_cast<ConstantArray>(Arr)) |
| 1412 | + NumElements = CA->getType()->getNumElements(); |
| 1413 | + else if (ConstantDataArray *CDA = dyn_cast<ConstantDataArray>(Arr)) |
| 1414 | + NumElements = CDA->getNumElements(); |
| 1415 | + else |
| 1416 | + return false; |
| 1417 | + if (NumElements < 2) |
| 1418 | + return false; |
| 1419 | + |
| 1420 | + // Split the block. |
| 1421 | + BasicBlock *OriginalBB = LI->getParent(); |
| 1422 | + BasicBlock *PostSwitchBB = OriginalBB->splitBasicBlock(LI); |
| 1423 | + |
| 1424 | + // Replace OriginalBB's terminator with a switch. |
| 1425 | + IRBuilder<> Builder(OriginalBB->getTerminator()); |
| 1426 | + SwitchInst *Switch = Builder.CreateSwitch(TableIndex, PostSwitchBB, |
| 1427 | + NumElements - 1); |
| 1428 | + OriginalBB->getTerminator()->eraseFromParent(); |
| 1429 | + |
| 1430 | + // Count the frequency of each value to decide which to use as default. |
| 1431 | + SmallDenseMap<Constant*, uint64_t> ValueFreq; |
| 1432 | + for (uint64_t I = 0; I < NumElements; ++I) |
| 1433 | + ++ValueFreq[Arr->getAggregateElement(I)]; |
| 1434 | + uint64_t MaxCount = 0; |
| 1435 | + Constant *DefaultValue = NULL; |
| 1436 | + for (SmallDenseMap<Constant*, uint64_t>::iterator I = ValueFreq.begin(), |
| 1437 | + E = ValueFreq.end(); I != E; ++I) { |
| 1438 | + if (I->second > MaxCount) { |
| 1439 | + MaxCount = I->second; |
| 1440 | + DefaultValue = I->first; |
| 1441 | + } |
| 1442 | + } |
| 1443 | + assert(DefaultValue && "No values in the array?"); |
| 1444 | + |
| 1445 | + // Create the phi node in PostSwitchBB, which will replace the load. |
| 1446 | + Builder.SetInsertPoint(PostSwitchBB->begin()); |
| 1447 | + PHINode *PHI = Builder.CreatePHI(LI->getType(), NumElements); |
| 1448 | + PHI->addIncoming(DefaultValue, OriginalBB); |
| 1449 | + |
| 1450 | + // Build basic blocks to target with the switch. |
| 1451 | + for (uint64_t I = 0; I < NumElements; ++I) { |
| 1452 | + Constant *C = Arr->getAggregateElement(I); |
| 1453 | + if (C == DefaultValue) continue; // Already covered by the default case. |
| 1454 | + |
| 1455 | + BasicBlock *BB = BasicBlock::Create(PostSwitchBB->getContext(), |
| 1456 | + "lookup.bb", |
| 1457 | + PostSwitchBB->getParent(), |
| 1458 | + PostSwitchBB); |
| 1459 | + Switch->addCase(ConstantInt::get(TableIndexTy, I), BB); |
| 1460 | + Builder.SetInsertPoint(BB); |
| 1461 | + Builder.CreateBr(PostSwitchBB); |
| 1462 | + PHI->addIncoming(C, BB); |
| 1463 | + } |
| 1464 | + |
| 1465 | + // Remove the load. |
| 1466 | + LI->replaceAllUsesWith(PHI); |
| 1467 | + LI->eraseFromParent(); |
| 1468 | + |
| 1469 | + // Clean up. |
| 1470 | + if (GEP->use_empty()) |
| 1471 | + GEP->eraseFromParent(); |
| 1472 | + if (GV->hasUnnamedAddr() && GV->hasPrivateLinkage() && GV->use_empty()) |
| 1473 | + GV->eraseFromParent(); |
| 1474 | + |
| 1475 | + CurInstIterator = Switch; |
| 1476 | + return true; |
| 1477 | +} |
0 commit comments