Vendor import of llvm release_40 branch r295910:

https://llvm.org/svn/llvm-project/llvm/branches/release_40@295910
This commit is contained in:
Dimitry Andric 2017-02-23 19:02:03 +00:00
parent c60b95818e
commit e49737eb04
10 changed files with 213 additions and 54 deletions

View File

@ -61,6 +61,13 @@ Non-comprehensive list of changes in this release
with LLVM option -adce-remove-loops when the loop body otherwise has
no live operations.
* The GVNHoist pass is now enabled by default. The new pass based on Global
Value Numbering detects similar computations in branch code and replaces
multiple instances of the same computation with a unique expression. The
transform benefits code size and generates better schedules. GVNHoist is
more aggressive at -Os and -Oz, hoisting more expressions at the expense of
execution time degradations.
* The llvm-cov tool can now export coverage data as json. Its html output mode
has also improved.

View File

@ -522,22 +522,19 @@ DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV,
}
// .. else use frame index.
if (DV.getFrameIndex().empty())
if (!DV.hasFrameIndexExprs())
return VariableDie;
auto Expr = DV.getExpression().begin();
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
for (auto FI : DV.getFrameIndex()) {
for (auto &Fragment : DV.getFrameIndexExprs()) {
unsigned FrameReg = 0;
const TargetFrameLowering *TFI = Asm->MF->getSubtarget().getFrameLowering();
int Offset = TFI->getFrameIndexReference(*Asm->MF, FI, FrameReg);
assert(Expr != DV.getExpression().end() && "Wrong number of expressions");
DwarfExpr.addFragmentOffset(*Expr);
int Offset = TFI->getFrameIndexReference(*Asm->MF, Fragment.FI, FrameReg);
DwarfExpr.addFragmentOffset(Fragment.Expr);
DwarfExpr.AddMachineRegIndirect(*Asm->MF->getSubtarget().getRegisterInfo(),
FrameReg, Offset);
DwarfExpr.AddExpression(*Expr);
++Expr;
DwarfExpr.AddExpression(Fragment.Expr);
}
addBlock(*VariableDie, dwarf::DW_AT_location, DwarfExpr.finalize());

View File

@ -199,6 +199,15 @@ const DIType *DbgVariable::getType() const {
return Ty;
}
ArrayRef<DbgVariable::FrameIndexExpr> DbgVariable::getFrameIndexExprs() const {
std::sort(FrameIndexExprs.begin(), FrameIndexExprs.end(),
[](const FrameIndexExpr &A, const FrameIndexExpr &B) -> bool {
return A.Expr->getFragmentInfo()->OffsetInBits <
B.Expr->getFragmentInfo()->OffsetInBits;
});
return FrameIndexExprs;
}
static const DwarfAccelTable::Atom TypeAtoms[] = {
DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4),
DwarfAccelTable::Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2),

View File

