}
}
+// XXX-update: For a relaxed load 'LI', if the first upcoming instruction is a
+// store/cond branch, return it; if its a load, returns the last load before the
+// first store/cond branch. Returns nullptr if there's no such immediately
+// following store/branch instructions, which we can only enforce the load with
+// 'acquire'. 'ChainedBB' contains all the blocks chained together with
+// unconditional branches from 'BB' to the block with the first store/cond
+// branch.
+template <typename Vector>
+Instruction* findLastLoadOrFirstStoreCondBranchInst(LoadInst* LI, Vector* ChainedBB) {
+ assert(ChainedBB != nullptr && "Chained BB should not be nullptr");
+ auto* BB = LI->getParent();
+ ChainedBB->push_back(BB);
+ auto BE = BB->end();
+ auto BBI = BasicBlock::iterator(LI);
+ BBI++;
+ bool IsFirstLoad = false;
+ Instruction* LastLI = nullptr;
+ while (true) {
+ for (; BBI != BE; BBI++) {
+ Instruction* Inst = &*BBI;
+ IntrinsicInst* II = dyn_cast<IntrinsicInst>(&*BBI);
+ if (II) {
+ if (II->getIntrinsicID() == Intrinsic::aarch64_stlxr) {
+
+ } else if (II->getIntrinsicID() == Intrinsic::aarch64_ldxr) {
+ return II;
+ }
+ } else if (Inst->getOpcode() == Instruction::Load) {
+ IsFirstLoad = true;
+ LastLI = Inst;
+ } else if (Inst->getOpcode() == Instruction::Store) {
+ if (IsFirstLoad) {
+ return LastLI;
+ } else {
+ return Inst;
+ }
+ } else if (Inst->getOpcode() == Instruction::Br) {
+ auto* BrInst = dyn_cast<BranchInst>(Inst);
+ if (BrInst->isConditional()) {
+ if (IsFirstLoad) {
+ return LastLI;
+ } else {
+ return Inst;
+ }
+ } else {
+ // Reinitialize iterators with the destination of the unconditional
+ // branch.
+ BB = BrInst->getSuccessor(0);
+ ChainedBB->push_back(BB);
+ BBI = BB->begin();
+ BE = BB->end();
+ break;
+ }
+ }
+ }
+ if (BBI == BE) {
+ if (IsFirstLoad) {
+ return LastLI;
+ } else {
+ return nullptr;
+ }
+ }
+ }
+}
+
// XXX-update: Find the next node of the last relaxed load from 'FromInst' to
// 'ToInst'. If none, return 'ToInst'.
Instruction* findLastLoadNext(Instruction* FromInst, Instruction* ToInst) {
auto* LI = *MonotonicLoadInsts.begin();
MonotonicLoadInsts.erase(LI);
SmallVector<BasicBlock*, 2> ChainedBB;
- auto* FirstInst = findFirstLoadStoreCondBranchInst(LI, &ChainedBB);
- if (!NeedExtraConstraints(LI, FirstInst)) {
+ auto* FirstStoreBranch = findFirstStoreCondBranchInst(LI, &ChainedBB);
+ if (!NeedExtraConstraints(LI, FirstStoreBranch)) {
// 'LI' doesn't need extra load-store constraints.
continue;
}
+ auto* FirstInst = findLastLoadOrFirstStoreCondBranchInst(LI, &ChainedBB);
// We really need to process the relaxed load now. Note that if the next
// instruction is a RMW, it will be transformed into a control block, so we
// can safely only taint upcoming store instructions.