-
Notifications
You must be signed in to change notification settings - Fork 11.9k
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
[InstCombine] Remove transformation on call instruction where return value need void to non-void conversion #98536
Conversation
… conversion on return value
@llvm/pr-subscribers-llvm-transforms Author: None (yozhu) ChangesAdd an option to skip simplification on call instruction where a non-void Full diff: https://github.com/llvm/llvm-project/pull/98536.diff 1 Files Affected:
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 0ca56f08c333d..880932159f570 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -89,6 +89,11 @@ static cl::opt<unsigned> GuardWideningWindow(
cl::desc("How wide an instruction window to bypass looking for "
"another guard"));
+static cl::opt<bool> SkipRetTypeVoidToNonVoidCallInst(
+ "instcombine-skip-call-ret-type-void-to-nonvoid", cl::init(false),
+ cl::desc("skip simplifying call instruction which expects a non-void "
+ "return value but the callee returns void"));
+
/// Return the specified type promoted as it would be to pass though a va_arg
/// area.
static Type *getPromotedType(Type *Ty) {
@@ -4073,7 +4078,7 @@ bool InstCombinerImpl::transformConstExprCastCall(CallBase &Call) {
if (!Caller->use_empty() &&
// void -> non-void is handled specially
- !NewRetTy->isVoidTy())
+ (SkipRetTypeVoidToNonVoidCallInst || !NewRetTy->isVoidTy()))
return false; // Cannot transform this return value.
}
|
Sorry - I messed up my local clone and branches and had to recreate this PR. It was the same code change as in #96574, where the conclusion is that adding an option to disable this optimization is fine but emitting a fatal error is not allowed. |
missing tests? |
Ping ~~ @nikic @goldsteinn |
I think we should remove the void/non-void transform entirely, not just add an option. I don't really see a good reason to perform this transform. Looking back at the history, I think this is just a leftover of an overly liberal initial implementation. |
Happy to remove this transformation entirely. Given this, should we also emit an error when seeing this void to non-void conversion at call sites? It is known to be undefined behavior that could result in non-determinism or crash at runtime; and If it is non-LTO compilation, clang would output an error unconditionally. |
…need void to non-void conversion
if (!Caller->use_empty() && | ||
// void -> non-void is handled specially | ||
!NewRetTy->isVoidTy()) | ||
if (!Caller->use_empty() || NewRetTy->isVoidTy()) |
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.
if (!Caller->use_empty() || NewRetTy->isVoidTy()) | |
if (!Caller->use_empty()) |
A more conservative change would be this. In that case we'd still allow changing the return type to void as long as the return value is not used. That may be more consistent with the overall handling?
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.
Yes this makes sense.
; RUN: opt --passes=instcombine %t.bc -S | FileCheck %s | ||
|
||
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" | ||
target triple = "x86_64-none-linux-android21" |
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.
Drop data layout and triple.
; RUN: llvm-as %s -o %t.bc | ||
; RUN: opt --passes=instcombine %t.bc -S | FileCheck %s |
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.
; RUN: llvm-as %s -o %t.bc | |
; RUN: opt --passes=instcombine %t.bc -S | FileCheck %s | |
; RUN: opt --passes=instcombine -S < %s | FileCheck %s |
; CHECK-NEXT: ret i32 [[TMP1]] | ||
; | ||
entry: | ||
%_rc_ = alloca i32, align 4 |
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.
This test is more complicated than it needs to be. You shouldn't need much more here than a call + return.
@@ -4233,9 +4231,6 @@ bool InstCombinerImpl::transformConstExprCastCall(CallBase &Call) { | |||
|
|||
AttributeSet FnAttrs = CallerPAL.getFnAttrs(); | |||
|
|||
if (NewRetTy->isVoidTy()) | |||
Caller->setName(""); // Void type should not have a name. |
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.
I think this bit might still be needed? Can you please add another function to your test that does %res = call i32 @foo()
but does not use the result? Just want to make sure this doesn't hit some void name assertion.
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.
Yes this would necessary now after we have tightened the condition above to skip transformation only when return value has uses.
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 | ||
; RUN: opt --passes=instcombine -S < %s | FileCheck %s | ||
|
||
define dso_local void @foo() { |
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.
Drop dso_local.
; | ||
entry: | ||
%1 = tail call i32 @foo() | ||
%2 = add i32 %1, 1 |
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.
Can drop the add too :)
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
Would it be wise to backport this as this is the removal of something undesirable from the codebase? Or are we okay with 19.x retaining this behavior? |
I'm fine with either way. This transformation is not desirable, but it had been in the codebase for quite a long time. |
…value need void to non-void conversion (llvm#98536) Skip simplification on call instruction where a non-void return value is expected but the callee returns void, which is undefined behavior and could lead to non-determinism or crashes.
Skip simplification on call instruction where a non-void return value is
expected but the callee returns void, which is undefined behavior and can
lead to non-determinism runtime behaviors or crashes.