Skip to content

Commit 51e148d

Browse files
Merge pull request #72694 from aschwaighofer/c_array_heuristic
LargeTypesReg2Mem: Add a heuristic for C character arrays
2 parents a967184 + 081a872 commit 51e148d

File tree

3 files changed

+68
-3
lines changed

3 files changed

+68
-3
lines changed

lib/IRGen/LoadableByAddress.cpp

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
//===----------------------------------------------------------------------===//
1818

1919
#define DEBUG_TYPE "loadable-address"
20+
#include "Explosion.h"
2021
#include "FixedTypeInfo.h"
2122
#include "IRGenMangler.h"
2223
#include "IRGenModule.h"
@@ -3432,6 +3433,29 @@ class AddressAssignment {
34323433
toDeleteBlockArg.push_back(std::make_pair(b, argIdx));
34333434
}
34343435

3436+
bool isPotentiallyCArray(SILType ty) {
3437+
if (ty.isAddress() || ty.isClassOrClassMetatype()) {
3438+
return false;
3439+
}
3440+
3441+
auto canType = ty.getASTType();
3442+
if (canType->hasTypeParameter()) {
3443+
assert(genEnv && "Expected a GenericEnv");
3444+
canType = genEnv->mapTypeIntoContext(canType)->getCanonicalType();
3445+
}
3446+
3447+
if (canType.getAnyGeneric() || isa<TupleType>(canType)) {
3448+
assert(ty.isObject() &&
3449+
"Expected only two categories: address and object");
3450+
assert(!canType->hasTypeParameter());
3451+
const TypeInfo &TI = irgenModule->getTypeInfoForLowered(canType);
3452+
auto explosionSchema = TI.getSchema();
3453+
if (explosionSchema.size() > 15)
3454+
return true;
3455+
}
3456+
return false;
3457+
}
3458+
34353459
bool isLargeLoadableType(SILType ty) {
34363460
if (ty.isAddress() || ty.isClassOrClassMetatype()) {
34373461
return false;
@@ -3449,7 +3473,11 @@ class AddressAssignment {
34493473
assert(!canType->hasTypeParameter());
34503474
const TypeInfo &TI = irgenModule->getTypeInfoForLowered(canType);
34513475
auto &nativeSchemaOrigParam = TI.nativeParameterValueSchema(*irgenModule);
3452-
return nativeSchemaOrigParam.size() > 15;
3476+
if (nativeSchemaOrigParam.size() > 15)
3477+
return true;
3478+
auto explosionSchema = TI.getSchema();
3479+
if (explosionSchema.size() > 15)
3480+
return true;
34533481
}
34543482
return false;
34553483
}
@@ -3765,7 +3793,7 @@ class AssignAddressToDef : SILInstructionVisitor<AssignAddressToDef> {
37653793
builder.createStore(bc->getLoc(), bc->getOperand(), opdAddr,
37663794
StoreOwnershipQualifier::Unqualified);
37673795
assignment.mapValueToAddress(origValue, addr);
3768-
3796+
assignment.markForDeletion(bc);
37693797
return;
37703798
}
37713799
auto opdAddr = assignment.getAddressForValue(bc->getOperand());
@@ -3936,7 +3964,9 @@ class RewriteUser : SILInstructionVisitor<RewriteUser> {
39363964
}
39373965

39383966
void visitDebugValueInst(DebugValueInst *dbg) {
3939-
if (!dbg->hasAddrVal() && overlapsWithOnStackDebugLoc(dbg->getOperand())) {
3967+
if (!dbg->hasAddrVal() &&
3968+
(assignment.isPotentiallyCArray(dbg->getOperand()->getType()) ||
3969+
overlapsWithOnStackDebugLoc(dbg->getOperand()))) {
39403970
assignment.markForDeletion(dbg);
39413971
return;
39423972
}

test/IRGen/Inputs/large_union.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#pragma once
2+
3+
typedef union {
4+
struct {
5+
unsigned char a;
6+
unsigned char arr[32];
7+
} in;
8+
struct {
9+
int a;
10+
unsigned char arr[32];
11+
unsigned char b;
12+
} out;
13+
} some_struct;

test/IRGen/large_union.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: %target-swift-frontend %s -Osize -Xllvm -sil-print-after=loadable-address -import-objc-header %S/Inputs/large_union.h -c -o %t/t.o 2>&1 | %FileCheck %s
2+
3+
public func test1(_ s: some_struct) -> some_struct {
4+
var copy = s
5+
copy.out.a = 1
6+
return copy
7+
}
8+
// CHECK: sil @$s1t5test1ySo11some_structaADF : $@convention(thin) (@in_guaranteed some_struct) -> @out some_struct {
9+
// CHECK-NOT: unchecked_trivial_bitcast
10+
// CHECK: unchecked_addr_cast {{.*}} : $*some_struct.__Unnamed_struct_out to $*some_struct
11+
// CHECK-NOT: unchecked_trivial_bitcast
12+
// CHECK: } // end sil function '$s1t5test1ySo11some_structaADF'
13+
14+
// CHECK: sil @$s1t5test2yySo11some_structazF : $@convention(thin) (@inout some_struct) -> () {
15+
// CHECK-NOT: unchecked_trivial_bitcast
16+
// CHECK: unchecked_addr_cast {{.*}} : $*some_struct.__Unnamed_struct_out to $*some_struct
17+
// CHECK-NOT: unchecked_trivial_bitcast
18+
// CHECK: } // end sil function '$s1t5test2yySo11some_structazF'
19+
20+
public func test2(_ s: inout some_struct) {
21+
s.out.a = 1
22+
}

0 commit comments

Comments
 (0)