bool SparcInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl<MachineOperand> &Cond, bool AllowModify) const { MachineBasicBlock::iterator I = MBB.end(); MachineBasicBlock::iterator UnCondBrIter = MBB.end(); while (I != MBB.begin()) { --I; if (I->isDebugValue()) continue; //When we see a non-terminator, we are done if (!isUnpredicatedTerminator(I)) break; //Terminator is not a branch if (!I->isBranch()) return true; //Handle Unconditional branches if (I->getOpcode() == SP::BA) { UnCondBrIter = I; if (!AllowModify) { TBB = I->getOperand(0).getMBB(); continue; } while (llvm::next(I) != MBB.end()) llvm::next(I)->eraseFromParent(); Cond.clear(); FBB = 0; if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) { TBB = 0; I->eraseFromParent(); I = MBB.end(); UnCondBrIter = MBB.end(); continue; } TBB = I->getOperand(0).getMBB(); continue; } unsigned Opcode = I->getOpcode(); if (Opcode != SP::BCOND && Opcode != SP::FBCOND) return true; //Unknown Opcode SPCC::CondCodes BranchCode = (SPCC::CondCodes)I->getOperand(1).getImm(); if (Cond.empty()) { MachineBasicBlock *TargetBB = I->getOperand(0).getMBB(); if (AllowModify && UnCondBrIter != MBB.end() && MBB.isLayoutSuccessor(TargetBB)) { //Transform the code // // brCC L1 // ba L2 // L1: // .. // L2: // // into // // brnCC L2 // L1: // ... // L2: // BranchCode = GetOppositeBranchCondition(BranchCode); MachineBasicBlock::iterator OldInst = I; BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(Opcode)) .addMBB(UnCondBrIter->getOperand(0).getMBB()).addImm(BranchCode); BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(SP::BA)) .addMBB(TargetBB); OldInst->eraseFromParent(); UnCondBrIter->eraseFromParent(); UnCondBrIter = MBB.end(); I = MBB.end(); continue; } FBB = TBB; TBB = I->getOperand(0).getMBB(); Cond.push_back(MachineOperand::CreateImm(BranchCode)); continue; } //FIXME: Handle subsequent conditional branches //For now, we can't handle multiple conditional branches return true; } return false; }
bool MSP430InstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl<MachineOperand> &Cond, bool AllowModify) const { // Start from the bottom of the block and work up, examining the // terminator instructions. MachineBasicBlock::iterator I = MBB.end(); while (I != MBB.begin()) { --I; if (I->isDebugValue()) continue; // Working from the bottom, when we see a non-terminator // instruction, we're done. if (!isUnpredicatedTerminator(I)) break; // A terminator that isn't a branch can't easily be handled // by this analysis. if (!I->isBranch()) return true; // Cannot handle indirect branches. if (I->getOpcode() == MSP430::Br || I->getOpcode() == MSP430::Bm) return true; // Handle unconditional branches. if (I->getOpcode() == MSP430::JMP) { if (!AllowModify) { TBB = I->getOperand(0).getMBB(); continue; } // If the block has any instructions after a JMP, delete them. while (std::next(I) != MBB.end()) std::next(I)->eraseFromParent(); Cond.clear(); FBB = 0; // Delete the JMP if it's equivalent to a fall-through. if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) { TBB = 0; I->eraseFromParent(); I = MBB.end(); continue; } // TBB is used to indicate the unconditinal destination. TBB = I->getOperand(0).getMBB(); continue; } // Handle conditional branches. assert(I->getOpcode() == MSP430::JCC && "Invalid conditional branch"); MSP430CC::CondCodes BranchCode = static_cast<MSP430CC::CondCodes>(I->getOperand(1).getImm()); if (BranchCode == MSP430CC::COND_INVALID) return true; // Can't handle weird stuff. // Working from the bottom, handle the first conditional branch. if (Cond.empty()) { FBB = TBB; TBB = I->getOperand(0).getMBB(); Cond.push_back(MachineOperand::CreateImm(BranchCode)); continue; } // Handle subsequent conditional branches. Only handle the case where all // conditional branches branch to the same destination. assert(Cond.size() == 1); assert(TBB); // Only handle the case where all conditional branches branch to // the same destination. if (TBB != I->getOperand(0).getMBB()) return true; MSP430CC::CondCodes OldBranchCode = (MSP430CC::CondCodes)Cond[0].getImm(); // If the conditions are the same, we can leave them alone. if (OldBranchCode == BranchCode) continue; return true; } return false; }
/// \brief Parses list of simple variables for '#pragma omp threadprivate' /// directive. /// /// simple-variable-list: /// '(' id-expression {, id-expression} ')' /// bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind, SmallVectorImpl<Expr *> &VarList, bool AllowScopeSpecifier) { VarList.clear(); // Parse '('. BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); if (T.expectAndConsume(diag::err_expected_lparen_after, getOpenMPDirectiveName(Kind))) return true; bool IsCorrect = true; bool NoIdentIsFound = true; // Read tokens while ')' or annot_pragma_openmp_end is not found. while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) { CXXScopeSpec SS; SourceLocation TemplateKWLoc; UnqualifiedId Name; // Read var name. Token PrevTok = Tok; NoIdentIsFound = false; if (AllowScopeSpecifier && getLangOpts().CPlusPlus && ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false)) { IsCorrect = false; SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); } else if (ParseUnqualifiedId(SS, false, false, false, ParsedType(), TemplateKWLoc, Name)) { IsCorrect = false; SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) { IsCorrect = false; SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); Diag(PrevTok.getLocation(), diag::err_expected) << tok::identifier << SourceRange(PrevTok.getLocation(), PrevTokLocation); } else { DeclarationNameInfo NameInfo = Actions.GetNameFromUnqualifiedId(Name); ExprResult Res = Actions.ActOnOpenMPIdExpression(getCurScope(), SS, NameInfo); if (Res.isUsable()) VarList.push_back(Res.get()); } // Consume ','. if (Tok.is(tok::comma)) { ConsumeToken(); } } if (NoIdentIsFound) { Diag(Tok, diag::err_expected) << tok::identifier; IsCorrect = false; } // Parse ')'. IsCorrect = !T.consumeClose() && IsCorrect; return !IsCorrect && VarList.empty(); }
static void updateSSAForUseOfInst(SILSSAUpdater &Updater, SmallVectorImpl<SILArgument*> &InsertedPHIs, const llvm::DenseMap<ValueBase *, SILValue> &ValueMap, SILBasicBlock *Header, SILBasicBlock *EntryCheckBlock, ValueBase *Inst) { if (Inst->use_empty()) return; // Find the mapped instruction. assert(ValueMap.count(Inst) && "Expected to find value in map!"); SILValue MappedValue = ValueMap.find(Inst)->second; auto *MappedInst = MappedValue.getDef(); assert(MappedValue); assert(MappedInst); // For each use of a specific result value of the instruction. for (unsigned i = 0, e = Inst->getNumTypes(); i != e; ++i) { SILValue Res(Inst, i); // For block arguments, MappedValue is already indexed to indicate the // single result value that feeds the argument. In this case, i==0 because // SILArgument only produces one value. SILValue MappedRes = isa<SILArgument>(Inst) ? MappedValue : SILValue(MappedInst, i); assert(Res.getType() == MappedRes.getType() && "The types must match"); InsertedPHIs.clear(); Updater.Initialize(Res.getType()); Updater.AddAvailableValue(Header, Res); Updater.AddAvailableValue(EntryCheckBlock, MappedRes); // Because of the way that phi nodes are represented we have to collect all // uses before we update SSA. Modifying one phi node can invalidate another // unrelated phi nodes operands through the common branch instruction (that // has to be modified). This would invalidate a plain ValueUseIterator. // Instead we collect uses wrapping uses in branches specially so that we // can reconstruct the use even after the branch has been modified. SmallVector<UseWrapper, 8> StoredUses; for (auto *U : Res.getUses()) StoredUses.push_back(UseWrapper(U)); for (auto U : StoredUses) { Operand *Use = U; SILInstruction *User = Use->getUser(); assert(User && "Missing user"); // Ignore uses in the same basic block. if (User->getParent() == Header) continue; assert(User->getParent() != EntryCheckBlock && "The entry check block should dominate the header"); Updater.RewriteUse(*Use); } // Canonicalize inserted phis to avoid extra BB Args. for (SILArgument *Arg : InsertedPHIs) { if (SILInstruction *Inst = replaceBBArgWithCast(Arg)) { Arg->replaceAllUsesWith(Inst); // DCE+SimplifyCFG runs as a post-pass cleanup. // DCE replaces dead arg values with undef. // SimplifyCFG deletes the dead BB arg. } } } }
bool ARCInstrInfo::analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl<MachineOperand> &Cond, bool AllowModify) const { TBB = FBB = nullptr; MachineBasicBlock::iterator I = MBB.end(); if (I == MBB.begin()) return false; --I; while (isPredicated(*I) || I->isTerminator() || I->isDebugValue()) { // Flag to be raised on unanalyzeable instructions. This is useful in cases // where we want to clean up on the end of the basic block before we bail // out. bool CantAnalyze = false; // Skip over DEBUG values and predicated nonterminators. while (I->isDebugValue() || !I->isTerminator()) { if (I == MBB.begin()) return false; --I; } if (isJumpOpcode(I->getOpcode())) { // Indirect branches and jump tables can't be analyzed, but we still want // to clean up any instructions at the tail of the basic block. CantAnalyze = true; } else if (isUncondBranchOpcode(I->getOpcode())) { TBB = I->getOperand(0).getMBB(); } else if (isCondBranchOpcode(I->getOpcode())) { // Bail out if we encounter multiple conditional branches. if (!Cond.empty()) return true; assert(!FBB && "FBB should have been null."); FBB = TBB; TBB = I->getOperand(0).getMBB(); Cond.push_back(I->getOperand(1)); Cond.push_back(I->getOperand(2)); Cond.push_back(I->getOperand(3)); } else if (I->isReturn()) { // Returns can't be analyzed, but we should run cleanup. CantAnalyze = !isPredicated(*I); } else { // We encountered other unrecognized terminator. Bail out immediately. return true; } // Cleanup code - to be run for unpredicated unconditional branches and // returns. if (!isPredicated(*I) && (isUncondBranchOpcode(I->getOpcode()) || isJumpOpcode(I->getOpcode()) || I->isReturn())) { // Forget any previous condition branch information - it no longer // applies. Cond.clear(); FBB = nullptr; // If we can modify the function, delete everything below this // unconditional branch. if (AllowModify) { MachineBasicBlock::iterator DI = std::next(I); while (DI != MBB.end()) { MachineInstr &InstToDelete = *DI; ++DI; InstToDelete.eraseFromParent(); } } } if (CantAnalyze) return true; if (I == MBB.begin()) return false; --I; } // We made it past the terminators without bailing out - we must have // analyzed this branch successfully. return false; }
// The AnalyzeBranch function is used to examine conditional instructions and // remove unnecessary instructions. This method is used by BranchFolder and // IfConverter machine function passes to improve the CFG. // - TrueBlock is set to the destination if condition evaluates true (it is the // nullptr if the destination is the fall-through branch); // - FalseBlock is set to the destination if condition evaluates to false (it // is the nullptr if the branch is unconditional); // - condition is populated with machine operands needed to generate the branch // to insert in InsertBranch; // Returns: false if branch could successfully be analyzed. bool LanaiInstrInfo::analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TrueBlock, MachineBasicBlock *&FalseBlock, SmallVectorImpl<MachineOperand> &Condition, bool AllowModify) const { // Iterator to current instruction being considered. MachineBasicBlock::iterator Instruction = MBB.end(); // Start from the bottom of the block and work up, examining the // terminator instructions. while (Instruction != MBB.begin()) { --Instruction; // Skip over debug values. if (Instruction->isDebugValue()) continue; // Working from the bottom, when we see a non-terminator // instruction, we're done. if (!isUnpredicatedTerminator(*Instruction)) break; // A terminator that isn't a branch can't easily be handled // by this analysis. if (!Instruction->isBranch()) return true; // Handle unconditional branches. if (Instruction->getOpcode() == Lanai::BT) { if (!AllowModify) { TrueBlock = Instruction->getOperand(0).getMBB(); continue; } // If the block has any instructions after a branch, delete them. while (std::next(Instruction) != MBB.end()) { std::next(Instruction)->eraseFromParent(); } Condition.clear(); FalseBlock = nullptr; // Delete the jump if it's equivalent to a fall-through. if (MBB.isLayoutSuccessor(Instruction->getOperand(0).getMBB())) { TrueBlock = nullptr; Instruction->eraseFromParent(); Instruction = MBB.end(); continue; } // TrueBlock is used to indicate the unconditional destination. TrueBlock = Instruction->getOperand(0).getMBB(); continue; } // Handle conditional branches unsigned Opcode = Instruction->getOpcode(); if (Opcode != Lanai::BRCC) return true; // Unknown opcode. // Multiple conditional branches are not handled here so only proceed if // there are no conditions enqueued. if (Condition.empty()) { LPCC::CondCode BranchCond = static_cast<LPCC::CondCode>(Instruction->getOperand(1).getImm()); // TrueBlock is the target of the previously seen unconditional branch. FalseBlock = TrueBlock; TrueBlock = Instruction->getOperand(0).getMBB(); Condition.push_back(MachineOperand::CreateImm(BranchCond)); continue; } // Multiple conditional branches are not handled. return true; } // Return false indicating branch successfully analyzed. return false; }
/// \brief Function to convert constant initializers for global /// variables into corresponding bitcode. Takes advantage that these /// global variable initializations are normalized (see /// lib/Transforms/NaCl/FlattenGlobals.cpp). void WriteGlobalInit(const Constant *C, unsigned GlobalVarID, SmallVectorImpl<uint32_t> &Vals, const NaClValueEnumerator &VE, NaClBitstreamWriter &Stream) { if (ArrayType *Ty = dyn_cast<ArrayType>(C->getType())) { if (!Ty->getElementType()->isIntegerTy(8)) report_fatal_error("Global array initializer not i8"); uint32_t Size = Ty->getNumElements(); if (isa<ConstantAggregateZero>(C)) { Vals.push_back(Size); Stream.EmitRecord(naclbitc::GLOBALVAR_ZEROFILL, Vals, GLOBALVAR_ZEROFILL_ABBREV); Vals.clear(); } else { const ConstantDataSequential *CD = cast<ConstantDataSequential>(C); StringRef Data = CD->getRawDataValues(); for (size_t i = 0; i < Size; ++i) { Vals.push_back(Data[i] & 0xFF); } Stream.EmitRecord(naclbitc::GLOBALVAR_DATA, Vals, GLOBALVAR_DATA_ABBREV); Vals.clear(); } return; } if (VE.IsIntPtrType(C->getType())) { // This constant defines a relocation. Start by verifying the // relocation is of the right form. const ConstantExpr *CE = dyn_cast<ConstantExpr>(C); if (CE == 0) report_fatal_error("Global i32 initializer not constant"); assert(CE); int32_t Addend = 0; if (CE->getOpcode() == Instruction::Add) { const ConstantInt *AddendConst = dyn_cast<ConstantInt>(CE->getOperand(1)); if (AddendConst == 0) report_fatal_error("Malformed addend in global relocation initializer"); Addend = AddendConst->getSExtValue(); CE = dyn_cast<ConstantExpr>(CE->getOperand(0)); if (CE == 0) report_fatal_error( "Base of global relocation initializer not constant"); } if (CE->getOpcode() != Instruction::PtrToInt) report_fatal_error("Global relocation base doesn't contain ptrtoint"); GlobalValue *GV = dyn_cast<GlobalValue>(CE->getOperand(0)); if (GV == 0) report_fatal_error( "Argument of ptrtoint in global relocation no global value"); // Now generate the corresponding relocation record. unsigned RelocID = VE.getValueID(GV); // This is a value index. unsigned AbbrevToUse = GLOBALVAR_RELOC_ABBREV; Vals.push_back(RelocID); if (Addend) { Vals.push_back(Addend); AbbrevToUse = GLOBALVAR_RELOC_WITH_ADDEND_ABBREV; } Stream.EmitRecord(naclbitc::GLOBALVAR_RELOC, Vals, AbbrevToUse); Vals.clear(); return; } report_fatal_error("Global initializer is not a SimpleElement"); }
bool SystemZInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl<MachineOperand> &Cond, bool AllowModify) const { // Most of the code and comments here are boilerplate. // Start from the bottom of the block and work up, examining the // terminator instructions. MachineBasicBlock::iterator I = MBB.end(); while (I != MBB.begin()) { --I; if (I->isDebugValue()) continue; // Working from the bottom, when we see a non-terminator instruction, we're // done. if (!isUnpredicatedTerminator(I)) break; // A terminator that isn't a branch can't easily be handled by this // analysis. unsigned ThisCond; const MachineOperand *ThisTarget; if (!isBranch(I, ThisCond, ThisTarget)) return true; // Can't handle indirect branches. if (!ThisTarget->isMBB()) return true; if (ThisCond == SystemZ::CCMASK_ANY) { // Handle unconditional branches. if (!AllowModify) { TBB = ThisTarget->getMBB(); continue; } // If the block has any instructions after a JMP, delete them. while (llvm::next(I) != MBB.end()) llvm::next(I)->eraseFromParent(); Cond.clear(); FBB = 0; // Delete the JMP if it's equivalent to a fall-through. if (MBB.isLayoutSuccessor(ThisTarget->getMBB())) { TBB = 0; I->eraseFromParent(); I = MBB.end(); continue; } // TBB is used to indicate the unconditinal destination. TBB = ThisTarget->getMBB(); continue; } // Working from the bottom, handle the first conditional branch. if (Cond.empty()) { // FIXME: add X86-style branch swap FBB = TBB; TBB = ThisTarget->getMBB(); Cond.push_back(MachineOperand::CreateImm(ThisCond)); continue; } // Handle subsequent conditional branches. assert(Cond.size() == 1); assert(TBB); // Only handle the case where all conditional branches branch to the same // destination. if (TBB != ThisTarget->getMBB()) return true; // If the conditions are the same, we can leave them alone. unsigned OldCond = Cond[0].getImm(); if (OldCond == ThisCond) continue; // FIXME: Try combining conditions like X86 does. Should be easy on Z! } return false; }
bool AVRInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl<MachineOperand> &Cond, bool AllowModify) const { // Start from the bottom of the block and work up, examining the // terminator instructions. MachineBasicBlock::iterator I = MBB.end(); MachineBasicBlock::iterator UnCondBrIter = MBB.end(); while (I != MBB.begin()) { --I; if (I->isDebugValue()) { continue; } // Working from the bottom, when we see a non-terminator // instruction, we're done. if (!isUnpredicatedTerminator(*I)) { break; } // A terminator that isn't a branch can't easily be handled // by this analysis. if (!I->getDesc().isBranch()) { return true; } // Handle unconditional branches. //:TODO: add here jmp if (I->getOpcode() == AVR::RJMPk) { UnCondBrIter = I; if (!AllowModify) { TBB = I->getOperand(0).getMBB(); continue; } // If the block has any instructions after a JMP, delete them. while (std::next(I) != MBB.end()) { std::next(I)->eraseFromParent(); } Cond.clear(); FBB = 0; // Delete the JMP if it's equivalent to a fall-through. if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) { TBB = 0; I->eraseFromParent(); I = MBB.end(); UnCondBrIter = MBB.end(); continue; } // TBB is used to indicate the unconditinal destination. TBB = I->getOperand(0).getMBB(); continue; } // Handle conditional branches. AVRCC::CondCodes BranchCode = getCondFromBranchOpc(I->getOpcode()); if (BranchCode == AVRCC::COND_INVALID) { return true; // Can't handle indirect branch. } // Working from the bottom, handle the first conditional branch. if (Cond.empty()) { MachineBasicBlock *TargetBB = I->getOperand(0).getMBB(); if (AllowModify && UnCondBrIter != MBB.end() && MBB.isLayoutSuccessor(TargetBB)) { // If we can modify the code and it ends in something like: // // jCC L1 // jmp L2 // L1: // ... // L2: // // Then we can change this to: // // jnCC L2 // L1: // ... // L2: // // Which is a bit more efficient. // We conditionally jump to the fall-through block. BranchCode = getOppositeCondition(BranchCode); unsigned JNCC = getBrCond(BranchCode).getOpcode(); MachineBasicBlock::iterator OldInst = I; BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(JNCC)) .addMBB(UnCondBrIter->getOperand(0).getMBB()); BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(AVR::RJMPk)) .addMBB(TargetBB); OldInst->eraseFromParent(); UnCondBrIter->eraseFromParent(); // Restart the analysis. UnCondBrIter = MBB.end(); I = MBB.end(); continue; } FBB = TBB; TBB = I->getOperand(0).getMBB(); Cond.push_back(MachineOperand::CreateImm(BranchCode)); continue; } // Handle subsequent conditional branches. Only handle the case where all // conditional branches branch to the same destination. assert(Cond.size() == 1); assert(TBB); // Only handle the case where all conditional branches branch to // the same destination. if (TBB != I->getOperand(0).getMBB()) { return true; } AVRCC::CondCodes OldBranchCode = (AVRCC::CondCodes)Cond[0].getImm(); // If the conditions are the same, we can leave them alone. if (OldBranchCode == BranchCode) { continue; } return true; } return false; }
unsigned ConstraintGraph::computeConnectedComponents( SmallVectorImpl<TypeVariableType *> &typeVars, SmallVectorImpl<unsigned> &components) { // Track those type variables that the caller cares about. llvm::SmallPtrSet<TypeVariableType *, 4> typeVarSubset(typeVars.begin(), typeVars.end()); typeVars.clear(); // Initialize the components with component == # of type variables, // a sentinel value indicating unsigned numTypeVariables = TypeVariables.size(); components.assign(numTypeVariables, numTypeVariables); // Perform a depth-first search from each type variable to identify // what component it is in. unsigned numComponents = 0; for (unsigned i = 0; i != numTypeVariables; ++i) { auto typeVar = TypeVariables[i]; // Look up the node for this type variable. auto nodeAndIndex = lookupNode(typeVar); // If we're already assigned a component for this node, skip it. unsigned &curComponent = components[nodeAndIndex.second]; if (curComponent != numTypeVariables) continue; // Record this component. unsigned component = numComponents++; // Note that this node is part of this component, then visit it. curComponent = component; connectedComponentsDFS(*this, nodeAndIndex.first, component, components); } // Figure out which components have unbound type variables; these // are the only components and type variables we want to report. SmallVector<bool, 4> componentHasUnboundTypeVar(numComponents, false); for (unsigned i = 0; i != numTypeVariables; ++i) { // If this type variable has a fixed type, skip it. if (CS.getFixedType(TypeVariables[i])) continue; // If we only care about a subset, and this type variable isn't in that // subset, skip it. if (!typeVarSubset.empty() && typeVarSubset.count(TypeVariables[i]) == 0) continue; componentHasUnboundTypeVar[components[i]] = true; } // Renumber the old components to the new components. SmallVector<unsigned, 4> componentRenumbering(numComponents, 0); numComponents = 0; for (unsigned i = 0, n = componentHasUnboundTypeVar.size(); i != n; ++i) { // Skip components that have no unbound type variables. if (!componentHasUnboundTypeVar[i]) continue; componentRenumbering[i] = numComponents++; } // Copy over the type variables in the live components and remap // component numbers. unsigned outIndex = 0; for (unsigned i = 0, n = TypeVariables.size(); i != n; ++i) { // Skip type variables in dead components. if (!componentHasUnboundTypeVar[components[i]]) continue; typeVars.push_back(TypeVariables[i]); components[outIndex] = componentRenumbering[components[i]]; ++outIndex; } components.erase(components.begin() + outIndex, components.end()); return numComponents; }
bool DCPU16InstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl<MachineOperand> &Cond, bool AllowModify) const { // Start from the bottom of the block and work up, examining the // terminator instructions. MachineBasicBlock::iterator I = MBB.end(); while (I != MBB.begin()) { --I; if (I->isDebugValue()) continue; // Working from the bottom, when we see a non-terminator // instruction, we're done. if (!isUnpredicatedTerminator(I)) break; // A terminator that isn't a branch can't easily be handled // by this analysis. if (!I->isBranch()) return true; // Cannot handle indirect branches. if (I->getOpcode() == DCPU16::Br || I->getOpcode() == DCPU16::Bm) return true; // Handle unconditional branches. if (I->getOpcode() == DCPU16::JMP) { if (!AllowModify) { TBB = I->getOperand(0).getMBB(); continue; } // If the block has any instructions after a JMP, delete them. while (llvm::next(I) != MBB.end()) llvm::next(I)->eraseFromParent(); Cond.clear(); FBB = 0; // Delete the JMP if it's equivalent to a fall-through. if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) { TBB = 0; I->eraseFromParent(); I = MBB.end(); continue; } // TBB is used to indicate the unconditinal destination. TBB = I->getOperand(0).getMBB(); continue; } // Handle conditional branches. assert(isBR_CC(I->getOpcode()) && "Invalid conditional branch"); DCPU16CC::CondCodes BranchCode = static_cast<DCPU16CC::CondCodes>(I->getOperand(0).getImm()); if (BranchCode == DCPU16CC::COND_INVALID) return true; // Can't handle weird stuff. MachineOperand LHS = I->getOperand(1); MachineOperand RHS = I->getOperand(2); // Working from the bottom, handle the first conditional branch. if (Cond.empty()) { FBB = TBB; TBB = I->getOperand(3).getMBB(); Cond.push_back(MachineOperand::CreateImm(I->getOpcode())); Cond.push_back(MachineOperand::CreateImm(BranchCode)); Cond.push_back(LHS); Cond.push_back(RHS); continue; } assert(Cond.size() == 4); assert(TBB); // Is it a complex CC? DCPU16CC::CondCodes complexCC; if ((BranchCode == DCPU16CC::COND_E) && AcceptsAdditionalEqualityCheck((DCPU16CC::CondCodes) Cond[1].getImm(), &complexCC) && (TBB == I->getOperand(3).getMBB()) // This should actually check for equality but that's just too much code... && (((Cond[2].getType() == LHS.getType()) && (Cond[3].getType() == RHS.getType())) || ((Cond[2].getType() == RHS.getType()) && (Cond[3].getType() == LHS.getType())))) { Cond[1] = MachineOperand::CreateImm(complexCC); } break; } return false; }