Skip to content

Add a loadInvariant builtin. #7965

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 9, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion include/swift/AST/Builtins.def
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,14 @@ BUILTIN_SIL_OPERATION(Load, "load", Special)

/// LoadRaw has type (Builtin.RawPointer) -> T
/// This is a load of T from raw memory.
/// It's address does not adhere to strict aliasing.
/// Its address does not adhere to strict aliasing.
BUILTIN_SIL_OPERATION(LoadRaw, "loadRaw", Special)

/// LoadInvariant has type (Builtin.RawPointer) -> T
/// This is a load of T from raw memory.
/// The load is marked as invariant.
BUILTIN_SIL_OPERATION(LoadInvariant, "loadInvariant", Special)

/// Take has type (Builtin.RawPointer) -> T
BUILTIN_SIL_OPERATION(Take, "take", Special)

Expand Down
6 changes: 4 additions & 2 deletions include/swift/SIL/SILBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -657,9 +657,11 @@ class SILBuilder {
}

PointerToAddressInst *createPointerToAddress(SILLocation Loc, SILValue Op,
SILType Ty, bool isStrict) {
SILType Ty,
bool isStrict,
bool isInvariant = false){
return insert(new (F.getModule()) PointerToAddressInst(
getSILDebugLocation(Loc), Op, Ty, isStrict));
getSILDebugLocation(Loc), Op, Ty, isStrict, isInvariant));
}

UncheckedRefCastInst *createUncheckedRefCast(SILLocation Loc, SILValue Op,
Expand Down
3 changes: 2 additions & 1 deletion include/swift/SIL/SILCloner.h
Original file line number Diff line number Diff line change
Expand Up @@ -937,7 +937,8 @@ SILCloner<ImplClass>::visitPointerToAddressInst(PointerToAddressInst *Inst) {
getBuilder().createPointerToAddress(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
getOpType(Inst->getType()),
Inst->isStrict()));
Inst->isStrict(),
Inst->isInvariant()));
}

template<typename ImplClass>
Expand Down
11 changes: 8 additions & 3 deletions include/swift/SIL/SILInstruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -2416,17 +2416,22 @@ class PointerToAddressInst
{
friend SILBuilder;

bool IsStrict;
bool IsStrict, IsInvariant;

PointerToAddressInst(SILDebugLocation DebugLoc, SILValue Operand, SILType Ty,
bool IsStrict)
: UnaryInstructionBase(DebugLoc, Operand, Ty), IsStrict(IsStrict) {}
bool IsStrict, bool IsInvariant)
: UnaryInstructionBase(DebugLoc, Operand, Ty),
IsStrict(IsStrict), IsInvariant(IsInvariant) {}

public:
/// Whether the returned address adheres to strict aliasing.
/// If true, then the type of each memory access dependent on
/// this address must be consistent with the memory's bound type.
bool isStrict() const { return IsStrict; }
/// Whether the returned address is invariant.
/// If true, then loading from an address derived from this pointer always
/// produces the same value.
bool isInvariant() const { return IsInvariant; }
};

/// Convert a heap object reference to a different type without any runtime
Expand Down
2 changes: 1 addition & 1 deletion include/swift/Serialization/ModuleFormat.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const uint16_t VERSION_MAJOR = 0;
/// in source control, you should also update the comment to briefly
/// describe what change you made. The content of this comment isn't important;
/// it just ensures a conflict if two people change the module format.
const uint16_t VERSION_MINOR = 325; // Last change: unchecked_ownership_conver
const uint16_t VERSION_MINOR = 326; // Last change: invariant bit on pointer_to_address

