bool ARMInstructionSelector::selectCmp(CmpConstants Helper,
                                       MachineInstrBuilder &MIB,
                                       MachineRegisterInfo &MRI) const {
  const InsertInfo I(MIB);

  auto ResReg = MIB->getOperand(0).getReg();
  if (!validReg(MRI, ResReg, 1, ARM::GPRRegBankID))
    return false;

  auto Cond =
      static_cast<CmpInst::Predicate>(MIB->getOperand(1).getPredicate());
  if (Cond == CmpInst::FCMP_TRUE || Cond == CmpInst::FCMP_FALSE) {
    putConstant(I, ResReg, Cond == CmpInst::FCMP_TRUE ? 1 : 0);
    MIB->eraseFromParent();
    return true;
  }

  auto LHSReg = MIB->getOperand(2).getReg();
  auto RHSReg = MIB->getOperand(3).getReg();
  if (!validOpRegPair(MRI, LHSReg, RHSReg, Helper.OperandSize,
                      Helper.OperandRegBankID))
    return false;

  auto ARMConds = getComparePreds(Cond);
  auto ZeroReg = MRI.createVirtualRegister(&ARM::GPRRegClass);
  putConstant(I, ZeroReg, 0);

  if (ARMConds.second == ARMCC::AL) {
    // Simple case, we only need one comparison and we're done.
    if (!insertComparison(Helper, I, ResReg, ARMConds.first, LHSReg, RHSReg,
                          ZeroReg))
      return false;
  } else {
    // Not so simple, we need two successive comparisons.
    auto IntermediateRes = MRI.createVirtualRegister(&ARM::GPRRegClass);
    if (!insertComparison(Helper, I, IntermediateRes, ARMConds.first, LHSReg,
                          RHSReg, ZeroReg))
      return false;
    if (!insertComparison(Helper, I, ResReg, ARMConds.second, LHSReg, RHSReg,
                          IntermediateRes))
      return false;
  }

  MIB->eraseFromParent();
  return true;
}
bool ARMInstructionSelector::selectSelect(MachineInstrBuilder &MIB,
                                          MachineRegisterInfo &MRI) const {
  auto &MBB = *MIB->getParent();
  auto InsertBefore = std::next(MIB->getIterator());
  auto &DbgLoc = MIB->getDebugLoc();

  // Compare the condition to 0.
  auto CondReg = MIB->getOperand(1).getReg();
  assert(validReg(MRI, CondReg, 1, ARM::GPRRegBankID) &&
         "Unsupported types for select operation");
  auto CmpI = BuildMI(MBB, InsertBefore, DbgLoc, TII.get(ARM::CMPri))
                  .addUse(CondReg)
                  .addImm(0)
                  .add(predOps(ARMCC::AL));
  if (!constrainSelectedInstRegOperands(*CmpI, TII, TRI, RBI))
    return false;

  // Move a value into the result register based on the result of the
  // comparison.
  auto ResReg = MIB->getOperand(0).getReg();
  auto TrueReg = MIB->getOperand(2).getReg();
  auto FalseReg = MIB->getOperand(3).getReg();
  assert(validOpRegPair(MRI, ResReg, TrueReg, 32, ARM::GPRRegBankID) &&
         validOpRegPair(MRI, TrueReg, FalseReg, 32, ARM::GPRRegBankID) &&
         "Unsupported types for select operation");
  auto Mov1I = BuildMI(MBB, InsertBefore, DbgLoc, TII.get(ARM::MOVCCr))
                   .addDef(ResReg)
                   .addUse(TrueReg)
                   .addUse(FalseReg)
                   .add(predOps(ARMCC::EQ, ARM::CPSR));
  if (!constrainSelectedInstRegOperands(*Mov1I, TII, TRI, RBI))
    return false;

  MIB->eraseFromParent();
  return true;
}
Example #3
0
/// GetValueInMiddleOfBlock - Construct SSA form, materializing a value that
/// is live in the middle of the specified block.
///
/// GetValueInMiddleOfBlock is the same as GetValueAtEndOfBlock except in one
/// important case: if there is a definition of the rewritten value after the
/// 'use' in BB.  Consider code like this:
///
///      X1 = ...
///   SomeBB:
///      use(X)
///      X2 = ...
///      br Cond, SomeBB, OutBB
///
/// In this case, there are two values (X1 and X2) added to the AvailableVals
/// set by the client of the rewriter, and those values are both live out of
/// their respective blocks.  However, the use of X happens in the *middle* of
/// a block.  Because of this, we need to insert a new PHI node in SomeBB to
/// merge the appropriate values, and this value isn't live out of the block.
///
unsigned MachineSSAUpdater::GetValueInMiddleOfBlock(MachineBasicBlock *BB) {
  // If there is no definition of the renamed variable in this block, just use
  // GetValueAtEndOfBlock to do our work.
  if (!HasValueForBlock(BB))
    return GetValueAtEndOfBlockInternal(BB);

  // If there are no predecessors, just return undef.
  if (BB->pred_empty()) {
    // Insert an implicit_def to represent an undef value.
    MachineInstr *NewDef = InsertNewDef(TargetOpcode::IMPLICIT_DEF,
                                        BB, BB->getFirstTerminator(),
                                        VRC, MRI, TII);
    return NewDef->getOperand(0).getReg();
  }

  // Otherwise, we have the hard case.  Get the live-in values for each
  // predecessor.
  SmallVector<std::pair<MachineBasicBlock*, unsigned>, 8> PredValues;
  unsigned SingularValue = 0;

  bool isFirstPred = true;
  for (MachineBasicBlock::pred_iterator PI = BB->pred_begin(),
         E = BB->pred_end(); PI != E; ++PI) {
    MachineBasicBlock *PredBB = *PI;
    unsigned PredVal = GetValueAtEndOfBlockInternal(PredBB);
    PredValues.push_back(std::make_pair(PredBB, PredVal));

    // Compute SingularValue.
    if (isFirstPred) {
      SingularValue = PredVal;
      isFirstPred = false;
    } else if (PredVal != SingularValue)
      SingularValue = 0;
  }

  // Otherwise, if all the merged values are the same, just use it.
  if (SingularValue != 0)
    return SingularValue;

  // If an identical PHI is already in BB, just reuse it.
  unsigned DupPHI = LookForIdenticalPHI(BB, PredValues);
  if (DupPHI)
    return DupPHI;

  // Otherwise, we do need a PHI: insert one now.
  MachineBasicBlock::iterator Loc = BB->empty() ? BB->end() : BB->begin();
  MachineInstrBuilder InsertedPHI = InsertNewDef(TargetOpcode::PHI, BB,
                                                 Loc, VRC, MRI, TII);

  // Fill in all the predecessors of the PHI.
  for (unsigned i = 0, e = PredValues.size(); i != e; ++i)
    InsertedPHI.addReg(PredValues[i].second).addMBB(PredValues[i].first);

  // See if the PHI node can be merged to a single value.  This can happen in
  // loop cases when we get a PHI of itself and one other value.
  if (unsigned ConstVal = InsertedPHI->isConstantValuePHI()) {
    InsertedPHI->eraseFromParent();
    return ConstVal;
  }

  // If the client wants to know about all new instructions, tell it.
  if (InsertedPHIs) InsertedPHIs->push_back(InsertedPHI);

  DEBUG(dbgs() << "  Inserted PHI: " << *InsertedPHI << "\n");
  return InsertedPHI->getOperand(0).getReg();
}