Skip to content

Commit 4c42ab1

Browse files
committed
[DAGCombiner] Change foldAndOrOfSETCC() to optimize and/or patterns
CMP(A,C)||CMP(B,C) => CMP(MIN/MAX(A,B), C) CMP(A,C)&&CMP(B,C) => CMP(MIN/MAX(A,B), C) This first patch handles integer types. Reviewed By: craig.topper Differential Revision: https://reviews.llvm.org/D153502
1 parent 11cd92a commit 4c42ab1

File tree

7 files changed

+262
-240
lines changed

7 files changed

+262
-240
lines changed

llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Lines changed: 73 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6021,26 +6021,91 @@ static SDValue foldAndOrOfSETCC(SDNode *LogicOp, SelectionDAG &DAG) {
60216021
AndOrSETCCFoldKind TargetPreference = TLI.isDesirableToCombineLogicOpOfSETCC(
60226022
LogicOp, LHS.getNode(), RHS.getNode());
60236023

6024-
if (TargetPreference == AndOrSETCCFoldKind::None)
6025-
return SDValue();
6026-
6027-
ISD::CondCode CCL = cast<CondCodeSDNode>(LHS.getOperand(2))->get();
6028-
ISD::CondCode CCR = cast<CondCodeSDNode>(RHS.getOperand(2))->get();
6029-
60306024
SDValue LHS0 = LHS->getOperand(0);
60316025
SDValue RHS0 = RHS->getOperand(0);
60326026
SDValue LHS1 = LHS->getOperand(1);
60336027
SDValue RHS1 = RHS->getOperand(1);
6034-
60356028
// TODO: We don't actually need a splat here, for vectors we just need the
60366029
// invariants to hold for each element.
60376030
auto *LHS1C = isConstOrConstSplat(LHS1);
60386031
auto *RHS1C = isConstOrConstSplat(RHS1);
6039-
6032+
ISD::CondCode CCL = cast<CondCodeSDNode>(LHS.getOperand(2))->get();
6033+
ISD::CondCode CCR = cast<CondCodeSDNode>(RHS.getOperand(2))->get();
60406034
EVT VT = LogicOp->getValueType(0);
60416035
EVT OpVT = LHS0.getValueType();
60426036
SDLoc DL(LogicOp);
60436037

6038+
// Check if the operands of an and/or operation are comparisons and if they
6039+
// compare against the same value. Replace the and/or-cmp-cmp sequence with
6040+
// min/max cmp sequence. If LHS1 is equal to RHS1, then the or-cmp-cmp
6041+
// sequence will be replaced with min-cmp sequence:
6042+
// (LHS0 < LHS1) | (RHS0 < RHS1) -> min(LHS0, RHS0) < LHS1
6043+
// and and-cmp-cmp will be replaced with max-cmp sequence:
6044+
// (LHS0 < LHS1) & (RHS0 < RHS1) -> max(LHS0, RHS0) < LHS1
6045+
if (OpVT.isInteger() && TLI.isOperationLegal(ISD::UMAX, OpVT) &&
6046+
TLI.isOperationLegal(ISD::SMAX, OpVT) &&
6047+
TLI.isOperationLegal(ISD::UMIN, OpVT) &&
6048+
TLI.isOperationLegal(ISD::SMIN, OpVT)) {
6049+
SDValue CommonValue;
6050+
SDValue Operand1;
6051+
SDValue Operand2;
6052+
ISD::CondCode CC = ISD::SETCC_INVALID;
6053+
if (LHS->getOpcode() == ISD::SETCC && RHS->getOpcode() == ISD::SETCC &&
6054+
LHS->hasOneUse() && RHS->hasOneUse() &&
6055+
// The two comparisons should have either the same predicate or the
6056+
// predicate of one of the comparisons is the opposite of the other one.
6057+
(CCL == CCR || CCL == ISD::getSetCCSwappedOperands(CCR)) &&
6058+
// The optimization does not work for `==` or `!=` .
6059+
!ISD::isIntEqualitySetCC(CCL) && !ISD::isIntEqualitySetCC(CCR)) {
6060+
if (CCL == CCR) {
6061+
if (LHS0 == RHS0) {
6062+
CommonValue = LHS0;
6063+
Operand1 = LHS1;
6064+
Operand2 = RHS1;
6065+
CC = ISD::getSetCCSwappedOperands(CCL);
6066+
} else if (LHS1 == RHS1) {
6067+
CommonValue = LHS1;
6068+
Operand1 = LHS0;
6069+
Operand2 = RHS0;
6070+
CC = CCL;
6071+
}
6072+
} else if (CCL == ISD::getSetCCSwappedOperands(CCR)) {
6073+
if (LHS0 == RHS1) {
6074+
CommonValue = LHS0;
6075+
Operand1 = LHS1;
6076+
Operand2 = RHS0;
6077+
CC = ISD::getSetCCSwappedOperands(CCL);
6078+
} else if (RHS0 == LHS1) {
6079+
CommonValue = LHS1;
6080+
Operand1 = LHS0;
6081+
Operand2 = RHS1;
6082+
CC = CCL;
6083+
}
6084+
}
6085+
6086+
if (CC != ISD::SETCC_INVALID) {
6087+
unsigned NewOpcode;
6088+
bool IsSigned = isSignedIntSetCC(CC);
6089+
if (((CC == ISD::SETLE || CC == ISD::SETULE || CC == ISD::SETLT ||
6090+
CC == ISD::SETULT) &&
6091+
(LogicOp->getOpcode() == ISD::OR)) ||
6092+
((CC == ISD::SETGE || CC == ISD::SETUGE || CC == ISD::SETGT ||
6093+
CC == ISD::SETUGT) &&
6094+
(LogicOp->getOpcode() == ISD::AND)))
6095+
NewOpcode = IsSigned ? ISD::SMIN : ISD::UMIN;
6096+
else
6097+
NewOpcode = IsSigned ? ISD::SMAX : ISD::UMAX;
6098+
6099+
SDValue MinMaxValue =
6100+
DAG.getNode(NewOpcode, DL, OpVT, Operand1, Operand2);
6101+
return DAG.getSetCC(DL, VT, MinMaxValue, CommonValue, CC);
6102+
}
6103+
}
6104+
}
6105+
6106+
if (TargetPreference == AndOrSETCCFoldKind::None)
6107+
return SDValue();
6108+
60446109
if (CCL == CCR &&
60456110
CCL == (LogicOp->getOpcode() == ISD::AND ? ISD::SETNE : ISD::SETEQ) &&
60466111
LHS0 == RHS0 && LHS1C && RHS1C && OpVT.isInteger() && LHS.hasOneUse() &&

llvm/test/CodeGen/AArch64/vecreduce-bool.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ define i32 @reduce_and_v16(<16 x i8> %a0, i32 %a1, i32 %a2) nounwind {
9696
define i32 @reduce_and_v32(<32 x i8> %a0, i32 %a1, i32 %a2) nounwind {
9797
; CHECK-LABEL: reduce_and_v32:
9898
; CHECK: // %bb.0:
99-
; CHECK-NEXT: and v0.16b, v0.16b, v1.16b
99+
; CHECK-NEXT: smax v0.16b, v0.16b, v1.16b
100100
; CHECK-NEXT: cmlt v0.16b, v0.16b, #0
101101
; CHECK-NEXT: uminv b0, v0.16b
102102
; CHECK-NEXT: fmov w8, s0
@@ -190,7 +190,7 @@ define i32 @reduce_or_v16(<16 x i8> %a0, i32 %a1, i32 %a2) nounwind {
190190
define i32 @reduce_or_v32(<32 x i8> %a0, i32 %a1, i32 %a2) nounwind {
191191
; CHECK-LABEL: reduce_or_v32:
192192
; CHECK: // %bb.0:
193-
; CHECK-NEXT: orr v0.16b, v0.16b, v1.16b
193+
; CHECK-NEXT: smin v0.16b, v0.16b, v1.16b
194194
; CHECK-NEXT: cmlt v0.16b, v0.16b, #0
195195
; CHECK-NEXT: umaxv b0, v0.16b
196196
; CHECK-NEXT: fmov w8, s0

llvm/test/CodeGen/AMDGPU/combine-cond-add-sub.ll

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -434,33 +434,31 @@ bb:
434434
define amdgpu_kernel void @add_and(ptr addrspace(1) nocapture %arg) {
435435
; GCN-LABEL: add_and:
436436
; GCN: ; %bb.0: ; %bb
437-
; GCN-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x9
438-
; GCN-NEXT: s_mov_b32 s7, 0xf000
439-
; GCN-NEXT: s_mov_b32 s6, 0
437+
; GCN-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x9
438+
; GCN-NEXT: s_mov_b32 s3, 0xf000
439+
; GCN-NEXT: s_mov_b32 s2, 0
440440
; GCN-NEXT: v_lshlrev_b32_e32 v2, 2, v0
441441
; GCN-NEXT: v_mov_b32_e32 v3, 0
442442
; GCN-NEXT: s_waitcnt lgkmcnt(0)
443-
; GCN-NEXT: buffer_load_dword v4, v[2:3], s[4:7], 0 addr64
444-
; GCN-NEXT: v_cmp_gt_u32_e32 vcc, v0, v1
445-
; GCN-NEXT: v_cmp_lt_u32_e64 s[0:1], 1, v0
446-
; GCN-NEXT: s_and_b64 vcc, vcc, s[0:1]
443+
; GCN-NEXT: buffer_load_dword v4, v[2:3], s[0:3], 0 addr64
444+
; GCN-NEXT: v_max_u32_e32 v1, 1, v1
445+
; GCN-NEXT: v_cmp_lt_u32_e32 vcc, v1, v0
447446
; GCN-NEXT: s_waitcnt vmcnt(0)
448447
; GCN-NEXT: v_addc_u32_e32 v0, vcc, 0, v4, vcc
449-
; GCN-NEXT: buffer_store_dword v0, v[2:3], s[4:7], 0 addr64
448+
; GCN-NEXT: buffer_store_dword v0, v[2:3], s[0:3], 0 addr64
450449
; GCN-NEXT: s_endpgm
451450
;
452451
; GFX9-LABEL: add_and:
453452
; GFX9: ; %bb.0: ; %bb
454-
; GFX9-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x24
453+
; GFX9-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24
455454
; GFX9-NEXT: v_lshlrev_b32_e32 v2, 2, v0
456-
; GFX9-NEXT: v_cmp_gt_u32_e32 vcc, v0, v1
457-
; GFX9-NEXT: v_cmp_lt_u32_e64 s[0:1], 1, v0
458-
; GFX9-NEXT: s_and_b64 vcc, vcc, s[0:1]
455+
; GFX9-NEXT: v_max_u32_e32 v1, 1, v1
456+
; GFX9-NEXT: v_cmp_lt_u32_e32 vcc, v1, v0
459457
; GFX9-NEXT: s_waitcnt lgkmcnt(0)
460-
; GFX9-NEXT: global_load_dword v3, v2, s[2:3]
458+
; GFX9-NEXT: global_load_dword v3, v2, s[0:1]
461459
; GFX9-NEXT: s_waitcnt vmcnt(0)
462460
; GFX9-NEXT: v_addc_co_u32_e32 v0, vcc, 0, v3, vcc
463-
; GFX9-NEXT: global_store_dword v2, v0, s[2:3]
461+
; GFX9-NEXT: global_store_dword v2, v0, s[0:1]
464462
; GFX9-NEXT: s_endpgm
465463
bb:
466464
%x = tail call i32 @llvm.amdgcn.workitem.id.x()

0 commit comments

Comments
 (0)