using DeclID = PointerEmbeddedInt<unsigned, 31>;
using DeclIDField = BCFixed<31>;
Expand Down
1 change: 1 addition & 0 deletions lib/AST/Builtins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1602,6 +1602,7 @@ ValueDecl *swift::getBuiltinValueDecl(ASTContext &Context, Identifier Id) {

case BuiltinValueKind::Load:
case BuiltinValueKind::LoadRaw:
case BuiltinValueKind::LoadInvariant:
case BuiltinValueKind::Take:
if (!Types.empty()) return nullptr;
return getLoadOperation(Context, Id);
Expand Down
20 changes: 19 additions & 1 deletion lib/IRGen/IRGenSIL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3200,6 +3200,18 @@ void IRGenSILFunction::visitRefTailAddrInst(RefTailAddrInst *i) {
setLoweredAddress(i, TailAddr);
}

static bool isInvariantAddress(SILValue v) {
auto root = getUnderlyingAddressRoot(v);
if (auto ptrRoot = dyn_cast<PointerToAddressInst>(root)) {
return ptrRoot->isInvariant();
}
// TODO: We could be more aggressive about considering addresses based on
// `let` variables as invariant when the type of the address is known not to
// have any sharably-mutable interior storage (in other words, no weak refs,
// atomics, etc.)
return false;
}

void IRGenSILFunction::visitLoadInst(swift::LoadInst *i) {
Explosion lowered;
Address source = getLoweredAddress(i->getOperand());
Expand All @@ -3216,7 +3228,13 @@ void IRGenSILFunction::visitLoadInst(swift::LoadInst *i) {
typeInfo.loadAsCopy(*this, source, lowered);
break;
}


if (isInvariantAddress(i->getOperand())) {
// It'd be better to push this down into `loadAs` methods, perhaps...
for (auto value : lowered.getAll())
if (auto load = dyn_cast<llvm::LoadInst>(value))
setInvariantLoad(load);
}
setLoweredExplosion(i, lowered);
}

Expand Down
16 changes: 11 additions & 5 deletions lib/Parse/ParseSIL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2377,21 +2377,27 @@ bool SILParser::parseSILInstruction(SILBasicBlock *BB, SILBuilder &B) {
SILType Ty;
Identifier ToToken;
SourceLoc ToLoc;
bool isStrict = false;
StringRef attr;
if (parseTypedValueRef(Val, B) ||
parseSILIdentifier(ToToken, ToLoc,
diag::expected_tok_in_sil_instr, "to") ||
parseSILOptional(isStrict, *this, "strict") ||
parseSILType(Ty) ||
diag::expected_tok_in_sil_instr, "to"))
return true;
if (parseSILOptional(attr, *this) && attr.empty())
return true;
if (parseSILType(Ty) ||
parseSILDebugLocation(InstLoc, B))
return true;

bool isStrict = attr.equals("strict");
bool isInvariant = attr.equals("invariant");

if (ToToken.str() != "to") {
P.diagnose(ToLoc, diag::expected_tok_in_sil_instr, "to");
return true;
}

ResultVal = B.createPointerToAddress(InstLoc, Val, Ty, isStrict);
ResultVal = B.createPointerToAddress(InstLoc, Val, Ty,
isStrict, isInvariant);
break;
}
case ValueKind::RefToBridgeObjectInst: {
Expand Down
1 change: 1 addition & 0 deletions lib/SIL/SILOwnershipVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1110,6 +1110,7 @@ BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(TryPin)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(Unpin)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(Load)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(LoadRaw)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(LoadInvariant)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(Take)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(Destroy)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(Assign)
Expand Down
2 changes: 2 additions & 0 deletions lib/SIL/SILPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1266,6 +1266,8 @@ class SILPrinter : public SILVisitor<SILPrinter> {
*this << getIDAndType(CI->getOperand()) << " to ";
if (CI->isStrict())
*this << "[strict] ";
if (CI->isInvariant())
*this << "[invariant] ";
*this << CI->getType();
}
void visitUncheckedRefCastInst(UncheckedRefCastInst *CI) {
Expand Down
1 change: 1 addition & 0 deletions lib/SIL/SILValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,7 @@ CONSTANT_OWNERSHIP_BUILTIN(Trivial, IntToPtr)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, LShr)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Load)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, LoadRaw)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, LoadInvariant)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Mul)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Or)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, PtrToInt)
Expand Down
8 changes: 6 additions & 2 deletions lib/SILGen/SILGenApply.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5289,7 +5289,9 @@ emitMaterializeForSetAccessor(SILLocation loc, SILDeclRef materializeForSet,
// materialize for set is strictly typed, whether it is the local buffer or
// stored property.
SILValue address = results[0].getUnmanagedValue();
address = B.createPointerToAddress(loc, address, buffer->getType(), /*isStrict*/ true);
address = B.createPointerToAddress(loc, address, buffer->getType(),
/*isStrict*/ true,
/*isInvariant*/ false);

// Project out the optional callback.
SILValue optionalCallback = results[1].getUnmanagedValue();
Expand Down Expand Up @@ -5391,7 +5393,9 @@ emitAddressorAccessor(SILLocation loc, SILDeclRef addressor,
SILType::getRawPointerType(getASTContext()));

// Convert to the appropriate address type and return.
SILValue address = B.createPointerToAddress(loc, pointer, addressType, /*isStrict*/ true);
SILValue address = B.createPointerToAddress(loc, pointer, addressType,
/*isStrict*/ true,
/*isInvariant*/ false);

// Mark dependence as necessary.
switch (cast<FuncDecl>(addressor.getDecl())->getAddressorKind()) {
Expand Down
39 changes: 29 additions & 10 deletions lib/SILGen/SILGenBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,8 @@ static ManagedValue emitBuiltinLoadOrTake(SILGenFunction &gen,
CanFunctionType formalApplyType,
SGFContext C,
IsTake_t isTake,
bool isStrict) {
bool isStrict,
bool isInvariant) {
assert(substitutions.size() == 1 && "load should have single substitution");
assert(args.size() == 1 && "load should have a single argument");

Expand All @@ -173,7 +174,7 @@ static ManagedValue emitBuiltinLoadOrTake(SILGenFunction &gen,
// Convert the pointer argument to a SIL address.
SILValue addr = gen.B.createPointerToAddress(loc, args[0].getUnmanagedValue(),
loadedType.getAddressType(),
isStrict);
isStrict, isInvariant);
// Perform the load.
return gen.emitLoad(loc, addr, rvalueTL, C, isTake);
}
Expand All @@ -186,7 +187,7 @@ static ManagedValue emitBuiltinLoad(SILGenFunction &gen,
SGFContext C) {
return emitBuiltinLoadOrTake(gen, loc, substitutions, args,
formalApplyType, C, IsNotTake,
/*isStrict*/ true);
/*isStrict*/ true, /*isInvariant*/ false);
}

static ManagedValue emitBuiltinLoadRaw(SILGenFunction &gen,
Expand All @@ -197,7 +198,17 @@ static ManagedValue emitBuiltinLoadRaw(SILGenFunction &gen,
SGFContext C) {
return emitBuiltinLoadOrTake(gen, loc, substitutions, args,
formalApplyType, C, IsNotTake,
/*isStrict*/ false);
/*isStrict*/ false, /*isInvariant*/ false);
}
static ManagedValue emitBuiltinLoadInvariant(SILGenFunction &gen,
SILLocation loc,
SubstitutionList substitutions,
ArrayRef<ManagedValue> args,
CanFunctionType formalApplyType,
SGFContext C) {
return emitBuiltinLoadOrTake(gen, loc, substitutions, args,
formalApplyType, C, IsNotTake,
/*isStrict*/ false, /*isInvariant*/ true);
}

static ManagedValue emitBuiltinTake(SILGenFunction &gen,
Expand All @@ -207,7 +218,8 @@ static ManagedValue emitBuiltinTake(SILGenFunction &gen,
CanFunctionType formalApplyType,
SGFContext C) {
return emitBuiltinLoadOrTake(gen, loc, substitutions, args,
formalApplyType, C, IsTake, /*isStrict*/ true);
formalApplyType, C, IsTake,
/*isStrict*/ true, /*isInvariant*/ false);
}

/// Specialized emitter for Builtin.destroy.
Expand All @@ -233,7 +245,8 @@ static ManagedValue emitBuiltinDestroy(SILGenFunction &gen,
SILValue addr =
gen.B.createPointerToAddress(loc, args[1].getUnmanagedValue(),
destroyType.getAddressType(),
/*isStrict*/ true);
/*isStrict*/ true,
/*isInvariant*/ false);

// Destroy the value indirectly. Canonicalization will promote to loads
// and releases if appropriate.
Expand All @@ -260,7 +273,8 @@ static ManagedValue emitBuiltinAssign(SILGenFunction &gen,
SILValue addr = gen.B.createPointerToAddress(loc,
args.back().getUnmanagedValue(),
assignType.getAddressType(),
/*isStrict*/ true);
/*isStrict*/ true,
/*isInvariant*/ false);

// Build the value to be assigned, reconstructing tuples if needed.
auto src = RValue::withPreExplodedElements(args.slice(0, args.size() - 1),
Expand All @@ -287,7 +301,8 @@ static ManagedValue emitBuiltinInit(SILGenFunction &gen,
SILValue addr = gen.emitRValueAsSingleValue(args[1]).getUnmanagedValue();
addr = gen.B.createPointerToAddress(
loc, addr, formalTL.getLoweredType().getAddressType(),
/*isStrict*/ true);
/*isStrict*/ true,
/*isInvariant*/ false);

TemporaryInitialization init(addr, CleanupHandle::invalid());
gen.emitExprInto(args[0], &init);
Expand Down Expand Up @@ -508,7 +523,9 @@ static ManagedValue emitBuiltinGep(SILGenFunction &gen,
SILType ElemTy = gen.getLoweredType(substitutions[0].getReplacement());
SILType RawPtrType = args[0].getUnmanagedValue()->getType();
SILValue addr = gen.B.createPointerToAddress(loc, args[0].getUnmanagedValue(),
ElemTy.getAddressType(), true);
ElemTy.getAddressType(),
/*strict*/ true,
/*invariant*/ false);
addr = gen.B.createIndexAddr(loc, addr, args[1].getUnmanagedValue());
addr = gen.B.createAddressToPointer(loc, addr, RawPtrType);

Expand All @@ -529,7 +546,9 @@ static ManagedValue emitBuiltinGetTailAddr(SILGenFunction &gen,
SILType TailTy = gen.getLoweredType(substitutions[1].getReplacement());
SILType RawPtrType = args[0].getUnmanagedValue()->getType();
SILValue addr = gen.B.createPointerToAddress(loc, args[0].getUnmanagedValue(),
ElemTy.getAddressType(), true);
ElemTy.getAddressType(),
/*strict*/ true,
/*invariant*/ false);
addr = gen.B.createTailAddr(loc, addr, args[1].getUnmanagedValue(),
TailTy.getAddressType());
addr = gen.B.createAddressToPointer(loc, addr, RawPtrType);
Expand Down
4 changes: 3 additions & 1 deletion lib/SILGen/SILGenExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1796,7 +1796,9 @@ VarargsInfo Lowering::emitBeginVarargs(SILGenFunction &gen, SILLocation loc,

// Turn the pointer into an address.
basePtr = gen.B.createPointerToAddress(
loc, basePtr, baseTL.getLoweredType().getAddressType(), /*isStrict*/ true);
loc, basePtr, baseTL.getLoweredType().getAddressType(),
/*isStrict*/ true,
/*isInvariant*/ false);

return VarargsInfo(array, abortCleanup, basePtr, baseTL, baseAbstraction);
}
Expand Down
2 changes: 1 addition & 1 deletion lib/SILGen/SILGenGlobalVariable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ SILGenFunction::emitGlobalVariableRef(SILLocation loc, VarDecl *var) {
// address.
addr = B.createPointerToAddress(
loc, addr, getLoweredType(var->getInterfaceType()).getAddressType(),
/*isStrict*/ true);
/*isStrict*/ true, /*isInvariant*/ false);
return ManagedValue::forLValue(addr);
}

