Skip to content

Commit f535b86

Browse files
authored
Merge pull request #14028 from eeckstein/option-set
Optimization changes to completely fold OptionSet literals (2nd try)
2 parents 36496ae + 14ae2c2 commit f535b86

34 files changed

+2390
-2094
lines changed

include/swift/SILOptimizer/Analysis/SideEffectAnalysis.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,9 @@ class SideEffectAnalysis : public BottomUpIPAnalysis {
247247
/// Get the array of parameter effects. If a side-effect can be associated
248248
/// to a specific parameter, it is contained here instead of the global
249249
/// effects.
250+
/// Note that if a parameter effect is mayRelease(), it means that the
251+
/// global function effects can be anything, because the destructor of an
252+
/// object can have arbitrary side effects.
250253
ArrayRef<Effects> getParameterEffects() const { return ParamEffects; }
251254

252255
/// Merge effects from \p RHS.

include/swift/SILOptimizer/PassManager/Passes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@ PASS(MoveCondFailToPreds, "move-cond-fail-to-preds",
200200
"Move SIL cond_fail by Hoisting Checks")
201201
PASS(NoReturnFolding, "noreturn-folding",
202202
"Prune Control Flow at No-Return Calls Using SIL unreachable")
203+
PASS(ObjectOutliner, "object-outliner",
204+
"Outlining of Global Objects")
203205
PASS(Outliner, "outliner",
204206
"Function Outlining Optimization")
205207
PASS(OwnershipModelEliminator, "ownership-model-eliminator",

include/swift/SILOptimizer/Utils/ConstantFolding.h

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
#define SWIFT_SIL_CONSTANTFOLDING_H
1919

2020
#include "swift/SIL/SILInstruction.h"
21+
#include "swift/SILOptimizer/Analysis/Analysis.h"
22+
#include "llvm/ADT/SetVector.h"
23+
#include <functional>
2124

2225
namespace swift {
2326

@@ -47,6 +50,52 @@ APInt constantFoldDiv(APInt lhs, APInt rhs, bool &Overflow, BuiltinValueKind ID)
4750
/// The \p ID must be the ID of a trunc/sext/zext builtin.
4851
APInt constantFoldCast(APInt val, const BuiltinInfo &BI);
4952

53+
54+
/// A utility class to do constant folding.
55+
class ConstantFolder {
56+
private:
57+
/// The worklist of the constants that could be folded into their users.
58+
llvm::SetVector<SILInstruction *> WorkList;
59+
60+
/// The assert configuration of SILOptions.
61+
unsigned AssertConfiguration;
62+
63+
/// Print diagnostics as part of mandatory constant propagation.
64+
bool EnableDiagnostics;
65+
66+
/// Called for each constant folded instruction.
67+
std::function<void (SILInstruction *)> Callback;
68+
69+
bool constantFoldStringConcatenation(ApplyInst *AI);
70+
71+
public:
72+
/// The constructor.
73+
///
74+
/// \param AssertConfiguration The assert configuration of SILOptions.
75+
/// \param EnableDiagnostics Print diagnostics as part of mandatory constant
76+
/// propagation.
77+
/// \param Callback Called for each constant folded instruction.
78+
ConstantFolder(unsigned AssertConfiguration,
79+
bool EnableDiagnostics = false,
80+
std::function<void (SILInstruction *)> Callback =
81+
[](SILInstruction *){}) :
82+
AssertConfiguration(AssertConfiguration),
83+
EnableDiagnostics(EnableDiagnostics),
84+
Callback(Callback) { }
85+
86+
/// Initialize the worklist with all instructions of the function \p F.
87+
void initializeWorklist(SILFunction &F);
88+
89+
/// Initialize the worklist with a single instruction \p I.
90+
void addToWorklist(SILInstruction *I) {
91+
WorkList.insert(I);
92+
}
93+
94+
/// Constant fold everything in the worklist and transitively all uses of
95+
/// folded instructions.
96+
SILAnalysis::InvalidationKind processWorkList();
97+
};
98+
5099
} // end namespace swift
51100

52101
#endif

include/swift/SILOptimizer/Utils/Local.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,48 @@ SILType getExactDynamicTypeOfUnderlyingObject(SILValue S, SILModule &M,
616616
void hoistAddressProjections(Operand &Op, SILInstruction *InsertBefore,
617617
DominanceInfo *DomTree);
618618

619+
/// Utility class for cloning init values into the static initializer of a
620+
/// SILGlobalVariable.
621+
class StaticInitCloner : public SILCloner<StaticInitCloner> {
622+
friend class SILInstructionVisitor<StaticInitCloner>;
623+
friend class SILCloner<StaticInitCloner>;
624+
625+
/// The number of not yet cloned operands for each instruction.
626+
llvm::DenseMap<SILInstruction *, int> NumOpsToClone;
627+
628+
/// List of instructions for which all operands are already cloned (or which
629+
/// don't have any operands).
630+
llvm::SmallVector<SILInstruction *, 8> ReadyToClone;
631+
632+
public:
633+
StaticInitCloner(SILGlobalVariable *GVar)
634+
: SILCloner<StaticInitCloner>(GVar) { }
635+
636+
/// Add \p InitVal and all its operands (transitively) for cloning.
637+
///
638+
/// Note: all init values must are added, before calling clone().
639+
void add(SILInstruction *InitVal);
640+
641+
/// Clone \p InitVal and all its operands into the initializer of the
642+
/// SILGlobalVariable.
643+
///
644+
/// \return Returns the cloned instruction in the SILGlobalVariable.
645+
SingleValueInstruction *clone(SingleValueInstruction *InitVal);
646+
647+
/// Convenience function to clone a single \p InitVal.
648+
static void appendToInitializer(SILGlobalVariable *GVar,
649+
SingleValueInstruction *InitVal) {
650+
StaticInitCloner Cloner(GVar);
651+
Cloner.add(InitVal);
652+
Cloner.clone(InitVal);
653+
}
654+
655+
protected:
656+
SILLocation remapLocation(SILLocation Loc) {
657+
return ArtificialUnreachableLocation();
658+
}
659+
};
660+
619661
} // end namespace swift
620662

621663
#endif

lib/SILOptimizer/Analysis/MemoryBehavior.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,10 @@ MemBehavior MemoryBehaviorVisitor::visitApplyInst(ApplyInst *AI) {
268268
Idx < End && Behavior < MemBehavior::MayHaveSideEffects; ++Idx) {
269269
auto &ArgEffect = ApplyEffects.getParameterEffects()[Idx];
270270
auto ArgBehavior = ArgEffect.getMemBehavior(InspectionMode);
271+
if (ArgEffect.mayRelease()) {
272+
Behavior = MemBehavior::MayHaveSideEffects;
273+
break;
274+
}
271275
auto NewBehavior = combineMemoryBehavior(Behavior, ArgBehavior);
272276
if (NewBehavior != Behavior) {
273277
SILValue Arg = AI->getArgument(Idx);

lib/SILOptimizer/Analysis/SideEffectAnalysis.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ static SILValue skipValueProjections(SILValue V) {
120120
case ValueKind::TupleExtractInst:
121121
case ValueKind::UncheckedEnumDataInst:
122122
case ValueKind::UncheckedTrivialBitCastInst:
123+
case ValueKind::UncheckedRefCastInst:
123124
V = cast<SingleValueInstruction>(V)->getOperand(0);
124125
break;
125126
default:
@@ -346,10 +347,6 @@ void SideEffectAnalysis::analyzeInstruction(FunctionInfo *FInfo,
346347
case SILInstructionKind::ReleaseValueInst:
347348
case SILInstructionKind::UnownedReleaseInst:
348349
FInfo->FE.getEffectsOn(I->getOperand(0))->Releases = true;
349-
350-
// TODO: Check the call graph to be less conservative about what
351-
// destructors might be called.
352-
FInfo->FE.setWorstEffects();
353350
return;
354351
case SILInstructionKind::UnconditionalCheckedCastInst:
355352
FInfo->FE.getEffectsOn(cast<UnconditionalCheckedCastInst>(I)->getOperand())->Reads = true;

0 commit comments

Comments
 (0)