[llvm] Llubi docs (PR #207210)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 2 08:43:45 PDT 2026


https://github.com/dtcxzyw created https://github.com/llvm/llvm-project/pull/207210

Update the docs to reflect the current status. This also addresses the post-commit review in https://github.com/llvm/llvm-project/pull/185196#discussion_r2995639990.


>From 2a4373c1be7144714287e4cff394833ebc6e8eff Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Thu, 2 Jul 2026 23:39:55 +0800
Subject: [PATCH 1/2] [llubi][Docs] Update docs and CLI interface of llubi

---
 llvm/docs/CommandGuide/llubi.rst              | 26 +++++++++++++++++++
 llvm/test/tools/llubi/fp_nan_preferred.ll     |  2 +-
 llvm/test/tools/llubi/fp_nan_quieting.ll      |  2 +-
 .../llubi/fp_nan_target_specific_sparc.ll     |  2 +-
 .../llubi/fp_nan_target_specific_wasm32.ll    |  2 +-
 .../fp_nan_target_specific_x86_64_linux.ll    |  2 +-
 llvm/test/tools/llubi/fp_nan_unchanged.ll     |  2 +-
 llvm/test/tools/llubi/undefmem_nondet.ll      | 15 +++++++++++
 llvm/test/tools/llubi/undefmem_zero.ll        | 18 +++++++++++++
 llvm/tools/llubi/llubi.cpp                    | 24 ++++++++---------
 10 files changed, 77 insertions(+), 18 deletions(-)
 create mode 100644 llvm/test/tools/llubi/undefmem_nondet.ll
 create mode 100644 llvm/test/tools/llubi/undefmem_zero.ll

diff --git a/llvm/docs/CommandGuide/llubi.rst b/llvm/docs/CommandGuide/llubi.rst
index 55528373cffef..f68332c4af2da 100644
--- a/llvm/docs/CommandGuide/llubi.rst
+++ b/llvm/docs/CommandGuide/llubi.rst
@@ -82,6 +82,32 @@ INTERPRETER OPTIONS
   * `nondet`: Each load from the same uninitialized byte yields a freshly random value. This is the default behavior.
   * `zero`: Uninitialized values are treated as zero.
 
+.. option:: -nan-behavior=mode
+
+  Set the behavior for payload preserving behavior of floating-point NaN values.
+  The options for `mode` are:
+
+  * `nondet`: The actual behavior is randomly chosen from the modes below. This is the default behavior.
+  * `preferred`: The quiet bit is set and the payload is all-zero.
+  * `quieting`: The quiet bit is set and the payload is copied from any input operand that is a NaN.
+  * `unchanged`: The quiet bit and payload are copied from any input operand that is a NaN.
+  * `target-specific`: The quiet bit is set and the payload is picked from a known target-specific set of extra possible NaN payloads.
+
+.. option:: -deterministic
+
+  Disable interpreter-introduced non-determinism (off by default).
+  This option implies '``-undef-behavior=zero``' and '``-nan-behavior=preferred``'.
+
+.. option:: -fuse-fmuladd
+
+  Treat '``llvm.fmuladd.*``' as '``llvm.fma.*``'. It is the default behavior.
+  Otherwise, it is expended into a \* b + c.
+
+.. option:: -disable-verify
+
+  Disable the validation of the input LLVM IR. The user is responsible for the validity of inputs.
+  The verifier is executed by default.
+
 EXIT STATUS
 -----------
 
diff --git a/llvm/test/tools/llubi/fp_nan_preferred.ll b/llvm/test/tools/llubi/fp_nan_preferred.ll
index f3364e1fd22ee..49261b369a21e 100644
--- a/llvm/test/tools/llubi/fp_nan_preferred.ll
+++ b/llvm/test/tools/llubi/fp_nan_preferred.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llubi_test_checks.py UTC_ARGS: --version 6
-; RUN: llubi --nan-preferred --verbose < %s 2>&1 | FileCheck %s
+; RUN: llubi --nan-behavior=preferred --verbose < %s 2>&1 | FileCheck %s
 
 define void @main() {
     %qnan_zero_payload = fadd double 1.0, 0x7FF8000000000000
diff --git a/llvm/test/tools/llubi/fp_nan_quieting.ll b/llvm/test/tools/llubi/fp_nan_quieting.ll
index 64e8cd67d2cd0..b3a531e04dc9c 100644
--- a/llvm/test/tools/llubi/fp_nan_quieting.ll
+++ b/llvm/test/tools/llubi/fp_nan_quieting.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llubi_test_checks.py UTC_ARGS: --version 6
-; RUN: llubi --nan-quieting --verbose < %s 2>&1 | FileCheck %s
+; RUN: llubi --nan-behavior=quieting --verbose < %s 2>&1 | FileCheck %s
 
 define void @main() {
     %qnan_zero_payload = fadd double 1.0, 0x7FF8000000000000
diff --git a/llvm/test/tools/llubi/fp_nan_target_specific_sparc.ll b/llvm/test/tools/llubi/fp_nan_target_specific_sparc.ll
index efb42737da794..f2959bcec7ec3 100644
--- a/llvm/test/tools/llubi/fp_nan_target_specific_sparc.ll
+++ b/llvm/test/tools/llubi/fp_nan_target_specific_sparc.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llubi_test_checks.py UTC_ARGS: --version 6
-; RUN: llubi --nan-target-specific --verbose < %s 2>&1 | FileCheck %s
+; RUN: llubi --nan-behavior=target-specific --verbose < %s 2>&1 | FileCheck %s
 
 target triple = "sparc-unknown-linux-gnu"
 
diff --git a/llvm/test/tools/llubi/fp_nan_target_specific_wasm32.ll b/llvm/test/tools/llubi/fp_nan_target_specific_wasm32.ll
index b5905e023bb3e..ef53331c482f7 100644
--- a/llvm/test/tools/llubi/fp_nan_target_specific_wasm32.ll
+++ b/llvm/test/tools/llubi/fp_nan_target_specific_wasm32.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llubi_test_checks.py UTC_ARGS: --version 6
-; RUN: llubi --nan-target-specific --verbose < %s 2>&1 | FileCheck %s
+; RUN: llubi --nan-behavior=target-specific --verbose < %s 2>&1 | FileCheck %s
 
 target triple = "wasm32-unknown-unknown"
 
diff --git a/llvm/test/tools/llubi/fp_nan_target_specific_x86_64_linux.ll b/llvm/test/tools/llubi/fp_nan_target_specific_x86_64_linux.ll
index 39a754c6f247b..3540ddb06fe9b 100644
--- a/llvm/test/tools/llubi/fp_nan_target_specific_x86_64_linux.ll
+++ b/llvm/test/tools/llubi/fp_nan_target_specific_x86_64_linux.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llubi_test_checks.py UTC_ARGS: --version 6
-; RUN: llubi --nan-target-specific --verbose < %s 2>&1 | FileCheck %s
+; RUN: llubi --nan-behavior=target-specific --verbose < %s 2>&1 | FileCheck %s
 
 target triple = "x86_64-unknown-linux-gnu"
 
diff --git a/llvm/test/tools/llubi/fp_nan_unchanged.ll b/llvm/test/tools/llubi/fp_nan_unchanged.ll
index 260e878f9f600..b4178a85e37fb 100644
--- a/llvm/test/tools/llubi/fp_nan_unchanged.ll
+++ b/llvm/test/tools/llubi/fp_nan_unchanged.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llubi_test_checks.py UTC_ARGS: --version 6
-; RUN: llubi --nan-unchanged --verbose < %s 2>&1 | FileCheck %s
+; RUN: llubi --nan-behavior=unchanged --verbose < %s 2>&1 | FileCheck %s
 
 define void @main() {
     %qnan_zero_payload = fadd double 1.0, 0x7FF8000000000000
diff --git a/llvm/test/tools/llubi/undefmem_nondet.ll b/llvm/test/tools/llubi/undefmem_nondet.ll
new file mode 100644
index 0000000000000..dc47bda0b97e8
--- /dev/null
+++ b/llvm/test/tools/llubi/undefmem_nondet.ll
@@ -0,0 +1,15 @@
+; NOTE: Assertions have been autogenerated by utils/update_llubi_test_checks.py UTC_ARGS: --version 6
+; RUN: llubi --undef-behavior=nondet --verbose < %s 2>&1 | FileCheck %s
+
+define void @main() {
+  %alloc = alloca i32
+  %load_undef1 = load i32, ptr %alloc
+  %load_undef2 = load i32, ptr %alloc
+  ret void
+}
+; CHECK: Entering function: main
+; CHECK-NEXT:   %alloc = alloca i32, align 4 => ptr 0x8 [alloc]
+; CHECK-NEXT:   %load_undef1 = load i32, ptr %alloc, align 4 => i32 -289830082
+; CHECK-NEXT:   %load_undef2 = load i32, ptr %alloc, align 4 => i32 -399511892
+; CHECK-NEXT:   ret void
+; CHECK-NEXT: Exiting function: main
diff --git a/llvm/test/tools/llubi/undefmem_zero.ll b/llvm/test/tools/llubi/undefmem_zero.ll
new file mode 100644
index 0000000000000..7369e4034ea1b
--- /dev/null
+++ b/llvm/test/tools/llubi/undefmem_zero.ll
@@ -0,0 +1,18 @@
+; NOTE: Assertions have been autogenerated by utils/update_llubi_test_checks.py UTC_ARGS: --version 6
+; RUN: not llubi --undef-behavior=zero --verbose < %s 2>&1 | FileCheck %s
+
+define void @main() {
+  %alloc = alloca i32
+  %load_undef1 = load i32, ptr %alloc
+  %load_undef2 = load i32, ptr %alloc
+  %load_noundef = load i32, ptr %alloc, !noundef !{}
+  ret void
+}
+; CHECK: Entering function: main
+; CHECK-NEXT:   %alloc = alloca i32, align 4 => ptr 0x8 [alloc]
+; CHECK-NEXT:   %load_undef1 = load i32, ptr %alloc, align 4 => i32 0
+; CHECK-NEXT:   %load_undef2 = load i32, ptr %alloc, align 4 => i32 0
+; CHECK-NEXT: Stacktrace:
+; CHECK-NEXT: #0   %load_noundef = load i32, ptr %alloc, align 4, !noundef !0 at @main <stdin>:8
+; CHECK-NEXT: Immediate UB detected: The value loaded contains undefined bits.
+; CHECK-NEXT: error: Execution of function 'main' failed.
diff --git a/llvm/tools/llubi/llubi.cpp b/llvm/tools/llubi/llubi.cpp
index fd6d0fa807761..fd0e8e8f55ace 100644
--- a/llvm/tools/llubi/llubi.cpp
+++ b/llvm/tools/llubi/llubi.cpp
@@ -94,30 +94,30 @@ static cl::opt<bool> NoVerify("disable-verify",
                               cl::init(false), cl::cat(InterpreterCategory));
 
 cl::opt<ubi::UndefValueBehavior> UndefBehavior(
-    "", cl::desc("Choose undef value behavior:"),
-    cl::values(clEnumVal(ubi::UndefValueBehavior::NonDeterministic,
-                         "Each load of an uninitialized byte yields a freshly "
-                         "random value."),
-               clEnumVal(ubi::UndefValueBehavior::Zero,
-                         "All uses of an uninitialized byte yield zero.")));
+    "undef-behavior", cl::desc("Choose undef value behavior:"),
+    cl::values(clEnumValN(ubi::UndefValueBehavior::NonDeterministic, "nondet",
+                          "Each load of an uninitialized byte yields a freshly "
+                          "random value."),
+               clEnumValN(ubi::UndefValueBehavior::Zero, "zero",
+                          "All uses of an uninitialized byte yield zero.")));
 
 cl::opt<ubi::NaNPropagationBehavior> NaNPropagationBehavior(
-    "", cl::desc("Choose NaN propagation behavior:"),
+    "nan-behavior", cl::desc("Choose NaN propagation behavior:"),
     cl::values(
-        clEnumValN(ubi::NaNPropagationBehavior::NonDeterministic, "nan-nodet",
+        clEnumValN(ubi::NaNPropagationBehavior::NonDeterministic, "nondet",
                    "Non-deterministically choose from valid NaN results as "
                    "specified by language reference."),
-        clEnumValN(ubi::NaNPropagationBehavior::PreferredNaN, "nan-preferred",
+        clEnumValN(ubi::NaNPropagationBehavior::PreferredNaN, "preferred",
                    "The quiet bit is set and the payload is all-zero."),
         clEnumValN(
-            ubi::NaNPropagationBehavior::QuietingNaN, "nan-quieting",
+            ubi::NaNPropagationBehavior::QuietingNaN, "quieting",
             "The quiet bit is set and the payload is copied from any input"
             "operand that is a NaN."),
-        clEnumValN(ubi::NaNPropagationBehavior::UnchangedNaN, "nan-unchanged",
+        clEnumValN(ubi::NaNPropagationBehavior::UnchangedNaN, "unchanged",
                    "The quiet bit and payload are copied from any input operand"
                    "that is a NaN"),
         clEnumValN(ubi::NaNPropagationBehavior::TargetSpecificNaN,
-                   "nan-target-specific",
+                   "target-specific",
                    "The quiet bit is set and the payload is picked from a "
                    "known target-specific set of \"extra\" possible NaN "
                    "payloads.")),

>From 587ad15a976f166555b36099091f59e2739ba171 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Thu, 2 Jul 2026 23:42:53 +0800
Subject: [PATCH 2/2] [Docs] Fix typo

---
 llvm/docs/CommandGuide/llubi.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/docs/CommandGuide/llubi.rst b/llvm/docs/CommandGuide/llubi.rst
index f68332c4af2da..0e8ed54592e5d 100644
--- a/llvm/docs/CommandGuide/llubi.rst
+++ b/llvm/docs/CommandGuide/llubi.rst
@@ -101,7 +101,7 @@ INTERPRETER OPTIONS
 .. option:: -fuse-fmuladd
 
   Treat '``llvm.fmuladd.*``' as '``llvm.fma.*``'. It is the default behavior.
-  Otherwise, it is expended into a \* b + c.
+  Otherwise, it is expanded into a \* b + c.
 
 .. option:: -disable-verify
 



More information about the llvm-commits mailing list