Skip to content

Commit f8575c9

Browse files
committed
[DAGCombiner] add fold (xor (smin(x, C), C)) -> select (x < C), xor(x, C), 0
1 parent 40b129a commit f8575c9

File tree

2 files changed

+117
-0
lines changed

2 files changed

+117
-0
lines changed

llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10086,6 +10086,48 @@ SDValue DAGCombiner::visitXOR(SDNode *N) {
1008610086
if (SDValue Combined = combineCarryDiamond(DAG, TLI, N0, N1, N))
1008710087
return Combined;
1008810088

10089+
// fold (xor (smin(x, C), C)) -> select (x < C), xor(x, C), 0
10090+
// fold (xor (smin(C, x), C)) -> select (x < C), xor(x, C), 0
10091+
if (N0.getOpcode() == ISD::SMIN && N0.hasOneUse()) {
10092+
SDValue Op0 = N0.getOperand(0);
10093+
SDValue Op1 = N0.getOperand(1);
10094+
10095+
if (Op1 != N1) {
10096+
std::swap(Op0, Op1);
10097+
}
10098+
10099+
if (Op1 == N1) {
10100+
if (isa<ConstantSDNode>(N1)) {
10101+
EVT CCVT = getSetCCResultType(VT);
10102+
SDValue Cmp = DAG.getSetCC(SDLoc(N), CCVT, Op0, N1, ISD::SETLT);
10103+
SDValue XorXC = DAG.getNode(ISD::XOR, SDLoc(N), VT, Op0, N1);
10104+
SDValue Zero = DAG.getConstant(0, SDLoc(N), VT);
10105+
return DAG.getSelect(SDLoc(N), VT, Cmp, XorXC, Zero);
10106+
}
10107+
}
10108+
}
10109+
10110+
// fold (xor (smax(x, C), C)) -> select (x > C), xor(x, C), 0
10111+
// fold (xor (smax(C, x), C)) -> select (x > C), xor(x, C), 0
10112+
if (N0.getOpcode() == ISD::SMAX && N0.hasOneUse()) {
10113+
SDValue Op0 = N0.getOperand(0);
10114+
SDValue Op1 = N0.getOperand(1);
10115+
10116+
if (Op1 != N1) {
10117+
std::swap(Op0, Op1);
10118+
}
10119+
10120+
if (Op1 == N1) {
10121+
if (isa<ConstantSDNode>(N1)) {
10122+
EVT CCVT = getSetCCResultType(VT);
10123+
SDValue Cmp = DAG.getSetCC(SDLoc(N), CCVT, Op0, N1, ISD::SETGT);
10124+
SDValue XorXC = DAG.getNode(ISD::XOR, SDLoc(N), VT, Op0, N1);
10125+
SDValue Zero = DAG.getConstant(0, SDLoc(N), VT);
10126+
return DAG.getSelect(SDLoc(N), VT, Cmp, XorXC, Zero);
10127+
}
10128+
}
10129+
}
10130+
1008910131
return SDValue();
1009010132
}
1009110133

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2+
; RUN: llc < %s -mtriple=aarch64-unknown-unknown | FileCheck %s
3+
4+
; Test for DAGCombiner optimization: fold (xor (smin(x, C), C)) -> select (x < C), xor (x, C), 0
5+
6+
define i64 @test_smin_neg_one(i64 %a) {
7+
; CHECK-LABEL: test_smin_neg_one:
8+
; CHECK: // %bb.0:
9+
; CHECK-NEXT: cmn x0, #1
10+
; CHECK-NEXT: csinv x0, xzr, x0, ge
11+
; CHECK-NEXT: ret
12+
%1 = tail call i64 @llvm.smin.i64(i64 %a, i64 -1)
13+
%retval.0 = xor i64 %1, -1
14+
ret i64 %retval.0
15+
}
16+
17+
define i64 @test_smin_zero(i64 %a) {
18+
; CHECK-LABEL: test_smin_zero:
19+
; CHECK: // %bb.0:
20+
; CHECK-NEXT: and x0, x0, x0, asr #63
21+
; CHECK-NEXT: ret
22+
%1 = tail call i64 @llvm.smin.i64(i64 %a, i64 0)
23+
%retval.0 = xor i64 %1, 0
24+
ret i64 %retval.0
25+
}
26+
27+
define i64 @test_smin_constant(i64 %a) {
28+
; CHECK-LABEL: test_smin_constant:
29+
; CHECK: // %bb.0:
30+
; CHECK-NEXT: eor x8, x0, #0x8
31+
; CHECK-NEXT: cmp x0, #8
32+
; CHECK-NEXT: csel x0, x8, xzr, lt
33+
; CHECK-NEXT: ret
34+
%1 = tail call i64 @llvm.smin.i64(i64 %a, i64 8)
35+
%retval.0 = xor i64 %1, 8
36+
ret i64 %retval.0
37+
}
38+
39+
; Test for DAGCombiner optimization: fold (xor (smax(x, C), C)) -> select (x > C), xor (x, C), 0
40+
41+
define i64 @test_smax_neg_one(i64 %a) {
42+
; CHECK-LABEL: test_smax_neg_one:
43+
; CHECK: // %bb.0:
44+
; CHECK-NEXT: mvn x8, x0
45+
; CHECK-NEXT: bic x0, x8, x0, asr #63
46+
; CHECK-NEXT: ret
47+
%1 = tail call i64 @llvm.smax.i64(i64 %a, i64 -1)
48+
%retval.0 = xor i64 %1, -1
49+
ret i64 %retval.0
50+
}
51+
52+
define i64 @test_smax_zero(i64 %a) {
53+
; CHECK-LABEL: test_smax_zero:
54+
; CHECK: // %bb.0:
55+
; CHECK-NEXT: bic x0, x0, x0, asr #63
56+
; CHECK-NEXT: ret
57+
%1 = tail call i64 @llvm.smax.i64(i64 %a, i64 0)
58+
%retval.0 = xor i64 %1, 0
59+
ret i64 %retval.0
60+
}
61+
62+
define i64 @test_smax_constant(i64 %a) {
63+
; CHECK-LABEL: test_smax_constant:
64+
; CHECK: // %bb.0:
65+
; CHECK-NEXT: eor x8, x0, #0x8
66+
; CHECK-NEXT: cmp x0, #8
67+
; CHECK-NEXT: csel x0, x8, xzr, gt
68+
; CHECK-NEXT: ret
69+
%1 = tail call i64 @llvm.smax.i64(i64 %a, i64 8)
70+
%retval.0 = xor i64 %1, 8
71+
ret i64 %retval.0
72+
}
73+
74+
declare i64 @llvm.smin.i64(i64, i64)
75+
declare i64 @llvm.smax.i64(i64, i64)

0 commit comments

Comments
 (0)