Example #1
0
MachineInstr *
LanaiInstrInfo::optimizeSelect(MachineInstr &MI,
                               SmallPtrSetImpl<MachineInstr *> &SeenMIs,
                               bool PreferFalse) const {
  assert(MI.getOpcode() == Lanai::SELECT && "unknown select instruction");
  MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo();
  MachineInstr *DefMI = canFoldIntoSelect(MI.getOperand(1).getReg(), MRI, this);
  bool Invert = !DefMI;
  if (!DefMI)
    DefMI = canFoldIntoSelect(MI.getOperand(2).getReg(), MRI, this);
  if (!DefMI)
    return nullptr;

  // Find new register class to use.
  MachineOperand FalseReg = MI.getOperand(Invert ? 1 : 2);
  unsigned DestReg = MI.getOperand(0).getReg();
  const TargetRegisterClass *PreviousClass = MRI.getRegClass(FalseReg.getReg());
  if (!MRI.constrainRegClass(DestReg, PreviousClass))
    return nullptr;

  // Create a new predicated version of DefMI.
  MachineInstrBuilder NewMI =
      BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), DefMI->getDesc(), DestReg);

  // Copy all the DefMI operands, excluding its (null) predicate.
  const MCInstrDesc &DefDesc = DefMI->getDesc();
  for (unsigned i = 1, e = DefDesc.getNumOperands();
       i != e && !DefDesc.OpInfo[i].isPredicate(); ++i)
    NewMI.addOperand(DefMI->getOperand(i));

  unsigned CondCode = MI.getOperand(3).getImm();
  if (Invert)
    NewMI.addImm(getOppositeCondition(LPCC::CondCode(CondCode)));
  else
    NewMI.addImm(CondCode);
  NewMI.copyImplicitOps(MI);

  // The output register value when the predicate is false is an implicit
  // register operand tied to the first def.  The tie makes the register
  // allocator ensure the FalseReg is allocated the same register as operand 0.
  FalseReg.setImplicit();
  NewMI.addOperand(FalseReg);
  NewMI->tieOperands(0, NewMI->getNumOperands() - 1);

  // Update SeenMIs set: register newly created MI and erase removed DefMI.
  SeenMIs.insert(NewMI);
  SeenMIs.erase(DefMI);

  // If MI is inside a loop, and DefMI is outside the loop, then kill flags on
  // DefMI would be invalid when transferred inside the loop.  Checking for a
  // loop is expensive, but at least remove kill flags if they are in different
  // BBs.
  if (DefMI->getParent() != MI.getParent())
    NewMI->clearKillInfo();

  // The caller will erase MI, but not DefMI.
  DefMI->eraseFromParent();
  return NewMI;
}
/// ExpandVLD - Translate VLD pseudo instructions with Q, QQ or QQQQ register
/// operands to real VLD instructions with D register operands.
void ARMExpandPseudo::ExpandVLD(MachineBasicBlock::iterator &MBBI) {
    MachineInstr &MI = *MBBI;
    MachineBasicBlock &MBB = *MI.getParent();

    const NEONLdStTableEntry *TableEntry = LookupNEONLdSt(MI.getOpcode());
    assert(TableEntry && TableEntry->IsLoad && "NEONLdStTable lookup failed");
    NEONRegSpacing RegSpc = TableEntry->RegSpacing;
    unsigned NumRegs = TableEntry->NumRegs;

    MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(),
                                      TII->get(TableEntry->RealOpc));
    unsigned OpIdx = 0;

    bool DstIsDead = MI.getOperand(OpIdx).isDead();
    unsigned DstReg = MI.getOperand(OpIdx++).getReg();
    unsigned D0, D1, D2, D3;
    GetDSubRegs(DstReg, RegSpc, TRI, D0, D1, D2, D3);
    MIB.addReg(D0, RegState::Define | getDeadRegState(DstIsDead))
    .addReg(D1, RegState::Define | getDeadRegState(DstIsDead));
    if (NumRegs > 2)
        MIB.addReg(D2, RegState::Define | getDeadRegState(DstIsDead));
    if (NumRegs > 3)
        MIB.addReg(D3, RegState::Define | getDeadRegState(DstIsDead));

    if (TableEntry->HasWriteBack)
        MIB.addOperand(MI.getOperand(OpIdx++));

    // Copy the addrmode6 operands.
    MIB.addOperand(MI.getOperand(OpIdx++));
    MIB.addOperand(MI.getOperand(OpIdx++));
    // Copy the am6offset operand.
    if (TableEntry->HasWriteBack)
        MIB.addOperand(MI.getOperand(OpIdx++));

    // For an instruction writing double-spaced subregs, the pseudo instruction
    // has an extra operand that is a use of the super-register.  Record the
    // operand index and skip over it.
    unsigned SrcOpIdx = 0;
    if (RegSpc == EvenDblSpc || RegSpc == OddDblSpc)
        SrcOpIdx = OpIdx++;

    // Copy the predicate operands.
    MIB.addOperand(MI.getOperand(OpIdx++));
    MIB.addOperand(MI.getOperand(OpIdx++));

    // Copy the super-register source operand used for double-spaced subregs over
    // to the new instruction as an implicit operand.
    if (SrcOpIdx != 0) {
        MachineOperand MO = MI.getOperand(SrcOpIdx);
        MO.setImplicit(true);
        MIB.addOperand(MO);
    }
    // Add an implicit def for the super-register.
    MIB.addReg(DstReg, RegState::ImplicitDefine | getDeadRegState(DstIsDead));
    TransferImpOps(MI, MIB, MIB);
    MI.eraseFromParent();
}
/// ExpandLaneOp - Translate VLD*LN and VST*LN instructions with Q, QQ or QQQQ
/// register operands to real instructions with D register operands.
void ARMExpandPseudo::ExpandLaneOp(MachineBasicBlock::iterator &MBBI) {
    MachineInstr &MI = *MBBI;
    MachineBasicBlock &MBB = *MI.getParent();

    const NEONLdStTableEntry *TableEntry = LookupNEONLdSt(MI.getOpcode());
    assert(TableEntry && "NEONLdStTable lookup failed");
    NEONRegSpacing RegSpc = TableEntry->RegSpacing;
    unsigned NumRegs = TableEntry->NumRegs;
    unsigned RegElts = TableEntry->RegElts;

    MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(),
                                      TII->get(TableEntry->RealOpc));
    unsigned OpIdx = 0;
    // The lane operand is always the 3rd from last operand, before the 2
    // predicate operands.
    unsigned Lane = MI.getOperand(MI.getDesc().getNumOperands() - 3).getImm();

    // Adjust the lane and spacing as needed for Q registers.
    assert(RegSpc != OddDblSpc && "unexpected register spacing for VLD/VST-lane");
    if (RegSpc == EvenDblSpc && Lane >= RegElts) {
        RegSpc = OddDblSpc;
        Lane -= RegElts;
    }
    assert(Lane < RegElts && "out of range lane for VLD/VST-lane");

    unsigned D0, D1, D2, D3;
    unsigned DstReg = 0;
    bool DstIsDead = false;
    if (TableEntry->IsLoad) {
        DstIsDead = MI.getOperand(OpIdx).isDead();
        DstReg = MI.getOperand(OpIdx++).getReg();
        GetDSubRegs(DstReg, RegSpc, TRI, D0, D1, D2, D3);
        MIB.addReg(D0, RegState::Define | getDeadRegState(DstIsDead))
        .addReg(D1, RegState::Define | getDeadRegState(DstIsDead));
        if (NumRegs > 2)
            MIB.addReg(D2, RegState::Define | getDeadRegState(DstIsDead));
        if (NumRegs > 3)
            MIB.addReg(D3, RegState::Define | getDeadRegState(DstIsDead));
    }

    if (TableEntry->HasWriteBack)
        MIB.addOperand(MI.getOperand(OpIdx++));

    // Copy the addrmode6 operands.
    MIB.addOperand(MI.getOperand(OpIdx++));
    MIB.addOperand(MI.getOperand(OpIdx++));
    // Copy the am6offset operand.
    if (TableEntry->HasWriteBack)
        MIB.addOperand(MI.getOperand(OpIdx++));

    // Grab the super-register source.
    MachineOperand MO = MI.getOperand(OpIdx++);
    if (!TableEntry->IsLoad)
        GetDSubRegs(MO.getReg(), RegSpc, TRI, D0, D1, D2, D3);

    // Add the subregs as sources of the new instruction.
    unsigned SrcFlags = (getUndefRegState(MO.isUndef()) |
                         getKillRegState(MO.isKill()));
    MIB.addReg(D0, SrcFlags).addReg(D1, SrcFlags);
    if (NumRegs > 2)
        MIB.addReg(D2, SrcFlags);
    if (NumRegs > 3)
        MIB.addReg(D3, SrcFlags);

    // Add the lane number operand.
    MIB.addImm(Lane);
    OpIdx += 1;

    // Copy the predicate operands.
    MIB.addOperand(MI.getOperand(OpIdx++));
    MIB.addOperand(MI.getOperand(OpIdx++));

    // Copy the super-register source to be an implicit source.
    MO.setImplicit(true);
    MIB.addOperand(MO);
    if (TableEntry->IsLoad)
        // Add an implicit def for the super-register.
        MIB.addReg(DstReg, RegState::ImplicitDefine | getDeadRegState(DstIsDead));
    TransferImpOps(MI, MIB, MIB);
    MI.eraseFromParent();
}