diff options
author | Albert Gutowski <agutowski@google.com> | 2016-09-08 22:32:19 +0000 |
---|---|---|
committer | Albert Gutowski <agutowski@google.com> | 2016-09-08 22:32:19 +0000 |
commit | b6a11acb533132bd1da786c73962ed8307b50ff7 (patch) | |
tree | 11bda798f5d3210955fe9c3e60a25db1f022148f /clang/lib/CodeGen/CGBuiltin.cpp | |
parent | dec394935fb1415315d21b6de10ab0f1ea1772fe (diff) | |
download | bcm5719-llvm-b6a11acb533132bd1da786c73962ed8307b50ff7.tar.gz bcm5719-llvm-b6a11acb533132bd1da786c73962ed8307b50ff7.zip |
Implement MS _rot intrinsics
Reviewers: thakis, Prazek, compnerd, rnk
Subscribers: majnemer, cfe-commits
Differential Revision: https://reviews.llvm.org/D24311
llvm-svn: 280997
Diffstat (limited to 'clang/lib/CodeGen/CGBuiltin.cpp')
-rw-r--r-- | clang/lib/CodeGen/CGBuiltin.cpp | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index c06fcf73f37..d74f06cbc5c 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -696,6 +696,58 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, "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 = cast<llvm::IntegerType>(ArgType)->getBitWidth(); + Value *ArgTypeSize = llvm::ConstantInt::get(ArgType, ArgWidth); + Value *ArgZero = llvm::Constant::getNullValue(ArgType); + + Value *Mask = llvm::ConstantInt::get(ArgType, ArgWidth - 1); + Shift = Builder.CreateAnd(Shift, Mask); + Value *LeftShift = Builder.CreateSub(ArgTypeSize, Shift); + + Value *RightShifted = Builder.CreateLShr(Val, Shift); + Value *LeftShifted = Builder.CreateShl(Val, LeftShift); + Value *Rotated = Builder.CreateOr(LeftShifted, RightShifted); + + Value *ShiftIsZero = Builder.CreateICmpEQ(Shift, ArgZero); + Value *Result = Builder.CreateSelect(ShiftIsZero, Val, Rotated); + 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 = cast<llvm::IntegerType>(ArgType)->getBitWidth(); + Value *ArgTypeSize = llvm::ConstantInt::get(ArgType, ArgWidth); + Value *ArgZero = llvm::Constant::getNullValue(ArgType); + + Value *Mask = llvm::ConstantInt::get(ArgType, ArgWidth - 1); + Shift = Builder.CreateAnd(Shift, Mask); + Value *RightShift = Builder.CreateSub(ArgTypeSize, Shift); + + Value *LeftShifted = Builder.CreateShl(Val, Shift); + Value *RightShifted = Builder.CreateLShr(Val, RightShift); + Value *Rotated = Builder.CreateOr(LeftShifted, RightShifted); + + Value *ShiftIsZero = Builder.CreateICmpEQ(Shift, ArgZero); + Value *Result = Builder.CreateSelect(ShiftIsZero, Val, Rotated); + 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 |