llvm.org GIT mirror llvm / 876a9b9
[mips] Match 'ins' and its' variants with C++ code Change the ISel matching of 'ins', 'dins[mu]' from tablegen code to C++ code. This resolves an issue where ISel would select 'dins' instead of 'dinsm' when the instructions size and position were individually in range but their sum was out of range according to the ISA specification. Reviewers: atanasyan Differential Revision: https://reviews.llvm.org/D39117 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@317331 91177308-0d34-0410-b5e6-96231b3b80d8 Simon Dardis 2 years ago
6 changed file(s) with 79 addition(s) and 17 deletion(s). Raw diff Collapse all Expand all
161161
162162 class DINSU_MM64R6_DESC : InsBase<"dinsu", GPR64Opnd, uimm5_plus32,
163163 uimm5_inssize_plus1, immZExt5Plus32,
164 immZExt5Plus1, MipsIns>;
164 immZExt5Plus1>;
165165 class DINSM_MM64R6_DESC : InsBase<"dinsm", GPR64Opnd, uimm5, uimm_range_2_64,
166 immZExt5, immZExtRange2To64, MipsIns>;
166 immZExt5, immZExtRange2To64>;
167167 class DINS_MM64R6_DESC : InsBase<"dins", GPR64Opnd, uimm5_report_uimm6,
168 uimm5_inssize_plus1, immZExt5, immZExt5Plus1,
169 MipsIns>;
168 uimm5_inssize_plus1, immZExt5, immZExt5Plus1>;
170169 class DMTC0_MM64R6_DESC : MTC0_MMR6_DESC_BASE<"dmtc0", COP0Opnd, GPR64Opnd,
171170 II_DMTC0>;
172171 class DMTC1_MM64R6_DESC : MTC1_MMR6_DESC_BASE<"dmtc1", FGR64Opnd, GPR64Opnd,
883883 def EXT_MM : MMRel, ExtBase<"ext", GPR32Opnd, uimm5, uimm5_plus1, immZExt5,
884884 immZExt5Plus1, MipsExt>, EXT_FM_MM<0x2c>;
885885 def INS_MM : MMRel, InsBase<"ins", GPR32Opnd, uimm5, uimm5_inssize_plus1,
886 immZExt5, immZExt5Plus1, MipsIns>,
886 immZExt5, immZExt5Plus1>,
887887 EXT_FM_MM<0x0c>;
888888
889889 /// Jump Instructions
340340 // for dinsm and dinsu like binutils.
341341 let DecoderMethod = "DecodeDINS" in {
342342 def DINS : InsBase<"dins", GPR64Opnd, uimm6, uimm5_inssize_plus1,
343 immZExt5, immZExt5Plus1, MipsIns>, EXT_FM<7>,
343 immZExt5, immZExt5Plus1>, EXT_FM<7>,
344344 ISA_MIPS64R2;
345345 def DINSU : InsBase<"dinsu", GPR64Opnd, uimm5_plus32, uimm5_inssize_plus1,
346 immZExt5Plus32, immZExt5Plus1, MipsIns>,
346 immZExt5Plus32, immZExt5Plus1>,
347347 EXT_FM<6>, ISA_MIPS64R2;
348348 def DINSM : InsBase<"dinsm", GPR64Opnd, uimm5, uimm_range_2_64,
349 immZExt5, immZExtRange2To64, MipsIns>,
349 immZExt5, immZExtRange2To64>,
350350 EXT_FM<5>, ISA_MIPS64R2;
351351 }
352352 }
17251725 [(set RO:$rt, (Op RO:$rs, PosImm:$pos, SizeImm:$size))], II_EXT,
17261726 FrmR, opstr>, ISA_MIPS32R2;
17271727
1728 // 'ins' and its' 64 bit variants are matched by C++ code.
17281729 class InsBase
1729 Operand SizeOpnd, PatFrag PosImm, PatFrag SizeImm,
1730 SDPatternOperator Op = null_frag>:
1730 Operand SizeOpnd, PatFrag PosImm, PatFrag SizeImm>:
17311731 InstSE<(outs RO:$rt), (ins RO:$rs, PosOpnd:$pos, SizeOpnd:$size, RO:$src),
17321732 !strconcat(opstr, " $rt, $rs, $pos, $size"),
1733 [(set RO:$rt, (Op RO:$rs, PosImm:$pos, SizeImm:$size, RO:$src))],
1733 [(set RO:$rt, (null_frag RO:$rs, PosImm:$pos, SizeImm:$size,
1734 RO:$src))],
17341735 II_INS, FrmR, opstr>, ISA_MIPS32R2 {
17351736 let Constraints = "$src = $rt";
17361737 }
22352236 EXT_FM<0>;
22362237 def INS : MMRel, StdMMR6Rel, InsBase<"ins", GPR32Opnd, uimm5,
22372238 uimm5_inssize_plus1, immZExt5,
2238 immZExt5Plus1, MipsIns>,
2239 immZExt5Plus1>,
22392240 EXT_FM<4>;
22402241 }
22412242 /// Move Control Registers From/To CPU Registers
902902 }
903903 }
904904 break;
905 }
906
907 // Manually match MipsISD::Ins nodes to get the correct instruction. It has
908 // to be done in this fashion so that we respect the differences between
909 // dins and dinsm, as the difference is that the size operand has the range
910 // 0 < size <= 32 for dins while dinsm has the range 2 <= size <= 64 which
911 // means SelectionDAGISel would have to test all the operands at once to
912 // match the instruction.
913 case MipsISD::Ins: {
914
915 // Sanity checking for the node operands.
916 if (Node->getValueType(0) != MVT::i32 && Node->getValueType(0) != MVT::i64)
917 return false;
918
919 if (Node->getNumOperands() != 4)
920 return false;
921
922 if (Node->getOperand(1)->getOpcode() != ISD::Constant ||
923 Node->getOperand(2)->getOpcode() != ISD::Constant)
924 return false;
925
926 MVT ResTy = Node->getSimpleValueType(0);
927 uint64_t Pos = Node->getConstantOperandVal(1);
928 uint64_t Size = Node->getConstantOperandVal(2);
929
930 // Size has to be >0 for 'ins', 'dins' and 'dinsu'.
931 if (!Size)
932 return false;
933
934 if (Pos + Size > 64)
935 return false;
936
937 if (ResTy != MVT::i32 && ResTy != MVT::i64)
938 return false;
939
940 unsigned Opcode = 0;
941 if (ResTy == MVT::i32) {
942 if (Pos + Size <= 32)
943 Opcode = Mips::INS;
944 } else {
945 if (Pos + Size <= 32)
946 Opcode = Mips::DINS;
947 else if (Pos < 32 && 1 < Size)
948 Opcode = Mips::DINSM;
949 else
950 Opcode = Mips::DINSU;
951 }
952
953 if (Opcode) {
954 SDValue Ops[4] = {
955 Node->getOperand(0), CurDAG->getTargetConstant(Pos, DL, MVT::i32),
956 CurDAG->getTargetConstant(Size, DL, MVT::i32), Node->getOperand(3)};
957
958 ReplaceNode(Node, CurDAG->getMachineNode(Opcode, DL, ResTy, Ops));
959 return true;
960 }
961
962 return false;
905963 }
906964
907965 case MipsISD::ThreadPointer: {
None ; RUN: llc -O2 -march=mips64 -mcpu=mips64r2 -target-abi=n64 < %s -o - | FileCheck %s -check-prefix=MIPS64R2
1 ; RUN: llc -O2 -march=mips -mcpu=mips32r2 < %s -o - | FileCheck %s -check-prefix=MIPS32R2
2 ; RUN: llc -O2 -march=mips -mattr=mips16 < %s -o - | FileCheck %s -check-prefix=MIPS16
3 ; RUN: llc -O2 -march=mips64 -mcpu=mips64r2 -target-abi=n32 < %s -o - | FileCheck %s -check-prefix=MIPS64R2N32
0 ; RUN: llc -O2 -verify-machineinstrs -march=mips64 -mcpu=mips64r2 \
1 ; RUN: -target-abi=n64 < %s -o - | FileCheck %s -check-prefix=MIPS64R2
2 ; RUN: llc -O2 -verify-machineinstrs -march=mips -mcpu=mips32r2 < %s -o - \
3 ; RUN: | FileCheck %s -check-prefix=MIPS32R2
4 ; RUN: llc -O2 -verify-machineinstrs -march=mips -mattr=mips16 < %s -o - \
5 ; RUN: | FileCheck %s -check-prefix=MIPS16
6 ; RUN: llc -O2 -verify-machineinstrs -march=mips64 -mcpu=mips64r2 \
7 ; RUN: -target-abi=n32 < %s -o - | FileCheck %s -check-prefix=MIPS64R2N32
48
59 ; #include
610 ; #include
5963 ; MIPS64R2: daddiu $[[R0:[0-9]+]], $zero, 123
6064 ; MIPS64R2: dinsm $[[R0:[0-9]+]], $[[R1:[0-9]+]], 27, 37
6165 ; MIPS64R2: daddiu $[[R0:[0-9]+]], $zero, 4
62 ; MIPS64R2: dins $[[R0:[0-9]+]], $[[R1:[0-9]+]], 28, 6
66 ; MIPS64R2: dinsm $[[R0:[0-9]+]], $[[R1:[0-9]+]], 28, 6
6367 ; MIPS64R2: daddiu $[[R0:[0-9]+]], $zero, 5
6468 ; MIPS64R2: dinsu $[[R0:[0-9]+]], $[[R1:[0-9]+]], 50, 14
6569 ; MIPS64R2: dsrl $[[R0:[0-9]+]], $[[R1:[0-9]+]], 50