Skip to content

Commit 7c25db3

Browse files
simonzgxRKSimon
andauthored
[DAG] Fold (and X, (add (not Y), Z)) -> (and X, (not (sub Y, Z))). (#141476)
Fixes #140639 --------- Co-authored-by: Simon Pilgrim <[email protected]>
1 parent 8e333e3 commit 7c25db3

File tree

3 files changed

+126
-6
lines changed

3 files changed

+126
-6
lines changed

llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,8 @@ namespace {
396396
bool PromoteLoad(SDValue Op);
397397

398398
SDValue foldShiftToAvg(SDNode *N);
399+
// Fold `a bitwiseop (~b +/- c)` -> `a bitwiseop ~(b -/+ c)`
400+
SDValue foldBitwiseOpWithNeg(SDNode *N, const SDLoc &DL, EVT VT);
399401

400402
SDValue combineMinNumMaxNum(const SDLoc &DL, EVT VT, SDValue LHS,
401403
SDValue RHS, SDValue True, SDValue False,
@@ -7541,6 +7543,12 @@ SDValue DAGCombiner::visitAND(SDNode *N) {
75417543
return DAG.getNode(ISD::AND, DL, VT, X,
75427544
DAG.getNOT(DL, DAG.getNode(Opc, DL, VT, Y, Z), VT));
75437545

7546+
// Fold (and X, (add (not Y), Z)) -> (and X, (not (sub Y, Z)))
7547+
// Fold (and X, (sub (not Y), Z)) -> (and X, (not (add Y, Z)))
7548+
if (TLI.hasAndNot(SDValue(N, 0)))
7549+
if (SDValue Folded = foldBitwiseOpWithNeg(N, DL, VT))
7550+
return Folded;
7551+
75447552
// Fold (and (srl X, C), 1) -> (srl X, BW-1) for signbit extraction
75457553
// If we are shifting down an extended sign bit, see if we can simplify
75467554
// this to shifting the MSB directly to expose further simplifications.
@@ -11652,6 +11660,22 @@ SDValue DAGCombiner::foldShiftToAvg(SDNode *N) {
1165211660
return DAG.getNode(FloorISD, SDLoc(N), N->getValueType(0), {A, B});
1165311661
}
1165411662

11663+
SDValue DAGCombiner::foldBitwiseOpWithNeg(SDNode *N, const SDLoc &DL, EVT VT) {
11664+
unsigned Opc = N->getOpcode();
11665+
SDValue X, Y, Z;
11666+
if (sd_match(
11667+
N, m_BitwiseLogic(m_Value(X), m_Add(m_Not(m_Value(Y)), m_Value(Z)))))
11668+
return DAG.getNode(Opc, DL, VT, X,
11669+
DAG.getNOT(DL, DAG.getNode(ISD::SUB, DL, VT, Y, Z), VT));
11670+
11671+
if (sd_match(N, m_BitwiseLogic(m_Value(X), m_Sub(m_OneUse(m_Not(m_Value(Y))),
11672+
m_Value(Z)))))
11673+
return DAG.getNode(Opc, DL, VT, X,
11674+
DAG.getNOT(DL, DAG.getNode(ISD::ADD, DL, VT, Y, Z), VT));
11675+
11676+
return SDValue();
11677+
}
11678+
1165511679
/// Generate Min/Max node
1165611680
SDValue DAGCombiner::combineMinNumMaxNum(const SDLoc &DL, EVT VT, SDValue LHS,
1165711681
SDValue RHS, SDValue True,
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
2+
; RUN: llc < %s -mtriple=aarch64-linux | FileCheck %s
3+
4+
define i8 @andnot_add_with_neg_i8(i8 %a0, i8 %a1) {
5+
; CHECK-LABEL: andnot_add_with_neg_i8:
6+
; CHECK: // %bb.0:
7+
; CHECK-NEXT: sub w8, w0, w1
8+
; CHECK-NEXT: bic w0, w0, w8
9+
; CHECK-NEXT: ret
10+
%not = xor i8 %a0, -1
11+
%sum = add i8 %not, %a1
12+
%and = and i8 %sum, %a0
13+
ret i8 %and
14+
}
15+
16+
define i8 @andnot_sub_with_neg_i8(i8 %a0, i8 %a1) {
17+
; CHECK-LABEL: andnot_sub_with_neg_i8:
18+
; CHECK: // %bb.0:
19+
; CHECK-NEXT: add w8, w0, w1
20+
; CHECK-NEXT: bic w0, w0, w8
21+
; CHECK-NEXT: ret
22+
%not = xor i8 %a0, -1
23+
%diff = sub i8 %not, %a1
24+
%and = and i8 %diff, %a0
25+
ret i8 %and
26+
}
27+
28+
define i16 @andnot_add_with_neg_i16(i16 %a0, i16 %a1) {
29+
; CHECK-LABEL: andnot_add_with_neg_i16:
30+
; CHECK: // %bb.0:
31+
; CHECK-NEXT: sub w8, w0, w1
32+
; CHECK-NEXT: bic w0, w0, w8
33+
; CHECK-NEXT: ret
34+
%not = xor i16 %a0, -1
35+
%sum = add i16 %not, %a1
36+
%and = and i16 %sum, %a0
37+
ret i16 %and
38+
}
39+
40+
define i16 @andnot_sub_with_neg_i16(i16 %a0, i16 %a1) {
41+
; CHECK-LABEL: andnot_sub_with_neg_i16:
42+
; CHECK: // %bb.0:
43+
; CHECK-NEXT: add w8, w0, w1
44+
; CHECK-NEXT: bic w0, w0, w8
45+
; CHECK-NEXT: ret
46+
%not = xor i16 %a0, -1
47+
%diff = sub i16 %not, %a1
48+
%and = and i16 %diff, %a0
49+
ret i16 %and
50+
}
51+
52+
define i32 @andnot_add_with_neg_i32(i32 %a0, i32 %a1) {
53+
; CHECK-LABEL: andnot_add_with_neg_i32:
54+
; CHECK: // %bb.0:
55+
; CHECK-NEXT: sub w8, w0, w1
56+
; CHECK-NEXT: bic w0, w0, w8
57+
; CHECK-NEXT: ret
58+
%not = xor i32 %a0, -1
59+
%sum = add i32 %not, %a1
60+
%and = and i32 %sum, %a0
61+
ret i32 %and
62+
}
63+
64+
define i32 @andnot_sub_with_neg_i32(i32 %a0, i32 %a1) {
65+
; CHECK-LABEL: andnot_sub_with_neg_i32:
66+
; CHECK: // %bb.0:
67+
; CHECK-NEXT: add w8, w0, w1
68+
; CHECK-NEXT: bic w0, w0, w8
69+
; CHECK-NEXT: ret
70+
%not = xor i32 %a0, -1
71+
%diff = sub i32 %not, %a1
72+
%and = and i32 %diff, %a0
73+
ret i32 %and
74+
}
75+
76+
define i64 @andnot_add_with_neg_i64(i64 %a0, i64 %a1) {
77+
; CHECK-LABEL: andnot_add_with_neg_i64:
78+
; CHECK: // %bb.0:
79+
; CHECK-NEXT: sub x8, x0, x1
80+
; CHECK-NEXT: bic x0, x0, x8
81+
; CHECK-NEXT: ret
82+
%not = xor i64 %a0, -1
83+
%sum = add i64 %not, %a1
84+
%and = and i64 %sum, %a0
85+
ret i64 %and
86+
}
87+
88+
define i64 @andnot_sub_with_neg_i64(i64 %a0, i64 %a1) {
89+
; CHECK-LABEL: andnot_sub_with_neg_i64:
90+
; CHECK: // %bb.0:
91+
; CHECK-NEXT: add x8, x0, x1
92+
; CHECK-NEXT: bic x0, x0, x8
93+
; CHECK-NEXT: ret
94+
%not = xor i64 %a0, -1
95+
%diff = sub i64 %not, %a1
96+
%and = and i64 %diff, %a0
97+
ret i64 %and
98+
}

llvm/test/CodeGen/LoongArch/ctlz-cttz-ctpop.ll

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -885,9 +885,8 @@ define i64 @test_cttz_i64(i64 %a) nounwind {
885885
define i8 @test_not_cttz_i8(i8 %a) nounwind {
886886
; LA32R-LABEL: test_not_cttz_i8:
887887
; LA32R: # %bb.0:
888-
; LA32R-NEXT: nor $a1, $a0, $zero
889-
; LA32R-NEXT: addi.w $a1, $a1, -1
890-
; LA32R-NEXT: and $a0, $a0, $a1
888+
; LA32R-NEXT: addi.w $a1, $a0, 1
889+
; LA32R-NEXT: andn $a0, $a0, $a1
891890
; LA32R-NEXT: srli.w $a1, $a0, 1
892891
; LA32R-NEXT: andi $a1, $a1, 85
893892
; LA32R-NEXT: sub.w $a0, $a0, $a1
@@ -921,9 +920,8 @@ define i8 @test_not_cttz_i8(i8 %a) nounwind {
921920
define i16 @test_not_cttz_i16(i16 %a) nounwind {
922921
; LA32R-LABEL: test_not_cttz_i16:
923922
; LA32R: # %bb.0:
924-
; LA32R-NEXT: nor $a1, $a0, $zero
925-
; LA32R-NEXT: addi.w $a1, $a1, -1
926-
; LA32R-NEXT: and $a0, $a0, $a1
923+
; LA32R-NEXT: addi.w $a1, $a0, 1
924+
; LA32R-NEXT: andn $a0, $a0, $a1
927925
; LA32R-NEXT: srli.w $a1, $a0, 1
928926
; LA32R-NEXT: lu12i.w $a2, 5
929927
; LA32R-NEXT: ori $a2, $a2, 1365

0 commit comments

Comments
 (0)