Expand Down
6 changes: 4 additions & 2 deletions lib/SILGen/SILGenMaterializeForSet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -860,7 +860,8 @@ MaterializeForSetEmitter::emitUsingGetterSetter(SILGenFunction &gen,
resultBuffer =
gen.B.createPointerToAddress(loc, resultBuffer,
RequirementStorageType.getAddressType(),
/*isStrict*/ true);
/*isStrict*/ true,
/*isInvariant*/ false);
TemporaryInitialization init(resultBuffer, CleanupHandle::invalid());

// Evaluate the getter into the result buffer.
Expand Down Expand Up @@ -943,7 +944,8 @@ MaterializeForSetEmitter::createSetterCallback(SILFunction &F,
// The callback gets the value at +1.
auto &valueTL = gen.getTypeLowering(lvalue.getTypeOfRValue());
value = gen.B.createPointerToAddress(
loc, value, valueTL.getLoweredType().getAddressType(), /*isStrict*/ true);
loc, value, valueTL.getLoweredType().getAddressType(),
/*isStrict*/ true, /*isInvariant*/ false);
if (valueTL.isLoadable() || !gen.silConv.useLoweredAddresses())
value = valueTL.emitLoad(gen.B, loc, value, LoadOwnershipQualifier::Take);
ManagedValue mValue = gen.emitManagedRValueWithCleanup(value, valueTL);
Expand Down
3 changes: 2 additions & 1 deletion lib/SILOptimizer/SILCombiner/SILCombinerBuiltinVisitors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,8 @@ static SILInstruction *createIndexAddrFrom(IndexRawPointerInst *I,

// index_raw_pointer's address type is currently always strict.
auto *NewPTAI = Builder.createPointerToAddress(
I->getLoc(), Ptr, InstanceType.getAddressType(), /*isStrict*/ true);
I->getLoc(), Ptr, InstanceType.getAddressType(),
/*isStrict*/ true, /*isInvariant*/ false);

