Skip to content

Commit d4d11a7

Browse files
[Transforms] Allow SimplifyCFG to fold loop latches with debug-only metadata
The transform TryToSimplifyUncondBranchFromEmptyBlock in SimplifyCFG contains a guard that is intended to prevent loop latches of nested loops that might have relevant loop metadata attached to them from being folded away, thus potentially destroying the metadata of the predecessor loop latch. This guard overprotects loop latches though, as in the case of compiling with debug information, loop metadata can be created that only contains debug location information, and doesn't carry any design intent. This commit changes the guard in such a way that metadata like this no longer protects against the loop latch from being folded away. The debug-only loop metadata is dropped in such a case.
1 parent 2df48fa commit d4d11a7

File tree

4 files changed

+106
-22
lines changed

4 files changed

+106
-22
lines changed

llvm/include/llvm/IR/Instruction.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,10 @@ class Instruction : public User,
367367
/// Return true if this instruction has any metadata attached to it.
368368
bool hasMetadata() const { return DbgLoc || Value::hasMetadata(); }
369369

370+
// Return true if this instruction contains loop metadata other than
371+
// a debug location
372+
bool hasNonDebugLocLoopMetadata() const;
373+
370374
/// Return true if this instruction has metadata attached to it other than a
371375
/// debug location.
372376
bool hasMetadataOtherThanDebugLoc() const { return Value::hasMetadata(); }

llvm/lib/IR/Instruction.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@
1212

1313
#include "llvm/IR/Instruction.h"
1414
#include "llvm/ADT/DenseSet.h"
15+
#include "llvm/ADT/STLExtras.h"
1516
#include "llvm/IR/AttributeMask.h"
1617
#include "llvm/IR/Attributes.h"
1718
#include "llvm/IR/Constants.h"
1819
#include "llvm/IR/InstrTypes.h"
1920
#include "llvm/IR/Instructions.h"
2021
#include "llvm/IR/IntrinsicInst.h"
2122
#include "llvm/IR/Intrinsics.h"
23+
#include "llvm/IR/LLVMContext.h"
2224
#include "llvm/IR/MemoryModelRelaxationAnnotations.h"
2325
#include "llvm/IR/Module.h"
2426
#include "llvm/IR/Operator.h"
@@ -461,6 +463,29 @@ bool Instruction::hasPoisonGeneratingMetadata() const {
461463
hasMetadata(LLVMContext::MD_align);
462464
}
463465

466+
bool Instruction::hasNonDebugLocLoopMetadata() const {
467+
// If there is no loop metadata at all, we also don't have
468+
// non-debug loop metadata, obviously.
469+
if (!hasMetadata(LLVMContext::MD_loop))
470+
return false;
471+
472+
// If we do have loop metadata, retrieve it.
473+
MDNode *LoopMD = getMetadata(LLVMContext::MD_loop);
474+
475+
// Check if the existing operands are debug locations. This loop
476+
// should terminate after at most three iterations. Skip
477+
// the first item because it is a self-reference.
478+
for (const MDOperand &Op : llvm::drop_begin(LoopMD->operands())) {
479+
// check for debug location type by attempting a cast.
480+
if (!dyn_cast<DILocation>(Op)) {
481+
return true;
482+
}
483+
}
484+
485+
// If we get here, then all we have is debug locations in the loop metadata.
486+
return false;
487+
}
488+
464489
void Instruction::dropPoisonGeneratingMetadata() {
465490
eraseMetadata(LLVMContext::MD_range);
466491
eraseMetadata(LLVMContext::MD_nonnull);

llvm/lib/Transforms/Utils/Local.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,10 +1279,10 @@ bool llvm::TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB,
12791279
// | for.body <---- (md2)
12801280
// |_______| |______|
12811281
if (Instruction *TI = BB->getTerminator())
1282-
if (TI->hasMetadata(LLVMContext::MD_loop))
1282+
if (TI->hasNonDebugLocLoopMetadata())
12831283
for (BasicBlock *Pred : predecessors(BB))
12841284
if (Instruction *PredTI = Pred->getTerminator())
1285-
if (PredTI->hasMetadata(LLVMContext::MD_loop))
1285+
if (PredTI->hasNonDebugLocLoopMetadata())
12861286
return false;
12871287

12881288
if (BBKillable)
@@ -1345,12 +1345,15 @@ bool llvm::TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB,
13451345
}
13461346
}
13471347

