mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-01 05:01:59 +01:00
[InstCombine] Simplify 'xor' to 'or' if no common bits are set.
Summary: In order to get the whole fold as specified in [[ https://bugs.llvm.org/show_bug.cgi?id=6773 | PR6773 ]], let's first handle the simple straight-forward things. Let's start with the `and` -> `or` simplification. The one obvious thing missing here: the constant mask is not handled. I have an idea how to handle it, but it will require some thinking, and is not strictly required here, so i've left that for later. https://rise4fun.com/Alive/Pkmg Reviewers: spatel, craig.topper, eli.friedman, jingyue Reviewed By: spatel Subscribers: llvm-commits Was reviewed as part of https://reviews.llvm.org/D45631 llvm-svn: 330103
This commit is contained in:
parent
23340b5f63
commit
afc2c5afb5
@ -2446,6 +2446,10 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
|
||||
if (Value *V = SimplifyBSwap(I, Builder))
|
||||
return replaceInstUsesWith(I, V);
|
||||
|
||||
// A^B --> A|B iff A and B have no bits set in common.
|
||||
if (haveNoCommonBitsSet(Op0, Op1, DL, &AC, &I, &DT))
|
||||
return BinaryOperator::CreateOr(Op0, Op1);
|
||||
|
||||
// Apply DeMorgan's Law for 'nand' / 'nor' logic with an inverted operand.
|
||||
Value *X, *Y;
|
||||
|
||||
|
@ -399,11 +399,8 @@ define i1 @bools_multi_uses1(i1 %a, i1 %b, i1 %c) {
|
||||
|
||||
define i1 @bools_multi_uses2(i1 %a, i1 %b, i1 %c) {
|
||||
; CHECK-LABEL: @bools_multi_uses2(
|
||||
; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[C:%.*]], true
|
||||
; CHECK-NEXT: [[AND1:%.*]] = and i1 [[NOT]], [[A:%.*]]
|
||||
; CHECK-NEXT: [[AND2:%.*]] = and i1 [[C]], [[B:%.*]]
|
||||
; CHECK-NEXT: [[ADD:%.*]] = xor i1 [[AND1]], [[AND2]]
|
||||
; CHECK-NEXT: ret i1 [[ADD]]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C:%.*]], i1 [[B:%.*]], i1 [[A:%.*]]
|
||||
; CHECK-NEXT: ret i1 [[TMP1]]
|
||||
;
|
||||
%not = xor i1 %c, -1
|
||||
%and1 = and i1 %not, %a
|
||||
|
@ -21,7 +21,7 @@ define i32 @p(i32 %x, i32 %y, i32 %m) {
|
||||
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], [[M:%.*]]
|
||||
; CHECK-NEXT: [[NEG:%.*]] = xor i32 [[M]], -1
|
||||
; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NEG]], [[Y:%.*]]
|
||||
; CHECK-NEXT: [[RET:%.*]] = xor i32 [[AND]], [[AND1]]
|
||||
; CHECK-NEXT: [[RET:%.*]] = or i32 [[AND]], [[AND1]]
|
||||
; CHECK-NEXT: ret i32 [[RET]]
|
||||
;
|
||||
%and = and i32 %x, %m
|
||||
@ -36,7 +36,7 @@ define <2 x i32> @p_splatvec(<2 x i32> %x, <2 x i32> %y, <2 x i32> %m) {
|
||||
; CHECK-NEXT: [[AND:%.*]] = and <2 x i32> [[X:%.*]], [[M:%.*]]
|
||||
; CHECK-NEXT: [[NEG:%.*]] = xor <2 x i32> [[M]], <i32 -1, i32 -1>
|
||||
; CHECK-NEXT: [[AND1:%.*]] = and <2 x i32> [[NEG]], [[Y:%.*]]
|
||||
; CHECK-NEXT: [[RET:%.*]] = xor <2 x i32> [[AND]], [[AND1]]
|
||||
; CHECK-NEXT: [[RET:%.*]] = or <2 x i32> [[AND]], [[AND1]]
|
||||
; CHECK-NEXT: ret <2 x i32> [[RET]]
|
||||
;
|
||||
%and = and <2 x i32> %x, %m
|
||||
@ -51,7 +51,7 @@ define <3 x i32> @p_vec_undef(<3 x i32> %x, <3 x i32> %y, <3 x i32> %m) {
|
||||
; CHECK-NEXT: [[AND:%.*]] = and <3 x i32> [[X:%.*]], [[M:%.*]]
|
||||
; CHECK-NEXT: [[NEG:%.*]] = xor <3 x i32> [[M]], <i32 -1, i32 undef, i32 -1>
|
||||
; CHECK-NEXT: [[AND1:%.*]] = and <3 x i32> [[NEG]], [[Y:%.*]]
|
||||
; CHECK-NEXT: [[RET:%.*]] = xor <3 x i32> [[AND]], [[AND1]]
|
||||
; CHECK-NEXT: [[RET:%.*]] = or <3 x i32> [[AND]], [[AND1]]
|
||||
; CHECK-NEXT: ret <3 x i32> [[RET]]
|
||||
;
|
||||
%and = and <3 x i32> %x, %m
|
||||
@ -129,7 +129,7 @@ define i32 @p_commutative0(i32 %x, i32 %y, i32 %m) {
|
||||
; CHECK-NEXT: [[AND:%.*]] = and i32 [[M:%.*]], [[X:%.*]]
|
||||
; CHECK-NEXT: [[NEG:%.*]] = xor i32 [[M]], -1
|
||||
; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NEG]], [[Y:%.*]]
|
||||
; CHECK-NEXT: [[RET:%.*]] = xor i32 [[AND]], [[AND1]]
|
||||
; CHECK-NEXT: [[RET:%.*]] = or i32 [[AND]], [[AND1]]
|
||||
; CHECK-NEXT: ret i32 [[RET]]
|
||||
;
|
||||
%and = and i32 %m, %x ; swapped order
|
||||
@ -145,7 +145,7 @@ define i32 @p_commutative1(i32 %x, i32 %m) {
|
||||
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], [[M:%.*]]
|
||||
; CHECK-NEXT: [[NEG:%.*]] = xor i32 [[M]], -1
|
||||
; CHECK-NEXT: [[AND1:%.*]] = and i32 [[Y]], [[NEG]]
|
||||
; CHECK-NEXT: [[RET:%.*]] = xor i32 [[AND]], [[AND1]]
|
||||
; CHECK-NEXT: [[RET:%.*]] = or i32 [[AND]], [[AND1]]
|
||||
; CHECK-NEXT: ret i32 [[RET]]
|
||||
;
|
||||
%y = call i32 @gen32()
|
||||
@ -161,7 +161,7 @@ define i32 @p_commutative2(i32 %x, i32 %y, i32 %m) {
|
||||
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], [[M:%.*]]
|
||||
; CHECK-NEXT: [[NEG:%.*]] = xor i32 [[M]], -1
|
||||
; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NEG]], [[Y:%.*]]
|
||||
; CHECK-NEXT: [[RET:%.*]] = xor i32 [[AND1]], [[AND]]
|
||||
; CHECK-NEXT: [[RET:%.*]] = or i32 [[AND1]], [[AND]]
|
||||
; CHECK-NEXT: ret i32 [[RET]]
|
||||
;
|
||||
%and = and i32 %x, %m
|
||||
@ -177,7 +177,7 @@ define i32 @p_commutative3(i32 %x, i32 %m) {
|
||||
; CHECK-NEXT: [[AND:%.*]] = and i32 [[M:%.*]], [[X:%.*]]
|
||||
; CHECK-NEXT: [[NEG:%.*]] = xor i32 [[M]], -1
|
||||
; CHECK-NEXT: [[AND1:%.*]] = and i32 [[Y]], [[NEG]]
|
||||
; CHECK-NEXT: [[RET:%.*]] = xor i32 [[AND]], [[AND1]]
|
||||
; CHECK-NEXT: [[RET:%.*]] = or i32 [[AND]], [[AND1]]
|
||||
; CHECK-NEXT: ret i32 [[RET]]
|
||||
;
|
||||
%y = call i32 @gen32()
|
||||
@ -193,7 +193,7 @@ define i32 @p_commutative4(i32 %x, i32 %y, i32 %m) {
|
||||
; CHECK-NEXT: [[AND:%.*]] = and i32 [[M:%.*]], [[X:%.*]]
|
||||
; CHECK-NEXT: [[NEG:%.*]] = xor i32 [[M]], -1
|
||||
; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NEG]], [[Y:%.*]]
|
||||
; CHECK-NEXT: [[RET:%.*]] = xor i32 [[AND1]], [[AND]]
|
||||
; CHECK-NEXT: [[RET:%.*]] = or i32 [[AND1]], [[AND]]
|
||||
; CHECK-NEXT: ret i32 [[RET]]
|
||||
;
|
||||
%and = and i32 %m, %x ; swapped order
|
||||
@ -209,7 +209,7 @@ define i32 @p_commutative5(i32 %x, i32 %m) {
|
||||
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], [[M:%.*]]
|
||||
; CHECK-NEXT: [[NEG:%.*]] = xor i32 [[M]], -1
|
||||
; CHECK-NEXT: [[AND1:%.*]] = and i32 [[Y]], [[NEG]]
|
||||
; CHECK-NEXT: [[RET:%.*]] = xor i32 [[AND1]], [[AND]]
|
||||
; CHECK-NEXT: [[RET:%.*]] = or i32 [[AND1]], [[AND]]
|
||||
; CHECK-NEXT: ret i32 [[RET]]
|
||||
;
|
||||
%y = call i32 @gen32()
|
||||
@ -226,7 +226,7 @@ define i32 @p_commutative6(i32 %x, i32 %m) {
|
||||
; CHECK-NEXT: [[AND:%.*]] = and i32 [[M:%.*]], [[X:%.*]]
|
||||
; CHECK-NEXT: [[NEG:%.*]] = xor i32 [[M]], -1
|
||||
; CHECK-NEXT: [[AND1:%.*]] = and i32 [[Y]], [[NEG]]
|
||||
; CHECK-NEXT: [[RET:%.*]] = xor i32 [[AND1]], [[AND]]
|
||||
; CHECK-NEXT: [[RET:%.*]] = or i32 [[AND1]], [[AND]]
|
||||
; CHECK-NEXT: ret i32 [[RET]]
|
||||
;
|
||||
%y = call i32 @gen32()
|
||||
@ -263,7 +263,7 @@ define i32 @n0_oneuse(i32 %x, i32 %y, i32 %m) {
|
||||
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], [[M:%.*]]
|
||||
; CHECK-NEXT: [[NEG:%.*]] = xor i32 [[M]], -1
|
||||
; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NEG]], [[Y:%.*]]
|
||||
; CHECK-NEXT: [[RET:%.*]] = xor i32 [[AND]], [[AND1]]
|
||||
; CHECK-NEXT: [[RET:%.*]] = or i32 [[AND]], [[AND1]]
|
||||
; CHECK-NEXT: call void @use32(i32 [[AND]])
|
||||
; CHECK-NEXT: call void @use32(i32 [[NEG]])
|
||||
; CHECK-NEXT: call void @use32(i32 [[AND1]])
|
||||
|
Loading…
x
Reference in New Issue
Block a user