diff --git a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp index 12fe28b29e5c8..89c3801dc203e 100644 --- a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp +++ b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp @@ -836,6 +836,24 @@ unsigned GISelValueTracking::computeNumSignBits(Register R, return TyBits - 1; // Every always-zero bit is a sign bit. break; } + case TargetOpcode::G_BUILD_VECTOR: { + // Collect the known bits that are shared by every demanded vector element. + FirstAnswer = TyBits; + APInt SingleDemandedElt(1, 1); + for (unsigned i = 0, e = MI.getNumOperands() - 1; i < e; ++i) { + if (!DemandedElts[i]) + continue; + + unsigned Tmp2 = computeNumSignBits(MI.getOperand(i + 1).getReg(), + SingleDemandedElt, Depth + 1); + FirstAnswer = std::min(FirstAnswer, Tmp2); + + // If we don't know any bits, early out. + if (FirstAnswer == 1) + break; + } + break; + } case TargetOpcode::G_INTRINSIC: case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS: case TargetOpcode::G_INTRINSIC_CONVERGENT: diff --git a/llvm/test/CodeGen/AArch64/aarch64-dup-ext.ll b/llvm/test/CodeGen/AArch64/aarch64-dup-ext.ll index c7a423f2e4f8d..b0d30d89e1e6a 100644 --- a/llvm/test/CodeGen/AArch64/aarch64-dup-ext.ll +++ b/llvm/test/CodeGen/AArch64/aarch64-dup-ext.ll @@ -312,15 +312,14 @@ define <4 x i32> @nonsplat_shuffleinsert2(<4 x i16> %b, i16 %b0, i16 %b1, i16 %b ; CHECK-GI-LABEL: nonsplat_shuffleinsert2: ; CHECK-GI: // %bb.0: // %entry ; CHECK-GI-NEXT: sxth w8, w0 -; CHECK-GI-NEXT: sshll v0.4s, v0.4h, #0 -; CHECK-GI-NEXT: mov v1.s[0], w8 -; CHECK-GI-NEXT: sxth w8, w1 -; CHECK-GI-NEXT: mov v1.s[1], w8 +; CHECK-GI-NEXT: sxth w9, w1 +; CHECK-GI-NEXT: fmov s1, w8 ; CHECK-GI-NEXT: sxth w8, w2 -; CHECK-GI-NEXT: mov v1.s[2], w8 +; CHECK-GI-NEXT: mov v1.h[1], w9 +; CHECK-GI-NEXT: mov v1.h[2], w8 ; CHECK-GI-NEXT: sxth w8, w3 -; CHECK-GI-NEXT: mov v1.s[3], w8 -; CHECK-GI-NEXT: mul v0.4s, v1.4s, v0.4s +; CHECK-GI-NEXT: mov v1.h[3], w8 +; CHECK-GI-NEXT: smull v0.4s, v1.4h, v0.4h ; CHECK-GI-NEXT: ret entry: %s0 = sext i16 %b0 to i32 diff --git a/llvm/unittests/CodeGen/GlobalISel/KnownBitsVectorTest.cpp b/llvm/unittests/CodeGen/GlobalISel/KnownBitsVectorTest.cpp index d3a619337ae97..67e6d140a445f 100644 --- a/llvm/unittests/CodeGen/GlobalISel/KnownBitsVectorTest.cpp +++ b/llvm/unittests/CodeGen/GlobalISel/KnownBitsVectorTest.cpp @@ -692,7 +692,7 @@ TEST_F(AArch64GISelMITest, TestVectorNumSignBitsConstant) { EXPECT_EQ(2u, Info.computeNumSignBits(CopyReg32)); EXPECT_EQ(3u, Info.computeNumSignBits(CopyRegNeg32)); EXPECT_EQ(3u, Info.computeNumSignBits(NonSplatSameSign)); - EXPECT_EQ(1u, Info.computeNumSignBits(NonSplatDifferentSign)); + EXPECT_EQ(2u, Info.computeNumSignBits(NonSplatDifferentSign)); } TEST_F(AArch64GISelMITest, TestVectorNumSignBitsSext) {