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; }
/// 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(); }