Teach CopyForwarding to handle enum initialization sequences.

This requires a bit of code motion.

e.g.

1. %Tmp = alloc_stack
2. copy_addr %InArg to [initialization] %Tmp
3. DataAddr = init_enum_data_addr %OutArg
4. copy_addr %Tmp#1 to [initialization] %DataAddr

becomes

1. %Tmp = alloc_stack
4. DataAddr = init_enum_data_addr %OutArg
2. copy_addr %InArg to [initialization] %DataAddr

Fixes at least one regression resulting from '++' removal.
See rdar://23874709 [perf] -Onone Execution Time regression of up-to 19%

-Onone results
|.benchmark............|.bestbase.|.bestopt.|..delta.|.%delta.|speedup.|
|.StringWalk...........|....33570.|...20967.|.-12603.|.-37.5%.|..1.60x.|
|.OpenClose............|......446.|.....376.|....-70.|.-15.7%.|..1.19x.|
|.SmallPT..............|....98959.|...83964.|.-14995.|.-15.2%.|..1.18x.|
|.StrToInt.............|....17550.|...16377.|..-1173.|..-6.7%.|..1.07x.|
|.BenchLangCallingCFunc|......453.|.....428.|....-25.|..-5.5%.|..1.06x.|
|.CaptureProp..........|....50758.|...48156.|..-2602.|..-5.1%.|..1.05x.|
|.ProtocolDispatch.....|.....5276.|....5017.|...-259.|..-4.9%.|..1.05x.|
|.Join.................|.....1433.|....1372.|....-61.|..-4.3%.|..1.04x.|
This commit is contained in:
Andrew Trick
2015-12-16 21:43:23 -08:00
parent 9a85a0254f
commit 0c7ee1f283
2 changed files with 61 additions and 4 deletions

View File

@@ -751,6 +751,30 @@ bool CopyForwarding::forwardPropagateCopy(
return true;
}
/// Given an address defined by 'Def', find the object root and all direct uses,
/// not including:
/// - 'Def' itself
/// - Transitive uses of 'Def' (listed elsewhere in DestUserInsts)
///
/// If the returned root is not 'Def' itself, then 'Def' must be an address
/// projection that can be trivially rematerialized with the root as its
/// operand.
static ValueBase *
findAddressRootAndUsers(ValueBase *Def,
SmallPtrSetImpl<SILInstruction*> &RootUserInsts) {
if (auto EDAI = dyn_cast<InitEnumDataAddrInst>(Def)) {
auto EnumRoot = EDAI->getOperand();
for (auto *Use : EnumRoot.getUses()) {
auto *UserInst = Use->getUser();
if (UserInst == Def)
continue;
RootUserInsts.insert(UserInst);
}
return EnumRoot.getDef();
}
return Def;
}
/// Perform backward copy-propagation. Find the initialization point of the
/// copy's source and replace the initializer's address with the copy's dest.
bool CopyForwarding::backwardPropagateCopy(
@@ -759,25 +783,33 @@ bool CopyForwarding::backwardPropagateCopy(
SILValue CopySrc = CopyInst->getSrc();
ValueBase *CopyDestDef = CopyInst->getDest().getDef();
SmallPtrSet<SILInstruction*, 8> RootUserInsts;
ValueBase *CopyDestRoot = findAddressRootAndUsers(CopyDestDef, RootUserInsts);
// Require the copy dest value to be identified by this address. This ensures
// that all instructions that may write to destination address depend on
// CopyDestDef.
if (!isIdentifiedDestValue(CopyDestDef))
// CopyDestRoot.
if (!isIdentifiedDestValue(CopyDestRoot))
return false;
// Scan backward recording all operands that use CopySrc until we see the
// most recent init of CopySrc.
bool seenInit = false;
bool seenCopyDestDef = false;
// ValueUses records the uses of CopySrc in reverse order.
SmallVector<Operand*, 16> ValueUses;
SmallVector<DebugValueAddrInst*, 4> DebugValueInstsToDelete;
auto SI = CopyInst->getIterator(), SE = CopyInst->getParent()->begin();
while (SI != SE) {
--SI;
SILInstruction *UserInst = &*SI;
if (UserInst == CopyDestDef)
seenCopyDestDef = true;
// If we see another use of Dest, then Dest is live after the Src location
// is initialized, so we really need the copy.
if (DestUserInsts.count(UserInst) || UserInst == CopyDestDef) {
if (UserInst == CopyDestRoot || DestUserInsts.count(UserInst)
|| RootUserInsts.count(UserInst)) {
if (auto *DVAI = dyn_cast<DebugValueAddrInst>(UserInst)) {
DebugValueInstsToDelete.push_back(DVAI);
continue;
@@ -797,7 +829,7 @@ bool CopyForwarding::backwardPropagateCopy(
// If this use cannot be analyzed, then abort.
if (!AnalyzeUse.Oper)
return false;
// Otherwise record the operand.
// Otherwise record the operand with the earliest use last in the list.
ValueUses.push_back(AnalyzeUse.Oper);
// If this is an init, we're done searching.
if (seenInit)
@@ -819,6 +851,10 @@ bool CopyForwarding::backwardPropagateCopy(
Copy->setIsInitializationOfDest(IsInitialization);
}
}
// Rematerialize the projection if needed by simply moving it.
if (seenCopyDestDef) {
cast<SILInstruction>(CopyDestDef)->moveBefore(&*SI);
}
// Now that an init was found, it is safe to substitute all recorded uses
// with the copy's dest.
for (auto *Oper : ValueUses) {