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 | |
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')
-rw-r--r-- | clang/lib/CodeGen/CGBuiltin.cpp | 29 | ||||
-rw-r--r-- | clang/test/CodeGen/aarch64-neon-intrinsics.c | 26 |
2 files changed, 40 insertions, 15 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: diff --git a/clang/test/CodeGen/aarch64-neon-intrinsics.c b/clang/test/CodeGen/aarch64-neon-intrinsics.c index e7fa048881f..83214f1f3ed 100644 --- a/clang/test/CodeGen/aarch64-neon-intrinsics.c +++ b/clang/test/CodeGen/aarch64-neon-intrinsics.c @@ -8572,11 +8572,24 @@ int64x1_t test_vshr_n_s64(int64x1_t a) { } uint64_t test_vshrd_n_u64(uint64_t a) { -// CHECK-LABEL: test_vshrd_n_u64 -// CHECK: {{ushr d[0-9]+, d[0-9]+, #64|lsr x0, x0, #63}} +// CHECK-AARCH64-LABEL: test_vshrd_n_u64 +// CHECK-AARCH64: {{ushr d[0-9]+, d[0-9]+, #64}} + +// CHECK-ARM64-LABEL: test_vshrd_n_u64 +// CHECK-ARM64: mov x0, xzr return (uint64_t)vshrd_n_u64(a, 64); } +uint64_t test_vshrd_n_u64_2() { +// CHECK-AARCH64-LABEL: test_vshrd_n_u64_2 +// CHECK-AARCH64: {{ushr d[0-9]+, d[0-9]+, #64}} + +// CHECK-ARM64-LABEL: test_vshrd_n_u64_2 +// CHECK-ARM64: mov x0, xzr + uint64_t a = UINT64_C(0xf000000000000000); + return vshrd_n_u64(a, 64); +} + uint64x1_t test_vshr_n_u64(uint64x1_t a) { // CHECK-LABEL: test_vshr_n_u64 // CHECK: ushr {{d[0-9]+}}, {{d[0-9]+}}, #1 @@ -8625,6 +8638,15 @@ uint64_t test_vsrad_n_u64(uint64_t a, uint64_t b) { return (uint64_t)vsrad_n_u64(a, b, 63); } +uint64_t test_vsrad_n_u64_2(uint64_t a, uint64_t b) { +// CHECK-AARCH64-LABEL: test_vsrad_n_u64_2 +// CHECK-AARCH64: {{usra d[0-9]+, d[0-9]+, #64}} + +// CHECK-ARM64-LABEL: test_vsrad_n_u64_2 +// CHECK-ARM64-NOT: add + return (uint64_t)vsrad_n_u64(a, b, 64); +} + uint64x1_t test_vsra_n_u64(uint64x1_t a, uint64x1_t b) { // CHECK-LABEL: test_vsra_n_u64 // CHECK: usra d{{[0-9]+}}, d{{[0-9]+}}, #1 |