Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.compilers > #2204 > unrolled thread

Re: Optimization techniques

Started byMartin Ward <martin@gkc.org.uk>
First post2019-04-25 16:46 +0100
Last post2019-04-30 15:01 +0200
Articles 13 — 9 participants

Back to article view | Back to comp.compilers

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: Optimization techniques Martin Ward <martin@gkc.org.uk> - 2019-04-25 16:46 +0100
    Re: Optimization techniques Kaz Kylheku <847-115-0292@kylheku.com> - 2019-04-25 23:01 +0000
    Re: Optimization techniques alexfrunews@gmail.com - 2019-04-26 01:33 -0700
      Re: language design and Optimization techniques Martin Ward <martin@gkc.org.uk> - 2019-04-27 11:56 +0100
      Re: Optimization techniques 0xe2.0x9a.0x9b@gmail.com - 2019-04-27 04:56 -0700
        Re: C language andOptimization techniques alexfrunews@gmail.com - 2019-04-27 19:47 -0700
      Re: reliability features and Optimization techniques Bart <bc@freeuk.com> - 2019-04-28 11:58 +0100
        Re: reliability features and Optimization techniques Jan Ziak <0xe2.0x9a.0x9b@gmail.com> - 2019-04-29 04:33 -0700
      Re: Optimization techniques Gene Wirchenko <genew@telus.net> - 2019-04-30 18:11 -0700
      Re: Optimization techniques David Brown <david.brown@hesbynett.no> - 2019-05-07 16:43 +0200
    Re: Optimization techniques Hans Aberg <haberg-news@telia.com> - 2019-04-27 23:01 +0200
      Re: Optimization techniques, C++ numeric representations David Brown <david.brown@hesbynett.no> - 2019-04-29 17:24 +0200
        Re: Optimization techniques, C++ numeric representations Hans Aberg <haberg-news@telia.com> - 2019-04-30 15:01 +0200

#2204 — Re: Optimization techniques

FromMartin Ward <martin@gkc.org.uk>
Date2019-04-25 16:46 +0100
SubjectRe: Optimization techniques
Message-ID<19-04-020@comp.compilers>
David Brown <david.brown@hesbynett.no> wrote:
> And there are undefined behaviours which could be given definitions, but
> doing so is not actually a positive thing.  The prime example is signed
> integer overflow.  Since overflowing your integers is almost always an
> error in the code anyway, there are no benefits in giving it defined
> behaviour.

