Movatterモバイル変換


[0]ホーム

URL:


LLVM 20.0.0git
SwiftErrorValueTracking.cpp
Go to the documentation of this file.
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
15#include "llvm/CodeGen/SwiftErrorValueTracking.h"
16#include "llvm/ADT/PostOrderIterator.h"
17#include "llvm/ADT/SmallSet.h"
18#include "llvm/CodeGen/MachineInstrBuilder.h"
19#include "llvm/CodeGen/MachineRegisterInfo.h"
20#include "llvm/CodeGen/TargetInstrInfo.h"
21#include "llvm/CodeGen/TargetLowering.h"
22#include "llvm/IR/Value.h"
23
24using namespacellvm;
25
26RegisterSwiftErrorValueTracking::getOrCreateVReg(constMachineBasicBlock *MBB,
27constValue *Val) {
28auto Key = std::make_pair(MBB, Val);
29auto It = VRegDefMap.find(Key);
30// If this is the first use of this swifterror value in this basic block,
31// create a new virtual register.
32// After we processed all basic blocks we will satisfy this "upwards exposed
33// use" by inserting a copy or phi at the beginning of this block.
34if (It == VRegDefMap.end()) {
35auto &DL = MF->getDataLayout();
36constTargetRegisterClass *RC = TLI->getRegClassFor(TLI->getPointerTy(DL));
37auto VReg = MF->getRegInfo().createVirtualRegister(RC);
38 VRegDefMap[Key] = VReg;
39 VRegUpwardsUse[Key] = VReg;
40return VReg;
41 }else
42return It->second;
43}
44
45voidSwiftErrorValueTracking::setCurrentVReg(constMachineBasicBlock *MBB,
46constValue *Val,Register VReg) {
47 VRegDefMap[std::make_pair(MBB, Val)] = VReg;
48}
49
50RegisterSwiftErrorValueTracking::getOrCreateVRegDefAt(
51constInstruction *I,constMachineBasicBlock *MBB,constValue *Val) {
52auto Key =PointerIntPair<const Instruction *, 1, bool>(I,true);
53auto It = VRegDefUses.find(Key);
54if (It != VRegDefUses.end())
55return It->second;
56
57auto &DL = MF->getDataLayout();
58constTargetRegisterClass *RC = TLI->getRegClassFor(TLI->getPointerTy(DL));
59Register VReg = MF->getRegInfo().createVirtualRegister(RC);
60 VRegDefUses[Key] = VReg;
61setCurrentVReg(MBB, Val, VReg);
62return VReg;
63}
64
65RegisterSwiftErrorValueTracking::getOrCreateVRegUseAt(
66constInstruction *I,constMachineBasicBlock *MBB,constValue *Val) {
67auto Key =PointerIntPair<const Instruction *, 1, bool>(I,false);
68auto It = VRegDefUses.find(Key);
69if (It != VRegDefUses.end())
70return It->second;
71
72Register VReg =getOrCreateVReg(MBB, Val);
73 VRegDefUses[Key] = VReg;
74return VReg;
75}
76
77/// Set up SwiftErrorVals by going through the function. If the function has
78/// swifterror argument, it will be the first entry.
79voidSwiftErrorValueTracking::setFunction(MachineFunction &mf) {
80 MF = &mf;
81 Fn = &MF->getFunction();
82 TLI = MF->getSubtarget().getTargetLowering();
83 TII = MF->getSubtarget().getInstrInfo();
84
85if (!TLI->supportSwiftError())
86return;
87
88 SwiftErrorVals.clear();
89 VRegDefMap.clear();
90 VRegUpwardsUse.clear();
91 VRegDefUses.clear();
92 SwiftErrorArg =nullptr;
93
94// Check if function has a swifterror argument.
95bool HaveSeenSwiftErrorArg =false;
96for (Function::const_arg_iterator AI = Fn->arg_begin(), AE = Fn->arg_end();
97 AI != AE; ++AI)
98if (AI->hasSwiftErrorAttr()) {
99assert(!HaveSeenSwiftErrorArg &&
100"Must have only one swifterror parameter");
101 (void)HaveSeenSwiftErrorArg;// silence warning.
102 HaveSeenSwiftErrorArg =true;
103 SwiftErrorArg = &*AI;
104 SwiftErrorVals.push_back(&*AI);
105 }
106
107for (constauto &LLVMBB : *Fn)
108for (constauto &Inst : LLVMBB) {
109if (constAllocaInst *Alloca = dyn_cast<AllocaInst>(&Inst))
110if (Alloca->isSwiftError())
111 SwiftErrorVals.push_back(Alloca);
112 }
113}
114
115boolSwiftErrorValueTracking::createEntriesInEntryBlock(DebugLoc DbgLoc) {
116if (!TLI->supportSwiftError())
117returnfalse;
118
119// We only need to do this when we have swifterror parameter or swifterror
120// alloc.
121if (SwiftErrorVals.empty())
122returnfalse;
123
124MachineBasicBlock *MBB = &*MF->begin();
125auto &DL = MF->getDataLayout();
126autoconst *RC = TLI->getRegClassFor(TLI->getPointerTy(DL));
127bool Inserted =false;
128for (constauto *SwiftErrorVal : SwiftErrorVals) {
129// We will always generate a copy from the argument. It is always used at
130// least by the 'return' of the swifterror.
131if (SwiftErrorArg && SwiftErrorArg == SwiftErrorVal)
132continue;
133Register VReg = MF->getRegInfo().createVirtualRegister(RC);
134// Assign Undef to Vreg. We construct MI directly to make sure it works
135// with FastISel.
136BuildMI(*MBB,MBB->getFirstNonPHI(), DbgLoc,
137 TII->get(TargetOpcode::IMPLICIT_DEF), VReg);
138
139setCurrentVReg(MBB, SwiftErrorVal, VReg);
140 Inserted =true;
141 }
142
143return Inserted;
144}
145
146/// Propagate swifterror values through the machine function CFG.
147voidSwiftErrorValueTracking::propagateVRegs() {
148if (!TLI->supportSwiftError())
149return;
150
151// We only need to do this when we have swifterror parameter or swifterror
152// alloc.
153if (SwiftErrorVals.empty())
154return;
155
156// For each machine basic block in reverse post order.
157ReversePostOrderTraversal<MachineFunction *> RPOT(MF);
158for (MachineBasicBlock *MBB : RPOT) {
159// For each swifterror value in the function.
160for (constauto *SwiftErrorVal : SwiftErrorVals) {
161auto Key = std::make_pair(MBB, SwiftErrorVal);
162auto UUseIt = VRegUpwardsUse.find(Key);
163auto VRegDefIt = VRegDefMap.find(Key);
164bool UpwardsUse = UUseIt != VRegUpwardsUse.end();
165Register UUseVReg = UpwardsUse ? UUseIt->second :Register();
166bool DownwardDef = VRegDefIt != VRegDefMap.end();
167assert(!(UpwardsUse && !DownwardDef) &&
168"We can't have an upwards use but no downwards def");
169
170// If there is no upwards exposed use and an entry for the swifterror in
171// the def map for this value we don't need to do anything: We already
172// have a downward def for this basic block.
173if (!UpwardsUse && DownwardDef)
174continue;
175
176// Otherwise we either have an upwards exposed use vreg that we need to
177// materialize or need to forward the downward def from predecessors.
178
179// Check whether we have a single vreg def from all predecessors.
180// Otherwise we need a phi.
181SmallVector<std::pair<MachineBasicBlock *, Register>, 4> VRegs;
182SmallSet<const MachineBasicBlock *, 8> Visited;
183for (auto *Pred :MBB->predecessors()) {
184if (!Visited.insert(Pred).second)
185continue;
186 VRegs.push_back(std::make_pair(
187 Pred,getOrCreateVReg(Pred, SwiftErrorVal)));
188if (Pred !=MBB)
189continue;
190// We have a self-edge.
191// If there was no upwards use in this basic block there is now one: the
192// phi needs to use it self.
193if (!UpwardsUse) {
194 UpwardsUse =true;
195 UUseIt = VRegUpwardsUse.find(Key);
196assert(UUseIt != VRegUpwardsUse.end());
197 UUseVReg = UUseIt->second;
198 }
199 }
200
201// We need a phi node if we have more than one predecessor with different
202// downward defs.
203bool needPHI =
204 VRegs.size() >= 1 &&
205llvm::any_of(
206 VRegs,
207 [&](const std::pair<const MachineBasicBlock *, Register> &V)
208 ->bool {return V.second != VRegs[0].second; });
209
210// If there is no upwards exposed used and we don't need a phi just
211// forward the swifterror vreg from the predecessor(s).
212if (!UpwardsUse && !needPHI) {
213assert(!VRegs.empty() &&
214"No predecessors? The entry block should bail out earlier");
215// Just forward the swifterror vreg from the predecessor(s).
216setCurrentVReg(MBB, SwiftErrorVal, VRegs[0].second);
217continue;
218 }
219
220auto DLoc = isa<Instruction>(SwiftErrorVal)
221 ? cast<Instruction>(SwiftErrorVal)->getDebugLoc()
222 :DebugLoc();
223constauto *TII = MF->getSubtarget().getInstrInfo();
224
225// If we don't need a phi create a copy to the upward exposed vreg.
226if (!needPHI) {
227assert(UpwardsUse);
228assert(!VRegs.empty() &&
229"No predecessors? Is the Calling Convention correct?");
230Register DestReg = UUseVReg;
231BuildMI(*MBB,MBB->getFirstNonPHI(), DLoc, TII->get(TargetOpcode::COPY),
232 DestReg)
233 .addReg(VRegs[0].second);
234continue;
235 }
236
237// We need a phi: if there is an upwards exposed use we already have a
238// destination virtual register number otherwise we generate a new one.
239auto &DL = MF->getDataLayout();
240autoconst *RC = TLI->getRegClassFor(TLI->getPointerTy(DL));
241Register PHIVReg =
242 UpwardsUse ? UUseVReg : MF->getRegInfo().createVirtualRegister(RC);
243MachineInstrBuilderPHI =
244BuildMI(*MBB,MBB->getFirstNonPHI(), DLoc,
245 TII->get(TargetOpcode::PHI), PHIVReg);
246for (auto BBRegPair : VRegs) {
247PHI.addReg(BBRegPair.second).addMBB(BBRegPair.first);
248 }
249
250// We did not have a definition in this block before: store the phi's vreg
251// as this block downward exposed def.
252if (!UpwardsUse)
253setCurrentVReg(MBB, SwiftErrorVal, PHIVReg);
254 }
255 }
256
257// Create implicit defs for upward uses from unreachable blocks
258MachineRegisterInfo &MRI = MF->getRegInfo();
259for (constauto &Use : VRegUpwardsUse) {
260constMachineBasicBlock *UseBB =Use.first.first;
261Register VReg =Use.second;
262if (!MRI.def_empty(VReg))
263continue;
264
265#ifdef EXPENSIVE_CHECKS
266assert(std::find(RPOT.begin(), RPOT.end(), UseBB) == RPOT.end() &&
267"Reachable block has VReg upward use without definition.");
268#endif
269
270MachineBasicBlock *UseBBMut = MF->getBlockNumbered(UseBB->getNumber());
271
272BuildMI(*UseBBMut, UseBBMut->getFirstNonPHI(),DebugLoc(),
273 TII->get(TargetOpcode::IMPLICIT_DEF), VReg);
274 }
275}
276
277voidSwiftErrorValueTracking::preassignVRegs(
278MachineBasicBlock *MBB,BasicBlock::const_iterator Begin,
279BasicBlock::const_iteratorEnd) {
280if (!TLI->supportSwiftError() || SwiftErrorVals.empty())
281return;
282
283// Iterator over instructions and assign vregs to swifterror defs and uses.
284for (auto It = Begin; It !=End; ++It) {
285if (auto *CB = dyn_cast<CallBase>(&*It)) {
286// A call-site with a swifterror argument is both use and def.
287constValue *SwiftErrorAddr =nullptr;
288for (constauto &Arg : CB->args()) {
289if (!Arg->isSwiftError())
290continue;
291// Use of swifterror.
292assert(!SwiftErrorAddr &&"Cannot have multiple swifterror arguments");
293 SwiftErrorAddr = &*Arg;
294assert(SwiftErrorAddr->isSwiftError() &&
295"Must have a swifterror value argument");
296getOrCreateVRegUseAt(&*It,MBB, SwiftErrorAddr);
297 }
298if (!SwiftErrorAddr)
299continue;
300
301// Def of swifterror.
302getOrCreateVRegDefAt(&*It,MBB, SwiftErrorAddr);
303
304// A load is a use.
305 }elseif (constLoadInst *LI = dyn_cast<const LoadInst>(&*It)) {
306constValue *V = LI->getOperand(0);
307if (!V->isSwiftError())
308continue;
309
310getOrCreateVRegUseAt(LI,MBB, V);
311
312// A store is a def.
313 }elseif (constStoreInst *SI = dyn_cast<const StoreInst>(&*It)) {
314constValue *SwiftErrorAddr = SI->getOperand(1);
315if (!SwiftErrorAddr->isSwiftError())
316continue;
317
318// Def of swifterror.
319getOrCreateVRegDefAt(&*It,MBB, SwiftErrorAddr);
320
321// A return in a swiferror returning function is a use.
322 }elseif (constReturnInst *R = dyn_cast<const ReturnInst>(&*It)) {
323constFunction *F = R->getParent()->getParent();
324if (!F->getAttributes().hasAttrSomewhere(Attribute::SwiftError))
325continue;
326
327getOrCreateVRegUseAt(R,MBB, SwiftErrorArg);
328 }
329 }
330}
MRI
unsigned const MachineRegisterInfo * MRI
Definition:AArch64AdvSIMDScalarPass.cpp:105
PHI
Rewrite undef for PHI
Definition:AMDGPURewriteUndefForPHI.cpp:100
MBB
MachineBasicBlock & MBB
Definition:ARMSLSHardening.cpp:71
DL
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Definition:ARMSLSHardening.cpp:73
End
bool End
Definition:ELF_riscv.cpp:480
Value.h
F
#define F(x, y, z)
Definition:MD5.cpp:55
I
#define I(x, y, z)
Definition:MD5.cpp:58
MachineInstrBuilder.h
MachineRegisterInfo.h
PostOrderIterator.h
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
SmallSet.h
This file defines the SmallSet class.
SwiftErrorValueTracking.h
TargetInstrInfo.h
TargetLowering.h
This file describes how to lower LLVM code to machine code.
llvm::AllocaInst
an instruction to allocate memory on the stack
Definition:Instructions.h:63
llvm::Argument
This class represents an incoming formal argument to a Function.
Definition:Argument.h:31
llvm::BasicBlock::const_iterator
InstListType::const_iterator const_iterator
Definition:BasicBlock.h:178
llvm::DebugLoc
A debug info location.
Definition:DebugLoc.h:33
llvm::Function
Definition:Function.h:63
llvm::Function::arg_end
arg_iterator arg_end()
Definition:Function.h:877
llvm::Function::arg_begin
arg_iterator arg_begin()
Definition:Function.h:868
llvm::Instruction
Definition:Instruction.h:68
llvm::LoadInst
An instruction for reading from memory.
Definition:Instructions.h:176
llvm::MCInstrInfo::get
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Definition:MCInstrInfo.h:63
llvm::MachineBasicBlock
Definition:MachineBasicBlock.h:125
llvm::MachineBasicBlock::getNumber
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
Definition:MachineBasicBlock.h:1217
llvm::MachineBasicBlock::getFirstNonPHI
iterator getFirstNonPHI()
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
Definition:MachineBasicBlock.cpp:202
llvm::MachineBasicBlock::predecessors
iterator_range< pred_iterator > predecessors()
Definition:MachineBasicBlock.h:438
llvm::MachineFunction
Definition:MachineFunction.h:267
llvm::MachineFunction::getSubtarget
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Definition:MachineFunction.h:733
llvm::MachineFunction::getRegInfo
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Definition:MachineFunction.h:743
llvm::MachineFunction::getBlockNumbered
MachineBasicBlock * getBlockNumbered(unsigned N) const
getBlockNumbered - MachineBasicBlocks are automatically numbered when they are inserted into the mach...
Definition:MachineFunction.h:866
llvm::MachineFunction::getDataLayout
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Definition:MachineFunction.cpp:309
llvm::MachineFunction::getFunction
Function & getFunction()
Return the LLVM function that this machine code represents.
Definition:MachineFunction.h:704
llvm::MachineFunction::begin
iterator begin()
Definition:MachineFunction.h:947
llvm::MachineInstrBuilder
Definition:MachineInstrBuilder.h:71
llvm::MachineInstrBuilder::addReg
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Definition:MachineInstrBuilder.h:99
llvm::MachineRegisterInfo
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Definition:MachineRegisterInfo.h:51
llvm::MachineRegisterInfo::createVirtualRegister
Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
Definition:MachineRegisterInfo.cpp:156
llvm::PointerIntPair
PointerIntPair - This class implements a pair of a pointer and small integer.
Definition:PointerIntPair.h:80
llvm::Register
Wrapper class representing virtual and physical registers.
Definition:Register.h:19
llvm::ReturnInst
Return a value (possibly void), from a function.
Definition:Instructions.h:2938
llvm::ReversePostOrderTraversal
Definition:PostOrderIterator.h:299
llvm::ReversePostOrderTraversal::begin
rpo_iterator begin()
Definition:PostOrderIterator.h:316
llvm::ReversePostOrderTraversal::end
rpo_iterator end()
Definition:PostOrderIterator.h:318
llvm::SmallSet
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition:SmallSet.h:132
llvm::SmallSet::insert
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Definition:SmallSet.h:181
llvm::SmallVectorBase::empty
bool empty() const
Definition:SmallVector.h:81
llvm::SmallVectorBase::size
size_t size() const
Definition:SmallVector.h:78
llvm::SmallVectorImpl::clear
void clear()
Definition:SmallVector.h:610
llvm::SmallVectorTemplateBase::push_back
void push_back(const T &Elt)
Definition:SmallVector.h:413
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition:SmallVector.h:1196
llvm::StoreInst
An instruction for storing to memory.
Definition:Instructions.h:292
llvm::SwiftErrorValueTracking::createEntriesInEntryBlock
bool createEntriesInEntryBlock(DebugLoc DbgLoc)
Create initial definitions of swifterror values in the entry block of the current function.
Definition:SwiftErrorValueTracking.cpp:115
llvm::SwiftErrorValueTracking::setFunction
void setFunction(MachineFunction &MF)
Initialize data structures for specified new function.
Definition:SwiftErrorValueTracking.cpp:79
llvm::SwiftErrorValueTracking::getOrCreateVReg
Register getOrCreateVReg(const MachineBasicBlock *, const Value *)
Get or create the swifterror value virtual register in VRegDefMap for this basic block.
Definition:SwiftErrorValueTracking.cpp:26
llvm::SwiftErrorValueTracking::setCurrentVReg
void setCurrentVReg(const MachineBasicBlock *MBB, const Value *, Register)
Set the swifterror virtual register in the VRegDefMap for this basic block.
Definition:SwiftErrorValueTracking.cpp:45
llvm::SwiftErrorValueTracking::getOrCreateVRegUseAt
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:65
llvm::SwiftErrorValueTracking::preassignVRegs
void preassignVRegs(MachineBasicBlock *MBB, BasicBlock::const_iterator Begin, BasicBlock::const_iterator End)
Definition:SwiftErrorValueTracking.cpp:277
llvm::SwiftErrorValueTracking::getOrCreateVRegDefAt
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:50
llvm::SwiftErrorValueTracking::propagateVRegs
void propagateVRegs()
Propagate assigned swifterror vregs through a function, synthesizing PHI nodes when needed to maintai...
Definition:SwiftErrorValueTracking.cpp:147
llvm::TargetLoweringBase::getRegClassFor
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
Definition:TargetLowering.h:1042
llvm::TargetLoweringBase::getPointerTy
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
Definition:TargetLowering.h:371
llvm::TargetLowering::supportSwiftError
virtual bool supportSwiftError() const
Return true if the target supports swifterror attribute.
Definition:TargetLowering.h:4390
llvm::TargetRegisterClass
Definition:TargetRegisterInfo.h:44
llvm::TargetSubtargetInfo::getInstrInfo
virtual const TargetInstrInfo * getInstrInfo() const
Definition:TargetSubtargetInfo.h:97
llvm::TargetSubtargetInfo::getTargetLowering
virtual const TargetLowering * getTargetLowering() const
Definition:TargetSubtargetInfo.h:101
llvm::Use
A Use represents the edge between a Value definition and its users.
Definition:Use.h:43
llvm::Value
LLVM Value Representation.
Definition:Value.h:74
llvm::Value::isSwiftError
bool isSwiftError() const
Return true if this value is a swifterror value.
Definition:Value.cpp:1096
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition:AddressRanges.h:18
llvm::BuildMI
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
Definition:MachineInstrBuilder.h:373
llvm::any_of
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition:STLExtras.h:1746

Generated on Fri Jul 18 2025 11:03:30 for LLVM by doxygen 1.9.6
[8]ページ先頭

©2009-2025 Movatter.jp