Alignment and -Wcast-align

727 views
Skip to first unread message

Richard W.M. Jones

unread,
Oct 21, 2016, 8:31:11 AM10/21/16
to sw-...@groups.riscv.org

I have a few related questions about alignment on RV64G, and the
GCC -Wcast-align warning. I am using:

gcc (GCC) 6.1.0 20160427 (Red Hat 6.1.0-1)

with the riscv-gcc patch.

(1) Is it correct that RV64G allows reads and writes of any size at
any byte alignment?

(2) The program align.c below provokes a -Wcast-align warning.
(Obviously the code is terrible and not even valid C99, it's just
designed to demonstrate the warning).

align.c:8:12: warning: cast increases required alignment of target type [-Wcast-align]
int *i = (int *) d;
^

Why does it print this warning if any alignment is permitted?

(3) When passing and returning pointers as syscall parameters to and
from the Linux kernel, are there any special alignment requirements?

Rich.

----------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>

int
main ()
{
char d[] = "abcd";
int *i = (int *) d;

printf ("i = %d\n", *i);
*i = 0;
printf ("i = %d\n", *i);
return 0;
}


--
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
Fedora Windows cross-compiler. Compile Windows programs, test, and
build Windows installers. Over 100 libraries supported.
http://fedoraproject.org/wiki/MinGW

Stefan O'Rear

unread,
Oct 21, 2016, 11:30:09 AM10/21/16
to Richard W.M. Jones, RISC-V SW Dev
On Fri, Oct 21, 2016 at 5:31 AM, Richard W.M. Jones <rjo...@redhat.com> wrote:
>
> I have a few related questions about alignment on RV64G, and the
> GCC -Wcast-align warning. I am using:
>
> gcc (GCC) 6.1.0 20160427 (Red Hat 6.1.0-1)
>
> with the riscv-gcc patch.
>
> (1) Is it correct that RV64G allows reads and writes of any size at
> any byte alignment?

Yes. ( https://content.riscv.org/wp-content/uploads/2016/06/riscv-spec-v2.1.pdf#page=28
)

> (2) The program align.c below provokes a -Wcast-align warning.
> (Obviously the code is terrible and not even valid C99, it's just
> designed to demonstrate the warning).
>
> align.c:8:12: warning: cast increases required alignment of target type [-Wcast-align]
> int *i = (int *) d;
> ^
>
> Why does it print this warning if any alignment is permitted?

Probably a gcc bug since it doesn't print the warning on x86, which
has the same rules.

> (3) When passing and returning pointers as syscall parameters to and
> from the Linux kernel, are there any special alignment requirements?

No. (Current systems handle misalignment traps in M-mode, so S-mode
and U-mode can both use misaligned addresses)

-s

Palmer Dabbelt

unread,
Oct 21, 2016, 2:08:54 PM10/21/16
to sor...@gmail.com, rjo...@redhat.com, sw-...@groups.riscv.org
On Fri, 21 Oct 2016 08:30:06 PDT (-0700), sor...@gmail.com wrote:
> On Fri, Oct 21, 2016 at 5:31 AM, Richard W.M. Jones <rjo...@redhat.com> wrote:
>>
>> I have a few related questions about alignment on RV64G, and the
>> GCC -Wcast-align warning. I am using:
>>
>> gcc (GCC) 6.1.0 20160427 (Red Hat 6.1.0-1)
>>
>> with the riscv-gcc patch.
>>
>> (1) Is it correct that RV64G allows reads and writes of any size at
>> any byte alignment?
>
> Yes. ( https://content.riscv.org/wp-content/uploads/2016/06/riscv-spec-v2.1.pdf#page=28
> )
>
>> (2) The program align.c below provokes a -Wcast-align warning.
>> (Obviously the code is terrible and not even valid C99, it's just
>> designed to demonstrate the warning).
>>
>> align.c:8:12: warning: cast increases required alignment of target type [-Wcast-align]
>> int *i = (int *) d;
>> ^
>>
>> Why does it print this warning if any alignment is permitted?
>
> Probably a gcc bug since it doesn't print the warning on x86, which
> has the same rules.

