[llvm] [llubi] Add support for integer arithmetic ops (PR #181224)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 12 12:59:17 PST 2026


================
@@ -0,0 +1,145 @@
+; NOTE: Assertions have been autogenerated by utils/update_llubi_test_checks.py UTC_ARGS: --version 6
+; RUN: llubi --verbose < %s 2>&1 | FileCheck %s
+; RUN: llubi --verbose --use-constant-int-for-fixed-length-splat < %s 2>&1 | FileCheck %s
+
+; Check constant and poison propagation for integer arithmetic operators.
+
+define void @main() {
+  %add = add i32 1, 2
+  %add_nuw_poison = add nuw i32 2147483648, 2147483648
+  %add_nsw_poison1 = add nsw i8 -1, -128
+  %add_nsw_poison2 = add nsw i8 127, 127
+  %add_use1 = add i32 %add, 3
+  %add_use2 = add i32 %add_nuw_poison, 2
+  %add_vec = add nuw nsw <4 x i32> <i32 2147483648, i32 -1, i32 poison, i32 0>, <i32 2147483648, i32 2147483648, i32 0, i32 poison>
+  %add_splat = add <4 x i32> splat(i32 1), zeroinitializer
+  %add_i1 = add <4 x i1> <i1 true, i1 true, i1 false, i1 false>, <i1 true, i1 false, i1 true, i1 false>
+
+  %sub = sub i32 1, 2
+  %sub_nuw_poison = sub nuw i32 0, 1
+  %sub_nsw_poison1 = sub nsw i32 -2147483648, 1
+  %sub_nsw_poison2 = sub nsw i32 0, -2147483648
+
+  %mul = mul i32 2, -3
+  %mul_nsw_poison = mul nsw i8 -16, 9
+  %mul_nuw_poison = mul nuw i8 16, 16
+
+  %sdiv = sdiv i32 90, 15
+  %sdiv_poison = sdiv i32 poison, %sdiv
+  %sdiv_exact = sdiv i32 4, 2
+  %sdiv_exact_poison = sdiv exact i32 3, 2
+  %srem = srem i32 90, 16
+  %srem_poison = srem i32 poison, 1
+
+  %udiv = udiv i32 90, 15
+  %udiv_poison = udiv i32 poison, %udiv
+  %udiv_exact = udiv i32 4, 2
+  %udiv_exact_poison = udiv exact i32 3, 2
+  %urem = urem i32 90, 16
+  %urem_poison = urem i32 poison, 1
+
+  %trunc = trunc i32 65533 to i8
+  %trunc_poison = trunc i32 poison to i8
+  %trunc_nsw = trunc nsw i32 -1 to i8
+  %trunc_nsw_poison = trunc nsw i32 511 to i8
+  %trunc_nuw = trunc nuw i32 255 to i8
+  %trunc_nuw_poison = trunc nuw i32 511 to i8
+
+  %zext = zext i8 -1 to i32
+  %zext_poison = zext i8 poison to i32
+  %zext_nneg_poison = zext nneg i8 -1 to i32
+
+  %sext = sext i8 -1 to i32
+  %sext_poison = sext i8 poison to i32
+
+  %and = and i8 15, 10
+  %xor = xor i8 13, 10
+  %or = or i8 15, 10
+  %or_disjoint = or disjoint i8 12, 3
+  %or_disjoint_poison = or disjoint i8 15, 10
+
+  %shl = shl i8 127, 3
+  %shl_oob = shl i8 127, 8
+  %shl_nsw = shl nsw i8 32, 1
+  %shl_nsw_poison = shl nsw i8 32, 2
+  %shl_nuw = shl nuw i8 10, 4
+  %shl_nuw_poison = shl nuw i8 10, 5
+
+  %lshr = lshr i8 127, 3
+  %lshr_exact = lshr exact i8 126, 1
+  %lshr_exact_poison = lshr exact i8 1, 1
+
+  %ashr = ashr i8 127, 3
+  %ashr_exact = ashr exact i8 126, 1
+  %ashr_exact_poison = ashr exact i8 1, 1
+
+  %select = select i1 true, i1 false, i1 poison
+  %select_vec1 = select <3 x i1> <i1 true, i1 false, i1 poison>, <3 x i32> splat(i32 10), <3 x i32> splat(i32 20)
+  %select_vec2 = select i1 false, <2 x i32> splat(i32 10), <2 x i32> splat(i32 20)
+  %select_struct = select i1 false, {i32, [2 x i1], { <2 x i16> }} zeroinitializer, {i32, [2 x i1], { <2 x i16> }} {i32 0, [2 x i1] [i1 true, i1 poison],{ <2 x i16> } { <2 x i16> <i16 1, i16 2> }}
+
+  ret void
+}
+; CHECK: Entering function: main
+; CHECK-NEXT:   %add = add i32 1, 2 => i32 3
+; CHECK-NEXT:   %add_nuw_poison = add nuw i32 -2147483648, -2147483648 => poison
+; CHECK-NEXT:   %add_nsw_poison1 = add nsw i8 -1, -128 => poison
+; CHECK-NEXT:   %add_nsw_poison2 = add nsw i8 127, 127 => poison
+; CHECK-NEXT:   %add_use1 = add i32 %add, 3 => i32 6
+; CHECK-NEXT:   %add_use2 = add i32 %add_nuw_poison, 2 => poison
+; CHECK-NEXT:   %add_vec = add nuw nsw <4 x i32> <i32 -2147483648, i32 -1, i32 poison, i32 0>, <i32 -2147483648, i32 -2147483648, i32 0, i32 poison> => { poison, poison, poison, poison }
+; CHECK-NEXT:   %add_splat = add <4 x i32> splat (i32 1), zeroinitializer => { i32 1, i32 1, i32 1, i32 1 }
+; CHECK-NEXT:   %add_i1 = add <4 x i1> <i1 true, i1 true, i1 false, i1 false>, <i1 true, i1 false, i1 true, i1 false> => { F, T, T, F }
+; CHECK-NEXT:   %sub = sub i32 1, 2 => i32 -1
+; CHECK-NEXT:   %sub_nuw_poison = sub nuw i32 0, 1 => poison
+; CHECK-NEXT:   %sub_nsw_poison1 = sub nsw i32 -2147483648, 1 => poison
+; CHECK-NEXT:   %sub_nsw_poison2 = sub nsw i32 0, -2147483648 => poison
+; CHECK-NEXT:   %mul = mul i32 2, -3 => i32 -6
+; CHECK-NEXT:   %mul_nsw_poison = mul nsw i8 -16, 9 => poison
+; CHECK-NEXT:   %mul_nuw_poison = mul nuw i8 16, 16 => poison
+; CHECK-NEXT:   %sdiv = sdiv i32 90, 15 => i32 6
+; CHECK-NEXT:   %sdiv_poison = sdiv i32 poison, %sdiv => poison
+; CHECK-NEXT:   %sdiv_exact = sdiv i32 4, 2 => i32 2
+; CHECK-NEXT:   %sdiv_exact_poison = sdiv exact i32 3, 2 => poison
+; CHECK-NEXT:   %srem = srem i32 90, 16 => i32 10
+; CHECK-NEXT:   %srem_poison = srem i32 poison, 1 => poison
+; CHECK-NEXT:   %udiv = udiv i32 90, 15 => i32 6
+; CHECK-NEXT:   %udiv_poison = udiv i32 poison, %udiv => poison
+; CHECK-NEXT:   %udiv_exact = udiv i32 4, 2 => i32 2
+; CHECK-NEXT:   %udiv_exact_poison = udiv exact i32 3, 2 => poison
+; CHECK-NEXT:   %urem = urem i32 90, 16 => i32 10
+; CHECK-NEXT:   %urem_poison = urem i32 poison, 1 => poison
+; CHECK-NEXT:   %trunc = trunc i32 65533 to i8 => i8 -3
+; CHECK-NEXT:   %trunc_poison = trunc i32 poison to i8 => poison
+; CHECK-NEXT:   %trunc_nsw = trunc nsw i32 -1 to i8 => i8 -1
+; CHECK-NEXT:   %trunc_nsw_poison = trunc nsw i32 511 to i8 => poison
+; CHECK-NEXT:   %trunc_nuw = trunc nuw i32 255 to i8 => i8 -1
+; CHECK-NEXT:   %trunc_nuw_poison = trunc nuw i32 511 to i8 => poison
+; CHECK-NEXT:   %zext = zext i8 -1 to i32 => i32 255
+; CHECK-NEXT:   %zext_poison = zext i8 poison to i32 => poison
+; CHECK-NEXT:   %zext_nneg_poison = zext nneg i8 -1 to i32 => poison
----------------
nikic wrote:

Test a non-poison nneg value as well?

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


More information about the llvm-commits mailing list