Skip to content

Commit 4bbb08f

Browse files
clingfeigithub-actions[bot]
authored andcommitted
Automerge: [AArch64] Recombine SETCCCARRY for legalized unsigned compares (#204504)
Type legalization can turn wide unsigned compares into SETCCCARRY nodes fed by USUBO carry results, hiding the original high/low compare shape from the existing CCMP conjunction/disjunction lowering. Add an AArch64 DAG combine for SETCCCARRY that recognizes these legalized wide-compare patterns and rebuilds them as SETCC plus AND/OR, exposing them to the existing CCMP lowering. This is separated from llvm/llvm-project#181822.
2 parents 08bb5ba + 779c908 commit 4bbb08f

2 files changed

Lines changed: 86 additions & 0 deletions

File tree

llvm/lib/Target/AArch64/AArch64ISelLowering.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1204,6 +1204,7 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,
12041204
// Try and combine setcc/select_cc with csel and bool-vector bitcasts.
12051205
setTargetDAGCombine(ISD::SETCC);
12061206
setTargetDAGCombine(ISD::SELECT_CC);
1207+
setTargetDAGCombine(ISD::SETCCCARRY);
12071208

12081209
setTargetDAGCombine(ISD::INTRINSIC_WO_CHAIN);
12091210

@@ -28222,6 +28223,40 @@ static SDValue performSETCCCombine(SDNode *N,
2822228223
return SDValue();
2822328224
}
2822428225

28226+
static SDValue performSETCCCARRYCombine(SDNode *N, SelectionDAG &DAG) {
28227+
assert(N->getOpcode() == ISD::SETCCCARRY && "Unexpected opcode!");
28228+
28229+
// Rebuild narrow high/low compares from type-legalized wide unsigned compares
28230+
// so the existing CCMP conjunction/disjunction lowering can handle them.
28231+
SDValue HiLHS = N->getOperand(0);
28232+
SDValue HiRHS = N->getOperand(1);
28233+
SDValue Carry = N->getOperand(2);
28234+
ISD::CondCode Cond = cast<CondCodeSDNode>(N->getOperand(3))->get();
28235+
if (Cond != ISD::SETULT || Carry.getOpcode() != ISD::USUBO ||
28236+
Carry.getResNo() != 1)
28237+
return SDValue();
28238+
28239+
if (!isNullConstant(HiLHS) && !isNullConstant(HiRHS))
28240+
return SDValue();
28241+
28242+
SDValue LoLHS = Carry.getOperand(0);
28243+
SDValue LoRHS = Carry.getOperand(1);
28244+
if (!isa<ConstantSDNode>(LoLHS) && !isa<ConstantSDNode>(LoRHS))
28245+
return SDValue();
28246+
28247+
EVT VT = N->getValueType(0);
28248+
SDLoc DL(N);
28249+
28250+
SDValue LoCmp = DAG.getSetCC(DL, VT, LoLHS, LoRHS, ISD::SETULT);
28251+
if (isNullConstant(HiRHS)) {
28252+
SDValue HiEq = DAG.getSetCC(DL, VT, HiLHS, HiRHS, ISD::SETEQ);
28253+
return DAG.getNode(ISD::AND, DL, VT, HiEq, LoCmp);
28254+
}
28255+
28256+
SDValue HiNe = DAG.getSetCC(DL, VT, HiRHS, HiLHS, ISD::SETNE);
28257+
return DAG.getNode(ISD::OR, DL, VT, HiNe, LoCmp);
28258+
}
28259+
2822528260
static SDValue performSELECT_CCCombine(SDNode *N,
2822628261
TargetLowering::DAGCombinerInfo &DCI,
2822728262
SelectionDAG &DAG) {
@@ -30154,6 +30189,8 @@ SDValue AArch64TargetLowering::PerformDAGCombine(SDNode *N,
3015430189
return performVSelectCombine(N, DCI, Subtarget);
3015530190
case ISD::SETCC:
3015630191
return performSETCCCombine(N, DCI, DAG);
30192+
case ISD::SETCCCARRY:
30193+
return performSETCCCARRYCombine(N, DAG);
3015730194
case ISD::LOAD:
3015830195
return performLOADCombine(N, DCI, DAG, Subtarget);
3015930196
case ISD::STORE:

llvm/test/CodeGen/AArch64/i128-cmp.ll

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,3 +323,52 @@ exit:
323323
ret void
324324
}
325325

326+
define i1 @cmp_i128_ult_small_const(i128 %a) {
327+
; CHECK-LABEL: cmp_i128_ult_small_const:
328+
; CHECK: // %bb.0:
329+
; CHECK-NEXT: cmp x1, #0
330+
; CHECK-NEXT: ccmp x0, #7, #2, eq
331+
; CHECK-NEXT: cset w0, lo
332+
; CHECK-NEXT: ret
333+
%cmp = icmp ult i128 %a, 7
334+
ret i1 %cmp
335+
}
336+
337+
define i1 @cmp_i128_small_const_ult(i128 %a) {
338+
; CHECK-LABEL: cmp_i128_small_const_ult:
339+
; CHECK: // %bb.0:
340+
; CHECK-NEXT: cmp x1, #0
341+
; CHECK-NEXT: ccmp x0, #7, #2, eq
342+
; CHECK-NEXT: cset w0, hi
343+
; CHECK-NEXT: ret
344+
%cmp = icmp ult i128 7, %a
345+
ret i1 %cmp
346+
}
347+
348+
define i1 @cmp_i128_ult_small_const_and_i64(i128 %a, i64 %b) {
349+
; CHECK-LABEL: cmp_i128_ult_small_const_and_i64:
350+
; CHECK: // %bb.0:
351+
; CHECK-NEXT: cmp x0, #7
352+
; CHECK-NEXT: ccmp x2, #11, #2, lo
353+
; CHECK-NEXT: ccmp x1, #0, #0, lo
354+
; CHECK-NEXT: cset w0, eq
355+
; CHECK-NEXT: ret
356+
%wide = icmp ult i128 %a, 7
357+
%narrow = icmp ult i64 %b, 11
358+
%cmp = and i1 %wide, %narrow
359+
ret i1 %cmp
360+
}
361+
362+
define i1 @cmp_i128_small_const_ult_or_i64(i128 %a, i64 %b) {
363+
; CHECK-LABEL: cmp_i128_small_const_ult_or_i64:
364+
; CHECK: // %bb.0:
365+
; CHECK-NEXT: cmp x1, #0
366+
; CHECK-NEXT: ccmp x0, #7, #2, eq
367+
; CHECK-NEXT: ccmp x2, #11, #0, ls
368+
; CHECK-NEXT: cset w0, lo
369+
; CHECK-NEXT: ret
370+
%wide = icmp ult i128 7, %a
371+
%narrow = icmp ult i64 %b, 11
372+
%cmp = or i1 %wide, %narrow
373+
ret i1 %cmp
374+
}

0 commit comments

Comments
 (0)