[llvm] [InstCombine] Fold xor(zext(or disjoint X, C1), C2) (PR #214970)

Andreas Jonson via llvm-commits llvm-commits at lists.llvm.org
Sat Aug 8 09:56:24 PDT 2026


=?utf-8?b?7KGw7JiB7KeEKEpveW91bmdqaW4p?=
Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/214970 at github.com>


================
@@ -1664,3 +1664,89 @@ entry:
   %or = or <2 x i32> %add, %c
   ret <2 x i32> %or
 }
+
+; xor(zext(or disjoint X, NarrowC), WideC) ->
+; xor(zext(X), WideC ^ zext(NarrowC))
+
+define i32 @fold_zext_or_disjoint_xor_i8_to_i32(i8 %input) {
+; CHECK-LABEL: @fold_zext_or_disjoint_xor_i8_to_i32(
+; CHECK-NEXT:    [[Z:%.*]] = zext i8 [[INPUT:%.*]] to i32
+; CHECK-NEXT:    [[R:%.*]] = xor i32 [[Z]], 267
+; CHECK-NEXT:    ret i32 [[R]]
+;
+  %or = or disjoint i8 %input, 10
+  %z = zext i8 %or to i32
+  %r = xor i32 %z, 257
+  ret i32 %r
+}
+
+define i64 @fold_zext_or_disjoint_xor_i32_to_i64(i32 %x) {
+; CHECK-LABEL: @fold_zext_or_disjoint_xor_i32_to_i64(
+; CHECK-NEXT:    [[Z:%.*]] = zext i32 [[X:%.*]] to i64
+; CHECK-NEXT:    [[R:%.*]] = xor i64 [[Z]], 2611923443488327890
+; CHECK-NEXT:    ret i64 [[R]]
+;
+  %or = or disjoint i32 %x, 1
+  %z = zext i32 %or to i64
+  %r = xor i64 %z, 2611923443488327891
+  ret i64 %r
+}
+
+define i64 @fold_zext_or_disjoint_xor_nneg(i32 %x) {
+; CHECK-LABEL: @fold_zext_or_disjoint_xor_nneg(
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i32 [[X:%.*]] to i64
+; CHECK-NEXT:    [[R:%.*]] = xor i64 [[TMP1]], 7640891576939301128
+; CHECK-NEXT:    ret i64 [[R]]
+;
+  %or = or disjoint i32 %x, 16842752
+  %z = zext nneg i32 %or to i64
+  %r = xor i64 %z, 7640891576956012808
+  ret i64 %r
+}
+
+define i32 @no_fold_zext_plain_or_xor(i8 %x) {
+; CHECK-LABEL: @no_fold_zext_plain_or_xor(
+; CHECK-NEXT:    [[OR:%.*]] = or i8 [[X:%.*]], 2
+; CHECK-NEXT:    [[Z:%.*]] = zext i8 [[OR]] to i32
+; CHECK-NEXT:    [[R:%.*]] = xor i32 [[Z]], 257
+; CHECK-NEXT:    ret i32 [[R]]
+;
+  %or = or i8 %x, 2
+  %z = zext i8 %or to i32
+  %r = xor i32 %z, 257
+  ret i32 %r
+}
+
+define i32 @no_fold_zext_multi_use(i8 %x) {
+; CHECK-LABEL: @no_fold_zext_multi_use(
+; CHECK-NEXT:    [[OR:%.*]] = or disjoint i8 [[X:%.*]], 2
+; CHECK-NEXT:    [[Z:%.*]] = zext i8 [[OR]] to i32
+; CHECK-NEXT:    [[R:%.*]] = xor i32 [[Z]], 257
+; CHECK-NEXT:    [[USE:%.*]] = add nuw nsw i32 [[Z]], 1
+; CHECK-NEXT:    [[RESULT:%.*]] = add nuw nsw i32 [[R]], [[USE]]
+; CHECK-NEXT:    ret i32 [[RESULT]]
+;
+  %or = or disjoint i8 %x, 2
+  %z = zext i8 %or to i32
+  %r = xor i32 %z, 257
+  %use = add i32 %z, 1
----------------
andjo403 wrote:

most common to use a call to a use function for extra uses eg:
call void @use(i8 %a)

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


More information about the llvm-commits mailing list