-
Notifications
You must be signed in to change notification settings - Fork 13.4k
[llvm][gvn-sink] Don't try to sink inline asm #138414
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
Conversation
@llvm/pr-subscribers-llvm-transforms Author: Paul Kirth (ilovepi) ChangesFixes #138345. Before this patch, gvn-sink would try to sink inline llvm-project/llvm/lib/Transforms/Scalar/GVN.cpp Line 2932 in b4fac94
Similarly, gvn-sink should skip these instructions, since they are not safe to move. The test added is reduced from a failure when compiling Fuchsia. There Full diff: https://github.com/llvm/llvm-project/pull/138414.diff 2 Files Affected:
diff --git a/llvm/lib/Transforms/Scalar/GVNSink.cpp b/llvm/lib/Transforms/Scalar/GVNSink.cpp
index 2058df33ea331..40f7a61cb5717 100644
--- a/llvm/lib/Transforms/Scalar/GVNSink.cpp
+++ b/llvm/lib/Transforms/Scalar/GVNSink.cpp
@@ -548,6 +548,9 @@ class GVNSink {
if (isa<PHINode>(I) || I->isEHPad() || isa<AllocaInst>(I) ||
I->getType()->isTokenTy())
return true;
+ // Inline asm can't be sunk either.
+ if (auto *CB = dyn_cast<CallBase>(I); CB->isInlineAsm())
+ return true;
return false;
}
diff --git a/llvm/test/Transforms/GVNSink/pr138345.ll b/llvm/test/Transforms/GVNSink/pr138345.ll
new file mode 100644
index 0000000000000..1c9ff5936625f
--- /dev/null
+++ b/llvm/test/Transforms/GVNSink/pr138345.ll
@@ -0,0 +1,51 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; REQUIRES: x86-registered-target
+; RUN: opt -passes="gvn-sink" -S %s | FileCheck %s
+; RUN: opt -passes="gvn-sink,correlated-propagation" -S %s | FileCheck %s
+
+;; See https://github.com/llvm/llvm-project/issues/138345 for details.
+;; The program below used to crash due to taking the address of the inline asm.
+;; gvn-sink shouldn't do anything in this case, so test that the pass no longer
+;; generates invalid IR and no longer crashes.
+
+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-unknown-linux-gnu"
+
+define void @c(i64 %num, ptr %ptr) {
+; CHECK-LABEL: define void @c(
+; CHECK-SAME: i64 [[NUM:%.*]], ptr [[PTR:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: switch i64 [[NUM]], label %[[SW_EPILOG:.*]] [
+; CHECK-NEXT: i64 1, label %[[SW_BB:.*]]
+; CHECK-NEXT: i64 0, label %[[SW_BB1:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[SW_BB]]:
+; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[PTR]], align 1
+; CHECK-NEXT: call void asm sideeffect "", "r,r,~{dirflag},~{fpsr},~{flags}"(i8 [[TMP1]], ptr @c)
+; CHECK-NEXT: br label %[[SW_EPILOG]]
+; CHECK: [[SW_BB1]]:
+; CHECK-NEXT: [[TMP2:%.*]] = load i8, ptr [[PTR]], align 1
+; CHECK-NEXT: call void asm sideeffect "movdqu 0 [[XMM0:%.*]] \0A\09", "r,r,~{dirflag},~{fpsr},~{flags}"(i8 [[TMP2]], ptr @c)
+; CHECK-NEXT: br label %[[SW_EPILOG]]
+; CHECK: [[SW_EPILOG]]:
+; CHECK-NEXT: ret void
+;
+entry:
+ switch i64 %num, label %sw.epilog [
+ i64 1, label %sw.bb
+ i64 0, label %sw.bb1
+ ]
+
+sw.bb: ; preds = %entry
+ %1 = load i8, ptr %ptr, align 1
+ call void asm sideeffect "", "r,r,~{dirflag},~{fpsr},~{flags}"(i8 %1, ptr @c)
+ br label %sw.epilog
+
+sw.bb1: ; preds = %entry
+ %2 = load i8, ptr %ptr, align 1
+ call void asm sideeffect "movdqu 0 %xmm0 \0A\09", "r,r,~{dirflag},~{fpsr},~{flags}"(i8 %2, ptr @c)
+ br label %sw.epilog
+
+sw.epilog: ; preds = %sw.bb1, %sw.bb, %entry
+ ret void
+}
|
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 seems like something that canReplaceOperandWithVariable() should be handling -- why doesn't it? Is it because the !isa<Constant>
bails out before we get to the inline asm check?
Yes, that seems to be why. For GVNSink, I'd guess its still better to skip numbering those instructions, but maybe the check in |
49c2f79
to
e680ddb
Compare
✅ With the latest revision this PR passed the C/C++ code formatter. |
I updated |
e680ddb
to
b3b25a5
Compare
I'd probably only leave the canReplaceOperandWithVariable() check -- you're right that we can avoid numbering this way, but given how rare this case should be, it's probably not worth having a duplicate check. |
Sounds good. I'll do that and try out your suggestion. Any idea what's happening on Windows? I'm having trouble getting llvm to build on my windows workstation for some reason (Its been quite some time since I tried, and I think some configs may have changed). It looks like a memory error, but I don't see how my change would introduce that only on Windows. |
Fixes #138345. Before this patch, gvn-sink would try to sink inline assembly statements. Other GVN passes avoid them (see https://github.com/llvm/llvm-project/blob/b4fac94181c4cf17dbb7ecc2ae975712b0e4a6d1/llvm/lib/Transforms/Scalar/GVN.cpp#L2932 Similarly, gvn-sink should skip these instructions, since they are not safe to move. To do this, we update the early exit in canReplaceOperandWithVariable, since it should have caught this case. It's more efficient to also skip numbering in GVNSink if the instruction is InlineAsm, but that should be infrequent. The test added is reduced from a failure when compiling Fuchsia with gvn-sink.
b3b25a5
to
170ab29
Compare
Well I guess windows is passing now, so I guess safe to ignore the question about windows. I still don't see anything in the old patch set that makes me think we were reading an invalid pointer for some reason. |
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
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.
Thanks for fixing it
I had forgotten to upload the formatting change.
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/138/builds/12689 Here is the relevant piece of the build log for the reference
|
Fixes #138345. Before this patch, gvn-sink would try to sink inline
assembly statements. Other GVN passes avoid them (see
llvm-project/llvm/lib/Transforms/Scalar/GVN.cpp
Line 2932 in b4fac94
Similarly, gvn-sink should skip these instructions, since they are not
safe to move. To do this, we update the early exit in
canReplaceOperandWithVariable, since it should have caught this case.
It's more efficient to also skip numbering in GVNSink if the instruction
is InlineAsm, but that should be infrequent.
The test added is reduced from a failure when compiling Fuchsia with
gvn-sink.