Skip to content

Commit 34c417d

Browse files
Merge pull request swiftlang#77379 from aschwaighofer/enable_aggressive_reg2mem
Enable heuristic that tries to keep large values in memory
2 parents 8e9df5c + 5105c16 commit 34c417d

File tree

11 files changed

+92
-49
lines changed

11 files changed

+92
-49
lines changed

include/swift/AST/SILOptions.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ class SILOptions {
324324

325325
/// Block expanding and register promotion more aggressively throughout the
326326
/// optimizer.
327-
bool UseAggressiveReg2MemForCodeSize = false;
327+
bool UseAggressiveReg2MemForCodeSize = true;
328328

329329
SILOptions() {}
330330

include/swift/Option/FrontendOptions.td

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1299,10 +1299,10 @@ def disable_lifetime_dependence_diagnostics :
12991299

13001300
def enable_aggressive_reg2mem :
13011301
Flag<["-"], "enable-aggressive-reg2mem">,
1302-
HelpText<"Enable a more aggresive reg2mem heuristic">;
1302+
HelpText<"Enable a more aggressive reg2mem heuristic">;
13031303
def disable_aggressive_reg2mem :
1304-
Flag<["-"], "disable-aggresive-reg2mem">,
1305-
HelpText<"Disable a more aggresive reg2mem heuristic">;
1304+
Flag<["-"], "disable-aggressive-reg2mem">,
1305+
HelpText<"Disable a more aggressive reg2mem heuristic">;
13061306

13071307
def enable_collocate_metadata_functions :
13081308
Flag<["-"], "enable-collocate-metadata-functions">,

include/swift/SIL/InstructionUtils.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,12 @@ bool visitExplodedTupleValue(SILValue value,
236236
std::pair<SILFunction *, SILWitnessTable *>
237237
lookUpFunctionInWitnessTable(WitnessMethodInst *wmi, SILModule::LinkingMode linkingMode);
238238

239+
/// True if a type can be expanded without a significant increase to code size.
240+
///
241+
/// False if expanding a type is invalid. For example, expanding a
242+
/// struct-with-deinit drops the deinit.
243+
bool shouldExpand(SILModule &module, SILType ty);
244+
239245
} // end namespace swift
240246

241247
#endif

include/swift/SILOptimizer/Utils/InstOptUtils.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -417,12 +417,6 @@ ignore_expect_uses(ValueBase *value) {
417417
/// operations from it. These can be simplified and removed.
418418
bool simplifyUsers(SingleValueInstruction *inst);
419419

420-
/// True if a type can be expanded without a significant increase to code size.
421-
///
422-
/// False if expanding a type is invalid. For example, expanding a
423-
/// struct-with-deinit drops the deinit.
424-
bool shouldExpand(SILModule &module, SILType ty);
425-
426420
/// Check if the value of value is computed by means of a simple initialization.
427421
/// Store the actual SILValue into \p Val and the reversed list of instructions
428422
/// initializing it in \p Insns.

lib/IRGen/LoadableByAddress.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3495,6 +3495,7 @@ class LargeLoadableHeuristic {
34953495
UseAggressiveHeuristic(UseAggressiveHeuristic) {}
34963496

34973497
void visit(SILInstruction *i);
3498+
void visit(SILArgument *arg);
34983499

34993500
bool isLargeLoadableType(SILType ty);
35003501
bool isPotentiallyCArray(SILType ty);
@@ -3539,6 +3540,27 @@ class LargeLoadableHeuristic {
35393540
};
35403541
}
35413542

3543+
void LargeLoadableHeuristic::visit(SILArgument *arg) {
3544+
auto objType = arg->getType().getObjectType();
3545+
if (numRegisters(objType) < NumRegistersLargeType)
3546+
return;
3547+
3548+
auto &entry = largeTypeProperties[objType];
3549+
for (auto *use : arg->getUses()) {
3550+
auto *usr = use->getUser();
3551+
switch (usr->getKind()) {
3552+
case SILInstructionKind::TupleExtractInst:
3553+
case SILInstructionKind::StructExtractInst: {
3554+
auto projectionTy = cast<SingleValueInstruction>(usr)->getType();
3555+
if (numRegisters(projectionTy) >= NumRegistersLargeType)
3556+
entry.addProjection();
3557+
break;
3558+
}
3559+
default:
3560+
continue;
3561+
}
3562+
}
3563+
}
35423564
void LargeLoadableHeuristic::visit(SILInstruction *i) {
35433565
if (!UseAggressiveHeuristic)
35443566
return;
@@ -4611,6 +4633,9 @@ static void runPeepholesAndReg2Mem(SILPassManager *pm, SILModule *silMod,
46114633
UseAggressiveHeuristic);
46124634
Peepholes opts(pm, silMod, irgenModule);
46134635
for (SILBasicBlock &BB : currF) {
4636+
for (auto *arg : BB.getArguments()) {
4637+
heuristic.visit(arg);
4638+
}
46144639
for (SILInstruction &I : BB) {
46154640
heuristic.visit(&I);
46164641
if (opts.ignore(&I))

lib/SIL/Utils/InstructionUtils.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,14 @@
2727
#include "swift/SIL/SILVisitor.h"
2828

2929
#include "clang/AST/DeclObjC.h"
30+
#include "llvm/Support/CommandLine.h"
3031

3132
using namespace swift;
3233

34+
static llvm::cl::opt<bool> EnableExpandAll("enable-expand-all",
35+
llvm::cl::init(false));
36+
37+
3338
SILValue swift::lookThroughOwnershipInsts(SILValue v) {
3439
while (true) {
3540
switch (v->getKind()) {
@@ -1412,3 +1417,29 @@ swift::lookUpFunctionInWitnessTable(WitnessMethodInst *wmi,
14121417
return mod.lookUpFunctionInWitnessTable(wmi->getConformance(), wmi->getMember(),
14131418
wmi->isSpecialized(), linkingMode);
14141419
}
1420+
1421+
// True if a type can be expanded without a significant increase to code size.
1422+
//
1423+
// False if expanding a type is invalid. For example, expanding a
1424+
// struct-with-deinit drops the deinit.
1425+
bool swift::shouldExpand(SILModule &module, SILType ty) {
1426+
// FIXME: Expansion
1427+
auto expansion = TypeExpansionContext::minimal();
1428+
1429+
if (module.Types.getTypeLowering(ty, expansion).isAddressOnly()) {
1430+
return false;
1431+
}
1432+
// A move-only-with-deinit type cannot be SROA.
1433+
//
1434+
// TODO: we could loosen this requirement if all paths lead to a drop_deinit.
1435+
if (auto *nominalTy = ty.getNominalOrBoundGenericNominal()) {
1436+
if (nominalTy->getValueTypeDestructor())
1437+
return false;
1438+
}
1439+
if (EnableExpandAll) {
1440+
return true;
1441+
}
1442+
1443+
unsigned numFields = module.Types.countNumberOfFields(ty, expansion);
1444+
return (numFields <= 6);
1445+
}

lib/SILOptimizer/Mandatory/PMOMemoryUseCollector.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -286,9 +286,14 @@ bool ElementUseCollector::collectUses(SILValue Pointer) {
286286
continue;
287287
}
288288

289+
auto &mod = User->getFunction()->getModule();
290+
bool shouldScalarizeTuple =
291+
!mod.getOptions().UseAggressiveReg2MemForCodeSize ||
292+
shouldExpand(mod, PointeeType);
293+
289294
// Loads are a use of the value.
290295
if (isa<LoadInst>(User) || isa<LoadBorrowInst>(User)) {
291-
if (PointeeType.is<TupleType>())
296+
if (PointeeType.is<TupleType>() && shouldScalarizeTuple)
292297
UsesToScalarize.push_back(User);
293298
else
294299
Uses.emplace_back(User, PMOUseKind::Load);
@@ -300,7 +305,8 @@ bool ElementUseCollector::collectUses(SILValue Pointer) {
300305
if (UI->getOperandNumber() == StoreInst::Dest) {
301306
if (auto tupleType = PointeeType.getAs<TupleType>()) {
302307
if (!tupleType->isEqual(Module.getASTContext().TheEmptyTupleType) &&
303-
!tupleType->containsPackExpansionType()) {
308+
!tupleType->containsPackExpansionType() &&
309+
shouldScalarizeTuple) {
304310
UsesToScalarize.push_back(User);
305311
continue;
306312
}
@@ -337,7 +343,8 @@ bool ElementUseCollector::collectUses(SILValue Pointer) {
337343
// have an access that crosses elements.
338344
if (auto tupleType = PointeeType.getAs<TupleType>()) {
339345
if (!tupleType->isEqual(Module.getASTContext().TheEmptyTupleType) &&
340-
!tupleType->containsPackExpansionType()) {
346+
!tupleType->containsPackExpansionType() &&
347+
shouldScalarizeTuple) {
341348
UsesToScalarize.push_back(CAI);
342349
continue;
343350
}

lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@
3838

3939
using namespace swift;
4040

41+
static llvm::cl::opt<bool> EnableAggressiveExpansionBlocking(
42+
"enable-aggressive-expansion-blocking", llvm::cl::init(false));
43+
4144
STATISTIC(NumLoadPromoted, "Number of loads promoted");
4245
STATISTIC(NumLoadTakePromoted, "Number of load takes promoted");
4346
STATISTIC(NumDestroyAddrPromoted, "Number of destroy_addrs promoted");
@@ -3156,7 +3159,8 @@ static AllocationInst *getOptimizableAllocation(SILInstruction *i) {
31563159

31573160
// Don't promote large types.
31583161
auto &mod = alloc->getFunction()->getModule();
3159-
if (mod.getOptions().UseAggressiveReg2MemForCodeSize &&
3162+
if (EnableAggressiveExpansionBlocking &&
3163+
mod.getOptions().UseAggressiveReg2MemForCodeSize &&
31603164
!shouldExpand(mod, alloc->getType().getObjectType()))
31613165
return nullptr;
31623166

lib/SILOptimizer/Utils/InstOptUtils.cpp

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,6 @@
4949

5050
using namespace swift;
5151

52-
static llvm::cl::opt<bool> EnableExpandAll("enable-expand-all",
53-
llvm::cl::init(false));
54-
5552
static llvm::cl::opt<bool> KeepWillThrowCall(
5653
"keep-will-throw-call", llvm::cl::init(false),
5754
llvm::cl::desc(
@@ -1269,32 +1266,6 @@ bool swift::simplifyUsers(SingleValueInstruction *inst) {
12691266
return changed;
12701267
}
12711268

1272-
// True if a type can be expanded without a significant increase to code size.
1273-
//
1274-
// False if expanding a type is invalid. For example, expanding a
1275-
// struct-with-deinit drops the deinit.
1276-
bool swift::shouldExpand(SILModule &module, SILType ty) {
1277-
// FIXME: Expansion
1278-
auto expansion = TypeExpansionContext::minimal();
1279-
1280-
if (module.Types.getTypeLowering(ty, expansion).isAddressOnly()) {
1281-
return false;
1282-
}
1283-
// A move-only-with-deinit type cannot be SROA.
1284-
//
1285-
// TODO: we could loosen this requirement if all paths lead to a drop_deinit.
1286-
if (auto *nominalTy = ty.getNominalOrBoundGenericNominal()) {
1287-
if (nominalTy->getValueTypeDestructor())
1288-
return false;
1289-
}
1290-
if (EnableExpandAll) {
1291-
return true;
1292-
}
1293-
1294-
unsigned numFields = module.Types.countNumberOfFields(ty, expansion);
1295-
return (numFields <= 6);
1296-
}
1297-
12981269
/// Some support functions for the global-opt and let-properties-opts
12991270

13001271
// Encapsulate the state used for recursive analysis of a static

test/IRGen/big_types.sil

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,16 +80,17 @@ unwind:
8080
// CHECK-LABEL: sil @use_yield_big : $@convention(thin) () -> () {
8181
// CHECK: bb0:
8282
// CHECK-NEXT: [[TEMP:%.*]] = alloc_stack $BigStruct
83+
// CHECK-NEXT: [[TEMP2:%.*]] = alloc_stack $BigStruct
8384
// CHECK-NEXT: // function_ref
8485
// CHECK-NEXT: [[CORO:%.*]] = function_ref @test_yield_big : $@yield_once @convention(thin) () -> @yields @in_guaranteed BigStruct
8586
// CHECK-NEXT: ([[ADDR:%.*]], [[TOKEN:%.*]]) = begin_apply [[CORO]]()
86-
// TODO: this isn't very efficient
87-
// CHECK-NEXT: [[T0:%.*]] = load [[ADDR]] : $*BigStruct
88-
// CHECK-NEXT: store [[T0]] to [[TEMP]] : $*BigStruct
87+
// CHECK-NEXT: copy_addr [take] [[ADDR]] to [init] [[TEMP]] : $*BigStruct
88+
// CHECK-NEXT: copy_addr [take] [[TEMP]] to [init] [[TEMP2]] : $*BigStruct
8989
// CHECK-NEXT: // function_ref
9090
// CHECK-NEXT: [[USE:%.*]] = function_ref @use_big_struct : $@convention(thin) (@in_guaranteed BigStruct) -> ()
91-
// CHECK-NEXT: apply [[USE]]([[TEMP]])
91+
// CHECK-NEXT: apply [[USE]]([[TEMP2]])
9292
// CHECK-NEXT: [[RET:%.*]] = end_apply [[TOKEN]] as $()
93+
// CHECK-NEXT: dealloc_stack [[TEMP2]] : $*BigStruct
9394
// CHECK-NEXT: dealloc_stack [[TEMP]] : $*BigStruct
9495
// CHECK-NEXT: return [[RET]] : $()
9596
sil @use_yield_big : $@convention(thin) () -> () {

0 commit comments

Comments
 (0)