This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.

Index Nav: Message Nav: [Date Index] [Subject Index] [Author Index] [Thread Index] [Date Prev] [Date Next] [Thread Prev] [Thread Next] [Raw text]

# Re: Signed division with rounding towards -infinity (and floating point rounding)

• From: Jim Wilson <wilson at specifix dot com>
• To: Christopher Key <cjk32 at cam dot ac dot uk>
• Cc: "gcc at gcc dot gnu dot org" <gcc at gcc dot gnu dot org>
• Date: Wed, 19 Sep 2007 18:21:11 -0700
• Subject: Re: Signed division with rounding towards -infinity (and floating point rounding)
• References: <46EFC6FC.1050808@cam.ac.uk>

Christopher Key wrote:
```The most concise form that I've found so far is:
const int d = 8; // 16, 32 etc
x = y / d - ((y % d < 0) ? 1 : 0)
although this still produces rather longer code (see example below).
```

Any integer divide by constant can be replaced by a sequence of multiply, shift, and add instructions that produces the same result for all inputs. There is a proof in a paper by Peter Montgomery and Torbjorn Granlund. Because integer divide instructions are slow on most hardware, this is often a profitable optimization. The same is true for the modulo operation. So what you are seeing here are two sequences of instructions to compute divide/modulo results using multiply/shift/add.

Gcc is not able to simplify the two sequences further. We would have to add code to recognize this sequence and handle it specially, and that isn't what you are asking for.

```On a similar point, is there a good way get floats rounded to the
nearest integer value rather than truncated.  The following give the
correct rounding behaviour (I'm only interested in +ve values),
x = (int) (f + 0.5)
although gets compiled as an addition of 0.5 followed by a truncation
(again, see example).
```

Gcc has some builtin support for the lrint library function, however, only x86 supports this, and you have to use -ffast-math to get this optimization.

```On an x86_64-linux system, compiling this testcase
long int lrint (double d);
long int sub (double d) { return lrint (d); }
with -O2 -ffast-math -S gives me
sub:
cvtsd2siq       %xmm0, %rax
ret
--
Jim Wilson, GNU Tools Support, http://www.specifix.com```

Index Nav: Message Nav: [Date Index] [Subject Index] [Author Index] [Thread Index] [Date Prev] [Date Next] [Thread Prev] [Thread Next]