|
20 | 20 | #include "llvm/Analysis/ValueLatticeUtils.h" |
21 | 21 | #include "llvm/Analysis/ValueTracking.h" |
22 | 22 | #include "llvm/IR/ConstantRange.h" |
| 23 | +#include "llvm/IR/DerivedTypes.h" |
23 | 24 | #include "llvm/IR/IRBuilder.h" |
24 | 25 | #include "llvm/IR/InstVisitor.h" |
25 | 26 | #include "llvm/IR/Instructions.h" |
@@ -760,6 +761,7 @@ class SCCPInstVisitor : public InstVisitor<SCCPInstVisitor> { |
760 | 761 | void handleCallArguments(CallBase &CB); |
761 | 762 | void handleExtractOfWithOverflow(ExtractValueInst &EVI, |
762 | 763 | const WithOverflowInst *WO, unsigned Idx); |
| 764 | + bool isInstFullyOverDefined(Instruction &Inst); |
763 | 765 |
|
764 | 766 | private: |
765 | 767 | friend class InstVisitor<SCCPInstVisitor>; |
@@ -1374,49 +1376,66 @@ bool SCCPInstVisitor::isEdgeFeasible(BasicBlock *From, BasicBlock *To) const { |
1374 | 1376 | // 7. If a conditional branch has a value that is overdefined, make all |
1375 | 1377 | // successors executable. |
1376 | 1378 | void SCCPInstVisitor::visitPHINode(PHINode &PN) { |
1377 | | - // If this PN returns a struct, just mark the result overdefined. |
1378 | | - // TODO: We could do a lot better than this if code actually uses this. |
1379 | | - if (PN.getType()->isStructTy()) |
1380 | | - return (void)markOverdefined(&PN); |
1381 | | - |
1382 | | - if (getValueState(&PN).isOverdefined()) |
1383 | | - return; // Quick exit |
1384 | | - |
1385 | 1379 | // Super-extra-high-degree PHI nodes are unlikely to ever be marked constant, |
1386 | 1380 | // and slow us down a lot. Just mark them overdefined. |
1387 | 1381 | if (PN.getNumIncomingValues() > 64) |
1388 | 1382 | return (void)markOverdefined(&PN); |
1389 | 1383 |
|
1390 | | - unsigned NumActiveIncoming = 0; |
| 1384 | + if (isInstFullyOverDefined(PN)) |
| 1385 | + return; |
| 1386 | + SmallVector<unsigned> FeasibleIncomingIndices; |
| 1387 | + for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) { |
| 1388 | + if (!isEdgeFeasible(PN.getIncomingBlock(i), PN.getParent())) |
| 1389 | + continue; |
| 1390 | + FeasibleIncomingIndices.push_back(i); |
| 1391 | + } |
1391 | 1392 |
|
1392 | 1393 | // Look at all of the executable operands of the PHI node. If any of them |
1393 | 1394 | // are overdefined, the PHI becomes overdefined as well. If they are all |
1394 | 1395 | // constant, and they agree with each other, the PHI becomes the identical |
1395 | 1396 | // constant. If they are constant and don't agree, the PHI is a constant |
1396 | 1397 | // range. If there are no executable operands, the PHI remains unknown. |
1397 | | - ValueLatticeElement PhiState = getValueState(&PN); |
1398 | | - for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) { |
1399 | | - if (!isEdgeFeasible(PN.getIncomingBlock(i), PN.getParent())) |
1400 | | - continue; |
1401 | | - |
1402 | | - const ValueLatticeElement &IV = getValueState(PN.getIncomingValue(i)); |
1403 | | - PhiState.mergeIn(IV); |
1404 | | - NumActiveIncoming++; |
1405 | | - if (PhiState.isOverdefined()) |
1406 | | - break; |
| 1398 | + if (StructType *STy = dyn_cast<StructType>(PN.getType())) { |
| 1399 | + for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { |
| 1400 | + ValueLatticeElement PhiState = getStructValueState(&PN, i); |
| 1401 | + if (PhiState.isOverdefined()) |
| 1402 | + continue; |
| 1403 | + for (unsigned j : FeasibleIncomingIndices) { |
| 1404 | + const ValueLatticeElement &IV = |
| 1405 | + getStructValueState(PN.getIncomingValue(j), i); |
| 1406 | + PhiState.mergeIn(IV); |
| 1407 | + if (PhiState.isOverdefined()) |
| 1408 | + break; |
| 1409 | + } |
| 1410 | + ValueLatticeElement &PhiStateRef = getStructValueState(&PN, i); |
| 1411 | + mergeInValue(PhiStateRef, &PN, PhiState, |
| 1412 | + ValueLatticeElement::MergeOptions().setMaxWidenSteps( |
| 1413 | + FeasibleIncomingIndices.size() + 1)); |
| 1414 | + PhiStateRef.setNumRangeExtensions( |
| 1415 | + std::max((unsigned)FeasibleIncomingIndices.size(), |
| 1416 | + PhiStateRef.getNumRangeExtensions())); |
| 1417 | + } |
| 1418 | + } else { |
| 1419 | + ValueLatticeElement PhiState = getValueState(&PN); |
| 1420 | + for (unsigned i : FeasibleIncomingIndices) { |
| 1421 | + const ValueLatticeElement &IV = getValueState(PN.getIncomingValue(i)); |
| 1422 | + PhiState.mergeIn(IV); |
| 1423 | + if (PhiState.isOverdefined()) |
| 1424 | + break; |
| 1425 | + } |
| 1426 | + // We allow up to 1 range extension per active incoming value and one |
| 1427 | + // additional extension. Note that we manually adjust the number of range |
| 1428 | + // extensions to match the number of active incoming values. This helps to |
| 1429 | + // limit multiple extensions caused by the same incoming value, if other |
| 1430 | + // incoming values are equal. |
| 1431 | + ValueLatticeElement &PhiStateRef = ValueState[&PN]; |
| 1432 | + mergeInValue(PhiStateRef, &PN, PhiState, |
| 1433 | + ValueLatticeElement::MergeOptions().setMaxWidenSteps( |
| 1434 | + FeasibleIncomingIndices.size() + 1)); |
| 1435 | + PhiStateRef.setNumRangeExtensions( |
| 1436 | + std::max((unsigned)FeasibleIncomingIndices.size(), |
| 1437 | + PhiStateRef.getNumRangeExtensions())); |
1407 | 1438 | } |
1408 | | - |
1409 | | - // We allow up to 1 range extension per active incoming value and one |
1410 | | - // additional extension. Note that we manually adjust the number of range |
1411 | | - // extensions to match the number of active incoming values. This helps to |
1412 | | - // limit multiple extensions caused by the same incoming value, if other |
1413 | | - // incoming values are equal. |
1414 | | - ValueLatticeElement &PhiStateRef = ValueState[&PN]; |
1415 | | - mergeInValue(PhiStateRef, &PN, PhiState, |
1416 | | - ValueLatticeElement::MergeOptions().setMaxWidenSteps( |
1417 | | - NumActiveIncoming + 1)); |
1418 | | - PhiStateRef.setNumRangeExtensions( |
1419 | | - std::max(NumActiveIncoming, PhiStateRef.getNumRangeExtensions())); |
1420 | 1439 | } |
1421 | 1440 |
|
1422 | 1441 | void SCCPInstVisitor::visitReturnInst(ReturnInst &I) { |
@@ -2127,6 +2146,21 @@ void SCCPInstVisitor::handleCallResult(CallBase &CB) { |
2127 | 2146 | } |
2128 | 2147 | } |
2129 | 2148 |
|
| 2149 | +bool SCCPInstVisitor::isInstFullyOverDefined(Instruction &Inst) { |
| 2150 | + // For structure Type, we handle each member separately. |
| 2151 | + // A structure object won't be considered as overdefined when |
| 2152 | + // there is at least one member that is not overdefined. |
| 2153 | + if (StructType *STy = dyn_cast<StructType>(Inst.getType())) { |
| 2154 | + for (unsigned i = 0, e = STy->getNumElements(); i < e; ++i) { |
| 2155 | + if (!getStructValueState(&Inst, i).isOverdefined()) |
| 2156 | + return false; |
| 2157 | + } |
| 2158 | + return true; |
| 2159 | + } |
| 2160 | + |
| 2161 | + return getValueState(&Inst).isOverdefined(); |
| 2162 | +} |
| 2163 | + |
2130 | 2164 | void SCCPInstVisitor::solve() { |
2131 | 2165 | // Process the work lists until they are empty! |
2132 | 2166 | while (!BBWorkList.empty() || !InstWorkList.empty()) { |
|
0 commit comments