Skip to content

Commit 3da8595

Browse files
authored
Merge pull request #32664 from eeckstein/revert-offsetof-opt
2 parents 906b3cb + 723a205 commit 3da8595

File tree

4 files changed

+20
-350
lines changed

4 files changed

+20
-350
lines changed

lib/SILOptimizer/SILCombiner/SILCombiner.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -246,11 +246,8 @@ class SILCombiner :
246246
bool tryOptimizeKeypath(ApplyInst *AI);
247247
bool tryOptimizeInoutKeypath(BeginApplyInst *AI);
248248
bool tryOptimizeKeypathApplication(ApplyInst *AI, SILFunction *callee);
249-
bool tryOptimizeKeypathOffsetOf(ApplyInst *AI, FuncDecl *calleeFn,
250-
KeyPathInst *kp);
251-
bool tryOptimizeKeypathKVCString(ApplyInst *AI, FuncDecl *calleeFn,
252-
KeyPathInst *kp);
253-
249+
bool tryOptimizeKeypathKVCString(ApplyInst *AI, SILDeclRef callee);
250+
254251
// Optimize concatenation of string literals.
255252
// Constant-fold concatenation of string literals known at compile-time.
256253
SILInstruction *optimizeConcatenationOfStringLiterals(ApplyInst *AI);

lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp

Lines changed: 18 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -271,122 +271,6 @@ bool SILCombiner::tryOptimizeKeypathApplication(ApplyInst *AI,
271271
return true;
272272
}
273273

