[llvm] 92068d6 - [SimplifyCFG] add tests for branch cond merging with prof metadata; NFC
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Thu Mar 18 12:39:57 PDT 2021
Author: Sanjay Patel
Date: 2021-03-18T15:39:50-04:00
New Revision: 92068d6c31a45315402e4cefd3ec1c340090b41d
URL: https://github.com/llvm/llvm-project/commit/92068d6c31a45315402e4cefd3ec1c340090b41d
DIFF: https://github.com/llvm/llvm-project/commit/92068d6c31a45315402e4cefd3ec1c340090b41d.diff
LOG: [SimplifyCFG] add tests for branch cond merging with prof metadata; NFC
See PR49336.
Added:
Modified:
llvm/test/Transforms/SimplifyCFG/preserve-branchweights.ll
Removed:
################################################################################
diff --git a/llvm/test/Transforms/SimplifyCFG/preserve-branchweights.ll b/llvm/test/Transforms/SimplifyCFG/preserve-branchweights.ll
index 25106d435cc7..657accc9b6c2 100644
--- a/llvm/test/Transforms/SimplifyCFG/preserve-branchweights.ll
+++ b/llvm/test/Transforms/SimplifyCFG/preserve-branchweights.ll
@@ -318,10 +318,10 @@ define void @test8(i64 %x, i64 %y) nounwind {
; CHECK-NEXT: [[LT:%.*]] = icmp slt i64 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: br i1 [[LT]], label [[A:%.*]], label [[B:%.*]], !prof !7
; CHECK: a:
-; CHECK-NEXT: call void @helper(i32 0) [[ATTR1:#.*]]
+; CHECK-NEXT: call void @helper(i32 0) #[[ATTR1:[0-9]+]]
; CHECK-NEXT: ret void
; CHECK: b:
-; CHECK-NEXT: call void @helper(i32 1) [[ATTR1]]
+; CHECK-NEXT: call void @helper(i32 1) #[[ATTR1]]
; CHECK-NEXT: ret void
;
entry:
@@ -355,14 +355,14 @@ define i1 @test9(i32 %x, i32 %y) nounwind {
; CHECK-NEXT: i32 92, label [[END]]
; CHECK-NEXT: ], !prof !8
; CHECK: a:
-; CHECK-NEXT: call void @helper(i32 0) [[ATTR1]]
+; CHECK-NEXT: call void @helper(i32 0) #[[ATTR1]]
; CHECK-NEXT: [[RETA:%.*]] = icmp slt i32 [[X]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[RETA]]
; CHECK: bees:
; CHECK-NEXT: br label [[END]]
; CHECK: end:
; CHECK-NEXT: [[RET:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ false, [[BEES]] ], [ true, [[ENTRY]] ], [ true, [[ENTRY]] ]
-; CHECK-NEXT: call void @helper(i32 2) [[ATTR1]]
+; CHECK-NEXT: call void @helper(i32 2) #[[ATTR1]]
; CHECK-NEXT: ret i1 [[RET]]
;
entry:
@@ -394,10 +394,10 @@ define void @test10(i32 %x) nounwind readnone ssp noredzone {
; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i32 [[X_OFF]], 3
; CHECK-NEXT: br i1 [[SWITCH]], label [[LOR_END:%.*]], label [[LOR_RHS:%.*]], !prof !9
; CHECK: lor.rhs:
-; CHECK-NEXT: call void @helper(i32 1) [[ATTR1]]
+; CHECK-NEXT: call void @helper(i32 1) #[[ATTR1]]
; CHECK-NEXT: ret void
; CHECK: lor.end:
-; CHECK-NEXT: call void @helper(i32 0) [[ATTR1]]
+; CHECK-NEXT: call void @helper(i32 0) #[[ATTR1]]
; CHECK-NEXT: ret void
;
entry:
@@ -424,10 +424,10 @@ define void @test11(i32 %x) nounwind {
; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[I]], 24
; CHECK-NEXT: br i1 [[COND]], label [[C:%.*]], label [[A:%.*]], !prof !10
; CHECK: a:
-; CHECK-NEXT: call void @helper(i32 0) [[ATTR1]]
+; CHECK-NEXT: call void @helper(i32 0) #[[ATTR1]]
; CHECK-NEXT: ret void
; CHECK: c:
-; CHECK-NEXT: call void @helper(i32 2) [[ATTR1]]
+; CHECK-NEXT: call void @helper(i32 2) #[[ATTR1]]
; CHECK-NEXT: ret void
;
%i = shl i32 %x, 1
@@ -472,7 +472,7 @@ sw.epilog:
define void @test13(i32 %x) nounwind {
; CHECK-LABEL: @test13(
; CHECK-NEXT: entry:
-; CHECK-NEXT: call void @helper(i32 0) [[ATTR1]]
+; CHECK-NEXT: call void @helper(i32 0) #[[ATTR1]]
; CHECK-NEXT: ret void
;
entry:
@@ -636,6 +636,400 @@ exit:
ret i32 %outval
}
+; FIXME: Merging the icmps with logic-op defeats the purpose of the metadata.
+; We can't tell which condition is expensive if they are combined.
+
+define void @or_icmps_harmful(i32 %x, i32 %y, i8* %p) {
+; CHECK-LABEL: @or_icmps_harmful(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[EXPECTED_TRUE:%.*]] = icmp sgt i32 [[X:%.*]], -1
+; CHECK-NEXT: [[EXPENSIVE:%.*]] = icmp eq i32 [[Y:%.*]], 0
+; CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[EXPECTED_TRUE]], [[EXPENSIVE]]
+; CHECK-NEXT: br i1 [[OR_COND]], label [[EXIT:%.*]], label [[FALSE:%.*]], !prof !19
+; CHECK: false:
+; CHECK-NEXT: store i8 42, i8* [[P:%.*]], align 1
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ %expected_true = icmp sgt i32 %x, -1
+ br i1 %expected_true, label %exit, label %rare, !prof !15
+
+rare:
+ %expensive = icmp eq i32 %y, 0
+ br i1 %expensive, label %exit, label %false
+
+false:
+ store i8 42, i8* %p, align 1
+ br label %exit
+
+exit:
+ ret void
+}
+
+; FIXME: Merging the icmps with logic-op defeats the purpose of the metadata.
+; We can't tell which condition is expensive if they are combined.
+
+define void @or_icmps_harmful_inverted(i32 %x, i32 %y, i8* %p) {
+; CHECK-LABEL: @or_icmps_harmful_inverted(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[EXPECTED_FALSE:%.*]] = icmp sle i32 [[X:%.*]], -1
+; CHECK-NEXT: [[EXPENSIVE:%.*]] = icmp eq i32 [[Y:%.*]], 0
+; CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[EXPECTED_FALSE]], [[EXPENSIVE]]
+; CHECK-NEXT: br i1 [[OR_COND]], label [[EXIT:%.*]], label [[FALSE:%.*]], !prof !19
+; CHECK: false:
+; CHECK-NEXT: store i8 42, i8* [[P:%.*]], align 1
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ %expected_false = icmp sgt i32 %x, -1
+ br i1 %expected_false, label %rare, label %exit, !prof !16
+
+rare:
+ %expensive = icmp eq i32 %y, 0
+ br i1 %expensive, label %exit, label %false
+
+false:
+ store i8 42, i8* %p, align 1
+ br label %exit
+
+exit:
+ ret void
+}
+
+; The probability threshold is set by a builtin_expect setting.
+
+define void @or_icmps_not_that_harmful(i32 %x, i32 %y, i8* %p) {
+; CHECK-LABEL: @or_icmps_not_that_harmful(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[EXPECTED_TRUE:%.*]] = icmp sgt i32 [[X:%.*]], -1
+; CHECK-NEXT: [[EXPENSIVE:%.*]] = icmp eq i32 [[Y:%.*]], 0
+; CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[EXPECTED_TRUE]], [[EXPENSIVE]]
+; CHECK-NEXT: br i1 [[OR_COND]], label [[EXIT:%.*]], label [[FALSE:%.*]], !prof !20
+; CHECK: false:
+; CHECK-NEXT: store i8 42, i8* [[P:%.*]], align 1
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ %expected_true = icmp sgt i32 %x, -1
+ br i1 %expected_true, label %exit, label %rare, !prof !17
+
+rare:
+ %expensive = icmp eq i32 %y, 0
+ br i1 %expensive, label %exit, label %false
+
+false:
+ store i8 42, i8* %p, align 1
+ br label %exit
+
+exit:
+ ret void
+}
+
+define void @or_icmps_not_that_harmful_inverted(i32 %x, i32 %y, i8* %p) {
+; CHECK-LABEL: @or_icmps_not_that_harmful_inverted(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[EXPECTED_TRUE:%.*]] = icmp sgt i32 [[X:%.*]], -1
+; CHECK-NEXT: [[EXPENSIVE:%.*]] = icmp eq i32 [[Y:%.*]], 0
+; CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[EXPECTED_TRUE]], [[EXPENSIVE]]
+; CHECK-NEXT: br i1 [[OR_COND]], label [[EXIT:%.*]], label [[FALSE:%.*]], !prof !21
+; CHECK: false:
+; CHECK-NEXT: store i8 42, i8* [[P:%.*]], align 1
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ %expected_true = icmp sgt i32 %x, -1
+ br i1 %expected_true, label %exit, label %rare, !prof !18
+
+rare:
+ %expensive = icmp eq i32 %y, 0
+ br i1 %expensive, label %exit, label %false
+
+false:
+ store i8 42, i8* %p, align 1
+ br label %exit
+
+exit:
+ ret void
+}
+
+define void @or_icmps_useful(i32 %x, i32 %y, i8* %p) {
+; CHECK-LABEL: @or_icmps_useful(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[EXPECTED_TRUE:%.*]] = icmp sle i32 [[X:%.*]], -1
+; CHECK-NEXT: [[EXPENSIVE:%.*]] = icmp eq i32 [[Y:%.*]], 0
+; CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[EXPECTED_TRUE]], [[EXPENSIVE]]
+; CHECK-NEXT: br i1 [[OR_COND]], label [[EXIT:%.*]], label [[FALSE:%.*]], !prof !22
+; CHECK: false:
+; CHECK-NEXT: store i8 42, i8* [[P:%.*]], align 1
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ %expected_true = icmp sgt i32 %x, -1
+ br i1 %expected_true, label %likely, label %exit, !prof !15
+
+likely:
+ %expensive = icmp eq i32 %y, 0
+ br i1 %expensive, label %exit, label %false
+
+false:
+ store i8 42, i8* %p, align 1
+ br label %exit
+
+exit:
+ ret void
+}
+
+define void @or_icmps_useful_inverted(i32 %x, i32 %y, i8* %p) {
+; CHECK-LABEL: @or_icmps_useful_inverted(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[EXPECTED_FALSE:%.*]] = icmp sgt i32 [[X:%.*]], -1
+; CHECK-NEXT: [[EXPENSIVE:%.*]] = icmp eq i32 [[Y:%.*]], 0
+; CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[EXPECTED_FALSE]], [[EXPENSIVE]]
+; CHECK-NEXT: br i1 [[OR_COND]], label [[EXIT:%.*]], label [[FALSE:%.*]], !prof !22
+; CHECK: false:
+; CHECK-NEXT: store i8 42, i8* [[P:%.*]], align 1
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ %expected_false = icmp sgt i32 %x, -1
+ br i1 %expected_false, label %exit, label %likely, !prof !16
+
+likely:
+ %expensive = icmp eq i32 %y, 0
+ br i1 %expensive, label %exit, label %false
+
+false:
+ store i8 42, i8* %p, align 1
+ br label %exit
+
+exit:
+ ret void
+}
+
+; Don't crash processing degenerate metadata.
+
+define void @or_icmps_empty_metadata(i32 %x, i32 %y, i8* %p) {
+; CHECK-LABEL: @or_icmps_empty_metadata(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[EXPECTED_TRUE:%.*]] = icmp sgt i32 [[X:%.*]], -1
+; CHECK-NEXT: [[EXPENSIVE:%.*]] = icmp eq i32 [[Y:%.*]], 0
+; CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[EXPECTED_TRUE]], [[EXPENSIVE]]
+; CHECK-NEXT: br i1 [[OR_COND]], label [[EXIT:%.*]], label [[MORE_RARE:%.*]]
+; CHECK: more_rare:
+; CHECK-NEXT: store i8 42, i8* [[P:%.*]], align 1
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ %expected_true = icmp sgt i32 %x, -1
+ br i1 %expected_true, label %exit, label %rare, !prof !19
+
+rare:
+ %expensive = icmp eq i32 %y, 0
+ br i1 %expensive, label %exit, label %more_rare
+
+more_rare:
+ store i8 42, i8* %p, align 1
+ br label %exit
+
+exit:
+ ret void
+}
+
+; FIXME: Merging the icmps with logic-op defeats the purpose of the metadata.
+; We can't tell which condition is expensive if they are combined.
+
+define void @and_icmps_harmful(i32 %x, i32 %y, i8* %p) {
+; CHECK-LABEL: @and_icmps_harmful(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[EXPECTED_FALSE:%.*]] = icmp sgt i32 [[X:%.*]], -1
+; CHECK-NEXT: [[EXPENSIVE:%.*]] = icmp eq i32 [[Y:%.*]], 0
+; CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[EXPECTED_FALSE]], [[EXPENSIVE]]
+; CHECK-NEXT: br i1 [[OR_COND]], label [[FALSE:%.*]], label [[EXIT:%.*]], !prof !23
+; CHECK: false:
+; CHECK-NEXT: store i8 42, i8* [[P:%.*]], align 1
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ %expected_false = icmp sgt i32 %x, -1
+ br i1 %expected_false, label %rare, label %exit, !prof !16
+
+rare:
+ %expensive = icmp eq i32 %y, 0
+ br i1 %expensive, label %false, label %exit
+
+false:
+ store i8 42, i8* %p, align 1
+ br label %exit
+
+exit:
+ ret void
+}
+
+; FIXME: Merging the icmps with logic-op defeats the purpose of the metadata.
+; We can't tell which condition is expensive if they are combined.
+
+define void @and_icmps_harmful_inverted(i32 %x, i32 %y, i8* %p) {
+; CHECK-LABEL: @and_icmps_harmful_inverted(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[EXPECTED_TRUE:%.*]] = icmp sle i32 [[X:%.*]], -1
+; CHECK-NEXT: [[EXPENSIVE:%.*]] = icmp eq i32 [[Y:%.*]], 0
+; CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[EXPECTED_TRUE]], [[EXPENSIVE]]
+; CHECK-NEXT: br i1 [[OR_COND]], label [[FALSE:%.*]], label [[EXIT:%.*]], !prof !23
+; CHECK: false:
+; CHECK-NEXT: store i8 42, i8* [[P:%.*]], align 1
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ %expected_true = icmp sgt i32 %x, -1
+ br i1 %expected_true, label %exit, label %rare, !prof !15
+
+rare:
+ %expensive = icmp eq i32 %y, 0
+ br i1 %expensive, label %false, label %exit
+
+false:
+ store i8 42, i8* %p, align 1
+ br label %exit
+
+exit:
+ ret void
+}
+
+define void @and_icmps_not_that_harmful(i32 %x, i32 %y, i8* %p) {
+; CHECK-LABEL: @and_icmps_not_that_harmful(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[EXPECTED_FALSE:%.*]] = icmp sgt i32 [[X:%.*]], -1
+; CHECK-NEXT: [[EXPENSIVE:%.*]] = icmp eq i32 [[Y:%.*]], 0
+; CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[EXPECTED_FALSE]], [[EXPENSIVE]]
+; CHECK-NEXT: br i1 [[OR_COND]], label [[FALSE:%.*]], label [[EXIT:%.*]], !prof !24
+; CHECK: false:
+; CHECK-NEXT: store i8 42, i8* [[P:%.*]], align 1
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ %expected_false = icmp sgt i32 %x, -1
+ br i1 %expected_false, label %rare, label %exit, !prof !18
+
+rare:
+ %expensive = icmp eq i32 %y, 0
+ br i1 %expensive, label %false, label %exit
+
+false:
+ store i8 42, i8* %p, align 1
+ br label %exit
+
+exit:
+ ret void
+}
+
+define void @and_icmps_not_that_harmful_inverted(i32 %x, i32 %y, i8* %p) {
+; CHECK-LABEL: @and_icmps_not_that_harmful_inverted(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[EXPECTED_TRUE:%.*]] = icmp sle i32 [[X:%.*]], -1
+; CHECK-NEXT: [[EXPENSIVE:%.*]] = icmp eq i32 [[Y:%.*]], 0
+; CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[EXPECTED_TRUE]], [[EXPENSIVE]]
+; CHECK-NEXT: br i1 [[OR_COND]], label [[FALSE:%.*]], label [[EXIT:%.*]], !prof !24
+; CHECK: false:
+; CHECK-NEXT: store i8 42, i8* [[P:%.*]], align 1
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ %expected_true = icmp sgt i32 %x, -1
+ br i1 %expected_true, label %exit, label %rare, !prof !17
+
+rare:
+ %expensive = icmp eq i32 %y, 0
+ br i1 %expensive, label %false, label %exit
+
+false:
+ store i8 42, i8* %p, align 1
+ br label %exit
+
+exit:
+ ret void
+}
+
+define void @and_icmps_useful(i32 %x, i32 %y, i8* %p) {
+; CHECK-LABEL: @and_icmps_useful(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[EXPECTED_TRUE:%.*]] = icmp sgt i32 [[X:%.*]], -1
+; CHECK-NEXT: [[EXPENSIVE:%.*]] = icmp eq i32 [[Y:%.*]], 0
+; CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[EXPECTED_TRUE]], [[EXPENSIVE]]
+; CHECK-NEXT: br i1 [[OR_COND]], label [[FALSE:%.*]], label [[EXIT:%.*]], !prof !25
+; CHECK: false:
+; CHECK-NEXT: store i8 42, i8* [[P:%.*]], align 1
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ %expected_true = icmp sgt i32 %x, -1
+ br i1 %expected_true, label %likely, label %exit, !prof !15
+
+likely:
+ %expensive = icmp eq i32 %y, 0
+ br i1 %expensive, label %false, label %exit
+
+false:
+ store i8 42, i8* %p, align 1
+ br label %exit
+
+exit:
+ ret void
+}
+
+define void @and_icmps_useful_inverted(i32 %x, i32 %y, i8* %p) {
+; CHECK-LABEL: @and_icmps_useful_inverted(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[EXPECTED_FALSE:%.*]] = icmp sle i32 [[X:%.*]], -1
+; CHECK-NEXT: [[EXPENSIVE:%.*]] = icmp eq i32 [[Y:%.*]], 0
+; CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[EXPECTED_FALSE]], [[EXPENSIVE]]
+; CHECK-NEXT: br i1 [[OR_COND]], label [[FALSE:%.*]], label [[EXIT:%.*]], !prof !25
+; CHECK: false:
+; CHECK-NEXT: store i8 42, i8* [[P:%.*]], align 1
+; CHECK-NEXT: br label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ %expected_false = icmp sgt i32 %x, -1
+ br i1 %expected_false, label %exit, label %likely, !prof !16
+
+likely:
+ %expensive = icmp eq i32 %y, 0
+ br i1 %expensive, label %false, label %exit
+
+false:
+ store i8 42, i8* %p, align 1
+ br label %exit
+
+exit:
+ ret void
+}
+
+
!0 = !{!"branch_weights", i32 3, i32 5}
!1 = !{!"branch_weights", i32 1, i32 1}
!2 = !{!"branch_weights", i32 1, i32 2}
@@ -651,6 +1045,11 @@ exit:
!12 = !{!"these_are_not_the_branch_weights_you_are_looking_for", i32 3, i32 5}
!13 = !{!"branch_weights", i32 2, i32 3}
!14 = !{!"branch_weights", i32 4, i32 7}
+!15 = !{!"branch_weights", i32 2000, i32 1}
+!16 = !{!"branch_weights", i32 1, i32 2000}
+!17 = !{!"branch_weights", i32 1999, i32 1}
+!18 = !{!"branch_weights", i32 1, i32 1999}
+!19 = !{!"branch_weights", i32 0, i32 0}
; CHECK: !0 = !{!"branch_weights", i32 5, i32 11}
; CHECK: !1 = !{!"branch_weights", i32 1, i32 3}
More information about the llvm-commits
mailing list