Index: lib/Target/X86/X86OptimizeLEAs.cpp =================================================================== --- lib/Target/X86/X86OptimizeLEAs.cpp +++ lib/Target/X86/X86OptimizeLEAs.cpp @@ -27,7 +27,9 @@ #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/Passes.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/Function.h" +#include "llvm/MC/MCContext.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetInstrInfo.h" @@ -262,6 +264,12 @@ /// \brief Removes redundant address calculations. bool removeRedundantAddrCalc(MemOpMap &LEAs); + /// Replace debug value MI with a new debug value instruction using register + /// VReg with an appropriate offset and DIExpression to incorporate the + /// address displacement AddrDispShift. Return new debug value instruction. + MachineInstr *replaceDebugValue(MachineInstr &MI, unsigned VReg, + int64_t AddrDispShift); + /// \brief Removes LEAs which calculate similar addresses. bool removeRedundantLEAs(MemOpMap &LEAs); @@ -532,6 +540,39 @@ return Changed; } +MachineInstr *OptimizeLEAPass::replaceDebugValue(MachineInstr &MI, + unsigned VReg, + int64_t AddrDispShift) { + const DIExpression *Expr = MI.getDebugExpression(); + + bool IsIndirect = MI.isIndirectDebugValue(); + int64_t Offset = (IsIndirect ? MI.getOperand(1).getImm() : 0) + AddrDispShift; + if (!IsIndirect && (Offset != 0)) { + // If required create new DIExpression with DW_OP_stack_value prepended to + // existing DIExpression. + ArrayRef OrigElements = Expr->getElements(); + if (OrigElements.empty()) { + Expr = DIExpression::get(Expr->getContext(), + { dwarf::DW_OP_stack_value }); + } else if (OrigElements[0] != dwarf::DW_OP_stack_value) { + SmallVector Elements(OrigElements.size() + 1); + Elements[0] = dwarf::DW_OP_stack_value; + std::copy(OrigElements.begin(), OrigElements.end(), + Elements.begin() + 1); + Expr = DIExpression::get(Expr->getContext(), Elements); + } + + IsIndirect = true; + } + + // Replace DBG_VALUE instruction with modified version. + MachineBasicBlock *MBB = MI.getParent(); + DebugLoc DL = MI.getDebugLoc(); + const MDNode *Var = MI.getDebugVariable(); + return BuildMI(*MBB, MBB->erase(&MI), DL, TII->get(TargetOpcode::DBG_VALUE), + IsIndirect, VReg, Offset, Var, Expr); +} + // Try to find similar LEAs in the list and replace one with another. bool OptimizeLEAPass::removeRedundantLEAs(MemOpMap &LEAs) { bool Changed = false; @@ -563,13 +604,21 @@ // Loop over all uses of the Last LEA and update their operands. Note // that the correctness of this has already been checked in the // isReplaceable function. + unsigned FirstVReg = First.getOperand(0).getReg(); unsigned LastVReg = Last.getOperand(0).getReg(); - for (auto UI = MRI->use_nodbg_begin(LastVReg), - UE = MRI->use_nodbg_end(); + for (auto UI = MRI->use_begin(LastVReg), UE = MRI->use_end(); UI != UE;) { MachineOperand &MO = *UI++; MachineInstr &MI = *MO.getParent(); + if (MI.isDebugValue()) { + // Replace DBG_VALUE instruction with modified version using the + // register from the replacing LEA and the address displacement + // between the LEA instructions. + replaceDebugValue(MI, FirstVReg, AddrDispShift); + continue; + } + // Get the number of the first memory operand. const MCInstrDesc &Desc = MI.getDesc(); int MemOpNo = @@ -577,7 +626,7 @@ X86II::getOperandBias(Desc); // Update address base. - MO.setReg(First.getOperand(0).getReg()); + MO.setReg(FirstVReg); // Update address disp. MachineOperand &Op = MI.getOperand(MemOpNo + X86::AddrDisp); @@ -587,11 +636,8 @@ Op.setOffset(Op.getOffset() + AddrDispShift); } - // Mark debug values referring to Last LEA as undefined. - MRI->markUsesInDebugValueAsUndef(LastVReg); - // Since we can possibly extend register lifetime, clear kill flags. - MRI->clearKillFlags(First.getOperand(0).getReg()); + MRI->clearKillFlags(FirstVReg); ++NumRedundantLEAs; DEBUG(dbgs() << "OptimizeLEAs: Remove redundant LEA: "; Last.dump();); Index: test/CodeGen/X86/lea-opt-with-debug.mir =================================================================== --- test/CodeGen/X86/lea-opt-with-debug.mir +++ test/CodeGen/X86/lea-opt-with-debug.mir @@ -1,7 +1,8 @@ # RUN: llc -mtriple=x86_64-unknown-unknown -start-after peephole-opt -stop-before detect-dead-lanes -o - %s | FileCheck %s -# Test that pass optimize LEA can remove a redundant LEA even when it is also -# used by a DBG_VALUE. +# Test that the optimize LEA pass can remove a redundant LEA even when it is +# also used by a DBG_VALUE. Check that the uses of the replaced LEA are updated +# correctly. --- | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" @@ -13,22 +14,22 @@ @d = common local_unnamed_addr global i32 0, align 4 @b = common local_unnamed_addr global i32 0, align 4 - define i32 @fn1() local_unnamed_addr !dbg !8 { - %1 = load %struct.A*, %struct.A** @c, align 8, !dbg !13 - %2 = load i32, i32* @a, align 4, !dbg !13 - %3 = sext i32 %2 to i64, !dbg !13 - %4 = getelementptr inbounds %struct.A, %struct.A* %1, i64 %3, !dbg !13 - %5 = ptrtoint %struct.A* %4 to i64, !dbg !13 - %6 = trunc i64 %5 to i32, !dbg !13 - store i32 %6, i32* @d, align 4, !dbg !13 - %7 = getelementptr inbounds %struct.A, %struct.A* %1, i64 %3, i32 2, !dbg !14 - tail call void @llvm.dbg.value(metadata i32* %7, i64 0, metadata !11, metadata !15), !dbg !16 - br label %8, !dbg !17 + define i32 @fn1() local_unnamed_addr !dbg !9 { + %1 = load %struct.A*, %struct.A** @c, align 8, !dbg !14 + %2 = load i32, i32* @a, align 4, !dbg !14 + %3 = sext i32 %2 to i64, !dbg !14 + %4 = getelementptr inbounds %struct.A, %struct.A* %1, i64 %3, !dbg !14 + %5 = ptrtoint %struct.A* %4 to i64, !dbg !14 + %6 = trunc i64 %5 to i32, !dbg !14 + store i32 %6, i32* @d, align 4, !dbg !14 + %7 = getelementptr inbounds %struct.A, %struct.A* %1, i64 %3, i32 2, !dbg !15 + tail call void @llvm.dbg.value(metadata i32* %7, i64 0, metadata !12, metadata !16), !dbg !17 + br label %8, !dbg !18 ;