mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-25 00:29:20 +00:00
InstCombine: Fold ((A | B) & C1) ^ (B & C2) -> (A & C1) ^ B if C1^C2=-1
Adapted from a patch by Richard Smith, test-case written by me. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@216157 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
e88b796285
commit
e234f93b3e
@ -152,6 +152,8 @@ public:
|
||||
Value *FoldOrOfFCmps(FCmpInst *LHS, FCmpInst *RHS);
|
||||
Instruction *FoldOrWithConstants(BinaryOperator &I, Value *Op, Value *A,
|
||||
Value *B, Value *C);
|
||||
Instruction *FoldXorWithConstants(BinaryOperator &I, Value *Op, Value *A,
|
||||
Value *B, Value *C);
|
||||
Instruction *visitOr(BinaryOperator &I);
|
||||
Instruction *visitXor(BinaryOperator &I);
|
||||
Instruction *visitShl(BinaryOperator &I);
|
||||
|
@ -1983,6 +1983,38 @@ Instruction *InstCombiner::FoldOrWithConstants(BinaryOperator &I, Value *Op,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// \brief This helper function folds:
|
||||
///
|
||||
/// ((A | B) & C1) ^ (B & C2)
|
||||
///
|
||||
/// into:
|
||||
///
|
||||
/// (A & C1) ^ B
|
||||
///
|
||||
/// when the XOR of the two constants is "all ones" (-1).
|
||||
Instruction *InstCombiner::FoldXorWithConstants(BinaryOperator &I, Value *Op,
|
||||
Value *A, Value *B, Value *C) {
|
||||
ConstantInt *CI1 = dyn_cast<ConstantInt>(C);
|
||||
if (!CI1)
|
||||
return nullptr;
|
||||
|
||||
Value *V1 = nullptr;
|
||||
ConstantInt *CI2 = nullptr;
|
||||
if (!match(Op, m_And(m_Value(V1), m_ConstantInt(CI2))))
|
||||
return nullptr;
|
||||
|
||||
APInt Xor = CI1->getValue() ^ CI2->getValue();
|
||||
if (!Xor.isAllOnesValue())
|
||||
return nullptr;
|
||||
|
||||
if (V1 == A || V1 == B) {
|
||||
Value *NewOp = Builder->CreateAnd(V1 == A ? B : A, CI1);
|
||||
return BinaryOperator::CreateXor(NewOp, V1);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Instruction *InstCombiner::visitOr(BinaryOperator &I) {
|
||||
bool Changed = SimplifyAssociativeOrCommutative(I);
|
||||
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
||||
@ -2165,6 +2197,18 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
|
||||
Instruction *Ret = FoldOrWithConstants(I, Op0, A, V1, D);
|
||||
if (Ret) return Ret;
|
||||
}
|
||||
// ((A^B)&1)|(B&-2) -> (A&1) ^ B
|
||||
if (match(A, m_Xor(m_Value(V1), m_Specific(B))) ||
|
||||
match(A, m_Xor(m_Specific(B), m_Value(V1)))) {
|
||||
Instruction *Ret = FoldXorWithConstants(I, Op1, V1, B, C);
|
||||
if (Ret) return Ret;
|
||||
}
|
||||
// (B&-2)|((A^B)&1) -> (A&1) ^ B
|
||||
if (match(B, m_Xor(m_Specific(A), m_Value(V1))) ||
|
||||
match(B, m_Xor(m_Value(V1), m_Specific(A)))) {
|
||||
Instruction *Ret = FoldXorWithConstants(I, Op0, A, V1, D);
|
||||
if (Ret) return Ret;
|
||||
}
|
||||
}
|
||||
|
||||
// (A ^ B) | ((B ^ C) ^ A) -> (A ^ B) | C
|
||||
|
@ -173,3 +173,11 @@ define i32 @test17(i32 %x, i32 %y) {
|
||||
; CHECK-NEXT: %xor = xor i32 %x, %y
|
||||
; CHECK-NEXT: ret i32 %xor
|
||||
}
|
||||
|
||||
define i32 @test18(i32 %a, i32 %b) {
|
||||
%or = xor i32 %a, %b
|
||||
%and1 = and i32 %or, 1
|
||||
%and2 = and i32 %b, -2
|
||||
%xor = or i32 %and1, %and2
|
||||
ret i32 %xor
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user