Skip to content

Commit d70d391

Browse files
committed
[IRGen] Mark inout ptrs noalias.
Thanks to exclusivity checking, inout arguments can be marked noalias. In the fullness of time, this should be applied in general. As an incremental step towards marking all such arguments noalias, start by marking inout arguments of pointer type noalias. Take this conservative step rather than always applying the attribute to ward against issues with LLVM's alias analysis. rdar://76540030
1 parent 23e1773 commit d70d391

File tree

3 files changed

+27
-6
lines changed

3 files changed

+27
-6
lines changed

lib/IRGen/GenCall.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -265,14 +265,19 @@ static void addIndirectValueParameterAttributes(IRGenModule &IGM,
265265
attrs = attrs.addParamAttributes(IGM.getLLVMContext(), argIndex, b);
266266
}
267267

268-
static void addInoutParameterAttributes(IRGenModule &IGM,
268+
static void addInoutParameterAttributes(IRGenModule &IGM, SILType paramSILType,
269269
llvm::AttributeList &attrs,
270270
const TypeInfo &ti, unsigned argIndex,
271271
bool aliasable) {
272272
llvm::AttrBuilder b;
273-
// Aliasing inouts is unspecified, but we still want aliasing to be memory-
274-
// safe, so we can't mark inouts as noalias at the LLVM level.
275-
// They still can't be captured without doing unsafe stuff, though.
273+
// Thanks to exclusivity checking, it is not possible to alias inouts except
274+
// those that are inout_aliasable.
275+
if (!aliasable && paramSILType.getASTType()->getAnyPointerElementType()) {
276+
// To ward against issues with LLVM's alias analysis, for now, only add the
277+
// attribute if it's a pointer being passed inout.
278+
b.addAttribute(llvm::Attribute::NoAlias);
279+
}
280+
// Aliasing inouts can't be captured without doing unsafe stuff.
276281
b.addAttribute(llvm::Attribute::NoCapture);
277282
// The inout must reference dereferenceable memory of the type.
278283
addDereferenceableAttributeToBuilder(IGM, b, ti);
@@ -1510,8 +1515,9 @@ void SignatureExpansion::expand(SILParameterInfo param) {
15101515

15111516
case ParameterConvention::Indirect_Inout:
15121517
case ParameterConvention::Indirect_InoutAliasable:
1513-
addInoutParameterAttributes(IGM, Attrs, ti, ParamIRTypes.size(),
1514-
conv == ParameterConvention::Indirect_InoutAliasable);
1518+
addInoutParameterAttributes(
1519+
IGM, paramSILType, Attrs, ti, ParamIRTypes.size(),
1520+
conv == ParameterConvention::Indirect_InoutAliasable);
15151521
addPointerParameter(IGM.getStorageType(getSILFuncConventions().getSILType(
15161522
param, IGM.getMaximalTypeExpansionContext())));
15171523
return;

test/IRGen/inout_noalias.sil

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// RUN: %target-swift-frontend -parse-sil %s -emit-ir | %FileCheck %s
2+
3+
import Swift
4+
5+
// CHECK: define{{.*}}swiftcc void @takeInoutAliasable(%TSP* nocapture dereferenceable({{[0-9]+}}) %0, %swift.type* %T)
6+
sil @takeInoutAliasable : $<T> (@inout_aliasable UnsafePointer<T>) -> () {
7+
entry(%ptr : $*UnsafePointer<T>):
8+
%retval = tuple ()
9+
return %retval : $()
10+
}

test/IRGen/inout_noalias.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// RUN: %target-swift-frontend %s -emit-ir | %FileCheck %s
2+
3+
// CHECK: define{{.*}}swiftcc void @swapPointers({{.*}}noalias{{.*}},{{.*}}noalias{{.*}})
4+
@_silgen_name("swapPointers")
5+
public func swapPointers<T>(_ lhs: inout UnsafePointer<T>, _ rhs: inout UnsafePointer<T>) {}

0 commit comments

Comments
 (0)