Skip to content

WRONG: Missing strength reduction for `rem 2`

Please disregard, that is actually wrong for signed integers. I mixed up remainder and modulus - the current implementation correctly returns negative remainders for negative dividends and positive divisors.

Motivation

I saw a tweet referring to this blog post on how Clang/LLVM can optimize a silly "isEven" implementation. Another user posted a screenshot showing that rustc can compile this down to 3 instructions.

GHC can't seem to do that, but I was more surprised that it emits the full division etc code for the straight forward "isEven" implementation: isEven n = n rem2 == 0. It emits shifts and adds and subs etc, even though you'd only need to test the least significant bit.

Here is the example with emitted assembly: https://gcc.godbolt.org/z/7MnrMhfrf

Proposal

Add a special case to GHC/Cmm/Opt.hs for MO_S_Rem with divisor being exactly 2.

Edited by Benjamin Maurer
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information