From 2e470e03b49f1d79ebc315ca9d62a690a633c0cd Mon Sep 17 00:00:00 2001 From: Albion Fung Date: Thu, 28 Jan 2021 15:17:18 -0500 Subject: [PATCH] [PowerPC][Power10] Fix XXSPLI32DX not correctly exploiting specific cases Some cases may be transformed into 32 bit splats before hitting the boolean statement, which may cause incorrect behaviour and provide XXSPLTI32DX with the incorrect values of splat. The condition was reversed so that the shortcut prevents this problem. Differential Revision: https://reviews.llvm.org/D95634 --- llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 11 +++++++---- llvm/test/CodeGen/PowerPC/p10-splatImm32.ll | 16 ++-------------- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index 663ee15db11e..929a72ac687e 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -8604,16 +8604,19 @@ SDValue PPCTargetLowering::LowerBUILD_VECTOR(SDValue Op, // If it is a splat of a double, check if we can shrink it to a 32 bit // non-denormal float which when converted back to double gives us the same - // double. This is to exploit the XXSPLTIDP instruction.+ // If we lose precision, we use XXSPLTI32DX. + // double. This is to exploit the XXSPLTIDP instruction. + // If we lose precision, we use XXSPLTI32DX. if (BVNIsConstantSplat && (SplatBitSize == 64) && Subtarget.hasPrefixInstrs()) { - if (convertToNonDenormSingle(APSplatBits) && - (Op->getValueType(0) == MVT::v2f64)) { + // Check the type first to short-circuit so we don't modify APSplatBits if + // this block isn't executed. + if ((Op->getValueType(0) == MVT::v2f64) && + convertToNonDenormSingle(APSplatBits)) { SDValue SplatNode = DAG.getNode( PPCISD::XXSPLTI_SP_TO_DP, dl, MVT::v2f64, DAG.getTargetConstant(APSplatBits.getZExtValue(), dl, MVT::i32)); return DAG.getBitcast(Op.getValueType(), SplatNode); - } else if (APSplatBits.getBitWidth() == 64) { + } else { // We may lose precision, so we have to use XXSPLTI32DX. uint32_t Hi = diff --git a/llvm/test/CodeGen/PowerPC/p10-splatImm32.ll b/llvm/test/CodeGen/PowerPC/p10-splatImm32.ll index 081cae729acf..ce4c2da24b0d 100644 --- a/llvm/test/CodeGen/PowerPC/p10-splatImm32.ll +++ b/llvm/test/CodeGen/PowerPC/p10-splatImm32.ll @@ -101,23 +101,11 @@ entry: ret <8 x i16> } -define dso_local <16 x i8> @test_xxsplti32dx_10() { -; CHECK-LABEL: test_xxsplti32dx_10: -; CHECK: # %bb.0: # %entry -; CHECK-NEXT: xxlxor vs34, vs34, vs34 -; CHECK-NEXT: xxsplti32dx vs34, 0, 1207959552 -; CHECK-NEXT: blr -entry: - ret <16 x i8> -} - -; FIXME: It appears that there is something wrong with the computation -; of the 64-bit constant to splat so we cannot emit xxsplti32dx for -; this test case for now. define dso_local <16 x i8> @constSplatBug() { ; CHECK-LABEL: constSplatBug: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: plxv vs34, .LCPI10_0@PCREL(0), 1 +; CHECK-NEXT: xxlxor vs34, vs34, vs34 +; CHECK-NEXT: xxsplti32dx vs34, 0, 1191182336 ; CHECK-NEXT: blr entry: ret <16 x i8>