Skip to content

Commit 768a404

Browse files
author
Josh Learn
authored
Merge pull request #32911 from guitard0g/oslog_profiling
[Constant Evaluator] Skip code-coverage instrumentation during constant evaluation
2 parents 6334c34 + 7cbc21b commit 768a404

16 files changed

+1072
-996
lines changed

include/swift/AST/Builtins.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,9 @@ BUILTIN_MISC_OPERATION(PoundAssert, "poundAssert", "", Special)
701701
// TypePtrAuthDiscriminator has type <T> (T.Type) -> Int64
702702
BUILTIN_MISC_OPERATION(TypePtrAuthDiscriminator, "typePtrAuthDiscriminator", "n", Special)
703703

704+
// int_instrprof_increment has type (Builtin.RawPointer, Builtin.Int64, Builtin.Int32, Builtin.Int32) -> ().
705+
BUILTIN_MISC_OPERATION(IntInstrprofIncrement, "int_instrprof_increment", "", Special)
706+
704707
// BUILTIN_MISC_OPERATION_WITH_SILGEN - Miscellaneous operations that are
705708
// specially emitted during SIL generation.
706709
//

include/swift/SIL/InstructionUtils.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@ bool mayCheckRefCount(SILInstruction *User);
118118
/// run-time sanitizers.
119119
bool isSanitizerInstrumentation(SILInstruction *Instruction);
120120

121+
/// Return true when the instruction represents added instrumentation for
122+
/// run-time sanitizers or code coverage.
123+
bool isInstrumentation(SILInstruction *Instruction);
124+
121125
/// Check that this is a partial apply of a reabstraction thunk and return the
122126
/// argument of the partial apply if it is.
123127
SILValue isPartialApplyOfReabstractionThunk(PartialApplyInst *PAI);

lib/AST/Builtins.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "swift/AST/Module.h"
2121
#include "swift/AST/ParameterList.h"
2222
#include "swift/AST/TypeCheckRequests.h"
23+
#include "swift/AST/Types.h"
2324
#include "swift/Strings.h"
2425
#include "llvm/ADT/SmallString.h"
2526
#include "llvm/ADT/StringSwitch.h"
@@ -950,6 +951,15 @@ static ValueDecl *getUnsafeGuaranteedEnd(ASTContext &C, Identifier Id) {
950951
return getBuiltinFunction(Id, { Int8Ty }, TupleType::getEmpty(C));
951952
}
952953

