-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[InstCombine] Guard noundef for transformation from xor to or disjoint #96905
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
@llvm/pr-subscribers-llvm-transforms Author: Allen (vfdff) ChangesFix #96857 Full diff: https://github.com/llvm/llvm-project/pull/96905.diff 2 Files Affected:
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index d767fa3930e2f..a8547b40eb6b0 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -4593,8 +4593,12 @@ Instruction *InstCombinerImpl::visitXor(BinaryOperator &I) {
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
Value *M;
if (match(&I, m_c_Xor(m_c_And(m_Not(m_Value(M)), m_Value()),
- m_c_And(m_Deferred(M), m_Value()))))
- return BinaryOperator::CreateDisjointOr(Op0, Op1);
+ m_c_And(m_Deferred(M), m_Value())))) {
+ if (isGuaranteedNotToBeUndefOrPoison(M))
+ return BinaryOperator::CreateDisjointOr(Op0, Op1);
+ else
+ return BinaryOperator::CreateOr(Op0, Op1);
+ }
if (Instruction *Xor = visitMaskedMerge(I, Builder))
return Xor;
diff --git a/llvm/test/Transforms/InstCombine/xor.ll b/llvm/test/Transforms/InstCombine/xor.ll
index 9a59db40ef8b1..2ff95821f4e00 100644
--- a/llvm/test/Transforms/InstCombine/xor.ll
+++ b/llvm/test/Transforms/InstCombine/xor.ll
@@ -1453,3 +1453,35 @@ define i32 @tryFactorization_xor_ashr_ashr(i32 %a) {
%xor = xor i32 %not, %shr1
ret i32 %xor
}
+
+; https://alive2.llvm.org/ce/z/SOxv-e
+define i4 @PR96857_xor_with_noundef(i4 %val0, i4 %val1, i4 noundef %val2) {
+; CHECK-LABEL: @PR96857_xor_with_noundef(
+; CHECK-NEXT: [[VAL4:%.*]] = and i4 [[VAL2:%.*]], [[VAL0:%.*]]
+; CHECK-NEXT: [[VAL5:%.*]] = xor i4 [[VAL2]], -1
+; CHECK-NEXT: [[VAL6:%.*]] = and i4 [[VAL5]], [[VAL1:%.*]]
+; CHECK-NEXT: [[VAL7:%.*]] = or disjoint i4 [[VAL4]], [[VAL6]]
+; CHECK-NEXT: ret i4 [[VAL7]]
+;
+ %val4 = and i4 %val2, %val0
+ %val5 = xor i4 %val2, -1
+ %val6 = and i4 %val5, %val1
+ %val7 = xor i4 %val4, %val6
+ ret i4 %val7
+}
+
+; https://alive2.llvm.org/ce/z/whLTaJ
+define i4 @PR96857_xor_without_noundef(i4 %val0, i4 %val1, i4 %val2) {
+; CHECK-LABEL: @PR96857_xor_without_noundef(
+; CHECK-NEXT: [[VAL4:%.*]] = and i4 [[VAL2:%.*]], [[VAL0:%.*]]
+; CHECK-NEXT: [[VAL5:%.*]] = xor i4 [[VAL2]], -1
+; CHECK-NEXT: [[VAL6:%.*]] = and i4 [[VAL5]], [[VAL1:%.*]]
+; CHECK-NEXT: [[VAL7:%.*]] = or i4 [[VAL4]], [[VAL6]]
+; CHECK-NEXT: ret i4 [[VAL7]]
+;
+ %val4 = and i4 %val2, %val0
+ %val5 = xor i4 %val2, -1
+ %val6 = and i4 %val5, %val1
+ %val7 = xor i4 %val4, %val6
+ ret i4 %val7
+}
|
m_c_And(m_Deferred(M), m_Value())))) | ||
return BinaryOperator::CreateDisjointOr(Op0, Op1); | ||
m_c_And(m_Deferred(M), m_Value())))) { | ||
if (isGuaranteedNotToBeUndefOrPoison(M)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (isGuaranteedNotToBeUndefOrPoison(M)) | |
if (isGuaranteedNotToBeUndef(M)) |
It is safe if M is a poison value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update, thanks @dtcxzyw
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Thanks for your review |
Fix #96857