diff options
author | Sanjay Patel <spatel@rotateright.com> | 2018-11-25 17:53:16 +0000 |
---|---|---|
committer | Sanjay Patel <spatel@rotateright.com> | 2018-11-25 17:53:16 +0000 |
commit | d0dcc6d923d6588f643c5c856145ef7619537637 (patch) | |
tree | fb0aa360dca847504e7899e397c5e1691cc35ef2 | |
parent | 2794e3315aa5beeee73b926e683c1e53db4bd7a9 (diff) | |
download | clang-d0dcc6d923d6588f643c5c856145ef7619537637.tar.gz |
[CodeGen] translate MS rotate builtins to LLVM funnel-shift intrinsics
This was originally part of:
D50924
and should resolve PR37387:
https://bugs.llvm.org/show_bug.cgi?id=37387
...but it was reverted because some bots using a gcc host compiler
would crash for unknown reasons with this included in the patch.
Trying again now to see if that's still a problem.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@347527 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/CGBuiltin.cpp | 50 | ||||
-rw-r--r-- | test/CodeGen/ms-intrinsics-rotations.c | 99 |
2 files changed, 31 insertions, 118 deletions
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index b1323031d9..cb15f19224 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -1820,46 +1820,6 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, "cast"); return RValue::get(Result); } - case Builtin::BI_rotr8: - case Builtin::BI_rotr16: - case Builtin::BI_rotr: - case Builtin::BI_lrotr: - case Builtin::BI_rotr64: { - Value *Val = EmitScalarExpr(E->getArg(0)); - Value *Shift = EmitScalarExpr(E->getArg(1)); - - llvm::Type *ArgType = Val->getType(); - Shift = Builder.CreateIntCast(Shift, ArgType, false); - unsigned ArgWidth = ArgType->getIntegerBitWidth(); - Value *Mask = llvm::ConstantInt::get(ArgType, ArgWidth - 1); - - Value *RightShiftAmt = Builder.CreateAnd(Shift, Mask); - Value *RightShifted = Builder.CreateLShr(Val, RightShiftAmt); - Value *LeftShiftAmt = Builder.CreateAnd(Builder.CreateNeg(Shift), Mask); - Value *LeftShifted = Builder.CreateShl(Val, LeftShiftAmt); - Value *Result = Builder.CreateOr(LeftShifted, RightShifted); - return RValue::get(Result); - } - case Builtin::BI_rotl8: - case Builtin::BI_rotl16: - case Builtin::BI_rotl: - case Builtin::BI_lrotl: - case Builtin::BI_rotl64: { - Value *Val = EmitScalarExpr(E->getArg(0)); - Value *Shift = EmitScalarExpr(E->getArg(1)); - - llvm::Type *ArgType = Val->getType(); - Shift = Builder.CreateIntCast(Shift, ArgType, false); - unsigned ArgWidth = ArgType->getIntegerBitWidth(); - Value *Mask = llvm::ConstantInt::get(ArgType, ArgWidth - 1); - - Value *LeftShiftAmt = Builder.CreateAnd(Shift, Mask); - Value *LeftShifted = Builder.CreateShl(Val, LeftShiftAmt); - Value *RightShiftAmt = Builder.CreateAnd(Builder.CreateNeg(Shift), Mask); - Value *RightShifted = Builder.CreateLShr(Val, RightShiftAmt); - Value *Result = Builder.CreateOr(LeftShifted, RightShifted); - return RValue::get(Result); - } case Builtin::BI__builtin_unpredictable: { // Always return the argument of __builtin_unpredictable. LLVM does not // handle this builtin. Metadata for this builtin should be added directly @@ -1918,12 +1878,22 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_rotateleft16: case Builtin::BI__builtin_rotateleft32: case Builtin::BI__builtin_rotateleft64: + case Builtin::BI_rotl8: // Microsoft variants of rotate left + case Builtin::BI_rotl16: + case Builtin::BI_rotl: + case Builtin::BI_lrotl: + case Builtin::BI_rotl64: return emitRotate(E, false); case Builtin::BI__builtin_rotateright8: case Builtin::BI__builtin_rotateright16: case Builtin::BI__builtin_rotateright32: case Builtin::BI__builtin_rotateright64: + case Builtin::BI_rotr8: // Microsoft variants of rotate right + case Builtin::BI_rotr16: + case Builtin::BI_rotr: + case Builtin::BI_lrotr: + case Builtin::BI_rotr64: return emitRotate(E, true); case Builtin::BI__builtin_constant_p: { diff --git a/test/CodeGen/ms-intrinsics-rotations.c b/test/CodeGen/ms-intrinsics-rotations.c index 735de6e41e..30428b12aa 100644 --- a/test/CodeGen/ms-intrinsics-rotations.c +++ b/test/CodeGen/ms-intrinsics-rotations.c @@ -30,66 +30,36 @@ unsigned char test_rotl8(unsigned char value, unsigned char shift) { return _rotl8(value, shift); } // CHECK: i8 @test_rotl8 -// CHECK: [[LSHIFT:%[0-9]+]] = and i8 [[SHIFT:%[0-9]+]], 7 -// CHECK: [[HIGH:%[0-9]+]] = shl i8 [[VALUE:%[0-9]+]], [[LSHIFT]] -// CHECK: [[NEGATE:%[0-9]+]] = sub i8 0, [[SHIFT]] -// CHECK: [[RSHIFT:%[0-9]+]] = and i8 [[NEGATE]], 7 -// CHECK: [[LOW:%[0-9]+]] = lshr i8 [[VALUE]], [[RSHIFT]] -// CHECK: [[RESULT:%[0-9]+]] = or i8 [[HIGH]], [[LOW]] -// CHECK: ret i8 [[RESULT]] -// CHECK } +// CHECK: [[R:%.*]] = call i8 @llvm.fshl.i8(i8 [[X:%.*]], i8 [[X]], i8 [[Y:%.*]]) +// CHECK: ret i8 [[R]] unsigned short test_rotl16(unsigned short value, unsigned char shift) { return _rotl16(value, shift); } // CHECK: i16 @test_rotl16 -// CHECK: [[LSHIFT:%[0-9]+]] = and i16 [[SHIFT:%[0-9]+]], 15 -// CHECK: [[HIGH:%[0-9]+]] = shl i16 [[VALUE:%[0-9]+]], [[LSHIFT]] -// CHECK: [[NEGATE:%[0-9]+]] = sub i16 0, [[SHIFT]] -// CHECK: [[RSHIFT:%[0-9]+]] = and i16 [[NEGATE]], 15 -// CHECK: [[LOW:%[0-9]+]] = lshr i16 [[VALUE]], [[RSHIFT]] -// CHECK: [[RESULT:%[0-9]+]] = or i16 [[HIGH]], [[LOW]] -// CHECK: ret i16 [[RESULT]] -// CHECK } +// CHECK: [[R:%.*]] = call i16 @llvm.fshl.i16(i16 [[X:%.*]], i16 [[X]], i16 [[Y:%.*]]) +// CHECK: ret i16 [[R]] unsigned int test_rotl(unsigned int value, int shift) { return _rotl(value, shift); } // CHECK: i32 @test_rotl -// CHECK: [[LSHIFT:%[0-9]+]] = and i32 [[SHIFT:%[0-9]+]], 31 -// CHECK: [[HIGH:%[0-9]+]] = shl i32 [[VALUE:%[0-9]+]], [[LSHIFT]] -// CHECK: [[NEGATE:%[0-9]+]] = sub i32 0, [[SHIFT]] -// CHECK: [[RSHIFT:%[0-9]+]] = and i32 [[NEGATE]], 31 -// CHECK: [[LOW:%[0-9]+]] = lshr i32 [[VALUE]], [[RSHIFT]] -// CHECK: [[RESULT:%[0-9]+]] = or i32 [[HIGH]], [[LOW]] -// CHECK: ret i32 [[RESULT]] -// CHECK } +// CHECK: [[R:%.*]] = call i32 @llvm.fshl.i32(i32 [[X:%.*]], i32 [[X]], i32 [[Y:%.*]]) +// CHECK: ret i32 [[R]] unsigned LONG test_lrotl(unsigned LONG value, int shift) { return _lrotl(value, shift); } // CHECK-32BIT-LONG: i32 @test_lrotl -// CHECK-32BIT-LONG: [[LSHIFT:%[0-9]+]] = and i32 [[SHIFT:%[0-9]+]], 31 -// CHECK-32BIT-LONG: [[HIGH:%[0-9]+]] = shl i32 [[VALUE:%[0-9]+]], [[LSHIFT]] -// CHECK-32BIT-LONG: [[NEGATE:%[0-9]+]] = sub i32 0, [[SHIFT]] -// CHECK-32BIT-LONG: [[RSHIFT:%[0-9]+]] = and i32 [[NEGATE]], 31 -// CHECK-32BIT-LONG: [[LOW:%[0-9]+]] = lshr i32 [[VALUE]], [[RSHIFT]] -// CHECK-32BIT-LONG: [[RESULT:%[0-9]+]] = or i32 [[HIGH]], [[LOW]] -// CHECK-32BIT-LONG: ret i32 [[RESULT]] -// CHECK-32BIT-LONG } +// CHECK-32BIT-LONG: [[R:%.*]] = call i32 @llvm.fshl.i32(i32 [[X:%.*]], i32 [[X]], i32 [[Y:%.*]]) +// CHECK-32BIT-LONG: ret i32 [[R]] unsigned __int64 test_rotl64(unsigned __int64 value, int shift) { return _rotl64(value, shift); } // CHECK: i64 @test_rotl64 -// CHECK: [[LSHIFT:%[0-9]+]] = and i64 [[SHIFT:%[0-9]+]], 63 -// CHECK: [[HIGH:%[0-9]+]] = shl i64 [[VALUE:%[0-9]+]], [[LSHIFT]] -// CHECK: [[NEGATE:%[0-9]+]] = sub i64 0, [[SHIFT]] -// CHECK: [[RSHIFT:%[0-9]+]] = and i64 [[NEGATE]], 63 -// CHECK: [[LOW:%[0-9]+]] = lshr i64 [[VALUE]], [[RSHIFT]] -// CHECK: [[RESULT:%[0-9]+]] = or i64 [[HIGH]], [[LOW]] -// CHECK: ret i64 [[RESULT]] -// CHECK } +// CHECK: [[R:%.*]] = call i64 @llvm.fshl.i64(i64 [[X:%.*]], i64 [[X]], i64 [[Y:%.*]]) +// CHECK: ret i64 [[R]] // rotate right @@ -97,61 +67,34 @@ unsigned char test_rotr8(unsigned char value, unsigned char shift) { return _rotr8(value, shift); } // CHECK: i8 @test_rotr8 -// CHECK: [[RSHIFT:%[0-9]+]] = and i8 [[SHIFT:%[0-9]+]], 7 -// CHECK: [[LOW:%[0-9]+]] = lshr i8 [[VALUE:%[0-9]+]], [[RSHIFT]] -// CHECK: [[NEGATE:%[0-9]+]] = sub i8 0, [[SHIFT]] -// CHECK: [[LSHIFT:%[0-9]+]] = and i8 [[NEGATE]], 7 -// CHECK: [[HIGH:%[0-9]+]] = shl i8 [[VALUE]], [[LSHIFT]] -// CHECK: [[RESULT:%[0-9]+]] = or i8 [[HIGH]], [[LOW]] -// CHECK } +// CHECK: [[R:%.*]] = call i8 @llvm.fshr.i8(i8 [[X:%.*]], i8 [[X]], i8 [[Y:%.*]]) +// CHECK: ret i8 [[R]] unsigned short test_rotr16(unsigned short value, unsigned char shift) { return _rotr16(value, shift); } // CHECK: i16 @test_rotr16 -// CHECK: [[RSHIFT:%[0-9]+]] = and i16 [[SHIFT:%[0-9]+]], 15 -// CHECK: [[LOW:%[0-9]+]] = lshr i16 [[VALUE:%[0-9]+]], [[RSHIFT]] -// CHECK: [[NEGATE:%[0-9]+]] = sub i16 0, [[SHIFT]] -// CHECK: [[LSHIFT:%[0-9]+]] = and i16 [[NEGATE]], 15 -// CHECK: [[HIGH:%[0-9]+]] = shl i16 [[VALUE]], [[LSHIFT]] -// CHECK: [[RESULT:%[0-9]+]] = or i16 [[HIGH]], [[LOW]] -// CHECK } +// CHECK: [[R:%.*]] = call i16 @llvm.fshr.i16(i16 [[X:%.*]], i16 [[X]], i16 [[Y:%.*]]) +// CHECK: ret i16 [[R]] unsigned int test_rotr(unsigned int value, int shift) { return _rotr(value, shift); } // CHECK: i32 @test_rotr -// CHECK: [[RSHIFT:%[0-9]+]] = and i32 [[SHIFT:%[0-9]+]], 31 -// CHECK: [[LOW:%[0-9]+]] = lshr i32 [[VALUE:%[0-9]+]], [[RSHIFT]] -// CHECK: [[NEGATE:%[0-9]+]] = sub i32 0, [[SHIFT]] -// CHECK: [[LSHIFT:%[0-9]+]] = and i32 [[NEGATE]], 31 -// CHECK: [[HIGH:%[0-9]+]] = shl i32 [[VALUE]], [[LSHIFT]] -// CHECK: [[RESULT:%[0-9]+]] = or i32 [[HIGH]], [[LOW]] -// CHECK: ret i32 [[RESULT]] -// CHECK } +// CHECK: [[R:%.*]] = call i32 @llvm.fshr.i32(i32 [[X:%.*]], i32 [[X]], i32 [[Y:%.*]]) +// CHECK: ret i32 [[R]] unsigned LONG test_lrotr(unsigned LONG value, int shift) { return _lrotr(value, shift); } // CHECK-32BIT-LONG: i32 @test_lrotr -// CHECK-32BIT-LONG: [[RSHIFT:%[0-9]+]] = and i32 [[SHIFT:%[0-9]+]], 31 -// CHECK-32BIT-LONG: [[LOW:%[0-9]+]] = lshr i32 [[VALUE:%[0-9]+]], [[RSHIFT]] -// CHECK-32BIT-LONG: [[NEGATE:%[0-9]+]] = sub i32 0, [[SHIFT]] -// CHECK-32BIT-LONG: [[LSHIFT:%[0-9]+]] = and i32 [[NEGATE]], 31 -// CHECK-32BIT-LONG: [[HIGH:%[0-9]+]] = shl i32 [[VALUE]], [[LSHIFT]] -// CHECK-32BIT-LONG: [[RESULT:%[0-9]+]] = or i32 [[HIGH]], [[LOW]] -// CHECK-32BIT-LONG: ret i32 [[RESULT]] -// CHECK-32BIT-LONG } +// CHECK-32BIT-LONG: [[R:%.*]] = call i32 @llvm.fshr.i32(i32 [[X:%.*]], i32 [[X]], i32 [[Y:%.*]]) +// CHECK-32BIT-LONG: ret i32 [[R]] unsigned __int64 test_rotr64(unsigned __int64 value, int shift) { return _rotr64(value, shift); } // CHECK: i64 @test_rotr64 -// CHECK: [[RSHIFT:%[0-9]+]] = and i64 [[SHIFT:%[0-9]+]], 63 -// CHECK: [[LOW:%[0-9]+]] = lshr i64 [[VALUE:%[0-9]+]], [[RSHIFT]] -// CHECK: [[NEGATE:%[0-9]+]] = sub i64 0, [[SHIFT]] -// CHECK: [[LSHIFT:%[0-9]+]] = and i64 [[NEGATE]], 63 -// CHECK: [[HIGH:%[0-9]+]] = shl i64 [[VALUE]], [[LSHIFT]] -// CHECK: [[RESULT:%[0-9]+]] = or i64 [[HIGH]], [[LOW]] -// CHECK: ret i64 [[RESULT]] -// CHECK } +// CHECK: [[R:%.*]] = call i64 @llvm.fshr.i64(i64 [[X:%.*]], i64 [[X]], i64 [[Y:%.*]]) +// CHECK: ret i64 [[R]] + |