Skip to content

Commit 8f1b353

Browse files
committed
[mandatory-combine] Just like SILCombine, perform SIL canonicialization while performing mandatory combining.
1 parent 06a712b commit 8f1b353

File tree

5 files changed

+79
-8
lines changed

5 files changed

+79
-8
lines changed

lib/SILOptimizer/Mandatory/MandatoryCombine.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "swift/SIL/SILVisitor.h"
3232
#include "swift/SILOptimizer/PassManager/Passes.h"
3333
#include "swift/SILOptimizer/PassManager/Transforms.h"
34+
#include "swift/SILOptimizer/Utils/CanonicalizeInstruction.h"
3435
#include "swift/SILOptimizer/Utils/InstOptUtils.h"
3536
#include "swift/SILOptimizer/Utils/StackNesting.h"
3637
#include "llvm/ADT/STLExtras.h"
@@ -53,6 +54,54 @@ static bool areAllValuesTrivial(Values values, SILFunction &function) {
5354
});
5455
}
5556

57+
//===----------------------------------------------------------------------===//
58+
// CanonicalizeInstruction subclass for use in Mandatory Combiner.
59+
//===----------------------------------------------------------------------===//
60+
61+
namespace {
62+
63+
class MandatoryCombineCanonicalize final : CanonicalizeInstruction {
64+
public:
65+
using Worklist = SmallSILInstructionWorklist<256>;
66+
67+
private:
68+
Worklist &worklist;
69+
bool changed = false;
70+
71+
public:
72+
MandatoryCombineCanonicalize(Worklist &worklist)
73+
: CanonicalizeInstruction(DEBUG_TYPE), worklist(worklist) {}
74+
75+
void notifyNewInstruction(SILInstruction *inst) override {
76+
worklist.add(inst);
77+
worklist.addUsersOfAllResultsToWorklist(inst);
78+
changed = true;
79+
}
80+
81+
// Just delete the given 'inst' and record its operands. The callback isn't
82+
// allowed to mutate any other instructions.
83+
void killInstruction(SILInstruction *inst) override {
84+
worklist.eraseSingleInstFromFunction(*inst,
85+
/*AddOperandsToWorklist*/ true);
86+
changed = true;
87+
}
88+
89+
void notifyHasNewUsers(SILValue value) override {
90+
if (worklist.size() < 10000) {
91+
worklist.addUsersToWorklist(value);
92+
}
93+
changed = true;
94+
}
95+
96+
bool tryCanonicalize(SILInstruction *inst) {
97+
changed = false;
98+
canonicalize(inst);
99+
return changed;
100+
}
101+
};
102+
103+
} // anonymous namespace
104+
56105
//===----------------------------------------------------------------------===//
57106
// MandatoryCombiner Interface
58107
//===----------------------------------------------------------------------===//
@@ -177,13 +226,19 @@ bool MandatoryCombiner::doOneIteration(SILFunction &function,
177226
madeChange = false;
178227

179228
addReachableCodeToWorklist(function);
229+
MandatoryCombineCanonicalize mcCanonicialize(worklist);
180230

181231
while (!worklist.isEmpty()) {
182232
auto *instruction = worklist.pop_back_val();
183233
if (instruction == nullptr) {
184234
continue;
185235
}
186236

237+
if (mcCanonicialize.tryCanonicalize(instruction)) {
238+
madeChange = true;
239+
continue;
240+
}
241+
187242
#ifndef NDEBUG
188243
std::string instructionDescription;
189244
#endif

test/SILGen/addressors.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
// RUN: %target-swift-emit-sil -parse-stdlib %s | %FileCheck %s
32
// RUN: %target-swift-emit-silgen -parse-stdlib %s | %FileCheck %s -check-prefix=SILGEN
43
// RUN: %target-swift-emit-ir -parse-stdlib %s
@@ -60,7 +59,8 @@ func test0() {
6059
// CHECK: [[T2:%.*]] = struct_extract [[T1]] : $UnsafePointer<Int32>, #UnsafePointer._rawValue
6160
// CHECK: [[T3:%.*]] = pointer_to_address [[T2]] : $Builtin.RawPointer to [strict] $*Int32
6261
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unsafe] [[T3]] : $*Int32
63-
// CHECK: [[Z:%.*]] = load [[ACCESS]] : $*Int32
62+
// CHECK: [[ACCESS_GEP:%.*]] = struct_element_addr [[ACCESS]]
63+
// CHECK: [[Z:%.*]] = load [[ACCESS_GEP]]
6464
let z = a[10]
6565

6666
// CHECK: [[WRITE:%.*]] = begin_access [modify] [static] [[A]] : $*A
@@ -106,8 +106,8 @@ var global: Int32 {
106106
}
107107
// CHECK-LABEL: sil hidden @$s10addressors6globals5Int32Vvlu : $@convention(thin) () -> UnsafePointer<Int32> {
108108
// CHECK: [[T0:%.*]] = global_addr @$s10addressors10uninitAddrSpys5Int32VGvp : $*UnsafeMutablePointer<Int32>
109-
// CHECK: [[T1:%.*]] = load [[T0]] : $*UnsafeMutablePointer<Int32>
110-
// CHECK: [[T2:%.*]] = struct_extract [[T1]] : $UnsafeMutablePointer<Int32>, #UnsafeMutablePointer._rawValue
109+
// CHECK: [[T1:%.*]] = struct_element_addr [[T0]]
110+
// CHECK: [[T2:%.*]] = load [[T1]]
111111
// CHECK: [[T3:%.*]] = struct $UnsafePointer<Int32> ([[T2]] : $Builtin.RawPointer)
112112
// CHECK: return [[T3]] : $UnsafePointer<Int32>
113113
}

test/SILGen/unmanaged.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ func set(holder holder: inout Holder) {
2424
// CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [static] [[ADDR]] : $*Holder
2525
// CHECK-NEXT: [[T0:%.*]] = struct_element_addr [[WRITE]] : $*Holder, #Holder.value
2626
// CHECK-NEXT: [[T1:%.*]] = ref_to_unmanaged [[C]]
27-
// CHECK-NEXT: store [[T1]] to [[T0]]
27+
// CHECK-NEXT: [[T2:%.*]] = struct $Holder ([[T1]] : $@sil_unmanaged C)
28+
// CHECK-NEXT: store [[T2]] to [[WRITE]]
2829
// CHECK-NEXT: strong_release [[C]]
2930
// CHECK-NEXT: end_access [[WRITE]] : $*Holder
3031
// CHECK-NEXT: tuple ()

test/SILOptimizer/mandatory_combiner.sil

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -918,3 +918,15 @@ bb0(%0 : @guaranteed $Klass, %1 : @guaranteed $Klass, %2 : @guaranteed $Klass):
918918
%9999 = tuple ()
919919
return %9999 : $()
920920
}
921+
922+
// CHECK-LABEL: sil [ossa] @eliminate_simple_arc_traffic : $@convention(thin) (@guaranteed Klass) -> () {
923+
// CHECK-NOT: copy_value
924+
// CHECK-NOT: destroy_value
925+
// CHECK: } // end sil function 'eliminate_simple_arc_traffic'
926+
sil [ossa] @eliminate_simple_arc_traffic : $@convention(thin) (@guaranteed Klass) -> () {
927+
bb0(%0 : @guaranteed $Klass):
928+
%1 = copy_value %0 : $Klass
929+
destroy_value %1 : $Klass
930+
%9999 = tuple()
931+
return %9999 : $()
932+
}

test/stdlib/Inputs/CommonArrayTests.gyb

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
% # - Suite -- an identifier for the test suite to append tests to.
66
% # - ArrayType -- the type being tested.
77

8+
// We use this global array to prevent ARC from eliminating temporary ARC
9+
// traffic in nonUniqueCode below. It is only ever assigned to.
10+
var globalArrayForNonUnique = ${ArrayType}<Int>()
811

912
extension ${ArrayType} {
1013
typealias _BufferID = UnsafeRawPointer?
@@ -107,7 +110,7 @@ ${Suite}.test("${ArrayType}/appendNonUnique")
107110
x.reserveCapacity(10002)
108111
let capacity = x.capacity
109112
for _ in 1...100 {
110-
let y = x
113+
globalArrayForNonUnique = x
111114
x.append(1)
112115
expectTrue(x.capacity == capacity)
113116
}
@@ -120,7 +123,7 @@ ${Suite}.test("${ArrayType}/removeNonUnique")
120123
var x = ${ArrayType}<Int>(repeating: 27, count: 200)
121124
x.reserveCapacity(10002)
122125
for _ in 1...100 {
123-
let y = x
126+
globalArrayForNonUnique = x
124127
x.remove(at: 0)
125128
expectTrue(x.capacity < 1000)
126129
}
@@ -133,7 +136,7 @@ ${Suite}.test("${ArrayType}/mutateNonUnique")
133136
var x = ${ArrayType}<Int>(repeating: 27, count: 200)
134137
x.reserveCapacity(10002)
135138
for _ in 1...100 {
136-
let y = x
139+
globalArrayForNonUnique = x
137140
x[0] = 0
138141
expectTrue(x.capacity < 1000)
139142
}

0 commit comments

Comments
 (0)