Skip to content

Commit 5b2f87d

Browse files
committed
[Metadata] Preserve MD_prof when merging instructions when one is missing.
Preserve branch weight metadata when merging instructions if one of the instructions is missing metadata. This is similar in behaviour to what we do today for other types of metadata such as mmra, memprof and callsite metadata.
1 parent 24e5573 commit 5b2f87d

File tree

3 files changed

+137
-6
lines changed

3 files changed

+137
-6
lines changed

llvm/lib/Transforms/Utils/Local.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3355,9 +3355,10 @@ static void combineMetadata(Instruction *K, const Instruction *J,
33553355
case LLVMContext::MD_invariant_group:
33563356
// Preserve !invariant.group in K.
33573357
break;
3358-
// Keep empty cases for mmra, memprof, and callsite to prevent them from
3359-
// being removed as unknown metadata. The actual merging is handled
3358+
// Keep empty cases for prof, mmra, memprof, and callsite to prevent them
3359+
// from being removed as unknown metadata. The actual merging is handled
33603360
// separately below.
3361+
case LLVMContext::MD_prof:
33613362
case LLVMContext::MD_mmra:
33623363
case LLVMContext::MD_memprof:
33633364
case LLVMContext::MD_callsite:
@@ -3386,10 +3387,6 @@ static void combineMetadata(Instruction *K, const Instruction *J,
33863387
if (!AAOnly)
33873388
K->setMetadata(Kind, JMD);
33883389
break;
3389-
case LLVMContext::MD_prof:
3390-
if (!AAOnly && DoesKMove)
3391-
K->setMetadata(Kind, MDNode::getMergedProfMetadata(KMD, JMD, K, J));
3392-
break;
33933390
case LLVMContext::MD_noalias_addrspace:
33943391
if (DoesKMove)
33953392
K->setMetadata(Kind,
@@ -3436,6 +3433,16 @@ static void combineMetadata(Instruction *K, const Instruction *J,
34363433
K->setMetadata(LLVMContext::MD_callsite,
34373434
MDNode::getMergedCallsiteMetadata(KCallSite, JCallSite));
34383435
}
3436+
3437+
// Merge prof metadata.
3438+
// Handle separately to support cases where only one instruction has the
3439+
// metadata.
3440+
auto JProf = J->getMetadata(LLVMContext::MD_prof);
3441+
auto KProf = K->getMetadata(LLVMContext::MD_prof);
3442+
if (!AAOnly && (JProf || KProf)) {
3443+
K->setMetadata(LLVMContext::MD_prof,
3444+
MDNode::getMergedProfMetadata(KProf, JProf, K, J));
3445+
}
34393446
}
34403447

34413448
void llvm::combineMetadataForCSE(Instruction *K, const Instruction *J,
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals --version 2
2+
; RUN: opt < %s -passes='simplifycfg<no-sink-common-insts;hoist-common-insts>' -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s --check-prefix=HOIST
3+
4+
; Test case based on C++ code with manualy annotated !prof metadata.
5+
; This is to test that when calls to 'func1' from 'if.then' block
6+
; and 'if.else' block are hoisted, the branch_weights are merged and
7+
; attached to merged call rather than dropped.
8+
;
9+
; int func1(int a, int b) ;
10+
; int func2(int a, int b) ;
11+
12+
; int func(int a, int b, bool c) {
13+
; int sum= 0;
14+
; if(c) {
15+
; sum += func1(a, b);
16+
; } else {
17+
; sum += func1(a, b);
18+
; sum -= func2(a, b);
19+
; }
20+
; return sum;
21+
; }
22+
define i32 @_Z4funciib(i32 %a, i32 %b, i1 %c) {
23+
; HOIST-LABEL: define i32 @_Z4funciib
24+
; HOIST-SAME: (i32 [[A:%.*]], i32 [[B:%.*]], i1 [[C:%.*]]) {
25+
; HOIST-NEXT: entry:
26+
; HOIST-NEXT: [[CALL:%.*]] = tail call i32 @_Z5func1ii(i32 [[A]], i32 [[B]]), !prof [[PROF0:![0-9]+]]
27+
; HOIST-NEXT: br i1 [[C]], label [[IF_END:%.*]], label [[IF_ELSE:%.*]]
28+
; HOIST: if.else:
29+
; HOIST-NEXT: [[CALL3:%.*]] = tail call i32 @_Z5func2ii(i32 [[A]], i32 [[B]])
30+
; HOIST-NEXT: [[SUB:%.*]] = sub i32 [[CALL]], [[CALL3]]
31+
; HOIST-NEXT: br label [[IF_END]]
32+
; HOIST: if.end:
33+
; HOIST-NEXT: [[SUM_0:%.*]] = phi i32 [ [[SUB]], [[IF_ELSE]] ], [ [[CALL]], [[ENTRY:%.*]] ]
34+
; HOIST-NEXT: ret i32 [[SUM_0]]
35+
;
36+
entry:
37+
br i1 %c, label %if.then, label %if.else
38+
39+
if.then: ; preds = %entry
40+
%call = tail call i32 @_Z5func1ii(i32 %a, i32 %b), !prof !0
41+
br label %if.end
42+
43+
if.else: ; preds = %entry
44+
%call1 = tail call i32 @_Z5func1ii(i32 %a, i32 %b)
45+
%call3 = tail call i32 @_Z5func2ii(i32 %a, i32 %b)
46+
%sub = sub i32 %call1, %call3
47+
br label %if.end
48+
49+
if.end: ; preds = %if.else, %if.then
50+
%sum.0 = phi i32 [ %call, %if.then ], [ %sub, %if.else ]
51+
ret i32 %sum.0
52+
}
53+
54+
declare i32 @_Z5func1ii(i32, i32)
55+
56+
declare i32 @_Z5func2ii(i32, i32)
57+
58+
!0 = !{!"branch_weights", i32 10}
59+
!1 = !{!"branch_weights", i32 90}
60+
;.
61+
; HOIST: [[PROF0]] = !{!"branch_weights", i32 10}
62+
;.
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals --version 2
2+
; RUN: opt < %s -passes='simplifycfg<sink-common-insts;no-hoist-common-insts>' -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s --check-prefix=SINK
3+
4+
5+
; Test case based on the following C++ code with manualy annotated !prof metadata.
6+
; This is to test that when calls to 'func1' from 'if.then' and 'if.else' are
7+
; sinked, the branch weights are merged and attached to sinked call.
8+
;
9+
; int func1(int a, int b) ;
10+
; int func2(int a, int b) ;
11+
12+
; int func(int a, int b, bool c) {
13+
; int sum = 0;
14+
; if (c) {
15+
; sum += func1(a,b);
16+
; } else {
17+
; b -= func2(a,b);
18+
; sum += func1(a,b);
19+
; }
20+
; return sum;
21+
; }
22+
23+
define i32 @_Z4funciib(i32 %a, i32 %b, i1 %c) {
24+
; SINK-LABEL: define i32 @_Z4funciib
25+
; SINK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]], i1 [[C:%.*]]) {
26+
; SINK-NEXT: entry:
27+
; SINK-NEXT: br i1 [[C]], label [[IF_END:%.*]], label [[IF_ELSE:%.*]]
28+
; SINK: if.else:
29+
; SINK-NEXT: [[CALL1:%.*]] = tail call i32 @_Z5func2ii(i32 [[A]], i32 [[B]])
30+
; SINK-NEXT: [[SUB:%.*]] = sub i32 [[B]], [[CALL1]]
31+
; SINK-NEXT: br label [[IF_END]]
32+
; SINK: if.end:
33+
; SINK-NEXT: [[SUB_SINK:%.*]] = phi i32 [ [[SUB]], [[IF_ELSE]] ], [ [[B]], [[ENTRY:%.*]] ]
34+
; SINK-NEXT: [[CALL2:%.*]] = tail call i32 @_Z5func1ii(i32 [[A]], i32 [[SUB_SINK]]), !prof [[PROF0:![0-9]+]]
35+
; SINK-NEXT: ret i32 [[CALL2]]
36+
;
37+
entry:
38+
br i1 %c, label %if.then, label %if.else
39+
40+
if.then: ; preds = %entry
41+
%call = tail call i32 @_Z5func1ii(i32 %a, i32 %b)
42+
br label %if.end
43+
44+
if.else: ; preds = %entry
45+
%call1 = tail call i32 @_Z5func2ii(i32 %a, i32 %b)
46+
%sub = sub i32 %b, %call1
47+
%call2 = tail call i32 @_Z5func1ii(i32 %a, i32 %sub), !prof !0
48+
br label %if.end
49+
50+
if.end: ; preds = %if.else, %if.then
51+
%sum.0 = phi i32 [ %call, %if.then ], [ %call2, %if.else ]
52+
ret i32 %sum.0
53+
}
54+
55+
declare i32 @_Z5func1ii(i32, i32)
56+
57+
declare i32 @_Z5func2ii(i32, i32)
58+
59+
!0 = !{!"branch_weights", i32 10}
60+
;.
61+
; SINK: [[PROF0]] = !{!"branch_weights", i32 10}
62+
;.

0 commit comments

Comments
 (0)