/// getFeasibleSuccessors - Return a vector of booleans to indicate which /// successors are reachable from a given terminator instruction. void SparseSolver::getFeasibleSuccessors(TerminatorInst &TI, SmallVectorImpl<bool> &Succs, bool AggressiveUndef) { Succs.resize(TI.getNumSuccessors()); if (TI.getNumSuccessors() == 0) return; if (BranchInst *BI = dyn_cast<BranchInst>(&TI)) { if (BI->isUnconditional()) { Succs[0] = true; return; } LatticeVal BCValue; if (AggressiveUndef) BCValue = getOrInitValueState(BI->getCondition()); else BCValue = getLatticeState(BI->getCondition()); if (BCValue == LatticeFunc->getOverdefinedVal() || BCValue == LatticeFunc->getUntrackedVal()) { // Overdefined condition variables can branch either way. Succs[0] = Succs[1] = true; return; } // If undefined, neither is feasible yet. if (BCValue == LatticeFunc->getUndefVal()) return; Constant *C = LatticeFunc->GetConstant(BCValue, BI->getCondition(), *this); if (C == 0 || !isa<ConstantInt>(C)) { // Non-constant values can go either way. Succs[0] = Succs[1] = true; return; } // Constant condition variables mean the branch can only go a single way Succs[C->isNullValue()] = true; return; } if (isa<InvokeInst>(TI)) { // Invoke instructions successors are always executable. // TODO: Could ask the lattice function if the value can throw. Succs[0] = Succs[1] = true; return; } if (isa<IndirectBrInst>(TI)) { Succs.assign(Succs.size(), true); return; } SwitchInst &SI = cast<SwitchInst>(TI); LatticeVal SCValue; if (AggressiveUndef) SCValue = getOrInitValueState(SI.getCondition()); else SCValue = getLatticeState(SI.getCondition()); if (SCValue == LatticeFunc->getOverdefinedVal() || SCValue == LatticeFunc->getUntrackedVal()) { // All destinations are executable! Succs.assign(TI.getNumSuccessors(), true); return; } // If undefined, neither is feasible yet. if (SCValue == LatticeFunc->getUndefVal()) return; Constant *C = LatticeFunc->GetConstant(SCValue, SI.getCondition(), *this); if (C == 0 || !isa<ConstantInt>(C)) { // All destinations are executable! Succs.assign(TI.getNumSuccessors(), true); return; } SwitchInst::CaseIt Case = SI.findCaseValue(cast<ConstantInt>(C)); Succs[Case.getSuccessorIndex()] = true; }
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; }
/// CollectSingleShuffleElements - If V is a shuffle of values that ONLY returns /// elements from either LHS or RHS, return the shuffle mask and true. /// Otherwise, return false. static bool CollectSingleShuffleElements(Value *V, Value *LHS, Value *RHS, SmallVectorImpl<Constant*> &Mask) { assert(V->getType() == LHS->getType() && V->getType() == RHS->getType() && "Invalid CollectSingleShuffleElements"); unsigned NumElts = cast<VectorType>(V->getType())->getNumElements(); if (isa<UndefValue>(V)) { Mask.assign(NumElts, UndefValue::get(Type::getInt32Ty(V->getContext()))); return true; } if (V == LHS) { for (unsigned i = 0; i != NumElts; ++i) Mask.push_back(ConstantInt::get(Type::getInt32Ty(V->getContext()), i)); return true; } if (V == RHS) { for (unsigned i = 0; i != NumElts; ++i) Mask.push_back(ConstantInt::get(Type::getInt32Ty(V->getContext()), i+NumElts)); return true; } if (InsertElementInst *IEI = dyn_cast<InsertElementInst>(V)) { // If this is an insert of an extract from some other vector, include it. Value *VecOp = IEI->getOperand(0); Value *ScalarOp = IEI->getOperand(1); Value *IdxOp = IEI->getOperand(2); if (!isa<ConstantInt>(IdxOp)) return false; unsigned InsertedIdx = cast<ConstantInt>(IdxOp)->getZExtValue(); if (isa<UndefValue>(ScalarOp)) { // inserting undef into vector. // Okay, we can handle this if the vector we are insertinting into is // transitively ok. if (CollectSingleShuffleElements(VecOp, LHS, RHS, Mask)) { // If so, update the mask to reflect the inserted undef. Mask[InsertedIdx] = UndefValue::get(Type::getInt32Ty(V->getContext())); return true; } } else if (ExtractElementInst *EI = dyn_cast<ExtractElementInst>(ScalarOp)){ if (isa<ConstantInt>(EI->getOperand(1)) && EI->getOperand(0)->getType() == V->getType()) { unsigned ExtractedIdx = cast<ConstantInt>(EI->getOperand(1))->getZExtValue(); // This must be extracting from either LHS or RHS. if (EI->getOperand(0) == LHS || EI->getOperand(0) == RHS) { // Okay, we can handle this if the vector we are insertinting into is // transitively ok. if (CollectSingleShuffleElements(VecOp, LHS, RHS, Mask)) { // If so, update the mask to reflect the inserted value. if (EI->getOperand(0) == LHS) { Mask[InsertedIdx % NumElts] = ConstantInt::get(Type::getInt32Ty(V->getContext()), ExtractedIdx); } else { assert(EI->getOperand(0) == RHS); Mask[InsertedIdx % NumElts] = ConstantInt::get(Type::getInt32Ty(V->getContext()), ExtractedIdx+NumElts); } return true; } } } } } // TODO: Handle shufflevector here! return false; }
static ShuffleOps CollectShuffleElements(Value *V, SmallVectorImpl<Constant *> &Mask, Value *PermittedRHS) { assert(V->getType()->isVectorTy() && "Invalid shuffle!"); unsigned NumElts = cast<VectorType>(V->getType())->getNumElements(); if (isa<UndefValue>(V)) { Mask.assign(NumElts, UndefValue::get(Type::getInt32Ty(V->getContext()))); return std::make_pair( PermittedRHS ? UndefValue::get(PermittedRHS->getType()) : V, nullptr); } if (isa<ConstantAggregateZero>(V)) { Mask.assign(NumElts, ConstantInt::get(Type::getInt32Ty(V->getContext()),0)); return std::make_pair(V, nullptr); } if (InsertElementInst *IEI = dyn_cast<InsertElementInst>(V)) { // If this is an insert of an extract from some other vector, include it. Value *VecOp = IEI->getOperand(0); Value *ScalarOp = IEI->getOperand(1); Value *IdxOp = IEI->getOperand(2); if (ExtractElementInst *EI = dyn_cast<ExtractElementInst>(ScalarOp)) { if (isa<ConstantInt>(EI->getOperand(1)) && isa<ConstantInt>(IdxOp)) { unsigned ExtractedIdx = cast<ConstantInt>(EI->getOperand(1))->getZExtValue(); unsigned InsertedIdx = cast<ConstantInt>(IdxOp)->getZExtValue(); // Either the extracted from or inserted into vector must be RHSVec, // otherwise we'd end up with a shuffle of three inputs. if (EI->getOperand(0) == PermittedRHS || PermittedRHS == nullptr) { Value *RHS = EI->getOperand(0); ShuffleOps LR = CollectShuffleElements(VecOp, Mask, RHS); assert(LR.second == nullptr || LR.second == RHS); if (LR.first->getType() != RHS->getType()) { // We tried our best, but we can't find anything compatible with RHS // further up the chain. Return a trivial shuffle. for (unsigned i = 0; i < NumElts; ++i) Mask[i] = ConstantInt::get(Type::getInt32Ty(V->getContext()), i); return std::make_pair(V, nullptr); } unsigned NumLHSElts = RHS->getType()->getVectorNumElements(); Mask[InsertedIdx % NumElts] = ConstantInt::get(Type::getInt32Ty(V->getContext()), NumLHSElts+ExtractedIdx); return std::make_pair(LR.first, RHS); } if (VecOp == PermittedRHS) { // We've gone as far as we can: anything on the other side of the // extractelement will already have been converted into a shuffle. unsigned NumLHSElts = EI->getOperand(0)->getType()->getVectorNumElements(); for (unsigned i = 0; i != NumElts; ++i) Mask.push_back(ConstantInt::get( Type::getInt32Ty(V->getContext()), i == InsertedIdx ? ExtractedIdx : NumLHSElts + i)); return std::make_pair(EI->getOperand(0), PermittedRHS); } // If this insertelement is a chain that comes from exactly these two // vectors, return the vector and the effective shuffle. if (EI->getOperand(0)->getType() == PermittedRHS->getType() && CollectSingleShuffleElements(IEI, EI->getOperand(0), PermittedRHS, Mask)) return std::make_pair(EI->getOperand(0), PermittedRHS); } } } // Otherwise, can't do anything fancy. Return an identity vector. for (unsigned i = 0; i != NumElts; ++i) Mask.push_back(ConstantInt::get(Type::getInt32Ty(V->getContext()), i)); return std::make_pair(V, nullptr); }