Skip to content

Commit c91fe5f

Browse files
committed
Fix SideEffectsAnalysis for a function with defined @effects
We weren't looking at the parameter conventions that resulted in different side-effects than the defined @effects.
1 parent befeab2 commit c91fe5f

File tree

3 files changed

+82
-19
lines changed

3 files changed

+82
-19
lines changed

include/swift/SILOptimizer/Analysis/SideEffectAnalysis.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,9 @@ class FunctionSideEffects {
418418
/// Returns true if \a F has an @_effects attribute which could be handled.
419419
bool setDefinedEffects(SILFunction *F);
420420

421+
/// Set the parameter effects of a function by looking at their conventions
422+
bool setParamEffects(SILFunction *F);
423+
421424
/// Set the side-effects of a semantic call.
422425
/// Return true if \p ASC could be handled.
423426
bool setSemanticEffects(ArraySemanticsCall ASC);

lib/SILOptimizer/Analysis/SideEffectAnalysis.cpp

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -341,32 +341,45 @@ FunctionSideEffectFlags *FunctionSideEffects::getEffectsOn(SILValue Addr) {
341341
return &GlobalEffects;
342342
}
343343

344+
bool FunctionSideEffects::setParamEffects(SILFunction *F) {
345+
for (auto i :
346+
range(F->getLoweredFunctionType()->getNumIndirectFormalResults())) {
347+
ParamEffects[i].Writes = true;
348+
}
349+
for (auto &paramAndIdx :
350+
enumerate(F->getLoweredFunctionType()->getParameters())) {
351+
auto &param = paramAndIdx.value();
352+
if (param.isIndirectMutating() || param.isConsumed()) {
353+
return false;
354+
}
355+
}
356+
return true;
357+
}
358+
344359
// Return true if the given function has defined effects that were successfully
345360
// recorded in this FunctionSideEffects object.
346361
bool FunctionSideEffects::setDefinedEffects(SILFunction *F) {
347362
if (F->hasSemanticsAttr(SEMANTICS_PROGRAMTERMINATION_POINT)) {
348363
Traps = true;
349364
return true;
350365
}
366+
351367
switch (F->getEffectsKind()) {
352-
case EffectsKind::ReleaseNone:
353-
GlobalEffects.Reads = true;
354-
GlobalEffects.Writes = true;
355-
GlobalEffects.Releases = false;
356-
return true;
357-
case EffectsKind::ReadNone:
358-
return true;
359-
case EffectsKind::ReadOnly:
360-
// @_effects(readonly) is worthless if we have owned parameters, because
361-
// the release inside the callee may call a deinit, which itself can do
362-
// anything.
363-
if (!F->hasOwnedParameters()) {
364-
GlobalEffects.Reads = true;
365-
return true;
366-
}
367-
break;
368-
default:
369-
break;
368+
case EffectsKind::ReleaseNone: {
369+
GlobalEffects.Reads = true;
370+
GlobalEffects.Writes = true;
371+
GlobalEffects.Releases = false;
372+
return setParamEffects(F);
373+
}
374+
case EffectsKind::ReadNone: {
375+
return setParamEffects(F);
376+
}
377+
case EffectsKind::ReadOnly: {
378+
GlobalEffects.Reads = true;
379+
return setParamEffects(F);
380+
}
381+
default:
382+
break;
370383
}
371384

372385
return false;
@@ -523,6 +536,7 @@ void FunctionSideEffects::analyzeInstruction(SILInstruction *I) {
523536
#include "swift/AST/ReferenceStorage.def"
524537
case SILInstructionKind::StrongRetainInst:
525538
case SILInstructionKind::RetainValueInst:
539+
case SILInstructionKind::CopyValueInst:
526540
getEffectsOn(I->getOperand(0))->Retains = true;
527541
return;
528542
#define UNCHECKED_REF_STORAGE(Name, ...) \
@@ -532,6 +546,8 @@ void FunctionSideEffects::analyzeInstruction(SILInstruction *I) {
532546
#include "swift/AST/ReferenceStorage.def"
533547
case SILInstructionKind::StrongReleaseInst:
534548
case SILInstructionKind::ReleaseValueInst:
549+
case SILInstructionKind::DestroyValueInst:
550+
case SILInstructionKind::DestroyAddrInst:
535551
getEffectsOn(I->getOperand(0))->Releases = true;
536552
return;
537553
case SILInstructionKind::UnconditionalCheckedCastInst:

test/SILOptimizer/side-effect.sil

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,12 @@ class X {
3232

3333
init()
3434
}
35-
3635
sil [_semantics "programtermination_point"] @exitfunc : $@convention(thin) () -> Never
3736
sil [readnone] @pure_func : $@convention(thin) () -> ()
3837
sil [releasenone] @releasenone_func : $@convention(thin) () -> ()
3938
sil [readonly] @readonly_owned : $@convention(thin) (@owned X) -> ()
4039
sil [readonly] @readonly_guaranteed : $@convention(thin) (@guaranteed X) -> ()
40+
sil [readnone] [ossa] @get_object : $@convention(thin) () -> (@owned X)
4141

4242
sil @unknown_func : $@convention(thin) () -> ()
4343

@@ -551,3 +551,47 @@ bb0:
551551
return %r : $()
552552
}
553553

554+
// CHECK-LABEL: sil @readonly_and_store
555+
// CHECK: <func=r,param0=w>
556+
sil [readonly] [ossa] @readonly_and_store : $@convention(thin) () -> @out X {
557+
bb0(%0 : $*X):
558+
%f = function_ref @get_object : $@convention(thin) () -> (@owned X)
559+
%a = apply %f() : $@convention(thin) () -> (@owned X)
560+
store %a to [init] %0 : $*X
561+
%r = tuple ()
562+
return %r : $()
563+
}
564+
565+
sil [readonly] [ossa] @readonly_ownedparam : $@convention(thin) (@owned X) -> () {
566+
bb0(%0 : @owned $X):
567+
destroy_value %0 : $X
568+
%r = tuple ()
569+
return %r : $()
570+
}
571+
572+
sil [readonly] [ossa] @readonly_inoutparam : $@convention(thin) (@inout X) -> () {
573+
bb0(%0 : $*X):
574+
%f = function_ref @get_object : $@convention(thin) () -> (@owned X)
575+
%a = apply %f() : $@convention(thin) () -> (@owned X)
576+
destroy_addr %0 : $*X
577+
store %a to [init] %0 : $*X
578+
%r = tuple ()
579+
return %r : $()
580+
}
581+
582+
sil [readnone] [ossa] @readnone_ownedparam : $@convention(thin) (@owned X) -> () {
583+
bb0(%0 : @owned $X):
584+
destroy_value %0 : $X
585+
%r = tuple ()
586+
return %r : $()
587+
}
588+
589+
sil [readnone] [ossa] @readnone_inoutparam : $@convention(thin) (@inout X) -> () {
590+
bb0(%0 : $*X):
591+
%f = function_ref @get_object : $@convention(thin) () -> (@owned X)
592+
%a = apply %f() : $@convention(thin) () -> (@owned X)
593+
destroy_addr %0 : $*X
594+
store %a to [init] %0 : $*X
595+
%r = tuple ()
596+
return %r : $()
597+
}

0 commit comments

Comments
 (0)