diff options
author | Tomasz Konojacki <me@xenu.pl> | 2018-11-21 09:26:31 +0100 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2018-11-21 12:39:09 +0000 |
commit | ad9b9a4926e4b0d348c048937df69e382f7e6d27 (patch) | |
tree | c7b0cc925a06b868b7b1fbedfe79c8f85c652ac0 /pp_hot.c | |
parent | 9ba9a28aaea66bad2de041880a2c4210a911dda6 (diff) | |
download | perl-ad9b9a4926e4b0d348c048937df69e382f7e6d27.tar.gz |
optimize IV -> UV conversions
This commit replaces all instances of code that looks like this:
uv = (iv == IV_MIN) ? (UV)iv : (UV)(-iv)
with simpler and more optimal:
uv = -(UV)iv
While -iv indeed results in an undefined behaviour when iv == IV_MIN,
-(UV)iv is perfectly well defined and does the right thing.
C standard guarantees that the result of (UV)iv (for negative iv) is
equal to iv + UV_MAX + 1 (see 6.3.1.3, paragraph 2 in C11). It also
guarantees that the result of -uv is UV_MAX - uv + 1 (6.2.5,
paragraph 9).
That means that the result of -(UV)iv is UV_MAX - (iv + UV_MAX + 1) + 1
which is equal to -iv for *all* possible negative values of iv.
[perl #133677]
Diffstat (limited to 'pp_hot.c')
-rw-r--r-- | pp_hot.c | 4 |
1 files changed, 2 insertions, 2 deletions
@@ -1521,7 +1521,7 @@ PP(pp_add) auv = aiv; auvok = 1; /* Now acting as a sign flag. */ } else { - auv = (aiv == IV_MIN) ? (UV)aiv : (UV)(-aiv); + auv = -(UV)aiv; } } a_valid = 1; @@ -1541,7 +1541,7 @@ PP(pp_add) buv = biv; buvok = 1; } else - buv = (biv == IV_MIN) ? (UV)biv : (UV)(-biv); + buv = -(UV)biv; } /* ?uvok if value is >= 0. basically, flagged as UV if it's +ve, else "IV" now, independent of how it came in. |