[llvm] [InstCombine] Fix undef widening in masked-merge (PR #219212)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 27 06:25:50 PDT 2026
https://github.com/OmarAzizi created https://github.com/llvm/llvm-project/pull/219212
Fixes #218908
The inverted-mask fold swaps which operand ends up unmasked (`X` instead of `B`). If `X` isn't provably undef-free, this can turn a partially-defined result into a fully undef one. Freeze `X` first to prevent that.
Alive2:
- https://alive2.llvm.org/ce/z/XEiEYr (original miscompile)
- https://alive2.llvm.org/ce/z/C4PQW8 (fixed)
>From 0b6b08b048580be88dadb03f1f119bae267f8a1a Mon Sep 17 00:00:00 2001
From: OmarAzizi <oalazizi75 at gmail.com>
Date: Thu, 27 Aug 2026 15:28:20 +0300
Subject: [PATCH 1/2] Precommit tests
---
.../InstCombine/masked-merge-xor.ll | 28 +++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/llvm/test/Transforms/InstCombine/masked-merge-xor.ll b/llvm/test/Transforms/InstCombine/masked-merge-xor.ll
index 463f220fcbb6d..6b83c0940d8d6 100644
--- a/llvm/test/Transforms/InstCombine/masked-merge-xor.ll
+++ b/llvm/test/Transforms/InstCombine/masked-merge-xor.ll
@@ -427,3 +427,31 @@ define i32 @n3_constmask_samemask(i32 %x, i32 %y) {
%ret = xor i32 %and, %and1
ret i32 %ret
}
+
+define i4 @masked_merge_inverted_mask_maybe_undef_x(i4 %x, i4 %y, i4 %m) {
+; CHECK-LABEL: @masked_merge_inverted_mask_maybe_undef_x(
+; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
+; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[X]]
+; CHECK-NEXT: ret i4 [[R]]
+;
+ %im = xor i4 %m, -1
+ %n0 = xor i4 %x, %y
+ %n1 = and i4 %n0, %im
+ %r = xor i4 %n1, %y
+ ret i4 %r
+}
+
+define i4 @masked_merge_inverted_mask_noundef_x(i4 noundef %x, i4 %y, i4 %m) {
+; CHECK-LABEL: @masked_merge_inverted_mask_noundef_x(
+; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
+; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[X]]
+; CHECK-NEXT: ret i4 [[R]]
+;
+ %im = xor i4 %m, -1
+ %n0 = xor i4 %x, %y
+ %n1 = and i4 %n0, %im
+ %r = xor i4 %n1, %y
+ ret i4 %r
+}
>From 2114e1b80d2c6d033e3afa853793d47b0f1c9c56 Mon Sep 17 00:00:00 2001
From: OmarAzizi <oalazizi75 at gmail.com>
Date: Thu, 27 Aug 2026 16:11:51 +0300
Subject: [PATCH 2/2] [InstCombine] Freeze operand in masked-merge fold to fix
#218908
---
.../InstCombine/InstCombineAndOrXor.cpp | 11 +++-
...rt-variable-mask-in-masked-merge-scalar.ll | 44 +++++++++------
...rt-variable-mask-in-masked-merge-vector.ll | 55 ++++++++++++-------
.../InstCombine/masked-merge-xor.ll | 5 +-
4 files changed, 75 insertions(+), 40 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 9e9ebfe5c5e90..b3b7da7dd9ec0 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -4944,8 +4944,15 @@ static Instruction *visitMaskedMerge(BinaryOperator &I,
Value *NotM;
if (match(M, m_Not(m_Value(NotM)))) {
// De-invert the mask and swap the value in B part.
- Value *NewA = Builder.CreateAnd(D, NotM);
- return BinaryOperator::CreateXor(NewA, X);
+ // If X isn't already known undef-free then freeze it.
+ Value *NewX = X;
+ Value *NewD = D;
+ if (!isGuaranteedNotToBeUndef(X)) {
+ NewX = Builder.CreateFreeze(X);
+ NewD = Builder.CreateXor(B, NewX);
+ }
+ Value *NewA = Builder.CreateAnd(NewD, NotM);
+ return BinaryOperator::CreateXor(NewA, NewX);
}
Constant *C;
diff --git a/llvm/test/Transforms/InstCombine/invert-variable-mask-in-masked-merge-scalar.ll b/llvm/test/Transforms/InstCombine/invert-variable-mask-in-masked-merge-scalar.ll
index abb36b6a785e5..c49b224712df9 100644
--- a/llvm/test/Transforms/InstCombine/invert-variable-mask-in-masked-merge-scalar.ll
+++ b/llvm/test/Transforms/InstCombine/invert-variable-mask-in-masked-merge-scalar.ll
@@ -8,9 +8,10 @@
define i4 @scalar (i4 %x, i4 %y, i4 %m) {
; CHECK-LABEL: @scalar(
-; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[Y:%.*]] = freeze i4 [[X1:%.*]]
+; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X:%.*]], [[Y]]
; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
-; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[X]]
+; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[Y]]
; CHECK-NEXT: ret i4 [[R]]
;
%im = xor i4 %m, -1
@@ -38,7 +39,8 @@ define i4 @in_constant_varx_mone_invmask(i4 %x, i4 %mask) {
define i4 @in_constant_varx_6_invmask(i4 %x, i4 %mask) {
; CHECK-LABEL: @in_constant_varx_6_invmask(
-; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X:%.*]], 6
+; CHECK-NEXT: [[X:%.*]] = freeze i4 [[X1:%.*]]
+; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X]], 6
; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[MASK:%.*]]
; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[X]]
; CHECK-NEXT: ret i4 [[R]]
@@ -88,7 +90,8 @@ declare i4 @gen4()
define i4 @c_1_0_0 (i4 %x, i4 %y, i4 %m) {
; CHECK-LABEL: @c_1_0_0(
-; CHECK-NEXT: [[N0:%.*]] = xor i4 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[X:%.*]] = freeze i4 [[X1:%.*]]
+; CHECK-NEXT: [[N0:%.*]] = xor i4 [[Y:%.*]], [[X]]
; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[X]]
; CHECK-NEXT: ret i4 [[R]]
@@ -102,7 +105,8 @@ define i4 @c_1_0_0 (i4 %x, i4 %y, i4 %m) {
define i4 @c_0_1_0 (i4 %x, i4 %y, i4 %m) {
; CHECK-LABEL: @c_0_1_0(
-; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[Y:%.*]] = freeze i4 [[Y1:%.*]]
+; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X:%.*]], [[Y]]
; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[Y]]
; CHECK-NEXT: ret i4 [[R]]
@@ -118,9 +122,10 @@ define i4 @c_0_0_1 (i4 %m) {
; CHECK-LABEL: @c_0_0_1(
; CHECK-NEXT: [[X:%.*]] = call i4 @gen4()
; CHECK-NEXT: [[Y:%.*]] = call i4 @gen4()
-; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X]], [[Y]]
+; CHECK-NEXT: [[TMP2:%.*]] = freeze i4 [[X]]
+; CHECK-NEXT: [[N0:%.*]] = xor i4 [[Y]], [[TMP2]]
; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
-; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[X]]
+; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[TMP2]]
; CHECK-NEXT: ret i4 [[R]]
;
%im = xor i4 %m, -1
@@ -134,9 +139,10 @@ define i4 @c_0_0_1 (i4 %m) {
define i4 @c_1_1_0 (i4 %x, i4 %y, i4 %m) {
; CHECK-LABEL: @c_1_1_0(
-; CHECK-NEXT: [[N0:%.*]] = xor i4 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[X:%.*]] = freeze i4 [[Y1:%.*]]
+; CHECK-NEXT: [[N0:%.*]] = xor i4 [[Y:%.*]], [[X]]
; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
-; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[Y]]
+; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[X]]
; CHECK-NEXT: ret i4 [[R]]
;
%im = xor i4 %m, -1
@@ -149,7 +155,8 @@ define i4 @c_1_1_0 (i4 %x, i4 %y, i4 %m) {
define i4 @c_1_0_1 (i4 %x, i4 %m) {
; CHECK-LABEL: @c_1_0_1(
; CHECK-NEXT: [[Y:%.*]] = call i4 @gen4()
-; CHECK-NEXT: [[N0:%.*]] = xor i4 [[Y]], [[X:%.*]]
+; CHECK-NEXT: [[X:%.*]] = freeze i4 [[X1:%.*]]
+; CHECK-NEXT: [[N0:%.*]] = xor i4 [[Y]], [[X]]
; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[X]]
; CHECK-NEXT: ret i4 [[R]]
@@ -165,7 +172,8 @@ define i4 @c_1_0_1 (i4 %x, i4 %m) {
define i4 @c_0_1_1 (i4 %y, i4 %m) {
; CHECK-LABEL: @c_0_1_1(
; CHECK-NEXT: [[X:%.*]] = call i4 @gen4()
-; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X]], [[Y:%.*]]
+; CHECK-NEXT: [[Y:%.*]] = freeze i4 [[Y1:%.*]]
+; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X]], [[Y]]
; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[Y]]
; CHECK-NEXT: ret i4 [[R]]
@@ -182,9 +190,10 @@ define i4 @c_1_1_1 (i4 %m) {
; CHECK-LABEL: @c_1_1_1(
; CHECK-NEXT: [[X:%.*]] = call i4 @gen4()
; CHECK-NEXT: [[Y:%.*]] = call i4 @gen4()
-; CHECK-NEXT: [[N0:%.*]] = xor i4 [[Y]], [[X]]
+; CHECK-NEXT: [[TMP2:%.*]] = freeze i4 [[Y]]
+; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X]], [[TMP2]]
; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
-; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[Y]]
+; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[TMP2]]
; CHECK-NEXT: ret i4 [[R]]
;
%im = xor i4 %m, -1
@@ -198,7 +207,8 @@ define i4 @c_1_1_1 (i4 %m) {
define i4 @commutativity_constant_varx_6_invmask(i4 %x, i4 %mask) {
; CHECK-LABEL: @commutativity_constant_varx_6_invmask(
-; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X:%.*]], 6
+; CHECK-NEXT: [[X:%.*]] = freeze i4 [[X1:%.*]]
+; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X]], 6
; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[MASK:%.*]]
; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[X]]
; CHECK-NEXT: ret i4 [[R]]
@@ -234,8 +244,10 @@ declare void @use4(i4)
define i4 @n_oneuse_D_is_ok (i4 %x, i4 %y, i4 %m) {
; CHECK-LABEL: @n_oneuse_D_is_ok(
-; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
+; CHECK-NEXT: [[X:%.*]] = freeze i4 [[X1:%.*]]
+; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X]], [[Y:%.*]]
+; CHECK-NEXT: [[TMP2:%.*]] = xor i4 [[Y]], [[X]]
+; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[TMP2]], [[M:%.*]]
; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[X]]
; CHECK-NEXT: call void @use4(i4 [[N0]])
; CHECK-NEXT: ret i4 [[R]]
diff --git a/llvm/test/Transforms/InstCombine/invert-variable-mask-in-masked-merge-vector.ll b/llvm/test/Transforms/InstCombine/invert-variable-mask-in-masked-merge-vector.ll
index c73b07cfbc668..0b60dada170b8 100644
--- a/llvm/test/Transforms/InstCombine/invert-variable-mask-in-masked-merge-vector.ll
+++ b/llvm/test/Transforms/InstCombine/invert-variable-mask-in-masked-merge-vector.ll
@@ -8,9 +8,10 @@
define <2 x i4> @vector (<2 x i4> %x, <2 x i4> %y, <2 x i4> %m) {
; CHECK-LABEL: @vector(
-; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[Y:%.*]] = freeze <2 x i4> [[X1:%.*]]
+; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[X:%.*]], [[Y]]
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[N0]], [[M:%.*]]
-; CHECK-NEXT: [[R:%.*]] = xor <2 x i4> [[TMP1]], [[X]]
+; CHECK-NEXT: [[R:%.*]] = xor <2 x i4> [[TMP1]], [[Y]]
; CHECK-NEXT: ret <2 x i4> [[R]]
;
%im = xor <2 x i4> %m, <i4 -1, i4 -1>
@@ -22,9 +23,10 @@ define <2 x i4> @vector (<2 x i4> %x, <2 x i4> %y, <2 x i4> %m) {
define <3 x i4> @vector_poison (<3 x i4> %x, <3 x i4> %y, <3 x i4> %m) {
; CHECK-LABEL: @vector_poison(
-; CHECK-NEXT: [[N0:%.*]] = xor <3 x i4> [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[Y:%.*]] = freeze <3 x i4> [[X1:%.*]]
+; CHECK-NEXT: [[N0:%.*]] = xor <3 x i4> [[X:%.*]], [[Y]]
; CHECK-NEXT: [[TMP1:%.*]] = and <3 x i4> [[N0]], [[M:%.*]]
-; CHECK-NEXT: [[R:%.*]] = xor <3 x i4> [[TMP1]], [[X]]
+; CHECK-NEXT: [[R:%.*]] = xor <3 x i4> [[TMP1]], [[Y]]
; CHECK-NEXT: ret <3 x i4> [[R]]
;
%im = xor <3 x i4> %m, <i4 -1, i4 poison, i4 -1>
@@ -52,7 +54,8 @@ define <2 x i4> @in_constant_varx_mone_invmask(<2 x i4> %x, <2 x i4> %mask) {
define <2 x i4> @in_constant_varx_6_invmask(<2 x i4> %x, <2 x i4> %mask) {
; CHECK-LABEL: @in_constant_varx_6_invmask(
-; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[X:%.*]], splat (i4 6)
+; CHECK-NEXT: [[X:%.*]] = freeze <2 x i4> [[X1:%.*]]
+; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[X]], splat (i4 6)
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[N0]], [[MASK:%.*]]
; CHECK-NEXT: [[R:%.*]] = xor <2 x i4> [[TMP1]], [[X]]
; CHECK-NEXT: ret <2 x i4> [[R]]
@@ -66,7 +69,8 @@ define <2 x i4> @in_constant_varx_6_invmask(<2 x i4> %x, <2 x i4> %mask) {
define <2 x i4> @in_constant_varx_6_invmask_nonsplat(<2 x i4> %x, <2 x i4> %mask) {
; CHECK-LABEL: @in_constant_varx_6_invmask_nonsplat(
-; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[X:%.*]], <i4 6, i4 7>
+; CHECK-NEXT: [[X:%.*]] = freeze <2 x i4> [[X1:%.*]]
+; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[X]], <i4 6, i4 7>
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[N0]], [[MASK:%.*]]
; CHECK-NEXT: [[R:%.*]] = xor <2 x i4> [[TMP1]], [[X]]
; CHECK-NEXT: ret <2 x i4> [[R]]
@@ -80,7 +84,8 @@ define <2 x i4> @in_constant_varx_6_invmask_nonsplat(<2 x i4> %x, <2 x i4> %mask
define <3 x i4> @in_constant_varx_6_invmask_poison(<3 x i4> %x, <3 x i4> %mask) {
; CHECK-LABEL: @in_constant_varx_6_invmask_poison(
-; CHECK-NEXT: [[N0:%.*]] = xor <3 x i4> [[X:%.*]], <i4 6, i4 poison, i4 7>
+; CHECK-NEXT: [[X:%.*]] = freeze <3 x i4> [[X1:%.*]]
+; CHECK-NEXT: [[N0:%.*]] = xor <3 x i4> [[X]], <i4 6, i4 poison, i4 7>
; CHECK-NEXT: [[TMP1:%.*]] = and <3 x i4> [[N0]], [[MASK:%.*]]
; CHECK-NEXT: [[R:%.*]] = xor <3 x i4> [[TMP1]], [[X]]
; CHECK-NEXT: ret <3 x i4> [[R]]
@@ -158,7 +163,8 @@ declare <2 x i4> @gen4()
define <2 x i4> @c_1_0_0 (<2 x i4> %x, <2 x i4> %y, <2 x i4> %m) {
; CHECK-LABEL: @c_1_0_0(
-; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[X:%.*]] = freeze <2 x i4> [[X1:%.*]]
+; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[Y:%.*]], [[X]]
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[N0]], [[M:%.*]]
; CHECK-NEXT: [[R:%.*]] = xor <2 x i4> [[TMP1]], [[X]]
; CHECK-NEXT: ret <2 x i4> [[R]]
@@ -172,7 +178,8 @@ define <2 x i4> @c_1_0_0 (<2 x i4> %x, <2 x i4> %y, <2 x i4> %m) {
define <2 x i4> @c_0_1_0 (<2 x i4> %x, <2 x i4> %y, <2 x i4> %m) {
; CHECK-LABEL: @c_0_1_0(
-; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[Y:%.*]] = freeze <2 x i4> [[Y1:%.*]]
+; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[X:%.*]], [[Y]]
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[N0]], [[M:%.*]]
; CHECK-NEXT: [[R:%.*]] = xor <2 x i4> [[TMP1]], [[Y]]
; CHECK-NEXT: ret <2 x i4> [[R]]
@@ -188,9 +195,10 @@ define <2 x i4> @c_0_0_1 (<2 x i4> %m) {
; CHECK-LABEL: @c_0_0_1(
; CHECK-NEXT: [[X:%.*]] = call <2 x i4> @gen4()
; CHECK-NEXT: [[Y:%.*]] = call <2 x i4> @gen4()
-; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[X]], [[Y]]
+; CHECK-NEXT: [[TMP2:%.*]] = freeze <2 x i4> [[X]]
+; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[Y]], [[TMP2]]
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[N0]], [[M:%.*]]
-; CHECK-NEXT: [[R:%.*]] = xor <2 x i4> [[TMP1]], [[X]]
+; CHECK-NEXT: [[R:%.*]] = xor <2 x i4> [[TMP1]], [[TMP2]]
; CHECK-NEXT: ret <2 x i4> [[R]]
;
%im = xor <2 x i4> %m, <i4 -1, i4 -1>
@@ -204,9 +212,10 @@ define <2 x i4> @c_0_0_1 (<2 x i4> %m) {
define <2 x i4> @c_1_1_0 (<2 x i4> %x, <2 x i4> %y, <2 x i4> %m) {
; CHECK-LABEL: @c_1_1_0(
-; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[X:%.*]] = freeze <2 x i4> [[Y1:%.*]]
+; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[Y:%.*]], [[X]]
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[N0]], [[M:%.*]]
-; CHECK-NEXT: [[R:%.*]] = xor <2 x i4> [[TMP1]], [[Y]]
+; CHECK-NEXT: [[R:%.*]] = xor <2 x i4> [[TMP1]], [[X]]
; CHECK-NEXT: ret <2 x i4> [[R]]
;
%im = xor <2 x i4> %m, <i4 -1, i4 -1>
@@ -219,7 +228,8 @@ define <2 x i4> @c_1_1_0 (<2 x i4> %x, <2 x i4> %y, <2 x i4> %m) {
define <2 x i4> @c_1_0_1 (<2 x i4> %x, <2 x i4> %m) {
; CHECK-LABEL: @c_1_0_1(
; CHECK-NEXT: [[Y:%.*]] = call <2 x i4> @gen4()
-; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[Y]], [[X:%.*]]
+; CHECK-NEXT: [[X:%.*]] = freeze <2 x i4> [[X1:%.*]]
+; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[Y]], [[X]]
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[N0]], [[M:%.*]]
; CHECK-NEXT: [[R:%.*]] = xor <2 x i4> [[TMP1]], [[X]]
; CHECK-NEXT: ret <2 x i4> [[R]]
@@ -235,7 +245,8 @@ define <2 x i4> @c_1_0_1 (<2 x i4> %x, <2 x i4> %m) {
define <2 x i4> @c_0_1_1 (<2 x i4> %y, <2 x i4> %m) {
; CHECK-LABEL: @c_0_1_1(
; CHECK-NEXT: [[X:%.*]] = call <2 x i4> @gen4()
-; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[X]], [[Y:%.*]]
+; CHECK-NEXT: [[Y:%.*]] = freeze <2 x i4> [[Y1:%.*]]
+; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[X]], [[Y]]
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[N0]], [[M:%.*]]
; CHECK-NEXT: [[R:%.*]] = xor <2 x i4> [[TMP1]], [[Y]]
; CHECK-NEXT: ret <2 x i4> [[R]]
@@ -252,9 +263,10 @@ define <2 x i4> @c_1_1_1 (<2 x i4> %m) {
; CHECK-LABEL: @c_1_1_1(
; CHECK-NEXT: [[X:%.*]] = call <2 x i4> @gen4()
; CHECK-NEXT: [[Y:%.*]] = call <2 x i4> @gen4()
-; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[Y]], [[X]]
+; CHECK-NEXT: [[TMP2:%.*]] = freeze <2 x i4> [[Y]]
+; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[X]], [[TMP2]]
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[N0]], [[M:%.*]]
-; CHECK-NEXT: [[R:%.*]] = xor <2 x i4> [[TMP1]], [[Y]]
+; CHECK-NEXT: [[R:%.*]] = xor <2 x i4> [[TMP1]], [[TMP2]]
; CHECK-NEXT: ret <2 x i4> [[R]]
;
%im = xor <2 x i4> %m, <i4 -1, i4 -1>
@@ -268,7 +280,8 @@ define <2 x i4> @c_1_1_1 (<2 x i4> %m) {
define <2 x i4> @commutativity_constant_varx_6_invmask(<2 x i4> %x, <2 x i4> %mask) {
; CHECK-LABEL: @commutativity_constant_varx_6_invmask(
-; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[X:%.*]], splat (i4 6)
+; CHECK-NEXT: [[X:%.*]] = freeze <2 x i4> [[X1:%.*]]
+; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[X]], splat (i4 6)
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[N0]], [[MASK:%.*]]
; CHECK-NEXT: [[R:%.*]] = xor <2 x i4> [[TMP1]], [[X]]
; CHECK-NEXT: ret <2 x i4> [[R]]
@@ -304,8 +317,10 @@ declare void @use4(<2 x i4>)
define <2 x i4> @n_oneuse_D_is_ok (<2 x i4> %x, <2 x i4> %y, <2 x i4> %m) {
; CHECK-LABEL: @n_oneuse_D_is_ok(
-; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[N0]], [[M:%.*]]
+; CHECK-NEXT: [[X:%.*]] = freeze <2 x i4> [[X1:%.*]]
+; CHECK-NEXT: [[N0:%.*]] = xor <2 x i4> [[X]], [[Y:%.*]]
+; CHECK-NEXT: [[TMP2:%.*]] = xor <2 x i4> [[Y]], [[X]]
+; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[TMP2]], [[M:%.*]]
; CHECK-NEXT: [[R:%.*]] = xor <2 x i4> [[TMP1]], [[X]]
; CHECK-NEXT: call void @use4(<2 x i4> [[N0]])
; CHECK-NEXT: ret <2 x i4> [[R]]
diff --git a/llvm/test/Transforms/InstCombine/masked-merge-xor.ll b/llvm/test/Transforms/InstCombine/masked-merge-xor.ll
index 6b83c0940d8d6..dead3467d1eae 100644
--- a/llvm/test/Transforms/InstCombine/masked-merge-xor.ll
+++ b/llvm/test/Transforms/InstCombine/masked-merge-xor.ll
@@ -430,9 +430,10 @@ define i32 @n3_constmask_samemask(i32 %x, i32 %y) {
define i4 @masked_merge_inverted_mask_maybe_undef_x(i4 %x, i4 %y, i4 %m) {
; CHECK-LABEL: @masked_merge_inverted_mask_maybe_undef_x(
-; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[Y:%.*]] = freeze i4 [[X1:%.*]]
+; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X:%.*]], [[Y]]
; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
-; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[X]]
+; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[Y]]
; CHECK-NEXT: ret i4 [[R]]
;
%im = xor i4 %m, -1
More information about the llvm-commits
mailing list