Skip to content

Commit 304f3db

Browse files
committed
[Distributed] IRGen: Load arguments directly into argument explosion
It's incorrect to load from the pointer directly, instead accessor should use `loadAsCopy` for loadable types.
1 parent 9b21742 commit 304f3db

File tree

2 files changed

+36
-62
lines changed

2 files changed

+36
-62
lines changed

lib/IRGen/GenDistributed.cpp

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,6 @@ void DistributedAccessor::computeArguments(llvm::Value *argumentBuffer,
208208

209209
if (paramTy.isObject()) {
210210
auto &nativeSchema = typeInfo.nativeParameterValueSchema(IGM);
211-
auto expandedTy = nativeSchema.getExpandedType(IGM);
212211

213212
if (nativeSchema.requiresIndirect()) {
214213
llvm_unreachable("indirect parameters are not supported");
@@ -219,25 +218,13 @@ void DistributedAccessor::computeArguments(llvm::Value *argumentBuffer,
219218
continue;
220219

221220
// 5. Load argument value from the element pointer.
222-
auto *argValue = IGF.Builder.CreateLoad(alignedOffset, "argval");
223-
224-
Explosion nonNativeParam;
225-
nonNativeParam.add(argValue);
226-
227-
// Convert SIL type into a native representation.
228-
auto nativeParam = nativeSchema.mapIntoNative(
229-
IGM, IGF, nonNativeParam, paramTy, /*isOutlined=*/false);
230-
231-
// If expanded type is a struct we need to explode it to match
232-
// expected argument schema.
233-
if (auto *ST = dyn_cast<llvm::StructType>(expandedTy)) {
234-
IGF.emitAllExtractValues(nativeParam.claimNext(), ST, arguments);
235-
} else {
236-
arguments.add(nativeParam.claimNext());
237-
}
221+
cast<LoadableTypeInfo>(typeInfo).loadAsCopy(IGF, alignedOffset, arguments);
238222
} else {
239-
// 5. Load argument value from the element pointer.
240-
arguments.add(IGF.Builder.CreateLoad(alignedOffset, "argval"));
223+
// If the value is not loadable e.g. generic or resilient
224+
// pass its address as an argument.
225+
//
226+
// TODO: This needs to be copied and destroyed.
227+
arguments.add(alignedOffset.getAddress());
241228
}
242229

243230
// 6. Move the offset to the beginning of the next element, unless

test/Distributed/distributed_actor_accessor_thunks.swift

Lines changed: 30 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,7 @@ public distributed actor MyOtherActor {
9393
// CHECK: store i8* %1, i8** %offset, align 8
9494
// CHECK-NEXT: %elt_offset = load i8*, i8** %offset, align 8
9595
// CHECK-NEXT: [[ELT_PTR:%.*]] = bitcast i8* %elt_offset to %TSi*
96-
// CHECK-NEXT: %argval = load %TSi, %TSi* [[ELT_PTR]], align 8
97-
98-
// CHECK: [[NATIVE_VAL_LOC:%.*]] = bitcast %TSi* %argval.coercion.coerced to i64*
96+
// CHECK-NEXT: [[NATIVE_VAL_LOC:%.*]] = getelementptr inbounds %TSi, %TSi* [[ELT_PTR]], i32 0, i32 0
9997
// CHECK-NEXT: [[ARG_VAL:%.*]] = load i64, i64* [[NATIVE_VAL_LOC]], align 8
10098

10199
/// Retrieve an async pointer to the distributed thunk for `simple1`
@@ -156,11 +154,11 @@ public distributed actor MyOtherActor {
156154

157155
// CHECK: [[TYPED_RESULT_BUFF:%.*]] = bitcast i8* [[RESULT_BUFF]] to %TSi*
158156

159-
// CHECK: %argval = load %TSS, %TSS* {{.*}}, align 8
160-
// CHECK: [[NATIVE_STR_PTR:%.*]] = bitcast %TSS* %argval.coercion.coerced to { i64, %swift.bridge* }*
161-
// CHECK-NEXT: [[NATIVE_STR:%.*]] = load { i64, %swift.bridge* }, { i64, %swift.bridge* }* [[NATIVE_STR_PTR]], align 8
162-
// CHECK: [[STR_SIZE:%.*]] = extractvalue { i64, %swift.bridge* } [[NATIVE_STR]], 0
163-
// CHECK-NEXT: [[STR_VAL:%.*]] = extractvalue { i64, %swift.bridge* } [[NATIVE_STR]], 1
157+
// CHECK: [[ELT_PTR:%.*]] = bitcast i8* %elt_offset to %TSS*
158+
// CHECK-NEXT: %._guts = getelementptr inbounds %TSS, %TSS* [[ELT_PTR]], i32 0, i32 0
159+
160+
// CHECK: [[STR_SIZE:%.*]] = load i64, i64* %._guts._object._countAndFlagsBits._value
161+
// CHECK: [[STR_VAL:%.*]] = load %swift.bridge*, %swift.bridge** %._guts._object._object, align 8
164162

165163
/// Load pointer to a distributed thunk for `simple3`
166164

@@ -211,23 +209,18 @@ public distributed actor MyOtherActor {
211209
// CHECK: [[TYPED_RESULT_BUFF:%.*]] = bitcast i8* %2 to %T27distributed_actor_accessors9IndirectEO*
212210
// CHECK: store i8* %1, i8** %offset, align 8
213211
// CHECK-NEXT: %elt_offset = load i8*, i8** %offset, align 8
212+
214213
// CHECK-NEXT: [[ENUM_PTR:%.*]] = bitcast i8* %elt_offset to %T27distributed_actor_accessors9IndirectEO*
215-
// CHECK-NEXT: %argval = load %T27distributed_actor_accessors9IndirectEO, %T27distributed_actor_accessors9IndirectEO* [[ENUM_PTR]], align 8
216-
// CHECK-NEXT: [[OPAQUE_ENUM_PTR:%.*]] = bitcast %T27distributed_actor_accessors9IndirectEO* %argval.coercion.coerced to i8*
217-
// CHECK: store %T27distributed_actor_accessors9IndirectEO %argval, %T27distributed_actor_accessors9IndirectEO* %argval.coercion.coerced, align 8
218-
// CHECK-NEXT: [[COERCED_ENUM_PTR:%.*]] = bitcast %T27distributed_actor_accessors9IndirectEO* %argval.coercion.coerced to i64*
219-
// CHECK-NEXT: [[NATIVE_ENUM_VAL:%.*]] = load i64, i64* [[COERCED_ENUM_PTR]], align 8
214+
// CHECK-NEXT: [[NATIVE_ENUM_PTR:%.*]] = bitcast %T27distributed_actor_accessors9IndirectEO* [[ENUM_PTR]] to i64*
215+
// CHECK-NEXT: [[NATIVE_ENUM_VAL:%.*]] = load i64, i64* [[NATIVE_ENUM_PTR]]
220216
// CHECK: [[ENUM_PTR_INT:%.*]] = ptrtoint %T27distributed_actor_accessors9IndirectEO* [[ENUM_PTR]] to i64
221217
// CHECK-NEXT: [[NEXT_ELT_LOC:%.*]] = add i64 [[ENUM_PTR_INT]], 8
222218
// CHECK-NEXT: [[NEXT_ELT_PTR:%.*]] = inttoptr i64 [[NEXT_ELT_LOC]] to i8*
223-
// CHECK-NEXT: store i8* [[NEXT_ELT_PTR]], i8** %offset, align 8
224-
// CHECK-NEXT: %elt_offset1 = load i8*, i8** %offset, align 8
219+
// CHECK-NEXT: store i8* [[NEXT_ELT_PTR]], i8** %offset
220+
// CHECK-NEXT: %elt_offset1 = load i8*, i8** %offset
225221
// CHECK-NEXT: [[INT_PTR:%.*]] = bitcast i8* %elt_offset1 to %TSi*
226-
// CHECK-NEXT: %argval2 = load %TSi, %TSi* [[INT_PTR]], align 8
227-
// CHECK-NEXT: [[OPAQUE_INT_PTR:%.*]] = bitcast %TSi* %argval2.coercion.coerced to i8*
228-
// CHECK: store %TSi %argval2, %TSi* %argval2.coercion.coerced, align 8
229-
// CHECK-NEXT: [[COERCED_INT_PTR:%.*]] = bitcast %TSi* %argval2.coercion.coerced to i64*
230-
// CHECK-NEXT: [[NATIVE_INT_VAL:%.*]] = load i64, i64* [[COERCED_INT_PTR]], align 8
222+
// CHECK-NEXT: %._value = getelementptr inbounds %TSi, %TSi* [[INT_PTR]], i32 0, i32 0
223+
// CHECK-NEXT: [[NATIVE_INT_VAL:%.*]] = load i64, i64* %._value
231224

232225
/// Call distributed thunk with extracted arguments.
233226

@@ -255,10 +248,8 @@ public distributed actor MyOtherActor {
255248

256249
// CHECK: %elt_offset = load i8*, i8** %offset, align 8
257250
// CHECK-NEXT: [[ARR_PTR:%.*]] = bitcast i8* %elt_offset to %TSa*
258-
// CHECK-NEXT: %argval = load %TSa, %TSa* [[ARR_PTR]], align 8
259-
// CHECK: store %TSa %argval, %TSa* %argval.coercion.coerced, align 8
260-
// CHECK-NEXT: [[PTR_TO_NATIVE_ARR:%.*]] = bitcast %TSa* %argval.coercion.coerced to [[NATIVE_ARR_TYPE:%.*]]
261-
// CHECK-NEXT: [[NATIVE_ARR_VAL:%.*]] = load {{.*}}, [[NATIVE_ARR_TYPE]] [[PTR_TO_NATIVE_ARR]], align 8
251+
// CHECK-NEXT: %._buffer = getelementptr inbounds %TSa, %TSa* [[ARR_PTR]], i32 0, i32 0
252+
// CHECK: [[NATIVE_ARR_VAL:%.*]] = load [[ARR_STORAGE_TYPE:%.*]], [[ARR_STORAGE_TYPE]]* %._buffer._storage
262253
// CHECK: [[ARR_PTR_INT:%.*]] = ptrtoint %TSa* [[ARR_PTR]] to i64
263254
// CHECK-NEXT: [[NEXT_ELT:%.*]] = add i64 [[ARR_PTR_INT]], 8
264255
// CHECK-NEXT: [[OPAQUE_NEXT_ELT:%.*]] = inttoptr i64 [[NEXT_ELT]] to i8*
@@ -269,41 +260,37 @@ public distributed actor MyOtherActor {
269260
// CHECK-NEXT: %elt_offset1 = load i8*, i8** %offset, align 8
270261
// CHECK-NEXT: [[OBJ_PTR:%.*]] = bitcast i8* %elt_offset1 to %T27distributed_actor_accessors3ObjC**
271262
// CHECK-NEXT: [[NATIVE_OBJ_VAL:%.*]] = load %T27distributed_actor_accessors3ObjC*, %T27distributed_actor_accessors3ObjC** [[OBJ_PTR]], align 8
272-
// CHECK-NEXT: [[OBJ_PTR_INT:%.*]] = ptrtoint %T27distributed_actor_accessors3ObjC** [[OBJ_PTR]] to i64
263+
// CHECK: [[OBJ_PTR_INT:%.*]] = ptrtoint %T27distributed_actor_accessors3ObjC** [[OBJ_PTR]] to i64
273264
// CHECK-NEXT: [[NEXT_ELT:%.*]] = add i64 [[OBJ_PTR_INT]], 8
274265
// CHECK-NEXT: [[NEXT_ELT_PTR:%.*]] = inttoptr i64 [[NEXT_ELT]] to i8*
275266
// CHECK-NEXT: store i8* [[NEXT_ELT_PTR]], i8** %offset, align 8
276267

277268
/// -> String?
278269

279-
// CHECK-NEXT: %elt_offset3 = load i8*, i8** %offset, align 8
280-
// CHECK-NEXT: [[OPT_PTR:%.*]] = bitcast i8* %elt_offset3 to %TSSSg*
281-
// CHECK-NEXT: %argval4 = load %TSSSg, %TSSSg* [[OPT_PTR]], align 8
282-
// CHECK: store %TSSSg %argval4, %TSSSg* %argval4.coercion.coerced, align 8
283-
// CHECK-NEXT: [[NATIVE_OPT_PTR:%.*]] = bitcast %TSSSg* %argval4.coercion.coerced to { i64, i64 }*
284-
// CHECK-NEXT: [[NATIVE_OPT_VAL:%.*]] = load { i64, i64 }, { i64, i64 }* [[NATIVE_OPT_PTR]], align 8
285-
// CHECK: [[NATIVE_OPT_VAL_0:%.*]] = extractvalue { i64, i64 } [[NATIVE_OPT_VAL]], 0
286-
// CHECK-NEXT: [[NATIVE_OPT_VAL_1:%.*]] = extractvalue { i64, i64 } [[NATIVE_OPT_VAL]], 1
287-
// CHECK-NEXT: [[OPT_PTR_INT:%.*]] = ptrtoint %TSSSg* [[OPT_PTR]] to i64
270+
// CHECK-NEXT: %elt_offset2 = load i8*, i8** %offset
271+
// CHECK-NEXT: [[OPT_PTR:%.*]] = bitcast i8* %elt_offset2 to %TSSSg*
272+
// CHECK-NEXT: [[NATIVE_OPT_PTR:%.*]] = bitcast %TSSSg* %22 to { i64, i64 }*
273+
// CHECK-NEXT: [[NATIVE_OPT_VAL_0_PTR:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[NATIVE_OPT_PTR]], i32 0, i32 0
274+
// CHECK-NEXT: [[NATIVE_OPT_VAL_0:%.*]] = load i64, i64* [[NATIVE_OPT_VAL_0_PTR]]
275+
// CHECK-NEXT: [[NATIVE_OPT_VAL_1_PTR:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[NATIVE_OPT_PTR]], i32 0, i32 1
276+
// CHECK-NEXT: [[NATIVE_OPT_VAL_1_OPAQUE:%.*]] = load i64, i64* [[NATIVE_OPT_VAL_1_PTR]]
277+
// CHECK-NEXT: [[NATIVE_OPT_VAL_1_OBJ:%.*]] = inttoptr i64 [[NATIVE_OPT_VAL_1_OPAQUE]] to %swift.bridge*
278+
// CHECK: [[NATIVE_OPT_VAL_1:%.*]] = ptrtoint %swift.bridge* [[NATIVE_OPT_VAL_1_OBJ]] to i64
279+
// CHECK: [[OPT_PTR_INT:%.*]] = ptrtoint %TSSSg* [[OPT_PTR]] to i64
288280
// CHECK-NEXT: [[NEXT_ELT:%.*]] = add i64 [[OPT_PTR_INT]], 16
289281
// CHECK-NEXT: [[NEXT_ELT_PTR:%.*]] = inttoptr i64 [[NEXT_ELT]] to i8*
290-
// CHECK-NEXT: store i8* [[NEXT_ELT_PTR]], i8** %offset, align 8
282+
// CHECK-NEXT: store i8* [[NEXT_ELT_PTR]], i8** %offset
291283

292284
/// -> LargeStruct (passed indirectly)
293285

294-
// CHECK-NEXT: %elt_offset5 = load i8*, i8** %offset, align 8
295-
// CHECK-NEXT: [[STRUCT_PTR:%.*]] = bitcast i8* %elt_offset5 to %T27distributed_actor_accessors11LargeStructV*
296-
// CHECK-NEXT: [[STRUCT_VAL:%.*]] = load %T27distributed_actor_accessors11LargeStructV, %T27distributed_actor_accessors11LargeStructV* [[STRUCT_PTR]], align 8
286+
// CHECK-NEXT: %elt_offset3 = load i8*, i8** %offset, align 8
287+
// CHECK-NEXT: [[STRUCT_PTR:%.*]] = bitcast i8* %elt_offset3 to %T27distributed_actor_accessors11LargeStructV*
297288

298289
// CHECK: [[INDIRECT_RESULT_BUFF:%.*]] = bitcast %swift.opaque* [[TYPED_RESULT_BUFF]] to %T27distributed_actor_accessors11LargeStructV*
299290

300-
// CHECK: store %T27distributed_actor_accessors11LargeStructV [[STRUCT_VAL]], %T27distributed_actor_accessors11LargeStructV* %argval6.coercion.coerced, align 8
301-
// CHECK-NEXT: [[PTR_TO_STRUCT:%.*]] = bitcast %T27distributed_actor_accessors11LargeStructV* %argval6.coercion.coerced to %T27distributed_actor_accessors11LargeStructV**
302-
// CHECK-NEXT: [[NATIVE_STRUCT_VAL:%.*]] = load %T27distributed_actor_accessors11LargeStructV*, %T27distributed_actor_accessors11LargeStructV** [[PTR_TO_STRUCT]], align 8
303-
304291
/// Now let's make sure that distributed thunk call uses the arguments correctly
305292

306-
// CHECK: [[THUNK_RESULT:%.*]] = call { i8*, %swift.error* } (i32, i8*, i8*, ...) @llvm.coro.suspend.async.sl_p0i8p0s_swift.errorss({{.*}}, %T27distributed_actor_accessors11LargeStructV* [[INDIRECT_RESULT_BUFF]], %swift.context* {{.*}}, {{.*}} [[NATIVE_ARR_VAL]], %T27distributed_actor_accessors3ObjC* [[NATIVE_OBJ_VAL]], i64 [[NATIVE_OPT_VAL_0]], i64 [[NATIVE_OPT_VAL_1]], %T27distributed_actor_accessors11LargeStructV* [[NATIVE_STRUCT_VAL]], %T27distributed_actor_accessors7MyActorC* {{.*}})
293+
// CHECK: [[THUNK_RESULT:%.*]] = call { i8*, %swift.error* } (i32, i8*, i8*, ...) @llvm.coro.suspend.async.sl_p0i8p0s_swift.errorss({{.*}}, %T27distributed_actor_accessors11LargeStructV* [[INDIRECT_RESULT_BUFF]], %swift.context* {{.*}}, {{.*}} [[NATIVE_ARR_VAL]], %T27distributed_actor_accessors3ObjC* [[NATIVE_OBJ_VAL]], i64 [[NATIVE_OPT_VAL_0]], i64 [[NATIVE_OPT_VAL_1]], %T27distributed_actor_accessors11LargeStructV* [[STRUCT_PTR]], %T27distributed_actor_accessors7MyActorC* {{.*}})
307294

308295
/// RESULT is returned indirectly so there is nothing to pass to `end`
309296

0 commit comments

Comments
 (0)