Skip to content

Commit 617c2d1

Browse files
committed
Linux/ARM: Fix +3000 bus errors of unit-test in case of O2/O3 levels
**PROBLEM** This patch is to resolve +3000 bus errors that are generated whenever we use the aggressive optimization levels of clang (issue #5844 ). When we enable the -O3 optimization level of the clang version(from clang 3.5 to clang 3.9(snapshot)), we have always got the lots of bus errors from the coreCLR's unit tests. Actually, we can easily monitor SIGBUS signals (e.g., "misaligned memory access") with /proc/cpu/alignment facility in kernel space. Using "echo 2 > /proc/cpu/alignment" makes Linux kernel fixes the problems but the performance of the application will be degraded. .source: http://lxr.free-electrons.com/source/Documentation/arm/mem_alignment **VERSION 2** .Add UNALIGNED_ARM macro for handling ARM core specific optimisation levels. .Add RISC-based ARM core handling into the existing infra-structure of the platform adaptation layer (PAL) for aggressive optimization cases on Linux/ARM. **VERSION 1** Basically, RISC-based ARM architecture requires aligned access with 4byte reads. In order to support aggressive optimization levels such as O2/O3, let's use attribute keyword of aligned(1) instead of using memcpy(2) in into a properly aligned buffer or the packing attribute. **BACKGROUND** According to ARM information center(infocenter.arm.com), By default, the ARM compiler expects normal C and C++ pointers to point to an aligned word in memory. A type qualifier __packed is provided to enable unaligned pointer access. If you want to define a pointer to a word that can be at any address (that is, that can be at a non-natural alignment), you must specify this using the __packed qualifier when defining the pointer: __packed int *pi; // pointer to unaligned int However, clang/llvm does not support the __packed qualifier such as __attribute__((packed)) or __attribute__((packed, aligned(4))) In -O0 (debug build) the innermost block is emitted as the following assembly, which works properly: ldr r1, [r0, dotnet#24] ldr r2, [r0, dotnet#20] In -O3 (release build) however the compiler realizes these fields are adjacent and generates this assembly: ldrdeq r2, r3, [r0, dotnet#20] Unfortunately, vldr/ldrdb instructions always generate an alignment fault (in practice). It seems that clang uses ldrb instruction although GCC uses ldr instruction because armv7 supports unaligned ldr instruction. Note: If some arm architectures (e.g., Linux/ARM Emulator) does not support unaligned ldr, this issue is not generated with aggressive optimization levels (e.g., -O2 and -O3). * source: How does the ARM Compiler support unaligned accesses? http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka15414.html Signed-off-by: Geunsik Lim <geunsik.lim@samsung.com>
1 parent 5257068 commit 617c2d1

File tree

2 files changed

+11
-2
lines changed

2 files changed

+11
-2
lines changed

src/jit/compiler.hpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -757,13 +757,16 @@ inline
757757
signed __int16 getI2LittleEndian(const BYTE * ptr)
758758
{ return * (UNALIGNED signed __int16 *)ptr; }
759759

760+
typedef signed __int32 UNALIGNED_ARM __unaligned_int32;
761+
typedef signed __int64 UNALIGNED_ARM __unaligned_int64;
762+
760763
inline
761764
signed __int32 getI4LittleEndian(const BYTE * ptr)
762-
{ return *(UNALIGNED signed __int32*)ptr; }
765+
{ return *(__unaligned_int32 *)ptr; }
763766

764767
inline
765768
signed __int64 getI8LittleEndian(const BYTE * ptr)
766-
{ return *(UNALIGNED signed __int64*)ptr; }
769+
{ return *(__unaligned_int64 *)ptr; }
767770

768771
inline
769772
float getR4LittleEndian(const BYTE * ptr)

src/pal/inc/pal.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,13 @@ extern "C" {
201201

202202
#else // _MSC_VER
203203

204+
#if defined (_M_ARM) && !defined (DEBUG)
204205
#define UNALIGNED
206+
#define UNALIGNED_ARM __attribute__((aligned(1))) //for -O2 and -O3
207+
#else
208+
#define UNALIGNED
209+
#define UNALIGNED_ARM //for -O0
210+
#endif
205211

206212
#endif // _MSC_VER
207213

0 commit comments

Comments
 (0)