LLVM: lib/CodeGen/SwiftErrorValueTracking.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

22

23using namespace llvm;

24

26 const Value *Val) {

27 auto Key = std::make_pair(MBB, Val);

28 auto It = VRegDefMap.find(Key);

29

30

31

32

33 if (It == VRegDefMap.end()) {

34 auto &DL = MF->getDataLayout();

36 auto VReg = MF->getRegInfo().createVirtualRegister(RC);

37 VRegDefMap[Key] = VReg;

38 VRegUpwardsUse[Key] = VReg;

39 return VReg;

40 } else

41 return It->second;

42}

43

46 VRegDefMap[std::make_pair(MBB, Val)] = VReg;

47}

48

52 auto It = VRegDefUses.find(Key);

53 if (It != VRegDefUses.end())

54 return It->second;

55

56 auto &DL = MF->getDataLayout();

58 Register VReg = MF->getRegInfo().createVirtualRegister(RC);

59 VRegDefUses[Key] = VReg;

61 return VReg;

62}

63

67 auto It = VRegDefUses.find(Key);

68 if (It != VRegDefUses.end())

69 return It->second;

70

72 VRegDefUses[Key] = VReg;

73 return VReg;

74}

75

76

77

79 MF = &mf;

81 TLI = MF->getSubtarget().getTargetLowering();

82 TII = MF->getSubtarget().getInstrInfo();

83

84 if (!TLI->supportSwiftError())

85 return;

86

87 SwiftErrorVals.clear();

88 VRegDefMap.clear();

89 VRegUpwardsUse.clear();

90 VRegDefUses.clear();

91 SwiftErrorArg = nullptr;

92

93

94 bool HaveSeenSwiftErrorArg = false;

96 AI != AE; ++AI)

97 if (AI->hasSwiftErrorAttr()) {

98 assert(!HaveSeenSwiftErrorArg &&

99 "Must have only one swifterror parameter");

100 (void)HaveSeenSwiftErrorArg;

101 HaveSeenSwiftErrorArg = true;

102 SwiftErrorArg = &*AI;

103 SwiftErrorVals.push_back(&*AI);

104 }

105

106 for (const auto &LLVMBB : *Fn)

107 for (const auto &Inst : LLVMBB) {

109 if (Alloca->isSwiftError())

110 SwiftErrorVals.push_back(Alloca);

111 }

112}

113

115 if (!TLI->supportSwiftError())

116 return false;

117

118

119

120 if (SwiftErrorVals.empty())

121 return false;

122

124 auto &DL = MF->getDataLayout();

125 auto const *RC = TLI->getRegClassFor(TLI->getPointerTy(DL));

126 bool Inserted = false;

127 for (const auto *SwiftErrorVal : SwiftErrorVals) {

128

129

130 if (SwiftErrorArg && SwiftErrorArg == SwiftErrorVal)

131 continue;

132 Register VReg = MF->getRegInfo().createVirtualRegister(RC);

133

134

136 TII->get(TargetOpcode::IMPLICIT_DEF), VReg);

137

139 Inserted = true;

140 }

141

142 return Inserted;

143}

144

145

147 if (!TLI->supportSwiftError())

148 return;

149

150

151

152 if (SwiftErrorVals.empty())

153 return;

154

155

158

159 for (const auto *SwiftErrorVal : SwiftErrorVals) {

160 auto Key = std::make_pair(MBB, SwiftErrorVal);

161 auto UUseIt = VRegUpwardsUse.find(Key);

162 auto VRegDefIt = VRegDefMap.find(Key);

163 bool UpwardsUse = UUseIt != VRegUpwardsUse.end();

164 Register UUseVReg = UpwardsUse ? UUseIt->second : Register();

165 bool DownwardDef = VRegDefIt != VRegDefMap.end();

166 assert(!(UpwardsUse && !DownwardDef) &&

167 "We can't have an upwards use but no downwards def");

168

169

170

171

172 if (!UpwardsUse && DownwardDef)

173 continue;

174

175

176

177

178

179

182 for (auto *Pred : MBB->predecessors()) {

183 if (!Visited.insert(Pred).second)

184 continue;

187 if (Pred != MBB)

188 continue;

189

190

191

192 if (!UpwardsUse) {

193 UpwardsUse = true;

194 UUseIt = VRegUpwardsUse.find(Key);

195 assert(UUseIt != VRegUpwardsUse.end());

196 UUseVReg = UUseIt->second;

197 }

198 }

199

200

201

202 bool needPHI =

203 VRegs.size() >= 1 &&

205 VRegs,

206 [&](const std::pair<const MachineBasicBlock *, Register> &V)

207 -> bool { return V.second != VRegs[0].second; });

208

209

210

211 if (!UpwardsUse && !needPHI) {

213 "No predecessors? The entry block should bail out earlier");

214

216 continue;

217 }

218

222 const auto *TII = MF->getSubtarget().getInstrInfo();

223

224

225 if (!needPHI) {

228 "No predecessors? Is the Calling Convention correct?");

230 BuildMI(*MBB, MBB->getFirstNonPHI(), DLoc, TII->get(TargetOpcode::COPY),

231 DestReg)

