llvm.org GIT mirror llvm / ed2ca70
Fix for http://llvm.org/bugs/show_bug.cgi?id=18590 This patch fixes the bug in peephole optimization that folds a load which defines one vreg into the one and only use of that vreg. With debug info, a DBG_VALUE that referenced the vreg considered to be a use, preventing the optimization. The fix is to ignore DBG_VALUE's during the optimization, and undef a DBG_VALUE that references a vreg that gets removed. Patch by Trevor Smigiel! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203829 91177308-0d34-0410-b5e6-96231b3b80d8 Ekaterina Romanova 5 years ago
5 changed file(s) with 114 addition(s) and 14 deletion(s). Raw diff Collapse all Expand all
509509 return Hint.first ? 0 : Hint.second;
510510 }
511511
512 /// markUsesInDebugValueAsUndef - Mark every DBG_VALUE referencing the
513 /// specified register as undefined which causes the DBG_VALUE to be
514 /// deleted during LiveDebugVariables analysis.
515 void markUsesInDebugValueAsUndef(unsigned Reg) const;
512516
513517 //===--------------------------------------------------------------------===//
514518 // Physical Register Use Info
126126 unsigned Reg = MO.getReg();
127127 if (!TargetRegisterInfo::isVirtualRegister(Reg))
128128 continue;
129 MachineRegisterInfo::use_iterator nextI;
130 for (MachineRegisterInfo::use_iterator I = MRI->use_begin(Reg),
131 E = MRI->use_end(); I!=E; I=nextI) {
132 nextI = std::next(I); // I is invalidated by the setReg
133 MachineOperand& Use = I.getOperand();
134 MachineInstr *UseMI = Use.getParent();
135 if (UseMI==MI)
136 continue;
137 assert(Use.isDebug());
138 UseMI->getOperand(0).setReg(0U);
139 }
129 MRI->markUsesInDebugValueAsUndef(Reg);
140130 }
141131 AnyChanges = true;
142132 MI->eraseFromParent();
413413 return false;
414414 return true;
415415 }
416
417 /// markUsesInDebugValueAsUndef - Mark every DBG_VALUE referencing the
418 /// specified register as undefined which causes the DBG_VALUE to be
419 /// deleted during LiveDebugVariables analysis.
420 void MachineRegisterInfo::markUsesInDebugValueAsUndef(unsigned Reg) const {
421 // Mark any DBG_VALUE that uses Reg as undef (but don't delete it.)
422 MachineRegisterInfo::use_iterator nextI;
423 for (use_iterator I = use_begin(Reg), E = use_end(); I != E; I = nextI) {
424 nextI = std::next(I); // I is invalidated by the setReg
425 MachineOperand& Use = I.getOperand();
426 MachineInstr *UseMI = Use.getParent();
427 if (UseMI->isDebugValue())
428 UseMI->getOperand(0).setReg(0U);
429 }
430 }
504504 return false;
505505
506506 unsigned Reg = MI->getOperand(0).getReg();
507 // To reduce compilation time, we check MRI->hasOneUse when inserting
507 // To reduce compilation time, we check MRI->hasOneNonDBGUse when inserting
508508 // loads. It should be checked when processing uses of the load, since
509509 // uses can be removed during peephole.
510510 if (!MI->getOperand(0).getSubReg() &&
511511 TargetRegisterInfo::isVirtualRegister(Reg) &&
512 MRI->hasOneUse(Reg)) {
512 MRI->hasOneNonDBGUse(Reg)) {
513513 FoldAsLoadDefReg = Reg;
514514 return true;
515515 }
593593 ++MII;
594594 LocalMIs.insert(MI);
595595
596 // Skip debug values. They should not affect this peephole optimization.
597 if (MI->isDebugValue())
598 continue;
599
596600 // If there exists an instruction which belongs to the following
597601 // categories, we will discard the load candidate.
598602 if (MI->isPosition() || MI->isPHI() || MI->isImplicitDef() ||
599 MI->isKill() || MI->isInlineAsm() || MI->isDebugValue() ||
603 MI->isKill() || MI->isInlineAsm() ||
600604 MI->hasUnmodeledSideEffects()) {
601605 FoldAsLoadDefReg = 0;
602606 continue;
632636 if (!isLoadFoldable(MI, FoldAsLoadDefReg) && FoldAsLoadDefReg) {
633637 // We need to fold load after optimizeCmpInstr, since optimizeCmpInstr
634638 // can enable folding by converting SUB to CMP.
639 // Save FoldAsLoadDefReg because optimizeLoadInstr() resets it and we
640 // need it for markUsesInDebugValueAsUndef().
641 unsigned FoldedReg = FoldAsLoadDefReg;
635642 MachineInstr *DefMI = 0;
636643 MachineInstr *FoldMI = TII->optimizeLoadInstr(MI, MRI,
637644 FoldAsLoadDefReg, DefMI);
644651 LocalMIs.insert(FoldMI);
645652 MI->eraseFromParent();
646653 DefMI->eraseFromParent();
654 MRI->markUsesInDebugValueAsUndef(FoldedReg);
647655 ++NumLoadFold;
648656
649657 // MI is replaced with FoldMI.
0 ; RUN: llc < %s -march=x86-64 | FileCheck %s
1
2 ; The Peephole optimizer should fold the load into the cmp even with debug info.
3 ; CHECK-LABEL: _ZN3Foo3batEv
4 ; CHECK-NOT: movq pfoo
5 ; CHECK: cmpq {{%[a-z]+}}, pfoo(%rip)
6 ;
7 ; CHECK-LABEL: _Z3bazv
8 ; CHECK-NOT: movq wibble2
9 ; CHECK: cmpq {{%[a-z]+}}, wibble2(%rip)
10
11 ; Regenerate test with this command:
12 ; clang -emit-llvm -S -O2 -g
13 ; from this source:
14 ; struct Foo {
15 ; bool bat();
16 ; bool operator==(Foo &arg) { return (this == &arg); }
17 ; };
18 ; Foo *pfoo;
19 ; bool Foo::bat() { return (*this == *pfoo); }
20 ;
21 ; struct Wibble {
22 ; int x;
23 ; } *wibble1, *wibble2;
24 ; struct Flibble {
25 ; void bar(Wibble *c) {
26 ; if (c < wibble2)
27 ; wibble2 = 0;
28 ; c->x = 0;
29 ; }
30 ; } flibble;
31 ; void baz() { flibble.bar(wibble1); }
32
33 %struct.Foo = type { i8 }
34 %struct.Wibble = type { i32 }
35 %struct.Flibble = type { i8 }
36
37 @pfoo = global %struct.Foo* null, align 8
38 @wibble1 = global %struct.Wibble* null, align 8
39 @wibble2 = global %struct.Wibble* null, align 8
40 @flibble = global %struct.Flibble zeroinitializer, align 1
41
42 ; Function Attrs: nounwind readonly uwtable
43 define zeroext i1 @_ZN3Foo3batEv(%struct.Foo* %this) #0 align 2 {
44 entry:
45 %0 = load %struct.Foo** @pfoo, align 8
46 tail call void @llvm.dbg.value(metadata !{%struct.Foo* %0}, i64 0, metadata !62)
47 %cmp.i = icmp eq %struct.Foo* %0, %this
48 ret i1 %cmp.i
49 }
50
51 ; Function Attrs: nounwind uwtable
52 define void @_Z3bazv() #1 {
53 entry:
54 %0 = load %struct.Wibble** @wibble1, align 8
55 tail call void @llvm.dbg.value(metadata !64, i64 0, metadata !65)
56 %1 = load %struct.Wibble** @wibble2, align 8
57 %cmp.i = icmp ugt %struct.Wibble* %1, %0
58 br i1 %cmp.i, label %if.then.i, label %_ZN7Flibble3barEP6Wibble.exit
59
60 if.then.i: ; preds = %entry
61 store %struct.Wibble* null, %struct.Wibble** @wibble2, align 8
62 br label %_ZN7Flibble3barEP6Wibble.exit
63
64 _ZN7Flibble3barEP6Wibble.exit: ; preds = %entry, %if.then.i
65 %x.i = getelementptr inbounds %struct.Wibble* %0, i64 0, i32 0
66 store i32 0, i32* %x.i, align 4
67 ret void
68 }
69
70 ; Function Attrs: nounwind readnone
71 declare void @llvm.dbg.value(metadata, i64, metadata) #2
72
73 attributes #0 = { nounwind readonly uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-frame-pointer-elim-non-leaf"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" }
74 attributes #1 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-frame-pointer-elim-non-leaf"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" }
75 attributes #2 = { nounwind readnone }
76
77
78 !17 = metadata !{i32 786448, null, null, null, i32 0, i64 0, i64 0, i64 0, i32 0, null} ; [ DW_TAG_reference_type ] [line 0, size 0, align 0, offset 0] [from Foo]
79 !45 = metadata !{i32 786447, null, null, metadata !"", i32 0, i64 64, i64 64, i64 0, i32 0, null} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from Flibble]
80 !62 = metadata !{i32 786689, null, metadata !"arg", null, i32 33554436, metadata !17, i32 0, null} ; [ DW_TAG_arg_variable ] [arg] [line 4]
81 !64 = metadata !{%struct.Flibble* undef}
82 !65 = metadata !{i32 786689, null, metadata !"this", null, i32 16777229, metadata !45, i32 1088, null} ; [ DW_TAG_arg_variable ] [this] [line 13]