1348-
// If the unconditional branch we replaced contains llvm.loop metadata, we
1349-
// add the metadata to the branch instructions in the predecessors.
1348+
// If the unconditional branch we replaced contains non-debug llvm.loop
1349+
// metadata, we add the metadata to the branch instructions in the
1350+
// predecessors.
13501351
if (Instruction *TI = BB->getTerminator())
1351-
if (MDNode *LoopMD = TI->getMetadata(LLVMContext::MD_loop))
1352+
if (TI->hasNonDebugLocLoopMetadata()) {
1353+
MDNode *LoopMD = TI->getMetadata(LLVMContext::MD_loop);
13521354
for (BasicBlock *Pred : predecessors(BB))
13531355
Pred->getTerminator()->setMetadata(LLVMContext::MD_loop, LoopMD);
1356+
}
13541357

13551358
if (BBKillable) {
13561359
// Everything that jumped to BB now goes to Succ.

llvm/test/Transforms/SimplifyCFG/preserve-llvm-loop-metadata.ll

Lines changed: 69 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ if.then: ; preds = %while.body
2828
br label %if.end
2929

3030
; CHECK: if.then:
31-
; CHECK: br label %while.cond, !llvm.loop !0
31+
; CHECK: br label %while.cond, !llvm.loop !1
3232

3333
if.else: ; preds = %while.body
3434
%4 = load i32, ptr %count, align 4
@@ -37,10 +37,10 @@ if.else: ; preds = %while.body
3737
br label %if.end
3838

3939
; CHECK: if.else:
40-
; CHECK: br label %while.cond, !llvm.loop !0
40+
; CHECK: br label %while.cond, !llvm.loop !1
4141

4242
if.end: ; preds = %if.else, %if.then
43-
br label %while.cond, !llvm.loop !0
43+
br label %while.cond, !llvm.loop !1
4444

4545
while.end: ; preds = %while.cond
4646
ret void
@@ -74,7 +74,7 @@ entry:
7474
br label %while.cond
7575

7676
while.cond.loopexit: ; preds = %for.body
77-
br label %while.cond, !llvm.loop !2
77+
br label %while.cond, !llvm.loop !3
7878

7979
while.cond: ; preds = %while.cond.loopexit, %entry
8080
%i.0 = phi i32 [ %a, %entry ], [ %add, %while.cond.loopexit ]
@@ -96,22 +96,74 @@ for.body: ; preds = %while.body, %for.bo
9696
%1 = tail call i32 asm sideeffect "add ${0:w}, ${1:w}\0A", "=r,r,~{cc}"(i32 %0)
9797
%inc = add nuw nsw i32 %k.07, 1
9898
%cmp1 = icmp ult i32 %inc, 5
99-
br i1 %cmp1, label %for.body, label %while.cond.loopexit, !llvm.loop !4
99+
br i1 %cmp1, label %for.body, label %while.cond.loopexit, !llvm.loop !5
100100

101101
while.end: ; preds = %while.cond
102102
%sum.0.lcssa = phi i32 [ %sum.0, %while.cond ]
103103
ret i32 %sum.0.lcssa
104104
}
105105

