Skip to content

Commit 2c97b72

Browse files
committed
[Constant evaluator] Add support for destructure_tuple and
destructure_struct instructions to the constant evaluator.
1 parent 46f130a commit 2c97b72

File tree

2 files changed

+86
-2
lines changed

2 files changed

+86
-2
lines changed

lib/SILOptimizer/Utils/ConstExpr.cpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1359,9 +1359,9 @@ ConstExprFunctionState::evaluateFlowSensitive(SILInstruction *inst) {
13591359
injectEnumInst->getOperand());
13601360
}
13611361

1362-
// If the instruction produces normal results, try constant folding it.
1362+
// If the instruction produces a result, try constant folding it.
13631363
// If this fails, then we fail.
1364-
if (inst->getNumResults() != 0) {
1364+
if (isa<SingleValueInstruction>(inst)) {
13651365
auto oneResultVal = inst->getResults()[0];
13661366
auto result = getConstantValue(oneResultVal);
13671367
if (!result.isConstant())
@@ -1370,6 +1370,23 @@ ConstExprFunctionState::evaluateFlowSensitive(SILInstruction *inst) {
13701370
return None;
13711371
}
13721372

1373+
if (isa<DestructureTupleInst>(inst) || isa<DestructureStructInst>(inst)) {
1374+
auto *mvi = cast<MultipleValueInstruction>(inst);
1375+
SymbolicValue aggVal = getConstantValue(mvi->getOperand(0));
1376+
if (!aggVal.isConstant()) {
1377+
return aggVal;
1378+
}
1379+
assert(aggVal.getKind() == SymbolicValue::Aggregate);
1380+
1381+
ArrayRef<SymbolicValue> aggElems = aggVal.getAggregateValue();
1382+
assert(aggElems.size() == mvi->getNumResults());
1383+
1384+
for (unsigned i = 0; i < mvi->getNumResults(); ++i) {
1385+
setValue(mvi->getResult(i), aggElems[i]);
1386+
}
1387+
return None;
1388+
}
1389+
13731390
LLVM_DEBUG(llvm::dbgs() << "ConstExpr Unknown FS: " << *inst << "\n");
13741391
// If this is an unknown instruction with no results then bail out.
13751392
return evaluator.getUnknown(inst, UnknownReason::UnsupportedInstruction);

test/SILOptimizer/constant_evaluator_test.sil

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,3 +1076,70 @@ bb0:
10761076
%9 = apply %8(%6) : $@convention(method) (@guaranteed String) -> @owned String
10771077
return %9 : $String
10781078
} // CHECK: Returns string: "%%%%%%a%% %%%%b%%"
1079+
1080+
// Tests for Ownership SIL.
1081+
1082+
// CHECK-LABEL: @interpretDestructureInt64
1083+
sil [ossa] @interpretDestructureInt64 : $@convention(thin) () -> Builtin.Int64 {
1084+
%1 = integer_literal $Builtin.Int64, 12
1085+
%2 = struct $Int64 (%1 : $Builtin.Int64)
1086+
%3 = destructure_struct %2 : $Int64
1087+
return %3 : $Builtin.Int64
1088+
} // CHECK: Returns int: 12
1089+
1090+
struct IntPair {
1091+
var first: Builtin.Int64
1092+
var second: Builtin.Int64
1093+
}
1094+
1095+
// CHECK-LABEL: @interpretIntPairStruct
1096+
sil [ossa] @interpretIntPairStruct : $@convention(thin) () -> Builtin.Int64 {
1097+
bb0:
1098+
%0 = integer_literal $Builtin.Int64, 17
1099+
%1 = integer_literal $Builtin.Int64, 34
1100+
%2 = struct $IntPair (%0: $Builtin.Int64, %1: $Builtin.Int64)
1101+
(%3, %4) = destructure_struct %2 : $IntPair
1102+
return %4 : $Builtin.Int64
1103+
} // CHECK: Returns int: 34
1104+
1105+
sil [ossa] @constructCustomStructOSSA : $@convention(thin) () -> CustomStruct {
1106+
bb0:
1107+
%1 = integer_literal $Builtin.Int64, 11
1108+
%2 = struct $Int64 (%1 : $Builtin.Int64)
1109+
%3 = integer_literal $Builtin.Int64, 12
1110+
%4 = struct $Int64 (%3 : $Builtin.Int64)
1111+
%6 = integer_literal $Builtin.Int64, 13
1112+
%7 = struct $Int64 (%6 : $Builtin.Int64)
1113+
%8 = integer_literal $Builtin.Int1, 0
1114+
%9 = struct $Bool (%8 : $Builtin.Int1)
1115+
1116+
%10 = struct $InnerStruct (%7 : $Int64, %9 : $Bool)
1117+
%11 = tuple (%2 : $Int64, %4 : $Int64)
1118+
%12 = struct $CustomStruct (%11 : $(Int64, Int64), %10 : $InnerStruct)
1119+
return %12 : $CustomStruct
1120+
}
1121+
1122+
// CHECK-LABEL: @interpretCustomStructOSSA
1123+
sil [ossa] @interpretCustomStructOSSA : $@convention(thin) () -> Builtin.Int64 {
1124+
bb0:
1125+
%1 = function_ref @constructCustomStructOSSA : $@convention(thin) () -> CustomStruct
1126+
%2 = apply %1() : $@convention(thin) () -> CustomStruct
1127+
(%3, %4) = destructure_struct %2 : $CustomStruct
1128+
(%5, %6) = destructure_tuple %3 : $(Int64, Int64)
1129+
(%7, %8) = destructure_struct %4 : $InnerStruct
1130+
%9 = destructure_struct %5 : $Int64
1131+
%10 = destructure_struct %6 : $Int64
1132+
%11 = destructure_struct %7 : $Int64
1133+
%12 = destructure_struct %8 : $Bool
1134+
cond_fail %12 : $Builtin.Int1
1135+
1136+
%13 = integer_literal $Builtin.Int1, -1
1137+
%14 = builtin "sadd_with_overflow_Int64"(%9 : $Builtin.Int64, %10 : $Builtin.Int64, %13 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
1138+
(%15, %16) = destructure_tuple %14 : $(Builtin.Int64, Builtin.Int1)
1139+
cond_fail %16 : $Builtin.Int1
1140+
1141+
%17 = builtin "sadd_with_overflow_Int64"(%15 : $Builtin.Int64, %11 : $Builtin.Int64, %13 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
1142+
(%18, %19) = destructure_tuple %17 : $(Builtin.Int64, Builtin.Int1)
1143+
cond_fail %19 : $Builtin.Int1
1144+
return %18 : $Builtin.Int64
1145+
} // CHECK: Returns int: 36

0 commit comments

Comments
 (0)