Skip to content

Commit 26dc092

Browse files
Merge pull request #24410 from ravikandhadai/consteval_inject_enum_addr
[Const Evaluator] Add support for inject_enum_addr, select_enum and select_enum_addr
2 parents 0d955da + cb9cb31 commit 26dc092

File tree

2 files changed

+88
-0
lines changed

2 files changed

+88
-0
lines changed

lib/SILOptimizer/Utils/ConstExpr.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,27 @@ SymbolicValue ConstExprFunctionState::computeConstantValue(SILValue value) {
374374
return createMemoryObject(value, enumVal.getEnumPayloadValue());
375375
}
376376

377+
if (isa<SelectEnumInst>(value) || isa<SelectEnumAddrInst>(value)) {
378+
SelectEnumInstBase *selectInst = dyn_cast<SelectEnumInst>(value);
379+
if (!selectInst) {
380+
selectInst = dyn_cast<SelectEnumAddrInst>(value);
381+
}
382+
383+
SILValue enumOperand = selectInst->getEnumOperand();
384+
SymbolicValue enumValue = isa<SelectEnumInst>(selectInst)
385+
? getConstantValue(enumOperand)
386+
: getConstAddrAndLoadResult(enumOperand);
387+
if (!enumValue.isConstant())
388+
return enumValue;
389+
390+
assert(enumValue.getKind() == SymbolicValue::Enum ||
391+
enumValue.getKind() == SymbolicValue::EnumWithPayload);
392+
393+
SILValue resultOperand =
394+
selectInst->getCaseResult(enumValue.getEnumValue());
395+
return getConstantValue(resultOperand);
396+
}
397+
377398
// This instruction is a marker that returns its first operand.
378399
if (auto *bai = dyn_cast<BeginAccessInst>(value))
379400
return getConstantValue(bai->getOperand());
@@ -1279,6 +1300,11 @@ ConstExprFunctionState::evaluateFlowSensitive(SILInstruction *inst) {
12791300
return computeFSStore(value, copy->getOperand(1));
12801301
}
12811302

1303+
if (auto *injectEnumInst = dyn_cast<InjectEnumAddrInst>(inst)) {
1304+
return computeFSStore(SymbolicValue::getEnum(injectEnumInst->getElement()),
1305+
injectEnumInst->getOperand());
1306+
}
1307+
12821308
// If the instruction produces normal results, try constant folding it.
12831309
// If this fails, then we fail.
12841310
if (inst->getNumResults() != 0) {

test/SILOptimizer/constant_evaluator_test.sil

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -740,6 +740,68 @@ bb3(%30 : $Builtin.Int64):
740740
return %30 : $Builtin.Int64
741741
} // CHECK: Returns int: 100
742742

743+
// Test inject_enum_addr instruction.
744+
745+
public enum Direction {
746+
case north
747+
case south
748+
case east
749+
case west
750+
}
751+
752+
sil @isNorth : $@convention(thin) (@in_guaranteed Direction) -> Builtin.Int32 {
753+
bb0(%0 : $*Direction):
754+
switch_enum_addr %0 : $*Direction, case #Direction.north!enumelt: bb1, default bb2
755+
756+
bb1:
757+
%3 = integer_literal $Builtin.Int32, 1
758+
br bb3(%3 : $Builtin.Int32)
759+
760+
bb2:
761+
%6 = integer_literal $Builtin.Int32, 0
762+
br bb3(%6 : $Builtin.Int32)
763+
764+
bb3(%9 : $Builtin.Int32):
765+
return %9 : $Builtin.Int32
766+
}
767+
768+
// CHECK: @interpretTestInjectEnumAddr
769+
sil hidden @interpretTestInjectEnumAddr : $@convention(thin) () -> Builtin.Int32 {
770+
bb0:
771+
%1 = alloc_stack $Direction
772+
inject_enum_addr %1 : $*Direction, #Direction.north!enumelt
773+
%2 = function_ref @isNorth : $@convention(thin) (@in_guaranteed Direction) -> Builtin.Int32
774+
%3 = apply %2(%1) : $@convention(thin) (@in_guaranteed Direction) -> Builtin.Int32
775+
destroy_addr %1 : $*Direction
776+
dealloc_stack %1 : $*Direction
777+
return %3 : $Builtin.Int32
778+
} // CHECK: Returns int: 1
779+
780+
// Test select_enum and select_enum_addr instructions.
781+
782+
// CHECK: @interpretTestSelectEnum
783+
sil hidden @interpretTestSelectEnum : $@convention(thin) () -> Builtin.Int32 {
784+
bb0:
785+
%1 = enum $Direction, #Direction.north!enumelt
786+
%2 = integer_literal $Builtin.Int32, 1
787+
%3 = integer_literal $Builtin.Int32, 0
788+
%4 = select_enum %1 : $Direction, case #Direction.north!enumelt: %2, default %3 : $Builtin.Int32
789+
return %4 : $Builtin.Int32
790+
} // CHECK: Returns int: 1
791+
792+
// CHECK: @interpretTestSelectEnumAddr
793+
sil hidden @interpretTestSelectEnumAddr : $@convention(thin) () -> Builtin.Int32 {
794+
bb0:
795+
%1 = alloc_stack $Direction
796+
inject_enum_addr %1 : $*Direction, #Direction.north!enumelt
797+
%2 = integer_literal $Builtin.Int32, 1
798+
%3 = integer_literal $Builtin.Int32, 0
799+
%4 = select_enum_addr %1 : $*Direction, case #Direction.north!enumelt: %2, default %3 : $Builtin.Int32
800+
destroy_addr %1 : $*Direction
801+
dealloc_stack %1 : $*Direction
802+
return %4 : $Builtin.Int32
803+
} // CHECK: Returns int: 1
804+
743805
// Test calling conventions.
744806

745807
// Test struct with a string property. The struct will be passed and returned

0 commit comments

Comments
 (0)