[llvm] [llvm][gvn-sink] Don't try to sink inline asm (PR #138414)

Paul Kirth via llvm-commits llvm-commits at lists.llvm.org
Sat May 3 09:58:37 PDT 2025


https://github.com/ilovepi created https://github.com/llvm/llvm-project/pull/138414

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
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
were two distinct failure modes. One occurred when only running gvn-sink
alone, but a different failure happened when running
correlated-propagation afterwards.

>From 49c2f79ab5b8019694ec1f7e20c41e1a01372a52 Mon Sep 17 00:00:00 2001
From: Paul Kirth <paulkirth at google.com>
Date: Sat, 3 May 2025 16:55:30 +0000
Subject: [PATCH] [llvm][gvn-sink] Don't try to sink inline asm

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
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
were two distinct failure modes. One occurred when only running gvn-sink
alone, but a different failure happened when running
correlated-propagation afterwards.
---
 llvm/lib/Transforms/Scalar/GVNSink.cpp   |  3 ++
 llvm/test/Transforms/GVNSink/pr138345.ll | 51 ++++++++++++++++++++++++
 2 files changed, 54 insertions(+)
 create mode 100644 llvm/test/Transforms/GVNSink/pr138345.ll

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
+}



More information about the llvm-commits mailing list