mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-15 20:29:48 +00:00
[mips][msa] Remove the VSPLAT and VSPLATD nodes in favour of matching BUILD_VECTOR.
Most constant BUILD_VECTOR's are matched using ComplexPatterns which cover bitcasted as well as normal vectors. However, it doesn't seem to be possible to match ldi.[bhwd] in a type-agnostic manner (e.g. to support the widest range of immediates, it should be possible to use ldi.b to load v2i64) using TableGen so ldi.[bhwd] is matched using custom code in MipsSEISelDAGToDAG.cpp This made the majority of the constant splat BUILD_VECTOR lowering redundant. The only transformation remaining for constant splats is when an (up-to) 32-bit constant splat is possible but the value does not fit into a 10-bit signed integer. In this case, the BUILD_VECTOR is transformed into a bitcasted BUILD_VECTOR so that fill.[bhw] can be used to splat the vector from a GPR32 register (which is initialized using the usual lui/addui sequence). There are no additional tests since this is a re-implementation of previous functionality. The change is intended to make it easier to implement some of the upcoming instruction selection patches since they can rely on existing support for BUILD_VECTOR's in the DAGCombiner. compare_float.ll changed slightly because a BITCAST is no longer introduced during legalization. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@191299 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
ad16ddeb8e
commit
acfa5a203c
@ -99,6 +99,46 @@ bool MipsDAGToDAGISel::selectAddr16(SDNode *Parent, SDValue N, SDValue &Base,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MipsDAGToDAGISel::selectVSplat(SDNode *N, APInt &Imm) const {
|
||||||
|
llvm_unreachable("Unimplemented function.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MipsDAGToDAGISel::selectVSplatUimm3(SDValue N, SDValue &Imm) const {
|
||||||
|
llvm_unreachable("Unimplemented function.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MipsDAGToDAGISel::selectVSplatUimm4(SDValue N, SDValue &Imm) const {
|
||||||
|
llvm_unreachable("Unimplemented function.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MipsDAGToDAGISel::selectVSplatUimm5(SDValue N, SDValue &Imm) const {
|
||||||
|
llvm_unreachable("Unimplemented function.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MipsDAGToDAGISel::selectVSplatUimm6(SDValue N, SDValue &Imm) const {
|
||||||
|
llvm_unreachable("Unimplemented function.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MipsDAGToDAGISel::selectVSplatUimm8(SDValue N, SDValue &Imm) const {
|
||||||
|
llvm_unreachable("Unimplemented function.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MipsDAGToDAGISel::selectVSplatSimm5(SDValue N, SDValue &Imm) const {
|
||||||
|
llvm_unreachable("Unimplemented function.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MipsDAGToDAGISel::selectVSplatUimmPow2(SDValue N, SDValue &Imm) const {
|
||||||
|
llvm_unreachable("Unimplemented function.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// Select instructions not customized! Used for
|
/// Select instructions not customized! Used for
|
||||||
/// expanded, promoted and normal instructions
|
/// expanded, promoted and normal instructions
|
||||||
SDNode* MipsDAGToDAGISel::Select(SDNode *Node) {
|
SDNode* MipsDAGToDAGISel::Select(SDNode *Node) {
|
||||||
|
@ -76,6 +76,23 @@ private:
|
|||||||
virtual bool selectAddr16(SDNode *Parent, SDValue N, SDValue &Base,
|
virtual bool selectAddr16(SDNode *Parent, SDValue N, SDValue &Base,
|
||||||
SDValue &Offset, SDValue &Alias);
|
SDValue &Offset, SDValue &Alias);
|
||||||
|
|
||||||
|
/// \brief Select constant vector splats.
|
||||||
|
virtual bool selectVSplat(SDNode *N, APInt &Imm) const;
|
||||||
|
/// \brief Select constant vector splats whose value fits in a uimm3.
|
||||||
|
virtual bool selectVSplatUimm3(SDValue N, SDValue &Imm) const;
|
||||||
|
/// \brief Select constant vector splats whose value fits in a uimm4.
|
||||||
|
virtual bool selectVSplatUimm4(SDValue N, SDValue &Imm) const;
|
||||||
|
/// \brief Select constant vector splats whose value fits in a uimm5.
|
||||||
|
virtual bool selectVSplatUimm5(SDValue N, SDValue &Imm) const;
|
||||||
|
/// \brief Select constant vector splats whose value fits in a uimm6.
|
||||||
|
virtual bool selectVSplatUimm6(SDValue N, SDValue &Imm) const;
|
||||||
|
/// \brief Select constant vector splats whose value fits in a uimm8.
|
||||||
|
virtual bool selectVSplatUimm8(SDValue N, SDValue &Imm) const;
|
||||||
|
/// \brief Select constant vector splats whose value fits in a simm5.
|
||||||
|
virtual bool selectVSplatSimm5(SDValue N, SDValue &Imm) const;
|
||||||
|
/// \brief Select constant vector splats whose value is a power of 2.
|
||||||
|
virtual bool selectVSplatUimmPow2(SDValue N, SDValue &Imm) const;
|
||||||
|
|
||||||
virtual SDNode *Select(SDNode *N);
|
virtual SDNode *Select(SDNode *N);
|
||||||
|
|
||||||
virtual std::pair<bool, SDNode*> selectNode(SDNode *Node) = 0;
|
virtual std::pair<bool, SDNode*> selectNode(SDNode *Node) = 0;
|
||||||
|
@ -221,8 +221,6 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const {
|
|||||||
case MipsISD::VSMIN: return "MipsISD::VSMIN";
|
case MipsISD::VSMIN: return "MipsISD::VSMIN";
|
||||||
case MipsISD::VUMAX: return "MipsISD::VUMAX";
|
case MipsISD::VUMAX: return "MipsISD::VUMAX";
|
||||||
case MipsISD::VUMIN: return "MipsISD::VUMIN";
|
case MipsISD::VUMIN: return "MipsISD::VUMIN";
|
||||||
case MipsISD::VSPLAT: return "MipsISD::VSPLAT";
|
|
||||||
case MipsISD::VSPLATD: return "MipsISD::VSPLATD";
|
|
||||||
case MipsISD::VEXTRACT_SEXT_ELT: return "MipsISD::VEXTRACT_SEXT_ELT";
|
case MipsISD::VEXTRACT_SEXT_ELT: return "MipsISD::VEXTRACT_SEXT_ELT";
|
||||||
case MipsISD::VEXTRACT_ZEXT_ELT: return "MipsISD::VEXTRACT_ZEXT_ELT";
|
case MipsISD::VEXTRACT_ZEXT_ELT: return "MipsISD::VEXTRACT_ZEXT_ELT";
|
||||||
case MipsISD::VNOR: return "MipsISD::VNOR";
|
case MipsISD::VNOR: return "MipsISD::VNOR";
|
||||||
|
@ -172,12 +172,6 @@ namespace llvm {
|
|||||||
VUMAX,
|
VUMAX,
|
||||||
VUMIN,
|
VUMIN,
|
||||||
|
|
||||||
// Special case of BUILD_VECTOR where all elements are the same.
|
|
||||||
VSPLAT,
|
|
||||||
// Special case of VSPLAT where the result is v2i64, the operand is
|
|
||||||
// constant, and the operand fits in a signed 10-bits value.
|
|
||||||
VSPLATD,
|
|
||||||
|
|
||||||
// Combined (XOR (OR $a, $b), -1)
|
// Combined (XOR (OR $a, $b), -1)
|
||||||
VNOR,
|
VNOR,
|
||||||
|
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
def SDT_MipsSplat : SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisInt<1>]>;
|
|
||||||
def SDT_MipsVecCond : SDTypeProfile<1, 1, [SDTCisInt<0>, SDTCisVec<1>]>;
|
def SDT_MipsVecCond : SDTypeProfile<1, 1, [SDTCisInt<0>, SDTCisVec<1>]>;
|
||||||
def SDT_VSetCC : SDTypeProfile<1, 3, [SDTCisInt<0>,
|
def SDT_VSetCC : SDTypeProfile<1, 3, [SDTCisInt<0>,
|
||||||
SDTCisInt<1>,
|
SDTCisInt<1>,
|
||||||
@ -34,8 +33,6 @@ def MipsVUMax : SDNode<"MipsISD::VUMAX", SDTIntBinOp,
|
|||||||
[SDNPCommutative, SDNPAssociative]>;
|
[SDNPCommutative, SDNPAssociative]>;
|
||||||
def MipsVUMin : SDNode<"MipsISD::VUMIN", SDTIntBinOp,
|
def MipsVUMin : SDNode<"MipsISD::VUMIN", SDTIntBinOp,
|
||||||
[SDNPCommutative, SDNPAssociative]>;
|
[SDNPCommutative, SDNPAssociative]>;
|
||||||
def MipsVSplat : SDNode<"MipsISD::VSPLAT", SDT_MipsSplat>;
|
|
||||||
def MipsVSplatD : SDNode<"MipsISD::VSPLATD", SDT_MipsSplat>;
|
|
||||||
def MipsVNOR : SDNode<"MipsISD::VNOR", SDTIntBinOp,
|
def MipsVNOR : SDNode<"MipsISD::VNOR", SDTIntBinOp,
|
||||||
[SDNPCommutative, SDNPAssociative]>;
|
[SDNPCommutative, SDNPAssociative]>;
|
||||||
|
|
||||||
@ -47,6 +44,48 @@ def MipsVExtractSExt : SDNode<"MipsISD::VEXTRACT_SEXT_ELT",
|
|||||||
def MipsVExtractZExt : SDNode<"MipsISD::VEXTRACT_ZEXT_ELT",
|
def MipsVExtractZExt : SDNode<"MipsISD::VEXTRACT_ZEXT_ELT",
|
||||||
SDTypeProfile<1, 3, [SDTCisPtrTy<2>]>, []>;
|
SDTypeProfile<1, 3, [SDTCisPtrTy<2>]>, []>;
|
||||||
|
|
||||||
|
// Operands
|
||||||
|
|
||||||
|
def uimm3 : Operand<i32> {
|
||||||
|
let PrintMethod = "printUnsignedImm";
|
||||||
|
}
|
||||||
|
|
||||||
|
def uimm4 : Operand<i32> {
|
||||||
|
let PrintMethod = "printUnsignedImm";
|
||||||
|
}
|
||||||
|
|
||||||
|
def uimm8 : Operand<i32> {
|
||||||
|
let PrintMethod = "printUnsignedImm";
|
||||||
|
}
|
||||||
|
|
||||||
|
def simm5 : Operand<i32>;
|
||||||
|
|
||||||
|
def simm10 : Operand<i32>;
|
||||||
|
|
||||||
|
def vsplat_uimm3 : Operand<vAny> {
|
||||||
|
let PrintMethod = "printUnsignedImm";
|
||||||
|
}
|
||||||
|
|
||||||
|
def vsplat_uimm4 : Operand<vAny> {
|
||||||
|
let PrintMethod = "printUnsignedImm";
|
||||||
|
}
|
||||||
|
|
||||||
|
def vsplat_uimm5 : Operand<vAny> {
|
||||||
|
let PrintMethod = "printUnsignedImm";
|
||||||
|
}
|
||||||
|
|
||||||
|
def vsplat_uimm6 : Operand<vAny> {
|
||||||
|
let PrintMethod = "printUnsignedImm";
|
||||||
|
}
|
||||||
|
|
||||||
|
def vsplat_uimm8 : Operand<vAny> {
|
||||||
|
let PrintMethod = "printUnsignedImm";
|
||||||
|
}
|
||||||
|
|
||||||
|
def vsplat_simm5 : Operand<vAny>;
|
||||||
|
|
||||||
|
def vsplat_simm10 : Operand<vAny>;
|
||||||
|
|
||||||
// Pattern fragments
|
// Pattern fragments
|
||||||
def vextract_sext_i8 : PatFrag<(ops node:$vec, node:$idx),
|
def vextract_sext_i8 : PatFrag<(ops node:$vec, node:$idx),
|
||||||
(MipsVExtractSExt node:$vec, node:$idx, i8)>;
|
(MipsVExtractSExt node:$vec, node:$idx, i8)>;
|
||||||
@ -131,31 +170,96 @@ def vsetult_v8i16 : vsetcc_type<v8i16, SETULT>;
|
|||||||
def vsetult_v4i32 : vsetcc_type<v4i32, SETULT>;
|
def vsetult_v4i32 : vsetcc_type<v4i32, SETULT>;
|
||||||
def vsetult_v2i64 : vsetcc_type<v2i64, SETULT>;
|
def vsetult_v2i64 : vsetcc_type<v2i64, SETULT>;
|
||||||
|
|
||||||
def vsplati8 : PatFrag<(ops node:$in), (v16i8 (MipsVSplat (i32 node:$in)))>;
|
def vsplati8 : PatFrag<(ops node:$e0),
|
||||||
def vsplati16 : PatFrag<(ops node:$in), (v8i16 (MipsVSplat (i32 node:$in)))>;
|
(v16i8 (build_vector node:$e0, node:$e0,
|
||||||
def vsplati32 : PatFrag<(ops node:$in), (v4i32 (MipsVSplat (i32 node:$in)))>;
|
node:$e0, node:$e0,
|
||||||
def vsplati64 : PatFrag<(ops node:$in), (v2i64 (MipsVSplatD (i32 node:$in)))>;
|
node:$e0, node:$e0,
|
||||||
|
node:$e0, node:$e0,
|
||||||
|
node:$e0, node:$e0,
|
||||||
|
node:$e0, node:$e0,
|
||||||
|
node:$e0, node:$e0,
|
||||||
|
node:$e0, node:$e0))>;
|
||||||
|
def vsplati16 : PatFrag<(ops node:$e0),
|
||||||
|
(v8i16 (build_vector node:$e0, node:$e0,
|
||||||
|
node:$e0, node:$e0,
|
||||||
|
node:$e0, node:$e0,
|
||||||
|
node:$e0, node:$e0))>;
|
||||||
|
def vsplati32 : PatFrag<(ops node:$e0),
|
||||||
|
(v4i32 (build_vector node:$e0, node:$e0,
|
||||||
|
node:$e0, node:$e0))>;
|
||||||
|
def vsplati64 : PatFrag<(ops node:$e0),
|
||||||
|
(v2i64 (build_vector:$v0 node:$e0, node:$e0))>;
|
||||||
|
|
||||||
|
class SplatPatLeaf<Operand opclass, dag frag, code pred = [{}],
|
||||||
|
SDNodeXForm xform = NOOP_SDNodeXForm>
|
||||||
|
: PatLeaf<frag, pred, xform> {
|
||||||
|
Operand OpClass = opclass;
|
||||||
|
}
|
||||||
|
|
||||||
|
class SplatComplexPattern<Operand opclass, ValueType ty, int numops, string fn,
|
||||||
|
list<SDNode> roots = [],
|
||||||
|
list<SDNodeProperty> props = []> :
|
||||||
|
ComplexPattern<ty, numops, fn, roots, props> {
|
||||||
|
Operand OpClass = opclass;
|
||||||
|
}
|
||||||
|
|
||||||
|
def vsplati8_uimm3 : SplatComplexPattern<vsplat_uimm3, v16i8, 1,
|
||||||
|
"selectVSplatUimm3",
|
||||||
|
[build_vector, bitconvert]>;
|
||||||
|
|
||||||
|
def vsplati8_uimm5 : SplatComplexPattern<vsplat_uimm5, v16i8, 1,
|
||||||
|
"selectVSplatUimm5",
|
||||||
|
[build_vector, bitconvert]>;
|
||||||
|
|
||||||
|
def vsplati8_uimm8 : SplatComplexPattern<vsplat_uimm8, v16i8, 1,
|
||||||
|
"selectVSplatUimm8",
|
||||||
|
[build_vector, bitconvert]>;
|
||||||
|
|
||||||
|
def vsplati8_simm5 : SplatComplexPattern<vsplat_simm5, v16i8, 1,
|
||||||
|
"selectVSplatSimm5",
|
||||||
|
[build_vector, bitconvert]>;
|
||||||
|
|
||||||
|
def vsplati16_uimm4 : SplatComplexPattern<vsplat_uimm4, v8i16, 1,
|
||||||
|
"selectVSplatUimm4",
|
||||||
|
[build_vector, bitconvert]>;
|
||||||
|
|
||||||
|
def vsplati16_uimm5 : SplatComplexPattern<vsplat_uimm5, v8i16, 1,
|
||||||
|
"selectVSplatUimm5",
|
||||||
|
[build_vector, bitconvert]>;
|
||||||
|
|
||||||
|
def vsplati16_simm5 : SplatComplexPattern<vsplat_simm5, v8i16, 1,
|
||||||
|
"selectVSplatSimm5",
|
||||||
|
[build_vector, bitconvert]>;
|
||||||
|
|
||||||
|
def vsplati32_uimm5 : SplatComplexPattern<vsplat_uimm5, v4i32, 1,
|
||||||
|
"selectVSplatUimm5",
|
||||||
|
[build_vector, bitconvert]>;
|
||||||
|
|
||||||
|
def vsplati32_simm5 : SplatComplexPattern<vsplat_simm5, v4i32, 1,
|
||||||
|
"selectVSplatSimm5",
|
||||||
|
[build_vector, bitconvert]>;
|
||||||
|
|
||||||
|
def vsplati64_uimm5 : SplatComplexPattern<vsplat_uimm5, v2i64, 1,
|
||||||
|
"selectVSplatUimm5",
|
||||||
|
[build_vector, bitconvert]>;
|
||||||
|
|
||||||
|
def vsplati64_uimm6 : SplatComplexPattern<vsplat_uimm6, v2i64, 1,
|
||||||
|
"selectVSplatUimm6",
|
||||||
|
[build_vector, bitconvert]>;
|
||||||
|
|
||||||
|
def vsplati64_simm5 : SplatComplexPattern<vsplat_simm5, v2i64, 1,
|
||||||
|
"selectVSplatSimm5",
|
||||||
|
[build_vector, bitconvert]>;
|
||||||
|
|
||||||
|
// Any build_vector that is a constant splat with a value that is an exact
|
||||||
|
// power of 2
|
||||||
|
def vsplat_uimm_pow2 : ComplexPattern<vAny, 1, "selectVSplatUimmPow2",
|
||||||
|
[build_vector, bitconvert]>;
|
||||||
|
|
||||||
// Immediates
|
// Immediates
|
||||||
def immSExt5 : ImmLeaf<i32, [{return isInt<5>(Imm);}]>;
|
def immSExt5 : ImmLeaf<i32, [{return isInt<5>(Imm);}]>;
|
||||||
def immSExt10: ImmLeaf<i32, [{return isInt<10>(Imm);}]>;
|
def immSExt10: ImmLeaf<i32, [{return isInt<10>(Imm);}]>;
|
||||||
|
|
||||||
def uimm3 : Operand<i32> {
|
|
||||||
let PrintMethod = "printUnsignedImm";
|
|
||||||
}
|
|
||||||
|
|
||||||
def uimm4 : Operand<i32> {
|
|
||||||
let PrintMethod = "printUnsignedImm";
|
|
||||||
}
|
|
||||||
|
|
||||||
def uimm8 : Operand<i32> {
|
|
||||||
let PrintMethod = "printUnsignedImm";
|
|
||||||
}
|
|
||||||
|
|
||||||
def simm5 : Operand<i32>;
|
|
||||||
|
|
||||||
def simm10 : Operand<i32>;
|
|
||||||
|
|
||||||
// Instruction encoding.
|
// Instruction encoding.
|
||||||
class ADD_A_B_ENC : MSA_3R_FMT<0b000, 0b00, 0b010000>;
|
class ADD_A_B_ENC : MSA_3R_FMT<0b000, 0b00, 0b010000>;
|
||||||
class ADD_A_H_ENC : MSA_3R_FMT<0b000, 0b01, 0b010000>;
|
class ADD_A_H_ENC : MSA_3R_FMT<0b000, 0b01, 0b010000>;
|
||||||
@ -912,47 +1016,14 @@ class MSA_BIT_D_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
|
|||||||
InstrItinClass Itinerary = itin;
|
InstrItinClass Itinerary = itin;
|
||||||
}
|
}
|
||||||
|
|
||||||
class MSA_BIT_SPLATB_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
|
class MSA_BIT_SPLAT_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
|
||||||
RegisterClass RCWD, RegisterClass RCWS = RCWD,
|
SplatComplexPattern SplatImm, RegisterClass RCWD,
|
||||||
InstrItinClass itin = NoItinerary> {
|
RegisterClass RCWS = RCWD,
|
||||||
|
InstrItinClass itin = NoItinerary> {
|
||||||
dag OutOperandList = (outs RCWD:$wd);
|
dag OutOperandList = (outs RCWD:$wd);
|
||||||
dag InOperandList = (ins RCWS:$ws, uimm3:$u3);
|
dag InOperandList = (ins RCWS:$ws, SplatImm.OpClass:$u);
|
||||||
string AsmString = !strconcat(instr_asm, "\t$wd, $ws, $u3");
|
string AsmString = !strconcat(instr_asm, "\t$wd, $ws, $u");
|
||||||
list<dag> Pattern = [(set RCWD:$wd, (OpNode RCWS:$ws,
|
list<dag> Pattern = [(set RCWD:$wd, (OpNode RCWS:$ws, SplatImm:$u))];
|
||||||
(vsplati8 immZExt3:$u3)))];
|
|
||||||
InstrItinClass Itinerary = itin;
|
|
||||||
}
|
|
||||||
|
|
||||||
class MSA_BIT_SPLATH_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
|
|
||||||
RegisterClass RCWD, RegisterClass RCWS = RCWD,
|
|
||||||
InstrItinClass itin = NoItinerary> {
|
|
||||||
dag OutOperandList = (outs RCWD:$wd);
|
|
||||||
dag InOperandList = (ins RCWS:$ws, uimm4:$u4);
|
|
||||||
string AsmString = !strconcat(instr_asm, "\t$wd, $ws, $u4");
|
|
||||||
list<dag> Pattern = [(set RCWD:$wd, (OpNode RCWS:$ws,
|
|
||||||
(vsplati16 immZExt4:$u4)))];
|
|
||||||
InstrItinClass Itinerary = itin;
|
|
||||||
}
|
|
||||||
|
|
||||||
class MSA_BIT_SPLATW_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
|
|
||||||
RegisterClass RCWD, RegisterClass RCWS = RCWD,
|
|
||||||
InstrItinClass itin = NoItinerary> {
|
|
||||||
dag OutOperandList = (outs RCWD:$wd);
|
|
||||||
dag InOperandList = (ins RCWS:$ws, uimm5:$u5);
|
|
||||||
string AsmString = !strconcat(instr_asm, "\t$wd, $ws, $u5");
|
|
||||||
list<dag> Pattern = [(set RCWD:$wd, (OpNode RCWS:$ws,
|
|
||||||
(vsplati32 immZExt5:$u5)))];
|
|
||||||
InstrItinClass Itinerary = itin;
|
|
||||||
}
|
|
||||||
|
|
||||||
class MSA_BIT_SPLATD_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
|
|
||||||
RegisterClass RCWD, RegisterClass RCWS = RCWD,
|
|
||||||
InstrItinClass itin = NoItinerary> {
|
|
||||||
dag OutOperandList = (outs RCWD:$wd);
|
|
||||||
dag InOperandList = (ins RCWS:$ws, uimm6:$u6);
|
|
||||||
string AsmString = !strconcat(instr_asm, "\t$wd, $ws, $u6");
|
|
||||||
list<dag> Pattern = [(set RCWD:$wd, (OpNode RCWS:$ws,
|
|
||||||
(vsplati64 immZExt6:$u6)))];
|
|
||||||
InstrItinClass Itinerary = itin;
|
InstrItinClass Itinerary = itin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -967,38 +1038,24 @@ class MSA_COPY_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
|
|||||||
}
|
}
|
||||||
|
|
||||||
class MSA_I5_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
|
class MSA_I5_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
|
||||||
SDPatternOperator SplatNode, RegisterClass RCWD,
|
SplatComplexPattern SplatImm, RegisterClass RCWD,
|
||||||
RegisterClass RCWS = RCWD,
|
RegisterClass RCWS = RCWD,
|
||||||
InstrItinClass itin = NoItinerary> {
|
InstrItinClass itin = NoItinerary> {
|
||||||
dag OutOperandList = (outs RCWD:$wd);
|
dag OutOperandList = (outs RCWD:$wd);
|
||||||
dag InOperandList = (ins RCWS:$ws, uimm5:$u5);
|
dag InOperandList = (ins RCWS:$ws, SplatImm.OpClass:$imm);
|
||||||
string AsmString = !strconcat(instr_asm, "\t$wd, $ws, $u5");
|
string AsmString = !strconcat(instr_asm, "\t$wd, $ws, $imm");
|
||||||
list<dag> Pattern = [(set RCWD:$wd, (OpNode RCWS:$ws,
|
list<dag> Pattern = [(set RCWD:$wd, (OpNode RCWS:$ws, SplatImm:$imm))];
|
||||||
(SplatNode immZExt5:$u5)))];
|
|
||||||
InstrItinClass Itinerary = itin;
|
|
||||||
}
|
|
||||||
|
|
||||||
class MSA_SI5_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
|
|
||||||
SDPatternOperator SplatNode, RegisterClass RCWD,
|
|
||||||
RegisterClass RCWS = RCWD,
|
|
||||||
InstrItinClass itin = NoItinerary> {
|
|
||||||
dag OutOperandList = (outs RCWD:$wd);
|
|
||||||
dag InOperandList = (ins RCWS:$ws, simm5:$s5);
|
|
||||||
string AsmString = !strconcat(instr_asm, "\t$wd, $ws, $s5");
|
|
||||||
list<dag> Pattern = [(set RCWD:$wd, (OpNode RCWS:$ws,
|
|
||||||
(SplatNode immSExt5:$s5)))];
|
|
||||||
InstrItinClass Itinerary = itin;
|
InstrItinClass Itinerary = itin;
|
||||||
}
|
}
|
||||||
|
|
||||||
class MSA_I8_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
|
class MSA_I8_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
|
||||||
SDPatternOperator SplatNode, RegisterClass RCWD,
|
SplatComplexPattern SplatImm, RegisterClass RCWD,
|
||||||
RegisterClass RCWS = RCWD,
|
RegisterClass RCWS = RCWD,
|
||||||
InstrItinClass itin = NoItinerary> {
|
InstrItinClass itin = NoItinerary> {
|
||||||
dag OutOperandList = (outs RCWD:$wd);
|
dag OutOperandList = (outs RCWD:$wd);
|
||||||
dag InOperandList = (ins RCWS:$ws, uimm8:$u8);
|
dag InOperandList = (ins RCWS:$ws, SplatImm.OpClass:$u8);
|
||||||
string AsmString = !strconcat(instr_asm, "\t$wd, $ws, $u8");
|
string AsmString = !strconcat(instr_asm, "\t$wd, $ws, $u8");
|
||||||
list<dag> Pattern = [(set RCWD:$wd, (OpNode RCWS:$ws,
|
list<dag> Pattern = [(set RCWD:$wd, (OpNode RCWS:$ws, SplatImm:$u8))];
|
||||||
(SplatNode immZExt8:$u8)))];
|
|
||||||
InstrItinClass Itinerary = itin;
|
InstrItinClass Itinerary = itin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1013,13 +1070,14 @@ class MSA_I8_X_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
|
|||||||
InstrItinClass Itinerary = itin;
|
InstrItinClass Itinerary = itin;
|
||||||
}
|
}
|
||||||
|
|
||||||
class MSA_I10_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
|
class MSA_I10_LDI_DESC_BASE<string instr_asm, RegisterClass RCWD,
|
||||||
RegisterClass RCWD,
|
InstrItinClass itin = NoItinerary> {
|
||||||
InstrItinClass itin = NoItinerary> {
|
|
||||||
dag OutOperandList = (outs RCWD:$wd);
|
dag OutOperandList = (outs RCWD:$wd);
|
||||||
dag InOperandList = (ins simm10:$i10);
|
dag InOperandList = (ins vsplat_simm10:$i10);
|
||||||
string AsmString = !strconcat(instr_asm, "\t$wd, $i10");
|
string AsmString = !strconcat(instr_asm, "\t$wd, $i10");
|
||||||
list<dag> Pattern = [(set RCWD:$wd, (OpNode immSExt10:$i10))];
|
// LDI is matched using custom matching code in MipsSEISelDAGToDAG.cpp
|
||||||
|
list<dag> Pattern = [];
|
||||||
|
bit hasSideEffects = 0;
|
||||||
InstrItinClass Itinerary = itin;
|
InstrItinClass Itinerary = itin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1033,6 +1091,17 @@ class MSA_2R_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
|
|||||||
InstrItinClass Itinerary = itin;
|
InstrItinClass Itinerary = itin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class MSA_2R_FILL_DESC_BASE<string instr_asm, ValueType VT,
|
||||||
|
SDPatternOperator OpNode, RegisterClass RCWD,
|
||||||
|
RegisterClass RCWS = RCWD,
|
||||||
|
InstrItinClass itin = NoItinerary> {
|
||||||
|
dag OutOperandList = (outs RCWD:$wd);
|
||||||
|
dag InOperandList = (ins RCWS:$ws);
|
||||||
|
string AsmString = !strconcat(instr_asm, "\t$wd, $ws");
|
||||||
|
list<dag> Pattern = [(set RCWD:$wd, (VT (OpNode RCWS:$ws)))];
|
||||||
|
InstrItinClass Itinerary = itin;
|
||||||
|
}
|
||||||
|
|
||||||
class MSA_2RF_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
|
class MSA_2RF_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
|
||||||
RegisterClass RCWD, RegisterClass RCWS = RCWD,
|
RegisterClass RCWD, RegisterClass RCWS = RCWD,
|
||||||
InstrItinClass itin = NoItinerary> :
|
InstrItinClass itin = NoItinerary> :
|
||||||
@ -1171,17 +1240,17 @@ class ADDV_H_DESC : MSA_3R_DESC_BASE<"addv.h", add, MSA128H>, IsCommutable;
|
|||||||
class ADDV_W_DESC : MSA_3R_DESC_BASE<"addv.w", add, MSA128W>, IsCommutable;
|
class ADDV_W_DESC : MSA_3R_DESC_BASE<"addv.w", add, MSA128W>, IsCommutable;
|
||||||
class ADDV_D_DESC : MSA_3R_DESC_BASE<"addv.d", add, MSA128D>, IsCommutable;
|
class ADDV_D_DESC : MSA_3R_DESC_BASE<"addv.d", add, MSA128D>, IsCommutable;
|
||||||
|
|
||||||
class ADDVI_B_DESC : MSA_I5_DESC_BASE<"addvi.b", add, vsplati8, MSA128B>;
|
class ADDVI_B_DESC : MSA_I5_DESC_BASE<"addvi.b", add, vsplati8_uimm5, MSA128B>;
|
||||||
class ADDVI_H_DESC : MSA_I5_DESC_BASE<"addvi.h", add, vsplati16, MSA128H>;
|
class ADDVI_H_DESC : MSA_I5_DESC_BASE<"addvi.h", add, vsplati16_uimm5, MSA128H>;
|
||||||
class ADDVI_W_DESC : MSA_I5_DESC_BASE<"addvi.w", add, vsplati32, MSA128W>;
|
class ADDVI_W_DESC : MSA_I5_DESC_BASE<"addvi.w", add, vsplati32_uimm5, MSA128W>;
|
||||||
class ADDVI_D_DESC : MSA_I5_DESC_BASE<"addvi.d", add, vsplati64, MSA128D>;
|
class ADDVI_D_DESC : MSA_I5_DESC_BASE<"addvi.d", add, vsplati64_uimm5, MSA128D>;
|
||||||
|
|
||||||
class AND_V_DESC : MSA_VEC_DESC_BASE<"and.v", and, MSA128B>;
|
class AND_V_DESC : MSA_VEC_DESC_BASE<"and.v", and, MSA128B>;
|
||||||
class AND_V_H_PSEUDO_DESC : MSA_VEC_PSEUDO_BASE<and, MSA128H>;
|
class AND_V_H_PSEUDO_DESC : MSA_VEC_PSEUDO_BASE<and, MSA128H>;
|
||||||
class AND_V_W_PSEUDO_DESC : MSA_VEC_PSEUDO_BASE<and, MSA128W>;
|
class AND_V_W_PSEUDO_DESC : MSA_VEC_PSEUDO_BASE<and, MSA128W>;
|
||||||
class AND_V_D_PSEUDO_DESC : MSA_VEC_PSEUDO_BASE<and, MSA128D>;
|
class AND_V_D_PSEUDO_DESC : MSA_VEC_PSEUDO_BASE<and, MSA128D>;
|
||||||
|
|
||||||
class ANDI_B_DESC : MSA_I8_DESC_BASE<"andi.b", and, vsplati8, MSA128B>;
|
class ANDI_B_DESC : MSA_I8_DESC_BASE<"andi.b", and, vsplati8_uimm8, MSA128B>;
|
||||||
|
|
||||||
class ASUB_S_B_DESC : MSA_3R_DESC_BASE<"asub_s.b", int_mips_asub_s_b, MSA128B>;
|
class ASUB_S_B_DESC : MSA_3R_DESC_BASE<"asub_s.b", int_mips_asub_s_b, MSA128B>;
|
||||||
class ASUB_S_H_DESC : MSA_3R_DESC_BASE<"asub_s.h", int_mips_asub_s_h, MSA128H>;
|
class ASUB_S_H_DESC : MSA_3R_DESC_BASE<"asub_s.h", int_mips_asub_s_h, MSA128H>;
|
||||||
@ -1304,11 +1373,11 @@ class BSEL_V_DESC {
|
|||||||
|
|
||||||
class BSELI_B_DESC {
|
class BSELI_B_DESC {
|
||||||
dag OutOperandList = (outs MSA128B:$wd);
|
dag OutOperandList = (outs MSA128B:$wd);
|
||||||
dag InOperandList = (ins MSA128B:$wd_in, MSA128B:$ws, uimm8:$u8);
|
dag InOperandList = (ins MSA128B:$wd_in, MSA128B:$ws, vsplat_uimm8:$u8);
|
||||||
string AsmString = "bseli.b\t$wd, $ws, $u8";
|
string AsmString = "bseli.b\t$wd, $ws, $u8";
|
||||||
list<dag> Pattern = [(set MSA128B:$wd, (vselect MSA128B:$wd_in,
|
list<dag> Pattern = [(set MSA128B:$wd, (vselect MSA128B:$wd_in,
|
||||||
MSA128B:$ws,
|
MSA128B:$ws,
|
||||||
(vsplati8 immZExt8:$u8)))];
|
vsplati8_uimm8:$u8))];
|
||||||
InstrItinClass Itinerary = NoItinerary;
|
InstrItinClass Itinerary = NoItinerary;
|
||||||
string Constraints = "$wd = $wd_in";
|
string Constraints = "$wd = $wd_in";
|
||||||
}
|
}
|
||||||
@ -1339,14 +1408,14 @@ class CEQ_W_DESC : MSA_3R_DESC_BASE<"ceq.w", vseteq_v4i32, MSA128W>,
|
|||||||
class CEQ_D_DESC : MSA_3R_DESC_BASE<"ceq.d", vseteq_v2i64, MSA128D>,
|
class CEQ_D_DESC : MSA_3R_DESC_BASE<"ceq.d", vseteq_v2i64, MSA128D>,
|
||||||
IsCommutable;
|
IsCommutable;
|
||||||
|
|
||||||
class CEQI_B_DESC : MSA_SI5_DESC_BASE<"ceqi.b", vseteq_v16i8, vsplati8,
|
class CEQI_B_DESC : MSA_I5_DESC_BASE<"ceqi.b", vseteq_v16i8, vsplati8_simm5,
|
||||||
MSA128B>;
|
MSA128B>;
|
||||||
class CEQI_H_DESC : MSA_SI5_DESC_BASE<"ceqi.h", vseteq_v8i16, vsplati16,
|
class CEQI_H_DESC : MSA_I5_DESC_BASE<"ceqi.h", vseteq_v8i16, vsplati16_simm5,
|
||||||
MSA128H>;
|
MSA128H>;
|
||||||
class CEQI_W_DESC : MSA_SI5_DESC_BASE<"ceqi.w", vseteq_v4i32, vsplati32,
|
class CEQI_W_DESC : MSA_I5_DESC_BASE<"ceqi.w", vseteq_v4i32, vsplati32_simm5,
|
||||||
MSA128W>;
|
MSA128W>;
|
||||||
class CEQI_D_DESC : MSA_SI5_DESC_BASE<"ceqi.d", vseteq_v2i64, vsplati64,
|
class CEQI_D_DESC : MSA_I5_DESC_BASE<"ceqi.d", vseteq_v2i64, vsplati64_simm5,
|
||||||
MSA128D>;
|
MSA128D>;
|
||||||
|
|
||||||
class CFCMSA_DESC {
|
class CFCMSA_DESC {
|
||||||
dag OutOperandList = (outs GPR32:$rd);
|
dag OutOperandList = (outs GPR32:$rd);
|
||||||
@ -1366,23 +1435,23 @@ class CLE_U_H_DESC : MSA_3R_DESC_BASE<"cle_u.h", vsetule_v8i16, MSA128H>;
|
|||||||
class CLE_U_W_DESC : MSA_3R_DESC_BASE<"cle_u.w", vsetule_v4i32, MSA128W>;
|
class CLE_U_W_DESC : MSA_3R_DESC_BASE<"cle_u.w", vsetule_v4i32, MSA128W>;
|
||||||
class CLE_U_D_DESC : MSA_3R_DESC_BASE<"cle_u.d", vsetule_v2i64, MSA128D>;
|
class CLE_U_D_DESC : MSA_3R_DESC_BASE<"cle_u.d", vsetule_v2i64, MSA128D>;
|
||||||
|
|
||||||
class CLEI_S_B_DESC : MSA_SI5_DESC_BASE<"clei_s.b", vsetle_v16i8, vsplati8,
|
class CLEI_S_B_DESC : MSA_I5_DESC_BASE<"clei_s.b", vsetle_v16i8,
|
||||||
MSA128B>;
|
vsplati8_simm5, MSA128B>;
|
||||||
class CLEI_S_H_DESC : MSA_SI5_DESC_BASE<"clei_s.h", vsetle_v8i16, vsplati16,
|
class CLEI_S_H_DESC : MSA_I5_DESC_BASE<"clei_s.h", vsetle_v8i16,
|
||||||
MSA128H>;
|
vsplati16_simm5, MSA128H>;
|
||||||
class CLEI_S_W_DESC : MSA_SI5_DESC_BASE<"clei_s.w", vsetle_v4i32, vsplati32,
|
class CLEI_S_W_DESC : MSA_I5_DESC_BASE<"clei_s.w", vsetle_v4i32,
|
||||||
MSA128W>;
|
vsplati32_simm5, MSA128W>;
|
||||||
class CLEI_S_D_DESC : MSA_SI5_DESC_BASE<"clei_s.d", vsetle_v2i64, vsplati64,
|
class CLEI_S_D_DESC : MSA_I5_DESC_BASE<"clei_s.d", vsetle_v2i64,
|
||||||
MSA128D>;
|
vsplati64_simm5, MSA128D>;
|
||||||
|
|
||||||
class CLEI_U_B_DESC : MSA_I5_DESC_BASE<"clei_u.b", vsetule_v16i8, vsplati8,
|
class CLEI_U_B_DESC : MSA_I5_DESC_BASE<"clei_u.b", vsetule_v16i8,
|
||||||
MSA128B>;
|
vsplati8_uimm5, MSA128B>;
|
||||||
class CLEI_U_H_DESC : MSA_I5_DESC_BASE<"clei_u.h", vsetule_v8i16, vsplati16,
|
class CLEI_U_H_DESC : MSA_I5_DESC_BASE<"clei_u.h", vsetule_v8i16,
|
||||||
MSA128H>;
|
vsplati16_uimm5, MSA128H>;
|
||||||
class CLEI_U_W_DESC : MSA_I5_DESC_BASE<"clei_u.w", vsetule_v4i32, vsplati32,
|
class CLEI_U_W_DESC : MSA_I5_DESC_BASE<"clei_u.w", vsetule_v4i32,
|
||||||
MSA128W>;
|
vsplati32_uimm5, MSA128W>;
|
||||||
class CLEI_U_D_DESC : MSA_I5_DESC_BASE<"clei_u.d", vsetule_v2i64, vsplati64,
|
class CLEI_U_D_DESC : MSA_I5_DESC_BASE<"clei_u.d", vsetule_v2i64,
|
||||||
MSA128D>;
|
vsplati64_uimm5, MSA128D>;
|
||||||
|
|
||||||
class CLT_S_B_DESC : MSA_3R_DESC_BASE<"clt_s.b", vsetlt_v16i8, MSA128B>;
|
class CLT_S_B_DESC : MSA_3R_DESC_BASE<"clt_s.b", vsetlt_v16i8, MSA128B>;
|
||||||
class CLT_S_H_DESC : MSA_3R_DESC_BASE<"clt_s.h", vsetlt_v8i16, MSA128H>;
|
class CLT_S_H_DESC : MSA_3R_DESC_BASE<"clt_s.h", vsetlt_v8i16, MSA128H>;
|
||||||
@ -1394,23 +1463,23 @@ class CLT_U_H_DESC : MSA_3R_DESC_BASE<"clt_u.h", vsetult_v8i16, MSA128H>;
|
|||||||
class CLT_U_W_DESC : MSA_3R_DESC_BASE<"clt_u.w", vsetult_v4i32, MSA128W>;
|
class CLT_U_W_DESC : MSA_3R_DESC_BASE<"clt_u.w", vsetult_v4i32, MSA128W>;
|
||||||
class CLT_U_D_DESC : MSA_3R_DESC_BASE<"clt_u.d", vsetult_v2i64, MSA128D>;
|
class CLT_U_D_DESC : MSA_3R_DESC_BASE<"clt_u.d", vsetult_v2i64, MSA128D>;
|
||||||
|
|
||||||
class CLTI_S_B_DESC : MSA_SI5_DESC_BASE<"clti_s.b", vsetlt_v16i8, vsplati8,
|
class CLTI_S_B_DESC : MSA_I5_DESC_BASE<"clti_s.b", vsetlt_v16i8,
|
||||||
MSA128B>;
|
vsplati8_simm5, MSA128B>;
|
||||||
class CLTI_S_H_DESC : MSA_SI5_DESC_BASE<"clti_s.h", vsetlt_v8i16, vsplati16,
|
class CLTI_S_H_DESC : MSA_I5_DESC_BASE<"clti_s.h", vsetlt_v8i16,
|
||||||
MSA128H>;
|
vsplati16_simm5, MSA128H>;
|
||||||
class CLTI_S_W_DESC : MSA_SI5_DESC_BASE<"clti_s.w", vsetlt_v4i32, vsplati32,
|
class CLTI_S_W_DESC : MSA_I5_DESC_BASE<"clti_s.w", vsetlt_v4i32,
|
||||||
MSA128W>;
|
vsplati32_simm5, MSA128W>;
|
||||||
class CLTI_S_D_DESC : MSA_SI5_DESC_BASE<"clti_s.d", vsetlt_v2i64, vsplati64,
|
class CLTI_S_D_DESC : MSA_I5_DESC_BASE<"clti_s.d", vsetlt_v2i64,
|
||||||
MSA128D>;
|
vsplati64_simm5, MSA128D>;
|
||||||
|
|
||||||
class CLTI_U_B_DESC : MSA_I5_DESC_BASE<"clti_u.b", vsetult_v16i8, vsplati8,
|
class CLTI_U_B_DESC : MSA_I5_DESC_BASE<"clti_u.b", vsetult_v16i8,
|
||||||
MSA128B>;
|
vsplati8_uimm5, MSA128B>;
|
||||||
class CLTI_U_H_DESC : MSA_I5_DESC_BASE<"clti_u.h", vsetult_v8i16, vsplati16,
|
class CLTI_U_H_DESC : MSA_I5_DESC_BASE<"clti_u.h", vsetult_v8i16,
|
||||||
MSA128H>;
|
vsplati16_uimm5, MSA128H>;
|
||||||
class CLTI_U_W_DESC : MSA_I5_DESC_BASE<"clti_u.w", vsetult_v4i32, vsplati32,
|
class CLTI_U_W_DESC : MSA_I5_DESC_BASE<"clti_u.w", vsetult_v4i32,
|
||||||
MSA128W>;
|
vsplati32_uimm5, MSA128W>;
|
||||||
class CLTI_U_D_DESC : MSA_I5_DESC_BASE<"clti_u.d", vsetult_v2i64, vsplati64,
|
class CLTI_U_D_DESC : MSA_I5_DESC_BASE<"clti_u.d", vsetult_v2i64,
|
||||||
MSA128D>;
|
vsplati64_uimm5, MSA128D>;
|
||||||
|
|
||||||
class COPY_S_B_DESC : MSA_COPY_DESC_BASE<"copy_s.b", vextract_sext_i8, v16i8,
|
class COPY_S_B_DESC : MSA_COPY_DESC_BASE<"copy_s.b", vextract_sext_i8, v16i8,
|
||||||
GPR32, MSA128B>;
|
GPR32, MSA128B>;
|
||||||
@ -1592,9 +1661,12 @@ class FFQR_W_DESC : MSA_2RF_DESC_BASE<"ffqr.w", int_mips_ffqr_w,
|
|||||||
class FFQR_D_DESC : MSA_2RF_DESC_BASE<"ffqr.d", int_mips_ffqr_d,
|
class FFQR_D_DESC : MSA_2RF_DESC_BASE<"ffqr.d", int_mips_ffqr_d,
|
||||||
MSA128D, MSA128W>;
|
MSA128D, MSA128W>;
|
||||||
|
|
||||||
class FILL_B_DESC : MSA_2R_DESC_BASE<"fill.b", vsplati8, MSA128B, GPR32>;
|
class FILL_B_DESC : MSA_2R_FILL_DESC_BASE<"fill.b", v16i8, vsplati8, MSA128B,
|
||||||
class FILL_H_DESC : MSA_2R_DESC_BASE<"fill.h", vsplati16, MSA128H, GPR32>;
|
GPR32>;
|
||||||
class FILL_W_DESC : MSA_2R_DESC_BASE<"fill.w", vsplati32, MSA128W, GPR32>;
|
class FILL_H_DESC : MSA_2R_FILL_DESC_BASE<"fill.h", v8i16, vsplati16, MSA128H,
|
||||||
|
GPR32>;
|
||||||
|
class FILL_W_DESC : MSA_2R_FILL_DESC_BASE<"fill.w", v4i32, vsplati32, MSA128W,
|
||||||
|
GPR32>;
|
||||||
|
|
||||||
class FLOG2_W_DESC : MSA_2RF_DESC_BASE<"flog2.w", flog2, MSA128W>;
|
class FLOG2_W_DESC : MSA_2RF_DESC_BASE<"flog2.w", flog2, MSA128W>;
|
||||||
class FLOG2_D_DESC : MSA_2RF_DESC_BASE<"flog2.d", flog2, MSA128D>;
|
class FLOG2_D_DESC : MSA_2RF_DESC_BASE<"flog2.d", flog2, MSA128D>;
|
||||||
@ -1779,10 +1851,10 @@ class LD_H_DESC : LD_DESC_BASE<"ld.h", load, v8i16, MSA128H>;
|
|||||||
class LD_W_DESC : LD_DESC_BASE<"ld.w", load, v4i32, MSA128W>;
|
class LD_W_DESC : LD_DESC_BASE<"ld.w", load, v4i32, MSA128W>;
|
||||||
class LD_D_DESC : LD_DESC_BASE<"ld.d", load, v2i64, MSA128D>;
|
class LD_D_DESC : LD_DESC_BASE<"ld.d", load, v2i64, MSA128D>;
|
||||||
|
|
||||||
class LDI_B_DESC : MSA_I10_DESC_BASE<"ldi.b", vsplati8, MSA128B>;
|
class LDI_B_DESC : MSA_I10_LDI_DESC_BASE<"ldi.b", MSA128B>;
|
||||||
class LDI_H_DESC : MSA_I10_DESC_BASE<"ldi.h", vsplati16, MSA128H>;
|
class LDI_H_DESC : MSA_I10_LDI_DESC_BASE<"ldi.h", MSA128H>;
|
||||||
class LDI_W_DESC : MSA_I10_DESC_BASE<"ldi.w", vsplati32, MSA128W>;
|
class LDI_W_DESC : MSA_I10_LDI_DESC_BASE<"ldi.w", MSA128W>;
|
||||||
class LDI_D_DESC : MSA_I10_DESC_BASE<"ldi.d", vsplati64, MSA128D>;
|
class LDI_D_DESC : MSA_I10_LDI_DESC_BASE<"ldi.d", MSA128D>;
|
||||||
|
|
||||||
class LDX_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
|
class LDX_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
|
||||||
ValueType TyNode, RegisterClass RCWD,
|
ValueType TyNode, RegisterClass RCWD,
|
||||||
@ -1830,22 +1902,22 @@ class MAX_U_H_DESC : MSA_3R_DESC_BASE<"max_u.h", MipsVUMax, MSA128H>;
|
|||||||
class MAX_U_W_DESC : MSA_3R_DESC_BASE<"max_u.w", MipsVUMax, MSA128W>;
|
class MAX_U_W_DESC : MSA_3R_DESC_BASE<"max_u.w", MipsVUMax, MSA128W>;
|
||||||
class MAX_U_D_DESC : MSA_3R_DESC_BASE<"max_u.d", MipsVUMax, MSA128D>;
|
class MAX_U_D_DESC : MSA_3R_DESC_BASE<"max_u.d", MipsVUMax, MSA128D>;
|
||||||
|
|
||||||
class MAXI_S_B_DESC : MSA_I5_DESC_BASE<"maxi_s.b", MipsVSMax, vsplati8,
|
class MAXI_S_B_DESC : MSA_I5_DESC_BASE<"maxi_s.b", MipsVSMax, vsplati8_simm5,
|
||||||
MSA128B>;
|
MSA128B>;
|
||||||
class MAXI_S_H_DESC : MSA_I5_DESC_BASE<"maxi_s.h", MipsVSMax, vsplati16,
|
class MAXI_S_H_DESC : MSA_I5_DESC_BASE<"maxi_s.h", MipsVSMax, vsplati16_simm5,
|
||||||
MSA128H>;
|
MSA128H>;
|
||||||
class MAXI_S_W_DESC : MSA_I5_DESC_BASE<"maxi_s.w", MipsVSMax, vsplati32,
|
class MAXI_S_W_DESC : MSA_I5_DESC_BASE<"maxi_s.w", MipsVSMax, vsplati32_simm5,
|
||||||
MSA128W>;
|
MSA128W>;
|
||||||
class MAXI_S_D_DESC : MSA_I5_DESC_BASE<"maxi_s.d", MipsVSMax, vsplati64,
|
class MAXI_S_D_DESC : MSA_I5_DESC_BASE<"maxi_s.d", MipsVSMax, vsplati64_simm5,
|
||||||
MSA128D>;
|
MSA128D>;
|
||||||
|
|
||||||
class MAXI_U_B_DESC : MSA_I5_DESC_BASE<"maxi_u.b", MipsVUMax, vsplati8,
|
class MAXI_U_B_DESC : MSA_I5_DESC_BASE<"maxi_u.b", MipsVUMax, vsplati8_uimm5,
|
||||||
MSA128B>;
|
MSA128B>;
|
||||||
class MAXI_U_H_DESC : MSA_I5_DESC_BASE<"maxi_u.h", MipsVUMax, vsplati16,
|
class MAXI_U_H_DESC : MSA_I5_DESC_BASE<"maxi_u.h", MipsVUMax, vsplati16_uimm5,
|
||||||
MSA128H>;
|
MSA128H>;
|
||||||
class MAXI_U_W_DESC : MSA_I5_DESC_BASE<"maxi_u.w", MipsVUMax, vsplati32,
|
class MAXI_U_W_DESC : MSA_I5_DESC_BASE<"maxi_u.w", MipsVUMax, vsplati32_uimm5,
|
||||||
MSA128W>;
|
MSA128W>;
|
||||||
class MAXI_U_D_DESC : MSA_I5_DESC_BASE<"maxi_u.d", MipsVUMax, vsplati64,
|
class MAXI_U_D_DESC : MSA_I5_DESC_BASE<"maxi_u.d", MipsVUMax, vsplati64_uimm5,
|
||||||
MSA128D>;
|
MSA128D>;
|
||||||
|
|
||||||
class MIN_A_B_DESC : MSA_3R_DESC_BASE<"min_a.b", int_mips_min_a_b, MSA128B>;
|
class MIN_A_B_DESC : MSA_3R_DESC_BASE<"min_a.b", int_mips_min_a_b, MSA128B>;
|
||||||
@ -1863,22 +1935,22 @@ class MIN_U_H_DESC : MSA_3R_DESC_BASE<"min_u.h", MipsVUMin, MSA128H>;
|
|||||||
class MIN_U_W_DESC : MSA_3R_DESC_BASE<"min_u.w", MipsVUMin, MSA128W>;
|
class MIN_U_W_DESC : MSA_3R_DESC_BASE<"min_u.w", MipsVUMin, MSA128W>;
|
||||||
class MIN_U_D_DESC : MSA_3R_DESC_BASE<"min_u.d", MipsVUMin, MSA128D>;
|
class MIN_U_D_DESC : MSA_3R_DESC_BASE<"min_u.d", MipsVUMin, MSA128D>;
|
||||||
|
|
||||||
class MINI_S_B_DESC : MSA_I5_DESC_BASE<"mini_s.b", MipsVSMin, vsplati8,
|
class MINI_S_B_DESC : MSA_I5_DESC_BASE<"mini_s.b", MipsVSMin, vsplati8_simm5,
|
||||||
MSA128B>;
|
MSA128B>;
|
||||||
class MINI_S_H_DESC : MSA_I5_DESC_BASE<"mini_s.h", MipsVSMin, vsplati16,
|
class MINI_S_H_DESC : MSA_I5_DESC_BASE<"mini_s.h", MipsVSMin, vsplati16_simm5,
|
||||||
MSA128H>;
|
MSA128H>;
|
||||||
class MINI_S_W_DESC : MSA_I5_DESC_BASE<"mini_s.w", MipsVSMin, vsplati32,
|
class MINI_S_W_DESC : MSA_I5_DESC_BASE<"mini_s.w", MipsVSMin, vsplati32_simm5,
|
||||||
MSA128W>;
|
MSA128W>;
|
||||||
class MINI_S_D_DESC : MSA_I5_DESC_BASE<"mini_s.d", MipsVSMin, vsplati64,
|
class MINI_S_D_DESC : MSA_I5_DESC_BASE<"mini_s.d", MipsVSMin, vsplati64_simm5,
|
||||||
MSA128D>;
|
MSA128D>;
|
||||||
|
|
||||||
class MINI_U_B_DESC : MSA_I5_DESC_BASE<"mini_u.b", MipsVUMin, vsplati8,
|
class MINI_U_B_DESC : MSA_I5_DESC_BASE<"mini_u.b", MipsVUMin, vsplati8_uimm5,
|
||||||
MSA128B>;
|
MSA128B>;
|
||||||
class MINI_U_H_DESC : MSA_I5_DESC_BASE<"mini_u.h", MipsVUMin, vsplati16,
|
class MINI_U_H_DESC : MSA_I5_DESC_BASE<"mini_u.h", MipsVUMin, vsplati16_uimm5,
|
||||||
MSA128H>;
|
MSA128H>;
|
||||||
class MINI_U_W_DESC : MSA_I5_DESC_BASE<"mini_u.w", MipsVUMin, vsplati32,
|
class MINI_U_W_DESC : MSA_I5_DESC_BASE<"mini_u.w", MipsVUMin, vsplati32_uimm5,
|
||||||
MSA128W>;
|
MSA128W>;
|
||||||
class MINI_U_D_DESC : MSA_I5_DESC_BASE<"mini_u.d", MipsVUMin, vsplati64,
|
class MINI_U_D_DESC : MSA_I5_DESC_BASE<"mini_u.d", MipsVUMin, vsplati64_uimm5,
|
||||||
MSA128D>;
|
MSA128D>;
|
||||||
|
|
||||||
class MOD_S_B_DESC : MSA_3R_DESC_BASE<"mod_s.b", int_mips_mod_s_b, MSA128B>;
|
class MOD_S_B_DESC : MSA_3R_DESC_BASE<"mod_s.b", int_mips_mod_s_b, MSA128B>;
|
||||||
@ -1942,14 +2014,15 @@ class NOR_V_H_PSEUDO_DESC : MSA_VEC_PSEUDO_BASE<MipsVNOR, MSA128H>;
|
|||||||
class NOR_V_W_PSEUDO_DESC : MSA_VEC_PSEUDO_BASE<MipsVNOR, MSA128W>;
|
class NOR_V_W_PSEUDO_DESC : MSA_VEC_PSEUDO_BASE<MipsVNOR, MSA128W>;
|
||||||
class NOR_V_D_PSEUDO_DESC : MSA_VEC_PSEUDO_BASE<MipsVNOR, MSA128D>;
|
class NOR_V_D_PSEUDO_DESC : MSA_VEC_PSEUDO_BASE<MipsVNOR, MSA128D>;
|
||||||
|
|
||||||
class NORI_B_DESC : MSA_I8_DESC_BASE<"nori.b", MipsVNOR, vsplati8, MSA128B>;
|
class NORI_B_DESC : MSA_I8_DESC_BASE<"nori.b", MipsVNOR, vsplati8_uimm8,
|
||||||
|
MSA128B>;
|
||||||
|
|
||||||
class OR_V_DESC : MSA_VEC_DESC_BASE<"or.v", or, MSA128B>;
|
class OR_V_DESC : MSA_VEC_DESC_BASE<"or.v", or, MSA128B>;
|
||||||
class OR_V_H_PSEUDO_DESC : MSA_VEC_PSEUDO_BASE<or, MSA128H>;
|
class OR_V_H_PSEUDO_DESC : MSA_VEC_PSEUDO_BASE<or, MSA128H>;
|
||||||
class OR_V_W_PSEUDO_DESC : MSA_VEC_PSEUDO_BASE<or, MSA128W>;
|
class OR_V_W_PSEUDO_DESC : MSA_VEC_PSEUDO_BASE<or, MSA128W>;
|
||||||
class OR_V_D_PSEUDO_DESC : MSA_VEC_PSEUDO_BASE<or, MSA128D>;
|
class OR_V_D_PSEUDO_DESC : MSA_VEC_PSEUDO_BASE<or, MSA128D>;
|
||||||
|
|
||||||
class ORI_B_DESC : MSA_I8_DESC_BASE<"ori.b", or, vsplati8, MSA128B>;
|
class ORI_B_DESC : MSA_I8_DESC_BASE<"ori.b", or, vsplati8_uimm8, MSA128B>;
|
||||||
|
|
||||||
class PCKEV_B_DESC : MSA_3R_DESC_BASE<"pckev.b", int_mips_pckev_b, MSA128B>;
|
class PCKEV_B_DESC : MSA_3R_DESC_BASE<"pckev.b", int_mips_pckev_b, MSA128B>;
|
||||||
class PCKEV_H_DESC : MSA_3R_DESC_BASE<"pckev.h", int_mips_pckev_h, MSA128H>;
|
class PCKEV_H_DESC : MSA_3R_DESC_BASE<"pckev.h", int_mips_pckev_h, MSA128H>;
|
||||||
@ -1995,10 +2068,14 @@ class SLL_H_DESC : MSA_3R_DESC_BASE<"sll.h", shl, MSA128H>;
|
|||||||
class SLL_W_DESC : MSA_3R_DESC_BASE<"sll.w", shl, MSA128W>;
|
class SLL_W_DESC : MSA_3R_DESC_BASE<"sll.w", shl, MSA128W>;
|
||||||
class SLL_D_DESC : MSA_3R_DESC_BASE<"sll.d", shl, MSA128D>;
|
class SLL_D_DESC : MSA_3R_DESC_BASE<"sll.d", shl, MSA128D>;
|
||||||
|
|
||||||
class SLLI_B_DESC : MSA_BIT_SPLATB_DESC_BASE<"slli.b", shl, MSA128B>;
|
class SLLI_B_DESC : MSA_BIT_SPLAT_DESC_BASE<"slli.b", shl, vsplati8_uimm3,
|
||||||
class SLLI_H_DESC : MSA_BIT_SPLATH_DESC_BASE<"slli.h", shl, MSA128H>;
|
MSA128B>;
|
||||||
class SLLI_W_DESC : MSA_BIT_SPLATW_DESC_BASE<"slli.w", shl, MSA128W>;
|
class SLLI_H_DESC : MSA_BIT_SPLAT_DESC_BASE<"slli.h", shl, vsplati16_uimm4,
|
||||||
class SLLI_D_DESC : MSA_BIT_SPLATD_DESC_BASE<"slli.d", shl, MSA128D>;
|
MSA128H>;
|
||||||
|
class SLLI_W_DESC : MSA_BIT_SPLAT_DESC_BASE<"slli.w", shl, vsplati32_uimm5,
|
||||||
|
MSA128W>;
|
||||||
|
class SLLI_D_DESC : MSA_BIT_SPLAT_DESC_BASE<"slli.d", shl, vsplati64_uimm6,
|
||||||
|
MSA128D>;
|
||||||
|
|
||||||
class SPLAT_B_DESC : MSA_3R_DESC_BASE<"splat.b", int_mips_splat_b, MSA128B,
|
class SPLAT_B_DESC : MSA_3R_DESC_BASE<"splat.b", int_mips_splat_b, MSA128B,
|
||||||
MSA128B, GPR32>;
|
MSA128B, GPR32>;
|
||||||
@ -2023,10 +2100,14 @@ class SRA_H_DESC : MSA_3R_DESC_BASE<"sra.h", sra, MSA128H>;
|
|||||||
class SRA_W_DESC : MSA_3R_DESC_BASE<"sra.w", sra, MSA128W>;
|
class SRA_W_DESC : MSA_3R_DESC_BASE<"sra.w", sra, MSA128W>;
|
||||||
class SRA_D_DESC : MSA_3R_DESC_BASE<"sra.d", sra, MSA128D>;
|
class SRA_D_DESC : MSA_3R_DESC_BASE<"sra.d", sra, MSA128D>;
|
||||||
|
|
||||||
class SRAI_B_DESC : MSA_BIT_SPLATB_DESC_BASE<"srai.b", sra, MSA128B>;
|
class SRAI_B_DESC : MSA_BIT_SPLAT_DESC_BASE<"srai.b", sra, vsplati8_uimm3,
|
||||||
class SRAI_H_DESC : MSA_BIT_SPLATH_DESC_BASE<"srai.h", sra, MSA128H>;
|
MSA128B>;
|
||||||
class SRAI_W_DESC : MSA_BIT_SPLATW_DESC_BASE<"srai.w", sra, MSA128W>;
|
class SRAI_H_DESC : MSA_BIT_SPLAT_DESC_BASE<"srai.h", sra, vsplati16_uimm4,
|
||||||
class SRAI_D_DESC : MSA_BIT_SPLATD_DESC_BASE<"srai.d", sra, MSA128D>;
|
MSA128H>;
|
||||||
|
class SRAI_W_DESC : MSA_BIT_SPLAT_DESC_BASE<"srai.w", sra, vsplati32_uimm5,
|
||||||
|
MSA128W>;
|
||||||
|
class SRAI_D_DESC : MSA_BIT_SPLAT_DESC_BASE<"srai.d", sra, vsplati64_uimm6,
|
||||||
|
MSA128D>;
|
||||||
|
|
||||||
class SRAR_B_DESC : MSA_3R_DESC_BASE<"srar.b", int_mips_srar_b, MSA128B>;
|
class SRAR_B_DESC : MSA_3R_DESC_BASE<"srar.b", int_mips_srar_b, MSA128B>;
|
||||||
class SRAR_H_DESC : MSA_3R_DESC_BASE<"srar.h", int_mips_srar_h, MSA128H>;
|
class SRAR_H_DESC : MSA_3R_DESC_BASE<"srar.h", int_mips_srar_h, MSA128H>;
|
||||||
@ -2043,10 +2124,14 @@ class SRL_H_DESC : MSA_3R_DESC_BASE<"srl.h", srl, MSA128H>;
|
|||||||
class SRL_W_DESC : MSA_3R_DESC_BASE<"srl.w", srl, MSA128W>;
|
class SRL_W_DESC : MSA_3R_DESC_BASE<"srl.w", srl, MSA128W>;
|
||||||
class SRL_D_DESC : MSA_3R_DESC_BASE<"srl.d", srl, MSA128D>;
|
class SRL_D_DESC : MSA_3R_DESC_BASE<"srl.d", srl, MSA128D>;
|
||||||
|
|
||||||
class SRLI_B_DESC : MSA_BIT_SPLATB_DESC_BASE<"srli.b", srl, MSA128B>;
|
class SRLI_B_DESC : MSA_BIT_SPLAT_DESC_BASE<"srli.b", srl, vsplati8_uimm3,
|
||||||
class SRLI_H_DESC : MSA_BIT_SPLATH_DESC_BASE<"srli.h", srl, MSA128H>;
|
MSA128B>;
|
||||||
class SRLI_W_DESC : MSA_BIT_SPLATW_DESC_BASE<"srli.w", srl, MSA128W>;
|
class SRLI_H_DESC : MSA_BIT_SPLAT_DESC_BASE<"srli.h", srl, vsplati16_uimm4,
|
||||||
class SRLI_D_DESC : MSA_BIT_SPLATD_DESC_BASE<"srli.d", srl, MSA128D>;
|
MSA128H>;
|
||||||
|
class SRLI_W_DESC : MSA_BIT_SPLAT_DESC_BASE<"srli.w", srl, vsplati32_uimm5,
|
||||||
|
MSA128W>;
|
||||||
|
class SRLI_D_DESC : MSA_BIT_SPLAT_DESC_BASE<"srli.d", srl, vsplati64_uimm6,
|
||||||
|
MSA128D>;
|
||||||
|
|
||||||
class SRLR_B_DESC : MSA_3R_DESC_BASE<"srlr.b", int_mips_srlr_b, MSA128B>;
|
class SRLR_B_DESC : MSA_3R_DESC_BASE<"srlr.b", int_mips_srlr_b, MSA128B>;
|
||||||
class SRLR_H_DESC : MSA_3R_DESC_BASE<"srlr.h", int_mips_srlr_h, MSA128H>;
|
class SRLR_H_DESC : MSA_3R_DESC_BASE<"srlr.h", int_mips_srlr_h, MSA128H>;
|
||||||
@ -2123,10 +2208,10 @@ class SUBV_H_DESC : MSA_3R_DESC_BASE<"subv.h", sub, MSA128H>;
|
|||||||
class SUBV_W_DESC : MSA_3R_DESC_BASE<"subv.w", sub, MSA128W>;
|
class SUBV_W_DESC : MSA_3R_DESC_BASE<"subv.w", sub, MSA128W>;
|
||||||
class SUBV_D_DESC : MSA_3R_DESC_BASE<"subv.d", sub, MSA128D>;
|
class SUBV_D_DESC : MSA_3R_DESC_BASE<"subv.d", sub, MSA128D>;
|
||||||
|
|
||||||
class SUBVI_B_DESC : MSA_I5_DESC_BASE<"subvi.b", sub, vsplati8, MSA128B>;
|
class SUBVI_B_DESC : MSA_I5_DESC_BASE<"subvi.b", sub, vsplati8_uimm5, MSA128B>;
|
||||||
class SUBVI_H_DESC : MSA_I5_DESC_BASE<"subvi.h", sub, vsplati16, MSA128H>;
|
class SUBVI_H_DESC : MSA_I5_DESC_BASE<"subvi.h", sub, vsplati16_uimm5, MSA128H>;
|
||||||
class SUBVI_W_DESC : MSA_I5_DESC_BASE<"subvi.w", sub, vsplati32, MSA128W>;
|
class SUBVI_W_DESC : MSA_I5_DESC_BASE<"subvi.w", sub, vsplati32_uimm5, MSA128W>;
|
||||||
class SUBVI_D_DESC : MSA_I5_DESC_BASE<"subvi.d", sub, vsplati64, MSA128D>;
|
class SUBVI_D_DESC : MSA_I5_DESC_BASE<"subvi.d", sub, vsplati64_uimm5, MSA128D>;
|
||||||
|
|
||||||
class VSHF_B_DESC : MSA_3R_DESC_BASE<"vshf.b", int_mips_vshf_b, MSA128B>;
|
class VSHF_B_DESC : MSA_3R_DESC_BASE<"vshf.b", int_mips_vshf_b, MSA128B>;
|
||||||
class VSHF_H_DESC : MSA_3R_DESC_BASE<"vshf.h", int_mips_vshf_h, MSA128H>;
|
class VSHF_H_DESC : MSA_3R_DESC_BASE<"vshf.h", int_mips_vshf_h, MSA128H>;
|
||||||
@ -2138,7 +2223,7 @@ class XOR_V_H_PSEUDO_DESC : MSA_VEC_PSEUDO_BASE<xor, MSA128H>;
|
|||||||
class XOR_V_W_PSEUDO_DESC : MSA_VEC_PSEUDO_BASE<xor, MSA128W>;
|
class XOR_V_W_PSEUDO_DESC : MSA_VEC_PSEUDO_BASE<xor, MSA128W>;
|
||||||
class XOR_V_D_PSEUDO_DESC : MSA_VEC_PSEUDO_BASE<xor, MSA128D>;
|
class XOR_V_D_PSEUDO_DESC : MSA_VEC_PSEUDO_BASE<xor, MSA128D>;
|
||||||
|
|
||||||
class XORI_B_DESC : MSA_I8_DESC_BASE<"xori.b", xor, vsplati8, MSA128B>;
|
class XORI_B_DESC : MSA_I8_DESC_BASE<"xori.b", xor, vsplati8_uimm8, MSA128B>;
|
||||||
|
|
||||||
// Instruction defs.
|
// Instruction defs.
|
||||||
def ADD_A_B : ADD_A_B_ENC, ADD_A_B_DESC;
|
def ADD_A_B : ADD_A_B_ENC, ADD_A_B_DESC;
|
||||||
|
@ -374,6 +374,147 @@ bool MipsSEDAGToDAGISel::selectIntAddrMM(SDValue Addr, SDValue &Base,
|
|||||||
selectAddrDefault(Addr, Base, Offset);
|
selectAddrDefault(Addr, Base, Offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Select constant vector splats.
|
||||||
|
//
|
||||||
|
// Returns true and sets Imm if:
|
||||||
|
// * MSA is enabled
|
||||||
|
// * N is a ISD::BUILD_VECTOR representing a constant splat
|
||||||
|
// * The splat value fits in a signed 32-bit value.
|
||||||
|
//
|
||||||
|
// That last requirement isn't strictly a requirement of the instruction set
|
||||||
|
// but it simplifies the callers by allowing them to assume they don't have to
|
||||||
|
// handle 64-bit values. The callers will also be placing stricter requirements
|
||||||
|
// on the immediates so this doesn't prohibit selection of legal immediates.
|
||||||
|
bool MipsSEDAGToDAGISel::selectVSplat(SDNode *N, APInt &Imm) const {
|
||||||
|
if (!Subtarget.hasMSA())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
BuildVectorSDNode *Node = dyn_cast<BuildVectorSDNode>(N);
|
||||||
|
|
||||||
|
if (Node == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
APInt SplatValue, SplatUndef;
|
||||||
|
unsigned SplatBitSize;
|
||||||
|
bool HasAnyUndefs;
|
||||||
|
|
||||||
|
if (!Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
|
||||||
|
HasAnyUndefs, 8,
|
||||||
|
!Subtarget.isLittle()))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// None of the immediate forms can handle more than 32 bits
|
||||||
|
if (!SplatValue.isIntN(32))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Imm = SplatValue;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select constant vector splats.
|
||||||
|
//
|
||||||
|
// In addition to the requirements of selectVSplat(), this function returns
|
||||||
|
// true and sets Imm if:
|
||||||
|
// * The splat value is the same width as the elements of the vector
|
||||||
|
// * The splat value fits in an integer with the specified signed-ness and
|
||||||
|
// width.
|
||||||
|
//
|
||||||
|
// This function looks through ISD::BITCAST nodes.
|
||||||
|
// TODO: This might not be appropriate for big-endian MSA since BITCAST is
|
||||||
|
// sometimes a shuffle in big-endian mode.
|
||||||
|
//
|
||||||
|
// It's worth noting that this function is not used as part of the selection
|
||||||
|
// of ldi.[bhwd] since it does not permit using the wrong-typed ldi.[bhwd]
|
||||||
|
// instruction to achieve the desired bit pattern. ldi.[bhwd] is selected in
|
||||||
|
// MipsSEDAGToDAGISel::selectNode.
|
||||||
|
bool MipsSEDAGToDAGISel::
|
||||||
|
selectVSplatCommon(SDValue N, SDValue &Imm, bool Signed,
|
||||||
|
unsigned ImmBitSize) const {
|
||||||
|
APInt ImmValue;
|
||||||
|
EVT EltTy = N->getValueType(0).getVectorElementType();
|
||||||
|
|
||||||
|
if (N->getOpcode() == ISD::BITCAST)
|
||||||
|
N = N->getOperand(0);
|
||||||
|
|
||||||
|
if (selectVSplat (N.getNode(), ImmValue) &&
|
||||||
|
ImmValue.getBitWidth() == EltTy.getSizeInBits()) {
|
||||||
|
if (( Signed && ImmValue.isSignedIntN(ImmBitSize)) ||
|
||||||
|
(!Signed && ImmValue.isIntN(ImmBitSize))) {
|
||||||
|
Imm = CurDAG->getTargetConstant(ImmValue, EltTy);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select constant vector splats.
|
||||||
|
bool MipsSEDAGToDAGISel::
|
||||||
|
selectVSplatUimm3(SDValue N, SDValue &Imm) const {
|
||||||
|
return selectVSplatCommon(N, Imm, false, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select constant vector splats.
|
||||||
|
bool MipsSEDAGToDAGISel::
|
||||||
|
selectVSplatUimm4(SDValue N, SDValue &Imm) const {
|
||||||
|
return selectVSplatCommon(N, Imm, false, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select constant vector splats.
|
||||||
|
bool MipsSEDAGToDAGISel::
|
||||||
|
selectVSplatUimm5(SDValue N, SDValue &Imm) const {
|
||||||
|
return selectVSplatCommon(N, Imm, false, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select constant vector splats.
|
||||||
|
bool MipsSEDAGToDAGISel::
|
||||||
|
selectVSplatUimm6(SDValue N, SDValue &Imm) const {
|
||||||
|
return selectVSplatCommon(N, Imm, false, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select constant vector splats.
|
||||||
|
bool MipsSEDAGToDAGISel::
|
||||||
|
selectVSplatUimm8(SDValue N, SDValue &Imm) const {
|
||||||
|
return selectVSplatCommon(N, Imm, false, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select constant vector splats.
|
||||||
|
bool MipsSEDAGToDAGISel::
|
||||||
|
selectVSplatSimm5(SDValue N, SDValue &Imm) const {
|
||||||
|
return selectVSplatCommon(N, Imm, true, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select constant vector splats whose value is a power of 2.
|
||||||
|
//
|
||||||
|
// In addition to the requirements of selectVSplat(), this function returns
|
||||||
|
// true and sets Imm if:
|
||||||
|
// * The splat value is the same width as the elements of the vector
|
||||||
|
// * The splat value is a power of two.
|
||||||
|
//
|
||||||
|
// This function looks through ISD::BITCAST nodes.
|
||||||
|
// TODO: This might not be appropriate for big-endian MSA since BITCAST is
|
||||||
|
// sometimes a shuffle in big-endian mode.
|
||||||
|
bool MipsSEDAGToDAGISel::selectVSplatUimmPow2(SDValue N, SDValue &Imm) const {
|
||||||
|
APInt ImmValue;
|
||||||
|
EVT EltTy = N->getValueType(0).getVectorElementType();
|
||||||
|
|
||||||
|
if (N->getOpcode() == ISD::BITCAST)
|
||||||
|
N = N->getOperand(0);
|
||||||
|
|
||||||
|
if (selectVSplat (N.getNode(), ImmValue) &&
|
||||||
|
ImmValue.getBitWidth() == EltTy.getSizeInBits()) {
|
||||||
|
int32_t Log2 = ImmValue.exactLogBase2();
|
||||||
|
|
||||||
|
if (Log2 != -1) {
|
||||||
|
Imm = CurDAG->getTargetConstant(Log2, EltTy);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) {
|
std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) {
|
||||||
unsigned Opcode = Node->getOpcode();
|
unsigned Opcode = Node->getOpcode();
|
||||||
SDLoc DL(Node);
|
SDLoc DL(Node);
|
||||||
@ -545,6 +686,82 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) {
|
|||||||
MVT::Untyped, Ops);
|
MVT::Untyped, Ops);
|
||||||
return std::make_pair(true, Res);
|
return std::make_pair(true, Res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case ISD::BUILD_VECTOR: {
|
||||||
|
// Select appropriate ldi.[bhwd] instructions for constant splats of
|
||||||
|
// 128-bit when MSA is enabled. Fixup any register class mismatches that
|
||||||
|
// occur as a result.
|
||||||
|
//
|
||||||
|
// This allows the compiler to use a wider range of immediates than would
|
||||||
|
// otherwise be allowed. If, for example, v4i32 could only use ldi.h then
|
||||||
|
// it would not be possible to load { 0x01010101, 0x01010101, 0x01010101,
|
||||||
|
// 0x01010101 } without using a constant pool. This would be sub-optimal
|
||||||
|
// when // 'ldi.b wd, 1' is capable of producing that bit-pattern in the
|
||||||
|
// same set/ of registers. Similarly, ldi.h isn't capable of producing {
|
||||||
|
// 0x00000000, 0x00000001, 0x00000000, 0x00000001 } but 'ldi.d wd, 1' can.
|
||||||
|
|
||||||
|
BuildVectorSDNode *BVN = cast<BuildVectorSDNode>(Node);
|
||||||
|
APInt SplatValue, SplatUndef;
|
||||||
|
unsigned SplatBitSize;
|
||||||
|
bool HasAnyUndefs;
|
||||||
|
unsigned LdiOp;
|
||||||
|
EVT ResVecTy = BVN->getValueType(0);
|
||||||
|
EVT ViaVecTy;
|
||||||
|
|
||||||
|
if (!Subtarget.hasMSA() || !BVN->getValueType(0).is128BitVector())
|
||||||
|
return std::make_pair(false, (SDNode*)NULL);
|
||||||
|
|
||||||
|
if (!BVN->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
|
||||||
|
HasAnyUndefs, 8,
|
||||||
|
!Subtarget.isLittle()))
|
||||||
|
return std::make_pair(false, (SDNode*)NULL);
|
||||||
|
|
||||||
|
switch (SplatBitSize) {
|
||||||
|
default:
|
||||||
|
return std::make_pair(false, (SDNode*)NULL);
|
||||||
|
case 8:
|
||||||
|
LdiOp = Mips::LDI_B;
|
||||||
|
ViaVecTy = MVT::v16i8;
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
LdiOp = Mips::LDI_H;
|
||||||
|
ViaVecTy = MVT::v8i16;
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
LdiOp = Mips::LDI_W;
|
||||||
|
ViaVecTy = MVT::v4i32;
|
||||||
|
break;
|
||||||
|
case 64:
|
||||||
|
LdiOp = Mips::LDI_D;
|
||||||
|
ViaVecTy = MVT::v2i64;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SplatValue.isSignedIntN(10))
|
||||||
|
return std::make_pair(false, (SDNode*)NULL);
|
||||||
|
|
||||||
|
SDValue Imm = CurDAG->getTargetConstant(SplatValue,
|
||||||
|
ViaVecTy.getVectorElementType());
|
||||||
|
|
||||||
|
SDNode *Res = CurDAG->getMachineNode(LdiOp, SDLoc(Node), ViaVecTy, Imm);
|
||||||
|
|
||||||
|
if (ResVecTy != ViaVecTy) {
|
||||||
|
// If LdiOp is writing to a different register class to ResVecTy, then
|
||||||
|
// fix it up here. This COPY_TO_REGCLASS should never cause a move.v
|
||||||
|
// since the source and destination register sets contain the same
|
||||||
|
// registers.
|
||||||
|
const TargetLowering *TLI = getTargetLowering();
|
||||||
|
MVT ResVecTySimple = ResVecTy.getSimpleVT();
|
||||||
|
const TargetRegisterClass *RC = TLI->getRegClassFor(ResVecTySimple);
|
||||||
|
Res = CurDAG->getMachineNode(Mips::COPY_TO_REGCLASS, SDLoc(Node),
|
||||||
|
ResVecTy, SDValue(Res, 0),
|
||||||
|
CurDAG->getTargetConstant(RC->getID(),
|
||||||
|
MVT::i32));
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::make_pair(true, Res);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::make_pair(false, (SDNode*)NULL);
|
return std::make_pair(false, (SDNode*)NULL);
|
||||||
|
@ -58,6 +58,26 @@ private:
|
|||||||
virtual bool selectIntAddrMM(SDValue Addr, SDValue &Base,
|
virtual bool selectIntAddrMM(SDValue Addr, SDValue &Base,
|
||||||
SDValue &Offset) const;
|
SDValue &Offset) const;
|
||||||
|
|
||||||
|
/// \brief Select constant vector splats.
|
||||||
|
virtual bool selectVSplat(SDNode *N, APInt &Imm) const;
|
||||||
|
/// \brief Select constant vector splats whose value fits in a given integer.
|
||||||
|
virtual bool selectVSplatCommon(SDValue N, SDValue &Imm, bool Signed,
|
||||||
|
unsigned ImmBitSize) const;
|
||||||
|
/// \brief Select constant vector splats whose value fits in a uimm3.
|
||||||
|
virtual bool selectVSplatUimm3(SDValue N, SDValue &Imm) const;
|
||||||
|
/// \brief Select constant vector splats whose value fits in a uimm4.
|
||||||
|
virtual bool selectVSplatUimm4(SDValue N, SDValue &Imm) const;
|
||||||
|
/// \brief Select constant vector splats whose value fits in a uimm5.
|
||||||
|
virtual bool selectVSplatUimm5(SDValue N, SDValue &Imm) const;
|
||||||
|
/// \brief Select constant vector splats whose value fits in a uimm6.
|
||||||
|
virtual bool selectVSplatUimm6(SDValue N, SDValue &Imm) const;
|
||||||
|
/// \brief Select constant vector splats whose value fits in a uimm8.
|
||||||
|
virtual bool selectVSplatUimm8(SDValue N, SDValue &Imm) const;
|
||||||
|
/// \brief Select constant vector splats whose value fits in a simm5.
|
||||||
|
virtual bool selectVSplatSimm5(SDValue N, SDValue &Imm) const;
|
||||||
|
/// \brief Select constant vector splats whose value is a power of 2.
|
||||||
|
virtual bool selectVSplatUimmPow2(SDValue N, SDValue &Imm) const;
|
||||||
|
|
||||||
virtual std::pair<bool, SDNode*> selectNode(SDNode *Node);
|
virtual std::pair<bool, SDNode*> selectNode(SDNode *Node);
|
||||||
|
|
||||||
virtual void processFunctionAfterISel(MachineFunction &MF);
|
virtual void processFunctionAfterISel(MachineFunction &MF);
|
||||||
|
@ -738,22 +738,11 @@ static SDValue performXORCombine(SDNode *N, SelectionDAG &DAG,
|
|||||||
SDValue Op0 = N->getOperand(0);
|
SDValue Op0 = N->getOperand(0);
|
||||||
SDValue Op1 = N->getOperand(1);
|
SDValue Op1 = N->getOperand(1);
|
||||||
SDValue NotOp;
|
SDValue NotOp;
|
||||||
ConstantSDNode *Const;
|
|
||||||
|
|
||||||
if (ISD::isBuildVectorAllOnes(Op0.getNode()))
|
if (ISD::isBuildVectorAllOnes(Op0.getNode()))
|
||||||
NotOp = Op1;
|
NotOp = Op1;
|
||||||
else if (ISD::isBuildVectorAllOnes(Op1.getNode()))
|
else if (ISD::isBuildVectorAllOnes(Op1.getNode()))
|
||||||
NotOp = Op0;
|
NotOp = Op0;
|
||||||
else if ((Op0->getOpcode() == MipsISD::VSPLAT ||
|
|
||||||
Op0->getOpcode() == MipsISD::VSPLATD) &&
|
|
||||||
(Const = dyn_cast<ConstantSDNode>(Op0->getOperand(0))) &&
|
|
||||||
Const->isAllOnesValue())
|
|
||||||
NotOp = Op1;
|
|
||||||
else if ((Op1->getOpcode() == MipsISD::VSPLAT ||
|
|
||||||
Op1->getOpcode() == MipsISD::VSPLATD) &&
|
|
||||||
(Const = dyn_cast<ConstantSDNode>(Op1->getOperand(0))) &&
|
|
||||||
Const->isAllOnesValue())
|
|
||||||
NotOp = Op0;
|
|
||||||
else
|
else
|
||||||
return SDValue();
|
return SDValue();
|
||||||
|
|
||||||
@ -1084,14 +1073,38 @@ static SDValue lowerMSAInsertIntr(SDValue Op, SelectionDAG &DAG, unsigned Opc) {
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDValue lowerMSASplatImm(SDValue Op, unsigned ImmOp, SelectionDAG &DAG) {
|
static SDValue lowerMSASplatImm(SDValue Op, SDValue ImmOp, SelectionDAG &DAG) {
|
||||||
EVT ResTy = Op->getValueType(0);
|
EVT ResTy = Op->getValueType(0);
|
||||||
|
EVT ViaVecTy = ResTy;
|
||||||
|
SmallVector<SDValue, 16> Ops;
|
||||||
|
SDValue ImmHiOp;
|
||||||
|
SDLoc DL(Op);
|
||||||
|
|
||||||
unsigned SplatOp = MipsISD::VSPLAT;
|
if (ViaVecTy == MVT::v2i64) {
|
||||||
if (ResTy == MVT::v2i64)
|
ImmHiOp = DAG.getNode(ISD::SRA, DL, MVT::i32, ImmOp,
|
||||||
SplatOp = MipsISD::VSPLATD;
|
DAG.getConstant(31, MVT::i32));
|
||||||
|
for (unsigned i = 0; i < ViaVecTy.getVectorNumElements(); ++i) {
|
||||||
|
Ops.push_back(ImmHiOp);
|
||||||
|
Ops.push_back(ImmOp);
|
||||||
|
}
|
||||||
|
ViaVecTy = MVT::v4i32;
|
||||||
|
} else {
|
||||||
|
for (unsigned i = 0; i < ResTy.getVectorNumElements(); ++i)
|
||||||
|
Ops.push_back(ImmOp);
|
||||||
|
}
|
||||||
|
|
||||||
return DAG.getNode(SplatOp, SDLoc(Op), ResTy, Op->getOperand(ImmOp));
|
SDValue Result = DAG.getNode(ISD::BUILD_VECTOR, DL, ViaVecTy, &Ops[0],
|
||||||
|
Ops.size());
|
||||||
|
|
||||||
|
if (ResTy != ViaVecTy)
|
||||||
|
Result = DAG.getNode(ISD::BITCAST, DL, ResTy, Result);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SDValue
|
||||||
|
lowerMSASplatImm(SDValue Op, unsigned ImmOp, SelectionDAG &DAG) {
|
||||||
|
return lowerMSASplatImm(Op, Op->getOperand(ImmOp), DAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDValue lowerMSAUnaryIntr(SDValue Op, SelectionDAG &DAG, unsigned Opc) {
|
static SDValue lowerMSAUnaryIntr(SDValue Op, SelectionDAG &DAG, unsigned Opc) {
|
||||||
@ -1306,8 +1319,16 @@ SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op,
|
|||||||
return lowerMSABinaryIntr(Op, DAG, ISD::FDIV);
|
return lowerMSABinaryIntr(Op, DAG, ISD::FDIV);
|
||||||
case Intrinsic::mips_fill_b:
|
case Intrinsic::mips_fill_b:
|
||||||
case Intrinsic::mips_fill_h:
|
case Intrinsic::mips_fill_h:
|
||||||
case Intrinsic::mips_fill_w:
|
case Intrinsic::mips_fill_w: {
|
||||||
return lowerMSAUnaryIntr(Op, DAG, MipsISD::VSPLAT);
|
SmallVector<SDValue, 16> Ops;
|
||||||
|
EVT ResTy = Op->getValueType(0);
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < ResTy.getVectorNumElements(); ++i)
|
||||||
|
Ops.push_back(Op->getOperand(1));
|
||||||
|
|
||||||
|
return DAG.getNode(ISD::BUILD_VECTOR, SDLoc(Op), ResTy, &Ops[0],
|
||||||
|
Ops.size());
|
||||||
|
}
|
||||||
case Intrinsic::mips_flog2_w:
|
case Intrinsic::mips_flog2_w:
|
||||||
case Intrinsic::mips_flog2_d:
|
case Intrinsic::mips_flog2_d:
|
||||||
return lowerMSAUnaryIntr(Op, DAG, ISD::FLOG2);
|
return lowerMSAUnaryIntr(Op, DAG, ISD::FLOG2);
|
||||||
@ -1331,7 +1352,7 @@ SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op,
|
|||||||
case Intrinsic::mips_ldi_h:
|
case Intrinsic::mips_ldi_h:
|
||||||
case Intrinsic::mips_ldi_w:
|
case Intrinsic::mips_ldi_w:
|
||||||
case Intrinsic::mips_ldi_d:
|
case Intrinsic::mips_ldi_d:
|
||||||
return lowerMSAUnaryIntr(Op, DAG, MipsISD::VSPLAT);
|
return lowerMSASplatImm(Op, 1, DAG);
|
||||||
case Intrinsic::mips_max_s_b:
|
case Intrinsic::mips_max_s_b:
|
||||||
case Intrinsic::mips_max_s_h:
|
case Intrinsic::mips_max_s_h:
|
||||||
case Intrinsic::mips_max_s_w:
|
case Intrinsic::mips_max_s_w:
|
||||||
@ -1597,18 +1618,36 @@ lowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const {
|
|||||||
DAG.getValueType(EltTy));
|
DAG.getValueType(EltTy));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool isConstantOrUndef(const SDValue Op) {
|
||||||
|
if (Op->getOpcode() == ISD::UNDEF)
|
||||||
|
return true;
|
||||||
|
if (dyn_cast<ConstantSDNode>(Op))
|
||||||
|
return true;
|
||||||
|
if (dyn_cast<ConstantFPSDNode>(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)))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Lowers ISD::BUILD_VECTOR into appropriate SelectionDAG nodes for the
|
// Lowers ISD::BUILD_VECTOR into appropriate SelectionDAG nodes for the
|
||||||
// backend.
|
// backend.
|
||||||
//
|
//
|
||||||
// Lowers according to the following rules:
|
// Lowers according to the following rules:
|
||||||
// - Vectors of 128-bits may be legal subject to the other rules. Other sizes
|
// - Constant splats are legal as-is as long as the SplatBitSize is a power of
|
||||||
// are not legal.
|
// 2 less than or equal to 64 and the value fits into a signed 10-bit
|
||||||
// - Non-constant splats are legal and are lowered to MipsISD::VSPLAT.
|
// immediate
|
||||||
// - Constant splats with an element size of 32-bits or less are legal and are
|
// - Constant splats are lowered to bitconverted BUILD_VECTORs if SplatBitSize
|
||||||
// lowered to MipsISD::VSPLAT.
|
// is a power of 2 less than or equal to 64 and the value does not fit into a
|
||||||
// - Constant splats with an element size of 64-bits but whose value would fit
|
// signed 10-bit immediate
|
||||||
// within a 10 bit immediate are legal and are lowered to MipsISD::VSPLATD.
|
// - Non-constant splats are legal as-is.
|
||||||
// - All other ISD::BUILD_VECTORS are not legal
|
// - Non-constant non-splats are lowered to sequences of INSERT_VECTOR_ELT.
|
||||||
|
// - All others are illegal and must be expanded.
|
||||||
SDValue MipsSETargetLowering::lowerBUILD_VECTOR(SDValue Op,
|
SDValue MipsSETargetLowering::lowerBUILD_VECTOR(SDValue Op,
|
||||||
SelectionDAG &DAG) const {
|
SelectionDAG &DAG) const {
|
||||||
BuildVectorSDNode *Node = cast<BuildVectorSDNode>(Op);
|
BuildVectorSDNode *Node = cast<BuildVectorSDNode>(Op);
|
||||||
@ -1623,52 +1662,51 @@ SDValue MipsSETargetLowering::lowerBUILD_VECTOR(SDValue Op,
|
|||||||
|
|
||||||
if (Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
|
if (Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
|
||||||
HasAnyUndefs, 8,
|
HasAnyUndefs, 8,
|
||||||
!Subtarget->isLittle())) {
|
!Subtarget->isLittle()) && SplatBitSize <= 64) {
|
||||||
SDValue Result;
|
// We can only cope with 8, 16, 32, or 64-bit elements
|
||||||
EVT TmpVecTy;
|
if (SplatBitSize != 8 && SplatBitSize != 16 && SplatBitSize != 32 &&
|
||||||
EVT ConstTy = MVT::i32;
|
SplatBitSize != 64)
|
||||||
unsigned SplatOp = MipsISD::VSPLAT;
|
return SDValue();
|
||||||
|
|
||||||
|
// If the value fits into a simm10 then we can use ldi.[bhwd]
|
||||||
|
if (SplatValue.isSignedIntN(10))
|
||||||
|
return Op;
|
||||||
|
|
||||||
|
EVT ViaVecTy;
|
||||||
|
|
||||||
switch (SplatBitSize) {
|
switch (SplatBitSize) {
|
||||||
default:
|
default:
|
||||||
return SDValue();
|
return SDValue();
|
||||||
case 64:
|
case 8:
|
||||||
TmpVecTy = MVT::v2i64;
|
ViaVecTy = MVT::v16i8;
|
||||||
|
|
||||||
// i64 is an illegal type on Mips32, but if it the constant fits into a
|
|
||||||
// signed 10-bit value then we can still handle it using VSPLATD and an
|
|
||||||
// i32 constant
|
|
||||||
if (HasMips64)
|
|
||||||
ConstTy = MVT::i64;
|
|
||||||
else if (isInt<10>(SplatValue.getSExtValue())) {
|
|
||||||
SplatValue = SplatValue.trunc(32);
|
|
||||||
SplatOp = MipsISD::VSPLATD;
|
|
||||||
} else
|
|
||||||
return SDValue();
|
|
||||||
break;
|
|
||||||
case 32:
|
|
||||||
TmpVecTy = MVT::v4i32;
|
|
||||||
break;
|
break;
|
||||||
case 16:
|
case 16:
|
||||||
TmpVecTy = MVT::v8i16;
|
ViaVecTy = MVT::v8i16;
|
||||||
SplatValue = SplatValue.sext(32);
|
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 32:
|
||||||
TmpVecTy = MVT::v16i8;
|
ViaVecTy = MVT::v4i32;
|
||||||
SplatValue = SplatValue.sext(32);
|
|
||||||
break;
|
break;
|
||||||
|
case 64:
|
||||||
|
// There's no fill.d to fall back on for 64-bit values
|
||||||
|
return SDValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result = DAG.getNode(SplatOp, DL, TmpVecTy,
|
SmallVector<SDValue, 16> Ops;
|
||||||
DAG.getConstant(SplatValue, ConstTy));
|
SDValue Constant = DAG.getConstant(SplatValue.sextOrSelf(32), MVT::i32);
|
||||||
if (ResTy != Result.getValueType())
|
|
||||||
Result = DAG.getNode(ISD::BITCAST, DL, ResTy, Result);
|
for (unsigned i = 0; i < ViaVecTy.getVectorNumElements(); ++i)
|
||||||
|
Ops.push_back(Constant);
|
||||||
|
|
||||||
|
SDValue Result = DAG.getNode(ISD::BUILD_VECTOR, SDLoc(Node), ViaVecTy,
|
||||||
|
&Ops[0], Ops.size());
|
||||||
|
|
||||||
|
if (ViaVecTy != ResTy)
|
||||||
|
Result = DAG.getNode(ISD::BITCAST, SDLoc(Node), ResTy, Result);
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
} else if (isSplatVector(Node))
|
||||||
else if (isSplatVector(Node))
|
return Op;
|
||||||
return DAG.getNode(MipsISD::VSPLAT, DL, ResTy, Op->getOperand(0));
|
else if (!isConstantOrUndefBUILD_VECTOR(Node)) {
|
||||||
else {
|
|
||||||
// Use INSERT_VECTOR_ELT operations rather than expand to stores.
|
// Use INSERT_VECTOR_ELT operations rather than expand to stores.
|
||||||
// The resulting code is the same length as the expansion, but it doesn't
|
// The resulting code is the same length as the expansion, but it doesn't
|
||||||
// use memory operations
|
// use memory operations
|
||||||
|
@ -17,7 +17,7 @@ define void @false_v4f32(<4 x i32>* %c, <4 x float>* %a, <4 x float>* %b) nounwi
|
|||||||
|
|
||||||
; (setcc $a, $b, SETFALSE) is always folded, so we won't get fcaf:
|
; (setcc $a, $b, SETFALSE) is always folded, so we won't get fcaf:
|
||||||
; CHECK-DAG: ldi.b [[R1:\$w[0-9]+]], 0
|
; CHECK-DAG: ldi.b [[R1:\$w[0-9]+]], 0
|
||||||
; CHECK-DAG: st.b [[R1]], 0($4)
|
; CHECK-DAG: st.w [[R1]], 0($4)
|
||||||
; CHECK: .size false_v4f32
|
; CHECK: .size false_v4f32
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -494,7 +494,7 @@ define void @true_v4f32(<4 x i32>* %c, <4 x float>* %a, <4 x float>* %b) nounwin
|
|||||||
|
|
||||||
; (setcc $a, $b, SETTRUE) is always folded, so we won't get fcaf:
|
; (setcc $a, $b, SETTRUE) is always folded, so we won't get fcaf:
|
||||||
; CHECK-DAG: ldi.b [[R1:\$w[0-9]+]], -1
|
; CHECK-DAG: ldi.b [[R1:\$w[0-9]+]], -1
|
||||||
; CHECK-DAG: st.b [[R1]], 0($4)
|
; CHECK-DAG: st.w [[R1]], 0($4)
|
||||||
; CHECK: .size true_v4f32
|
; CHECK: .size true_v4f32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user