mirror of
https://github.com/RPCSX/llvm.git
synced 2025-02-25 23:45:36 +00:00
[InstCombine] try to canonicalize xor-of-icmps to and-of-icmps
We have a large portfolio of folds for and-of-icmps and or-of-icmps in InstSimplify and InstCombine, but hardly anything for xor-of-icmps. Rather than trying to rethink and translate all of those folds, we can use the truth table definition of xor: X ^ Y --> (X | Y) & !(X & Y) ...to see if we can convert the xor to and/or and then use the existing folds. http://rise4fun.com/Alive/J9v Differential Revision: https://reviews.llvm.org/D33342 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@305792 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
a4b49d696a
commit
3e4188dc6c
@ -2351,6 +2351,30 @@ Value *InstCombiner::foldXorOfICmps(ICmpInst *LHS, ICmpInst *RHS) {
|
||||
}
|
||||
}
|
||||
|
||||
// Instead of trying to imitate the folds for and/or, decompose this 'xor'
|
||||
// into those logic ops. That is, try to turn this into an and-of-icmps
|
||||
// because we have many folds for that pattern.
|
||||
//
|
||||
// This is based on a truth table definition of xor:
|
||||
// X ^ Y --> (X | Y) & !(X & Y)
|
||||
if (Value *OrICmp = SimplifyBinOp(Instruction::Or, LHS, RHS, SQ)) {
|
||||
// TODO: If OrICmp is true, then the definition of xor simplifies to !(X&Y).
|
||||
// TODO: If OrICmp is false, the whole thing is false (InstSimplify?).
|
||||
if (Value *AndICmp = SimplifyBinOp(Instruction::And, LHS, RHS, SQ)) {
|
||||
// TODO: Independently handle cases where the 'and' side is a constant.
|
||||
if (OrICmp == LHS && AndICmp == RHS && RHS->hasOneUse()) {
|
||||
// (LHS | RHS) & !(LHS & RHS) --> LHS & !RHS
|
||||
RHS->setPredicate(RHS->getInversePredicate());
|
||||
return Builder->CreateAnd(LHS, RHS);
|
||||
}
|
||||
if (OrICmp == RHS && AndICmp == LHS && LHS->hasOneUse()) {
|
||||
// !(LHS & RHS) & (LHS | RHS) --> !LHS & !RHS
|
||||
LHS->setPredicate(LHS->getInversePredicate());
|
||||
return Builder->CreateAnd(LHS, RHS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -164,10 +164,8 @@ define i1 @bool_eq0(i64 %a) {
|
||||
|
||||
define i1 @xor_of_icmps(i64 %a) {
|
||||
; CHECK-LABEL: @xor_of_icmps(
|
||||
; CHECK-NEXT: [[B:%.*]] = icmp sgt i64 %a, 0
|
||||
; CHECK-NEXT: [[C:%.*]] = icmp eq i64 %a, 1
|
||||
; CHECK-NEXT: [[XOR:%.*]] = xor i1 [[C]], [[B]]
|
||||
; CHECK-NEXT: ret i1 [[XOR]]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i64 %a, 1
|
||||
; CHECK-NEXT: ret i1 [[TMP1]]
|
||||
;
|
||||
%b = icmp sgt i64 %a, 0
|
||||
%c = icmp eq i64 %a, 1
|
||||
@ -179,10 +177,8 @@ define i1 @xor_of_icmps(i64 %a) {
|
||||
|
||||
define i1 @xor_of_icmps_commute(i64 %a) {
|
||||
; CHECK-LABEL: @xor_of_icmps_commute(
|
||||
; CHECK-NEXT: [[B:%.*]] = icmp sgt i64 %a, 0
|
||||
; CHECK-NEXT: [[C:%.*]] = icmp eq i64 %a, 1
|
||||
; CHECK-NEXT: [[XOR:%.*]] = xor i1 [[B]], [[C]]
|
||||
; CHECK-NEXT: ret i1 [[XOR]]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i64 %a, 1
|
||||
; CHECK-NEXT: ret i1 [[TMP1]]
|
||||
;
|
||||
%b = icmp sgt i64 %a, 0
|
||||
%c = icmp eq i64 %a, 1
|
||||
@ -209,10 +205,10 @@ define i1 @xor_of_icmps_folds_more(i64 %a) {
|
||||
|
||||
define i32 @PR2844(i32 %x) {
|
||||
; CHECK-LABEL: @PR2844(
|
||||
; CHECK-NEXT: [[A:%.*]] = icmp eq i32 %x, 0
|
||||
; CHECK-NEXT: [[A:%.*]] = icmp ne i32 %x, 0
|
||||
; CHECK-NEXT: [[B:%.*]] = icmp sgt i32 %x, -638208502
|
||||
; CHECK-NEXT: [[NOT_OR:%.*]] = xor i1 [[A]], [[B]]
|
||||
; CHECK-NEXT: [[SEL:%.*]] = zext i1 [[NOT_OR]] to i32
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = and i1 [[A]], [[B]]
|
||||
; CHECK-NEXT: [[SEL:%.*]] = zext i1 [[TMP1]] to i32
|
||||
; CHECK-NEXT: ret i32 [[SEL]]
|
||||
;
|
||||
%A = icmp eq i32 %x, 0
|
||||
|
Loading…
x
Reference in New Issue
Block a user