-
Notifications
You must be signed in to change notification settings - Fork 15k
[FnSpecialization] Only accept codesize savings if strictly greater than the minimum amount #164867
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
For some tests, need to explicity list the MinCodeSizeSavings since they were relying on the bug for their behavior. Added new test that clearly demonstrates the behavior and will change with the fix.
…han the minimum amount If the knob for minimum code size is turned down low enough, for small functions: `MinCodeSizeSavings * FuncSize / 100` will evaluate to `0`, and then with strict less than we will accept Specialization that doesn't lead to any benefit.
|
@llvm/pr-subscribers-function-specialization @llvm/pr-subscribers-llvm-transforms Author: Ryan Buchner (bababuck) ChangesWhen When MinCodeSizeSavings is set by default to 20, so if I don't think this is generally an issue in the wild since Prior to this change, Full diff: https://github.com/llvm/llvm-project/pull/164867.diff 5 Files Affected:
diff --git a/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp b/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp
index 150a2dc5d48e2..6d4b2fb7e0065 100644
--- a/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp
+++ b/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp
@@ -995,7 +995,7 @@ bool FunctionSpecializer::findSpecializations(Function *F, unsigned FuncSize,
<< (CodeSizeSavings * 100 / FuncSize) << "%)}\n");
// Minimum codesize savings.
- if (CodeSizeSavings < MinCodeSizeSavings * FuncSize / 100)
+ if (CodeSizeSavings <= MinCodeSizeSavings * FuncSize / 100)
return false;
// Lazily compute the Latency, to avoid unnecessarily computing BFI.
diff --git a/llvm/test/Transforms/FunctionSpecialization/dead-gv-load.ll b/llvm/test/Transforms/FunctionSpecialization/dead-gv-load.ll
index 134a79d349035..45e41bd1bdce9 100644
--- a/llvm/test/Transforms/FunctionSpecialization/dead-gv-load.ll
+++ b/llvm/test/Transforms/FunctionSpecialization/dead-gv-load.ll
@@ -1,5 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
-; RUN: opt -passes=ipsccp --funcspec-min-function-size=1 -S < %s | FileCheck %s
+; RUN: opt -passes=ipsccp --funcspec-min-function-size=1 \
+; RUN: -funcspec-min-codesize-savings=1 -S < %s | FileCheck %s
@gv = internal global ptr null
diff --git a/llvm/test/Transforms/FunctionSpecialization/maxgrowth.ll b/llvm/test/Transforms/FunctionSpecialization/maxgrowth.ll
index 82d1f7ae4a6e1..c07948489dd5e 100644
--- a/llvm/test/Transforms/FunctionSpecialization/maxgrowth.ll
+++ b/llvm/test/Transforms/FunctionSpecialization/maxgrowth.ll
@@ -1,7 +1,7 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 5
; RUN: opt -passes="ipsccp<func-spec>" -funcspec-min-function-size=1 \
; RUN: -funcspec-for-literal-constant=true \
-; RUN: -funcspec-min-codesize-savings=50 \
+; RUN: -funcspec-min-codesize-savings=1 \
; RUN: -funcspec-min-latency-savings=50 \
; RUN: -funcspec-max-codesize-growth=1 \
; RUN: -S < %s | FileCheck %s
diff --git a/llvm/test/Transforms/FunctionSpecialization/min-codesize-savings.ll b/llvm/test/Transforms/FunctionSpecialization/min-codesize-savings.ll
new file mode 100644
index 0000000000000..4547e0e009852
--- /dev/null
+++ b/llvm/test/Transforms/FunctionSpecialization/min-codesize-savings.ll
@@ -0,0 +1,28 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -passes=ipsccp --funcspec-min-function-size=0 -S < %s | FileCheck %s
+
+; Call to unprofitable_spec should not specialize since no folding can occur for the add
+; instruction as only 1 of the values is know. The score for this specialization will be 0.
+define i32 @main(i32 %y) {
+; CHECK-LABEL: define i32 @main(
+; CHECK-SAME: i32 [[Y:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[SPEC:%.*]] = call i32 @unprofitable_spec(i32 1, i32 [[Y]])
+; CHECK-NEXT: ret i32 [[SPEC]]
+;
+entry:
+ %spec = call i32 @unprofitable_spec(i32 1, i32 %y)
+ ret i32 %spec
+}
+
+define i32 @unprofitable_spec(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @unprofitable_spec(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], [[Y]]
+; CHECK-NEXT: ret i32 [[ADD]]
+;
+entry:
+ %add = add i32 %x, %y
+ ret i32 %add
+}
diff --git a/llvm/test/Transforms/FunctionSpecialization/recursive-penalty.ll b/llvm/test/Transforms/FunctionSpecialization/recursive-penalty.ll
index fc17387dec94d..409e7b870355d 100644
--- a/llvm/test/Transforms/FunctionSpecialization/recursive-penalty.ll
+++ b/llvm/test/Transforms/FunctionSpecialization/recursive-penalty.ll
@@ -1,7 +1,8 @@
; REQUIRES: asserts
; RUN: opt -passes="ipsccp<func-spec>,inline,instcombine,simplifycfg" -S \
; RUN: -funcspec-min-function-size=23 -funcspec-max-iters=100 \
-; RUN: -debug-only=function-specialization < %s 2>&1 | FileCheck %s
+; RUN: -debug-only=function-specialization -funcspec-min-codesize-savings=1 \
+; RUN: < %s 2>&1 | FileCheck %s
; Make sure the number of specializations created are not
; linear to the number of iterations (funcspec-max-iters).
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
20% is the bare minimum threshold (see https://github.com/llvm/llvm-project/blob/main/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp#L72), you are now making it higher. With your change given MinCodeSizeSavings=25 and FuncSize=4 a specialization is not profitable, since MinCodeSizeSavings must be at least 50%.
Again I am not seeing the issue here. 20% of zero is zero, --funcspec-min-function-size=0 suggests the user wants everything to be considered profitable. |
|
Sorry for the slow response, out on trip. Thanks for taking the time to respond.
Would something like the following be preferable? It would leave the behavior the same in the case you mention.
My understanding is that |
When
--funcspec-min-function-sizeis set to a small value, any small function (provided passed a constant) will be scored favorably in terms of code size savings due to the rounding in integer division in the following statement:When MinCodeSizeSavings is set by default to 20, so if
FuncSize < 5all allowed by the knob, thenMinCodeSizeSavings * FuncSize / 100evaluates to 0. As a result, a CodeSizeSavings of0will pass this check and be possibly considered profitable.I don't think this is generally an issue in the wild since
--funcspec-min-function-sizeis not usually set to small values (it defaults to 500), but might be on inline cases.Prior to this change,
unprofitable_specspecializes (with--funcspec-min-function-size=0) despite not having any savings.