diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index 0f8e5e57c58b7..54a78900c5ecc 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -9580,6 +9580,37 @@ static bool isValidSplatLoad(const PPCSubtarget &Subtarget, const SDValue &Op, return false; } +bool isValidMtVsrBmi(APInt &BitMask, BuildVectorSDNode &BVN) { + unsigned int NumOps = BVN.getNumOperands(); + assert(NumOps > 0 && "Unexpected 0-size build vector"); + + BitMask.clearAllBits(); + EVT VT = BVN.getValueType(0); + APInt ConstValue(VT.getSizeInBits(), 0); + + unsigned EltWidth = VT.getScalarSizeInBits(); + + unsigned BitPos = 0; + for (auto OpVal : BVN.op_values()) { + auto *CN = dyn_cast(OpVal); + + if (!CN) + return false; + + ConstValue.insertBits(CN->getAPIntValue().zextOrTrunc(EltWidth), BitPos); + BitPos += EltWidth; + } + + for (unsigned J = 0; J < 16; ++J) { + APInt ExtractValue = ConstValue.extractBits(8, J * 8); + if (ExtractValue != 0x00 && ExtractValue != 0xFF) + return false; + if (ExtractValue == 0xFF) + BitMask.setBit(J); + } + return true; +} + // If this is a case we can't handle, return null and let the default // expansion code take care of it. If we CAN select this case, and if it // selects to a single instruction, return Op. Otherwise, if we can codegen @@ -9591,6 +9622,25 @@ SDValue PPCTargetLowering::LowerBUILD_VECTOR(SDValue Op, BuildVectorSDNode *BVN = dyn_cast(Op.getNode()); assert(BVN && "Expected a BuildVectorSDNode in LowerBUILD_VECTOR"); + if (Subtarget.hasP10Vector()) { + APInt BitMask(32, 0); + // If the value of the vector is all zeros or all ones, + // we do not convert it to MTVSRBMI. + // The xxleqv instruction sets a vector with all ones. + // The xxlxor instruction sets a vector with all zeros. + if (isValidMtVsrBmi(BitMask, *BVN) && BitMask != 0 && BitMask != 0xffff) { + SDValue SDConstant = DAG.getTargetConstant(BitMask, dl, MVT::i32); + MachineSDNode *MSDNode = + DAG.getMachineNode(PPC::MTVSRBMI, dl, MVT::v16i8, SDConstant); + SDValue SDV = SDValue(MSDNode, 0); + EVT DVT = BVN->getValueType(0); + EVT SVT = SDV.getValueType(); + if (SVT != DVT) { + SDV = DAG.getNode(ISD::BITCAST, dl, DVT, SDV); + } + return SDV; + } + } // Check if this is a splat of a constant value. APInt APSplatBits, APSplatUndef; unsigned SplatBitSize; diff --git a/llvm/test/CodeGen/PowerPC/mtvsrbmi.ll b/llvm/test/CodeGen/PowerPC/mtvsrbmi.ll index 5486dc02faf90..232014db9a012 100644 --- a/llvm/test/CodeGen/PowerPC/mtvsrbmi.ll +++ b/llvm/test/CodeGen/PowerPC/mtvsrbmi.ll @@ -10,28 +10,13 @@ ; RUN: | FileCheck %s --check-prefix=CHECK define dso_local noundef range(i8 -1, 1) <16 x i8> @_Z5v00FFv() { -; CHECK: L..CPI0_0: -; CHECK-NEXT: .byte 255 # 0xff -; CHECK-NEXT: .byte 0 # 0x0 -; CHECK-NEXT: .byte 0 # 0x0 -; CHECK-NEXT: .byte 0 # 0x0 -; CHECK-NEXT: .byte 0 # 0x0 -; CHECK-NEXT: .byte 0 # 0x0 -; CHECK-NEXT: .byte 0 # 0x0 -; CHECK-NEXT: .byte 0 # 0x0 -; CHECK-NEXT: .byte 0 # 0x0 -; CHECK-NEXT: .byte 0 # 0x0 -; CHECK-NEXT: .byte 0 # 0x0 -; CHECK-NEXT: .byte 0 # 0x0 -; CHECK-NEXT: .byte 0 # 0x0 -; CHECK-NEXT: .byte 0 # 0x0 -; CHECK-NEXT: .byte 0 # 0x0 -; CHECK-NEXT: .byte 0 # 0x0 +; CHECK-NOT: L..CPI0_0: +; CHECK-NOT: .byte 255 # 0xff +; CHECK-NOT: .byte 0 # 0x0 ; CHECK-LABEL: _Z5v00FFv: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: lwz r3, L..C0(r2) # %const.0 -; CHECK-NEXT: lxv vs34, 0(r3) +; CHECK-NEXT: mtvsrbmi v2, 1 ; CHECK-NEXT: blr entry: ret <16 x i8>