mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-02 22:02:51 +01:00
Though I started this thinking about performance of parse of large
decimal integers, I extended it to generally improve performance of
integer values (TBH I hadn't expected such a difference for binary/hex,
but I'll take it).
Note I think tests change because I'm making subtle changes to bit
widths. The changes themselves appear harmless to me, but happy to make
changes if it'd help.
Bumping up the number of digits by 10x because it's not really a
performance issue anymore (eh, maybe somebody will want to specify a
256-byte value in binary). But, at a certain point it still seems like a
mistake if somebody has that many digits in a row.
Fixes #980
Highlighting benchmark differences:
```diff
- BM_ComputeValue_IntDecimalN/1 37.1 ns 37.1 ns 18887116
+ BM_ComputeValue_IntDecimalN/1 21.9 ns 21.9 ns 31902433
- BM_ComputeValue_IntDecimalN/10000 1251228680 ns 1250457559 ns 1
+ BM_ComputeValue_IntDecimalN/10000 458818 ns 458626 ns 1523
- BM_ComputeValue_IntBinaryN/1 29.0 ns 29.0 ns 24058533
+ BM_ComputeValue_IntBinaryN/1 22.2 ns 22.1 ns 31566949
- BM_ComputeValue_IntBinaryN/10000 1390557 ns 1389782 ns 506
+ BM_ComputeValue_IntBinaryN/10000 16402 ns 16396 ns 42744
- BM_ComputeValue_IntHexN/1 34.0 ns 34.0 ns 20562432
+ BM_ComputeValue_IntHexN/1 22.4 ns 22.4 ns 31238055
- BM_ComputeValue_IntHexN/10000 5387942 ns 5385262 ns 130
+ BM_ComputeValue_IntHexN/10000 39249 ns 39233 ns 17859
```
Benchmark before:
```
----------------------------------------------------------------------------
Benchmark Time CPU Iterations
----------------------------------------------------------------------------
BM_Lex_Float 10.6 ns 10.6 ns 66138191
BM_Lex_Int 15.5 ns 15.4 ns 45149703
BM_Lex_IntDecimalN/1 3.11 ns 3.11 ns 225524908
BM_Lex_IntDecimalN/10 11.8 ns 11.8 ns 56719805
BM_Lex_IntDecimalN/100 102 ns 102 ns 6867468
BM_Lex_IntDecimalN/1000 943 ns 942 ns 745313
BM_Lex_IntDecimalN/10000 9465 ns 9461 ns 73970
BM_ComputeValue_Float 61.6 ns 61.6 ns 11377463
BM_ComputeValue_Int 106 ns 106 ns 6587381
BM_ComputeValue_IntDecimalN/1 37.1 ns 37.1 ns 18887116
BM_ComputeValue_IntDecimalN/10 87.7 ns 87.7 ns 7960837
BM_ComputeValue_IntDecimalN/100 7963 ns 7956 ns 88858
BM_ComputeValue_IntDecimalN/1000 1212577 ns 1211906 ns 578
BM_ComputeValue_IntDecimalN/10000 1251228680 ns 1250457559 ns 1
BM_ComputeValue_IntBinaryN/1 29.0 ns 29.0 ns 24058533
BM_ComputeValue_IntBinaryN/10 69.4 ns 69.4 ns 10108642
BM_ComputeValue_IntBinaryN/100 963 ns 962 ns 726982
BM_ComputeValue_IntBinaryN/1000 21562 ns 21551 ns 32506
BM_ComputeValue_IntBinaryN/10000 1390557 ns 1389782 ns 506
BM_ComputeValue_IntHexN/1 34.0 ns 34.0 ns 20562432
BM_ComputeValue_IntHexN/10 70.4 ns 70.4 ns 9953165
BM_ComputeValue_IntHexN/100 1474 ns 1473 ns 472776
BM_ComputeValue_IntHexN/1000 61818 ns 61762 ns 11363
BM_ComputeValue_IntHexN/10000 5387942 ns 5385262 ns 130
```
Benchmark after:
```
----------------------------------------------------------------------------
Benchmark Time CPU Iterations
----------------------------------------------------------------------------
BM_Lex_Float 10.9 ns 10.9 ns 63993114
BM_Lex_Int 15.1 ns 15.1 ns 46869766
BM_Lex_IntDecimalN/1 3.16 ns 3.16 ns 220923300
BM_Lex_IntDecimalN/10 12.2 ns 12.2 ns 57731654
BM_Lex_IntDecimalN/100 102 ns 102 ns 6875516
BM_Lex_IntDecimalN/1000 942 ns 942 ns 742359
BM_Lex_IntDecimalN/10000 9353 ns 9350 ns 75096
BM_ComputeValue_Float 44.9 ns 44.9 ns 15619691
BM_ComputeValue_Int 48.9 ns 48.9 ns 14361507
BM_ComputeValue_IntDecimalN/1 21.9 ns 21.9 ns 31902433
BM_ComputeValue_IntDecimalN/10 30.3 ns 30.3 ns 23134117
BM_ComputeValue_IntDecimalN/100 224 ns 223 ns 3092567
BM_ComputeValue_IntDecimalN/1000 5834 ns 5830 ns 117469
BM_ComputeValue_IntDecimalN/10000 458818 ns 458626 ns 1523
BM_ComputeValue_IntBinaryN/1 22.2 ns 22.1 ns 31566949
BM_ComputeValue_IntBinaryN/10 32.9 ns 32.9 ns 21306927
BM_ComputeValue_IntBinaryN/100 198 ns 198 ns 3545277
BM_ComputeValue_IntBinaryN/1000 1671 ns 1669 ns 419656
BM_ComputeValue_IntBinaryN/10000 16402 ns 16396 ns 42744
BM_ComputeValue_IntHexN/1 22.4 ns 22.4 ns 31238055
BM_ComputeValue_IntHexN/10 47.8 ns 47.7 ns 14694407
BM_ComputeValue_IntHexN/100 436 ns 436 ns 1609794
BM_ComputeValue_IntHexN/1000 3966 ns 3962 ns 177109
BM_ComputeValue_IntHexN/10000 39249 ns 39233 ns 17859
```
Assisted-by: Google Antigravity with Gemini
169 lines
10 KiB
Plaintext
169 lines
10 KiB
Plaintext
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
|
// Exceptions. See /LICENSE for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon
|
|
//
|
|
// AUTOUPDATE
|
|
// TIP: To test this file alone, run:
|
|
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/primitives/numeric_literals.carbon
|
|
// TIP: To dump output, run:
|
|
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/primitives/numeric_literals.carbon
|
|
|
|
// --- literal_values.carbon
|
|
|
|
library "[[@TEST_NAME]]";
|
|
|
|
fn F() {
|
|
// 8 and 9 trigger special behavior in APInt when mishandling signed versus
|
|
// unsigned, so we pay extra attention to those.
|
|
var unused ints: array(i32, 6) = (
|
|
//@dump-sem-ir-begin
|
|
8,
|
|
9,
|
|
0x8,
|
|
0b1000,
|
|
2147483647,
|
|
0x7FFFFFFF,
|
|
//@dump-sem-ir-end
|
|
);
|
|
var unused floats: array(f64, 6) = (
|
|
//@dump-sem-ir-begin
|
|
0.9,
|
|
8.0,
|
|
80.0,
|
|
1.0e7,
|
|
1.0e8,
|
|
1.0e-8
|
|
//@dump-sem-ir-end
|
|
);
|
|
}
|
|
|
|
// --- fail_overflow_very_large.carbon
|
|
|
|
library "[[@TEST_NAME]]";
|
|
|
|
// CHECK:STDERR: fail_overflow_very_large.carbon:[[@LINE+4]]:14: error: integer value 39999999999999999993 too large for type `i32` [IntTooLargeForType]
|
|
// CHECK:STDERR: let a: i32 = 39999999999999999993;
|
|
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~
|
|
// CHECK:STDERR:
|
|
let a: i32 = 39999999999999999993;
|
|
|
|
// --- fail_overflow_boundary.carbon
|
|
|
|
library "[[@TEST_NAME]]";
|
|
|
|
// CHECK:STDERR: fail_overflow_boundary.carbon:[[@LINE+4]]:14: error: integer value 2147483648 too large for type `i32` [IntTooLargeForType]
|
|
// CHECK:STDERR: let b: i32 = 2_147_483_648;
|
|
// CHECK:STDERR: ^~~~~~~~~~~~~
|
|
// CHECK:STDERR:
|
|
let b: i32 = 2_147_483_648;
|
|
|
|
// --- fail_overflow_boundary_hex.carbon
|
|
|
|
library "[[@TEST_NAME]]";
|
|
|
|
// CHECK:STDERR: fail_overflow_boundary_hex.carbon:[[@LINE+4]]:14: error: integer value 2147483648 too large for type `i32` [IntTooLargeForType]
|
|
// CHECK:STDERR: let c: i32 = 0x8000_0000;
|
|
// CHECK:STDERR: ^~~~~~~~~~~
|
|
// CHECK:STDERR:
|
|
let c: i32 = 0x8000_0000;
|
|
|
|
// --- very_large_mantissa.carbon
|
|
|
|
library "[[@TEST_NAME]]";
|
|
|
|
let large: f64 = 99999999999999999999999999999999999999999999999999999999999999999999999.0e237;
|
|
let max_trunc: f64 = 17976931348623157081452742373170435679807056752584499659891747680315726.0e238;
|
|
let max: f64 = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0;
|
|
|
|
let max_hex: f64 = 0x1.FFFFFFFFFFFFFp+1023;
|
|
|
|
// The largest number that wouldn't round to have an out-of-bounds exponent.
|
|
// This is 2^1024 - 2^54 - epsilon.
|
|
// TODO: The design says that we should treat this as an error. Decide if that's
|
|
// right or if we want to round before checking for overflow.
|
|
let max_rounds_down: f64 = 179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497791.9999999999999;
|
|
let max_rounds_down_trunc: f64 = 17976931348623158079372897140530341507993413271003782693617377898044496.8e238;
|
|
|
|
let max_rounds_down_hex: f64 = 0x1.FFFFFFFFFFFFF7FFFFFFFFFFp+1023;
|
|
|
|
// --- fail_overflow_very_large_mantissa.carbon
|
|
|
|
library "[[@TEST_NAME]]";
|
|
|
|
// CHECK:STDERR: fail_overflow_very_large_mantissa.carbon:[[@LINE+4]]:22: error: value 399999999999999999999999999999999999999999999999999999999999999999999990*10^237 too large for floating-point type `f64` [FloatLiteralTooLargeForType]
|
|
// CHECK:STDERR: let too_large: f64 = 39999999999999999999999999999999999999999999999999999999999999999999999.0e238;
|
|
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// CHECK:STDERR:
|
|
let too_large: f64 = 39999999999999999999999999999999999999999999999999999999999999999999999.0e238;
|
|
|
|
// TODO: These are larger than DBL_MAX but would still round to DBL_MAX if f64
|
|
// had a wider exponent field. The design says these are invalid.
|
|
let above_max_trunc: f64 = 17976931348623157081452742373170435679807056752584499659891747680315727.0e238;
|
|
let max_plus_one: f64 = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858369.0;
|
|
let max_plus_a_bit_hex: f64 = 0x1.FFFFFFFFFFFFF00000000000000000000001p+1023;
|
|
|
|
// The smallest number that would round to having an over-large exponent.
|
|
// CHECK:STDERR: fail_overflow_very_large_mantissa.carbon:[[@LINE+4]]:30: error: value 1797693134862315807937289714053034150799341327100378269361737789804449682927647509466490179775872070963302864166928879109465555478519404026306574886715058206819089020007083836762738548458177115317644757302700698555713669596228429148198608349364752927190741684443655107043427115596995080930428801779041744977920*10^-1 too large for floating-point type `f64` [FloatLiteralTooLargeForType]
|
|
// CHECK:STDERR: let min_rounds_to_inf: f64 = 179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497792.0;
|
|
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// CHECK:STDERR:
|
|
let min_rounds_to_inf: f64 = 179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497792.0;
|
|
|
|
// CHECK:STDERR: fail_overflow_very_large_mantissa.carbon:[[@LINE+4]]:41: error: value 179769313486231580793728971405303415079934132710037826936173778980444969*10^237 too large for floating-point type `f64` [FloatLiteralTooLargeForType]
|
|
// CHECK:STDERR: let min_rounds_to_inf_rounded_up: f64 = 17976931348623158079372897140530341507993413271003782693617377898044496.9e238;
|
|
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// CHECK:STDERR:
|
|
let min_rounds_to_inf_rounded_up: f64 = 17976931348623158079372897140530341507993413271003782693617377898044496.9e238;
|
|
|
|
// CHECK:STDERR: fail_overflow_very_large_mantissa.carbon:[[@LINE+4]]:34: error: value 144115188075855864*2^967 too large for floating-point type `f64` [FloatLiteralTooLargeForType]
|
|
// CHECK:STDERR: let min_rounds_to_inf_hex: f64 = 0x1.FFFFFFFFFFFFF8p+1023;
|
|
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~
|
|
// CHECK:STDERR:
|
|
let min_rounds_to_inf_hex: f64 = 0x1.FFFFFFFFFFFFF8p+1023;
|
|
|
|
// --- fail_overflow_very_large_exponent.carbon
|
|
|
|
library "[[@TEST_NAME]]";
|
|
|
|
// CHECK:STDERR: fail_overflow_very_large_exponent.carbon:[[@LINE+4]]:14: error: value 50*10^39999999999999999992 too large for floating-point type `f64` [FloatLiteralTooLargeForType]
|
|
// CHECK:STDERR: let e: f64 = 5.0e39999999999999999993;
|
|
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~
|
|
// CHECK:STDERR:
|
|
let e: f64 = 5.0e39999999999999999993;
|
|
|
|
// CHECK:STDOUT: --- literal_values.carbon
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: constants {
|
|
// CHECK:STDOUT: %int_8.b85: Core.IntLiteral = int_value 8 [concrete]
|
|
// CHECK:STDOUT: %int_9.988: Core.IntLiteral = int_value 9 [concrete]
|
|
// CHECK:STDOUT: %int_2147483647.d89: Core.IntLiteral = int_value 2147483647 [concrete]
|
|
// CHECK:STDOUT: %float.b06: Core.FloatLiteral = float_literal_value 9e-1 [concrete]
|
|
// CHECK:STDOUT: %float.025: Core.FloatLiteral = float_literal_value 80e-1 [concrete]
|
|
// CHECK:STDOUT: %float.3b0: Core.FloatLiteral = float_literal_value 800e-1 [concrete]
|
|
// CHECK:STDOUT: %float.d22: Core.FloatLiteral = float_literal_value 10e6 [concrete]
|
|
// CHECK:STDOUT: %float.8d2: Core.FloatLiteral = float_literal_value 10e7 [concrete]
|
|
// CHECK:STDOUT: %float.48b: Core.FloatLiteral = float_literal_value 10e-9 [concrete]
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|
|
// CHECK:STDOUT: fn @F() {
|
|
// CHECK:STDOUT: !entry:
|
|
// CHECK:STDOUT: <elided>
|
|
// CHECK:STDOUT: %int_8.loc9: Core.IntLiteral = int_value 8 [concrete = constants.%int_8.b85]
|
|
// CHECK:STDOUT: %int_9: Core.IntLiteral = int_value 9 [concrete = constants.%int_9.988]
|
|
// CHECK:STDOUT: %int_8.loc11: Core.IntLiteral = int_value 8 [concrete = constants.%int_8.b85]
|
|
// CHECK:STDOUT: %int_8.loc12: Core.IntLiteral = int_value 8 [concrete = constants.%int_8.b85]
|
|
// CHECK:STDOUT: %int_2147483647.loc13: Core.IntLiteral = int_value 2147483647 [concrete = constants.%int_2147483647.d89]
|
|
// CHECK:STDOUT: %int_2147483647.loc14: Core.IntLiteral = int_value 2147483647 [concrete = constants.%int_2147483647.d89]
|
|
// CHECK:STDOUT: <elided>
|
|
// CHECK:STDOUT: %float.loc19: Core.FloatLiteral = float_literal_value 9e-1 [concrete = constants.%float.b06]
|
|
// CHECK:STDOUT: %float.loc20: Core.FloatLiteral = float_literal_value 80e-1 [concrete = constants.%float.025]
|
|
// CHECK:STDOUT: %float.loc21: Core.FloatLiteral = float_literal_value 800e-1 [concrete = constants.%float.3b0]
|
|
// CHECK:STDOUT: %float.loc22: Core.FloatLiteral = float_literal_value 10e6 [concrete = constants.%float.d22]
|
|
// CHECK:STDOUT: %float.loc23: Core.FloatLiteral = float_literal_value 10e7 [concrete = constants.%float.8d2]
|
|
// CHECK:STDOUT: %float.loc24: Core.FloatLiteral = float_literal_value 10e-9 [concrete = constants.%float.48b]
|
|
// CHECK:STDOUT: <elided>
|
|
// CHECK:STDOUT: }
|
|
// CHECK:STDOUT:
|