@ -54,7 +54,7 @@ class MachineModuleInfo;
///
/// Variables can be created from allocas, in which case they're generated from
/// the MMI table. Such variables can have multiple expressions and frame
/// indices. The \a Expr and \a FrameIndices array must match.
/// indices.
///
/// Variables can be created from \c DBG_VALUE instructions. Those whose
/// location changes over time use \a DebugLocListIndex, while those with a
@ -64,11 +64,16 @@ class MachineModuleInfo;
class DbgVariable {
const DILocalVariable *Var; /// Variable Descriptor.
const DILocation *IA; /// Inlined at location.
SmallVector<const DIExpression *, 1> Expr; /// Complex address.
DIE *TheDIE = nullptr; /// Variable DIE.
unsigned DebugLocListIndex = ~0u; /// Offset in DebugLocs.
const MachineInstr *MInsn = nullptr; /// DBG_VALUE instruction.
SmallVector<int, 1> FrameIndex; /// Frame index.
struct FrameIndexExpr {
int FI;
const DIExpression *Expr;
};
mutable SmallVector<FrameIndexExpr, 1>
FrameIndexExprs; /// Frame index + expression.
public:
/// Construct a DbgVariable.
@ -80,21 +85,18 @@ public:
/// Initialize from the MMI table.
void initializeMMI(const DIExpression *E, int FI) {
assert(Expr.empty() && "Already initialized?");
assert(FrameIndex.empty() && "Already initialized?");
assert(FrameIndexExprs.empty() && "Already initialized?");
assert(!MInsn && "Already initialized?");
assert((!E || E->isValid()) && "Expected valid expression");
assert(~FI && "Expected valid index");
Expr.push_back(E);
FrameIndex.push_back(FI);
FrameIndexExprs.push_back({FI, E});
}
/// Initialize from a DBG_VALUE instruction.
void initializeDbgValue(const MachineInstr *DbgValue) {
assert(Expr.empty() && "Already initialized?");
assert(FrameIndex.empty() && "Already initialized?");
assert(FrameIndexExprs.empty() && "Already initialized?");
assert(!MInsn && "Already initialized?");
assert(Var == DbgValue->getDebugVariable() && "Wrong variable");
@ -103,16 +105,15 @@ public:
MInsn = DbgValue;
if (auto *E = DbgValue->getDebugExpression())
if (E->getNumElements())
Expr.push_back(E);
FrameIndexExprs.push_back({0, E});
}
// Accessors.
const DILocalVariable *getVariable() const { return Var; }
const DILocation *getInlinedAt() const { return IA; }
ArrayRef<const DIExpression *> getExpression() const { return Expr; }
const DIExpression *getSingleExpression() const {
assert(MInsn && Expr.size() <= 1);
return Expr.size() ? Expr[0] : nullptr;
assert(MInsn && FrameIndexExprs.size() <= 1);
return FrameIndexExprs.size() ? FrameIndexExprs[0].Expr : nullptr;
}
void setDIE(DIE &D) { TheDIE = &D; }
DIE *getDIE() const { return TheDIE; }
@ -120,7 +121,9 @@ public:
unsigned getDebugLocListIndex() const { return DebugLocListIndex; }
StringRef getName() const { return Var->getName(); }
const MachineInstr *getMInsn() const { return MInsn; }
ArrayRef<int> getFrameIndex() const { return FrameIndex; }
/// Get the FI entries, sorted by fragment offset.
ArrayRef<FrameIndexExpr> getFrameIndexExprs() const;
bool hasFrameIndexExprs() const { return !FrameIndexExprs.empty(); }
void addMMIEntry(const DbgVariable &V) {
assert(DebugLocListIndex == ~0U && !MInsn && "not an MMI entry");
@ -128,16 +131,15 @@ public:
assert(V.Var == Var && "conflicting variable");
assert(V.IA == IA && "conflicting inlined-at location");
assert(!FrameIndex.empty() && "Expected an MMI entry");
assert(!V.FrameIndex.empty() && "Expected an MMI entry");
assert(Expr.size() == FrameIndex.size() && "Mismatched expressions");
assert(V.Expr.size() == V.FrameIndex.size() && "Mismatched expressions");
assert(!FrameIndexExprs.empty() && "Expected an MMI entry");
assert(!V.FrameIndexExprs.empty() && "Expected an MMI entry");
Expr.append(V.Expr.begin(), V.Expr.end());
FrameIndex.append(V.FrameIndex.begin(), V.FrameIndex.end());
assert(all_of(Expr, [](const DIExpression *E) {
return E && E->isFragment();
}) && "conflicting locations for variable");
FrameIndexExprs.append(V.FrameIndexExprs.begin(), V.FrameIndexExprs.end());
assert(all_of(FrameIndexExprs,
[](FrameIndexExpr &FIE) {
return FIE.Expr && FIE.Expr->isFragment();
}) &&
"conflicting locations for variable");
}
// Translate tag to proper Dwarf tag.
@ -167,11 +169,11 @@ public:
bool hasComplexAddress() const {
assert(MInsn && "Expected DBG_VALUE, not MMI variable");
assert(FrameIndex.empty() && "Expected DBG_VALUE, not MMI variable");
assert(
(Expr.empty() || (Expr.size() == 1 && Expr.back()->getNumElements())) &&
"Invalid Expr for DBG_VALUE");
return !Expr.empty();
assert((FrameIndexExprs.empty() ||
(FrameIndexExprs.size() == 1 &&
FrameIndexExprs[0].Expr->getNumElements())) &&
"Invalid Expr for DBG_VALUE");
return !FrameIndexExprs.empty();
}
bool isBlockByrefVariable() const;
const DIType *getType() const;

View File

@ -853,9 +853,11 @@ AArch64LoadStoreOpt::promoteLoadFromStore(MachineBasicBlock::iterator LoadI,
.addImm(Imms);
}
}
StoreI->clearRegisterKills(StRt, TRI);
(void)BitExtMI;
// Clear kill flags between store and load.
for (MachineInstr &MI : make_range(StoreI->getIterator(),
BitExtMI->getIterator()))
MI.clearRegisterKills(StRt, TRI);
DEBUG(dbgs() << "Promoting load by replacing :\n ");
DEBUG(StoreI->print(dbgs()));

