[llvm] [InstCombine] Fix undef widening in masked-merge (PR #219212)

via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 27 06:26:36 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Kryptonite (OmarAzizi)

<details>
<summary>Changes</summary>

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)

---
Full diff: https://github.com/llvm/llvm-project/pull/219212.diff


4 Files Affected:

- (modified) llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp (+9-2) 
- (modified) llvm/test/Transforms/InstCombine/invert-variable-mask-in-masked-merge-scalar.ll (+28-16) 
- (modified) llvm/test/Transforms/InstCombine/invert-variable-mask-in-masked-merge-vector.ll (+35-20) 
- (modified) llvm/test/Transforms/InstCombine/masked-merge-xor.ll (+29) 


``````````diff
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 463f220fcbb6d..dead3467d1eae 100644
--- a/llvm/test/Transforms/InstCombine/masked-merge-xor.ll
+++ b/llvm/test/Transforms/InstCombine/masked-merge-xor.ll
@@ -427,3 +427,32 @@ 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:    [[Y:%.*]] = freeze i4 [[X1:%.*]]
+; 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]]
+;
+  %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
+}

``````````

</details>


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


More information about the llvm-commits mailing list