----------------------------
LLVM uses several intrinsic functions (name prefixed with "``llvm.dbg``") to
-track source local variables through optimization and code generation.
+provide debug information at various points in generated code.
-``llvm.dbg.addr``
+``llvm.dbg.declare``
^^^^^^^^^^^^^^^^^^^^
.. code-block:: llvm
- void @llvm.dbg.addr(metadata, metadata, metadata)
+ void @llvm.dbg.declare(metadata, metadata, metadata)
-This intrinsic provides information about a local element (e.g., variable).
-The first argument is metadata holding the address of variable, typically a
-static alloca in the function entry block. The second argument is a
-`local variable <LangRef.html#dilocalvariable>`_ containing a description of
-the variable. The third argument is a `complex expression
-<LangRef.html#diexpression>`_. An `llvm.dbg.addr` intrinsic describes the
-*address* of a source variable.
+This intrinsic provides information about a local element (e.g., variable). The
+first argument is metadata holding the alloca for the variable. The second
+argument is a `local variable <LangRef.html#dilocalvariable>`_ containing a
+description of the variable. The third argument is a `complex expression
+<LangRef.html#diexpression>`_. An `llvm.dbg.declare` instrinsic describes the
+*location* of a source variable.
.. code-block:: llvm
%i.addr = alloca i32, align 4
- call void @llvm.dbg.addr(metadata i32* %i.addr, metadata !1,
- metadata !DIExpression()), !dbg !2
+ call void @llvm.dbg.declare(metadata i32* %i.addr, metadata !1, metadata !2), !dbg !3
!1 = !DILocalVariable(name: "i", ...) ; int i
- !2 = !DILocation(...)
+ !2 = !DIExpression()
+ !3 = !DILocation(...)
...
%buffer = alloca [256 x i8], align 8
; The address of i is buffer+64.
- call void @llvm.dbg.addr(metadata [256 x i8]* %buffer, metadata !3,
- metadata !DIExpression(DW_OP_plus, 64)), !dbg !4
- !3 = !DILocalVariable(name: "i", ...) ; int i
- !4 = !DILocation(...)
-
-A frontend should generate exactly one call to ``llvm.dbg.addr`` at the point
-of declaration of a source variable. Optimization passes that fully promote the
-variable from memory to SSA values will replace this call with possibly
-multiple calls to `llvm.dbg.value`. Passes that delete stores are effectively
-partial promotion, and they will insert a mix of calls to ``llvm.dbg.value``
-and ``llvm.dbg.addr`` to track the source variable value when it is available.
-After optimization, there may be multiple calls to ``llvm.dbg.addr`` describing
-the program points where the variables lives in memory. All calls for the same
-concrete source variable must agree on the memory location.
-
-
-``llvm.dbg.declare``
-^^^^^^^^^^^^^^^^^^^^
-
-.. code-block:: llvm
-
- void @llvm.dbg.declare(metadata, metadata, metadata)
-
-This intrinsic is identical to `llvm.dbg.addr`, except that there can only be
-one call to `llvm.dbg.declare` for a given concrete `local variable
-<LangRef.html#dilocalvariable>`_. It is not control-dependent, meaning that if
-a call to `llvm.dbg.declare` exists and has a valid location argument, that
-address is considered to be the true home of the variable across its entire
-lifetime. This makes it hard for optimizations to preserve accurate debug info
-in the presence of ``llvm.dbg.declare``, so we are transitioning away from it,
-and we plan to deprecate it in future LLVM releases.
+ call void @llvm.dbg.declare(metadata [256 x i8]* %buffer, metadata !1, metadata !2)
+ !1 = !DILocalVariable(name: "i", ...) ; int i
+ !2 = !DIExpression(DW_OP_plus, 64)
``llvm.dbg.value``
8. X = Y;
9. }
-.. FIXME: Update the following example to use llvm.dbg.addr once that is the
- default in clang.
-
Compiled to LLVM, this function would be represented like this:
.. code-block:: text
/// variable's value or its address.
Value *getVariableLocation(bool AllowNullOp = true) const;
- /// Does this describe the address of a local variable. True for dbg.addr
- /// and dbg.declare, but not dbg.value, which describes its value.
- bool isAddressOfVariable() const {
- return getIntrinsicID() != Intrinsic::dbg_value;
- }
-
DILocalVariable *getVariable() const {
return cast<DILocalVariable>(getRawVariable());
}
return cast<MetadataAsValue>(getArgOperand(2))->getMetadata();
}
- /// \name Casting methods
- /// @{
+ // Methods for support type inquiry through isa, cast, and dyn_cast:
static bool classof(const IntrinsicInst *I) {
switch (I->getIntrinsicID()) {
case Intrinsic::dbg_declare:
case Intrinsic::dbg_value:
- case Intrinsic::dbg_addr:
return true;
default: return false;
}
static bool classof(const Value *V) {
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
}
- /// @}
};
/// This represents the llvm.dbg.declare instruction.
public:
Value *getAddress() const { return getVariableLocation(); }
- /// \name Casting methods
- /// @{
+ // Methods for support type inquiry through isa, cast, and dyn_cast:
static bool classof(const IntrinsicInst *I) {
return I->getIntrinsicID() == Intrinsic::dbg_declare;
}
static bool classof(const Value *V) {
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
}
- /// @}
- };
-
- /// This represents the llvm.dbg.addr instruction.
- class DbgAddrIntrinsic : public DbgInfoIntrinsic {
- public:
- Value *getAddress() const { return getVariableLocation(); }
-
- /// \name Casting methods
- /// @{
- static bool classof(const IntrinsicInst *I) {
- return I->getIntrinsicID() == Intrinsic::dbg_addr;
- }
- static bool classof(const Value *V) {
- return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
- }
};
/// This represents the llvm.dbg.value instruction.
return getVariableLocation(/* AllowNullOp = */ false);
}
- /// \name Casting methods
- /// @{
+ // Methods for support type inquiry through isa, cast, and dyn_cast:
static bool classof(const IntrinsicInst *I) {
return I->getIntrinsicID() == Intrinsic::dbg_value;
}
static bool classof(const Value *V) {
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
}
- /// @}
};
/// This is the common base class for constrained floating point intrinsics.
let IntrProperties = [IntrNoMem, IntrSpeculatable] in {
def int_dbg_declare : Intrinsic<[],
[llvm_metadata_ty,
- llvm_metadata_ty,
- llvm_metadata_ty]>;
+ llvm_metadata_ty,
+ llvm_metadata_ty]>;
def int_dbg_value : Intrinsic<[],
[llvm_metadata_ty,
llvm_metadata_ty,
llvm_metadata_ty]>;
- def int_dbg_addr : Intrinsic<[],
- [llvm_metadata_ty,
- llvm_metadata_ty,
- llvm_metadata_ty]>;
}
//===------------------ Exception Handling Intrinsics----------------------===//
#define LLVM_TRANSFORMS_UTILS_LOCAL_H
#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Dominators.h"
class Instruction;
class CallInst;
class DbgDeclareInst;
-class DbgInfoIntrinsic;
class DbgValueInst;
class StoreInst;
class LoadInst;
///
/// Inserts a llvm.dbg.value intrinsic before a store to an alloca'd value
-/// that has an associated llvm.dbg.declare or llvm.dbg.addr intrinsic.
-void ConvertDebugDeclareToDebugValue(DbgInfoIntrinsic *DII,
+/// that has an associated llvm.dbg.decl intrinsic.
+void ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI,
StoreInst *SI, DIBuilder &Builder);
/// Inserts a llvm.dbg.value intrinsic before a load of an alloca'd value
-/// that has an associated llvm.dbg.declare or llvm.dbg.addr intrinsic.
-void ConvertDebugDeclareToDebugValue(DbgInfoIntrinsic *DII,
+/// that has an associated llvm.dbg.decl intrinsic.
+void ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI,
LoadInst *LI, DIBuilder &Builder);
-/// Inserts a llvm.dbg.value intrinsic after a phi that has an associated
-/// llvm.dbg.declare or llvm.dbg.addr intrinsic.
-void ConvertDebugDeclareToDebugValue(DbgInfoIntrinsic *DII,
+/// Inserts a llvm.dbg.value intrinsic after a phi of an alloca'd value
+/// that has an associated llvm.dbg.decl intrinsic.
+void ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI,
PHINode *LI, DIBuilder &Builder);
/// Lowers llvm.dbg.declare intrinsics into appropriate set of
/// llvm.dbg.value intrinsics.
bool LowerDbgDeclare(Function &F);
-/// Finds all intrinsics declaring local variables as living in the memory that
-/// 'V' points to. This may include a mix of dbg.declare and
-/// dbg.addr intrinsics.
-TinyPtrVector<DbgInfoIntrinsic *> FindDbgAddrUses(Value *V);
+/// Finds the llvm.dbg.declare intrinsic corresponding to an alloca, if any.
+DbgDeclareInst *FindAllocaDbgDeclare(Value *V);
/// Finds the llvm.dbg.value intrinsics describing a value.
void findDbgValues(SmallVectorImpl<DbgValueInst *> &DbgValues, Value *V);
DAG.setRoot(CallResult.second);
return nullptr;
}
- case Intrinsic::dbg_addr:
case Intrinsic::dbg_declare: {
- const DbgInfoIntrinsic &DI = cast<DbgInfoIntrinsic>(I);
+ const DbgDeclareInst &DI = cast<DbgDeclareInst>(I);
DILocalVariable *Variable = DI.getVariable();
DIExpression *Expression = DI.getExpression();
+ const Value *Address = DI.getAddress();
assert(Variable && "Missing variable");
+ if (!Address) {
+ DEBUG(dbgs() << "Dropping debug info for " << DI << "\n");
+ return nullptr;
+ }
// Check if address has undef value.
- const Value *Address = DI.getVariableLocation();
- if (!Address || isa<UndefValue>(Address) ||
+ if (isa<UndefValue>(Address) ||
(Address->use_empty() && !isa<Argument>(Address))) {
DEBUG(dbgs() << "Dropping debug info for " << DI << "\n");
return nullptr;
}
- bool isParameter = Variable->isParameter() || isa<Argument>(Address);
-
- // Check if this variable can be described by a frame index, typically
- // either as a static alloca or a byval parameter.
- int FI = INT_MAX;
+ // Static allocas are handled more efficiently in the variable frame index
+ // side table.
if (const auto *AI =
- dyn_cast<AllocaInst>(Address->stripInBoundsConstantOffsets())) {
- if (AI->isStaticAlloca()) {
- auto I = FuncInfo.StaticAllocaMap.find(AI);
- if (I != FuncInfo.StaticAllocaMap.end())
- FI = I->second;
- }
- } else if (const auto *Arg = dyn_cast<Argument>(
- Address->stripInBoundsConstantOffsets())) {
- FI = FuncInfo.getArgumentFrameIndex(Arg);
- }
+ dyn_cast<AllocaInst>(Address->stripInBoundsConstantOffsets()))
+ if (AI->isStaticAlloca() && FuncInfo.StaticAllocaMap.count(AI))
+ return nullptr;
- // llvm.dbg.addr is control dependent and always generates indirect
- // DBG_VALUE instructions. llvm.dbg.declare is handled as a frame index in
- // the MachineFunction variable table.
- if (FI != INT_MAX) {
- if (Intrinsic == Intrinsic::dbg_addr)
- DAG.AddDbgValue(DAG.getFrameIndexDbgValue(Variable, Expression, FI, dl,
- SDNodeOrder),
- getRoot().getNode(), isParameter);
- return nullptr;
- }
+ // Byval arguments with frame indices were already handled after argument
+ // lowering and before isel.
+ if (const auto *Arg =
+ dyn_cast<Argument>(Address->stripInBoundsConstantOffsets()))
+ if (FuncInfo.getArgumentFrameIndex(Arg) != INT_MAX)
+ return nullptr;
SDValue &N = NodeMap[Address];
if (!N.getNode() && isa<Argument>(Address))
if (const BitCastInst *BCI = dyn_cast<BitCastInst>(Address))
Address = BCI->getOperand(0);
// Parameters are handled specially.
+ bool isParameter = Variable->isParameter() || isa<Argument>(Address);
auto FINode = dyn_cast<FrameIndexSDNode>(N.getNode());
if (isParameter && FINode) {
// Byval parameter. We have a frame index at this point.
using namespace llvm;
using namespace llvm::dwarf;
-cl::opt<bool>
- UseDbgAddr("use-dbg-addr",
- llvm::cl::desc("Use llvm.dbg.addr for all local variables"),
- cl::init(false));
-
DIBuilder::DIBuilder(Module &m, bool AllowUnresolvedNodes)
: M(m), VMContext(M.getContext()), CUNode(nullptr),
DeclareFn(nullptr), ValueFn(nullptr),
return I;
}
-static Function *getDeclareIntrin(Module &M) {
- return Intrinsic::getDeclaration(&M, UseDbgAddr ? Intrinsic::dbg_addr
- : Intrinsic::dbg_declare);
-}
-
Instruction *DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo,
DIExpression *Expr, const DILocation *DL,
Instruction *InsertBefore) {
VarInfo->getScope()->getSubprogram() &&
"Expected matching subprograms");
if (!DeclareFn)
- DeclareFn = getDeclareIntrin(M);
+ DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare);
trackIfUnresolved(VarInfo);
trackIfUnresolved(Expr);
VarInfo->getScope()->getSubprogram() &&
"Expected matching subprograms");
if (!DeclareFn)
- DeclareFn = getDeclareIntrin(M);
+ DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare);
trackIfUnresolved(VarInfo);
trackIfUnresolved(Expr);
"invalid llvm.dbg.declare intrinsic call 1", CS);
visitDbgIntrinsic("declare", cast<DbgInfoIntrinsic>(*CS.getInstruction()));
break;
- case Intrinsic::dbg_addr: // llvm.dbg.addr
- visitDbgIntrinsic("addr", cast<DbgInfoIntrinsic>(*CS.getInstruction()));
case Intrinsic::dbg_value: // llvm.dbg.value
visitDbgIntrinsic("value", cast<DbgInfoIntrinsic>(*CS.getInstruction()));
break;
// If we are removing an alloca with a dbg.declare, insert dbg.value calls
// before each store.
- TinyPtrVector<DbgInfoIntrinsic *> DIIs;
+ DbgDeclareInst *DDI = nullptr;
std::unique_ptr<DIBuilder> DIB;
if (isa<AllocaInst>(MI)) {
- DIIs = FindDbgAddrUses(&MI);
+ DDI = FindAllocaDbgDeclare(&MI);
DIB.reset(new DIBuilder(*MI.getModule(), /*AllowUnresolved=*/false));
}
} else if (isa<BitCastInst>(I) || isa<GetElementPtrInst>(I) ||
isa<AddrSpaceCastInst>(I)) {
replaceInstUsesWith(*I, UndefValue::get(I->getType()));
- } else if (auto *SI = dyn_cast<StoreInst>(I)) {
- for (auto *DII : DIIs)
- ConvertDebugDeclareToDebugValue(DII, SI, *DIB);
+ } else if (DDI && isa<StoreInst>(I)) {
+ ConvertDebugDeclareToDebugValue(DDI, cast<StoreInst>(I), *DIB);
}
eraseInstFromFunction(*I);
}
None, "", II->getParent());
}
- for (auto *DII : DIIs)
- eraseInstFromFunction(*DII);
+ if (DDI)
+ eraseInstFromFunction(*DDI);
return eraseInstFromFunction(MI);
}
// Migrate debug information from the old alloca to the new alloca(s)
// and the individual partitions.
- TinyPtrVector<DbgInfoIntrinsic *> DbgDeclares = FindDbgAddrUses(&AI);
- if (!DbgDeclares.empty()) {
- auto *Var = DbgDeclares.front()->getVariable();
- auto *Expr = DbgDeclares.front()->getExpression();
+ if (DbgDeclareInst *DbgDecl = FindAllocaDbgDeclare(&AI)) {
+ auto *Var = DbgDecl->getVariable();
+ auto *Expr = DbgDecl->getExpression();
DIBuilder DIB(*AI.getModule(), /*AllowUnresolved*/ false);
uint64_t AllocaSize = DL.getTypeSizeInBits(AI.getAllocatedType());
for (auto Fragment : Fragments) {
DIExpression::createFragmentExpression(Expr, Start, Size);
}
- // Remove any existing intrinsics describing the same alloca.
- for (DbgInfoIntrinsic *OldDII : FindDbgAddrUses(Fragment.Alloca))
- OldDII->eraseFromParent();
+ // Remove any existing dbg.declare intrinsic describing the same alloca.
+ if (DbgDeclareInst *OldDDI = FindAllocaDbgDeclare(Fragment.Alloca))
+ OldDDI->eraseFromParent();
DIB.insertDeclare(Fragment.Alloca, Var, FragmentExpr,
- DbgDeclares.front()->getDebugLoc(), &AI);
+ DbgDecl->getDebugLoc(), &AI);
}
}
return Changed;
Instruction *I = DeadInsts.pop_back_val();
DEBUG(dbgs() << "Deleting dead instruction: " << *I << "\n");
- // If the instruction is an alloca, find the possible dbg.declare connected
- // to it, and remove it too. We must do this before calling RAUW or we will
- // not be able to find it.
- if (AllocaInst *AI = dyn_cast<AllocaInst>(I)) {
- DeletedAllocas.insert(AI);
- for (DbgInfoIntrinsic *OldDII : FindDbgAddrUses(AI))
- OldDII->eraseFromParent();
- }
-
I->replaceAllUsesWith(UndefValue::get(I->getType()));
for (Use &Operand : I->operands())
DeadInsts.insert(U);
}
+ if (AllocaInst *AI = dyn_cast<AllocaInst>(I)) {
+ DeletedAllocas.insert(AI);
+ if (DbgDeclareInst *DbgDecl = FindAllocaDbgDeclare(AI))
+ DbgDecl->eraseFromParent();
+ }
+
++NumDeleted;
I->eraseFromParent();
}
}
/// Inserts a llvm.dbg.value intrinsic before a store to an alloca'd value
-/// that has an associated llvm.dbg.declare or llvm.dbg.addr intrinsic.
-void llvm::ConvertDebugDeclareToDebugValue(DbgInfoIntrinsic *DII,
+/// that has an associated llvm.dbg.decl intrinsic.
+void llvm::ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI,
StoreInst *SI, DIBuilder &Builder) {
- assert(DII->isAddressOfVariable());
- auto *DIVar = DII->getVariable();
+ auto *DIVar = DDI->getVariable();
assert(DIVar && "Missing variable");
- auto *DIExpr = DII->getExpression();
+ auto *DIExpr = DDI->getExpression();
Value *DV = SI->getOperand(0);
// If an argument is zero extended then use argument directly. The ZExt
if (SExtInst *SExt = dyn_cast<SExtInst>(SI->getOperand(0)))
ExtendedArg = dyn_cast<Argument>(SExt->getOperand(0));
if (ExtendedArg) {
- // If this DII was already describing only a fragment of a variable, ensure
+ // If this DDI was already describing only a fragment of a variable, ensure
// that fragment is appropriately narrowed here.
// But if a fragment wasn't used, describe the value as the original
// argument (rather than the zext or sext) so that it remains described even
DIExpr->elements_end() - 3);
Ops.push_back(dwarf::DW_OP_LLVM_fragment);
Ops.push_back(FragmentOffset);
- const DataLayout &DL = DII->getModule()->getDataLayout();
+ const DataLayout &DL = DDI->getModule()->getDataLayout();
Ops.push_back(DL.getTypeSizeInBits(ExtendedArg->getType()));
DIExpr = Builder.createExpression(Ops);
}
DV = ExtendedArg;
}
if (!LdStHasDebugValue(DIVar, DIExpr, SI))
- Builder.insertDbgValueIntrinsic(DV, DIVar, DIExpr, DII->getDebugLoc(),
+ Builder.insertDbgValueIntrinsic(DV, DIVar, DIExpr, DDI->getDebugLoc(),
SI);
}
/// Inserts a llvm.dbg.value intrinsic before a load of an alloca'd value
-/// that has an associated llvm.dbg.declare or llvm.dbg.addr intrinsic.
-void llvm::ConvertDebugDeclareToDebugValue(DbgInfoIntrinsic *DII,
+/// that has an associated llvm.dbg.decl intrinsic.
+void llvm::ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI,
LoadInst *LI, DIBuilder &Builder) {
- auto *DIVar = DII->getVariable();
- auto *DIExpr = DII->getExpression();
+ auto *DIVar = DDI->getVariable();
+ auto *DIExpr = DDI->getExpression();
assert(DIVar && "Missing variable");
if (LdStHasDebugValue(DIVar, DIExpr, LI))
// preferable to keep tracking both the loaded value and the original
// address in case the alloca can not be elided.
Instruction *DbgValue = Builder.insertDbgValueIntrinsic(
- LI, DIVar, DIExpr, DII->getDebugLoc(), (Instruction *)nullptr);
+ LI, DIVar, DIExpr, DDI->getDebugLoc(), (Instruction *)nullptr);
DbgValue->insertAfter(LI);
}
-/// Inserts a llvm.dbg.value intrinsic after a phi that has an associated
-/// llvm.dbg.declare or llvm.dbg.addr intrinsic.
-void llvm::ConvertDebugDeclareToDebugValue(DbgInfoIntrinsic *DII,
+/// Inserts a llvm.dbg.value intrinsic after a phi
+/// that has an associated llvm.dbg.decl intrinsic.
+void llvm::ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI,
PHINode *APN, DIBuilder &Builder) {
- auto *DIVar = DII->getVariable();
- auto *DIExpr = DII->getExpression();
+ auto *DIVar = DDI->getVariable();
+ auto *DIExpr = DDI->getExpression();
assert(DIVar && "Missing variable");
if (PhiHasDebugValue(DIVar, DIExpr, APN))
// insertion point.
// FIXME: Insert dbg.value markers in the successors when appropriate.
if (InsertionPt != BB->end())
- Builder.insertDbgValueIntrinsic(APN, DIVar, DIExpr, DII->getDebugLoc(),
+ Builder.insertDbgValueIntrinsic(APN, DIVar, DIExpr, DDI->getDebugLoc(),
&*InsertionPt);
}
return true;
}
-/// Finds all intrinsics declaring local variables as living in the memory that
-/// 'V' points to. This may include a mix of dbg.declare and
-/// dbg.addr intrinsics.
-TinyPtrVector<DbgInfoIntrinsic *> llvm::FindDbgAddrUses(Value *V) {
- auto *L = LocalAsMetadata::getIfExists(V);
- if (!L)
- return {};
- auto *MDV = MetadataAsValue::getIfExists(V->getContext(), L);
- if (!MDV)
- return {};
-
- TinyPtrVector<DbgInfoIntrinsic *> Declares;
- for (User *U : MDV->users()) {
- if (auto *DII = dyn_cast<DbgInfoIntrinsic>(U))
- if (DII->isAddressOfVariable())
- Declares.push_back(DII);
- }
+/// FindAllocaDbgDeclare - Finds the llvm.dbg.declare intrinsic describing the
+/// alloca 'V', if any.
+DbgDeclareInst *llvm::FindAllocaDbgDeclare(Value *V) {
+ if (auto *L = LocalAsMetadata::getIfExists(V))
+ if (auto *MDV = MetadataAsValue::getIfExists(V->getContext(), L))
+ for (User *U : MDV->users())
+ if (DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(U))
+ return DDI;
- return Declares;
+ return nullptr;
}
void llvm::findDbgValues(SmallVectorImpl<DbgValueInst *> &DbgValues, Value *V) {
DbgValues.push_back(DVI);
}
+
bool llvm::replaceDbgDeclare(Value *Address, Value *NewAddress,
Instruction *InsertBefore, DIBuilder &Builder,
bool Deref, int Offset) {
- auto DbgAddrs = FindDbgAddrUses(Address);
- for (DbgInfoIntrinsic *DII : DbgAddrs) {
- DebugLoc Loc = DII->getDebugLoc();
- auto *DIVar = DII->getVariable();
- auto *DIExpr = DII->getExpression();
- assert(DIVar && "Missing variable");
- DIExpr = DIExpression::prepend(DIExpr, Deref, Offset);
- // Insert llvm.dbg.declare immediately after the original alloca, and remove
- // old llvm.dbg.declare.
- Builder.insertDeclare(NewAddress, DIVar, DIExpr, Loc, InsertBefore);
- DII->eraseFromParent();
- }
- return !DbgAddrs.empty();
+ DbgDeclareInst *DDI = FindAllocaDbgDeclare(Address);
+ if (!DDI)
+ return false;
+ DebugLoc Loc = DDI->getDebugLoc();
+ auto *DIVar = DDI->getVariable();
+ auto *DIExpr = DDI->getExpression();
+ assert(DIVar && "Missing variable");
+ DIExpr = DIExpression::prepend(DIExpr, Deref, Offset);
+ // Insert llvm.dbg.declare immediately after the original alloca, and remove
+ // old llvm.dbg.declare.
+ Builder.insertDeclare(NewAddress, DIVar, DIExpr, Loc, InsertBefore);
+ DDI->eraseFromParent();
+ return true;
}
bool llvm::replaceDbgDeclareForAlloca(AllocaInst *AI, Value *NewAllocaAddress,
bool OnlyUsedInOneBlock;
Value *AllocaPointerVal;
- TinyPtrVector<DbgInfoIntrinsic*> DbgDeclares;
+ DbgDeclareInst *DbgDeclare;
void clear() {
DefiningBlocks.clear();
OnlyBlock = nullptr;
OnlyUsedInOneBlock = true;
AllocaPointerVal = nullptr;
- DbgDeclares.clear();
+ DbgDeclare = nullptr;
}
/// Scan the uses of the specified alloca, filling in the AllocaInfo used
}
}
- DbgDeclares = FindDbgAddrUses(AI);
+ DbgDeclare = FindAllocaDbgDeclare(AI);
}
};
/// For each alloca, we keep track of the dbg.declare intrinsic that
/// describes it, if any, so that we can convert it to a dbg.value
/// intrinsic if the alloca gets promoted.
- SmallVector<TinyPtrVector<DbgInfoIntrinsic *>, 8> AllocaDbgDeclares;
+ SmallVector<DbgDeclareInst *, 8> AllocaDbgDeclares;
/// The set of basic blocks the renamer has already visited.
///
// Record debuginfo for the store and remove the declaration's
// debuginfo.
- for (DbgInfoIntrinsic *DII : Info.DbgDeclares) {
+ if (DbgDeclareInst *DDI = Info.DbgDeclare) {
DIBuilder DIB(*AI->getModule(), /*AllowUnresolved*/ false);
- ConvertDebugDeclareToDebugValue(DII, Info.OnlyStore, DIB);
- DII->eraseFromParent();
- LBI.deleteValue(DII);
+ ConvertDebugDeclareToDebugValue(DDI, Info.OnlyStore, DIB);
+ DDI->eraseFromParent();
+ LBI.deleteValue(DDI);
}
// Remove the (now dead) store and alloca.
Info.OnlyStore->eraseFromParent();
while (!AI->use_empty()) {
StoreInst *SI = cast<StoreInst>(AI->user_back());
// Record debuginfo for the store before removing it.
- for (DbgInfoIntrinsic *DII : Info.DbgDeclares) {
+ if (DbgDeclareInst *DDI = Info.DbgDeclare) {
DIBuilder DIB(*AI->getModule(), /*AllowUnresolved*/ false);
- ConvertDebugDeclareToDebugValue(DII, SI, DIB);
+ ConvertDebugDeclareToDebugValue(DDI, SI, DIB);
}
SI->eraseFromParent();
LBI.deleteValue(SI);
LBI.deleteValue(AI);
// The alloca's debuginfo can be removed as well.
- for (DbgInfoIntrinsic *DII : Info.DbgDeclares) {
- DII->eraseFromParent();
- LBI.deleteValue(DII);
+ if (DbgDeclareInst *DDI = Info.DbgDeclare) {
+ DDI->eraseFromParent();
+ LBI.deleteValue(DDI);
}
++NumLocalPromoted;
}
// Remember the dbg.declare intrinsic describing this alloca, if any.
- if (!Info.DbgDeclares.empty())
- AllocaDbgDeclares[AllocaNum] = Info.DbgDeclares;
+ if (Info.DbgDeclare)
+ AllocaDbgDeclares[AllocaNum] = Info.DbgDeclare;
// Keep the reverse mapping of the 'Allocas' array for the rename pass.
AllocaLookup[Allocas[AllocaNum]] = AllocaNum;
}
// Remove alloca's dbg.declare instrinsics from the function.
- for (auto &Declares : AllocaDbgDeclares)
- for (auto *DII : Declares)
- DII->eraseFromParent();
+ for (DbgDeclareInst *DDI : AllocaDbgDeclares)
+ if (DDI)
+ DDI->eraseFromParent();
// Loop over all of the PHI nodes and see if there are any that we can get
// rid of because they merge all of the same incoming values. This can
// The currently active variable for this block is now the PHI.
IncomingVals[AllocaNo] = APN;
- for (DbgInfoIntrinsic *DII : AllocaDbgDeclares[AllocaNo])
- ConvertDebugDeclareToDebugValue(DII, APN, DIB);
+ if (DbgDeclareInst *DDI = AllocaDbgDeclares[AllocaNo])
+ ConvertDebugDeclareToDebugValue(DDI, APN, DIB);
// Get the next phi node.
++PNI;
// what value were we writing?
IncomingVals[ai->second] = SI->getOperand(0);
// Record debuginfo for the store before removing it.
- for (DbgInfoIntrinsic *DII : AllocaDbgDeclares[ai->second])
- ConvertDebugDeclareToDebugValue(DII, SI, DIB);
+ if (DbgDeclareInst *DDI = AllocaDbgDeclares[ai->second])
+ ConvertDebugDeclareToDebugValue(DDI, SI, DIB);
BB->getInstList().erase(SI);
}
}
+++ /dev/null
-; RUN: llc %s -o %t.s
-; RUN: llvm-mc %t.s -filetype=obj -triple=x86_64-windows-msvc -o %t.o
-; RUN: FileCheck %s < %t.s --check-prefix=ASM
-; RUN: llvm-dwarfdump %t.o | FileCheck %s --check-prefix=DWARF
-
-; In this example, the variable lives mostly in memory, but at the point of the
-; assignment to global, it lives nowhere, and is described as the constant
-; value 1.
-
-; C source:
-;
-; void escape(int *);
-; extern int global;
-; void f(int x) {
-; escape(&x);
-; x = 1; // DSE should delete and insert dbg.value(i32 1)
-; global = x;
-; x = 2; // DSE should insert dbg.addr
-; escape(&x);
-; }
-
-; ModuleID = 'dse.c'
-source_filename = "dse.c"
-target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
-target triple = "x86_64-pc-windows-msvc19.0.24215"
-
-declare void @llvm.dbg.addr(metadata, metadata, metadata) #2
-declare void @llvm.dbg.value(metadata, metadata, metadata) #2
-declare void @escape(i32*)
-
-@global = external global i32, align 4
-
-; Function Attrs: nounwind uwtable
-define void @f(i32 %x) #0 !dbg !8 {
-entry:
- %x.addr = alloca i32, align 4
- store i32 %x, i32* %x.addr, align 4
- call void @llvm.dbg.addr(metadata i32* %x.addr, metadata !13, metadata !DIExpression()), !dbg !18
- call void @escape(i32* %x.addr), !dbg !19
- call void @llvm.dbg.value(metadata i32 1, metadata !13, metadata !DIExpression()), !dbg !20
- store i32 1, i32* @global, align 4, !dbg !22
- call void @llvm.dbg.addr(metadata i32* %x.addr, metadata !13, metadata !DIExpression()), !dbg !23
- store i32 2, i32* %x.addr, align 4, !dbg !23
- call void @escape(i32* %x.addr), !dbg !24
- ret void, !dbg !25
-}
-
-; ASM-LABEL: f: # @f
-; ASM: movl %ecx, [[OFF_X:[0-9]+]](%rsp)
-; ASM: #DEBUG_VALUE: f:x <- [DW_OP_plus_uconst [[OFF_X]]] [%RSP+0]
-; ASM: callq escape
-; ASM: #DEBUG_VALUE: f:x <- 1
-; ASM: movl $1, global(%rip)
-; FIXME: Needs a fix to LiveDebugVariables
-; ASMX: #DEBUG_VALUE: f:x <- [DW_OP_plus_uconst [[OFF_X]]] [%RSP+0]
-; ASM: movl $2, [[OFF_X]](%rsp)
-; ASM: callq escape
-; ASM: retq
-
-; DWARF: DW_TAG_formal_parameter
-; DWARF-NEXT: DW_AT_location (0x00000000
-; DWARF-NEXT: {{[^:]*}}: DW_OP_breg7 RSP+{{[0-9]+}}
-; DWARF-NEXT: {{[^:]*}}: DW_OP_consts +1, DW_OP_stack_value
-; FIXME: Needs a fix to LiveDebugVariables
-; DWARFX-NEXT: {{[^:]*}}: DW_OP_breg7 RSP+{{[0-9]+}})
-; DWARF-NEXT: DW_AT_name ("x")
-
-attributes #0 = { nounwind uwtable }
-attributes #2 = { nounwind readnone speculatable }
-
-!llvm.dbg.cu = !{!0}
-!llvm.module.flags = !{!3, !4, !5, !6}
-!llvm.ident = !{!7}
-
-!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
-!1 = !DIFile(filename: "dse.c", directory: "C:\5Csrc\5Cllvm-project\5Cbuild")
-!2 = !{}
-!3 = !{i32 2, !"Dwarf Version", i32 4}
-!4 = !{i32 2, !"Debug Info Version", i32 3}
-!5 = !{i32 1, !"wchar_size", i32 2}
-!6 = !{i32 7, !"PIC Level", i32 2}
-!7 = !{!"clang version 6.0.0 "}
-!8 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 3, type: !9, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !12)
-!9 = !DISubroutineType(types: !10)
-!10 = !{null, !11}
-!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
-!12 = !{!13}
-!13 = !DILocalVariable(name: "x", arg: 1, scope: !8, file: !1, line: 3, type: !11)
-!14 = !{!15, !15, i64 0}
-!15 = !{!"int", !16, i64 0}
-!16 = !{!"omnipotent char", !17, i64 0}
-!17 = !{!"Simple C/C++ TBAA"}
-!18 = !DILocation(line: 3, column: 12, scope: !8)
-!19 = !DILocation(line: 4, column: 3, scope: !8)
-!20 = !DILocation(line: 5, column: 5, scope: !8)
-!21 = !DILocation(line: 6, column: 12, scope: !8)
-!22 = !DILocation(line: 6, column: 10, scope: !8)
-!23 = !DILocation(line: 7, column: 5, scope: !8)
-!24 = !DILocation(line: 8, column: 3, scope: !8)
-!25 = !DILocation(line: 9, column: 1, scope: !8)
+++ /dev/null
-; RUN: llc %s -o %t.s
-; RUN: llvm-mc -triple x86_64--linux %t.s -filetype=obj -o %t.o
-; RUN: FileCheck < %t.s %s
-; RUN: llvm-dwarfdump %t.o | FileCheck %s --check-prefix=DWARF
-
-; Unlike dbg.declare, dbg.addr should be lowered to DBG_VALUE instructions. It
-; is control-dependent.
-
-; CHECK-LABEL: use_dbg_addr:
-; CHECK: #DEBUG_VALUE: use_dbg_addr:o <- [%RSP+0]
-
-; FIXME: Avoid the use of a single-location location list and use
-; DW_AT_start_offset instead.
-
-; DWARF: DW_TAG_variable
-; DWARF-NEXT: DW_AT_location (0x00000000
-; DWARF-NEXT: 0x{{.*}} - 0x{{.*}}: DW_OP_breg7 RSP+0)
-; DWARF-NEXT: DW_AT_name ("o")
-
-
-; ModuleID = 't.c'
-source_filename = "t.c"
-target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
-target triple = "x86_64--linux"
-
-%struct.Foo = type { i32 }
-
-; Function Attrs: noinline nounwind uwtable
-define void @use_dbg_addr() #0 !dbg !7 {
-entry:
- %o = alloca %struct.Foo, align 4
- call void @llvm.dbg.addr(metadata %struct.Foo* %o, metadata !10, metadata !15), !dbg !16
- call void @escape_foo(%struct.Foo* %o), !dbg !17
- ret void, !dbg !18
-}
-
-; Function Attrs: nounwind readnone speculatable
-declare void @llvm.dbg.addr(metadata, metadata, metadata) #1
-
-declare void @escape_foo(%struct.Foo*)
-
-attributes #0 = { noinline nounwind uwtable }
-attributes #1 = { nounwind readnone speculatable }
-
-!llvm.dbg.cu = !{!0}
-!llvm.module.flags = !{!3, !4, !5}
-!llvm.ident = !{!6}
-
-!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
-!1 = !DIFile(filename: "t.c", directory: "C:\5Csrc\5Cllvm-project\5Cbuild")
-!2 = !{}
-!3 = !{i32 2, !"Dwarf Version", i32 4}
-!4 = !{i32 2, !"Debug Info Version", i32 3}
-!5 = !{i32 1, !"wchar_size", i32 4}
-!6 = !{!"clang version 6.0.0 "}
-!7 = distinct !DISubprogram(name: "use_dbg_addr", scope: !1, file: !1, line: 3, type: !8, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2)
-!8 = !DISubroutineType(types: !9)
-!9 = !{null}
-!10 = !DILocalVariable(name: "o", scope: !7, file: !1, line: 4, type: !11)
-!11 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo", file: !1, line: 1, size: 32, elements: !12)
-!12 = !{!13}
-!13 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !11, file: !1, line: 1, baseType: !14, size: 32)
-!14 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
-!15 = !DIExpression()
-!16 = !DILocation(line: 4, column: 14, scope: !7)
-!17 = !DILocation(line: 5, column: 3, scope: !7)
-!18 = !DILocation(line: 6, column: 1, scope: !7)
;
; There should be no debug info for the padding.
; CHECK-NOT: DW_OP_LLVM_fragment, 56
-; CHECK: DIExpression(DW_OP_LLVM_fragment, 0, 32)
-; CHECK-NOT: DW_OP_LLVM_fragment, 56
; CHECK: DIExpression(DW_OP_LLVM_fragment, 32, 24)
; CHECK-NOT: DW_OP_LLVM_fragment, 56
+; CHECK: DIExpression(DW_OP_LLVM_fragment, 0, 32)
+; CHECK-NOT: DW_OP_LLVM_fragment, 56
%struct.prog_src_register = type { i32, i24 }
; Function Attrs: nounwind
+++ /dev/null
-; RUN: opt -S -sroa -o - %s | FileCheck %s
-
-; SROA should split the alloca in two new ones, each with its own dbg.declare.
-; The original alloca and dbg.declare should be removed.
-
-define void @f1() {
-entry:
- %0 = alloca [9 x i32]
- call void @llvm.dbg.declare(metadata [9 x i32]* %0, metadata !11, metadata !DIExpression()), !dbg !17
- %1 = bitcast [9 x i32]* %0 to i8*
- call void @llvm.memset.p0i8.i64(i8* %1, i8 0, i64 36, i32 16, i1 true)
- %2 = getelementptr [9 x i32], [9 x i32]* %0, i32 0, i32 0
- store volatile i32 1, i32* %2
- ret void
-}
-
-; Function Attrs: nounwind readnone speculatable
-declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
-
-; Function Attrs: argmemonly nounwind
-declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i32, i1) #0
-
-attributes #0 = { argmemonly nounwind }
-attributes #1 = { nounwind readnone speculatable }
-
-!llvm.dbg.cu = !{!0}
-!llvm.module.flags = !{!3, !4, !5}
-!llvm.ident = !{!6}
-
-!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
-!1 = !DIFile(filename: "foo.c", directory: "/bar")
-!2 = !{}
-!3 = !{i32 2, !"Dwarf Version", i32 4}
-!4 = !{i32 2, !"Debug Info Version", i32 3}
-!5 = !{i32 1, !"wchar_size", i32 4}
-!6 = !{!"clang version 6.0.0"}
-!7 = distinct !DISubprogram(name: "f1", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !10)
-!8 = !DISubroutineType(types: !9)
-!9 = !{null}
-!10 = !{!11}
-!11 = !DILocalVariable(name: "b", scope: !7, file: !1, line: 3, type: !12)
-!12 = !DICompositeType(tag: DW_TAG_array_type, baseType: !13, size: 288, elements: !15)
-!13 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !14)
-!14 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
-!15 = !{!16}
-!16 = !DISubrange(count: 9)
-!17 = !DILocation(line: 3, column: 18, scope: !7)
-
-; CHECK-NOT: = alloca [9 x i32]
-; CHECK-NOT: call void @llvm.dbg.declare(metadata [9 x i32]*
-
-; CHECK: %[[VAR1:.*]] = alloca i32
-; CHECK-NEXT: %[[VAR2:.*]] = alloca [8 x i32]
-; CHECK-NEXT: call void @llvm.dbg.declare(metadata i32* %[[VAR1]]
-; CHECK-NEXT: call void @llvm.dbg.declare(metadata [8 x i32]* %[[VAR2]]
-
-; CHECK-NOT: = alloca [9 x i32]
-; CHECK-NOT: call void @llvm.dbg.declare(metadata [9 x i32]*
-
+++ /dev/null
-; RUN: opt -mem2reg -S < %s | FileCheck %s -implicit-check-not="call void @llvm.dbg.addr"
-
-; This example is intended to simulate this pass pipeline, which may not exist
-; in practice:
-; 1. DSE f from the original C source
-; 2. Inline escape
-; 3. mem2reg
-; This exercises the corner case of multiple llvm.dbg.addr intrinsics.
-
-; C source:
-;
-; void escape(int *px) { ++*px; }
-; extern int global;
-; void f(int x) {
-; escape(&x);
-; x = 1; // DSE should delete and insert dbg.value(i32 1)
-; global = x;
-; x = 2; // DSE should insert dbg.addr
-; escape(&x);
-; }
-
-; ModuleID = 'dse.c'
-source_filename = "dse.c"
-target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
-target triple = "x86_64-pc-windows-msvc19.0.24215"
-
-declare void @llvm.dbg.addr(metadata, metadata, metadata) #2
-declare void @llvm.dbg.value(metadata, metadata, metadata) #2
-
-@global = external global i32, align 4
-
-; Function Attrs: nounwind uwtable
-define void @f(i32 %x) #0 !dbg !8 {
-entry:
- %x.addr = alloca i32, align 4
- store i32 %x, i32* %x.addr, align 4
- call void @llvm.dbg.addr(metadata i32* %x.addr, metadata !13, metadata !DIExpression()), !dbg !18
- %ld.1 = load i32, i32* %x.addr, align 4, !dbg !19
- %inc.1 = add nsw i32 %ld.1, 1, !dbg !19
- store i32 %inc.1, i32* %x.addr, align 4, !dbg !19
- call void @llvm.dbg.value(metadata i32 1, metadata !13, metadata !DIExpression()), !dbg !20
- store i32 1, i32* @global, align 4, !dbg !22
- call void @llvm.dbg.addr(metadata i32* %x.addr, metadata !13, metadata !DIExpression()), !dbg !23
- store i32 2, i32* %x.addr, align 4, !dbg !23
- %ld.2 = load i32, i32* %x.addr, align 4, !dbg !19
- %inc.2 = add nsw i32 %ld.2, 1, !dbg !19
- store i32 %inc.2, i32* %x.addr, align 4, !dbg !19
- ret void, !dbg !25
-}
-
-; CHECK-LABEL: define void @f(i32 %x)
-; CHECK: call void @llvm.dbg.value(metadata i32 %x, metadata !13, metadata !DIExpression())
-; CHECK: %inc.1 = add nsw i32 %x, 1
-; CHECK: call void @llvm.dbg.value(metadata i32 %inc.1, metadata !13, metadata !DIExpression())
-; CHECK: call void @llvm.dbg.value(metadata i32 1, metadata !13, metadata !DIExpression())
-; CHECK: store i32 1, i32* @global, align 4
-; CHECK: call void @llvm.dbg.value(metadata i32 2, metadata !13, metadata !DIExpression())
-; CHECK: %inc.2 = add nsw i32 2, 1
-; CHECK: call void @llvm.dbg.value(metadata i32 %inc.2, metadata !13, metadata !DIExpression())
-; CHECK: ret void
-
-attributes #0 = { nounwind uwtable }
-attributes #2 = { nounwind readnone speculatable }
-
-!llvm.dbg.cu = !{!0}
-!llvm.module.flags = !{!3, !4, !5, !6}
-!llvm.ident = !{!7}
-
-!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
-!1 = !DIFile(filename: "dse.c", directory: "C:\5Csrc\5Cllvm-project\5Cbuild")
-!2 = !{}
-!3 = !{i32 2, !"Dwarf Version", i32 4}
-!4 = !{i32 2, !"Debug Info Version", i32 3}
-!5 = !{i32 1, !"wchar_size", i32 2}
-!6 = !{i32 7, !"PIC Level", i32 2}
-!7 = !{!"clang version 6.0.0 "}
-!8 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 3, type: !9, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !12)
-!9 = !DISubroutineType(types: !10)
-!10 = !{null, !11}
-!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
-!12 = !{!13}
-!13 = !DILocalVariable(name: "x", arg: 1, scope: !8, file: !1, line: 3, type: !11)
-!14 = !{!15, !15, i64 0}
-!15 = !{!"int", !16, i64 0}
-!16 = !{!"omnipotent char", !17, i64 0}
-!17 = !{!"Simple C/C++ TBAA"}
-!18 = !DILocation(line: 3, column: 12, scope: !8)
-!19 = !DILocation(line: 4, column: 3, scope: !8)
-!20 = !DILocation(line: 5, column: 5, scope: !8)
-!21 = !DILocation(line: 6, column: 12, scope: !8)
-!22 = !DILocation(line: 6, column: 10, scope: !8)
-!23 = !DILocation(line: 7, column: 5, scope: !8)
-!24 = !DILocation(line: 8, column: 3, scope: !8)
-!25 = !DILocation(line: 9, column: 1, scope: !8)
+++ /dev/null
-; RUN: opt -mem2reg -S < %s | FileCheck %s
-
-; ModuleID = 'newvars.c'
-source_filename = "newvars.c"
-target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
-target triple = "x86_64-pc-windows-msvc19.0.24215"
-
-; Function Attrs: nounwind uwtable
-define i32 @if_else(i32 %cond, i32 %a, i32 %b) !dbg !8 {
-entry:
- %x = alloca i32, align 4
- call void @llvm.dbg.addr(metadata i32* %x, metadata !16, metadata !DIExpression()), !dbg !26
- store i32 %a, i32* %x, align 4, !dbg !26, !tbaa !17
- %tobool = icmp ne i32 %cond, 0, !dbg !28
- br i1 %tobool, label %if.then, label %if.else, !dbg !30
-
-if.then: ; preds = %entry
- store i32 0, i32* %x, align 4, !dbg !31, !tbaa !17
- br label %if.end, !dbg !33
-
-if.else: ; preds = %entry
- store i32 %b, i32* %x, align 4, !dbg !36, !tbaa !17
- br label %if.end
-
-if.end: ; preds = %if.else, %if.then
- %rv = load i32, i32* %x, align 4, !dbg !37, !tbaa !17
- ret i32 %rv, !dbg !39
-}
-
-; CHECK-LABEL: define i32 @if_else({{.*}})
-; CHECK: entry:
-; CHECK-NOT: alloca i32
-; CHECK: call void @llvm.dbg.value(metadata i32 %a, metadata ![[X_LOCAL:[0-9]+]], metadata !DIExpression())
-; CHECK: if.then: ; preds = %entry
-; CHECK: call void @llvm.dbg.value(metadata i32 0, metadata ![[X_LOCAL]], metadata !DIExpression())
-; CHECK: if.else: ; preds = %entry
-; CHECK: call void @llvm.dbg.value(metadata i32 %b, metadata ![[X_LOCAL]], metadata !DIExpression())
-; CHECK: if.end: ; preds = %if.else, %if.then
-; CHECK: %[[PHI:[^ ]*]] = phi i32 [ 0, %if.then ], [ %b, %if.else ]
-; CHECK: call void @llvm.dbg.value(metadata i32 %[[PHI]], metadata ![[X_LOCAL]], metadata !DIExpression())
-; CHECK: ret i32
-
-; CHECK: ![[X_LOCAL]] = !DILocalVariable(name: "x", {{.*}})
-
-; Function Attrs: nounwind readnone speculatable
-declare void @llvm.dbg.declare(metadata, metadata, metadata)
-declare void @llvm.dbg.addr(metadata, metadata, metadata)
-
-!llvm.dbg.cu = !{!0}
-!llvm.module.flags = !{!3, !4, !5, !6}
-!llvm.ident = !{!7}
-
-!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
-!1 = !DIFile(filename: "newvars.c", directory: "C:\5Csrc\5Cllvm-project\5Cbuild")
-!2 = !{}
-!3 = !{i32 2, !"Dwarf Version", i32 4}
-!4 = !{i32 2, !"Debug Info Version", i32 3}
-!5 = !{i32 1, !"wchar_size", i32 2}
-!6 = !{i32 7, !"PIC Level", i32 2}
-!7 = !{!"clang version 6.0.0 "}
-!8 = distinct !DISubprogram(name: "if_else", scope: !1, file: !1, line: 1, type: !9, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !12)
-!9 = !DISubroutineType(types: !10)
-!10 = !{!11, !11, !11, !11}
-!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
-!12 = !{!13, !14, !15, !16}
-!13 = !DILocalVariable(name: "b", arg: 3, scope: !8, file: !1, line: 1, type: !11)
-!14 = !DILocalVariable(name: "a", arg: 2, scope: !8, file: !1, line: 1, type: !11)
-!15 = !DILocalVariable(name: "cond", arg: 1, scope: !8, file: !1, line: 1, type: !11)
-!16 = !DILocalVariable(name: "x", scope: !8, file: !1, line: 2, type: !11)
-!17 = !{!18, !18, i64 0}
-!18 = !{!"int", !19, i64 0}
-!19 = !{!"omnipotent char", !20, i64 0}
-!20 = !{!"Simple C/C++ TBAA"}
-!22 = !DILocation(line: 1, column: 34, scope: !8)
-!23 = !DILocation(line: 1, column: 27, scope: !8)
-!24 = !DILocation(line: 1, column: 17, scope: !8)
-!25 = !DILocation(line: 2, column: 3, scope: !8)
-!26 = !DILocation(line: 2, column: 7, scope: !8)
-!27 = !DILocation(line: 2, column: 11, scope: !8)
-!28 = !DILocation(line: 3, column: 7, scope: !29)
-!29 = distinct !DILexicalBlock(scope: !8, file: !1, line: 3, column: 7)
-!30 = !DILocation(line: 3, column: 7, scope: !8)
-!31 = !DILocation(line: 4, column: 7, scope: !32)
-!32 = distinct !DILexicalBlock(scope: !29, file: !1, line: 3, column: 13)
-!33 = !DILocation(line: 5, column: 3, scope: !32)
-!34 = !DILocation(line: 6, column: 9, scope: !35)
-!35 = distinct !DILexicalBlock(scope: !29, file: !1, line: 5, column: 10)
-!36 = !DILocation(line: 6, column: 7, scope: !35)
-!37 = !DILocation(line: 8, column: 10, scope: !8)
-!38 = !DILocation(line: 9, column: 1, scope: !8)
-!39 = !DILocation(line: 8, column: 3, scope: !8)
+++ /dev/null
-; RUN: opt -use-dbg-addr -sroa -S < %s | FileCheck %s
-
-; ModuleID = '<stdin>'
-source_filename = "newvars.c"
-target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
-target triple = "x86_64-pc-windows-msvc19.0.24215"
-
-%struct.Pair = type { i32, i32 }
-
-@pair = internal global %struct.Pair zeroinitializer
-
-; Function Attrs: nounwind uwtable
-define void @if_else(i32 %cond, i32 %a, i32 %b) !dbg !8 {
-entry:
- %p = alloca %struct.Pair, align 4
- %0 = bitcast %struct.Pair* %p to i8*, !dbg !25
- call void @llvm.dbg.addr(metadata %struct.Pair* %p, metadata !20, metadata !DIExpression()), !dbg !26
- %x = getelementptr inbounds %struct.Pair, %struct.Pair* %p, i32 0, i32 0, !dbg !27
- store i32 %a, i32* %x, align 4, !dbg !28
- %y = getelementptr inbounds %struct.Pair, %struct.Pair* %p, i32 0, i32 1, !dbg !34
- store i32 %b, i32* %y, align 4, !dbg !35
- %tobool = icmp ne i32 %cond, 0, !dbg !37
- br i1 %tobool, label %if.then, label %if.else, !dbg !39
-
-if.then: ; preds = %entry
- %x1 = getelementptr inbounds %struct.Pair, %struct.Pair* %p, i32 0, i32 0, !dbg !40
- store i32 0, i32* %x1, align 4, !dbg !42
- %y2 = getelementptr inbounds %struct.Pair, %struct.Pair* %p, i32 0, i32 1, !dbg !43
- store i32 %a, i32* %y2, align 4, !dbg !44
- br label %if.end, !dbg !45
-
-if.else: ; preds = %entry
- %x3 = getelementptr inbounds %struct.Pair, %struct.Pair* %p, i32 0, i32 0, !dbg !46
- store i32 %b, i32* %x3, align 4, !dbg !48
- %y4 = getelementptr inbounds %struct.Pair, %struct.Pair* %p, i32 0, i32 1, !dbg !49
- store i32 0, i32* %y4, align 4, !dbg !50
- br label %if.end
-
-if.end: ; preds = %if.else, %if.then
- %1 = bitcast %struct.Pair* %p to i8*, !dbg !51
- %2 = bitcast %struct.Pair* @pair to i8*, !dbg !51
- call void @llvm.memcpy.p0i8.p0i8.i64(i8* %2, i8* %1, i64 8, i32 4, i1 false), !dbg !51
- ret void
-}
-
-; CHECK-LABEL: define void @if_else(i32 %cond, i32 %a, i32 %b)
-; CHECK: entry:
-; CHECK: call void @llvm.dbg.value(metadata i32 %a, metadata ![[PVAR:[0-9]+]], metadata ![[XFRAG:DIExpression\(DW_OP_LLVM_fragment, 0, 32\)]])
-; CHECK: call void @llvm.dbg.value(metadata i32 %b, metadata ![[PVAR]], metadata ![[YFRAG:DIExpression\(DW_OP_LLVM_fragment, 32, 32\)]])
-; CHECK: if.then:
-; CHECK: call void @llvm.dbg.value(metadata i32 0, metadata ![[PVAR]], metadata ![[XFRAG]])
-; CHECK: call void @llvm.dbg.value(metadata i32 %a, metadata ![[PVAR]], metadata ![[YFRAG]])
-; CHECK: if.else:
-; CHECK: call void @llvm.dbg.value(metadata i32 %b, metadata ![[PVAR]], metadata ![[XFRAG]])
-; CHECK: call void @llvm.dbg.value(metadata i32 0, metadata ![[PVAR]], metadata ![[YFRAG]])
-; CHECK: if.end:
-; CHECK: %p.sroa.4.0 = phi i32 [ %a, %if.then ], [ 0, %if.else ]
-; CHECK: %p.sroa.0.0 = phi i32 [ 0, %if.then ], [ %b, %if.else ]
-; CHECK: call void @llvm.dbg.value(metadata i32 %p.sroa.0.0, metadata ![[PVAR]], metadata ![[XFRAG]])
-; CHECK: call void @llvm.dbg.value(metadata i32 %p.sroa.4.0, metadata ![[PVAR]], metadata ![[YFRAG]])
-
-; CHECK: ![[PVAR]] = !DILocalVariable(name: "p", {{.*}})
-
-; Function Attrs: argmemonly nounwind
-declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i32, i1) #2
-
-; Function Attrs: nounwind readnone speculatable
-declare void @llvm.dbg.addr(metadata, metadata, metadata)
-
-!llvm.dbg.cu = !{!0}
-!llvm.module.flags = !{!3, !4, !5, !6}
-!llvm.ident = !{!7}
-
-!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
-!1 = !DIFile(filename: "newvars.c", directory: "C:\5Csrc\5Cllvm-project\5Cbuild")
-!2 = !{}
-!3 = !{i32 2, !"Dwarf Version", i32 4}
-!4 = !{i32 2, !"Debug Info Version", i32 3}
-!5 = !{i32 1, !"wchar_size", i32 2}
-!6 = !{i32 7, !"PIC Level", i32 2}
-!7 = !{!"clang version 6.0.0 "}
-!8 = distinct !DISubprogram(name: "if_else", scope: !1, file: !1, line: 2, type: !9, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !16)
-!9 = !DISubroutineType(types: !10)
-!10 = !{!11, !14, !14, !14}
-!11 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Pair", file: !1, line: 1, size: 64, elements: !12)
-!12 = !{!13, !15}
-!13 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !11, file: !1, line: 1, baseType: !14, size: 32)
-!14 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
-!15 = !DIDerivedType(tag: DW_TAG_member, name: "y", scope: !11, file: !1, line: 1, baseType: !14, size: 32, offset: 32)
-!16 = !{!17, !18, !19, !20}
-!17 = !DILocalVariable(name: "b", arg: 3, scope: !8, file: !1, line: 2, type: !14)
-!18 = !DILocalVariable(name: "a", arg: 2, scope: !8, file: !1, line: 2, type: !14)
-!19 = !DILocalVariable(name: "cond", arg: 1, scope: !8, file: !1, line: 2, type: !14)
-!20 = !DILocalVariable(name: "p", scope: !8, file: !1, line: 3, type: !11)
-!22 = !DILocation(line: 2, column: 42, scope: !8)
-!23 = !DILocation(line: 2, column: 35, scope: !8)
-!24 = !DILocation(line: 2, column: 25, scope: !8)
-!25 = !DILocation(line: 3, column: 3, scope: !8)
-!26 = !DILocation(line: 3, column: 15, scope: !8)
-!27 = !DILocation(line: 4, column: 5, scope: !8)
-!28 = !DILocation(line: 4, column: 7, scope: !8)
-!29 = !{!30, !31, i64 0}
-!30 = !{!"Pair", !31, i64 0, !31, i64 4}
-!31 = !{!"int", !32, i64 0}
-!32 = !{!"omnipotent char", !33, i64 0}
-!33 = !{!"Simple C/C++ TBAA"}
-!34 = !DILocation(line: 5, column: 5, scope: !8)
-!35 = !DILocation(line: 5, column: 7, scope: !8)
-!36 = !{!30, !31, i64 4}
-!37 = !DILocation(line: 6, column: 7, scope: !38)
-!38 = distinct !DILexicalBlock(scope: !8, file: !1, line: 6, column: 7)
-!39 = !DILocation(line: 6, column: 7, scope: !8)
-!40 = !DILocation(line: 7, column: 7, scope: !41)
-!41 = distinct !DILexicalBlock(scope: !38, file: !1, line: 6, column: 13)
-!42 = !DILocation(line: 7, column: 9, scope: !41)
-!43 = !DILocation(line: 8, column: 7, scope: !41)
-!44 = !DILocation(line: 8, column: 9, scope: !41)
-!45 = !DILocation(line: 9, column: 3, scope: !41)
-!46 = !DILocation(line: 10, column: 7, scope: !47)
-!47 = distinct !DILexicalBlock(scope: !38, file: !1, line: 9, column: 10)
-!48 = !DILocation(line: 10, column: 9, scope: !47)
-!49 = !DILocation(line: 11, column: 7, scope: !47)
-!50 = !DILocation(line: 11, column: 9, scope: !47)
-!51 = !DILocation(line: 13, column: 10, scope: !8)
-!52 = !{i64 0, i64 4, !53, i64 4, i64 4, !53}
-!53 = !{!31, !31, i64 0}
-!54 = !DILocation(line: 14, column: 1, scope: !8)