From 5dd322ffaf9dab6701c87c99752cca54f84f2977 Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Fri, 5 Feb 2021 08:53:03 +0100 Subject: [PATCH] SILCombine: remove release_value of a trivial enum Even if the enum type is not trivial (because it has not trivial payloads for some cases), a release of such an enum can be removed if the enum is constructed with a trivial case. --- .../SILCombiner/SILCombinerMiscVisitors.cpp | 6 +++ test/SILOptimizer/sil_combine.sil | 43 +++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp b/lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp index daa175a4a31e3..fbf4042cbdddd 100644 --- a/lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp +++ b/lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp @@ -1000,6 +1000,7 @@ SILInstruction *SILCombiner::visitIndexAddrInst(IndexAddrInst *IA) { /// Walks over all fields of an aggregate and checks if a reference count /// operation for \p value is required. This differs from a simple `isTrivial` /// check, because it treats a value_to_bridge_object instruction as "trivial". +/// It can also handle non-trivial enums with trivial cases. static bool isTrivial(SILValue value, SILFunction *function) { SmallVector workList; SmallPtrSet visited; @@ -1017,6 +1018,11 @@ static bool isTrivial(SILValue value, SILFunction *function) { } continue; } + if (auto *en = dyn_cast(v)) { + if (en->hasOperand() && visited.insert(en->getOperand()).second) + workList.push_back(en->getOperand()); + continue; + } return false; } return true; diff --git a/test/SILOptimizer/sil_combine.sil b/test/SILOptimizer/sil_combine.sil index fa821eaa276c6..583dd7bcaf495 100644 --- a/test/SILOptimizer/sil_combine.sil +++ b/test/SILOptimizer/sil_combine.sil @@ -3855,6 +3855,49 @@ bb0(%0 : $UInt64): return %7 : $() } +enum EnumWithPayload { + case A(UInt64) + case B(AnyObject) + case C +} + +// CHECK-LABEL: sil @optimize_arc_with_trivial_payload_enum +// CHECK: bb0(%0 : $UInt64): +// CHECK-NEXT: tuple +// CHECK-NEXT: return +// CHECK: } // end sil function 'optimize_arc_with_trivial_payload_enum' +sil @optimize_arc_with_trivial_payload_enum : $@convention(thin) (UInt64) -> () { +bb0(%0 : $UInt64): + %1 = enum $EnumWithPayload, #EnumWithPayload.A!enumelt, %0 : $UInt64 + release_value %1 : $EnumWithPayload + %7 = tuple () + return %7 : $() +} + +// CHECK-LABEL: sil @optimize_arc_with_trivial_enum +// CHECK: bb0: +// CHECK-NEXT: tuple +// CHECK-NEXT: return +// CHECK: } // end sil function 'optimize_arc_with_trivial_enum' +sil @optimize_arc_with_trivial_enum : $@convention(thin) () -> () { +bb0: + %1 = enum $EnumWithPayload, #EnumWithPayload.C!enumelt + release_value %1 : $EnumWithPayload + %7 = tuple () + return %7 : $() +} + +// CHECK-LABEL: sil @dont_remove_release_of_nontrivial_enum +// CHECK: strong_release %0 +// CHECK: } // end sil function 'dont_remove_release_of_nontrivial_enum' +sil @dont_remove_release_of_nontrivial_enum : $@convention(thin) (@guaranteed AnyObject) -> () { +bb0(%0 : $AnyObject): + %1 = enum $EnumWithPayload, #EnumWithPayload.B!enumelt, %0 : $AnyObject + release_value %1 : $EnumWithPayload + %7 = tuple () + return %7 : $() +} + // CHECK-LABEL: sil @optimize_stringObject_bit_operations // CHECK: bb0: // CHECK-NEXT: %0 = integer_literal $Builtin.Int64, 4611686018427387904