232 .addReg(VRegs[0].second);

233 continue;

234 }

235

236

237

238 auto &DL = MF->getDataLayout();

239 auto const *RC = TLI->getRegClassFor(TLI->getPointerTy(DL));

241 UpwardsUse ? UUseVReg : MF->getRegInfo().createVirtualRegister(RC);

244 TII->get(TargetOpcode::PHI), PHIVReg);

245 for (auto BBRegPair : VRegs) {

246 PHI.addReg(BBRegPair.second).addMBB(BBRegPair.first);

247 }

248

249

250

251 if (!UpwardsUse)

253 }

254 }

255

256

258 for (const auto &Use : VRegUpwardsUse) {

261 if (MRI.def_empty(VReg))

262 continue;

263

264#ifdef EXPENSIVE_CHECKS

265 assert(std::find(RPOT.begin(), RPOT.end(), UseBB) == RPOT.end() &&

266 "Reachable block has VReg upward use without definition.");

267#endif

268

270

272 TII->get(TargetOpcode::IMPLICIT_DEF), VReg);

273 }

274}

275

279 if (!TLI->supportSwiftError() || SwiftErrorVals.empty())

280 return;

281

282

283 for (auto It = Begin; It != End; ++It) {

285

286 const Value *SwiftErrorAddr = nullptr;

287 for (const auto &Arg : CB->args()) {

288 if (!Arg->isSwiftError())

289 continue;

290

291 assert(!SwiftErrorAddr && "Cannot have multiple swifterror arguments");

292 SwiftErrorAddr = &*Arg;

294 "Must have a swifterror value argument");

296 }

297 if (!SwiftErrorAddr)

298 continue;

299

300

302

303

305 const Value *V = LI->getOperand(0);

306 if (!V->isSwiftError())

307 continue;

308

310

311

313 const Value *SwiftErrorAddr = SI->getOperand(1);

315 continue;

316

317

319

320

322 const Function *F = R->getParent()->getParent();

323 if (F->getAttributes().hasAttrSomewhere(Attribute::SwiftError))

324 continue;

325

327 }

328 }

329}

unsigned const MachineRegisterInfo * MRI

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

Promote Memory to Register

This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.

This file describes how to lower LLVM code to machine code.

an instruction to allocate memory on the stack

InstListType::const_iterator const_iterator

const Argument * const_arg_iterator

An instruction for reading from memory.

static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)

int getNumber() const

MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...

LLVM_ABI iterator getFirstNonPHI()

Returns a pointer to the first instruction in this block that is not a PHINode instruction.

Function & getFunction()

Return the LLVM function that this machine code represents.

const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const

Add a new virtual register operand.

MachineRegisterInfo - Keep track of information for virtual and physical registers,...

PointerIntPair - This class implements a pair of a pointer and small integer.

Wrapper class representing virtual and physical registers.

Return a value (possibly void), from a function.

std::pair< iterator, bool > insert(PtrType Ptr)

Inserts Ptr if and only if there is no element in the container equal to Ptr.

SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

An instruction for storing to memory.

bool createEntriesInEntryBlock(DebugLoc DbgLoc)

Create initial definitions of swifterror values in the entry block of the current function.

Definition SwiftErrorValueTracking.cpp:114

void setFunction(MachineFunction &MF)

Initialize data structures for specified new function.

Definition SwiftErrorValueTracking.cpp:78

Register getOrCreateVReg(const MachineBasicBlock *, const Value *)

Get or create the swifterror value virtual register in VRegDefMap for this basic block.

Definition SwiftErrorValueTracking.cpp:25

void setCurrentVReg(const MachineBasicBlock *MBB, const Value *, Register)

Set the swifterror virtual register in the VRegDefMap for this basic block.

Definition SwiftErrorValueTracking.cpp:44

Register getOrCreateVRegUseAt(const Instruction *, const MachineBasicBlock *, const Value *)

Get or create the swifterror value virtual register for a use of a swifterror by an instruction.

Definition SwiftErrorValueTracking.cpp:64

void preassignVRegs(MachineBasicBlock *MBB, BasicBlock::const_iterator Begin, BasicBlock::const_iterator End)

Definition SwiftErrorValueTracking.cpp:276

Register getOrCreateVRegDefAt(const Instruction *, const MachineBasicBlock *, const Value *)

Get or create the swifterror value virtual register for a def of a swifterror by an instruction.

Definition SwiftErrorValueTracking.cpp:49

void propagateVRegs()

Propagate assigned swifterror vregs through a function, synthesizing PHI nodes when needed to maintai...

Definition SwiftErrorValueTracking.cpp:146

A Use represents the edge between a Value definition and its users.

LLVM Value Representation.

LLVM_ABI bool isSwiftError() const

Return true if this value is a swifterror value.

This is an optimization pass for GlobalISel generic memory operations.

MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)

Builder interface. Specify how to create the initial instruction itself.

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

bool any_of(R &&range, UnaryPredicate P)

Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.

bool isa(const From &Val)

isa - Return true if the parameter to the template is an instance of one of the template type argu...

LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key

decltype(auto) cast(const From &Val)

cast - Return the argument parameter cast to the specified type.