[llvm] [InstCombine] Add optimization to combine adds through zext nneg, and add testcase (PR #157723)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 25 05:55:56 PDT 2025


================
@@ -976,3 +976,85 @@ entry:
   %res = zext nneg i2 %x to i32
   ret i32 %res
 }
+
+define i32 @zext_nneg_add_cancel(i8 %arg) {
+; CHECK-LABEL: @zext_nneg_add_cancel(
+; CHECK-NEXT:    [[ADD2:%.*]] = zext i8 [[ARG:%.*]] to i32
+; CHECK-NEXT:    ret i32 [[ADD2]]
+;
+  %add = add i8 %arg, -2
+  %zext = zext nneg i8 %add to i32
+  %add2 = add i32 %zext, 2
+  ret i32 %add2
+}
+
+define i32 @zext_nneg_add_cancel_multi_use(i8 %arg) {
+; CHECK-LABEL: @zext_nneg_add_cancel_multi_use(
+; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[ARG:%.*]], -2
+; CHECK-NEXT:    [[ZEXT:%.*]] = zext nneg i8 [[ADD]] to i32
+; CHECK-NEXT:    call void @use32(i32 [[ZEXT]])
+; CHECK-NEXT:    [[ADD2:%.*]] = zext i8 [[ARG]] to i32
+; CHECK-NEXT:    ret i32 [[ADD2]]
+;
+  %add = add i8 %arg, -2
+  %zext = zext nneg i8 %add to i32
+  call void @use32(i32 %zext)
+  %add2 = add i32 %zext, 2
+  ret i32 %add2
+}
+
+define i32 @zext_nneg_no_cancel(i8 %arg) {
+; CHECK-LABEL: @zext_nneg_no_cancel(
+; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[ARG:%.*]], -1
+; CHECK-NEXT:    [[ADD2:%.*]] = zext i8 [[TMP1]] to i32
+; CHECK-NEXT:    ret i32 [[ADD2]]
+;
+  %add = add i8 %arg, -2
+  %zext = zext nneg i8 %add to i32
+  %add2 = add i32 %zext, 1
+  ret i32 %add2
+}
+
+define i32 @zext_nneg_no_cancel_multi_use(i8 %arg) {
+; CHECK-LABEL: @zext_nneg_no_cancel_multi_use(
+; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[ARG:%.*]], -2
+; CHECK-NEXT:    [[ZEXT:%.*]] = zext nneg i8 [[ADD]] to i32
+; CHECK-NEXT:    call void @use32(i32 [[ZEXT]])
+; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[ARG]], -1
+; CHECK-NEXT:    [[ADD2:%.*]] = zext i8 [[TMP1]] to i32
----------------
nikic wrote:

We should do this fold, but guarded by a hasOneUse check.

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


More information about the llvm-commits mailing list