274-
/// Replaces a call of the getter of AnyKeyPath._storedInlineOffset with a
275-
/// "constant" offset, in case of a keypath literal.
276-
///
277-
/// "Constant" offset means a series of struct_element_addr and
278-
/// tuple_element_addr instructions with a 0-pointer as base address.
279-
/// These instructions can then be lowered to "real" constants in IRGen for
280-
/// concrete types, or to metatype offset lookups for generic or resilient types.
281-
///
282-
/// Replaces:
283-
/// %kp = keypath ...
284-
/// %offset = apply %_storedInlineOffset_method(%kp)
285-
/// with:
286-
/// %zero = integer_literal $Builtin.Word, 0
287-
/// %null_ptr = unchecked_trivial_bit_cast %zero to $Builtin.RawPointer
288-
/// %null_addr = pointer_to_address %null_ptr
289-
/// %projected_addr = struct_element_addr %null_addr
290-
/// ... // other address projections
291-
/// %offset_ptr = address_to_pointer %projected_addr
292-
/// %offset_builtin_int = unchecked_trivial_bit_cast %offset_ptr
293-
/// %offset_int = struct $Int (%offset_builtin_int)
294-
/// %offset = enum $Optional<Int>, #Optional.some!enumelt, %offset_int
295-
bool SILCombiner::tryOptimizeKeypathOffsetOf(ApplyInst *AI,
296-
FuncDecl *calleeFn,
297-
KeyPathInst *kp) {
298-
auto *accessor = dyn_cast<AccessorDecl>(calleeFn);
299-
if (!accessor || !accessor->isGetter())
300-
return false;
301-
302-
AbstractStorageDecl *storage = accessor->getStorage();
303-
DeclName name = storage->getName();
304-
if (!name.isSimpleName() ||
305-
(name.getBaseIdentifier().str() != "_storedInlineOffset"))
306-
return false;
307-
308-
KeyPathPattern *pattern = kp->getPattern();
309-
SubstitutionMap patternSubs = kp->getSubstitutions();
310-
CanType rootTy = pattern->getRootType().subst(patternSubs)->getCanonicalType();
311-
CanType parentTy = rootTy;
312-
313-
// First check if _storedInlineOffset would return an offset or nil. Basically
314-
// only stored struct and tuple elements produce an offset. Everything else
315-
// (e.g. computed properties, class properties) result in nil.
316-
bool hasOffset = true;
317-
for (const KeyPathPatternComponent &component : pattern->getComponents()) {
318-
switch (component.getKind()) {
319-
case KeyPathPatternComponent::Kind::StoredProperty: {
320-
if (!parentTy.getStructOrBoundGenericStruct())
321-
hasOffset = false;
322-
break;
323-
}
324-
case KeyPathPatternComponent::Kind::TupleElement:
325-
break;
326-
case KeyPathPatternComponent::Kind::GettableProperty:
327-
case KeyPathPatternComponent::Kind::SettableProperty:
328-
// We cannot predict the offset of fields in resilient types, because it's
329-
// unknown if a resilient field is a computed or stored property.
330-
if (component.getExternalDecl())
331-
return false;
332-
hasOffset = false;
333-
break;
334-
case KeyPathPatternComponent::Kind::OptionalChain:
335-
case KeyPathPatternComponent::Kind::OptionalForce:
336-
case KeyPathPatternComponent::Kind::OptionalWrap:
337-
hasOffset = false;
338-
break;
339-
}
340-
parentTy = component.getComponentType();
341-
}
342-
343-
SILLocation loc = AI->getLoc();
344-
SILValue result;
345-
346-
if (hasOffset) {
347-
SILType rootAddrTy = SILType::getPrimitiveAddressType(rootTy);
348-
SILValue rootAddr = Builder.createBaseAddrForOffset(loc, rootAddrTy);
349-
350-
auto projector = KeyPathProjector::create(kp, rootAddr, loc, Builder);
351-
if (!projector)
352-
return false;
353-
354-
// Create the address projections of the keypath.
355-
SILType ptrType = SILType::getRawPointerType(Builder.getASTContext());
356-
SILValue offsetPtr;
357-
projector->project(KeyPathProjector::AccessType::Get, [&](SILValue addr) {
358-
offsetPtr = Builder.createAddressToPointer(loc, addr, ptrType);
359-
});
360-
361-
// The result of the _storedInlineOffset call should be Optional<Int>. If
362-
// not, something is wrong with the stdlib. Anyway, if it's not like we
363-
// expect, bail.
364-
SILType intType = AI->getType().getOptionalObjectType();
365-
if (!intType)
366-
return false;
367-
StructDecl *intDecl = intType.getStructOrBoundGenericStruct();
368-
if (!intDecl || intDecl->getStoredProperties().size() != 1)
369-
return false;
370-
VarDecl *member = intDecl->getStoredProperties()[0];
371-
CanType builtinIntTy = member->getType()->getCanonicalType();
372-
if (!isa<BuiltinIntegerType>(builtinIntTy))
373-
return false;
374-
375-
// Convert the projected address back to an optional integer.
376-
SILValue offset = Builder.createUncheckedBitCast(loc, offsetPtr,
377-
SILType::getPrimitiveObjectType(builtinIntTy));
378-
SILValue offsetInt = Builder.createStruct(loc, intType, { offset });
379-
result = Builder.createOptionalSome(loc, offsetInt, AI->getType());
380-
} else {
381-
// The keypath has no offset.
382-
result = Builder.createOptionalNone(loc, AI->getType());
383-
}
384-
AI->replaceAllUsesWith(result);
385-
eraseInstFromFunction(*AI);
386-
++NumOptimizedKeypaths;
387-
return true;
388-
}
389-
390274
/// Try to optimize a keypath KVC string access on a literal key path.
391275
///
392276
/// Replace:
@@ -395,8 +279,17 @@ bool SILCombiner::tryOptimizeKeypathOffsetOf(ApplyInst *AI,
395279
/// With:
396280
/// %string = string_literal "blah"
397281
bool SILCombiner::tryOptimizeKeypathKVCString(ApplyInst *AI,
398-
FuncDecl *calleeFn,
399-
KeyPathInst *kp) {
282+
SILDeclRef callee) {
283+
if (AI->getNumArguments() != 1) {
284+
return false;
285+
}
286+
if (!callee.hasDecl()) {
287+
return false;
288+
}
289+
auto calleeFn = dyn_cast<FuncDecl>(callee.getDecl());
290+
if (!calleeFn)
291+
return false;
292+
400293
if (!calleeFn->getAttrs()
401294
.hasSemanticsAttr(semantics::KEYPATH_KVC_KEY_PATH_STRING))
402295
return false;
@@ -407,6 +300,11 @@ bool SILCombiner::tryOptimizeKeypathKVCString(ApplyInst *AI,
407300
if (!objTy || objTy.getStructOrBoundGenericStruct() != C.getStringDecl())
408301
return false;
409302

303+
KeyPathInst *kp
304+
= KeyPathProjector::getLiteralKeyPath(AI->getArgument(0));
305+
if (!kp || !kp->hasPattern())
306+
return false;
307+
410308
auto objcString = kp->getPattern()->getObjCString();
411309

412310
SILValue literalValue;
@@ -459,33 +357,10 @@ bool SILCombiner::tryOptimizeKeypath(ApplyInst *AI) {
459357
return tryOptimizeKeypathApplication(AI, callee);
460358
}
461359

462-
// Try optimize keypath method calls.
463-
auto *methodInst = dyn_cast<ClassMethodInst>(AI->getCallee());
464-
if (!methodInst)
465-
return false;
466-
467-
if (AI->getNumArguments() != 1) {
468-
return false;
469-
}
470-
471-
SILDeclRef callee = methodInst->getMember();
472-
if (!callee.hasDecl()) {
473-
return false;
360+
if (auto method = dyn_cast<ClassMethodInst>(AI->getCallee())) {
361+
return tryOptimizeKeypathKVCString(AI, method->getMember());
474362
}
475-
auto *calleeFn = dyn_cast<FuncDecl>(callee.getDecl());
476-
if (!calleeFn)
477-
return false;
478-
479-
KeyPathInst *kp = KeyPathProjector::getLiteralKeyPath(AI->getArgument(0));
480-
if (!kp || !kp->hasPattern())
481-
return false;
482363

483-
if (tryOptimizeKeypathOffsetOf(AI, calleeFn, kp))
484-
return true;
485-
486-
if (tryOptimizeKeypathKVCString(AI, calleeFn, kp))
487-
return true;
488-
489364
return false;
490365
}
491366

test/SILOptimizer/Inputs/struct_with_fields.swift

Lines changed: 0 additions & 5 deletions
This file was deleted.

0 commit comments

Comments
 (0)