This is an archive of the discontinued LLVM Phabricator instance.

[mips] Match 'ins' and its' variants with C++ code
ClosedPublic

Authored by sdardis on Oct 20 2017, 3:13 AM.

Details

Summary

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.

Diff Detail

Repository
rL LLVM

Event Timeline

sdardis created this revision.Oct 20 2017, 3:13 AM
atanasyan added inline comments.Oct 23 2017, 10:10 AM
lib/Target/Mips/MipsSEISelDAGToDAG.cpp
933 ↗(On Diff #119642)

In the code below if Pos is greater than zero and Size is 0 and Node->getValueType(0) is equal to MVT::i32, the function returns false. But if Node->getValueType(0) is equal to MVT::i64, the function returns true and replaces the node by the Mips::DINS opcode. Does it conform the specification?

935 ↗(On Diff #119642)
  • 0 <= Pos && Pos < 32 can be changed to Pos < 32 because the Pos is unsigned integer.
  • I think 0 < Size <= 32 should be changed to the 0 < Size && Size <= 32
938 ↗(On Diff #119642)
sdardis updated this revision to Diff 120036.Oct 24 2017, 4:04 AM
sdardis marked 3 inline comments as done.

Address review comments.

I've reflowed the logic for handling dins* to match the ISA documentation, with the exception of an early return if the size is zero.

lib/Target/Mips/MipsSEISelDAGToDAG.cpp
933 ↗(On Diff #119642)

If size is zero, then it doesn't match the specification for any of the cases. I've changed the logic accordingly.

935 ↗(On Diff #119642)

Thanks for spotting, I've reflowed the logic around these checks.

atanasyan added inline comments.Oct 24 2017, 4:32 AM
lib/Target/Mips/MipsSEISelDAGToDAG.cpp
927 ↗(On Diff #120036)

Now the code below is okay, but i think we can write it a bit more clear. I think the following variant is logically equal to the original one. But I do not force to use it.

uint64_t MVT = Node->getConstantOperandVal(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 (Size + Pos > 64)
  return false;

unsigned Opcode = 0;
if (MVT == MVT::i32) {
  if (Pos + Size <= 32)
    Opcode = Mips::INS;
} else {
  if (Pos + Size <= 32)
    Opcode = Mips::DINS;
  else if (Pos < 32)
    Opcode = Mips::DINSM;
  else
    Opcode = Mips::DINSU;
}

if (Opcode) {
  SDValue Ops[4] = {
          MVT, CurDAG->getTargetConstant(Pos, DL, MVT::i32),
          CurDAG->getTargetConstant(Size, DL, MVT::i32), Node->getOperand(3)};

  ReplaceNode(Node, CurDAG->getMachineNode(Opcode, DL, MVT, Ops));
  return true;
}

return false;
sdardis updated this revision to Diff 121274.Nov 2 2017, 4:01 AM

Address review comments.

sdardis added inline comments.Nov 2 2017, 4:02 AM
lib/Target/Mips/MipsSEISelDAGToDAG.cpp
927 ↗(On Diff #120036)

I agree, I think this is clearer.

This revision is now accepted and ready to land.Nov 2 2017, 8:24 AM
This revision was automatically updated to reflect the committed changes.