I'm hesitant to call this a bug: even though RISC-V allows unaligned memory
operations, on all the implementations I know about it's a bad idea from a
performance perspective and since this is just a warning I think it's sane.
Since this doesn't trigger on x86 I'd be OK changing the behavior, but I'd want
to make sure it doesn't have any ramifications first (and I'm pretty sure it
will). Looking at the GCC sources, it should be an easy fix: I believe
STRICT_ALIGNMENT is the port-specific flag that controls these kind of
warnings. We have

/* All accesses must be aligned. */
#define STRICT_ALIGNMENT 1

which is false according the spec, but I think a reasonable assumption given
the implementations that exist. x86 has

/* x86 doesn't require strict alignment for the basic types. */
#define STRICT_ALIGNMENT 0

so based on that x86 comment I think we would be safe removing the alignment
constraint, but I'd be super worried about the codegen going terrible if we
flipped that bit. The x86 port is complicated and I'm not sure what the
alignment restrictions on high-performance x86 code are, so I didn't look
further into it.

Note that TileGx, which had exactly the same alignment requirements RISC-V does
(Linux fixed unaligned accesses from userspace) just sets

#define STRICT_ALIGNMENT 1

without any comments, so I'm assuming this would result in bad code gen (the
alignment traps are really slow, so it doesn't take many unaligned accesses to
make this approach bad).

The 68k GCC port looks like it has support for changing the alignment as a GCC
option:

$ git grep STRICT_ALIGNMENT | grep m68k
gcc/ChangeLog-1999: * config/m68k/m68k.h (MASK_NO_STRICT_ALIGNMENT): New macro.
gcc/ChangeLog-2007: * config/m68k/m68k.h (M68K_HONOR_TARGET_STRICT_ALIGNMENT):
gcc/FSFChangeLog.10: * m68k/linux.h (STRICT_ALIGNMENT): Define to zero.
gcc/config/m68k/linux.h:#undef STRICT_ALIGNMENT
gcc/config/m68k/linux.h:#define STRICT_ALIGNMENT 0
gcc/config/m68k/linux.h:#undef M68K_HONOR_TARGET_STRICT_ALIGNMENT
gcc/config/m68k/linux.h:#define M68K_HONOR_TARGET_STRICT_ALIGNMENT 0
gcc/config/m68k/m68k.c:#if M68K_HONOR_TARGET_STRICT_ALIGNMENT
gcc/config/m68k/m68k.c:#if M68K_HONOR_TARGET_STRICT_ALIGNMENT
gcc/config/m68k/m68k.c: target_mask |= MASK_STRICT_ALIGNMENT;
gcc/config/m68k/m68k.c:#if M68K_HONOR_TARGET_STRICT_ALIGNMENT
gcc/config/m68k/m68k.h:#define STRICT_ALIGNMENT (TARGET_STRICT_ALIGNMENT)
gcc/config/m68k/m68k.h:#define M68K_HONOR_TARGET_STRICT_ALIGNMENT 1
gcc/config/m68k/m68k.opt:Target Report Mask(STRICT_ALIGNMENT)

I'd be OK taking a patch that implements this on RISC-V, but I'm not going to
write one until there's hardware that supports unaligned operations. This flag
will probably break the ABI, so it's probably not going to be well supported.

I'd tell you to open a github issue for further comments, but it looks like the
internet has completely melted down here :).

Richard W.M. Jones

