@@ -53,6 +53,11 @@ static cl::opt<bool>
53
53
AdjustJumpTableBlocks (" arm-adjust-jump-tables" , cl::Hidden, cl::init(true ),
54
54
cl::desc(" Adjust basic block layout to better use TB[BH]" ));
55
55
56
+ static cl::opt<unsigned >
57
+ CPMaxIteration (" arm-constant-island-max-iteration" , cl::Hidden, cl::init(30 ),
58
+ cl::desc(" The max number of iteration for converge" ));
59
+
60
+
56
61
// / UnknownPadding - Return the worst case padding that could result from
57
62
// / unknown offset bits. This does not include alignment padding caused by
58
63
// / known offset bits.
@@ -293,10 +298,10 @@ namespace {
293
298
unsigned getCombinedIndex (const MachineInstr *CPEMI);
294
299
int findInRangeCPEntry (CPUser& U, unsigned UserOffset);
295
300
bool findAvailableWater (CPUser&U, unsigned UserOffset,
296
- water_iterator &WaterIter);
301
+ water_iterator &WaterIter, bool CloserWater );
297
302
void createNewWater (unsigned CPUserIndex, unsigned UserOffset,
298
303
MachineBasicBlock *&NewMBB);
299
- bool handleConstantPoolUser (unsigned CPUserIndex);
304
+ bool handleConstantPoolUser (unsigned CPUserIndex, bool CloserWater );
300
305
void removeDeadCPEMI (MachineInstr *CPEMI);
301
306
bool removeUnusedCPEntries ();
302
307
bool isCPEntryInRange (MachineInstr *MI, unsigned UserOffset,
@@ -456,8 +461,11 @@ bool ARMConstantIslands::runOnMachineFunction(MachineFunction &mf) {
456
461
DEBUG (dbgs () << " Beginning CP iteration #" << NoCPIters << ' \n ' );
457
462
bool CPChange = false ;
458
463
for (unsigned i = 0 , e = CPUsers.size (); i != e; ++i)
459
- CPChange |= handleConstantPoolUser (i);
460
- if (CPChange && ++NoCPIters > 30 )
464
+ // For most inputs, it converges in no more than 5 iterations.
465
+ // If it doens't end in 10, the input may have huge BB or many CPEs.
466
+ // In this case, we will try differnt heuristics.
467
+ CPChange |= handleConstantPoolUser (i, NoCPIters >= CPMaxIteration / 2 );
468
+ if (CPChange && ++NoCPIters > CPMaxIteration)
461
469
report_fatal_error (" Constant Island pass failed to converge!" );
462
470
DEBUG (dumpBBs ());
463
471
@@ -1285,11 +1293,27 @@ static inline unsigned getUnconditionalBrDisp(int Opc) {
1285
1293
// / move to a lower address, so search backward from the end of the list and
1286
1294
// / prefer the first water that is in range.
1287
1295
bool ARMConstantIslands::findAvailableWater (CPUser &U, unsigned UserOffset,
1288
- water_iterator &WaterIter) {
1296
+ water_iterator &WaterIter,
1297
+ bool CloserWater) {
1289
1298
if (WaterList.empty ())
1290
1299
return false ;
1291
1300
1292
1301
unsigned BestGrowth = ~0u ;
1302
+ // The nearest water without splitting the UserBB is right after it.
1303
+ // If the distance is still large (we have a big BB), then we need to split it
1304
+ // if we don't converge after certain iterations. This helps the following
1305
+ // situation to converge:
1306
+ // BB0:
1307
+ // Big BB
1308
+ // BB1:
1309
+ // Constant Pool
1310
+ // When a CP access is out of range, BB0 may be used as water. However,
1311
+ // inserting islands between BB0 and BB1 makes other accesses out of range.
1312
+ MachineBasicBlock *UserBB = U.MI ->getParent ();
1313
+ unsigned MinNoSplitDisp =
1314
+ BBInfo[UserBB->getNumber ()].postOffset (getCPELogAlign (U.CPEMI ));
1315
+ if (CloserWater && MinNoSplitDisp > U.getMaxDisp () / 2 )
1316
+ return false ;
1293
1317
for (water_iterator IP = std::prev (WaterList.end ()), B = WaterList.begin ();;
1294
1318
--IP) {
1295
1319
MachineBasicBlock* WaterBB = *IP;
@@ -1301,6 +1325,8 @@ bool ARMConstantIslands::findAvailableWater(CPUser &U, unsigned UserOffset,
1301
1325
// should be relatively uncommon and when it does happen, we want to be
1302
1326
// sure to take advantage of it for all the CPEs near that block, so that
1303
1327
// we don't insert more branches than necessary.
1328
+ // When CloserWater is true, we try to find the lowest address after (or
1329
+ // equal to) user MI's BB no matter of padding growth.
1304
1330
unsigned Growth;
1305
1331
if (isWaterInRange (UserOffset, WaterBB, U, Growth) &&
1306
1332
(WaterBB->getNumber () < U.HighWaterMark ->getNumber () ||
@@ -1312,8 +1338,11 @@ bool ARMConstantIslands::findAvailableWater(CPUser &U, unsigned UserOffset,
1312
1338
DEBUG (dbgs () << " Found water after BB#" << WaterBB->getNumber ()
1313
1339
<< " Growth=" << Growth << ' \n ' );
1314
1340
1315
- // Keep looking unless it is perfect.
1316
- if (BestGrowth == 0 )
1341
+ if (CloserWater && WaterBB == U.MI ->getParent ())
1342
+ return true ;
1343
+ // Keep looking unless it is perfect and we're not looking for the lowest
1344
+ // possible address.
1345
+ if (!CloserWater && BestGrowth == 0 )
1317
1346
return true ;
1318
1347
}
1319
1348
if (IP == B)
@@ -1471,7 +1500,8 @@ void ARMConstantIslands::createNewWater(unsigned CPUserIndex,
1471
1500
// / is out-of-range. If so, pick up the constant pool value and move it some
1472
1501
// / place in-range. Return true if we changed any addresses (thus must run
1473
1502
// / another pass of branch lengthening), false otherwise.
1474
- bool ARMConstantIslands::handleConstantPoolUser (unsigned CPUserIndex) {
1503
+ bool ARMConstantIslands::handleConstantPoolUser (unsigned CPUserIndex,
1504
+ bool CloserWater) {
1475
1505
CPUser &U = CPUsers[CPUserIndex];
1476
1506
MachineInstr *UserMI = U.MI ;
1477
1507
MachineInstr *CPEMI = U.CPEMI ;
@@ -1494,7 +1524,7 @@ bool ARMConstantIslands::handleConstantPoolUser(unsigned CPUserIndex) {
1494
1524
MachineBasicBlock *NewIsland = MF->CreateMachineBasicBlock ();
1495
1525
MachineBasicBlock *NewMBB;
1496
1526
water_iterator IP;
1497
- if (findAvailableWater (U, UserOffset, IP)) {
1527
+ if (findAvailableWater (U, UserOffset, IP, CloserWater )) {
1498
1528
DEBUG (dbgs () << " Found water in range\n " );
1499
1529
MachineBasicBlock *WaterBB = *IP;
1500
1530
0 commit comments