Skip to content

Commit 11efa58

Browse files
committed
[Const Evaluator] Make compile-time constant evaluator correctly handle
s_to_s_checked_trunc_IntLiteral_IntNN where the bit width of the source symbolic value (an APInt) could be smaller than the destination bits.
1 parent 88a5c00 commit 11efa58

File tree

2 files changed

+26
-12
lines changed

2 files changed

+26
-12
lines changed

lib/SILOptimizer/Utils/ConstExpr.cpp

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -448,30 +448,35 @@ ConstExprFunctionState::computeConstantValueBuiltin(BuiltinInst *inst) {
448448
if (operand.getKind() != SymbolicValue::Integer)
449449
return unknownResult();
450450

451-
auto operandVal = operand.getIntegerValue();
451+
APInt operandVal = operand.getIntegerValue();
452452
uint32_t srcBitWidth = operandVal.getBitWidth();
453453
auto dstBitWidth =
454454
builtin.Types[1]->castTo<BuiltinIntegerType>()->getGreatestWidth();
455455

456-
APInt result = operandVal.trunc(dstBitWidth);
456+
// Note that the if the source type is a Builtin.IntLiteral, operandVal
457+
// could have fewer bits than the destination bit width and may only
458+
// require a sign extension.
459+
APInt result = operandVal.sextOrTrunc(dstBitWidth);
457460

458-
// Compute the overflow by re-extending the value back to its source and
459-
// checking for loss of value.
460-
APInt reextended =
461-
dstSigned ? result.sext(srcBitWidth) : result.zext(srcBitWidth);
462-
bool overflowed = (operandVal != reextended);
461+
// Determine if there is a overflow.
462+
if (operandVal.getBitWidth() > dstBitWidth) {
463+
// Re-extend the value back to its source and check for loss of value.
464+
APInt reextended =
465+
dstSigned ? result.sext(srcBitWidth) : result.zext(srcBitWidth);
466+
bool overflowed = (operandVal != reextended);
463467

464-
if (!srcSigned && dstSigned)
465-
overflowed |= result.isSignBitSet();
468+
if (!srcSigned && dstSigned)
469+
overflowed |= result.isSignBitSet();
466470

467-
if (overflowed)
468-
return evaluator.getUnknown(SILValue(inst), UnknownReason::Overflow);
471+
if (overflowed)
472+
return evaluator.getUnknown(SILValue(inst), UnknownReason::Overflow);
473+
}
469474

470475
auto &allocator = evaluator.getAllocator();
471476
// Build the Symbolic value result for our truncated value.
472477
return SymbolicValue::getAggregate(
473478
{SymbolicValue::getInteger(result, allocator),
474-
SymbolicValue::getInteger(APInt(1, overflowed), allocator)},
479+
SymbolicValue::getInteger(APInt(1, false), allocator)},
475480
allocator);
476481
};
477482

test/SILOptimizer/constant_evaluator_test.sil

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,15 @@ bb0:
153153
return %2 : $(Builtin.Int8)
154154
} // CHECK: Returns int: -1
155155

156+
// CHECK-LABEL: @interpretSignedTruncWithIntLiteral
157+
sil @interpretSignedTruncWithIntLiteral : $@convention(thin) () -> Builtin.Int64 {
158+
bb0:
159+
%0 = integer_literal $Builtin.IntLiteral, 5
160+
%1 = builtin "s_to_s_checked_trunc_IntLiteral_Int64"(%0 : $Builtin.IntLiteral) : $(Builtin.Int64, Builtin.Int1)
161+
%2 = tuple_extract %1 : $(Builtin.Int64, Builtin.Int1), 0
162+
return %2 : $(Builtin.Int64)
163+
} // CHECK: Returns int: 5
164+
156165
// CHECK-LABEL: @interpretSignedExtend
157166
sil @interpretSignedExtend : $@convention(thin) () -> Builtin.Int64 {
158167
bb0:

0 commit comments

Comments
 (0)