Index: lib/CodeGen/CGBuiltin.cpp =================================================================== --- lib/CodeGen/CGBuiltin.cpp +++ lib/CodeGen/CGBuiltin.cpp @@ -5580,38 +5580,41 @@ case NEON::BI__builtin_neon_vshld_n_u64: { llvm::ConstantInt *Amt = cast(EmitScalarExpr(E->getArg(1))); return Builder.CreateShl( - Ops[0], ConstantInt::get(Int64Ty, std::min(static_cast(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(EmitScalarExpr(E->getArg(1))); return Builder.CreateAShr( Ops[0], ConstantInt::get(Int64Ty, std::min(static_cast(63), Amt->getZExtValue())), - "vshr_n"); + "shrd_n"); } case NEON::BI__builtin_neon_vshrd_n_u64: { llvm::ConstantInt *Amt = cast(EmitScalarExpr(E->getArg(1))); - return Builder.CreateLShr( - Ops[0], ConstantInt::get(Int64Ty, std::min(static_cast(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(EmitScalarExpr(E->getArg(2))); Ops[1] = Builder.CreateAShr( Ops[1], ConstantInt::get(Int64Ty, std::min(static_cast(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(EmitScalarExpr(E->getArg(2))); - Ops[1] = Builder.CreateLShr( - Ops[1], ConstantInt::get(Int64Ty, std::min(static_cast(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: Index: test/CodeGen/aarch64-neon-intrinsics.c =================================================================== --- test/CodeGen/aarch64-neon-intrinsics.c +++ test/CodeGen/aarch64-neon-intrinsics.c @@ -8572,11 +8572,24 @@ } 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 @@ 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