View File

@ -1225,16 +1225,36 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB,
}
case ARM::tTPsoft:
case ARM::TPsoft: {
const bool Thumb = Opcode == ARM::tTPsoft;
MachineInstrBuilder MIB;
if (Opcode == ARM::tTPsoft)
if (STI->genLongCalls()) {
MachineFunction *MF = MBB.getParent();
MachineConstantPool *MCP = MF->getConstantPool();
unsigned PCLabelID = AFI->createPICLabelUId();
MachineConstantPoolValue *CPV =
ARMConstantPoolSymbol::Create(MF->getFunction()->getContext(),
"__aeabi_read_tp", PCLabelID, 0);
unsigned Reg = MI.getOperand(0).getReg();
MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(),
TII->get( ARM::tBL))
.addImm((unsigned)ARMCC::AL).addReg(0)
.addExternalSymbol("__aeabi_read_tp", 0);
else
TII->get(Thumb ? ARM::tLDRpci : ARM::LDRi12), Reg)
.addConstantPoolIndex(MCP->getConstantPoolIndex(CPV, 4));
if (!Thumb)
MIB.addImm(0);
MIB.addImm(static_cast<unsigned>(ARMCC::AL)).addReg(0);
MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(),
TII->get( ARM::BL))
.addExternalSymbol("__aeabi_read_tp", 0);
TII->get(Thumb ? ARM::tBLXr : ARM::BLX));
if (Thumb)
MIB.addImm(static_cast<unsigned>(ARMCC::AL)).addReg(0);
MIB.addReg(Reg, RegState::Kill);
} else {
MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(),
TII->get(Thumb ? ARM::tBL : ARM::BL));
if (Thumb)
MIB.addImm(static_cast<unsigned>(ARMCC::AL)).addReg(0);
MIB.addExternalSymbol("__aeabi_read_tp", 0);
}
MIB->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
TransferImpOps(MI, MIB, MIB);

View File

