mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-01 05:01:59 +01:00
[mips][msa] Fix generation of bm(n)zi and bins[lr]i instructions
We have two cases here, the first one being the following instruction selection from the builtin function: bm(n)zi builtin -> vselect node -> bins[lr]i machine instruction In case of bm(n)zi having an immediate which has either its high or low bits set, a bins[lr] instruction can be selected through the selectVSplatMask[LR] function. The function counts the number of bits set, and that value is being passed to the bins[lr]i instruction as its immediate, which in turn copies immediate modulo the size of the element in bits plus 1 as per specs, where we get the off-by-one-error. The other case is: bins[lr]i -> vselect node -> bsel.v In this case, a bsel.v instruction gets selected with a mask having one bit less set than required. Patch by Stefan Maksimovic. Differential Revision: https://reviews.llvm.org/D30579 llvm-svn: 299768
This commit is contained in:
parent
ab371a9d51
commit
e7b11baac1
@ -692,7 +692,7 @@ bool MipsSEDAGToDAGISel::selectVSplatMaskL(SDValue N, SDValue &Imm) const {
|
||||
// as the original value.
|
||||
if (ImmValue == ~(~ImmValue & ~(~ImmValue + 1))) {
|
||||
|
||||
Imm = CurDAG->getTargetConstant(ImmValue.countPopulation(), SDLoc(N),
|
||||
Imm = CurDAG->getTargetConstant(ImmValue.countPopulation() - 1, SDLoc(N),
|
||||
EltTy);
|
||||
return true;
|
||||
}
|
||||
@ -724,7 +724,7 @@ bool MipsSEDAGToDAGISel::selectVSplatMaskR(SDValue N, SDValue &Imm) const {
|
||||
// Extract the run of set bits starting with bit zero, and test that the
|
||||
// result is the same as the original value
|
||||
if (ImmValue == (ImmValue & ~(ImmValue + 1))) {
|
||||
Imm = CurDAG->getTargetConstant(ImmValue.countPopulation(), SDLoc(N),
|
||||
Imm = CurDAG->getTargetConstant(ImmValue.countPopulation() - 1, SDLoc(N),
|
||||
EltTy);
|
||||
return true;
|
||||
}
|
||||
|
@ -1644,7 +1644,7 @@ SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op,
|
||||
if (Op->getConstantOperandVal(3) >= EltTy.getSizeInBits())
|
||||
report_fatal_error("Immediate out of range");
|
||||
APInt Mask = APInt::getHighBitsSet(EltTy.getSizeInBits(),
|
||||
Op->getConstantOperandVal(3));
|
||||
Op->getConstantOperandVal(3) + 1);
|
||||
return DAG.getNode(ISD::VSELECT, DL, VecTy,
|
||||
DAG.getConstant(Mask, DL, VecTy, true),
|
||||
Op->getOperand(2), Op->getOperand(1));
|
||||
@ -1659,7 +1659,7 @@ SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op,
|
||||
if (Op->getConstantOperandVal(3) >= EltTy.getSizeInBits())
|
||||
report_fatal_error("Immediate out of range");
|
||||
APInt Mask = APInt::getLowBitsSet(EltTy.getSizeInBits(),
|
||||
Op->getConstantOperandVal(3));
|
||||
Op->getConstantOperandVal(3) + 1);
|
||||
return DAG.getNode(ISD::VSELECT, DL, VecTy,
|
||||
DAG.getConstant(Mask, DL, VecTy, true),
|
||||
Op->getOperand(2), Op->getOperand(1));
|
||||
|
@ -1099,7 +1099,7 @@ define void @binsl_v16i8_i(<16 x i8>* %c, <16 x i8>* %a, <16 x i8>* %b) nounwind
|
||||
i8 63, i8 63, i8 63, i8 63,
|
||||
i8 63, i8 63, i8 63, i8 63>
|
||||
%5 = or <16 x i8> %3, %4
|
||||
; CHECK-DAG: binsli.b [[R2]], [[R1]], 2
|
||||
; CHECK-DAG: binsli.b [[R2]], [[R1]], 1
|
||||
store <16 x i8> %5, <16 x i8>* %c
|
||||
; CHECK-DAG: st.b [[R2]], 0($4)
|
||||
|
||||
@ -1119,7 +1119,7 @@ define void @binsl_v8i16_i(<8 x i16>* %c, <8 x i16>* %a, <8 x i16>* %b) nounwind
|
||||
%4 = and <8 x i16> %2, <i16 16383, i16 16383, i16 16383, i16 16383,
|
||||
i16 16383, i16 16383, i16 16383, i16 16383>
|
||||
%5 = or <8 x i16> %3, %4
|
||||
; CHECK-DAG: binsli.h [[R2]], [[R1]], 2
|
||||
; CHECK-DAG: binsli.h [[R2]], [[R1]], 1
|
||||
store <8 x i16> %5, <8 x i16>* %c
|
||||
; CHECK-DAG: st.h [[R2]], 0($4)
|
||||
|
||||
@ -1137,7 +1137,7 @@ define void @binsl_v4i32_i(<4 x i32>* %c, <4 x i32>* %a, <4 x i32>* %b) nounwind
|
||||
%3 = and <4 x i32> %1, <i32 3221225472, i32 3221225472, i32 3221225472, i32 3221225472>
|
||||
%4 = and <4 x i32> %2, <i32 1073741823, i32 1073741823, i32 1073741823, i32 1073741823>
|
||||
%5 = or <4 x i32> %3, %4
|
||||
; CHECK-DAG: binsli.w [[R2]], [[R1]], 2
|
||||
; CHECK-DAG: binsli.w [[R2]], [[R1]], 1
|
||||
store <4 x i32> %5, <4 x i32>* %c
|
||||
; CHECK-DAG: st.w [[R2]], 0($4)
|
||||
|
||||
@ -1159,7 +1159,7 @@ define void @binsl_v2i64_i(<2 x i64>* %c, <2 x i64>* %a, <2 x i64>* %b) nounwind
|
||||
; issue. If the mask doesn't fit within a 10-bit immediate, it gets
|
||||
; legalized into a constant pool. We should add a test to cover the
|
||||
; other cases once they correctly select binsli.d.
|
||||
; CHECK-DAG: binsli.d [[R2]], [[R1]], 61
|
||||
; CHECK-DAG: binsli.d [[R2]], [[R1]], 60
|
||||
store <2 x i64> %5, <2 x i64>* %c
|
||||
; CHECK-DAG: st.d [[R2]], 0($4)
|
||||
|
||||
@ -1181,7 +1181,7 @@ define void @binsr_v16i8_i(<16 x i8>* %c, <16 x i8>* %a, <16 x i8>* %b) nounwind
|
||||
i8 252, i8 252, i8 252, i8 252,
|
||||
i8 252, i8 252, i8 252, i8 252>
|
||||
%5 = or <16 x i8> %3, %4
|
||||
; CHECK-DAG: binsri.b [[R2]], [[R1]], 2
|
||||
; CHECK-DAG: binsri.b [[R2]], [[R1]], 1
|
||||
store <16 x i8> %5, <16 x i8>* %c
|
||||
; CHECK-DAG: st.b [[R2]], 0($4)
|
||||
|
||||
@ -1201,7 +1201,7 @@ define void @binsr_v8i16_i(<8 x i16>* %c, <8 x i16>* %a, <8 x i16>* %b) nounwind
|
||||
%4 = and <8 x i16> %2, <i16 65532, i16 65532, i16 65532, i16 65532,
|
||||
i16 65532, i16 65532, i16 65532, i16 65532>
|
||||
%5 = or <8 x i16> %3, %4
|
||||
; CHECK-DAG: binsri.h [[R2]], [[R1]], 2
|
||||
; CHECK-DAG: binsri.h [[R2]], [[R1]], 1
|
||||
store <8 x i16> %5, <8 x i16>* %c
|
||||
; CHECK-DAG: st.h [[R2]], 0($4)
|
||||
|
||||
@ -1219,7 +1219,7 @@ define void @binsr_v4i32_i(<4 x i32>* %c, <4 x i32>* %a, <4 x i32>* %b) nounwind
|
||||
%3 = and <4 x i32> %1, <i32 3, i32 3, i32 3, i32 3>
|
||||
%4 = and <4 x i32> %2, <i32 4294967292, i32 4294967292, i32 4294967292, i32 4294967292>
|
||||
%5 = or <4 x i32> %3, %4
|
||||
; CHECK-DAG: binsri.w [[R2]], [[R1]], 2
|
||||
; CHECK-DAG: binsri.w [[R2]], [[R1]], 1
|
||||
store <4 x i32> %5, <4 x i32>* %c
|
||||
; CHECK-DAG: st.w [[R2]], 0($4)
|
||||
|
||||
@ -1237,7 +1237,7 @@ define void @binsr_v2i64_i(<2 x i64>* %c, <2 x i64>* %a, <2 x i64>* %b) nounwind
|
||||
%3 = and <2 x i64> %1, <i64 3, i64 3>
|
||||
%4 = and <2 x i64> %2, <i64 18446744073709551612, i64 18446744073709551612>
|
||||
%5 = or <2 x i64> %3, %4
|
||||
; CHECK-DAG: binsri.d [[R2]], [[R1]], 2
|
||||
; CHECK-DAG: binsri.d [[R2]], [[R1]], 1
|
||||
store <2 x i64> %5, <2 x i64>* %c
|
||||
; CHECK-DAG: st.d [[R2]], 0($4)
|
||||
|
||||
|
55
test/CodeGen/Mips/msa/bmzi_bmnzi.ll
Normal file
55
test/CodeGen/Mips/msa/bmzi_bmnzi.ll
Normal file
@ -0,0 +1,55 @@
|
||||
; RUN: llc -march=mipsel -mattr=+msa,+fp64 -relocation-model=pic < %s | FileCheck %s
|
||||
|
||||
@llvm_mips_bmnzi_b_ARG1 = global <16 x i8> <i8 15, i8 15, i8 15, i8 15, i8 15, i8 15, i8 15, i8 15, i8 15, i8 15, i8 15, i8 15, i8 15, i8 15, i8 15, i8 15>, align 16
|
||||
@llvm_mips_bmnzi_b_ARG2 = global <16 x i8> zeroinitializer, align 16
|
||||
@llvm_mips_bmnzi_b_RES = global <16 x i8> zeroinitializer, align 16
|
||||
|
||||
define void @llvm_mips_bmnzi_b_test() nounwind {
|
||||
entry:
|
||||
%0 = load <16 x i8>, <16 x i8>* @llvm_mips_bmnzi_b_ARG1
|
||||
%1 = load <16 x i8>, <16 x i8>* @llvm_mips_bmnzi_b_ARG2
|
||||
%2 = tail call <16 x i8> @llvm.mips.bmnzi.b(<16 x i8> %0, <16 x i8> %1, i32 240)
|
||||
store <16 x i8> %2, <16 x i8>* @llvm_mips_bmnzi_b_RES
|
||||
%3 = tail call <16 x i8> @llvm.mips.bmnzi.b(<16 x i8> %0, <16 x i8> %1, i32 15)
|
||||
store <16 x i8> %3, <16 x i8>* @llvm_mips_bmnzi_b_RES
|
||||
%4 = tail call <16 x i8> @llvm.mips.bmnzi.b(<16 x i8> %0, <16 x i8> %1, i32 170)
|
||||
store <16 x i8> %4, <16 x i8>* @llvm_mips_bmnzi_b_RES
|
||||
ret void
|
||||
}
|
||||
; CHECK-LABEL: llvm_mips_bmnzi_b_test:
|
||||
; CHECK: lw [[R0:\$[0-9]+]], %got(llvm_mips_bmnzi_b_RES)(
|
||||
; CHECK: lw [[R1:\$[0-9]+]], %got(llvm_mips_bmnzi_b_ARG1)(
|
||||
; CHECK: lw [[R2:\$[0-9]+]], %got(llvm_mips_bmnzi_b_ARG2)(
|
||||
; CHECK: ld.b [[R3:\$w[0-9]+]], 0([[R2]])
|
||||
; CHECK: ld.b [[R4:\$w[0-9]+]], 0([[R1]])
|
||||
; CHECK: move.v [[R5:\$w[0-9]+]], [[R4]]
|
||||
; CHECK: binsli.b [[R5]], [[R3]], 3
|
||||
; CHECK: binsri.b [[R5]], [[R3]], 3
|
||||
; CHECK: bmnzi.b [[R4]], [[R3]], 170
|
||||
|
||||
define void @llvm_mips_bmzi_b_test() nounwind {
|
||||
entry:
|
||||
%0 = load <16 x i8>, <16 x i8>* @llvm_mips_bmnzi_b_ARG1
|
||||
%1 = load <16 x i8>, <16 x i8>* @llvm_mips_bmnzi_b_ARG2
|
||||
%2 = tail call <16 x i8> @llvm.mips.bmzi.b(<16 x i8> %0, <16 x i8> %1, i32 240)
|
||||
store <16 x i8> %2, <16 x i8>* @llvm_mips_bmnzi_b_RES
|
||||
%3 = tail call <16 x i8> @llvm.mips.bmzi.b(<16 x i8> %0, <16 x i8> %1, i32 15)
|
||||
store <16 x i8> %3, <16 x i8>* @llvm_mips_bmnzi_b_RES
|
||||
%4 = tail call <16 x i8> @llvm.mips.bmzi.b(<16 x i8> %0, <16 x i8> %1, i32 170)
|
||||
store <16 x i8> %4, <16 x i8>* @llvm_mips_bmnzi_b_RES
|
||||
ret void
|
||||
}
|
||||
; CHECK-LABEL: llvm_mips_bmzi_b_test:
|
||||
; CHECK: lw [[R0:\$[0-9]+]], %got(llvm_mips_bmnzi_b_RES)(
|
||||
; CHECK: lw [[R1:\$[0-9]+]], %got(llvm_mips_bmnzi_b_ARG2)(
|
||||
; CHECK: lw [[R2:\$[0-9]+]], %got(llvm_mips_bmnzi_b_ARG1)(
|
||||
; CHECK: ld.b [[R3:\$w[0-9]+]], 0([[R2]])
|
||||
; CHECK: ld.b [[R4:\$w[0-9]+]], 0([[R1]])
|
||||
; CHECK: move.v [[R5:\$w[0-9]+]], [[R4]]
|
||||
; CHECK: binsli.b [[R5]], [[R3]], 3
|
||||
; CHECK: binsri.b [[R5]], [[R3]], 3
|
||||
; bmnzi.b is the same as bmzi.b with ws and wd_in swapped
|
||||
; CHECK: bmnzi.b [[R4]], [[R3]], 170
|
||||
|
||||
declare <16 x i8> @llvm.mips.bmnzi.b(<16 x i8>, <16 x i8>, i32) nounwind
|
||||
declare <16 x i8> @llvm.mips.bmzi.b(<16 x i8>, <16 x i8>, i32) nounwind
|
@ -89,7 +89,7 @@ define void @llvm_mips_binsli_b_test() nounwind {
|
||||
entry:
|
||||
%0 = load <16 x i8>, <16 x i8>* @llvm_mips_binsli_b_ARG1
|
||||
%1 = load <16 x i8>, <16 x i8>* @llvm_mips_binsli_b_ARG2
|
||||
%2 = tail call <16 x i8> @llvm.mips.binsli.b(<16 x i8> %0, <16 x i8> %1, i32 7)
|
||||
%2 = tail call <16 x i8> @llvm.mips.binsli.b(<16 x i8> %0, <16 x i8> %1, i32 6)
|
||||
store <16 x i8> %2, <16 x i8>* @llvm_mips_binsli_b_RES
|
||||
ret void
|
||||
}
|
||||
@ -101,7 +101,7 @@ declare <16 x i8> @llvm.mips.binsli.b(<16 x i8>, <16 x i8>, i32) nounwind
|
||||
; CHECK-DAG: lw [[R2:\$[0-9]+]], %got(llvm_mips_binsli_b_ARG2)(
|
||||
; CHECK-DAG: ld.b [[R3:\$w[0-9]+]], 0([[R1]])
|
||||
; CHECK-DAG: ld.b [[R4:\$w[0-9]+]], 0([[R2]])
|
||||
; CHECK-DAG: binsli.b [[R3]], [[R4]], 7
|
||||
; CHECK-DAG: binsli.b [[R3]], [[R4]], 6
|
||||
; CHECK-DAG: lw [[R5:\$[0-9]+]], %got(llvm_mips_binsli_b_RES)(
|
||||
; CHECK-DAG: st.b [[R3]], 0([[R5]])
|
||||
; CHECK: .size llvm_mips_binsli_b_test
|
||||
@ -193,7 +193,7 @@ define void @llvm_mips_binsri_b_test() nounwind {
|
||||
entry:
|
||||
%0 = load <16 x i8>, <16 x i8>* @llvm_mips_binsri_b_ARG1
|
||||
%1 = load <16 x i8>, <16 x i8>* @llvm_mips_binsri_b_ARG2
|
||||
%2 = tail call <16 x i8> @llvm.mips.binsri.b(<16 x i8> %0, <16 x i8> %1, i32 7)
|
||||
%2 = tail call <16 x i8> @llvm.mips.binsri.b(<16 x i8> %0, <16 x i8> %1, i32 6)
|
||||
store <16 x i8> %2, <16 x i8>* @llvm_mips_binsri_b_RES
|
||||
ret void
|
||||
}
|
||||
@ -205,7 +205,7 @@ declare <16 x i8> @llvm.mips.binsri.b(<16 x i8>, <16 x i8>, i32) nounwind
|
||||
; CHECK-DAG: lw [[R2:\$[0-9]+]], %got(llvm_mips_binsri_b_ARG2)(
|
||||
; CHECK-DAG: ld.b [[R3:\$w[0-9]+]], 0([[R1]])
|
||||
; CHECK-DAG: ld.b [[R4:\$w[0-9]+]], 0([[R2]])
|
||||
; CHECK-DAG: binsri.b [[R3]], [[R4]], 7
|
||||
; CHECK-DAG: binsri.b [[R3]], [[R4]], 6
|
||||
; CHECK-DAG: lw [[R5:\$[0-9]+]], %got(llvm_mips_binsri_b_RES)(
|
||||
; CHECK-DAG: st.b [[R3]], 0([[R5]])
|
||||
; CHECK: .size llvm_mips_binsri_b_test
|
||||
|
@ -616,7 +616,7 @@ entry:
|
||||
; CHECK: binsri.h
|
||||
%a = load <8 x i16>, <8 x i16> * %ptr, align 16
|
||||
%b = load <8 x i16>, <8 x i16> * %ptr2, align 16
|
||||
%r = call <8 x i16> @llvm.mips.binsri.h(<8 x i16> %a, <8 x i16> %b, i32 15)
|
||||
%r = call <8 x i16> @llvm.mips.binsri.h(<8 x i16> %a, <8 x i16> %b, i32 14)
|
||||
store <8 x i16> %r, <8 x i16> * %ptr, align 16
|
||||
ret void
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user