aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSanjay Patel <spatel@rotateright.com>2018-11-25 17:53:16 +0000
committerSanjay Patel <spatel@rotateright.com>2018-11-25 17:53:16 +0000
commitd0dcc6d923d6588f643c5c856145ef7619537637 (patch)
treefb0aa360dca847504e7899e397c5e1691cc35ef2
parent2794e3315aa5beeee73b926e683c1e53db4bd7a9 (diff)
downloadclang-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.cpp50
-rw-r--r--test/CodeGen/ms-intrinsics-rotations.c99
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]]
+