@ -1196,10 +1196,7 @@ LoopInvariantCodeMotion::collectAliasInfoForLoop(Loop *L, LoopInfo *LI,
auto mergeLoop = [&](Loop *L) {
// Loop over the body of this loop, looking for calls, invokes, and stores.
// Because subloops have already been incorporated into AST, we skip blocks
// in subloops.
for (BasicBlock *BB : L->blocks())
if (LI->getLoopFor(BB) == L) // Ignore blocks in subloops.
CurAST->add(*BB); // Incorporate the specified basic block
};

View File

@ -1,10 +1,4 @@
# RUN: llc -mtriple=aarch64--linux-gnu -run-pass=aarch64-ldst-opt %s -verify-machineinstrs -o - 2>&1 | FileCheck %s
--- |
define void @promote-load-from-store() { ret void }
define void @store-pair() { ret void }
define void @store-pair-clearkill0() { ret void }
define void @store-pair-clearkill1() { ret void }
...
---
name: promote-load-from-store
tracksRegLiveness: true
@ -130,3 +124,23 @@ body: |
# CHECK-NOT: %w2 = COPY killed %w1
# CHECK: %w2 = COPY %w1
# CHECK: STPWi %w1, killed %w2, killed %x0, 0
---
name: store-load-clearkill
tracksRegLiveness: true
body: |
bb.0:
liveins: %w1
STRWui %w1, %sp, 0 :: (store 4)
%wzr = COPY killed %w1 ; killing use of %w1
%w11 = LDRWui %sp, 0 :: (load 4)
HINT 0, implicit %w11 ; some use of %w11
...
# When replaceing the load of a store-load pair with a copy the kill flags
# along the way need to be cleared.
# CHECK-LABEL: name: store-load-clearkill
# CHECK: STRWui %w1, %sp, 0 :: (store 4)
# CHECK-NOT: COPY killed %w1
# CHECK: %wzr = COPY %w1
# CHECK: %w11 = ORRWrs %wzr, %w1, 0
# CHECK: HINT 0, implicit %w11

View File

@ -0,0 +1,26 @@
; RUN: llc -mtriple armv7---eabi -filetype asm -o - %s | FileCheck %s -check-prefix CHECK -check-prefix CHECK-SHORT
; RUN: llc -mtriple thumbv7---eabi -filetype asm -o - %s | FileCheck %s -check-prefix CHECK -check-prefix CHECK-SHORT
; RUN: llc -mtriple armv7---eabi -mattr=+long-calls -filetype asm -o - %s | FileCheck %s -check-prefix CHECK -check-prefix CHECK-LONG
; RUN: llc -mtriple thumbv7---eabi -mattr=+long-calls -filetype asm -o - %s | FileCheck %s -check-prefix CHECK -check-prefix CHECK-LONG
@i = thread_local local_unnamed_addr global i32 0, align 4
define i32 @f() local_unnamed_addr {
entry:
%0 = load i32, i32* @i, align 4
ret i32 %0
}
; CHECK-LABEL: f:
; CHECK-SHORT: ldr r1, [[VAR:.LCPI[0-9]+_[0-9]+]]
; CHECK-SHORT-NEXT: bl __aeabi_read_tp
; CHECK-SHORT: [[VAR]]:
; CHECK-SHORT-NEXT: .long i(TPOFF)
; CHECK-LONG: ldr [[REG:r[0-9]+]], [[FUN:.LCPI[0-9]+_[0-9]+]]
; CHECK-LONG-NEXT: ldr r1, [[VAR:.LCPI[0-9]+_[0-9]+]]
; CHECK-LONG-NEXT: blx [[REG]]
; CHECK-LONG: [[VAR]]:
; CHECK-LONG-NEXT: .long i(TPOFF)
; CHECK-LONG: [[FUN]]:
; CHECK-LONG-NEXT: .long __aeabi_read_tp

View File

@ -0,0 +1,85 @@
; PR31381: An assertion in the DWARF backend when fragments in MMI slots are
; sorted by largest offset first.
; RUN: llc -mtriple=x86_64-apple-darwin -filetype=obj < %s | llvm-dwarfdump -debug-dump=info - | FileCheck %s
; CHECK: DW_TAG_formal_parameter
; CHECK: DW_TAG_formal_parameter
; CHECK-NEXT: DW_AT_location [DW_FORM_exprloc] (<0xa> 91 78 93 03 93 06 91 7d 93 03 )
; fbreg -8, piece 0x00000003, piece 0x00000006, fbreg -3, piece 0x00000003
; CHECK-NEXT: DW_AT_abstract_origin {{.*}}"p"
source_filename = "bugpoint-reduced-simplified.ll"
target triple = "x86_64-apple-darwin"
@f = common local_unnamed_addr global i32 0, align 4, !dbg !0
@h = common local_unnamed_addr global i32 0, align 4, !dbg !6
; Function Attrs: nounwind readnone
declare void @llvm.dbg.declare(metadata, metadata, metadata) #0
define void @fn4() local_unnamed_addr !dbg !12 {
entry:
%l1.sroa.7.i = alloca [3 x i8], align 1
tail call void @llvm.dbg.declare(metadata [3 x i8]* %l1.sroa.7.i, metadata !15, metadata !26), !dbg !27
%i.sroa.4.i = alloca [3 x i8], align 8
tail call void @llvm.dbg.declare(metadata [3 x i8]* %i.sroa.4.i, metadata !15, metadata !32), !dbg !27
%0 = load i32, i32* @h, align 4
br label %while.body.i.i, !dbg !33
while.body.i.i: ; preds = %while.body.i.i, %entry
br label %while.body.i.i, !dbg !34
fn3.exit: ; No predecessors!
%1 = load i32, i32* @f, align 4
%tobool.i = icmp eq i32 %1, 0
br label %while.body.i
while.body.i: ; preds = %if.end.i, %fn3.exit
br i1 %tobool.i, label %if.end.i, label %if.then.i
if.then.i: ; preds = %while.body.i
br label %if.end.i
if.end.i: ; preds = %if.then.i, %while.body.i
br label %while.body.i
}
attributes #0 = { nounwind readnone }
!llvm.dbg.cu = !{!2}
!llvm.module.flags = !{!9, !10, !11}
!0 = !DIGlobalVariableExpression(var: !1)
!1 = distinct !DIGlobalVariable(name: "f", scope: !2, file: !3, line: 8, type: !8, isLocal: false, isDefinition: true)
!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5)
!3 = !DIFile(filename: "PR31381.c", directory: "/")
!4 = !{}
!5 = !{!0, !6}
!6 = !DIGlobalVariableExpression(var: !7)
!7 = distinct !DIGlobalVariable(name: "h", scope: !2, file: !3, line: 8, type: !8, isLocal: false, isDefinition: true)
!8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!9 = !{i32 2, !"Dwarf Version", i32 4}
!10 = !{i32 2, !"Debug Info Version", i32 3}
!11 = !{i32 1, !"PIC Level", i32 2}
!12 = distinct !DISubprogram(name: "fn4", scope: !3, file: !3, line: 31, type: !13, isLocal: false, isDefinition: true, scopeLine: 32, isOptimized: true, unit: !2, variables: !4)
!13 = !DISubroutineType(types: !14)
!14 = !{null}
!15 = !DILocalVariable(name: "p", arg: 1, scope: !16, file: !3, line: 19, type: !19)
!16 = distinct !DISubprogram(name: "fn2", scope: !3, file: !3, line: 19, type: !17, isLocal: false, isDefinition: true, scopeLine: 20, flags: DIFlagPrototyped, isOptimized: true, unit: !2, variables: !25)
!17 = !DISubroutineType(types: !18)
!18 = !{null, !19}
!19 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "S", file: !3, line: 1, size: 96, elements: !20)
!20 = !{!21, !23, !24}
!21 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !19, file: !3, line: 4, baseType: !22, size: 8, offset: 24)
!22 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
!23 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !19, file: !3, line: 5, baseType: !8, size: 32, offset: 32)
!24 = !DIDerivedType(tag: DW_TAG_member, name: "d", scope: !19, file: !3, line: 6, baseType: !8, size: 6, offset: 64, flags: DIFlagBitField, extraData: i64 64)
!25 = !{!15}
!26 = !DIExpression(DW_OP_LLVM_fragment, 72, 24)
!27 = !DILocation(line: 19, column: 20, scope: !16, inlinedAt: !28)
!28 = distinct !DILocation(line: 27, column: 3, scope: !29, inlinedAt: !30)
!29 = distinct !DISubprogram(name: "fn3", scope: !3, file: !3, line: 24, type: !13, isLocal: false, isDefinition: true, scopeLine: 25, isOptimized: true, unit: !2, variables: !4)
!30 = distinct !DILocation(line: 34, column: 7, scope: !31)
!31 = distinct !DILexicalBlock(scope: !12, file: !3, line: 33, column: 5)
!32 = !DIExpression(DW_OP_LLVM_fragment, 0, 24)
!33 = !DILocation(line: 22, column: 9, scope: !16, inlinedAt: !28)
!34 = !DILocation(line: 21, column: 3, scope: !35, inlinedAt: !28)
!35 = !DILexicalBlockFile(scope: !16, file: !3, discriminator: 2)