SwiftErrorValueTracking.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. //===-- SwiftErrorValueTracking.cpp --------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This implements a limited mem2reg-like analysis to promote uses of function
  10. // arguments and allocas marked with swiftalloc from memory into virtual
  11. // registers tracked by this class.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "llvm/CodeGen/SwiftErrorValueTracking.h"
  15. #include "llvm/ADT/PostOrderIterator.h"
  16. #include "llvm/ADT/SmallSet.h"
  17. #include "llvm/CodeGen/MachineInstrBuilder.h"
  18. #include "llvm/CodeGen/MachineRegisterInfo.h"
  19. #include "llvm/CodeGen/TargetInstrInfo.h"
  20. #include "llvm/CodeGen/TargetLowering.h"
  21. #include "llvm/IR/Value.h"
  22. using namespace llvm;
  23. Register SwiftErrorValueTracking::getOrCreateVReg(const MachineBasicBlock *MBB,
  24. const Value *Val) {
  25. auto Key = std::make_pair(MBB, Val);
  26. auto It = VRegDefMap.find(Key);
  27. // If this is the first use of this swifterror value in this basic block,
  28. // create a new virtual register.
  29. // After we processed all basic blocks we will satisfy this "upwards exposed
  30. // use" by inserting a copy or phi at the beginning of this block.
  31. if (It == VRegDefMap.end()) {
  32. auto &DL = MF->getDataLayout();
  33. const TargetRegisterClass *RC = TLI->getRegClassFor(TLI->getPointerTy(DL));
  34. auto VReg = MF->getRegInfo().createVirtualRegister(RC);
  35. VRegDefMap[Key] = VReg;
  36. VRegUpwardsUse[Key] = VReg;
  37. return VReg;
  38. } else
  39. return It->second;
  40. }
  41. void SwiftErrorValueTracking::setCurrentVReg(const MachineBasicBlock *MBB,
  42. const Value *Val, Register VReg) {
  43. VRegDefMap[std::make_pair(MBB, Val)] = VReg;
  44. }
  45. Register SwiftErrorValueTracking::getOrCreateVRegDefAt(
  46. const Instruction *I, const MachineBasicBlock *MBB, const Value *Val) {
  47. auto Key = PointerIntPair<const Instruction *, 1, bool>(I, true);
  48. auto It = VRegDefUses.find(Key);
  49. if (It != VRegDefUses.end())
  50. return It->second;
  51. auto &DL = MF->getDataLayout();
  52. const TargetRegisterClass *RC = TLI->getRegClassFor(TLI->getPointerTy(DL));
  53. Register VReg = MF->getRegInfo().createVirtualRegister(RC);
  54. VRegDefUses[Key] = VReg;
  55. setCurrentVReg(MBB, Val, VReg);
  56. return VReg;
  57. }
  58. Register SwiftErrorValueTracking::getOrCreateVRegUseAt(
  59. const Instruction *I, const MachineBasicBlock *MBB, const Value *Val) {
  60. auto Key = PointerIntPair<const Instruction *, 1, bool>(I, false);
  61. auto It = VRegDefUses.find(Key);
  62. if (It != VRegDefUses.end())
  63. return It->second;
  64. Register VReg = getOrCreateVReg(MBB, Val);
  65. VRegDefUses[Key] = VReg;
  66. return VReg;
  67. }
  68. /// Set up SwiftErrorVals by going through the function. If the function has
  69. /// swifterror argument, it will be the first entry.
  70. void SwiftErrorValueTracking::setFunction(MachineFunction &mf) {
  71. MF = &mf;
  72. Fn = &MF->getFunction();
  73. TLI = MF->getSubtarget().getTargetLowering();
  74. TII = MF->getSubtarget().getInstrInfo();
  75. if (!TLI->supportSwiftError())
  76. return;
  77. SwiftErrorVals.clear();
  78. VRegDefMap.clear();
  79. VRegUpwardsUse.clear();
  80. VRegDefUses.clear();
  81. SwiftErrorArg = nullptr;
  82. // Check if function has a swifterror argument.
  83. bool HaveSeenSwiftErrorArg = false;
  84. for (Function::const_arg_iterator AI = Fn->arg_begin(), AE = Fn->arg_end();
  85. AI != AE; ++AI)
  86. if (AI->hasSwiftErrorAttr()) {
  87. assert(!HaveSeenSwiftErrorArg &&
  88. "Must have only one swifterror parameter");
  89. (void)HaveSeenSwiftErrorArg; // silence warning.
  90. HaveSeenSwiftErrorArg = true;
  91. SwiftErrorArg = &*AI;
  92. SwiftErrorVals.push_back(&*AI);
  93. }
  94. for (const auto &LLVMBB : *Fn)
  95. for (const auto &Inst : LLVMBB) {
  96. if (const AllocaInst *Alloca = dyn_cast<AllocaInst>(&Inst))
  97. if (Alloca->isSwiftError())
  98. SwiftErrorVals.push_back(Alloca);
  99. }
  100. }
  101. bool SwiftErrorValueTracking::createEntriesInEntryBlock(DebugLoc DbgLoc) {
  102. if (!TLI->supportSwiftError())
  103. return false;
  104. // We only need to do this when we have swifterror parameter or swifterror
  105. // alloc.
  106. if (SwiftErrorVals.empty())
  107. return false;
  108. MachineBasicBlock *MBB = &*MF->begin();
  109. auto &DL = MF->getDataLayout();
  110. auto const *RC = TLI->getRegClassFor(TLI->getPointerTy(DL));
  111. bool Inserted = false;
  112. for (const auto *SwiftErrorVal : SwiftErrorVals) {
  113. // We will always generate a copy from the argument. It is always used at
  114. // least by the 'return' of the swifterror.
  115. if (SwiftErrorArg && SwiftErrorArg == SwiftErrorVal)
  116. continue;
  117. Register VReg = MF->getRegInfo().createVirtualRegister(RC);
  118. // Assign Undef to Vreg. We construct MI directly to make sure it works
  119. // with FastISel.
  120. BuildMI(*MBB, MBB->getFirstNonPHI(), DbgLoc,
  121. TII->get(TargetOpcode::IMPLICIT_DEF), VReg);
  122. setCurrentVReg(MBB, SwiftErrorVal, VReg);
  123. Inserted = true;
  124. }
  125. return Inserted;
  126. }
  127. /// Propagate swifterror values through the machine function CFG.
  128. void SwiftErrorValueTracking::propagateVRegs() {
  129. if (!TLI->supportSwiftError())
  130. return;
  131. // We only need to do this when we have swifterror parameter or swifterror
  132. // alloc.
  133. if (SwiftErrorVals.empty())
  134. return;
  135. // For each machine basic block in reverse post order.
  136. ReversePostOrderTraversal<MachineFunction *> RPOT(MF);
  137. for (MachineBasicBlock *MBB : RPOT) {
  138. // For each swifterror value in the function.
  139. for (const auto *SwiftErrorVal : SwiftErrorVals) {
  140. auto Key = std::make_pair(MBB, SwiftErrorVal);
  141. auto UUseIt = VRegUpwardsUse.find(Key);
  142. auto VRegDefIt = VRegDefMap.find(Key);
  143. bool UpwardsUse = UUseIt != VRegUpwardsUse.end();
  144. Register UUseVReg = UpwardsUse ? UUseIt->second : Register();
  145. bool DownwardDef = VRegDefIt != VRegDefMap.end();
  146. assert(!(UpwardsUse && !DownwardDef) &&
  147. "We can't have an upwards use but no downwards def");
  148. // If there is no upwards exposed use and an entry for the swifterror in
  149. // the def map for this value we don't need to do anything: We already
  150. // have a downward def for this basic block.
  151. if (!UpwardsUse && DownwardDef)
  152. continue;
  153. // Otherwise we either have an upwards exposed use vreg that we need to
  154. // materialize or need to forward the downward def from predecessors.
  155. // Check whether we have a single vreg def from all predecessors.
  156. // Otherwise we need a phi.
  157. SmallVector<std::pair<MachineBasicBlock *, Register>, 4> VRegs;
  158. SmallSet<const MachineBasicBlock *, 8> Visited;
  159. for (auto *Pred : MBB->predecessors()) {
  160. if (!Visited.insert(Pred).second)
  161. continue;
  162. VRegs.push_back(std::make_pair(
  163. Pred, getOrCreateVReg(Pred, SwiftErrorVal)));
  164. if (Pred != MBB)
  165. continue;
  166. // We have a self-edge.
  167. // If there was no upwards use in this basic block there is now one: the
  168. // phi needs to use it self.
  169. if (!UpwardsUse) {
  170. UpwardsUse = true;
  171. UUseIt = VRegUpwardsUse.find(Key);
  172. assert(UUseIt != VRegUpwardsUse.end());
  173. UUseVReg = UUseIt->second;
  174. }
  175. }
  176. // We need a phi node if we have more than one predecessor with different
  177. // downward defs.
  178. bool needPHI =
  179. VRegs.size() >= 1 &&
  180. llvm::find_if(
  181. VRegs,
  182. [&](const std::pair<const MachineBasicBlock *, Register> &V)
  183. -> bool { return V.second != VRegs[0].second; }) !=
  184. VRegs.end();
  185. // If there is no upwards exposed used and we don't need a phi just
  186. // forward the swifterror vreg from the predecessor(s).
  187. if (!UpwardsUse && !needPHI) {
  188. assert(!VRegs.empty() &&
  189. "No predecessors? The entry block should bail out earlier");
  190. // Just forward the swifterror vreg from the predecessor(s).
  191. setCurrentVReg(MBB, SwiftErrorVal, VRegs[0].second);
  192. continue;
  193. }
  194. auto DLoc = isa<Instruction>(SwiftErrorVal)
  195. ? cast<Instruction>(SwiftErrorVal)->getDebugLoc()
  196. : DebugLoc();
  197. const auto *TII = MF->getSubtarget().getInstrInfo();
  198. // If we don't need a phi create a copy to the upward exposed vreg.
  199. if (!needPHI) {
  200. assert(UpwardsUse);
  201. assert(!VRegs.empty() &&
  202. "No predecessors? Is the Calling Convention correct?");
  203. Register DestReg = UUseVReg;
  204. BuildMI(*MBB, MBB->getFirstNonPHI(), DLoc, TII->get(TargetOpcode::COPY),
  205. DestReg)
  206. .addReg(VRegs[0].second);
  207. continue;
  208. }
  209. // We need a phi: if there is an upwards exposed use we already have a
  210. // destination virtual register number otherwise we generate a new one.
  211. auto &DL = MF->getDataLayout();
  212. auto const *RC = TLI->getRegClassFor(TLI->getPointerTy(DL));
  213. Register PHIVReg =
  214. UpwardsUse ? UUseVReg : MF->getRegInfo().createVirtualRegister(RC);
  215. MachineInstrBuilder PHI =
  216. BuildMI(*MBB, MBB->getFirstNonPHI(), DLoc,
  217. TII->get(TargetOpcode::PHI), PHIVReg);
  218. for (auto BBRegPair : VRegs) {
  219. PHI.addReg(BBRegPair.second).addMBB(BBRegPair.first);
  220. }
  221. // We did not have a definition in this block before: store the phi's vreg
  222. // as this block downward exposed def.
  223. if (!UpwardsUse)
  224. setCurrentVReg(MBB, SwiftErrorVal, PHIVReg);
  225. }
  226. }
  227. }
  228. void SwiftErrorValueTracking::preassignVRegs(
  229. MachineBasicBlock *MBB, BasicBlock::const_iterator Begin,
  230. BasicBlock::const_iterator End) {
  231. if (!TLI->supportSwiftError() || SwiftErrorVals.empty())
  232. return;
  233. // Iterator over instructions and assign vregs to swifterror defs and uses.
  234. for (auto It = Begin; It != End; ++It) {
  235. if (auto *CB = dyn_cast<CallBase>(&*It)) {
  236. // A call-site with a swifterror argument is both use and def.
  237. const Value *SwiftErrorAddr = nullptr;
  238. for (auto &Arg : CB->args()) {
  239. if (!Arg->isSwiftError())
  240. continue;
  241. // Use of swifterror.
  242. assert(!SwiftErrorAddr && "Cannot have multiple swifterror arguments");
  243. SwiftErrorAddr = &*Arg;
  244. assert(SwiftErrorAddr->isSwiftError() &&
  245. "Must have a swifterror value argument");
  246. getOrCreateVRegUseAt(&*It, MBB, SwiftErrorAddr);
  247. }
  248. if (!SwiftErrorAddr)
  249. continue;
  250. // Def of swifterror.
  251. getOrCreateVRegDefAt(&*It, MBB, SwiftErrorAddr);
  252. // A load is a use.
  253. } else if (const LoadInst *LI = dyn_cast<const LoadInst>(&*It)) {
  254. const Value *V = LI->getOperand(0);
  255. if (!V->isSwiftError())
  256. continue;
  257. getOrCreateVRegUseAt(LI, MBB, V);
  258. // A store is a def.
  259. } else if (const StoreInst *SI = dyn_cast<const StoreInst>(&*It)) {
  260. const Value *SwiftErrorAddr = SI->getOperand(1);
  261. if (!SwiftErrorAddr->isSwiftError())
  262. continue;
  263. // Def of swifterror.
  264. getOrCreateVRegDefAt(&*It, MBB, SwiftErrorAddr);
  265. // A return in a swiferror returning function is a use.
  266. } else if (const ReturnInst *R = dyn_cast<const ReturnInst>(&*It)) {
  267. const Function *F = R->getParent()->getParent();
  268. if (!F->getAttributes().hasAttrSomewhere(Attribute::SwiftError))
  269. continue;
  270. getOrCreateVRegUseAt(R, MBB, SwiftErrorArg);
  271. }
  272. }
  273. }