// Look for control dependencies on a read. bool branchesOn(BasicBlock *bb, Value *load, ICmpInst **icmpOut, int *outIdx) { // XXX: make this platform configured; on some platforms maybe an // atomic cmpxchg does /not/ behave like it branches on the old value if (isa<AtomicCmpXchgInst>(load) || isa<AtomicRMWInst>(load)) { if (icmpOut) *icmpOut = nullptr; if (outIdx) *outIdx = 0; return true; } // TODO: we should be able to follow values through phi nodes, // since we are path dependent anyways. BranchInst *br = dyn_cast<BranchInst>(bb->getTerminator()); if (!br || !br->isConditional()) return false; // TODO: We only check one level of things. Check deeper? // We pretty heavily restrict what operations we handle here. // Some would just be wrong (like call), but really icmp is // the main one, so. Probably we should be able to also // pick through casts and wideness changes. ICmpInst *icmp = dyn_cast<ICmpInst>(br->getCondition()); if (!icmp) return false; int idx = 0; for (auto v : icmp->operand_values()) { if (getRealValue(v) == load) { if (icmpOut) *icmpOut = icmp; if (outIdx) *outIdx = idx; return true; } ++idx; } return false; }