2

I'm writing the spectacular function:

void foo(void* a) {
    if (check_something_at_runtime_only()) {
        int* as_ints { a };
        // do things with as_ints
    }
    else {
        char* as_chars { a };
        // do things with as_chars
    }
}

Suppose we know that some work with as_ints would benefit from it being better-aligned; e.g. if the memory transaction size on my platform is N bytes, then I can read the first N/sizeof(int) elements with a single machine instruction (ignoring SIMD/vectorization here) - provided a is N-byte-aligned.

Now, I could indicate alignment by having foo always take an int * - at least on platforms for which larger types can only be read from aligned addresses - but I would rather keep the type void *, since it doesn't have to be an array of ints, really.

I would have liked to be able to write something like

void foo(alignas(sizeof(int)) void* a) { ... }

but, apparently, alignas doesn't apply to pointers, so I can't.

Is there another way to guarantee to the compiler than the argument address will be aligned?

Notes:

  • I'm interested both in what the C++ standard (any version) allows, and in compiler-specific extensions in GCC, clang and NVCC (the CUDA compiler).
einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • 5
    You seem to be putting the cart before the horses, it's the pointee that's aligned. You can't force the system to treat one address as aligned when it isn't. The only thing you can do is adjust the address. – StoryTeller - Unslander Monica Mar 27 '17 at 09:32
  • @StoryTeller: I'm not sure I understand what you mean. I want to tell the compiler "`a` can be `0x1004`, but it cannot be `0x1002` (for 4-byte-sized `int`'s). I know that, theoretically, you could call `foo(0x1002)` - but I want to promise the compiler this won't actually happen - similarly to what we have with `__restrict__`. – einpoklum Mar 27 '17 at 09:35
  • `__restrict__` is a whole different beast, and it has no baring on pointers that are used in isolation. If you know the alignment of the pointee is one thing or another, you can hint the optimizer about it with [__builtin_unreachable](http://stackoverflow.com/a/40447259/817643). The answer is about integer ranges, but I'm sure you can create a condition about alignment. – StoryTeller - Unslander Monica Mar 27 '17 at 09:56
  • This looks like a perfect candidate for templating. Then the whole problem more or less vanishes. And I agree with the first comment, this looks like a back-to-front view of the alignment question – talonmies Mar 27 '17 at 10:27
  • @talonmies: The thing is, sometime you can't template, e.g. if you're using code that's loaded dynamically from a library, or when the type you use can only be determined at run-time; see my edit. The question is only about indicating alignment, though, not about the `foo()` function. – einpoklum Mar 27 '17 at 10:45

2 Answers2

2

In C++20 you can use std::assume_aligned:

#include <memory>

int *as_ints = std::assume_aligned<sizeof(int)>(a);
HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
1

In GCC/Clang you can do

int *as_ints = __builtin_assume_aligned(a);

or if a is function parameter just mark it directly with __attribute((aligned(4))).

yugr
  • 19,769
  • 3
  • 51
  • 96