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

via llvm-commits llvm-commits at lists.llvm.org
Thu May 7 14:50:00 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Thurston Dang (thurstond)

<details>
<summary>Changes</summary>

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.

---
Full diff: https://github.com/llvm/llvm-project/pull/196429.diff


2 Files Affected:

- (modified) llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp (+9) 
- (modified) llvm/test/Instrumentation/MemorySanitizer/ftrunc.ll (+7-19) 


``````````diff
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}
-;.

``````````

</details>


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


More information about the llvm-commits mailing list