unread,
Oct 21, 2016, 2:54:19 PM10/21/16
to Palmer Dabbelt, sor...@gmail.com, sw-...@groups.riscv.org
On Fri, Oct 21, 2016 at 11:08:51AM -0700, Palmer Dabbelt wrote:
> I'm hesitant to call this a bug: even though RISC-V allows unaligned memory
> operations, on all the implementations I know about it's a bad idea from a
> performance perspective and since this is just a warning I think it's sane.
> Since this doesn't trigger on x86 I'd be OK changing the behavior, but I'd want
> to make sure it doesn't have any ramifications first (and I'm pretty sure it
> will). Looking at the GCC sources, it should be an easy fix: I believe
> STRICT_ALIGNMENT is the port-specific flag that controls these kind of
> warnings. We have
>
> /* All accesses must be aligned. */
> #define STRICT_ALIGNMENT 1
>
> which is false according the spec, but I think a reasonable assumption given
> the implementations that exist. x86 has
>
> /* x86 doesn't require strict alignment for the basic types. */
> #define STRICT_ALIGNMENT 0
>
> so based on that x86 comment I think we would be safe removing the alignment
> constraint, but I'd be super worried about the codegen going terrible if we
> flipped that bit. The x86 port is complicated and I'm not sure what the
> alignment restrictions on high-performance x86 code are, so I didn't look
> further into it.

I'm actually happy with any approach you want to take. I simply
wanted to understand the problem, and now I have a convenient email
thread that I can point people to if (like the LVM2 maintainers) they
are worried about these warnings appearing in their code on RISC-V.

Thanks,

Rich.

--
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
virt-p2v converts physical machines to virtual machines. Boot with a
live CD or over the network (PXE) and turn machines into KVM guests.
http://libguestfs.org/virt-v2v

Palmer Dabbelt

unread,
Oct 21, 2016, 2:55:29 PM10/21/16
to rjo...@redhat.com, sor...@gmail.com, sw-...@groups.riscv.org
Great. It was certianly an interesting find.

Stefan O'Rear

unread,
Oct 22, 2016, 8:41:57 PM10/22/16
to Palmer Dabbelt, Richard W.M. Jones, RISC-V SW Dev
I found relevant documentation:

https://gcc.gnu.org/onlinedocs/gccint/Storage-Layout.html#index-STRICT_005fALIGNMENT-3987

> Macro: STRICT_ALIGNMENT

> Define this macro to be the value 1 if instructions will fail to work if given data not on the nominal alignment. If instructions will merely go slower in that case, define this macro as 0.

https://gcc.gnu.org/onlinedocs/gccint/Costs.html#index-SLOW_005fUNALIGNED_005fACCESS-4481

> Macro: SLOW_UNALIGNED_ACCESS (mode, alignment)

> Define this macro to be the value 1 if memory accesses described by the mode and alignment parameters have a cost many times greater than aligned accesses, for example if they are emulated in a trap handler.

> When this macro is nonzero, the compiler will act as if STRICT_ALIGNMENT were nonzero when generating code for block moves. This can cause significantly more instructions to be produced. Therefore, do not set this macro nonzero if unaligned accesses only add a cycle or two to the time for a memory access.

So it sounds to me like STRICT_ALIGNMENT should be 0, and
SLOW_UNALIGNED_ACCESS should somehow depend on the -mtune flags but
probably default to 1. That said I don't have any experience with the
gcc port and I don't know whether it is likely to actually work as
described.

-s

Andrew Waterman

unread,
Oct 23, 2016, 10:54:59 PM10/23/16
to Stefan O'Rear, Palmer Dabbelt, Richard W.M. Jones, RISC-V SW Dev
I suggest keeping strict alignment, as we want to use GCC to compile M-mode software where misalignment is not supported. In future, could add a flag (disabled by default) for systems with fast misaligned accesses.

Also note that AMOs are not allowed to be misaligned (unlike x86). So we'd need to special-case that somehow.
--
You received this message because you are subscribed to the Google Groups "RISC-V SW Dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sw-dev+un...@groups.riscv.org.
To post to this group, send email to sw-...@groups.riscv.org.
Visit this group at https://groups.google.com/a/groups.riscv.org/group/sw-dev/.
To view this discussion on the web visit https://groups.google.com/a/groups.riscv.org/d/msgid/sw-dev/CADJ6UvP68mUXMF6a46u97pZ4mwDi4Hh_LOyQKAro930ApbjDyg%40mail.gmail.com.
Reply all
Reply to author
Forward
0 new messages