mirror of
https://github.com/RPCS3/llvm.git
synced 2025-03-06 09:39:28 +00:00
[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
This commit is contained in:
parent
d1f487bc59
commit
876a9b9b65
@ -162,12 +162,11 @@ class DCLZ_MM64R6_DESC {
|
||||
|
||||
class DINSU_MM64R6_DESC : InsBase<"dinsu", GPR64Opnd, uimm5_plus32,
|
||||
uimm5_inssize_plus1, immZExt5Plus32,
|
||||
immZExt5Plus1, MipsIns>;
|
||||
immZExt5Plus1>;
|
||||
class DINSM_MM64R6_DESC : InsBase<"dinsm", GPR64Opnd, uimm5, uimm_range_2_64,
|
||||
immZExt5, immZExtRange2To64, MipsIns>;
|
||||
immZExt5, immZExtRange2To64>;
|
||||
class DINS_MM64R6_DESC : InsBase<"dins", GPR64Opnd, uimm5_report_uimm6,
|
||||
uimm5_inssize_plus1, immZExt5, immZExt5Plus1,
|
||||
MipsIns>;
|
||||
uimm5_inssize_plus1, immZExt5, immZExt5Plus1>;
|
||||
class DMTC0_MM64R6_DESC : MTC0_MMR6_DESC_BASE<"dmtc0", COP0Opnd, GPR64Opnd,
|
||||
II_DMTC0>;
|
||||
class DMTC1_MM64R6_DESC : MTC1_MMR6_DESC_BASE<"dmtc1", FGR64Opnd, GPR64Opnd,
|
||||
|
@ -884,7 +884,7 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in {
|
||||
def EXT_MM : MMRel, ExtBase<"ext", GPR32Opnd, uimm5, uimm5_plus1, immZExt5,
|
||||
immZExt5Plus1, MipsExt>, EXT_FM_MM<0x2c>;
|
||||
def INS_MM : MMRel, InsBase<"ins", GPR32Opnd, uimm5, uimm5_inssize_plus1,
|
||||
immZExt5, immZExt5Plus1, MipsIns>,
|
||||
immZExt5, immZExt5Plus1>,
|
||||
EXT_FM_MM<0x0c>;
|
||||
|
||||
/// Jump Instructions
|
||||
|
@ -341,13 +341,13 @@ let AdditionalPredicates = [NotInMicroMips] in {
|
||||
// for dinsm and dinsu like binutils.
|
||||
let DecoderMethod = "DecodeDINS" in {
|
||||
def DINS : InsBase<"dins", GPR64Opnd, uimm6, uimm5_inssize_plus1,
|
||||
immZExt5, immZExt5Plus1, MipsIns>, EXT_FM<7>,
|
||||
immZExt5, immZExt5Plus1>, EXT_FM<7>,
|
||||
ISA_MIPS64R2;
|
||||
def DINSU : InsBase<"dinsu", GPR64Opnd, uimm5_plus32, uimm5_inssize_plus1,
|
||||
immZExt5Plus32, immZExt5Plus1, MipsIns>,
|
||||
immZExt5Plus32, immZExt5Plus1>,
|
||||
EXT_FM<6>, ISA_MIPS64R2;
|
||||
def DINSM : InsBase<"dinsm", GPR64Opnd, uimm5, uimm_range_2_64,
|
||||
immZExt5, immZExtRange2To64, MipsIns>,
|
||||
immZExt5, immZExtRange2To64>,
|
||||
EXT_FM<5>, ISA_MIPS64R2;
|
||||
}
|
||||
}
|
||||
|
@ -1726,12 +1726,13 @@ class ExtBase<string opstr, RegisterOperand RO, Operand PosOpnd,
|
||||
[(set RO:$rt, (Op RO:$rs, PosImm:$pos, SizeImm:$size))], II_EXT,
|
||||
FrmR, opstr>, ISA_MIPS32R2;
|
||||
|
||||
// 'ins' and its' 64 bit variants are matched by C++ code.
|
||||
class InsBase<string opstr, RegisterOperand RO, Operand PosOpnd,
|
||||
Operand SizeOpnd, PatFrag PosImm, PatFrag SizeImm,
|
||||
SDPatternOperator Op = null_frag>:
|
||||
Operand SizeOpnd, PatFrag PosImm, PatFrag SizeImm>:
|
||||
InstSE<(outs RO:$rt), (ins RO:$rs, PosOpnd:$pos, SizeOpnd:$size, RO:$src),
|
||||
!strconcat(opstr, " $rt, $rs, $pos, $size"),
|
||||
[(set RO:$rt, (Op RO:$rs, PosImm:$pos, SizeImm:$size, RO:$src))],
|
||||
[(set RO:$rt, (null_frag RO:$rs, PosImm:$pos, SizeImm:$size,
|
||||
RO:$src))],
|
||||
II_INS, FrmR, opstr>, ISA_MIPS32R2 {
|
||||
let Constraints = "$src = $rt";
|
||||
}
|
||||
@ -2236,7 +2237,7 @@ let AdditionalPredicates = [NotInMicroMips] in {
|
||||
EXT_FM<0>;
|
||||
def INS : MMRel, StdMMR6Rel, InsBase<"ins", GPR32Opnd, uimm5,
|
||||
uimm5_inssize_plus1, immZExt5,
|
||||
immZExt5Plus1, MipsIns>,
|
||||
immZExt5Plus1>,
|
||||
EXT_FM<4>;
|
||||
}
|
||||
/// Move Control Registers From/To CPU Registers
|
||||
|
@ -905,6 +905,64 @@ bool MipsSEDAGToDAGISel::trySelect(SDNode *Node) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Manually match MipsISD::Ins nodes to get the correct instruction. It has
|
||||
// to be done in this fashion so that we respect the differences between
|
||||
// dins and dinsm, as the difference is that the size operand has the range
|
||||
// 0 < size <= 32 for dins while dinsm has the range 2 <= size <= 64 which
|
||||
// means SelectionDAGISel would have to test all the operands at once to
|
||||
// match the instruction.
|
||||
case MipsISD::Ins: {
|
||||
|
||||
// Sanity checking for the node operands.
|
||||
if (Node->getValueType(0) != MVT::i32 && Node->getValueType(0) != MVT::i64)
|
||||
return false;
|
||||
|
||||
if (Node->getNumOperands() != 4)
|
||||
return false;
|
||||
|
||||
if (Node->getOperand(1)->getOpcode() != ISD::Constant ||
|
||||
Node->getOperand(2)->getOpcode() != ISD::Constant)
|
||||
return false;
|
||||
|
||||
MVT ResTy = Node->getSimpleValueType(0);
|
||||
uint64_t Pos = Node->getConstantOperandVal(1);
|
||||
uint64_t Size = Node->getConstantOperandVal(2);
|
||||
|
||||
// Size has to be >0 for 'ins', 'dins' and 'dinsu'.
|
||||
if (!Size)
|
||||
return false;
|
||||
|
||||
if (Pos + Size > 64)
|
||||
return false;
|
||||
|
||||
if (ResTy != MVT::i32 && ResTy != MVT::i64)
|
||||
return false;
|
||||
|
||||
unsigned Opcode = 0;
|
||||
if (ResTy == MVT::i32) {
|
||||
if (Pos + Size <= 32)
|
||||
Opcode = Mips::INS;
|
||||
} else {
|
||||
if (Pos + Size <= 32)
|
||||
Opcode = Mips::DINS;
|
||||
else if (Pos < 32 && 1 < Size)
|
||||
Opcode = Mips::DINSM;
|
||||
else
|
||||
Opcode = Mips::DINSU;
|
||||
}
|
||||
|
||||
if (Opcode) {
|
||||
SDValue Ops[4] = {
|
||||
Node->getOperand(0), CurDAG->getTargetConstant(Pos, DL, MVT::i32),
|
||||
CurDAG->getTargetConstant(Size, DL, MVT::i32), Node->getOperand(3)};
|
||||
|
||||
ReplaceNode(Node, CurDAG->getMachineNode(Opcode, DL, ResTy, Ops));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
case MipsISD::ThreadPointer: {
|
||||
EVT PtrVT = getTargetLowering()->getPointerTy(CurDAG->getDataLayout());
|
||||
unsigned RdhwrOpc, DestReg;
|
||||
|
@ -1,7 +1,11 @@
|
||||
; RUN: llc -O2 -march=mips64 -mcpu=mips64r2 -target-abi=n64 < %s -o - | FileCheck %s -check-prefix=MIPS64R2
|
||||
; RUN: llc -O2 -march=mips -mcpu=mips32r2 < %s -o - | FileCheck %s -check-prefix=MIPS32R2
|
||||
; RUN: llc -O2 -march=mips -mattr=mips16 < %s -o - | FileCheck %s -check-prefix=MIPS16
|
||||
; RUN: llc -O2 -march=mips64 -mcpu=mips64r2 -target-abi=n32 < %s -o - | FileCheck %s -check-prefix=MIPS64R2N32
|
||||
; RUN: llc -O2 -verify-machineinstrs -march=mips64 -mcpu=mips64r2 \
|
||||
; RUN: -target-abi=n64 < %s -o - | FileCheck %s -check-prefix=MIPS64R2
|
||||
; RUN: llc -O2 -verify-machineinstrs -march=mips -mcpu=mips32r2 < %s -o - \
|
||||
; RUN: | FileCheck %s -check-prefix=MIPS32R2
|
||||
; RUN: llc -O2 -verify-machineinstrs -march=mips -mattr=mips16 < %s -o - \
|
||||
; RUN: | FileCheck %s -check-prefix=MIPS16
|
||||
; RUN: llc -O2 -verify-machineinstrs -march=mips64 -mcpu=mips64r2 \
|
||||
; RUN: -target-abi=n32 < %s -o - | FileCheck %s -check-prefix=MIPS64R2N32
|
||||
|
||||
; #include <stdint.h>
|
||||
; #include <stdio.h>
|
||||
@ -60,7 +64,7 @@ entry:
|
||||
; MIPS64R2: daddiu $[[R0:[0-9]+]], $zero, 123
|
||||
; MIPS64R2: dinsm $[[R0:[0-9]+]], $[[R1:[0-9]+]], 27, 37
|
||||
; MIPS64R2: daddiu $[[R0:[0-9]+]], $zero, 4
|
||||
; MIPS64R2: dins $[[R0:[0-9]+]], $[[R1:[0-9]+]], 28, 6
|
||||
; MIPS64R2: dinsm $[[R0:[0-9]+]], $[[R1:[0-9]+]], 28, 6
|
||||
; MIPS64R2: daddiu $[[R0:[0-9]+]], $zero, 5
|
||||
; MIPS64R2: dinsu $[[R0:[0-9]+]], $[[R1:[0-9]+]], 50, 14
|
||||
; MIPS64R2: dsrl $[[R0:[0-9]+]], $[[R1:[0-9]+]], 50
|
||||
|
Loading…
x
Reference in New Issue
Block a user