this post was submitted on 23 Aug 2023
9 points (100.0% liked)

C++

1783 readers
1 users here now

The center for all discussion and news regarding C++.

Rules

founded 1 year ago
MODERATORS
 

Assume you have following C++ snippet:

// i, j, n are of type size_t
// we assume that i, j and n are not optimized away
if((n > 0) && (j < n))
{
  size_t a = i * n +j;
  size_t p = a / n;
  size_t q = a % n;
  // now do something with p and q
  // a is never used afterwards
}

clang 16 and gcc 13.2 with -O2 and -O3 will produce assembly code that computes a exactly as written above and then performs an integer division.

Here's the thing though, it's completely pointless. Ideally the compiler should be able to understand that inside that if block, p and q are respectively always going to be equal to i and j without the need to even compute a or do an integer division. So ideally, the compiler should optimize away a and simply put p = i and q = j.

However, the compiler is not optimizing those away. So maybe it is being careful because i * n +j may overflow? In that case, how would one indicate to the compiler that that won't be a problem?

(the above code is obviously not written by hand in practice, I'd get that very often after inlining functions that manipulate matrix indices and it just frustrates me to see the compiler not understanding that lots pf arithmetic can be avoided)

top 2 comments
sorted by: hot top controversial new old
[โ€“] [email protected] 2 points 1 year ago* (last edited 1 year ago) (1 children)

Okay so far I got around this using clang's __builtin_assume to enforce that (i * n + j) % n is always j when j < n, and together with -O2 it works perfectly. I guess when C++23 is ready we could do the same using the [[assume(...)]] attribute.