954+
static ValueDecl *getIntInstrprofIncrement(ASTContext &C, Identifier Id) {
955+
// (Builtin.RawPointer, Builtin.Int64, Builtin.Int32, Builtin.Int32) -> ()
956+
Type Int64Ty = BuiltinIntegerType::get(64, C);
957+
Type Int32Ty = BuiltinIntegerType::get(32, C);
958+
return getBuiltinFunction(Id,
959+
{C.TheRawPointerType, Int64Ty, Int32Ty, Int32Ty},
960+
TupleType::getEmpty(C));
961+
}
962+
953963
static ValueDecl *getTypePtrAuthDiscriminator(ASTContext &C, Identifier Id) {
954964
// <T : AnyObject> (T.Type) -> Int64
955965
BuiltinFunctionBuilder builder(C);
@@ -2458,6 +2468,9 @@ ValueDecl *swift::getBuiltinValueDecl(ASTContext &Context, Identifier Id) {
24582468
{},
24592469
TupleType::getEmpty(Context));
24602470

2471+
case BuiltinValueKind::IntInstrprofIncrement:
2472+
return getIntInstrprofIncrement(Context, Id);
2473+
24612474
case BuiltinValueKind::TypePtrAuthDiscriminator:
24622475
return getTypePtrAuthDiscriminator(Context, Id);
24632476

lib/SIL/IR/OperandOwnership.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,6 +1013,7 @@ ANY_OWNERSHIP_BUILTIN(Swift3ImplicitObjCEntrypoint)
10131013
ANY_OWNERSHIP_BUILTIN(PoundAssert)
10141014
ANY_OWNERSHIP_BUILTIN(GlobalStringTablePointer)
10151015
ANY_OWNERSHIP_BUILTIN(TypePtrAuthDiscriminator)
1016+
ANY_OWNERSHIP_BUILTIN(IntInstrprofIncrement)
10161017
#undef ANY_OWNERSHIP_BUILTIN
10171018

10181019
// This is correct today since we do not have any builtins which return

lib/SIL/IR/ValueOwnership.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,7 @@ CONSTANT_OWNERSHIP_BUILTIN(None, TSanInoutAccess)
539539
CONSTANT_OWNERSHIP_BUILTIN(None, Swift3ImplicitObjCEntrypoint)
540540
CONSTANT_OWNERSHIP_BUILTIN(None, PoundAssert)
541541
CONSTANT_OWNERSHIP_BUILTIN(None, TypePtrAuthDiscriminator)
542+
CONSTANT_OWNERSHIP_BUILTIN(None, IntInstrprofIncrement)
542543
CONSTANT_OWNERSHIP_BUILTIN(None, GlobalStringTablePointer)
543544

544545
#undef CONSTANT_OWNERSHIP_BUILTIN

lib/SIL/Utils/InstructionUtils.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,21 @@ bool swift::isSanitizerInstrumentation(SILInstruction *Instruction) {
327327
return false;
328328
}
329329

330+
// Instrumentation instructions should not affect the correctness of the
331+
// program. That is, they should not affect the observable program state.
332+
// The constant evaluator relies on this property to skip instructions.
333+
bool swift::isInstrumentation(SILInstruction *Instruction) {
334+
if (isSanitizerInstrumentation(Instruction))
335+
return true;
336+
337+
if (BuiltinInst *bi = dyn_cast<BuiltinInst>(Instruction)) {
338+
if (bi->getBuiltinKind() == BuiltinValueKind::IntInstrprofIncrement)
339+
return true;
340+
}
341+
342+
return false;
343+
}
344+
330345
SILValue swift::isPartialApplyOfReabstractionThunk(PartialApplyInst *PAI) {
331346
// A partial_apply of a reabstraction thunk either has a single capture
332347
// (a function) or two captures (function and dynamic Self type).

lib/SILGen/SILGenFunction.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -973,8 +973,10 @@ void SILGenFunction::emitProfilerIncrement(ASTNode N) {
973973
B.createIntegerLiteral(Loc, Int64Ty, SP->getPGOFuncHash()),
974974
B.createIntegerLiteral(Loc, Int32Ty, SP->getNumRegionCounters()),
975975
B.createIntegerLiteral(Loc, Int32Ty, CounterIt->second)};
976-
B.createBuiltin(Loc, C.getIdentifier("int_instrprof_increment"),
977-
SGM.Types.getEmptyTupleType(), {}, Args);
976+
B.createBuiltin(
977+
Loc,
978+
C.getIdentifier(getBuiltinName(BuiltinValueKind::IntInstrprofIncrement)),
979+
SGM.Types.getEmptyTupleType(), {}, Args);
978980
}
979981

980982
ProfileCounter SILGenFunction::loadProfilerCount(ASTNode Node) const {

lib/SILOptimizer/Transforms/AccessEnforcementReleaseSinking.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ static bool isBarrier(SILInstruction *inst) {
139139
case BuiltinValueKind::TypePtrAuthDiscriminator:
140140
case BuiltinValueKind::GlobalStringTablePointer:
141141
case BuiltinValueKind::COWBufferForReading:
142+
case BuiltinValueKind::IntInstrprofIncrement:
142143
return false;
143144

144145
// Handle some rare builtins that may be sensitive to object lifetime

lib/SILOptimizer/Utils/ConstExpr.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
#include "swift/SIL/SILInstruction.h"
1314
#define DEBUG_TYPE "ConstExpr"
1415
#include "swift/SILOptimizer/Utils/ConstExpr.h"
16+
#include "swift/AST/Builtins.h"
1517
#include "swift/AST/ProtocolConformance.h"
1618
#include "swift/AST/SemanticAttrs.h"
1719
#include "swift/AST/SubstitutionMap.h"
@@ -1756,8 +1758,8 @@ ConstExprFunctionState::evaluateFlowSensitive(SILInstruction *inst) {
17561758
isa<ReleaseValueInst>(inst) || isa<StrongRetainInst>(inst) ||
17571759
isa<StrongReleaseInst>(inst) || isa<DestroyValueInst>(inst) ||
17581760
isa<EndBorrowInst>(inst) ||
1759-
// Skip sanitizer instrumentation
1760-
isSanitizerInstrumentation(inst))
1761+
// Skip instrumentation
1762+
isInstrumentation(inst))
17611763
return None;
17621764

17631765
// If this is a special flow-sensitive instruction like a stack allocation,
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Source Input used by OSLogConstantEvaluableTest.swift and OSLogConstantEvaluableProfilerTest.swift
2+
// Test that the functions defined in the OSLogPrototype overlay annotated as
3+
// constant evaluable are so (with the constexpr-limit defined above).
4+
// This test is meant to catch regressions in the OSLog overlay implementation
5+
// affecting the constant evaluability of functions that are expected to be so.
6+
7+
import OSLogTestHelper
8+
9+
// CHECK-LABEL: @init(stringLiteral: String) -> OSLogMessage
10+
// CHECK-NOT: error:
11+
@_semantics("test_driver")
12+
func osLogMessageStringLiteralInitTest() -> OSLogMessage {
13+
return "A string literal"
14+
}
15+
16+
// CHECK-LABEL: @init(literalCapacity: Int, interpolationCount: Int) -> OSLogInterpolation
17+
// CHECK-NOT: error:
18+
// CHECK-LABEL: @appendLiteral(String) -> ()
19+
// CHECK-NOT: error:
20+
// CHECK-LABEL: @appendInterpolation(_: @autoclosure () -> Int, format: OSLogIntegerFormatting, align: OSLogStringAlignment, privacy: OSLogPrivacy) -> ()
21+
// CHECK-NOT: error:
22+
// CHECK-LABEL: @appendLiteral(String) -> ()
23+
// CHECK-NOT: error:
24+
// CHECK-LABEL: @init(stringInterpolation: OSLogInterpolation) -> OSLogMessage
25+
// CHECK-NOT: error:
26+
@_semantics("test_driver")
27+
func intValueInterpolationTest() -> OSLogMessage {
28+
return "An integer value \(10)"
29+
}
30+
31+
// CHECK-LABEL: @init(literalCapacity: Int, interpolationCount: Int) -> OSLogInterpolation
32+
// CHECK-NOT: error:
33+
// CHECK-LABEL: @appendInterpolation(_: @autoclosure () -> String, align: OSLogStringAlignment, privacy: OSLogPrivacy) -> ()
34+
// CHECK-NOT: error:
35+
@_semantics("test_driver")
36+
func stringValueInterpolationTest() -> OSLogMessage {
37+
return "A string value \("xyz")"
38+
}
39+
40+
@_semantics("test_driver")
41+
func intValueWithPrecisionTest() -> OSLogMessage {
42+
return
43+
"""
44+
An integer value \
45+
\(10, format: .decimal(minDigits: 25), align: .right(columns: 10))
46+
"""
47+
}

0 commit comments

Comments
 (0)