[llvm] [msan] Handle fpto[us]i_sat (PR #196429)

Thurston Dang via llvm-commits llvm-commits at lists.llvm.org
Thu May 7 14:53:15 PDT 2026


https://github.com/thurstond updated https://github.com/llvm/llvm-project/pull/196429

>From 5c5ce3050ed20482ff120dd25002c01ce4ea0c0b Mon Sep 17 00:00:00 2001
From: Thurston Dang <thurston at google.com>
Date: Thu, 7 May 2026 21:42:26 +0000
Subject: [PATCH 1/2] [msan] Handle fpto[us]i_sat

This adds explicit handling for fpto[us]i_sat, similar to how the
non-saturating versions are handled.

N.B. PR #191365 lowered NEON fcvtz[us] intrinsics into fpto[us]i.sat.
There is a slight inconsistency in MSan insofar as the former were
handled by handleNEONVectorConvertIntrinsic(), which takes an
all-or-nothing propagation approach to the shadows (i.e., even a single
uninitialized bit will result in the corresponding integer being fully
uninitialized). For now, we choose to follow the laxer behavior of
fpto[usi. Future work may consider changing the behavior of fpto[us]i
and fpto[us]i_sat to use the all-or-nothing approach.
---
 .../Instrumentation/MemorySanitizer.cpp       |  9 +++++++
 .../Instrumentation/MemorySanitizer/ftrunc.ll | 26 +++++--------------
 2 files changed, 16 insertions(+), 19 deletions(-)

diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
index 933865f9cb7be..a69177b54ae95 100644
--- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -5864,6 +5864,15 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
       setOrigin(&I, getCleanOrigin());
       break;
 
+   // The non-saturating versions are handled by visitFPTo[US]IInst().
+   //
+   // N.B. some platform-specific intrinsics, such as Aarch64 fcvtz[us], are
+   //      lowered to these cross-platform intrinsics.
+   case Intrinsic::fptosi_sat:
+   case Intrinsic::fptoui_sat:
+      handleShadowOr(I);
+      break;
+
     default:
       return false;
     }
diff --git a/llvm/test/Instrumentation/MemorySanitizer/ftrunc.ll b/llvm/test/Instrumentation/MemorySanitizer/ftrunc.ll
index e061a1048a6ef..878bdd24eed73 100644
--- a/llvm/test/Instrumentation/MemorySanitizer/ftrunc.ll
+++ b/llvm/test/Instrumentation/MemorySanitizer/ftrunc.ll
@@ -3,8 +3,9 @@
 ;
 ; Forked from llvm/test/Instrumentation/MemorySanitizer/ftrunc.ll
 ;
-; Handled strictly:
-; - llvm.fptoui.sat, llvm.fptosi.sat
+; Handled strictly: (none)
+;
+; Handled heuristically: (none)
 ;
 ; REQUIRES: x86-registered-target
 
@@ -235,15 +236,10 @@ define float @trunc_unsigned_f32_disable_via_intrinsic(float %x) #0 {
 ; CHECK-SAME: float [[X:%.*]]) #[[ATTR1]] {
 ; CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr @__msan_param_tls, align 8
 ; CHECK-NEXT:    call void @llvm.donothing()
-; CHECK-NEXT:    [[_MSCMP:%.*]] = icmp ne i32 [[TMP1]], 0
-; CHECK-NEXT:    br i1 [[_MSCMP]], label %[[BB2:.*]], label %[[BB3:.*]], !prof [[PROF1:![0-9]+]]
-; CHECK:       [[BB2]]:
-; CHECK-NEXT:    call void @__msan_warning_noreturn() #[[ATTR4:[0-9]+]]
-; CHECK-NEXT:    unreachable
-; CHECK:       [[BB3]]:
+; CHECK-NEXT:    [[_MSPROP:%.*]] = or i32 [[TMP1]], 0
 ; CHECK-NEXT:    [[I:%.*]] = call i32 @llvm.fptoui.sat.i32.f32(float [[X]])
 ; CHECK-NEXT:    [[R:%.*]] = uitofp i32 [[I]] to float
-; CHECK-NEXT:    store i32 0, ptr @__msan_retval_tls, align 8
+; CHECK-NEXT:    store i32 [[_MSPROP]], ptr @__msan_retval_tls, align 8
 ; CHECK-NEXT:    ret float [[R]]
 ;
   %i = call i32 @llvm.fptoui.sat.i32.f32(float %x)
@@ -256,15 +252,10 @@ define double @trunc_signed_f64_disable_via_intrinsic(double %x) #0 {
 ; CHECK-SAME: double [[X:%.*]]) #[[ATTR1]] {
 ; CHECK-NEXT:    [[TMP1:%.*]] = load i64, ptr @__msan_param_tls, align 8
 ; CHECK-NEXT:    call void @llvm.donothing()
-; CHECK-NEXT:    [[_MSCMP:%.*]] = icmp ne i64 [[TMP1]], 0
-; CHECK-NEXT:    br i1 [[_MSCMP]], label %[[BB2:.*]], label %[[BB3:.*]], !prof [[PROF1]]
-; CHECK:       [[BB2]]:
-; CHECK-NEXT:    call void @__msan_warning_noreturn() #[[ATTR4]]
-; CHECK-NEXT:    unreachable
-; CHECK:       [[BB3]]:
+; CHECK-NEXT:    [[_MSPROP:%.*]] = or i64 [[TMP1]], 0
 ; CHECK-NEXT:    [[I:%.*]] = call i64 @llvm.fptosi.sat.i64.f64(double [[X]])
 ; CHECK-NEXT:    [[R:%.*]] = sitofp i64 [[I]] to double
-; CHECK-NEXT:    store i64 0, ptr @__msan_retval_tls, align 8
+; CHECK-NEXT:    store i64 [[_MSPROP]], ptr @__msan_retval_tls, align 8
 ; CHECK-NEXT:    ret double [[R]]
 ;
   %i = call i64 @llvm.fptosi.sat.i64.f64(double %x)
@@ -273,6 +264,3 @@ define double @trunc_signed_f64_disable_via_intrinsic(double %x) #0 {
 }
 
 attributes #0 = { sanitize_memory }
-;.
-; CHECK: [[PROF1]] = !{!"branch_weights", i32 1, i32 1048575}
-;.

>From c1ba44e7934882bc7bd7758331142b12b9d24459 Mon Sep 17 00:00:00 2001
From: Thurston Dang <thurston at google.com>
Date: Thu, 7 May 2026 21:52:57 +0000
Subject: [PATCH 2/2] clang-format

---
 .../Transforms/Instrumentation/MemorySanitizer.cpp   | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
index a69177b54ae95..980edc14ff57c 100644
--- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -5864,12 +5864,12 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
       setOrigin(&I, getCleanOrigin());
       break;
 
-   // The non-saturating versions are handled by visitFPTo[US]IInst().
-   //
-   // N.B. some platform-specific intrinsics, such as Aarch64 fcvtz[us], are
-   //      lowered to these cross-platform intrinsics.
-   case Intrinsic::fptosi_sat:
-   case Intrinsic::fptoui_sat:
+    // The non-saturating versions are handled by visitFPTo[US]IInst().
+    //
+    // N.B. some platform-specific intrinsics, such as Aarch64 fcvtz[us], are
+    //      lowered to these cross-platform intrinsics.
+    case Intrinsic::fptosi_sat:
+    case Intrinsic::fptoui_sat:
       handleShadowOr(I);
       break;
 



More information about the llvm-commits mailing list