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