Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
New Contributor I
28 Views

Alignment attributes not inherited.

Jump to solution
ICC does not currently exhibit the same behavior with regards to inheritance of alignment specifiers (__declspec(align(16)), __attribute__((aligned(16))) as MSVC 2008 and GCC 4.4.3.
That is: if you derive a class/struct from a structure with an alignment specifier, MSVC and GCC will inherit the alignment specifier. Intel Compiler does not, require a fresh alignment specifier.
In the following example, "SeventeenBytes_v1" inherits an alignment from a base class, while SeventeenBytes_v2 inherits the same base but provides its own additional specifier.
Several instances of each class are created on the stack and their addresses tested for alignment. MSVC and GCC create all of the instances at the specified base-class alignment. The Intel C++ compiler only aligns the v2 structure.
[cpp]#include 
#include 
#include 

namespace Memory
{
#if defined(_MSC_VER)
	#define __align(_boundary_size) __declspec((align(_boundary_size)))
#else
	#define __align(_boundary_size) __attribute__((aligned(_boundary_size)))
#endif

	// Test if a pointer is X-byte aligned.
	template bool IsAligned(const void* const ptr) { return ((((unsigned long long)ptr) & (unsigned long long)(BoundarySize-1)) == 0ULL) ; }
	static inline bool IsAligned16(const void* const ptr) { return IsAligned<16>(ptr) ; }

	template
	struct Aligned
	{
		static const size_t AlignmentBoundary = Boundary ;
	} ;

	struct __align(16) Aligned16 : public Memory::Aligned<16> {} ;
} // namespace Memory


// Inheriting Memory::Aligned16 seems to be good enough to make
// GCC 16-byte align stack allocations of this object.
struct SeventeenBytes_v1 : public Memory::Aligned16
{
	char bytes[17] ;
} ;

// ICC seems to require derived classes to specifically state
// their desire to be aligned.
struct __align(16) SeventeenBytes_v2 : public Memory::Aligned16
{
	char bytes[17] ;
} ;

static bool testIsClean ;

static void _test(const char* const desc, const char* const obj, const void* const ptr)
{
	if ( !Memory::IsAligned16(ptr) )
	{
		fprintf(stderr, "%s: %s: NOT 16-byte aligned: address = %p, offset = %u\n", desc, obj, ptr, ((unsigned int)ptr & 0x0f)) ;
		testIsClean = false ;
	}
}

template
static void testFunction(const char* const desc)
{
	_Type i1 ;	// First instance.
	_Type a[3] ;

	testIsClean = true ;

	_test(desc, "i1", &i1) ;
	_test(desc, "a[0]", &a[0]) ;
	_test(desc, "a[1]", &a[1]) ;
	_test(desc, "a[2]", &a[2]) ;

	printf("%s: %s\n", (testIsClean ? "SUCCESS" : "FAIL"), desc) ;
}

int main(int argc, char* argv[])
{
	testFunction("v1") ;
	testFunction("v2") ;

	return 0 ;
}
[/cpp]
Please note: This is a functional reduction of a larger project, in-case you are wondering "why"?
[bash]osmith@lucid32:~$ alignTest () { echo "********** Testing with ${CC}" ; ${CC} --version ; echo ; rm -f ./aligntest ; ${CC} -O3 -o aligntest aligntest.cpp ; ./aligntest ; echo ; }
osmith@lucid32:~$ CC=g++ alignTest
********** Testing with g++
g++ (Ubuntu 4.4.3-4ubuntu5) 4.4.3
Copyright (C) 2009 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


SUCCESS: v1
SUCCESS: v2

osmith@lucid32:~$ CC=icpc alignTest
********** Testing with icpc
icpc (ICC) 11.1 20100203
Copyright (C) 1985-2010 Intel Corporation.  All rights reserved.


v1: a[1]: NOT 16-byte aligned: address = 0xbf92c771, offset = 1
v1: a[2]: NOT 16-byte aligned: address = 0xbf92c782, offset = 2
FAIL: v1
SUCCESS: v2

osmith@lucid32:~$ [/bash]
0 Kudos

Accepted Solutions
Highlighted
Employee
28 Views
Below is a simple example. I have entered this in our bug tracking database as cq #153620.

Thank you for reporting it. We cannot fix it in a supported release (11.1) because it could
potentially break link compatibility --which we won't do from update to update. But we will
definitelytry to fix it for version 12.0. You can workaround it (as youmentioned) by explicitly
specifying the alignment attribute for derived classes.


/*
g++ version 4.3 and later prints PASSED for the code below,
but icpc prints FAILED with -gcc-version=430 and later.

icl is compatible with MSVC++ (both print PASSED) so this is only a
Gnu compatibility bug with themore recent versions of Gnu.
*/

extern "C" int printf(const char*,...);

#if defined(_MSC_VER)
#define __align(_boundary_size) __declspec(align(_boundary_size))
#else
#define __align(_boundary_size) __attribute__((aligned(_boundary_size)))
#endif

struct __align(16) Base {} ;
struct Derived : public Base {};

int main()
{
if (__alignof(Derived)==16)
printf("PASSED\n");
else
printf("FAILED\n");
return 0 ;
}

Judy

View solution in original post

0 Kudos
8 Replies
Highlighted
Black Belt
28 Views
Thanks for the interesting test.
In my first attempt, on 32-bit ICL, it reports success.
I'll extend it shamelessly to test availability of 32-byte (as well as 16-byte) alignment on linux x86_64 FC12, which is supposed to support both.

I just submitted premier.intel.com issue 586103

It does work with g++ even for 32-byte alignment (but requires -fpermissive; you might consider fixing that).
0 Kudos
Highlighted
New Contributor I
28 Views
The original source actually includes 32, 64, cache-aligned, and page-aligned derivatives (hence the templating -- obviously the templates aren't necessary for just one type :)
The only FC boxes I have are FC8 (this is an aside, but I found it near impossible to build binaries for our FC8-hosted servers with any version of Fedora above 8, but I can happily build FC8-compatible binaries on Ubuntu 8, 9 and 10 - how weird is that? And I'm not doing anything particularly fancy! It seems that FC8 is a particularly bad fedora to be stuck on, *sigh*)
I did the tests under Ubuntu 10.4b1 and 9.10, all 32 bit.
After some sleep and coffee, it occurs I may have tested MSVC under Windows twice rather than MSVC followed by ICC :)
Can you post the icpc --version output and uname -a of your system?
[bash]osmith@lucid32:~/pn/host$ icpc --version && uname -a
icpc (ICC) 11.1 20100203
Copyright (C) 1985-2010 Intel Corporation.  All rights reserved.

Linux lucid32 2.6.32-19-generic #28-Ubuntu SMP Wed Mar 31 17:46:20 UTC 2010 i686 GNU/Linux
[/bash]
0 Kudos
Highlighted
Black Belt
28 Views
Unfortunately, icpc 11.1 isn't working on our FC12 x86_64 either; I haven't got a reply from the people who chose the combination, which isn't a supported one, as to whether they attempted to satisfy the missing prerequisites. Generally, I've been able to build with icpc 11.1/069 on a supported RHEL, then run on FC12, but didn't verify that this time. The icpc which I ran is a beta version for Intel64, but I believe you about the results being similar on 11.1 ia32, and needing some attention for future versions. The gcc 4.4 which comes with FC12 makes a fatal error of your typecast in printf() unless I set -fpermissive.

uname -r: 2.6.32.9-71.xstate.0.fc12.x86_64
0 Kudos
Highlighted
Employee
29 Views
Below is a simple example. I have entered this in our bug tracking database as cq #153620.

Thank you for reporting it. We cannot fix it in a supported release (11.1) because it could
potentially break link compatibility --which we won't do from update to update. But we will
definitelytry to fix it for version 12.0. You can workaround it (as youmentioned) by explicitly
specifying the alignment attribute for derived classes.


/*
g++ version 4.3 and later prints PASSED for the code below,
but icpc prints FAILED with -gcc-version=430 and later.

icl is compatible with MSVC++ (both print PASSED) so this is only a
Gnu compatibility bug with themore recent versions of Gnu.
*/

extern "C" int printf(const char*,...);

#if defined(_MSC_VER)
#define __align(_boundary_size) __declspec(align(_boundary_size))
#else
#define __align(_boundary_size) __attribute__((aligned(_boundary_size)))
#endif

struct __align(16) Base {} ;
struct Derived : public Base {};

int main()
{
if (__alignof(Derived)==16)
printf("PASSED\n");
else
printf("FAILED\n");
return 0 ;
}

Judy

View solution in original post

0 Kudos
Highlighted
Black Belt
28 Views
I got a report that the compiler development team fixed the problem and will let us know when a corrected compiler becomes available.
0 Kudos
Highlighted
New Contributor I
28 Views

I also just hit that issue... Finding my way from the assembler output to the actual problem. Good to hear that it's going to be fixed.

I wanted to mention another useful workaround if you do not know the alignment restriction but were relying on the base class to get it right. So instead of

class A : public B {};
you'd do
class A : public B {}
#ifdef __INTEL_COMPILER
__attribute__((__aligned(__alignof(B))))
#endif
;
Saved me from more elaborate workarounds.

0 Kudos
Highlighted
Black Belt
28 Views
A further report indicates the correction was made for the C++ 12.0 release "Composer XE."
0 Kudos
Highlighted
28 Views
The latest intel compiler (Intel C++ Compiler XE 12.0 Update 2) contains the fix for this issue. You may download it at https://registrationcenter.intel.com.

Thanks,
Feilong
0 Kudos