[llvm] [InstCombineSimplifyDemanded] Fold xor into or based on condition (PR #151870)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Aug 3 08:50:11 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Panagiotis Karouzakis (karouzakisp)
<details>
<summary>Changes</summary>
This patch folds a XOR operation into an OR one, if the conditions are valid.
(X & C1) ^ C2 --> (X & C1) | C2 iff(C1 & C2) == 0
This is always legal.
Alive proof: https://alive2.llvm.org/ce/z/3P2jdP
---
Full diff: https://github.com/llvm/llvm-project/pull/151870.diff
2 Files Affected:
- (modified) llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp (+11)
- (added) llvm/test/Transforms/InstCombine/xor-into-or.ll (+15)
``````````diff
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 0e3436d12702d..c24e831722a54 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -335,6 +335,17 @@ Value *InstCombinerImpl::SimplifyDemandedUseBits(Instruction *I,
return InsertNewInstWith(And, I->getIterator());
}
+ // If all of the demanded bits on one side are known, and all of the set
+ // bits on that side are also known to not be set on the other side, turn
+ // this into an OR, as we know the bits will not affect the result. e.g (X &
+ // C1) ^ C2 --> (X & C1) | C2 iff(C1 & C2) == 0
+ if (DemandedMask.isSubsetOf(RHSKnown.Zero | RHSKnown.One) &&
+ (RHSKnown.One.isSubsetOf(LHSKnown.Zero))) {
+ Instruction *Or =
+ BinaryOperator::CreateOr(I->getOperand(0), I->getOperand(1));
+ return InsertNewInstWith(Or, I->getIterator());
+ }
+
// If the RHS is a constant, see if we can change it. Don't alter a -1
// constant because that's a canonical 'not' op, and that is better for
// combining, SCEV, and codegen.
diff --git a/llvm/test/Transforms/InstCombine/xor-into-or.ll b/llvm/test/Transforms/InstCombine/xor-into-or.ll
new file mode 100644
index 0000000000000..b647941b9645c
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/xor-into-or.ll
@@ -0,0 +1,15 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+
+define i8 @a(i8 %x) nounwind {
+; CHECK-LABEL: @a(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[REM:%.*]] = and i8 [[X:%.*]], -120
+; CHECK-NEXT: [[XOR:%.*]] = or disjoint i8 [[REM]], 36
+; CHECK-NEXT: ret i8 [[XOR]]
+;
+entry:
+ %rem = and i8 %x, 136
+ %xor = xor i8 %rem, 36
+ ret i8 %xor
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/151870
More information about the llvm-commits
mailing list