1//===-- SwiftErrorValueTracking.cpp --------------------------------------===// 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 7//===----------------------------------------------------------------------===// 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. 13//===----------------------------------------------------------------------===// 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()) {
38 VRegDefMap[Key] = VReg;
39 VRegUpwardsUse[Key] = VReg;
47 VRegDefMap[std::make_pair(
MBB, Val)] = VReg;
53auto It = VRegDefUses.find(Key);
54if (It != VRegDefUses.end())
60 VRegDefUses[Key] = VReg;
68auto It = VRegDefUses.find(Key);
69if (It != VRegDefUses.end())
73 VRegDefUses[Key] = VReg;
77/// Set up SwiftErrorVals by going through the function. If the function has 78/// swifterror argument, it will be the first entry. 88 SwiftErrorVals.
clear();
90 VRegUpwardsUse.clear();
92 SwiftErrorArg =
nullptr;
94// Check if function has a swifterror argument. 95bool HaveSeenSwiftErrorArg =
false;
98if (AI->hasSwiftErrorAttr()) {
99assert(!HaveSeenSwiftErrorArg &&
100"Must have only one swifterror parameter");
101 (void)HaveSeenSwiftErrorArg;
// silence warning. 102 HaveSeenSwiftErrorArg =
true;
103 SwiftErrorArg = &*AI;
107for (
constauto &LLVMBB : *Fn)
108for (
constauto &Inst : LLVMBB) {
109if (
constAllocaInst *Alloca = dyn_cast<AllocaInst>(&Inst))
110if (Alloca->isSwiftError())
119// We only need to do this when we have swifterror parameter or swifterror 121if (SwiftErrorVals.
empty())
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)
134// Assign Undef to Vreg. We construct MI directly to make sure it works 137 TII->
get(TargetOpcode::IMPLICIT_DEF), VReg);
146/// Propagate swifterror values through the machine function CFG. 151// We only need to do this when we have swifterror parameter or swifterror 153if (SwiftErrorVals.
empty())
156// For each machine basic block in reverse post order. 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();
166bool DownwardDef = VRegDefIt != VRegDefMap.end();
167assert(!(UpwardsUse && !DownwardDef) &&
168"We can't have an upwards use but no downwards def");
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)
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. 179// Check whether we have a single vreg def from all predecessors. 180// Otherwise we need a phi. 184if (!Visited.
insert(Pred).second)
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. 195 UUseIt = VRegUpwardsUse.find(Key);
196assert(UUseIt != VRegUpwardsUse.end());
197 UUseVReg = UUseIt->second;
201// We need a phi node if we have more than one predecessor with different 207 [&](
const std::pair<const MachineBasicBlock *, Register> &V)
208 ->
bool {
return V.second != VRegs[0].second; });
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) {
214"No predecessors? The entry block should bail out earlier");
215// Just forward the swifterror vreg from the predecessor(s). 220auto DLoc = isa<Instruction>(SwiftErrorVal)
221 ? cast<Instruction>(SwiftErrorVal)->getDebugLoc()
225// If we don't need a phi create a copy to the upward exposed vreg. 229"No predecessors? Is the Calling Convention correct?");
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. 245 TII->
get(TargetOpcode::PHI), PHIVReg);
246for (
auto BBRegPair : VRegs) {
247PHI.addReg(BBRegPair.second).addMBB(BBRegPair.first);
250// We did not have a definition in this block before: store the phi's vreg 251// as this block downward exposed def. 257// Create implicit defs for upward uses from unreachable blocks 259for (
constauto &
Use : VRegUpwardsUse) {
262if (!
MRI.def_empty(VReg))
265#ifdef EXPENSIVE_CHECKS 267"Reachable block has VReg upward use without definition.");
273 TII->
get(TargetOpcode::IMPLICIT_DEF), VReg);
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())
292assert(!SwiftErrorAddr &&
"Cannot have multiple swifterror arguments");
293 SwiftErrorAddr = &*Arg;
295"Must have a swifterror value argument");
305 }
elseif (
constLoadInst *LI = dyn_cast<const LoadInst>(&*It)) {
306constValue *V = LI->getOperand(0);
307if (!V->isSwiftError())
313 }
elseif (
constStoreInst *SI = dyn_cast<const StoreInst>(&*It)) {
314constValue *SwiftErrorAddr = SI->getOperand(1);
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))
unsigned const MachineRegisterInfo * MRI
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallSet class.
This file describes how to lower LLVM code to machine code.
an instruction to allocate memory on the stack
This class represents an incoming formal argument to a Function.
InstListType::const_iterator const_iterator
An instruction for reading from memory.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
iterator getFirstNonPHI()
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
iterator_range< pred_iterator > predecessors()
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
MachineBasicBlock * getBlockNumbered(unsigned N) const
getBlockNumbered - MachineBasicBlocks are automatically numbered when they are inserted into the mach...
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
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,...
Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
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.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
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.
void setFunction(MachineFunction &MF)
Initialize data structures for specified new function.
Register getOrCreateVReg(const MachineBasicBlock *, const Value *)
Get or create the swifterror value virtual register in VRegDefMap for this basic block.
void setCurrentVReg(const MachineBasicBlock *MBB, const Value *, Register)
Set the swifterror virtual register in the VRegDefMap for this basic block.
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.
void preassignVRegs(MachineBasicBlock *MBB, BasicBlock::const_iterator Begin, BasicBlock::const_iterator End)
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.
void propagateVRegs()
Propagate assigned swifterror vregs through a function, synthesizing PHI nodes when needed to maintai...
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
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...
virtual bool supportSwiftError() const
Return true if the target supports swifterror attribute.
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetLowering * getTargetLowering() const
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
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.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.