From: Stefan Maksimovic Date: Fri, 23 Jun 2017 09:09:31 +0000 (+0000) Subject: [mips][msa] Splat.d endianness check X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=bc1000f7b06448f49bf05ed90c3c6384947570ce;p=llvm [mips][msa] Splat.d endianness check Before this change, it was always the first element of a vector that got splatted since the lower 6 bits of vshf.d $wd were always zero for little endian. Additionally, masking has been performed for vshf via which splat.d is created. Vshf has a property where if its first operand's elements have either bit 6 or 7 set, destination element is set to zero. Initially masked with 63 to avoid this property, which would result in generation of and.v + vshf.d in all cases. Masking with one results in generating a single splati.d instruction when possible. Differential Revision: https://reviews.llvm.org/D32216 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@306090 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/Mips/MipsSEISelLowering.cpp b/lib/Target/Mips/MipsSEISelLowering.cpp index 2382ea27166..b57bceb3c83 100644 --- a/lib/Target/Mips/MipsSEISelLowering.cpp +++ b/lib/Target/Mips/MipsSEISelLowering.cpp @@ -1257,19 +1257,22 @@ static SDValue lowerMSACopyIntr(SDValue Op, SelectionDAG &DAG, unsigned Opc) { static SDValue lowerMSASplatZExt(SDValue Op, unsigned OpNr, SelectionDAG &DAG) { EVT ResVecTy = Op->getValueType(0); EVT ViaVecTy = ResVecTy; + bool BigEndian = !DAG.getSubtarget().getTargetTriple().isLittleEndian(); SDLoc DL(Op); // When ResVecTy == MVT::v2i64, LaneA is the upper 32 bits of the lane and // LaneB is the lower 32-bits. Otherwise LaneA and LaneB are alternating // lanes. - SDValue LaneA; - SDValue LaneB = Op->getOperand(2); + SDValue LaneA = Op->getOperand(OpNr); + SDValue LaneB; if (ResVecTy == MVT::v2i64) { - LaneA = DAG.getConstant(0, DL, MVT::i32); + LaneB = DAG.getConstant(0, DL, MVT::i32); ViaVecTy = MVT::v4i32; + if(BigEndian) + std::swap(LaneA, LaneB); } else - LaneA = LaneB; + LaneB = LaneA; SDValue Ops[16] = { LaneA, LaneB, LaneA, LaneB, LaneA, LaneB, LaneA, LaneB, LaneA, LaneB, LaneA, LaneB, LaneA, LaneB, LaneA, LaneB }; @@ -1277,8 +1280,11 @@ static SDValue lowerMSASplatZExt(SDValue Op, unsigned OpNr, SelectionDAG &DAG) { SDValue Result = DAG.getBuildVector( ViaVecTy, DL, makeArrayRef(Ops, ViaVecTy.getVectorNumElements())); - if (ViaVecTy != ResVecTy) - Result = DAG.getNode(ISD::BITCAST, DL, ResVecTy, Result); + if (ViaVecTy != ResVecTy) { + SDValue One = DAG.getConstant(1, DL, ViaVecTy); + Result = DAG.getNode(ISD::BITCAST, DL, ResVecTy, + DAG.getNode(ISD::AND, DL, ViaVecTy, Result, One)); + } return Result; } diff --git a/test/CodeGen/Mips/msa/3r_splat.ll b/test/CodeGen/Mips/msa/3r_splat.ll index 78c485f4f86..a5f4999f852 100644 --- a/test/CodeGen/Mips/msa/3r_splat.ll +++ b/test/CodeGen/Mips/msa/3r_splat.ll @@ -92,3 +92,24 @@ declare <2 x i64> @llvm.mips.splat.d(<2 x i64>, i32) nounwind ; MIPS64-DAG: splat.d [[R4:\$w[0-9]+]], [[R3]][$4] ; MIPS64-DAG: st.d [[R4]], 0([[R2]]) ; MIPS32: .size llvm_mips_splat_d_test + +define void @llvm_mips_splat_d_arg_test(i32 %arg) { +entry: + %0 = tail call <2 x i64> @llvm.mips.splat.d(<2 x i64> , i32 %arg) + store volatile <2 x i64> %0, <2 x i64>* @llvm_mips_splat_d_RES + ret void +} +; CHECK-LABEL: llvm_mips_splat_d_arg_test +; CHECK: ldi.w [[R1:\$w[0-9]+]], 1 +; CHECK: and.v [[R2:\$w[0-9]+]], {{\$w[0-9]+}}, [[R1]] +; CHECK: vshf.d [[R2]], {{.*}} + +define void @llvm_mips_splat_d_imm_test() { +entry: + %0 = tail call <2 x i64> @llvm.mips.splat.d(<2 x i64> , i32 76) + store volatile<2 x i64> %0, <2 x i64>* @llvm_mips_splat_d_RES + ret void +} +; CHECK-LABEL: llvm_mips_splat_d_imm_test +; CHECK: splati. d {{.*}}, {{.*}}[0] +; CHECK-NOT: vshf.d