106-
!0 = distinct !{!0, !1}
107-
!1 = !{!"llvm.loop.distribute.enable", i1 true}
108-
!2 = distinct !{!2, !3}
109-
!3 = !{!"llvm.loop.mustprogress"}
110-
!4 = distinct !{!4, !3, !5}
111-
!5 = !{!"llvm.loop.unroll.enable"}
112-
; CHECK: !0 = distinct !{!0, !1}
113-
; CHECK: !1 = !{!"llvm.loop.distribute.enable", i1 true}
114-
; CHECK: !2 = distinct !{!2, !3}
115-
; CHECK: !3 = !{!"llvm.loop.mustprogress"}
116-
; CHECK: !4 = distinct !{!4, !3, !5}
117-
; CHECK: !5 = !{!"llvm.loop.unroll.enable"}
106+
; Test that the condition tested above does not trigger when the loop metadata consists only of debug locations,
107+
; i.e.the empty loop latch `while.cond.loopexit` *will* be folded into its successor if its
108+
; predecessor blocks are also loop latches and any loop metadata attached to it consists of debug information.
109+
;
110+
define i32 @test3(i32 %a, i32 %b, i32 %step, i32 %remainder, ptr %input) !dbg !7 {
111+
entry:
112+
br label %while.cond
113+
114+
;CHECK-LABEL: @test3(
115+
;CHECK-NOT: while.cond.loopexit
116+
while.cond.loopexit: ; preds = %for.body
117+
br label %while.cond, !llvm.loop !10
118+
119+
while.cond: ; preds = %while.cond.loopexit, %entry
120+
%i.0 = phi i32 [ %a, %entry ], [ %add, %while.cond.loopexit ]
121+
%sum.0 = phi i32 [ 0, %entry ], [ %1, %while.cond.loopexit ]
122+
%sub = sub nsw i32 %b, %i.0
123+
%cmp = icmp sgt i32 %sub, %remainder
124+
br i1 %cmp, label %while.body, label %while.end
125+
126+
while.body: ; preds = %while.cond
127+
%add = add nsw i32 %i.0, %step
128+
br label %for.body
129+
130+
for.body: ; preds = %while.body, %for.body
131+
%k.07 = phi i32 [ 0, %while.body ], [ %inc, %for.body ]
132+
%add2 = add nsw i32 %k.07, %add
133+
%idxprom = sext i32 %add2 to i64
134+
%arrayidx = getelementptr inbounds i32, ptr %input, i64 %idxprom
135+
%0 = load i32, ptr %arrayidx, align 4
136+
%1 = tail call i32 asm sideeffect "add ${0:w}, ${1:w}\0A", "=r,r,~{cc}"(i32 %0)
137+
%inc = add nuw nsw i32 %k.07, 1
138+
%cmp1 = icmp ult i32 %inc, 5
139+
br i1 %cmp1, label %for.body, label %while.cond.loopexit, !llvm.loop !5
140+
141+
while.end: ; preds = %while.cond
142+
%sum.0.lcssa = phi i32 [ %sum.0, %while.cond ]
143+
ret i32 %sum.0.lcssa
144+
}
145+
146+
!llvm.module.flags = !{!0}
147+
148+
!0 = !{i32 2, !"Debug Info Version", i32 3}
149+
!1 = distinct !{!1, !2}
150+
!2 = !{!"llvm.loop.distribute.enable", i1 true}
151+
!3 = distinct !{!3, !4}
152+
!4 = !{!"llvm.loop.mustprogress"}
153+
!5 = distinct !{!5, !4, !6}
154+
!6 = !{!"llvm.loop.unroll.enable"}
155+
!7 = distinct !DISubprogram(name: "test3", scope: !8, file: !8, spFlags: DISPFlagDefinition, unit: !9)
156+
!8 = !DIFile(filename: "preserve-llvm-loop-metadata.ll", directory: "/")
157+
!9 = distinct !DICompileUnit(language: DW_LANG_C99, file: !8, isOptimized: false, runtimeVersion: 0, emissionKind: NoDebug)
158+
!10 = distinct !{!10, !11, !13}
159+
!11 = !DILocation(line: 8, column: 4, scope: !12)
160+
!12 = distinct !DILexicalBlock(scope: !7, file: !8, line: 8, column: 2)
161+
!13 = !DILocation(line: 9, column: 23, scope: !12)
162+
163+
; CHECK: !1 = distinct !{!1, !2}
164+
; CHECK: !2 = !{!"llvm.loop.distribute.enable", i1 true}
165+
; CHECK: !3 = distinct !{!3, !4}
166+
; CHECK: !4 = !{!"llvm.loop.mustprogress"}
167+
; CHECK: !5 = distinct !{!5, !4, !6}
168+
; CHECK: !6 = !{!"llvm.loop.unroll.enable"}
169+
; CHECK-NOT: !10 = distinct !{!10, !11, !13}

0 commit comments

Comments
 (0)