This is completely backwards. If signed overflow was given a defined
behaviour (such as the two's complement result), then compilers for
CPUs which do not implement two's complement operations would have to
generate less efficient code (but does anyone still make such a CPU?).
Any program which guarantees not to overflow would be unaffected. Any
program which expects a two's complement result could now be relied
upon to work correctly, and not suddenly produce random results when
the next version of the compuler comes out!  Any program which
expected a different result (one's complement anyone?)  would need
additional code.

With the current situation, anyone wanting to avoid
undefined behaviour (and don't we all?) has to write code like
this for any signed operation:

signed int sum;
if (((si_b > 0) && (si_a > (INT_MAX - si_b))) ||
     ((si_b < 0) && (si_a < (INT_MIN - si_b)))) {
   /* Handle error */
} else {
   sum = si_a + si_b;
}

See:

https://wiki.sei.cmu.edu/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow

>  But mathematical identities such as associativity and commutativity are
> valid because signed integer overflow does not happen - thus "a * (b +
> c)" can be changed to "(a * b) + (a * c)".

The following slide set discusses some of the problems with undefined
behaviour starting on slide 43:

http://www0.cs.ucl.ac.uk/staff/B.Karp/3007/s2018/lectures/3007-lecture5-C-arith-undef-behav.pdf

Examples of problems include privilege elevation exploits and denial
of service attacks.

There was a discussion about undefined behaviour on this list in
March/April last year. Some examples:

https://blog.regehr.org/archives/213
https://blog.regehr.org/archives/759

Gcc may optimize out tests for buffer overflows because of integer
overflows:

https://lwn.net/Articles/278137/

--
			Martin

Dr Martin Ward | Email: martin@gkc.org.uk | http://www.gkc.org.uk
G.K.Chesterton site: http://www.gkc.org.uk/gkc | Erdos number: 4
[I don't think there are any ones complement machines left but there are certainly
machines with different word sizes. -John]

[toc] | [next] | [standalone]


#2206

FromKaz Kylheku <847-115-0292@kylheku.com>
Date2019-04-25 23:01 +0000
Message-ID<19-04-022@comp.compilers>
In reply to#2204
On 2019-04-25, Martin Ward <martin@gkc.org.uk> wrote:
> David Brown <david.brown@hesbynett.no> wrote:
>> And there are undefined behaviours which could be given definitions, but
>> doing so is not actually a positive thing.  The prime example is signed
>> integer overflow.  Since overflowing your integers is almost always an
>> error in the code anyway, there are no benefits in giving it defined
>> behaviour.
>
> This is completely backwards. If signed overflow was given a defined
> behaviour (such as the two's complement result), then compilers for
> CPUs which do not implement two's complement operations would have to
> generate less efficient code (but does anyone still make such a CPU?).
> Any program which guarantees not to overflow would be unaffected. Any
> program which expects a two's complement result could now be relied
> upon to work correctly, and not suddenly produce random results when
> the next version of the compuler comes out!  Any program which
> expected a different result (one's complement anyone?)  would need
> additional code.
>
> With the current situation, anyone wanting to avoid
> undefined behaviour (and don't we all?) has to write code like
> this for any signed operation:
>
> signed int sum;
> if (((si_b > 0) && (si_a > (INT_MAX - si_b))) ||
>      ((si_b < 0) && (si_a < (INT_MIN - si_b)))) {
>    /* Handle error */
> } else {
>    sum = si_a + si_b;
> }

Problem is that even though we have made the overflowing addition
defined behavior, it's often not the right behavior for the program,
which really wanted the arithmetic sum that doesn't fit into the type.

We still need to defend against this situation, and so need a glob of
code.

However, that code becomes a little bit simpler and more elegant: gone
are the INT_MAX and INT_MIN constants, and calculations:

  int sum = si_a + si_b;

  if ((si_a > 0 && si_b > 0 && sum < 0) ||
      (si_a < 0 && si_b < 0 && sum > 0))
      /* Handle error */

Overflow happens when the operands have the same sign, which is opposite
to the result's sign. We can test for that with bit ops:

  if (((si_a ^ s_b) & SIGN_BIT_MASK) == 0) &&
      ((si_a ^ sum) & SIGN_BIT_MASK) != 0))
      /* Handle error */

--
TXR Programming Lanuage: http://nongnu.org/txr
Music DIY Mailing List:  http://www.kylheku.com/diy
ADA MP-1 Mailing List:   http://www.kylheku.com/mp1

[toc] | [prev] | [next] | [standalone]


#2209

Fromalexfrunews@gmail.com
Date2019-04-26 01:33 -0700
Message-ID<19-04-025@comp.compilers>
In reply to#2204
On Thursday, April 25, 2019 at 1:14:54 PM UTC-7, Martin Ward wrote:
...
> With the current situation, anyone wanting to avoid
> undefined behaviour (and don't we all?) has to write code like
> this for any signed operation:
>
> signed int sum;
> if (((si_b > 0) && (si_a > (INT_MAX - si_b))) ||
>      ((si_b < 0) && (si_a < (INT_MIN - si_b)))) {
>    /* Handle error */
> } else {
>    sum = si_a + si_b;
> }

In this day and age it is a shame that the language that is still very
much alive does not provide the programmer with easy-to-use (and
implement!) tools to perform/handle:

- overflow checks like the above for +, -, *, /,
  %, <<, both signed and unsigned
- mathematically meaningful comparison of signed
  and unsigned integers
- arithmetic right shift out of the box
- ditto rotation
- arbitrary precision arithmetic (for integers
  of compile-time-constant length)
- endianness at last
- (I probably forget many more)

Often times the desired functionality is already in the CPU or needs
just a few more instructions but there's no simple, short and standard
way to tell the compiler to generate the code for the common problem.
It's always compiler extensions (or dependencies on specific
compilers), #ifdefs, inline (and non-inline) assembly, code like shown
above, reinvented wheels all the way, over and over again, from
project to project.  I understand that C is minimalistic, but I think
it needs to step up a bit.

When I'm handling arbitrary, potentially maliciously crafted data, I
want to have those overflow checks, but I don't want to be burdened
with what the compiler can easily do for me but fails to deliver year
after year just because it's not in the language.

What may have been deemed sufficient back in the 80's is no more.
Because the Internet.  Deprecating gets() is nice but doesn't quite
cut it.

Alex
P.S. this should've probably gone to some C group.

[toc] | [prev] | [next] | [standalone]


#2215 — Re: language design and Optimization techniques

FromMartin Ward <martin@gkc.org.uk>
Date2019-04-27 11:56 +0100
SubjectRe: language design and Optimization techniques
Message-ID<19-04-031@comp.compilers>
In reply to#2209
On 26/04/19 09:33, alexfrunews@gmail.com wrote:
> In this day and age it is a shame that the language that is still very
> much alive does not provide the programmer with easy-to-use (and
> implement!) tools to perform/handle:
 > ...
 > Often times the desired functionality is already in the CPU

I agree 100%. My guess is that manufacturers of CPUs which
did *not* have a certain feature lobbied to have the feature
removed from the language. The resulting compromise
is a minimal intersection of features with 199 cases
of undefined behaviour when agreement cannot be made.

For a language which is supposed to give access to the "bare metal",
C provides very little.

We should be designing languages for people to use and then designing
CPUs which can efficiently compile and execute these languages.

I have quoted this before, but it bears repeating:

"We shall do a much better programming job, provided that we approach
the task with a full appreciation of its tremendous difficulty,
provided that we stick to modest and elegant programming languages,
provided that we respect the intrinsic limitations of the human mind
and approach the task as Very Humble Programmers."
-- E.W.Dijkstra, ACM Turing Lecture 1972, "The Humble Programmer"

> P.S. this should've probably gone to some C group.

I think that C is beyond hope and therefore this is definitely
the most appropriate group!

--
			Martin

Dr Martin Ward | Email: martin@gkc.org.uk | http://www.gkc.org.uk
G.K.Chesterton site: http://www.gkc.org.uk/gkc | Erdos number: 4
[C is close to the bare metal if the metal is a PDP-11 or maybe a GE 635.
Other than that, it's an abstract machine of, as we have seen, highly
debatable similarity to the underlying hardware. -John]

[toc] | [prev] | [next] | [standalone]


#2216

From0xe2.0x9a.0x9b@gmail.com
Date2019-04-27 04:56 -0700
Message-ID<19-04-032@comp.compilers>
In reply to#2209
On Friday, April 26, 2019 at 9:11:46 PM UTC+2, alexf...@gmail.com wrote:
> In this day and age it is a shame that the language [C] that is still very
> much alive does not provide the programmer with easy-to-use (and
> implement!) tools to perform/handle:
>
> - overflow checks like the above for +, -, *, /,
>   %, <<, both signed and unsigned
> - mathematically meaningful comparison of signed
>   and unsigned integers
> - arithmetic right shift out of the box
> - ditto rotation
> - arbitrary precision arithmetic (for integers
>   of compile-time-constant length)
> - endianness at last
> - (I probably forget many more)

Hi. In my opinion, the C extensions you are requesting would just turn C into
C++ which allows the programmer to create a new class/struct and overload the
arithmetic operators.

> Often times the desired functionality is already in the CPU

With a Turing-complete CPU, any desired functionality is already in the CPU.

The only distinctions between Turing-complete CPUs are: performance, distance
to solutions (aka programming convenience).

> or needs
> just a few more instructions but there's no simple, short and standard
> way to tell the compiler to generate the code for the common problem.
> It's always compiler extensions (or dependencies on specific
> compilers), #ifdefs, inline (and non-inline) assembly, code like shown
> above, reinvented wheels all the way, over and over again, from
> project to project.  I understand that C is minimalistic, but I think
> it needs to step up a bit.
>
> When I'm handling arbitrary, potentially maliciously crafted data, I
> want to have those overflow checks, but I don't want to be burdened
> with what the compiler can easily do for me but fails to deliver year
> after year just because it's not in the language.
>
> What may have been deemed sufficient back in the 80's is no more.
> Because the Internet.  Deprecating gets() is nice but doesn't quite
> cut it.
>
> Alex

I don't fully understand. Are you suggesting to add buffer overflow checks to
the C language? When developing a C compiler, clearly it *is* possible to
transparently add those checks to C when the compilation target is something
like a virtual machine, the compiler&runtime just need to know which functions
are allocating and freeing memory.

Performance of the code generated by the compiler you seem to be requesting
depends on the choice of the physical representation of C pointers. The C
compiler can generate code performing buffer overflow checks even if pointer
size is unchanged from the traditional 4 or 8 bytes.

When calling assembly code from C, the C compiler can run the assembly code in
a virtual machine and thus can perform safety checks in a lot of cases. This
is clearly possible to implement, and the only factor here is performance.

Summary: If sacrificing performance is OK, it is possible to transparently
implement any imaginable kind of a safety measure.

Sincerely
Jan

[toc] | [prev] | [next] | [standalone]


#2218 — Re: C language andOptimization techniques

Fromalexfrunews@gmail.com
Date2019-04-27 19:47 -0700
SubjectRe: C language andOptimization techniques
Message-ID<19-04-034@comp.compilers>
In reply to#2216
On Saturday, April 27, 2019 at 7:19:34 AM UTC-7, Jan Ziak wrote:
> On Friday, April 26, 2019 at 9:11:46 PM UTC+2, alexf...@gmail.com wrote:
> > In this day and age it is a shame that the language [C] that is still very
> > much alive does not provide the programmer with easy-to-use (and
> > implement!) tools to perform/handle:
> >
> > - overflow checks like the above for +, -, *, /,
> >   %, <<, both signed and unsigned
> > - mathematically meaningful comparison of signed
> >   and unsigned integers
> > - arithmetic right shift out of the box
> > - ditto rotation
> > - arbitrary precision arithmetic (for integers
> >   of compile-time-constant length)
> > - endianness at last
> > - (I probably forget many more)
>
> Hi. In my opinion, the C extensions you are requesting would just turn C into
> C++ which allows the programmer to create a new class/struct and overload the
> arithmetic operators.

I did not say or mean that. One big thing I dislike about C++ is that
it's not just a bigger language, it's much more complex, with lots of
implicit things and many more things interacting with or affecting one
another. I would not advocate for having more of that in C.

The things that I mentioned above are conceptually simple (often
trivial), not changing the nature of the language, just giving it a
few more tools for solving common problems, tools that people need to
reinvent since they aren't part of the library or core language.  Just
like the trunc() and round() functions that were included in C99 for
the first time.  Simple things that don't need to be reinvented
needlessly, things that can possibly be implemented with bugs every
time. I'm mostly talking about this kind of language extension.
Conceptually simple things done right and available out of the box.

> > Often times the desired functionality is already in the CPU
>
> With a Turing-complete CPU, any desired functionality is already in the CPU.
>
> The only distinctions between Turing-complete CPUs are: performance, distance
> to solutions (aka programming convenience).

You can call it convenience. It doesn't make it useless or
undesirable. It can cut costs (think of security costs as well, not
just the ability to churn out code more quickly simply because the
language/library is rich).

> > or needs
> > just a few more instructions but there's no simple, short and standard
> > way to tell the compiler to generate the code for the common problem.
> > It's always compiler extensions (or dependencies on specific
> > compilers), #ifdefs, inline (and non-inline) assembly, code like shown
> > above, reinvented wheels all the way, over and over again, from
> > project to project.  I understand that C is minimalistic, but I think
> > it needs to step up a bit.
> >
> > When I'm handling arbitrary, potentially maliciously crafted data, I
> > want to have those overflow checks, but I don't want to be burdened
> > with what the compiler can easily do for me but fails to deliver year
> > after year just because it's not in the language.
> >
> > What may have been deemed sufficient back in the 80's is no more.
> > Because the Internet.  Deprecating gets() is nice but doesn't quite
> > cut it.
> >
> > Alex
>
> I don't fully understand. Are you suggesting to add buffer overflow checks to
> the C language?

No. However, I think the language could provide a designated
tuple-like type containing a pointer and a count/size and maybe some
functions/macros to check the range. Or something like that. But...

What I primarily had in mind was things like complex data structures
of variable size, which contain counts/ sizes, indices and such.
Consider your favorite multimedia file formats or file systems. Proper
parsing includes checking of those, including for overflows.

I have seen some file system and driver code written in C. I've seen
some bad code that desperately lacked those checks, had them wrong or
insufficient.

I'd want the language to help me perform these important checks. But
it doesn't. The language forces me to manually write the
functions/macros (or inline code) to perform these checks for all
relevant types.  You get undefined behavior for free for all types
alright.  Most CPUs provide defined overflow control for multiple
types and ALU operations, but you can't get it because there's no way
to express it in the language.  It is an insult to the programmer.

Just because K&R never checked for overflows or did it by hand,
doesn't mean we should keep the tradition 30+ years later. The
language and compilers can do it for us.  Mundane stuff like this
should be done by machines, not people (hello to C++'s "one definition
rule", which must have been checked by the compiler too, but no, in
projects of many thousands lines of code it's humans to somehow keep
track of improper redefinitions that cause undefined behavior, how
sane is that?).

Alex

[toc] | [prev] | [next] | [standalone]


#2219 — Re: reliability features and Optimization techniques

FromBart <bc@freeuk.com>
Date2019-04-28 11:58 +0100
SubjectRe: reliability features and Optimization techniques
Message-ID<19-04-035@comp.compilers>
In reply to#2209
On 26/04/2019 09:33, alexfrunews@gmail.com wrote:
> On Thursday, April 25, 2019 at 1:14:54 PM UTC-7, Martin Ward wrote:
> ...
>> With the current situation, anyone wanting to avoid
>> undefined behaviour (and don't we all?) has to write code like
>> this for any signed operation:
>>
>> signed int sum;
>> if (((si_b > 0) && (si_a > (INT_MAX - si_b))) ||
>>       ((si_b < 0) && (si_a < (INT_MIN - si_b)))) {
>>     /* Handle error */
>> } else {
>>     sum = si_a + si_b;
>> }
>
> In this day and age it is a shame that the language that is still very
> much alive does not provide the programmer with easy-to-use (and
> implement!) tools to perform/handle:
>
> - overflow checks like the above for +, -, *, /,
>    %, <<, both signed and unsigned
> - mathematically meaningful comparison of signed
>    and unsigned integers
> - arithmetic right shift out of the box
> - ditto rotation
> - arbitrary precision arithmetic (for integers
>    of compile-time-constant length)
> - endianness at last
> - (I probably forget many more)

I've drawn up my own lists of things that I think ought to be in a
language like C, many dozens of them. But I realise they are never going
to be in C itself, whose design is pretty much frozen. (I'm implemented
most on my own projects.)

They don't however include any of the things you've listed. Like,
overflow checks: what would be the purpose, and what could a program do
if overflow is detected at runtime?

Not sure what you mean by the next two items. As for rotation (I assume
bit-rotation of int types); I had such operators many years ago, but
never used them.

Arbitrary precision - even if limited to a pre-set length - I feel
doesn't belong at this level of language. A C-like language can be used
to /implement/ such arithmetic elsewhere; it doesn't need it itself!

It would also demand other things that are not in the language. Remember
that C itself is barely capable of defining basic integer types, or of
printing them out:

Is int64 written as 'long int', 'long long int' or 'int64_t'? You might
find that 'int64_t' is an alias for one of the former, but which one? To
print an int64_t type might require a "%ld" format, or a "%lld" one, and
in practice means using PRId64. What macro gives int64's maximum value?
There will be several. And all this requiring various assorted headers.

If anything, C could do with tightening up and removing or restricting
features, rather than adding more.


Jan Ziak wrote:
 >> I don't fully understand. Are you suggesting to add buffer overflow
checks to
 >> the C language?
 >
 > No. However, I think the language could provide a designated
 > tuple-like type containing a pointer and a count/size and maybe some
 > functions/macros to check the range. Or something like that. But...

Yes, that's a feature I call a slice, which is a pointer and length.
That would be quite useful, except that typical C doesn't even use
arrays properly:

Instead of a function parameter being of type T(*)[] (pointer to array
of T), usually it is just T* (pointer to its element type). The array is
implied, which means it is possible to pass a pointer to anything: a
single T value; 2 successive T members of a struct. Or even just the
middle of an array.

It is undisciplined, with the 'length' of the implied array of such a
pointer being badly defined. (It can't even be the bounds of an
allocated memory block, because that can be bigger than the array.)

So C is pretty much a lost cause.

 > Mundane stuff like this
 > should be done by machines, not people (hello to C++'s "one definition
 > rule", which must have been checked by the compiler too, but no, in
 > projects of many thousands lines of code it's humans to somehow keep
 > track of improper redefinitions that cause undefined behavior, how
 > sane is that?).

You mean having to have multiple definitions/declarations of variables
and functions that are shared across modules? I always found it crazy
that you can just write 'int a,a,a,a,a,a,a,a;' and the compiler says
nothing, but that is apparently necessary to make C's approach possible:

    int a;     # in a shared header included by this module
    int a;     # in the main module

Fixing that however would be a massive job (it really needs proper
modules) and would be ineffective, since the language must be backwards
compatible, so the old stuff is still there, and everyone will keep
using that. You've just made the language even more of a mess.

The solution would be to start again with something that does need to be
compatible, but which will create its own problems (it needs to interact
with billions of lines of existing C programs).

(Plenty of new languages like that but they tend to be heavyweight, and
have their own issues.)

[toc] | [prev] | [next] | [standalone]


#2224 — Re: reliability features and Optimization techniques

FromJan Ziak <0xe2.0x9a.0x9b@gmail.com>
Date2019-04-29 04:33 -0700
SubjectRe: reliability features and Optimization techniques
Message-ID<19-04-040@comp.compilers>
In reply to#2219
On Monday, April 29, 2019 at 12:31:16 AM UTC+2, Bart wrote:
> On 26/04/2019 09:33, alexfrunews@gmail.com wrote:
> Jan Ziak wrote:
>  >> I don't fully understand. Are you suggesting to add buffer overflow
> checks to
>  >> the C language?
>  >
>  > No. However, I think the language could provide a designated
>  > tuple-like type containing a pointer and a count/size and maybe some
>  > functions/macros to check the range. Or something like that. But...
>
> Yes, that's a feature I call a slice, which is a pointer and length.
> That would be quite useful, except that typical C doesn't even use
> arrays properly:
>
> Instead of a function parameter being of type T(*)[] (pointer to array
> of T), usually it is just T* (pointer to its element type). The array is
> implied, which means it is possible to pass a pointer to anything: a
> single T value; 2 successive T members of a struct. Or even just the
> middle of an array.
>
> It is undisciplined, with the 'length' of the implied array of such a
> pointer being badly defined. (It can't even be the bounds of an
> allocated memory block, because that can be bigger than the array.)
>
> So C is pretty much a lost cause.

You don't necessarily need to introduce slices to C in order to enable the
safety checks (slice-like safety checks). By sacrificing a bit of runtime
performance and slightly increasing memory consumption, the generated assembly
code can perform the checks even if the pointer size remains to be 8 bytes (or
4 bytes in case of a 32-bit address space).

Sincerely
Jan

[toc] | [prev] | [next] | [standalone]


#2235

FromGene Wirchenko <genew@telus.net>
Date2019-04-30 18:11 -0700
Message-ID<19-04-051@comp.compilers>
In reply to#2209
On Fri, 26 Apr 2019 01:33:48 -0700 (PDT), alexfrunews@gmail.com wrote:

[snip]

>P.S. this should've probably gone to some C group.

     No.  I think that covering it here is good idea.  The people here
can knowledgeably discuss the ins and outs of implementing various
ideas.  End users tend more to take what they get.

Sincerely,

Gene Wirchenko

[toc] | [prev] | [next] | [standalone]


#2289

FromDavid Brown <david.brown@hesbynett.no>
Date2019-05-07 16:43 +0200
Message-ID<19-05-054@comp.compilers>
In reply to#2209
On 26/04/2019 10:33, alexfrunews@gmail.com wrote:
> On Thursday, April 25, 2019 at 1:14:54 PM UTC-7, Martin Ward wrote:
> ...
>> With the current situation, anyone wanting to avoid
>> undefined behaviour (and don't we all?) has to write code like
>> this for any signed operation:
>>
>> signed int sum;
>> if (((si_b > 0) && (si_a > (INT_MAX - si_b))) ||
>>      ((si_b < 0) && (si_a < (INT_MIN - si_b)))) {
>>    /* Handle error */
>> } else {
>>    sum = si_a + si_b;
>> }
>
> In this day and age it is a shame that the language that is still very
> much alive does not provide the programmer with easy-to-use (and
> implement!) tools to perform/handle:
>
> - overflow checks like the above for +, -, *, /,
>   %, <<, both signed and unsigned
> - mathematically meaningful comparison of signed
>   and unsigned integers
> - arithmetic right shift out of the box
> - ditto rotation
> - arbitrary precision arithmetic (for integers
>   of compile-time-constant length)
> - endianness at last
> - (I probably forget many more)
>

One possible consideration here is that C, these days, regularly means
gcc and/or clang.  These dominate the C compiler market to a very large
extent.  And they both have support for overflow checks (and wrapping
signed arithmetic, if you want).  Some other compilers I have used have
copied extensions from gcc.

Still, a major point of C is that it does not change much - it is
intentionally kept (relatively) small and as stable as possible.

[toc] | [prev] | [next] | [standalone]


#2217

FromHans Aberg <haberg-news@telia.com>
Date2019-04-27 23:01 +0200
Message-ID<19-04-033@comp.compilers>
In reply to#2204
On 2019-04-25 17:46, Martin Ward wrote:
> If signed overflow was given a defined
> behaviour (such as the two's complement result), then compilers for
> CPUs which do not implement two's complement operations would have to
> generate less efficient code (but does anyone still make such a CPU?).

All C++ compilers use two's complement, and as of C++20, that is
required, cf. [1], "Range of values". It is required for int32_t etc in
C++11 [2] and C99 [3].

1. https://en.cppreference.com/w/cpp/language/types
2. https://en.cppreference.com/w/cpp/types/integer
3. https://en.cppreference.com/w/c/types/integer
[I realize that if you look very hard, you can still find a few legacy
machines that are not pure two's complement and do not have 8-bit byte
addressing.  But these days, so what. -John]

[toc] | [prev] | [next] | [standalone]


#2227 — Re: Optimization techniques, C++ numeric representations

FromDavid Brown <david.brown@hesbynett.no>
Date2019-04-29 17:24 +0200
SubjectRe: Optimization techniques, C++ numeric representations
Message-ID<19-04-043@comp.compilers>
In reply to#2217
On 27/04/2019 23:01, Hans Aberg wrote:
> On 2019-04-25 17:46, Martin Ward wrote:
>> If signed overflow was given a defined
>> behaviour (such as the two's complement result), then compilers for
>> CPUs which do not implement two's complement operations would have to
>> generate less efficient code (but does anyone still make such a CPU?).
>
> All C++ compilers use two's complement, and as of C++20, that is
> required, cf. [1], "Range of values". It is required for int32_t etc in
> C++11 [2] and C99 [3].
>
> 1. https://en.cppreference.com/w/cpp/language/types
> 2. https://en.cppreference.com/w/cpp/types/integer
> 3. https://en.cppreference.com/w/c/types/integer
> [I realize that if you look very hard, you can still find a few legacy
> machines that are not pure two's complement and do not have 8-bit byte
> addressing.  But these days, so what. -John]

Note, however, that this applies only to the representation of the
types.  C++20 will /not/ require two's complement wrapping on signed
integer overflow - this will remain undefined behaviour.  (And, as
always, compilers are free to define it if they want.)

[toc] | [prev] | [next] | [standalone]


#2232 — Re: Optimization techniques, C++ numeric representations

FromHans Aberg <haberg-news@telia.com>
Date2019-04-30 15:01 +0200
SubjectRe: Optimization techniques, C++ numeric representations
Message-ID<19-04-048@comp.compilers>
In reply to#2227
On 2019-04-29 17:24, David Brown wrote:
> On 27/04/2019 23:01, Hans Aberg wrote:
>> On 2019-04-25 17:46, Martin Ward wrote:
>>> If signed overflow was given a defined
>>> behaviour (such as the two's complement result), then compilers for
>>> CPUs which do not implement two's complement operations would have to
>>> generate less efficient code (but does anyone still make such a CPU?).
>>
>> All C++ compilers use two's complement, and as of C++20, that is
>> required, cf. [1], "Range of values". It is required for int32_t etc in
>> C++11 [2] and C99 [3].
>>
>> 1. https://en.cppreference.com/w/cpp/language/types
>> 2. https://en.cppreference.com/w/cpp/types/integer
>> 3. https://en.cppreference.com/w/c/types/integer
>> [I realize that if you look very hard, you can still find a few legacy
>> machines that are not pure two's complement and do not have 8-bit byte
>> addressing.  But these days, so what. -John]
>
> Note, however, that this applies only to the representation of the
> types.  C++20 will /not/ require two's complement wrapping on signed
> integer overflow - this will remain undefined behaviour.  (And, as
> always, compilers are free to define it if they want.)

For that, one will have to use the unsigned types. It is required in
Java, though, which does not have the unsigned type. So the question is
why UB is kept in C/C++. There is a list of languages here:
   https://en.wikipedia.org/wiki/Integer_overflow

[toc] | [prev] | [standalone]


Back to top | Article view | comp.compilers


csiph-web