Skip to content

Commit 0e350d8

Browse files
Merge pull request #72708 from aschwaighofer/c_array_heuristic_6.0
[6.0] LargeTypesReg2Mem: Add a heuristic for C character arrays
2 parents 1e5659e + ca8c2ff commit 0e350d8

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"
@@ -3431,6 +3432,29 @@ class AddressAssignment {
34313432
toDeleteBlockArg.push_back(std::make_pair(b, argIdx));
34323433
}
34333434

3435+
bool isPotentiallyCArray(SILType ty) {
3436+
if (ty.isAddress() || ty.isClassOrClassMetatype()) {
3437+
return false;
3438+
}
3439+
3440+
auto canType = ty.getASTType();
3441+
if (canType->hasTypeParameter()) {
3442+
assert(genEnv && "Expected a GenericEnv");
3443+
canType = genEnv->mapTypeIntoContext(canType)->getCanonicalType();
3444+
}
3445+
3446+
if (canType.getAnyGeneric() || isa<TupleType>(canType)) {
3447+
assert(ty.isObject() &&
3448+
"Expected only two categories: address and object");
3449+
assert(!canType->hasTypeParameter());
3450+
const TypeInfo &TI = irgenModule->getTypeInfoForLowered(canType);
3451+
auto explosionSchema = TI.getSchema();
3452+
if (explosionSchema.size() > 15)
3453+
return true;
3454+
}
3455+
return false;
3456+
}
3457+
34343458
bool isLargeLoadableType(SILType ty) {
34353459
if (ty.isAddress() || ty.isClassOrClassMetatype()) {
34363460
return false;
@@ -3448,7 +3472,11 @@ class AddressAssignment {
34483472
assert(!canType->hasTypeParameter());
34493473
const TypeInfo &TI = irgenModule->getTypeInfoForLowered(canType);
34503474
auto &nativeSchemaOrigParam = TI.nativeParameterValueSchema(*irgenModule);
3451-
return nativeSchemaOrigParam.size() > 15;
3475+
if (nativeSchemaOrigParam.size() > 15)
3476+
return true;
3477+
auto explosionSchema = TI.getSchema();
3478+
if (explosionSchema.size() > 15)
3479+
return true;
34523480
}
34533481
return false;
34543482
}
@@ -3764,7 +3792,7 @@ class AssignAddressToDef : SILInstructionVisitor<AssignAddressToDef> {
37643792
builder.createStore(bc->getLoc(), bc->getOperand(), opdAddr,
37653793
StoreOwnershipQualifier::Unqualified);
37663794
assignment.mapValueToAddress(origValue, addr);
3767-
3795+
assignment.markForDeletion(bc);
37683796
return;
37693797
}
37703798
auto opdAddr = assignment.getAddressForValue(bc->getOperand());
@@ -3926,7 +3954,9 @@ class RewriteUser : SILInstructionVisitor<RewriteUser> {
39263954
}
39273955

39283956
void visitDebugValueInst(DebugValueInst *dbg) {
3929-
if (!dbg->hasAddrVal() && overlapsWithOnStackDebugLoc(dbg->getOperand())) {
3957+
if (!dbg->hasAddrVal() &&
3958+
(assignment.isPotentiallyCArray(dbg->getOperand()->getType()) ||
3959+
overlapsWithOnStackDebugLoc(dbg->getOperand()))) {
39303960
assignment.markForDeletion(dbg);
39313961
return;
39323962
}

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)