bool executive::ReconvergenceBarrier::eval_Bra(executive::CTAContext &context, const ir::PTXInstruction &instr, const boost::dynamic_bitset<> & branch, const boost::dynamic_bitset<> & fallthrough) { bool isDivergent = false; if (instr.uni) { // unfiorm if (branch.count()) { // all threads branch context.PC = instr.branchTargetInstruction; } else { // all threads fall through context.PC ++; } } else { // divergence - complicated CTAContext branchContext(context), fallthroughContext(context); branchContext.active = branch; branchContext.PC = instr.branchTargetInstruction; fallthroughContext.active = fallthrough; fallthroughContext.PC++; runtimeStack.pop_back(); if (branchContext.active.any()) { runtimeStack.push_back(branchContext); } if (fallthroughContext.active.any()) { runtimeStack.push_back(fallthroughContext); } isDivergent = true; } return isDivergent; }
/// \brief Check if the split is informative /// /// \param p The split bool informative(const boost::dynamic_bitset<>& p) { int N = p.size(); int C = p.count(); return (C >= 2) and ((N-C) >= 2); }
std::size_t range_calculate_size(boost::dynamic_bitset<I,A> const& c) { return c.count(); }
bool executive::ReconvergenceIPDOM::eval_Bra(executive::CTAContext &context, const ir::PTXInstruction &instr, const boost::dynamic_bitset<> & branch, const boost::dynamic_bitset<> & fallthrough) { bool isDivergent = false; if (instr.uni) { // unfiorm if (branch.count()) { // all threads branch context.PC = instr.branchTargetInstruction; } else { // all threads fall through context.PC ++; } } else { // divergence - complicated CTAContext branchContext(context), fallthroughContext(context), reconvergeContext(context); int pc = context.PC + 1; branchContext.active = branch; branchContext.PC = instr.branchTargetInstruction; fallthroughContext.active = fallthrough; fallthroughContext.PC = pc; reconvergeContext.PC = instr.reconvergeInstruction + 1; int reconverge = pcStack.back(); Token token = tokenStack.back(); runtimeStack.pop_back(); pcStack.pop_back(); tokenStack.pop_back(); bool reconvergeContextAlreadyExists = false; // only look for existing contexts in the current stack frame if(token != Call) { auto ti = tokenStack.rbegin(); for(auto si = runtimeStack.rbegin(); si != runtimeStack.rend(); ++si, ++ti) { assert(ti != tokenStack.rend()); if(si->PC == reconvergeContext.PC) { reconvergeContextAlreadyExists = true; break; } if(*ti != Branch) { continue; } } } if(!reconvergeContextAlreadyExists) { report(" (" << pc << ") Pushing reconvergence context at " << reconvergeContext.PC << " (type " << toString(token) << ")"); runtimeStack.push_back(reconvergeContext); pcStack.push_back(reconverge); tokenStack.push_back(token); } if (branchContext.active.any()) { report(" (" << pc << ") Pushing branch context at " << branchContext.PC << ", reconverge at " << instr.reconvergeInstruction << " (type " << toString(Branch) << ")"); runtimeStack.push_back(branchContext); pcStack.push_back(instr.reconvergeInstruction); tokenStack.push_back(Branch); } if (fallthroughContext.active.any()) { report(" (" << pc << ") Pushing fallthrough context at " << fallthroughContext.PC << ", reconverge at " << instr.reconvergeInstruction << " (type " << toString(Branch) << ")"); runtimeStack.push_back(fallthroughContext); pcStack.push_back(instr.reconvergeInstruction); tokenStack.push_back(Branch); } } return isDivergent; }