Skip to content

Commit 9678936

Browse files
committed
[DAGCombine] Fold (X & ~Y) | Y with truncated not
This extends the (X & ~Y) | Y to X | Y fold to also work if ~Y is a truncated not (when taking into account the mask X). This is done by exporting the infrastructure added in D124856 and reusing it here. I've retained the old value of AllowUndefs=false, though probably this can be switched to true with extra test coverage. Differential Revision: https://reviews.llvm.org/D124930
1 parent 6bd2b70 commit 9678936

File tree

4 files changed

+21
-18
lines changed

4 files changed

+21
-18
lines changed

llvm/include/llvm/CodeGen/SelectionDAGNodes.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1688,6 +1688,11 @@ SDValue peekThroughExtractSubvectors(SDValue V);
16881688
/// constant is canonicalized to be operand 1.
16891689
bool isBitwiseNot(SDValue V, bool AllowUndefs = false);
16901690

1691+
/// If \p V is a bitwise not, returns the inverted operand. Otherwise returns
1692+
/// an empty SDValue. Only bits set in \p Mask are required to be inverted,
1693+
/// other bits may be arbitrary.
1694+
SDValue getBitwiseNotOperand(SDValue V, SDValue Mask, bool AllowUndefs);
1695+
16911696
/// Returns the SDNode if it is a constant splat BuildVector or constant int.
16921697
ConstantSDNode *isConstOrConstSplat(SDValue N, bool AllowUndefs = false,
16931698
bool AllowTruncation = false);

llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6814,11 +6814,14 @@ static SDValue visitORCommutative(
68146814
EVT VT = N0.getValueType();
68156815
if (N0.getOpcode() == ISD::AND) {
68166816
// fold (or (and X, (xor Y, -1)), Y) -> (or X, Y)
6817-
if (isBitwiseNot(N0.getOperand(1)) && N0.getOperand(1).getOperand(0) == N1)
6817+
// TODO: Set AllowUndefs = true.
6818+
if (getBitwiseNotOperand(N0.getOperand(1), N0.getOperand(0),
6819+
/* AllowUndefs */ false) == N1)
68186820
return DAG.getNode(ISD::OR, SDLoc(N), VT, N0.getOperand(0), N1);
68196821

68206822
// fold (or (and (xor Y, -1), X), Y) -> (or X, Y)
6821-
if (isBitwiseNot(N0.getOperand(0)) && N0.getOperand(0).getOperand(0) == N1)
6823+
if (getBitwiseNotOperand(N0.getOperand(0), N0.getOperand(1),
6824+
/* AllowUndefs */ false) == N1)
68226825
return DAG.getNode(ISD::OR, SDLoc(N), VT, N0.getOperand(1), N1);
68236826
}
68246827

llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4685,8 +4685,8 @@ bool SelectionDAG::isEqualTo(SDValue A, SDValue B) const {
46854685
}
46864686

46874687
// Only bits set in Mask must be negated, other bits may be arbitrary.
4688-
static SDValue getBitwiseNotOperand(SDValue V, SDValue Mask) {
4689-
if (isBitwiseNot(V, true))
4688+
SDValue llvm::getBitwiseNotOperand(SDValue V, SDValue Mask, bool AllowUndefs) {
4689+
if (isBitwiseNot(V, AllowUndefs))
46904690
return V.getOperand(0);
46914691

46924692
// Handle any_extend (not (truncate X)) pattern, where Mask only sets
@@ -4697,7 +4697,7 @@ static SDValue getBitwiseNotOperand(SDValue V, SDValue Mask) {
46974697
SDValue ExtArg = V.getOperand(0);
46984698
if (ExtArg.getScalarValueSizeInBits() >=
46994699
MaskC->getAPIntValue().getActiveBits() &&
4700-
isBitwiseNot(ExtArg, true) &&
4700+
isBitwiseNot(ExtArg, AllowUndefs) &&
47014701
ExtArg.getOperand(0).getOpcode() == ISD::TRUNCATE &&
47024702
ExtArg.getOperand(0).getOperand(0).getValueType() == V.getValueType())
47034703
return ExtArg.getOperand(0).getOperand(0);
@@ -4709,7 +4709,8 @@ static bool haveNoCommonBitsSetCommutative(SDValue A, SDValue B) {
47094709
// Including degenerate case (X & ~M) op M
47104710
auto MatchNoCommonBitsPattern = [&](SDValue Not, SDValue Mask,
47114711
SDValue Other) {
4712-
if (SDValue NotOperand = getBitwiseNotOperand(Not, Mask)) {
4712+
if (SDValue NotOperand =
4713+
getBitwiseNotOperand(Not, Mask, /* AllowUndefs */ true)) {
47134714
if (Other == NotOperand)
47144715
return true;
47154716
if (Other->getOpcode() == ISD::AND)

llvm/test/CodeGen/X86/add-and-not.ll

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,8 @@ define i8 @add_and_xor_extra_use(i8 %x, i8 %y) nounwind {
118118
define i64 @add_and_xor_const(i64 %x) {
119119
; CHECK-LABEL: add_and_xor_const:
120120
; CHECK: # %bb.0:
121-
; CHECK-NEXT: movl %edi, %eax
122-
; CHECK-NEXT: notl %eax
123-
; CHECK-NEXT: andl $1, %eax
124-
; CHECK-NEXT: orq %rdi, %rax
121+
; CHECK-NEXT: movq %rdi, %rax
122+
; CHECK-NEXT: orq $1, %rax
125123
; CHECK-NEXT: retq
126124
%xor = xor i64 %x, -1
127125
%and = and i64 %xor, 1
@@ -145,10 +143,8 @@ define i64 @add_and_xor_const_wrong_op(i64 %x, i64 %y) {
145143
define i64 @add_and_xor_const_explicit_trunc(i64 %x) {
146144
; CHECK-LABEL: add_and_xor_const_explicit_trunc:
147145
; CHECK: # %bb.0:
148-
; CHECK-NEXT: movl %edi, %eax
149-
; CHECK-NEXT: notl %eax
150-
; CHECK-NEXT: andl $1, %eax
151-
; CHECK-NEXT: orq %rdi, %rax
146+
; CHECK-NEXT: movq %rdi, %rax
147+
; CHECK-NEXT: orq $1, %rax
152148
; CHECK-NEXT: retq
153149
%trunc = trunc i64 %x to i32
154150
%xor = xor i32 %trunc, -1
@@ -192,10 +188,8 @@ define i8* @gep_and_xor(i8* %a, i64 %m) {
192188
define i8* @gep_and_xor_const(i8* %a) {
193189
; CHECK-LABEL: gep_and_xor_const:
194190
; CHECK: # %bb.0:
195-
; CHECK-NEXT: movl %edi, %eax
196-
; CHECK-NEXT: notl %eax
197-
; CHECK-NEXT: andl $1, %eax
198-
; CHECK-NEXT: orq %rdi, %rax
191+
; CHECK-NEXT: movq %rdi, %rax
192+
; CHECK-NEXT: orq $1, %rax
199193
; CHECK-NEXT: retq
200194
%old = ptrtoint i8* %a to i64
201195
%old.not = and i64 %old, 1

0 commit comments

Comments
 (0)