-
Notifications
You must be signed in to change notification settings - Fork 11k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[X86] Add gcc rotate intrinsics to ia32intrin.h
This is another attempt at what Erich Keane tried to do in r355322. This adds rolb, rolw, rold, rolq and their ror equivalent as always_inline wrappers around __builtin_rotate* which will lower to funnel shift intrinsics in IR. Additionally, when _MSC_VER is not defined we will define _rotl, _lrotl, _rotr, _lrotr as macros to one of the always_inline intrinsics mentioned above. Making sure that _lrotl/_lrotr use either 32 or 64 bit based on the size of long. These need to be macros because we have builtins with the same name for MS compatibility, but _MSC_VER isn't always defined when those builtins are enabled. We also define _rotwl and _rotwr as macros aliasing to rolw/rorw just like gcc to complete the set. These don't need to be gated with _MSC_VER because these aren't MS builtins. I've added tests both for non-MS and -ms-extensions with and without _MSC_VER being defined. Differential Revision: https://reviews.llvm.org/D59346 llvm-svn: 356423
- Loading branch information
Showing
2 changed files
with
180 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
// RUN: %clang_cc1 -ffreestanding -triple i686--linux -emit-llvm %s -o - | FileCheck %s --check-prefixes CHECK,CHECK-32BIT-LONG | ||
// RUN: %clang_cc1 -ffreestanding -triple x86_64--linux -emit-llvm %s -o - | FileCheck %s --check-prefixes CHECK,CHECK-64BIT-LONG | ||
// RUN: %clang_cc1 -fms-extensions -fms-compatibility -ffreestanding %s -triple=i686-windows-msvc -target-feature +sse2 -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefixes CHECK,CHECK-32BIT-LONG | ||
// RUN: %clang_cc1 -fms-extensions -fms-compatibility -ffreestanding %s -triple=x86_64-windows-msvc -target-feature +sse2 -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefixes CHECK,CHECK-32BIT-LONG | ||
// RUN: %clang_cc1 -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 -ffreestanding %s -triple=i686-windows-msvc -target-feature +sse2 -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefixes CHECK,CHECK-32BIT-LONG | ||
// RUN: %clang_cc1 -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 -ffreestanding %s -triple=x86_64-windows-msvc -target-feature +sse2 -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefixes CHECK,CHECK-32BIT-LONG | ||
|
||
#include <x86intrin.h> | ||
|
||
unsigned char test__rolb(unsigned char value, int shift) { | ||
// CHECK-LABEL: i8 @test__rolb | ||
// CHECK: [[R:%.*]] = call i8 @llvm.fshl.i8(i8 [[X:%.*]], i8 [[X]], i8 [[Y:%.*]]) | ||
// CHECK: ret i8 [[R]] | ||
return __rolb(value, shift); | ||
} | ||
|
||
unsigned short test__rolw(unsigned short value, int shift) { | ||
// CHECK-LABEL: i16 @test__rolw | ||
// CHECK: [[R:%.*]] = call i16 @llvm.fshl.i16(i16 [[X:%.*]], i16 [[X]], i16 [[Y:%.*]]) | ||
// CHECK: ret i16 [[R]] | ||
return __rolw(value, shift); | ||
} | ||
|
||
unsigned int test__rold(unsigned int value, int shift) { | ||
// CHECK-LABEL: i32 @test__rold | ||
// CHECK: [[R:%.*]] = call i32 @llvm.fshl.i32(i32 [[X:%.*]], i32 [[X]], i32 [[Y:%.*]]) | ||
// CHECK: ret i32 [[R]] | ||
return __rold(value, shift); | ||
} | ||
|
||
#if defined(__x86_64__) | ||
unsigned long test__rolq(unsigned long value, int shift) { | ||
// CHECK-LONG-LABEL: i64 @test__rolq | ||
// CHECK-LONG: [[R:%.*]] = call i64 @llvm.fshl.i64(i64 [[X:%.*]], i64 [[X]], i64 [[Y:%.*]]) | ||
// CHECK-LONG: ret i64 [[R]] | ||
return __rolq(value, shift); | ||
} | ||
#endif | ||
|
||
unsigned char test__rorb(unsigned char value, int shift) { | ||
// CHECK-LABEL: i8 @test__rorb | ||
// CHECK: [[R:%.*]] = call i8 @llvm.fshr.i8(i8 [[X:%.*]], i8 [[X]], i8 [[Y:%.*]]) | ||
// CHECK: ret i8 [[R]] | ||
return __rorb(value, shift); | ||
} | ||
|
||
unsigned short test__rorw(unsigned short value, int shift) { | ||
// CHECK-LABEL: i16 @test__rorw | ||
// CHECK: [[R:%.*]] = call i16 @llvm.fshr.i16(i16 [[X:%.*]], i16 [[X]], i16 [[Y:%.*]]) | ||
// CHECK: ret i16 [[R]] | ||
return __rorw(value, shift); | ||
} | ||
|
||
unsigned int test__rord(unsigned int value, int shift) { | ||
// CHECK-LABEL: i32 @test__rord | ||
// CHECK: [[R:%.*]] = call i32 @llvm.fshr.i32(i32 [[X:%.*]], i32 [[X]], i32 [[Y:%.*]]) | ||
// CHECK: ret i32 [[R]] | ||
return __rord(value, shift); | ||
} | ||
|
||
#if defined(__x86_64__) | ||
unsigned long test__rorq(unsigned long value, int shift) { | ||
// CHECK-LONG-LABEL: i64 @test__rorq | ||
// CHECK-LONG: [[R:%.*]] = call i64 @llvm.fshr.i64(i64 [[X:%.*]], i64 [[X]], i64 [[Y:%.*]]) | ||
// CHECK-LONG: ret i64 [[R]] | ||
return __rorq(value, shift); | ||
} | ||
#endif | ||
|
||
unsigned short test_rotwl(unsigned short value, int shift) { | ||
// CHECK-LABEL: i16 @test_rotwl | ||
// CHECK: [[R:%.*]] = call i16 @llvm.fshl.i16(i16 [[X:%.*]], i16 [[X]], i16 [[Y:%.*]]) | ||
// CHECK: ret i16 [[R]] | ||
return _rotwl(value, shift); | ||
} | ||
|
||
unsigned int test_rotl(unsigned int value, int shift) { | ||
// CHECK-LABEL: i32 @test_rotl | ||
// CHECK: [[R:%.*]] = call i32 @llvm.fshl.i32(i32 [[X:%.*]], i32 [[X]], i32 [[Y:%.*]]) | ||
// CHECK: ret i32 [[R]] | ||
return _rotl(value, shift); | ||
} | ||
|
||
unsigned long test_lrotl(unsigned long value, int shift) { | ||
// CHECK-32BIT-LONG-LABEL: i32 @test_lrotl | ||
// CHECK-32BIT-LONG: [[R:%.*]] = call i32 @llvm.fshl.i32(i32 [[X:%.*]], i32 [[X]], i32 [[Y:%.*]]) | ||
// CHECK-32BIT-LONG: ret i32 [[R]] | ||
// | ||
// CHECK-64BIT-LONG-LABEL: i64 @test_lrotl | ||
// CHECK-64BIT-LONG: [[R:%.*]] = call i64 @llvm.fshl.i64(i64 [[X:%.*]], i64 [[X]], i64 [[Y:%.*]]) | ||
// CHECK-64BIT-LONG: ret i64 [[R]] | ||
return _lrotl(value, shift); | ||
} | ||
|
||
|
||
unsigned short test_rotwr(unsigned short value, int shift) { | ||
// CHECK-LABEL: i16 @test_rotwr | ||
// CHECK: [[R:%.*]] = call i16 @llvm.fshr.i16(i16 [[X:%.*]], i16 [[X]], i16 [[Y:%.*]]) | ||
// CHECK: ret i16 [[R]] | ||
return _rotwr(value, shift); | ||
} | ||
|
||
unsigned int test_rotr(unsigned int value, int shift) { | ||
// CHECK-LABEL: i32 @test_rotr | ||
// CHECK: [[R:%.*]] = call i32 @llvm.fshr.i32(i32 [[X:%.*]], i32 [[X]], i32 [[Y:%.*]]) | ||
// CHECK: ret i32 [[R]] | ||
return _rotr(value, shift); | ||
} | ||
|
||
unsigned long test_lrotr(unsigned long value, int shift) { | ||
// CHECK-32BIT-LONG-LABEL: i32 @test_lrotr | ||
// CHECK-32BIT-LONG: [[R:%.*]] = call i32 @llvm.fshr.i32(i32 [[X:%.*]], i32 [[X]], i32 [[Y:%.*]]) | ||
// CHECK-32BIT-LONG: ret i32 [[R]] | ||
// | ||
// CHECK-64BIT-LONG-LABEL: i64 @test_lrotr | ||
// CHECK-64BIT-LONG: [[R:%.*]] = call i64 @llvm.fshr.i64(i64 [[X:%.*]], i64 [[X]], i64 [[Y:%.*]]) | ||
// CHECK-64BIT-LONG: ret i64 [[R]] | ||
return _lrotr(value, shift); | ||
} | ||
|