Index: lib/Target/Mips/MipsMSAInstrInfo.td =================================================================== --- lib/Target/Mips/MipsMSAInstrInfo.td +++ lib/Target/Mips/MipsMSAInstrInfo.td @@ -180,8 +180,26 @@ def vsplati32 : PatFrag<(ops node:$e0), (v4i32 (build_vector node:$e0, node:$e0, node:$e0, node:$e0))>; + +def vsplati64_imm_eq_1 : PatLeaf<(bitconvert (v4i32 (build_vector))), [{ + APInt Imm; + SDNode *BV = N->getOperand(0).getNode(); + EVT EltTy = N->getValueType(0).getVectorElementType(); + + return selectVSplat(BV, Imm, EltTy.getSizeInBits()) && + Imm.getBitWidth() == EltTy.getSizeInBits() && Imm == 1; +}]>; + def vsplati64 : PatFrag<(ops node:$e0), (v2i64 (build_vector node:$e0, node:$e0))>; + +def vsplati64_splat_d : PatFrag<(ops node:$e0), + (v2i64 (bitconvert + (v4i32 (and + (v4i32 (build_vector node:$e0, node:$e0, + node:$e0, node:$e0)), + vsplati64_imm_eq_1))))>; + def vsplatf32 : PatFrag<(ops node:$e0), (v4f32 (build_vector node:$e0, node:$e0, node:$e0, node:$e0))>; @@ -195,7 +213,8 @@ def vsplati32_elt : PatFrag<(ops node:$v, node:$i), (MipsVSHF (vsplati32 node:$i), node:$v, node:$v)>; def vsplati64_elt : PatFrag<(ops node:$v, node:$i), - (MipsVSHF (vsplati64 node:$i), node:$v, node:$v)>; + (MipsVSHF (vsplati64_splat_d node:$i), + node:$v, node:$v)>; class SplatPatLeaf @@ -326,15 +345,6 @@ Imm.getBitWidth() == EltTy.getSizeInBits() && Imm == 1; }]>; -def vsplati64_imm_eq_1 : PatLeaf<(bitconvert (v4i32 (build_vector))), [{ - APInt Imm; - SDNode *BV = N->getOperand(0).getNode(); - EVT EltTy = N->getValueType(0).getVectorElementType(); - - return selectVSplat(BV, Imm, EltTy.getSizeInBits()) && - Imm.getBitWidth() == EltTy.getSizeInBits() && Imm == 1; -}]>; - def vbclr_b : PatFrag<(ops node:$ws, node:$wt), (and node:$ws, (xor (shl vsplat_imm_eq_1, node:$wt), immAllOnesV))>; Index: lib/Target/Mips/MipsSEISelLowering.cpp =================================================================== --- lib/Target/Mips/MipsSEISelLowering.cpp +++ lib/Target/Mips/MipsSEISelLowering.cpp @@ -1343,7 +1343,16 @@ SDValue LaneB; if (ResVecTy == MVT::v2i64) { - LaneB = DAG.getConstant(0, DL, MVT::i32); + // In case of index passed as an immediate value, set the upper lane to 0 + // so that the splati.d instruction can be matched. + if (isa(LaneA)) + LaneB = DAG.getConstant(0, DL, MVT::i32); + // Having the index passed in a register, set the upper lane to the same + // value as the lower - this results in the BUILD_VECTOR node not being + // expanded through stack. This way we are able to pattern match the set of + // nodes created here to splat.d. + else + LaneB = LaneA; ViaVecTy = MVT::v4i32; if(BigEndian) std::swap(LaneA, LaneB); Index: test/CodeGen/Mips/msa/3r_splat.ll =================================================================== --- test/CodeGen/Mips/msa/3r_splat.ll +++ test/CodeGen/Mips/msa/3r_splat.ll @@ -1,9 +1,9 @@ ; Test the MSA splat intrinsics that are encoded with the 3R instruction ; format. -; RUN: llc -march=mips -mattr=+msa,+fp64 -relocation-model=pic < %s | \ +; RUN: llc -march=mips -mcpu=mips32r5 -mattr=+msa,+fp64 -relocation-model=pic < %s | \ ; RUN: FileCheck -check-prefix=MIPS32 %s -; RUN: llc -march=mipsel -mattr=+msa,+fp64 -relocation-model=pic < %s | \ +; RUN: llc -march=mipsel -mcpu=mips32r5 -mattr=+msa,+fp64 -relocation-model=pic < %s | \ ; RUN: FileCheck -check-prefix=MIPS32 %s @llvm_mips_splat_b_ARG1 = global <16 x i8> , align 16 @@ -83,14 +83,11 @@ declare <2 x i64> @llvm.mips.splat.d(<2 x i64>, i32) nounwind ; MIPS32: llvm_mips_splat_d_test: -; FIXME: This test is currently disabled for MIPS32 because the indices are -; difficult to match. This is because 64-bit values cannot be stored in -; GPR32. -; MIPS64-DAG: lw [[R1:\$[0-9]+]], %got(llvm_mips_splat_d_ARG1)( -; MIPS64-DAG: lw [[R2:\$[0-9]+]], %got(llvm_mips_splat_d_RES)( -; MIPS64-DAG: ld.d [[R3:\$w[0-9]+]], 0([[R1]]) -; MIPS64-DAG: splat.d [[R4:\$w[0-9]+]], [[R3]][$4] -; MIPS64-DAG: st.d [[R4]], 0([[R2]]) +; MIPS32-DAG: lw [[R1:\$[0-9]+]], %got(llvm_mips_splat_d_ARG1)( +; MIPS32-DAG: lw [[R2:\$[0-9]+]], %got(llvm_mips_splat_d_RES)( +; MIPS32-DAG: ld.d [[R3:\$w[0-9]+]], 0([[R1]]) +; MIPS32-DAG: splat.d [[R4:\$w[0-9]+]], [[R3]][$4] +; MIPS32-DAG: st.d [[R4]], 0([[R2]]) ; MIPS32: .size llvm_mips_splat_d_test define void @llvm_mips_splat_d_arg_test(i32 %arg) { @@ -99,10 +96,15 @@ 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]], {{.*}} +; MIPS32-LABEL: llvm_mips_splat_d_arg_test +; MIPS32-DAG: lw [[R0:\$[0-9]+]], %got( +; MIPS32-DAG: addiu [[R1:\$[0-9]+]], [[R0]], %lo( +; MIPS32-DAG: lw [[R2:\$[0-9]+]], %got(llvm_mips_splat_d_RES)( +; MIPS32-DAG: ld.d [[R3:\$w[0-9]+]], 0([[R1]]) +; MIPS32-DAG: splat.d [[R4:\$w[0-9]+]], [[R3]][$4] +; MIPS32-DAG: st.d [[R4]], 0([[R2]]) +; MIPS32-NOT: vshf.d +; MIPS32: .size llvm_mips_splat_d_arg_test define void @llvm_mips_splat_d_imm_test() { entry: @@ -110,6 +112,12 @@ 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 +; MIPS32-LABEL: llvm_mips_splat_d_imm_test +; MIPS32-DAG: lw [[R0:\$[0-9]+]], %got( +; MIPS32-DAG: addiu [[R1:\$[0-9]+]], [[R0]], %lo( +; MIPS32-DAG: lw [[R2:\$[0-9]+]], %got(llvm_mips_splat_d_RES)( +; MIPS32-DAG: ld.d [[R3:\$w[0-9]+]], 0([[R1]]) +; MIPS32-DAG: splati.d [[R4:\$w[0-9]+]], [[R3]][0] +; MIPS32-DAG: st.d [[R4]], 0([[R2]]) +; MIPS32-NOT: vshf.d +; MIPS32: .size llvm_mips_splat_d_imm_test