Skip to content

Commit 96eb876

Browse files
authored
[LateLowerGC] Fix typo sret handling so we properly handle selects in the worklist (#57741)
Fixes #57737
1 parent ce747fe commit 96eb876

File tree

3 files changed

+87
-6
lines changed

3 files changed

+87
-6
lines changed

src/llvm-gc-interface-passes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#include "llvm-pass-helpers.h"
4747
#include <map>
4848
#include <string>
49+
#include <optional>
4950

5051
#ifndef LLVM_GC_PASSES_H
5152
#define LLVM_GC_PASSES_H

src/llvm-late-gc-lowering.cpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1128,7 +1128,7 @@ void LateLowerGCFrame::FixUpRefinements(ArrayRef<int> PHINumbers, State &S)
11281128
}
11291129

11301130
// Look through instructions to find all possible allocas that might become the sret argument
1131-
static SmallSetVector<AllocaInst *, 8> FindSretAllocas(Value* SRetArg) {
1131+
static std::optional<SmallSetVector<AllocaInst *, 8>> FindSretAllocas(Value* SRetArg) {
11321132
SmallSetVector<AllocaInst *, 8> allocas;
11331133
if (AllocaInst *OneSRet = dyn_cast<AllocaInst>(SRetArg)) {
11341134
allocas.insert(OneSRet); // Found it directly
@@ -1143,7 +1143,7 @@ static SmallSetVector<AllocaInst *, 8> FindSretAllocas(Value* SRetArg) {
11431143
for (Value *Incoming : Phi->incoming_values()) {
11441144
worklist.insert(Incoming);
11451145
}
1146-
} else if (SelectInst *SI = dyn_cast<SelectInst>(SRetArg)) {
1146+
} else if (SelectInst *SI = dyn_cast<SelectInst>(V)) {
11471147
auto TrueBranch = SI->getTrueValue();
11481148
auto FalseBranch = SI->getFalseValue();
11491149
if (TrueBranch && FalseBranch) {
@@ -1152,12 +1152,12 @@ static SmallSetVector<AllocaInst *, 8> FindSretAllocas(Value* SRetArg) {
11521152
} else {
11531153
llvm_dump(SI);
11541154
dbgs() << "Malformed Select\n";
1155-
abort();
1155+
return {};
11561156
}
11571157
} else {
11581158
llvm_dump(V);
11591159
dbgs() << "Unexpected SRet argument\n";
1160-
abort();
1160+
return {};
11611161
}
11621162
}
11631163
}
@@ -1221,10 +1221,15 @@ State LateLowerGCFrame::LocalScan(Function &F) {
12211221
Type *ElT = getAttributeAtIndex(CI->getAttributes(), 1, Attribute::StructRet).getValueAsType();
12221222
auto tracked = CountTrackedPointers(ElT, true);
12231223
if (tracked.count) {
1224-
SmallSetVector<AllocaInst *, 8> allocas = FindSretAllocas((CI->arg_begin()[0])->stripInBoundsOffsets());
1224+
auto allocas_opt = FindSretAllocas((CI->arg_begin()[0])->stripInBoundsOffsets());
12251225
// We know that with the right optimizations we can forward a sret directly from an argument
12261226
// This hasn't been seen without adding IPO effects to julia functions but it's possible we need to handle that too
12271227
// If they are tracked.all we can just pass through but if they have a roots bundle it's possible we need to emit some copies ¯\_(ツ)_/¯
1228+
if (!allocas_opt.has_value()) {
1229+
llvm_dump(&F);
1230+
abort();
1231+
}
1232+
auto allocas = allocas_opt.value();
12281233
for (AllocaInst *SRet : allocas) {
12291234
if (!(SRet->isStaticAlloca() && isa<PointerType>(ElT) && ElT->getPointerAddressSpace() == AddressSpace::Tracked)) {
12301235
assert(!tracked.derived);
@@ -1233,7 +1238,12 @@ State LateLowerGCFrame::LocalScan(Function &F) {
12331238
}
12341239
else {
12351240
Value *arg1 = (CI->arg_begin()[1])->stripInBoundsOffsets();
1236-
SmallSetVector<AllocaInst *, 8> gc_allocas = FindSretAllocas(arg1);
1241+
auto gc_allocas_opt = FindSretAllocas(arg1);
1242+
if (!gc_allocas_opt.has_value()) {
1243+
llvm_dump(&F);
1244+
abort();
1245+
}
1246+
auto gc_allocas = gc_allocas_opt.value();
12371247
if (gc_allocas.size() == 0) {
12381248
llvm_dump(CI);
12391249
errs() << "Expected one Alloca at least\n";

test/llvmpasses/late-lower-gc-sret.ll

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,73 @@ ret: ; preds = %false, %true
7979
; CHECK: call void @julia.pop_gc_frame(ptr %gcframe)
8080
ret void
8181
}
82+
83+
84+
define hidden swiftcc void @sret_gc_root_phi_select(ptr nonnull swiftself %0, i1 %unpredictable, i1 %unpredictable2) {
85+
top:
86+
; CHECK-LABEL: @sret_gc_root_phi_select
87+
; CHECK: %gcframe = call ptr @julia.new_gc_frame(i32 3)
88+
; CHECK: call ptr @julia.get_gc_frame_slot(ptr %gcframe, i32 2)
89+
; CHECK: call ptr @julia.get_gc_frame_slot(ptr %gcframe, i32 1)
90+
; CHECK: call ptr @julia.get_gc_frame_slot(ptr %gcframe, i32 0)
91+
; CHECK: %pgcstack = call ptr @julia.get_pgcstack()
92+
; CHECK: call void @julia.push_gc_frame(ptr %gcframe, i32 3)
93+
; CHECK: alloca [3 x i64], align 8
94+
%pgcstack = call ptr @julia.get_pgcstack()
95+
%1 = alloca [3 x i64], align 8
96+
%2 = alloca ptr addrspace(10), align 8
97+
%3 = alloca ptr addrspace(10), align 8
98+
%4 = alloca ptr addrspace(10), align 8
99+
store i64 0, ptr %2, align 8
100+
store i64 0, ptr %3, align 8
101+
store i64 0, ptr %4, align 8
102+
br i1 %unpredictable, label %true, label %false
103+
104+
true: ; preds = %top
105+
br label %ret
106+
107+
false: ; preds = %top
108+
br label %ret
109+
110+
ret: ; preds = %false, %true
111+
%5 = phi ptr [ %2, %true ], [ %3, %false ]
112+
%6 = select i1 %unpredictable2, ptr %4, ptr %5
113+
call swiftcc void @sret_call_gc(ptr noalias nocapture noundef sret({ ptr addrspace(10), i64, i64 }) %1, ptr noalias nocapture noundef %6, ptr nonnull swiftself %0)
114+
; CHECK: call void @julia.pop_gc_frame(ptr %gcframe)
115+
ret void
116+
}
117+
118+
define hidden swiftcc void @sret_gc_root_select_phi(ptr nonnull swiftself %0, i1 %unpredictable, i1 %unpredictable2) {
119+
top:
120+
; CHECK-LABEL: @sret_gc_root_select_phi
121+
; CHECK: %gcframe = call ptr @julia.new_gc_frame(i32 3)
122+
; CHECK: call ptr @julia.get_gc_frame_slot(ptr %gcframe, i32 2)
123+
; CHECK: call ptr @julia.get_gc_frame_slot(ptr %gcframe, i32 1)
124+
; CHECK: call ptr @julia.get_gc_frame_slot(ptr %gcframe, i32 0)
125+
; CHECK: %pgcstack = call ptr @julia.get_pgcstack()
126+
; CHECK: call void @julia.push_gc_frame(ptr %gcframe, i32 3)
127+
; CHECK: alloca [3 x i64], align 8
128+
%pgcstack = call ptr @julia.get_pgcstack()
129+
%1 = alloca [3 x i64], align 8
130+
%2 = alloca ptr addrspace(10), align 8
131+
%3 = alloca ptr addrspace(10), align 8
132+
%4 = alloca ptr addrspace(10), align 8
133+
store i64 0, ptr %2, align 8
134+
store i64 0, ptr %3, align 8
135+
store i64 0, ptr %4, align 8
136+
%5 = select i1 %unpredictable2, ptr %3, ptr %4
137+
br i1 %unpredictable, label %true, label %false
138+
139+
true: ; preds = %top
140+
br label %ret
141+
142+
false: ; preds = %top
143+
br label %ret
144+
145+
ret: ; preds = %false, %true
146+
%6 = phi ptr [ %2, %true ], [ %5, %false ]
147+
148+
call swiftcc void @sret_call_gc(ptr noalias nocapture noundef sret({ ptr addrspace(10), i64, i64 }) %1, ptr noalias nocapture noundef %6, ptr nonnull swiftself %0)
149+
; CHECK: call void @julia.pop_gc_frame(ptr %gcframe)
150+
ret void
151+
}

0 commit comments

Comments
 (0)