auto *DistanceAsWord =
Builder.createBuiltin(I->getLoc(), TruncOrBitCast->getName(),
Expand Down
5 changes: 3 additions & 2 deletions lib/SILOptimizer/SILCombiner/SILCombinerCastVisitors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@ visitPointerToAddressInst(PointerToAddressInst *PTAI) {

auto *NewPTAI = Builder.createPointerToAddress(PTAI->getLoc(), Ptr,
PTAI->getType(),
PTAI->isStrict());
PTAI->isStrict(),
PTAI->isInvariant());
auto DistanceAsWord = Builder.createBuiltin(
PTAI->getLoc(), Trunc->getName(), Trunc->getType(), {}, Distance);

Expand Down Expand Up @@ -181,7 +182,7 @@ visitPointerToAddressInst(PointerToAddressInst *PTAI) {
SILValue Distance = Bytes->getArguments()[0];
auto *NewPTAI =
Builder.createPointerToAddress(PTAI->getLoc(), Ptr, PTAI->getType(),
PTAI->isStrict());
PTAI->isStrict(), PTAI->isInvariant());
return Builder.createIndexAddr(PTAI->getLoc(), NewPTAI, Distance);
}
}
Expand Down
3 changes: 2 additions & 1 deletion lib/Serialization/DeserializeSIL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -913,12 +913,13 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB,
assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND &&
"Layout should be OneTypeOneOperand.");
bool isStrict = Attr & 0x01;
bool isInvariant = Attr & 0x02;
ResultVal = Builder.createPointerToAddress(
Loc,
getLocalValue(ValID, getSILType(MF->getType(TyID2),
(SILValueCategory)TyCategory2)),
getSILType(MF->getType(TyID), (SILValueCategory)TyCategory),
isStrict);
isStrict, isInvariant);
break;
}
case ValueKind::DeallocExistentialBoxInst: {
Expand Down
Loading