Skip to content

Commit

Permalink
Merge pull request #25677 from ravikandhadai/constexpr-intliteral-trunc
Browse files Browse the repository at this point in the history
[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
  • Loading branch information
ravikandhadai committed Jun 23, 2019
2 parents f7d37aa + 11efa58 commit bcdd46c
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 12 deletions.
29 changes: 17 additions & 12 deletions lib/SILOptimizer/Utils/ConstExpr.cpp
Expand Up @@ -448,30 +448,35 @@ ConstExprFunctionState::computeConstantValueBuiltin(BuiltinInst *inst) {
if (operand.getKind() != SymbolicValue::Integer)
return unknownResult();

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

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

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

if (!srcSigned && dstSigned)
overflowed |= result.isSignBitSet();
if (!srcSigned && dstSigned)
overflowed |= result.isSignBitSet();

if (overflowed)
return evaluator.getUnknown(SILValue(inst), UnknownReason::Overflow);
if (overflowed)
return evaluator.getUnknown(SILValue(inst), UnknownReason::Overflow);
}

auto &allocator = evaluator.getAllocator();
// Build the Symbolic value result for our truncated value.
return SymbolicValue::getAggregate(
{SymbolicValue::getInteger(result, allocator),
SymbolicValue::getInteger(APInt(1, overflowed), allocator)},
SymbolicValue::getInteger(APInt(1, false), allocator)},
allocator);
};

Expand Down
9 changes: 9 additions & 0 deletions test/SILOptimizer/constant_evaluator_test.sil
Expand Up @@ -153,6 +153,15 @@ bb0:
return %2 : $(Builtin.Int8)
} // CHECK: Returns int: -1

// CHECK-LABEL: @interpretSignedTruncWithIntLiteral
sil @interpretSignedTruncWithIntLiteral : $@convention(thin) () -> Builtin.Int64 {
bb0:
%0 = integer_literal $Builtin.IntLiteral, 5
%1 = builtin "s_to_s_checked_trunc_IntLiteral_Int64"(%0 : $Builtin.IntLiteral) : $(Builtin.Int64, Builtin.Int1)
%2 = tuple_extract %1 : $(Builtin.Int64, Builtin.Int1), 0
return %2 : $(Builtin.Int64)
} // CHECK: Returns int: 5

// CHECK-LABEL: @interpretSignedExtend
sil @interpretSignedExtend : $@convention(thin) () -> Builtin.Int64 {
bb0:
Expand Down

0 comments on commit bcdd46c

Please sign in to comment.