Index: lib/Target/Mips/MipsSEISelLowering.cpp =================================================================== --- lib/Target/Mips/MipsSEISelLowering.cpp +++ lib/Target/Mips/MipsSEISelLowering.cpp @@ -1547,11 +1547,53 @@ return DAG.getNode(Opc, DL, VecTy, Op->getOperand(1), Exp2Imm); } +static bool isConstantOrUndef(const SDValue Op) { + if (Op->isUndef()) + return true; + if (isa(Op)) + return true; + if (isa(Op)) + return true; + return false; +} + +static bool isAllConstantOrUndefBUILD_VECTOR(const BuildVectorSDNode *Op) { + for (unsigned i = 0; i < Op->getNumOperands(); ++i) + if (!(isConstantOrUndef(Op->getOperand(i)))) + return false; + return true; +} + +SDValue truncateVecElts(SDValue Op, SelectionDAG &DAG) { + SDLoc DL(Op); + SDValue Output[16]; + SDValue Vec = Op->getOperand(2); + BuildVectorSDNode *Node = dyn_cast(Vec); + if(Node && isAllConstantOrUndefBUILD_VECTOR(Node)) { + unsigned i; + EVT VecValTy = Node->getValueType(0); + unsigned VecEltSize = VecValTy.getScalarType().getSizeInBits(); + for (i = 0; i < Node->getNumOperands(); ++i) { + SDValue Elt; + EVT EltValTy = Node->getOperand(i)->getValueType(0); + if(Node->isUndef()) + Elt = DAG.getConstant(0, DL, EltValTy); + else { + uint64_t ConstValue = Node->getConstantOperandVal(i); + Elt = DAG.getConstant(ConstValue % VecEltSize, DL, EltValTy); + } + Output[i] = Elt; + } + return DAG.getBuildVector(VecValTy, DL, makeArrayRef(Output, i)); + } + return Vec; +} + static SDValue lowerMSABitClear(SDValue Op, SelectionDAG &DAG) { EVT ResTy = Op->getValueType(0); SDLoc DL(Op); SDValue One = DAG.getConstant(1, DL, ResTy); - SDValue Bit = DAG.getNode(ISD::SHL, DL, ResTy, One, Op->getOperand(2)); + SDValue Bit = DAG.getNode(ISD::SHL, DL, ResTy, One, truncateVecElts(Op, DAG)); return DAG.getNode(ISD::AND, DL, ResTy, Op->getOperand(1), DAG.getNOT(DL, Bit, ResTy)); @@ -1687,7 +1729,7 @@ return DAG.getNode(ISD::XOR, DL, VecTy, Op->getOperand(1), DAG.getNode(ISD::SHL, DL, VecTy, One, - Op->getOperand(2))); + truncateVecElts(Op, DAG))); } case Intrinsic::mips_bnegi_b: case Intrinsic::mips_bnegi_h: @@ -1723,7 +1765,7 @@ return DAG.getNode(ISD::OR, DL, VecTy, Op->getOperand(1), DAG.getNode(ISD::SHL, DL, VecTy, One, - Op->getOperand(2))); + truncateVecElts(Op, DAG))); } case Intrinsic::mips_bseti_b: case Intrinsic::mips_bseti_h: @@ -2210,7 +2252,7 @@ case Intrinsic::mips_sll_w: case Intrinsic::mips_sll_d: return DAG.getNode(ISD::SHL, DL, Op->getValueType(0), Op->getOperand(1), - Op->getOperand(2)); + truncateVecElts(Op, DAG)); case Intrinsic::mips_slli_b: case Intrinsic::mips_slli_h: case Intrinsic::mips_slli_w: @@ -2240,7 +2282,7 @@ case Intrinsic::mips_sra_w: case Intrinsic::mips_sra_d: return DAG.getNode(ISD::SRA, DL, Op->getValueType(0), Op->getOperand(1), - Op->getOperand(2)); + truncateVecElts(Op, DAG)); case Intrinsic::mips_srai_b: case Intrinsic::mips_srai_h: case Intrinsic::mips_srai_w: @@ -2270,7 +2312,7 @@ case Intrinsic::mips_srl_w: case Intrinsic::mips_srl_d: return DAG.getNode(ISD::SRL, DL, Op->getValueType(0), Op->getOperand(1), - Op->getOperand(2)); + truncateVecElts(Op, DAG)); case Intrinsic::mips_srli_b: case Intrinsic::mips_srli_h: case Intrinsic::mips_srli_w: @@ -2480,16 +2522,6 @@ return Op; } -static bool isConstantOrUndef(const SDValue Op) { - if (Op->isUndef()) - return true; - if (isa(Op)) - return true; - if (isa(Op)) - return true; - return false; -} - static bool isConstantOrUndefBUILD_VECTOR(const BuildVectorSDNode *Op) { for (unsigned i = 0; i < Op->getNumOperands(); ++i) if (isConstantOrUndef(Op->getOperand(i))) Index: test/CodeGen/Mips/msa/shift_constant_pool.ll =================================================================== --- test/CodeGen/Mips/msa/shift_constant_pool.ll +++ test/CodeGen/Mips/msa/shift_constant_pool.ll @@ -0,0 +1,156 @@ +; Test whether the following functions, with vectors featuring negative or values larger than the element +; bit size have their results of operations generated correctly when placed into constant pools + +; RUN: llc -march=mips64el -mattr=+msa,+fp64 -relocation-model=pic < %s | FileCheck -check-prefix=CHECK-ALL -check-prefix=MIPS64 %s +; RUN: llc -march=mipsel -mattr=+msa,+fp64 -relocation-model=pic < %s | FileCheck -check-prefix=CHECK-ALL -check-prefix=MIPS32 %s + +@llvm_mips_sll_w_test_const_vec_res = global <4 x i32> zeroinitializer, align 16 + +define i32 @llvm_mips_sll_w_test_const_vec() nounwind { +entry: + %0 = tail call <4 x i32> @llvm.mips.sll.w(<4 x i32> , <4 x i32> ) + store <4 x i32> %0, <4 x i32>* @llvm_mips_sll_w_test_const_vec_res + ret i32 0 +} + +declare <4 x i32> @llvm.mips.sll.w(<4 x i32>, <4 x i32>) nounwind + +; MIPS32: [[LABEL:\$CPI[0-9]+_[0-9]+]]: +; MIPS64: [[LABEL:\.LCPI[0-9]+_[0-9]+]]: +; CHECK-ALL: .4byte 2147483648 # 0x80000000 +; CHECK-ALL: .4byte 2147483648 # 0x80000000 +; CHECK-ALL: .4byte 4 # 0x4 +; CHECK-ALL: .4byte 4 # 0x4 +; CHECK-ALL: llvm_mips_sll_w_test_const_vec: +; MIPS32: lw $[[R2:[0-9]+]], %got([[LABEL]])($[[R1:[0-9]+]]) +; MIPS32: addiu $[[R2]], $[[R2]], %lo([[LABEL]]) +; MIPS32: lw $[[R3:[0-9]+]], %got(llvm_mips_sll_w_test_const_vec_res)($[[R1]]) +; MIPS64: ld $[[R2:[0-9]+]], %got_page([[LABEL]])($[[R1:[0-9]+]]) +; MIPS64: daddiu $[[R2]], $[[R2]], %got_ofst([[LABEL]]) +; MIPS64: ld $[[R3:[0-9]+]], %got_disp(llvm_mips_sll_w_test_const_vec_res)($[[R1]]) +; CHECK-ALL: ld.w $w0, 0($[[R2]]) +; CHECK-ALL: st.w $w0, 0($[[R3]]) +; CHECK-ALL: .end llvm_mips_sll_w_test_const_vec +; +@llvm_mips_sll_d_test_const_vec_res = global <2 x i64> zeroinitializer, align 16 + +define i32 @llvm_mips_sll_d_test_const_vec() nounwind { +entry: + %0 = tail call <2 x i64> @llvm.mips.sll.d(<2 x i64> , <2 x i64> ) + store <2 x i64> %0, <2 x i64>* @llvm_mips_sll_d_test_const_vec_res + ret i32 0 +} + +declare <2 x i64> @llvm.mips.sll.d(<2 x i64>, <2 x i64>) nounwind + +; MIPS64: [[LABEL:\.LCPI[0-9]+_[0-9]+]]: +; MIPS64: .8byte -9223372036854775808 # 0x8000000000000000 +; MIPS64: .8byte 2 # 0x2 +; CHECK-ALL: llvm_mips_sll_d_test_const_vec: +; MIPS64: ld $[[R2:[0-9]+]], %got_page([[LABEL]])($[[R1:[0-9]+]]) +; MIPS64: daddiu $[[R2]], $[[R2]], %got_ofst([[LABEL]]) +; MIPS64: ld $[[R3:[0-9]+]], %got_disp(llvm_mips_sll_d_test_const_vec_res)($[[R1]]) +; MIPS64: ld.d $w0, 0($[[R2]]) +; MIPS64: st.d $w0, 0($[[R3]]) +; CHECK-ALL: .end llvm_mips_sll_d_test_const_vec +; +@llvm_mips_srl_w_test_const_vec_res = global <4 x i32> zeroinitializer, align 16 + +define i32 @llvm_mips_srl_w_test_const_vec() nounwind { +entry: + %0 = tail call <4 x i32> @llvm.mips.srl.w(<4 x i32> , <4 x i32> ) + store <4 x i32> %0, <4 x i32>* @llvm_mips_srl_w_test_const_vec_res + ret i32 0 +} + +declare <4 x i32> @llvm.mips.srl.w(<4 x i32>, <4 x i32>) nounwind + +; MIPS32: [[LABEL:\$CPI[0-9]+_[0-9]+]]: +; MIPS64: [[LABEL:\.LCPI[0-9]+_[0-9]+]]: +; CHECK-ALL: .4byte 1073741820 # 0x3ffffffc +; CHECK-ALL: .4byte 4 # 0x4 +; CHECK-ALL: .4byte 8 # 0x8 +; CHECK-ALL: .4byte 8 # 0x8 +; CHECK-ALL: llvm_mips_srl_w_test_const_vec: +; MIPS32: lw $[[R2:[0-9]+]], %got([[LABEL]])($[[R1:[0-9]+]]) +; MIPS32: addiu $[[R2]], $[[R2]], %lo([[LABEL]]) +; MIPS32: lw $[[R3:[0-9]+]], %got(llvm_mips_srl_w_test_const_vec_res)($[[R1]]) +; MIPS64: ld $[[R2:[0-9]+]], %got_page([[LABEL]])($[[R1:[0-9]+]]) +; MIPS64: daddiu $[[R2]], $[[R2]], %got_ofst([[LABEL]]) +; MIPS64: ld $[[R3:[0-9]+]], %got_disp(llvm_mips_srl_w_test_const_vec_res)($[[R1]]) +; CHECK-ALL: ld.w $w0, 0($[[R2]]) +; CHECK-ALL: st.w $w0, 0($[[R3]]) +; CHECK-ALL: .end llvm_mips_srl_w_test_const_vec +; +@llvm_mips_srl_d_test_const_vec_res = global <2 x i64> zeroinitializer, align 16 + +define i32 @llvm_mips_srl_d_test_const_vec() nounwind { +entry: + %0 = tail call <2 x i64> @llvm.mips.srl.d(<2 x i64> , <2 x i64> ) + store <2 x i64> %0, <2 x i64>* @llvm_mips_srl_d_test_const_vec_res + ret i32 0 +} + +declare <2 x i64> @llvm.mips.srl.d(<2 x i64>, <2 x i64>) nounwind + +; MIPS64: [[LABEL:\.LCPI[0-9]+_[0-9]+]]: +; MIPS64: .8byte 1152921504606846974 # 0xffffffffffffffe +; MIPS64: .8byte 14 # 0xe +; CHECK-ALL: llvm_mips_srl_d_test_const_vec: +; MIPS64: ld $[[R2:[0-9]+]], %got_page([[LABEL]])($[[R1:[0-9]+]]) +; MIPS64: daddiu $[[R2]], $[[R2]], %got_ofst([[LABEL]]) +; MIPS64: ld $[[R3:[0-9]+]], %got_disp(llvm_mips_srl_d_test_const_vec_res)($[[R1]]) +; MIPS64: ld.d $w0, 0($[[R2]]) +; MIPS64: st.d $w0, 0($[[R3]]) +; CHECK-ALL: .end llvm_mips_srl_d_test_const_vec +; +@llvm_mips_sra_w_test_const_vec_res = global <4 x i32> zeroinitializer, align 16 + +define i32 @llvm_mips_sra_w_test_const_vec() nounwind { +entry: + %0 = tail call <4 x i32> @llvm.mips.sra.w(<4 x i32> , <4 x i32> ) + store <4 x i32> %0, <4 x i32>* @llvm_mips_sra_w_test_const_vec_res + ret i32 0 +} + +declare <4 x i32> @llvm.mips.sra.w(<4 x i32>, <4 x i32>) nounwind + +; MIPS32: [[LABEL:\$CPI[0-9]+_[0-9]+]]: +; MIPS64: [[LABEL:\.LCPI[0-9]+_[0-9]+]]: +; CHECK-ALL: .4byte 4294967292 # 0xfffffffc +; CHECK-ALL: .4byte 4 # 0x4 +; CHECK-ALL: .4byte 8 # 0x8 +; CHECK-ALL: .4byte 8 # 0x8 +; CHECK-ALL: llvm_mips_sra_w_test_const_vec: +; MIPS32: lw $[[R2:[0-9]+]], %got([[LABEL]])($[[R1:[0-9]+]]) +; MIPS32: addiu $[[R2]], $[[R2]], %lo([[LABEL]]) +; MIPS32: lw $[[R3:[0-9]+]], %got(llvm_mips_sra_w_test_const_vec_res)($[[R1]]) +; MIPS64: ld $[[R2:[0-9]+]], %got_page([[LABEL]])($[[R1:[0-9]+]]) +; MIPS64: daddiu $[[R2]], $[[R2]], %got_ofst([[LABEL]]) +; MIPS64: ld $[[R3:[0-9]+]], %got_disp(llvm_mips_sra_w_test_const_vec_res)($[[R1]]) +; CHECK-ALL: ld.w $w0, 0($[[R2]]) +; CHECK-ALL: st.w $w0, 0($[[R3]]) +; CHECK-ALL: .end llvm_mips_sra_w_test_const_vec +; +@llvm_mips_sra_d_test_const_vec_res = global <2 x i64> zeroinitializer, align 16 + +define i32 @llvm_mips_sra_d_test_const_vec() nounwind { +entry: + %0 = tail call <2 x i64> @llvm.mips.sra.d(<2 x i64> , <2 x i64> ) + store <2 x i64> %0, <2 x i64>* @llvm_mips_sra_d_test_const_vec_res + ret i32 0 +} + +declare <2 x i64> @llvm.mips.sra.d(<2 x i64>, <2 x i64>) nounwind + +; MIPS64: [[LABEL:\.LCPI[0-9]+_[0-9]+]]: +; MIPS64: .8byte -4 # 0xfffffffffffffffc +; MIPS64: .8byte -2 # 0xfffffffffffffffe +; MIPS64: llvm_mips_sra_d_test_const_vec: +; MIPS64: ld $[[R2:[0-9]+]], %got_page([[LABEL]])($[[R1:[0-9]+]]) +; MIPS64: daddiu $[[R2]], $[[R2]], %got_ofst([[LABEL]]) +; MIPS64: ld $[[R3:[0-9]+]], %got_disp(llvm_mips_sra_d_test_const_vec_res)($[[R1]]) +; MIPS64: ld.d $w0, 0($[[R2]]) +; MIPS64: st.d $w0, 0($[[R3]]) +; MIPS64: .end llvm_mips_sra_d_test_const_vec +;