Index: lib/Basic/Targets/X86.cpp =================================================================== --- lib/Basic/Targets/X86.cpp +++ lib/Basic/Targets/X86.cpp @@ -1081,6 +1081,9 @@ if (HasMWAITX) Builder.defineMacro("__MWAITX__"); + if (HasMOVBE) + Builder.defineMacro("__MOVBE__"); + switch (XOPLevel) { case XOP: Builder.defineMacro("__XOP__"); Index: lib/Headers/immintrin.h =================================================================== --- lib/Headers/immintrin.h +++ lib/Headers/immintrin.h @@ -306,6 +306,58 @@ #endif #endif /* __FSGSBASE__ */ +#if !defined(_MSC_VER) || __has_feature(modules) || defined(__MOVBE__) +static __inline__ short __attribute__((__always_inline__, __nodebug__, __target__("movbe"))) +_loadbe_i16(void const * __P) { + struct __loadu_i16 { + short __v; + } __attribute__((__packed__, __may_alias__)); + return __builtin_bswap16(((struct __loadu_i16*)__P)->__v); +} + +static __inline__ void __attribute__((__always_inline__, __nodebug__, __target__("movbe"))) +_storebe_i16(void * __P, short __D) { + struct __storeu_i16 { + short __v; + } __attribute__((__packed__, __may_alias__)); + ((struct __storeu_i16*)__P)->__v = __builtin_bswap16(__D); +} + +static __inline__ int __attribute__((__always_inline__, __nodebug__, __target__("movbe"))) +_loadbe_i32(void const * __P) { + struct __loadu_i32 { + int __v; + } __attribute__((__packed__, __may_alias__)); + return __builtin_bswap32(((struct __loadu_i32*)__P)->__v); +} + +static __inline__ void __attribute__((__always_inline__, __nodebug__, __target__("movbe"))) +_storebe_i32(void * __P, int __D) { + struct __storeu_i32 { + int __v; + } __attribute__((__packed__, __may_alias__)); + ((struct __storeu_i32*)__P)->__v = __builtin_bswap32(__D); +} + +#ifdef __x86_64__ +static __inline__ long long __attribute__((__always_inline__, __nodebug__, __target__("movbe"))) +_loadbe_i64(void const * __P) { + struct __loadu_i64 { + long long __v; + } __attribute__((__packed__, __may_alias__)); + return __builtin_bswap64(((struct __loadu_i64*)__P)->__v); +} + +static __inline__ void __attribute__((__always_inline__, __nodebug__, __target__("movbe"))) +_storebe_i64(void * __P, long long __D) { + struct __storeu_i64 { + long long __v; + } __attribute__((__packed__, __may_alias__)); + ((struct __storeu_i64*)__P)->__v = __builtin_bswap64(__D); +} +#endif +#endif /* __MOVEBE */ + #if !defined(_MSC_VER) || __has_feature(modules) || defined(__RTM__) #include #include Index: test/CodeGen/movbe-builtins.c =================================================================== --- /dev/null +++ test/CodeGen/movbe-builtins.c @@ -0,0 +1,49 @@ +// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +movbe -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-X64 +// RUN: %clang_cc1 -ffreestanding %s -triple=i686-apple-darwin -target-feature +movbe -emit-llvm -o - | FileCheck %s + + +#include + +short test_loadbe_i16(const short *P) { + // CHECK-LABEL: @test_loadbe_i16 + // CHECK: [[LOAD:%.*]] = load i16, i16* %{{.*}}, align 1 + // CHECK: call i16 @llvm.bswap.i16(i16 [[LOAD]]) + return _loadbe_i16(P); +} + +void test_storebe_i16(short *P, short D) { + // CHECK-LABEL: @test_storebe_i16 + // CHECK: [[DATA:%.*]] = call i16 @llvm.bswap.i16(i16 %{{.*}}) + // CHECK: store i16 [[DATA]], i16* %{{.*}}, align 1 + _storebe_i16(P, D); +} + +int test_loadbe_i32(const int *P) { + // CHECK-LABEL: @test_loadbe_i32 + // CHECK: [[LOAD:%.*]] = load i32, i32* %{{.*}}, align 1 + // CHECK: call i32 @llvm.bswap.i32(i32 [[LOAD]]) + return _loadbe_i32(P); +} + +void test_storebe_i32(int *P, int D) { + // CHECK-LABEL: @test_storebe_i32 + // CHECK: [[DATA:%.*]] = call i32 @llvm.bswap.i32(i32 %{{.*}}) + // CHECK: store i32 [[DATA]], i32* %{{.*}}, align 1 + _storebe_i32(P, D); +} + +#ifdef __x86_64__ +long long test_loadbe_i64(const long long *P) { + // CHECK-X64-LABEL: @test_loadbe_i64 + // CHECK-X64: [[LOAD:%.*]] = load i64, i64* %{{.*}}, align 1 + // CHECK-X64: call i64 @llvm.bswap.i64(i64 [[LOAD]]) + return _loadbe_i64(P); +} + +void test_storebe_i64(long long *P, long long D) { + // CHECK-X64-LABEL: @test_storebe_i64 + // CHECK-X64: [[DATA:%.*]] = call i64 @llvm.bswap.i64(i64 %{{.*}}) + // CHECK-X64: store i64 [[DATA]], i64* %{{.*}}, align 1 + _storebe_i64(P, D); +} +#endif