Skip to content

Commit 830ea2d

Browse files
Merge pull request #65770 from ravikandhadai/release/5.9
🍒 [5.9][Constant Evaluator] Enable SILConstants::setIndexedElement function to work with aggregates containing unknown values
2 parents 6c6f3f0 + 8693f76 commit 830ea2d

File tree

5 files changed

+90
-7
lines changed

5 files changed

+90
-7
lines changed

include/swift/SILOptimizer/Utils/ConstExpr.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,10 @@ class ConstExprStepEvaluator {
127127
ConstExprStepEvaluator(const ConstExprStepEvaluator &) = delete;
128128
void operator=(const ConstExprStepEvaluator &) = delete;
129129

130+
/// Set all addresses that could be mutated by the instruction to an
131+
/// unknown symbolic value if it is not already so.
132+
void setMutableAddressesToUnknown(SILInstruction *inst);
133+
130134
public:
131135
/// Constructs a step evaluator given an allocator and a non-null pointer to a
132136
/// SILFunction.

lib/SIL/IR/SILConstants.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,6 +1174,11 @@ static SymbolicValue setIndexedElement(SymbolicValue aggregate,
11741174
if (accessPath.empty())
11751175
return newElement;
11761176

1177+
// Callers are required to ensure unknowns are not passed. However,
1178+
// the recurisve call can pass an unknown as an aggregate.
1179+
if (aggregate.getKind() == SymbolicValue::Unknown)
1180+
return aggregate;
1181+
11771182
// If we have an uninit memory, then scalarize it into an aggregate to
11781183
// continue. This happens when memory objects are initialized piecewise.
11791184
if (aggregate.getKind() == SymbolicValue::UninitMemory) {

lib/SILOptimizer/Utils/ConstExpr.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2162,13 +2162,8 @@ ConstExprStepEvaluator::evaluate(SILBasicBlock::iterator instI) {
21622162
return internalState->evaluateInstructionAndGetNext(instI, visitedBlocks);
21632163
}
21642164

2165-
std::pair<Optional<SILBasicBlock::iterator>, Optional<SymbolicValue>>
2166-
ConstExprStepEvaluator::skipByMakingEffectsNonConstant(
2167-
SILBasicBlock::iterator instI) {
2168-
SILInstruction *inst = &(*instI);
2169-
2170-
// Set all constant state that could be mutated by the instruction
2171-
// to an unknown symbolic value.
2165+
void ConstExprStepEvaluator::setMutableAddressesToUnknown(
2166+
SILInstruction *inst) {
21722167
for (auto &operand : inst->getAllOperands()) {
21732168
auto constValOpt = lookupConstValue(operand.get());
21742169
if (!constValOpt) {
@@ -2225,6 +2220,15 @@ ConstExprStepEvaluator::skipByMakingEffectsNonConstant(
22252220
memoryObject->setValue(unknownValue);
22262221
}
22272222
}
2223+
}
2224+
2225+
std::pair<Optional<SILBasicBlock::iterator>, Optional<SymbolicValue>>
2226+
ConstExprStepEvaluator::skipByMakingEffectsNonConstant(
2227+
SILBasicBlock::iterator instI) {
2228+
SILInstruction *inst = &(*instI);
2229+
2230+
if (inst->mayWriteToMemory())
2231+
setMutableAddressesToUnknown(inst);
22282232

22292233
// Map the results of this instruction to unknown values.
22302234
for (auto result : inst->getResults()) {

test/SILOptimizer/Inputs/OSLogConstantEvaluable.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,19 @@ func intValueWithPrecisionTest() -> OSLogMessage {
5050
func intValueWithPrivacyTest() -> OSLogMessage {
5151
return "An integer value \(10, privacy: .private(mask: .hash))"
5252
}
53+
54+
// Test OSLogMessage with SIMD interpolations
55+
struct FloatVector {
56+
let zero = SIMD4<Float>()
57+
var pair: (SIMD4<Float>, SIMD4<Float>)
58+
59+
init() {
60+
pair = (zero, zero)
61+
}
62+
}
63+
64+
@_semantics("test_driver")
65+
func testOSLogMessageSIMDInterpolation() -> OSLogMessage {
66+
let vector = FloatVector()
67+
return "\(vector.pair.0.x)"
68+
}

test/SILOptimizer/constant_evaluator_skip_test.sil

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,3 +330,57 @@ bb0:
330330
dealloc_stack %0 : $*Outer
331331
return %32 : $Builtin.Int64
332332
} // CHECK: Returns int: 103
333+
334+
// Test whether the constant evaluator can handle reading and writing into
335+
// structs containing unknown symbolic values created by skipping functions.
336+
337+
struct UnknownStruct {
338+
let value: Int64
339+
}
340+
341+
struct StructWithSkippedElements {
342+
let knownValue: Int64
343+
let unknownValue: UnknownStruct
344+
}
345+
346+
sil @skipUnknownStructCreate : $@convention(thin) () -> UnknownStruct
347+
348+
// CHECK-LABEL: @interpretStructsWithSkippedElements
349+
sil @interpretStructsWithSkippedElements : $@convention(thin) () -> Builtin.Int64 {
350+
bb0:
351+
%0 = integer_literal $Builtin.Int64, 301
352+
%1 = struct $Int64 (%0 : $Builtin.Int64)
353+
%2 = function_ref @skipUnknownStructCreate : $@convention(thin) () -> UnknownStruct
354+
%3 = apply %2() : $@convention(thin) () -> UnknownStruct
355+
%4 = struct $StructWithSkippedElements (%1 : $Int64, %3 : $UnknownStruct)
356+
%5 = alloc_stack $StructWithSkippedElements, var, name "s"
357+
store %4 to %5 : $*StructWithSkippedElements
358+
359+
%6 = struct_element_addr %5 : $*StructWithSkippedElements, #StructWithSkippedElements.unknownValue
360+
%7 = struct_element_addr %6 : $*UnknownStruct, #UnknownStruct.value
361+
%8 = load %7 : $*Int64
362+
%9 = struct_extract %8 : $Int64, #Int64._value
363+
dealloc_stack %5 : $*StructWithSkippedElements
364+
return %9 : $Builtin.Int64
365+
} // CHECK: Returns unknown
366+
367+
// CHECK-LABEL: @interpretStructsWithSkippedElementsRW
368+
sil @interpretStructsWithSkippedElementsRW : $@convention(thin) () -> Builtin.Int64 {
369+
bb0:
370+
%0 = integer_literal $Builtin.Int64, 301
371+
%1 = struct $Int64 (%0 : $Builtin.Int64)
372+
%2 = function_ref @skipUnknownStructCreate : $@convention(thin) () -> UnknownStruct
373+
%3 = apply %2() : $@convention(thin) () -> UnknownStruct
374+
%4 = struct $StructWithSkippedElements (%1 : $Int64, %3 : $UnknownStruct)
375+
%5 = alloc_stack $StructWithSkippedElements, var, name "s"
376+
store %4 to %5 : $*StructWithSkippedElements
377+
378+
%6 = struct_element_addr %5 : $*StructWithSkippedElements, #StructWithSkippedElements.unknownValue
379+
%7 = struct_element_addr %6 : $*UnknownStruct, #UnknownStruct.value
380+
store %1 to %7 : $*Int64
381+
%8 = struct_element_addr %5 : $*StructWithSkippedElements, #StructWithSkippedElements.knownValue
382+
%9 = load %8 : $*Int64
383+
%10 = struct_extract %9 : $Int64, #Int64._value
384+
dealloc_stack %5 : $*StructWithSkippedElements
385+
return %10 : $Builtin.Int64
386+
} // CHECK: Returns int: 301

0 commit comments

Comments
 (0)