diff options
author | Hao Liu <Hao.Liu@arm.com> | 2014-05-14 08:59:30 +0000 |
---|---|---|
committer | Hao Liu <Hao.Liu@arm.com> | 2014-05-14 08:59:30 +0000 |
commit | 9f9492b657358da8f7787e652b2f425fc5570208 (patch) | |
tree | 88f39fe5998b399e2e603ee3bfc4486d5c991210 /clang/lib/CodeGen | |
parent | 7534a60753ee243e1a4e1a3bd0bd2ea245844e42 (diff) | |
download | bcm5719-llvm-9f9492b657358da8f7787e652b2f425fc5570208.tar.gz bcm5719-llvm-9f9492b657358da8f7787e652b2f425fc5570208.zip |
[ARM64]Fix the bug right shift uint64_t by 64 generates incorrect result.
llvm-svn: 208761
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGBuiltin.cpp | 29 |
1 files changed, 16 insertions, 13 deletions
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 824de8ccbb9..f77aeecd292 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -5580,38 +5580,41 @@ Value *CodeGenFunction::EmitARM64BuiltinExpr(unsigned BuiltinID, case NEON::BI__builtin_neon_vshld_n_u64: { llvm::ConstantInt *Amt = cast<ConstantInt>(EmitScalarExpr(E->getArg(1))); return Builder.CreateShl( - Ops[0], ConstantInt::get(Int64Ty, std::min(static_cast<uint64_t>(63), - Amt->getZExtValue())), - "vshr_n"); + Ops[0], ConstantInt::get(Int64Ty, Amt->getZExtValue()), "shld_n"); } case NEON::BI__builtin_neon_vshrd_n_s64: { llvm::ConstantInt *Amt = cast<ConstantInt>(EmitScalarExpr(E->getArg(1))); return Builder.CreateAShr( Ops[0], ConstantInt::get(Int64Ty, std::min(static_cast<uint64_t>(63), Amt->getZExtValue())), - "vshr_n"); + "shrd_n"); } case NEON::BI__builtin_neon_vshrd_n_u64: { llvm::ConstantInt *Amt = cast<ConstantInt>(EmitScalarExpr(E->getArg(1))); - return Builder.CreateLShr( - Ops[0], ConstantInt::get(Int64Ty, std::min(static_cast<uint64_t>(63), - Amt->getZExtValue())), - "vshr_n"); + uint64_t ShiftAmt = Amt->getZExtValue(); + // Right-shifting an unsigned value by its size yields 0. + if (ShiftAmt == 64) + return ConstantInt::get(Int64Ty, 0); + return Builder.CreateLShr(Ops[0], ConstantInt::get(Int64Ty, ShiftAmt), + "shrd_n"); } case NEON::BI__builtin_neon_vsrad_n_s64: { llvm::ConstantInt *Amt = cast<ConstantInt>(EmitScalarExpr(E->getArg(2))); Ops[1] = Builder.CreateAShr( Ops[1], ConstantInt::get(Int64Ty, std::min(static_cast<uint64_t>(63), Amt->getZExtValue())), - "vshr_n"); + "shrd_n"); return Builder.CreateAdd(Ops[0], Ops[1]); } case NEON::BI__builtin_neon_vsrad_n_u64: { llvm::ConstantInt *Amt = cast<ConstantInt>(EmitScalarExpr(E->getArg(2))); - Ops[1] = Builder.CreateLShr( - Ops[1], ConstantInt::get(Int64Ty, std::min(static_cast<uint64_t>(63), - Amt->getZExtValue())), - "vshr_n"); + uint64_t ShiftAmt = Amt->getZExtValue(); + // Right-shifting an unsigned value by its size yields 0. + // As Op + 0 = Op, return Ops[0] directly. + if (ShiftAmt == 64) + return Ops[0]; + Ops[1] = Builder.CreateLShr(Ops[1], ConstantInt::get(Int64Ty, ShiftAmt), + "shrd_n"); return Builder.CreateAdd(Ops[0], Ops[1]); } case NEON::BI__builtin_neon_vqdmlalh_lane_s16: |