Skip to content

Commit 129fca6

Browse files
authored
Merge pull request #36447 from eeckstein/main
SILOptimizer: fix a compiler crash when optimizing a global variable with an empty tuple.
2 parents 4fe3214 + eee33a7 commit 129fca6

File tree

6 files changed

+60
-4
lines changed

6 files changed

+60
-4
lines changed

lib/SIL/IR/SILGlobalVariable.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,11 @@ BuiltinInst *SILGlobalVariable::getOffsetSubtract(const TupleExtractInst *TE,
111111

112112
bool SILGlobalVariable::isValidStaticInitializerInst(const SILInstruction *I,
113113
SILModule &M) {
114+
for (const Operand &op : I->getAllOperands()) {
115+
// Rule out SILUndef and SILArgument.
116+
if (!isa<SingleValueInstruction>(op.get()))
117+
return false;
118+
}
114119
switch (I->getKind()) {
115120
case SILInstructionKind::BuiltinInst: {
116121
auto *bi = cast<BuiltinInst>(I);

lib/SILOptimizer/Transforms/SILMem2Reg.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,18 @@ StackAllocationPromoter::promoteAllocationInBlock(SILBasicBlock *BB) {
576576
return LastStore;
577577
}
578578

579+
/// Create a tuple value for an empty tuple or a tuple of empty tuples.
580+
SILValue createValueForEmptyTuple(SILType ty, SILInstruction *insertionPoint) {
581+
auto tupleTy = ty.castTo<TupleType>();
582+
SmallVector<SILValue, 4> elements;
583+
for (unsigned idx = 0, end = tupleTy->getNumElements(); idx < end; ++ idx) {
584+
SILType elementTy = ty.getTupleElementType(idx);
585+
elements.push_back(createValueForEmptyTuple(elementTy, insertionPoint));
586+
}
587+
SILBuilder builder(insertionPoint);
588+
return builder.createTuple(insertionPoint->getLoc(), ty, elements);
589+
}
590+
579591
void MemoryToRegisters::removeSingleBlockAllocation(AllocStackInst *ASI) {
580592
LLVM_DEBUG(llvm::dbgs() << "*** Promoting in-block: " << *ASI);
581593

@@ -596,7 +608,7 @@ void MemoryToRegisters::removeSingleBlockAllocation(AllocStackInst *ASI) {
596608
if (!RunningVal) {
597609
// Loading without a previous store is only acceptable if the type is
598610
// Void (= empty tuple) or a tuple of Voids.
599-
RunningVal = SILUndef::get(ASI->getElementType(), *ASI->getFunction());
611+
RunningVal = createValueForEmptyTuple(ASI->getElementType(), Inst);
600612
}
601613
replaceLoad(cast<LoadInst>(Inst), RunningVal, ASI);
602614
++NumInstRemoved;

test/SILOptimizer/globalopt_let_propagation.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ var VPI = 3.1415
7272
var VI = 100
7373
var VS = "String2"
7474

75+
struct GenericStruct<T> {
76+
var x: T
77+
}
78+
7579
// Define some static let variables inside a struct.
7680
struct B {
7781
static let PI = 3.1415
@@ -109,6 +113,8 @@ struct B {
109113
static let IT1 = ((10, 20), 30, 40)
110114

111115
static let IT2 = (100, 200, 300)
116+
117+
static let emptyStruct = GenericStruct(x: ())
112118
}
113119

114120
// Define some static let variables inside a class.

test/SILOptimizer/globalopt_trivial_nontrivial_ossa.sil

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ public class TClass {
1818
deinit
1919
}
2020

21+
struct GenericStruct<T> {
22+
var x: T
23+
}
24+
2125
let nontrivialglobal: TClass
2226

2327
// CHECK-LABEL: sil_global hidden [let] @$trivialglobal : $TStruct = {
@@ -32,6 +36,9 @@ sil_global private @globalinit_nontrivialglobal_token : $Builtin.Word
3236

3337
sil_global hidden [let] @$nontrivialglobal : $TClass
3438

39+
sil_global hidden [let] @empty_global : $GenericStruct<()>
40+
sil_global private @empty_global_token : $Builtin.Word
41+
3542
sil private [global_init_once_fn] [ossa] @globalinit_trivialglobal_func : $@convention(c) () -> () {
3643
bb0:
3744
alloc_global @$trivialglobal
@@ -126,3 +133,28 @@ bb0:
126133
return %5 : $Int32
127134
}
128135

136+
// Check that we don't crash on an initializer struct with an "undef" operand.
137+
// CHECK-LABEL: sil hidden [global_init_once_fn] [ossa] @globalinit_empty_global :
138+
// CHECK: struct $GenericStruct<()> (undef : $())
139+
// CHECK-LABEL: } // end sil function 'globalinit_empty_global'
140+
sil hidden [global_init_once_fn] [ossa] @globalinit_empty_global : $@convention(c) () -> () {
141+
bb0:
142+
alloc_global @empty_global
143+
%1 = global_addr @empty_global : $*GenericStruct<()>
144+
%2 = struct $GenericStruct<()> (undef : $())
145+
store %2 to [trivial] %1 : $*GenericStruct<()>
146+
%4 = tuple ()
147+
return %4 : $()
148+
}
149+
150+
sil hidden [global_init] [ossa] @empty_global_accessor : $@convention(thin) () -> Builtin.RawPointer {
151+
bb0:
152+
%0 = global_addr @empty_global_token : $*Builtin.Word
153+
%1 = address_to_pointer %0 : $*Builtin.Word to $Builtin.RawPointer
154+
%2 = function_ref @globalinit_empty_global : $@convention(c) () -> ()
155+
%3 = builtin "once"(%1 : $Builtin.RawPointer, %2 : $@convention(c) () -> ()) : $()
156+
%4 = global_addr @empty_global : $*GenericStruct<()>
157+
%5 = address_to_pointer %4 : $*GenericStruct<()> to $Builtin.RawPointer
158+
return %5 : $Builtin.RawPointer
159+
}
160+

test/SILOptimizer/mem2reg.sil

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -438,8 +438,8 @@ bb3(%20 : $((), ())):
438438
}
439439

440440
// CHECK-LABEL: sil @load_tuple_of_void
441-
// CHECK-NOT: alloc_stack
442-
// CHECK: return undef : $((), ())
441+
// CHECK: [[T:%[0-9]+]] = tuple (%{{[0-9]+}} : $(), %{{[0-9]+}} : $())
442+
// CHECK: return [[T]] : $((), ())
443443
// CHECK: } // end sil function 'load_tuple_of_void'
444444
sil @load_tuple_of_void : $@convention(thin) () -> ((), ()) {
445445
bb0:

test/SILOptimizer/mem2reg_ossa.sil

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,8 @@ bb3(%20 : $((), ())):
478478

479479
// CHECK-LABEL: sil [ossa] @load_tuple_of_void :
480480
// CHECK-NOT: alloc_stack
481-
// CHECK: return undef : $((), ())
481+
// CHECK: [[T:%[0-9]+]] = tuple (%{{[0-9]+}} : $(), %{{[0-9]+}} : $())
482+
// CHECK: return [[T]] : $((), ())
482483
// CHECK: } // end sil function 'load_tuple_of_void'
483484
sil [ossa] @load_tuple_of_void : $@convention(thin) () -> ((), ()) {
484485
bb0:

0 commit comments

Comments
 (0)