-
Notifications
You must be signed in to change notification settings - Fork 15k
[InstCombine] Remove foldSelectICmpEq() fold #122098
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This fold matches complex patterns, for which we have no proof of real-world relevance, and which does not actually handle the originally motivating cases from llvm#71792. In llvm#121708 and llvm#121753 we have handled some simpler variants by extending existing folds. I propose to remove this code until we have evidence that it is useful for something.
@llvm/pr-subscribers-llvm-transforms Author: Nikita Popov (nikic) ChangesThis fold matches complex patterns, for which we have no proof of real-world relevance, and which does not actually handle the originally motivating cases from #71792 either. In #121708 and #121753 we have handled some simpler variants by extending existing folds. I propose to remove this code until we have evidence that it is useful for something. Full diff: https://github.com/llvm/llvm-project/pull/122098.diff 2 Files Affected:
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index c58a63483a717e..4ba9d52213aaf6 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -1843,92 +1843,6 @@ static Instruction *foldSelectICmpEq(SelectInst &SI, ICmpInst *ICI,
foldSelectWithExtremeEqCond(CmpLHS, CmpRHS, TrueVal, FalseVal))
return Res;
- // Transform (X == C) ? X : Y -> (X == C) ? C : Y
- // specific handling for Bitwise operation.
- // x&y -> (x|y) ^ (x^y) or (x|y) & ~(x^y)
- // x|y -> (x&y) | (x^y) or (x&y) ^ (x^y)
- // x^y -> (x|y) ^ (x&y) or (x|y) & ~(x&y)
- Value *X, *Y;
- if (!match(CmpLHS, m_BitwiseLogic(m_Value(X), m_Value(Y))) ||
- !match(TrueVal, m_c_BitwiseLogic(m_Specific(X), m_Specific(Y))))
- return nullptr;
-
- const unsigned AndOps = Instruction::And, OrOps = Instruction::Or,
- XorOps = Instruction::Xor, NoOps = 0;
- enum NotMask { None = 0, NotInner, NotRHS };
-
- auto matchFalseVal = [&](unsigned OuterOpc, unsigned InnerOpc,
- unsigned NotMask) {
- auto matchInner = m_c_BinOp(InnerOpc, m_Specific(X), m_Specific(Y));
- if (OuterOpc == NoOps)
- return match(CmpRHS, m_Zero()) && match(FalseVal, matchInner);
-
- if (NotMask == NotInner) {
- return match(FalseVal, m_c_BinOp(OuterOpc, m_NotForbidPoison(matchInner),
- m_Specific(CmpRHS)));
- } else if (NotMask == NotRHS) {
- return match(FalseVal, m_c_BinOp(OuterOpc, matchInner,
- m_NotForbidPoison(m_Specific(CmpRHS))));
- } else {
- return match(FalseVal,
- m_c_BinOp(OuterOpc, matchInner, m_Specific(CmpRHS)));
- }
- };
-
- // (X&Y)==C ? X|Y : X^Y -> (X^Y)|C : X^Y or (X^Y)^ C : X^Y
- // (X&Y)==C ? X^Y : X|Y -> (X|Y)^C : X|Y or (X|Y)&~C : X|Y
- if (match(CmpLHS, m_And(m_Value(X), m_Value(Y)))) {
- if (match(TrueVal, m_c_Or(m_Specific(X), m_Specific(Y)))) {
- // (X&Y)==C ? X|Y : (X^Y)|C -> (X^Y)|C : (X^Y)|C -> (X^Y)|C
- // (X&Y)==C ? X|Y : (X^Y)^C -> (X^Y)^C : (X^Y)^C -> (X^Y)^C
- if (matchFalseVal(OrOps, XorOps, None) ||
- matchFalseVal(XorOps, XorOps, None))
- return IC.replaceInstUsesWith(SI, FalseVal);
- } else if (match(TrueVal, m_c_Xor(m_Specific(X), m_Specific(Y)))) {
- // (X&Y)==C ? X^Y : (X|Y)^ C -> (X|Y)^ C : (X|Y)^ C -> (X|Y)^ C
- // (X&Y)==C ? X^Y : (X|Y)&~C -> (X|Y)&~C : (X|Y)&~C -> (X|Y)&~C
- if (matchFalseVal(XorOps, OrOps, None) ||
- matchFalseVal(AndOps, OrOps, NotRHS))
- return IC.replaceInstUsesWith(SI, FalseVal);
- }
- }
-
- // (X|Y)==C ? X&Y : X^Y -> (X^Y)^C : X^Y or ~(X^Y)&C : X^Y
- // (X|Y)==C ? X^Y : X&Y -> (X&Y)^C : X&Y or ~(X&Y)&C : X&Y
- if (match(CmpLHS, m_Or(m_Value(X), m_Value(Y)))) {
- if (match(TrueVal, m_c_And(m_Specific(X), m_Specific(Y)))) {
- // (X|Y)==C ? X&Y: (X^Y)^C -> (X^Y)^C: (X^Y)^C -> (X^Y)^C
- // (X|Y)==C ? X&Y:~(X^Y)&C ->~(X^Y)&C:~(X^Y)&C -> ~(X^Y)&C
- if (matchFalseVal(XorOps, XorOps, None) ||
- matchFalseVal(AndOps, XorOps, NotInner))
- return IC.replaceInstUsesWith(SI, FalseVal);
- } else if (match(TrueVal, m_c_Xor(m_Specific(X), m_Specific(Y)))) {
- // (X|Y)==C ? X^Y : (X&Y)^C -> (X&Y)^C : (X&Y)^C -> (X&Y)^C
- // (X|Y)==C ? X^Y :~(X&Y)&C -> ~(X&Y)&C :~(X&Y)&C -> ~(X&Y)&C
- if (matchFalseVal(XorOps, AndOps, None) ||
- matchFalseVal(AndOps, AndOps, NotInner))
- return IC.replaceInstUsesWith(SI, FalseVal);
- }
- }
-
- // (X^Y)==C ? X&Y : X|Y -> (X|Y)^C : X|Y or (X|Y)&~C : X|Y
- // (X^Y)==C ? X|Y : X&Y -> (X&Y)|C : X&Y or (X&Y)^ C : X&Y
- if (match(CmpLHS, m_Xor(m_Value(X), m_Value(Y)))) {
- if ((match(TrueVal, m_c_And(m_Specific(X), m_Specific(Y))))) {
- // (X^Y)==C ? X&Y : (X|Y)^C -> (X|Y)^C
- // (X^Y)==C ? X&Y : (X|Y)&~C -> (X|Y)&~C
- if (matchFalseVal(XorOps, OrOps, None) ||
- matchFalseVal(AndOps, OrOps, NotRHS))
- return IC.replaceInstUsesWith(SI, FalseVal);
- } else if (match(TrueVal, m_c_Or(m_Specific(X), m_Specific(Y)))) {
- // (X^Y)==C ? (X|Y) : (X&Y)|C -> (X&Y)|C
- // (X^Y)==C ? (X|Y) : (X&Y)^C -> (X&Y)^C
- if (matchFalseVal(OrOps, AndOps, None) ||
- matchFalseVal(XorOps, AndOps, None))
- return IC.replaceInstUsesWith(SI, FalseVal);
- }
- }
-
return nullptr;
}
diff --git a/llvm/test/Transforms/InstCombine/select.ll b/llvm/test/Transforms/InstCombine/select.ll
index 0f15fa6c0cc50a..3c3111492fc681 100644
--- a/llvm/test/Transforms/InstCombine/select.ll
+++ b/llvm/test/Transforms/InstCombine/select.ll
@@ -3841,9 +3841,13 @@ entry:
define i32 @src_and_eq_C_or_xororC(i32 %x, i32 %y, i32 %c) {
; CHECK-LABEL: @src_and_eq_C_or_xororC(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[OR1:%.*]] = or i32 [[XOR]], [[C:%.*]]
-; CHECK-NEXT: ret i32 [[OR1]]
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], [[C:%.*]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
+; CHECK-NEXT: [[OR1:%.*]] = or i32 [[XOR]], [[C]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[OR]], i32 [[OR1]]
+; CHECK-NEXT: ret i32 [[COND]]
;
entry:
%and = and i32 %y, %x
@@ -3858,9 +3862,13 @@ entry:
define i32 @src_and_eq_C_or_xorxorC(i32 %x, i32 %y, i32 %c) {
; CHECK-LABEL: @src_and_eq_C_or_xorxorC(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[XOR]], [[C:%.*]]
-; CHECK-NEXT: ret i32 [[XOR1]]
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], [[C:%.*]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
+; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[XOR]], [[C]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[OR]], i32 [[XOR1]]
+; CHECK-NEXT: ret i32 [[COND]]
;
entry:
%and = and i32 %y, %x
@@ -3875,10 +3883,14 @@ entry:
define i32 @src_and_eq_C_xor_OrAndNotC(i32 %x, i32 %y, i32 %c) {
; CHECK-LABEL: @src_and_eq_C_xor_OrAndNotC(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[C:%.*]], -1
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], [[C:%.*]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
+; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[C]], -1
; CHECK-NEXT: [[AND1:%.*]] = and i32 [[OR]], [[NOT]]
-; CHECK-NEXT: ret i32 [[AND1]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[XOR]], i32 [[AND1]]
+; CHECK-NEXT: ret i32 [[COND]]
;
entry:
%and = and i32 %y, %x
@@ -3917,9 +3929,13 @@ entry:
define i32 @src_and_eq_C_xor_orxorC(i32 %x, i32 %y, i32 %c) {
; CHECK-LABEL: @src_and_eq_C_xor_orxorC(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[OR]], [[C:%.*]]
-; CHECK-NEXT: ret i32 [[XOR1]]
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], [[C:%.*]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
+; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[OR]], [[C]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[XOR]], i32 [[XOR1]]
+; CHECK-NEXT: ret i32 [[COND]]
;
entry:
%and = and i32 %y, %x
@@ -3968,9 +3984,13 @@ entry:
define i32 @src_or_eq_neg1_and_xor(i32 %x, i32 %y) {
; CHECK-LABEL: @src_or_eq_neg1_and_xor(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP0:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[OR]], -1
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
+; CHECK-NEXT: [[TMP0:%.*]] = xor i32 [[X]], [[Y]]
; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[TMP0]], -1
-; CHECK-NEXT: ret i32 [[NOT]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[AND]], i32 [[NOT]]
+; CHECK-NEXT: ret i32 [[COND]]
;
entry:
%or = or i32 %y, %x
@@ -3985,9 +4005,13 @@ entry:
define i32 @src_or_eq_neg1_xor_and(i32 %x, i32 %y) {
; CHECK-LABEL: @src_or_eq_neg1_xor_and(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[OR]], -1
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[AND]], -1
-; CHECK-NEXT: ret i32 [[NOT]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[XOR]], i32 [[NOT]]
+; CHECK-NEXT: ret i32 [[COND]]
;
entry:
%or = or i32 %y, %x
@@ -4002,9 +4026,13 @@ entry:
define i32 @src_or_eq_C_and_xorC(i32 %x, i32 %y, i32 %c) {
; CHECK-LABEL: @src_or_eq_C_and_xorC(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[XOR]], [[C:%.*]]
-; CHECK-NEXT: ret i32 [[XOR1]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[OR]], [[C:%.*]]
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
+; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[XOR]], [[C]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[AND]], i32 [[XOR1]]
+; CHECK-NEXT: ret i32 [[COND]]
;
entry:
%or = or i32 %y, %x
@@ -4019,10 +4047,14 @@ entry:
define i32 @src_or_eq_C_and_andnotxorC(i32 %x, i32 %y, i32 %c) {
; CHECK-LABEL: @src_or_eq_C_and_andnotxorC(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP0:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[OR]], [[C:%.*]]
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
+; CHECK-NEXT: [[TMP0:%.*]] = xor i32 [[X]], [[Y]]
; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[TMP0]], -1
-; CHECK-NEXT: [[AND1:%.*]] = and i32 [[C:%.*]], [[NOT]]
-; CHECK-NEXT: ret i32 [[AND1]]
+; CHECK-NEXT: [[AND1:%.*]] = and i32 [[C]], [[NOT]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[AND]], i32 [[AND1]]
+; CHECK-NEXT: ret i32 [[COND]]
;
entry:
%or = or i32 %y, %x
@@ -4038,9 +4070,13 @@ entry:
define i32 @src_or_eq_C_xor_xorandC(i32 %x, i32 %y, i32 %c) {
; CHECK-LABEL: @src_or_eq_C_xor_xorandC(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[AND]], [[C:%.*]]
-; CHECK-NEXT: ret i32 [[XOR1]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[OR]], [[C:%.*]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
+; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[AND]], [[C]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[XOR]], i32 [[XOR1]]
+; CHECK-NEXT: ret i32 [[COND]]
;
entry:
%or = or i32 %y, %x
@@ -4055,10 +4091,14 @@ entry:
define i32 @src_or_eq_C_xor_andnotandC(i32 %x, i32 %y, i32 %c) {
; CHECK-LABEL: @src_or_eq_C_xor_andnotandC(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[OR]], [[C:%.*]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[AND]], -1
-; CHECK-NEXT: [[AND1:%.*]] = and i32 [[C:%.*]], [[NOT]]
-; CHECK-NEXT: ret i32 [[AND1]]
+; CHECK-NEXT: [[AND1:%.*]] = and i32 [[C]], [[NOT]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[XOR]], i32 [[AND1]]
+; CHECK-NEXT: ret i32 [[COND]]
;
entry:
%or = or i32 %y, %x
@@ -4076,9 +4116,13 @@ entry:
define i32 @src_xor_eq_neg1_and(i32 %x, i32 %y) {
; CHECK-LABEL: @src_xor_eq_neg1_and(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[XOR]], -1
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[OR]], -1
-; CHECK-NEXT: ret i32 [[NOT]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[AND]], i32 [[NOT]]
+; CHECK-NEXT: ret i32 [[COND]]
;
entry:
%xor = xor i32 %y, %x
@@ -4111,9 +4155,13 @@ entry:
define i32 @src_xor_eq_C_and_xororC(i32 %x, i32 %y, i32 %c) {
; CHECK-LABEL: @src_xor_eq_C_and_xororC(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[OR]], [[C:%.*]]
-; CHECK-NEXT: ret i32 [[XOR1]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[XOR]], [[C:%.*]]
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
+; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[OR]], [[C]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[AND]], i32 [[XOR1]]
+; CHECK-NEXT: ret i32 [[COND]]
;
entry:
%xor = xor i32 %y, %x
@@ -4128,10 +4176,14 @@ entry:
define i32 @src_xor_eq_C_and_andornotC(i32 %x, i32 %y, i32 %c) {
; CHECK-LABEL: @src_xor_eq_C_and_andornotC(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[C:%.*]], -1
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[XOR]], [[C:%.*]]
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
+; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[C]], -1
; CHECK-NEXT: [[AND1:%.*]] = and i32 [[OR]], [[NOT]]
-; CHECK-NEXT: ret i32 [[AND1]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[AND]], i32 [[AND1]]
+; CHECK-NEXT: ret i32 [[COND]]
;
entry:
%xor = xor i32 %y, %x
@@ -4147,9 +4199,13 @@ entry:
define i32 @src_xor_eq_C_or_xorandC(i32 %x, i32 %y, i32 %c) {
; CHECK-LABEL: @src_xor_eq_C_or_xorandC(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[AND]], [[C:%.*]]
-; CHECK-NEXT: ret i32 [[XOR1]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[XOR]], [[C:%.*]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
+; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[AND]], [[C]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[OR]], i32 [[XOR1]]
+; CHECK-NEXT: ret i32 [[COND]]
;
entry:
%xor = xor i32 %y, %x
@@ -4164,9 +4220,13 @@ entry:
define i32 @src_xor_eq_C_or_orandC(i32 %x, i32 %y, i32 %c) {
; CHECK-LABEL: @src_xor_eq_C_or_orandC(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[OR1:%.*]] = or i32 [[AND]], [[C:%.*]]
-; CHECK-NEXT: ret i32 [[OR1]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[XOR]], [[C:%.*]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], [[X]]
+; CHECK-NEXT: [[OR1:%.*]] = or i32 [[AND]], [[C]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[OR]], i32 [[OR1]]
+; CHECK-NEXT: ret i32 [[COND]]
;
entry:
%xor = xor i32 %y, %x
|
+1 |
This fold matches complex patterns, for which we have no proof of real-world relevance, and which does not actually handle the originally motivating cases from #71792 either.
In #121708 and #121753 we have handled some simpler variants by extending existing folds.
I propose to remove this code until we have evidence that it is useful for something.