Skip to content

Commit 57b49a0

Browse files
committed
[AArch64] Snap 32 and -32 to 31 and -31 if possible for ccmp and ccmn
This lets us encode the immediate in the instruction.
1 parent a591bd2 commit 57b49a0

File tree

2 files changed

+93
-0
lines changed

2 files changed

+93
-0
lines changed

llvm/lib/Target/AArch64/AArch64ISelLowering.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3716,6 +3716,55 @@ static SDValue emitConjunctionRec(SelectionDAG &DAG, SDValue Val,
37163716
// Produce a normal comparison if we are first in the chain
37173717
if (!CCOp)
37183718
return emitComparison(LHS, RHS, CC, DL, DAG);
3719+
3720+
if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(RHS.getNode())) {
3721+
EVT VT = RHS.getValueType();
3722+
APInt C = RHSC->getAPIntValue();
3723+
// shouldBeAdjustedToZero is a special case to better fold with
3724+
// emitComparison().
3725+
if (C.getZExtValue() == 32 && (CC == ISD::SETLT || CC == ISD::SETGE ||
3726+
CC == ISD::SETULT || CC == ISD::SETUGE)) {
3727+
switch (CC) {
3728+
case ISD::SETLT:
3729+
CC = ISD::SETLE;
3730+
break;
3731+
case ISD::SETGE:
3732+
CC = ISD::SETGT;
3733+
break;
3734+
case ISD::SETULT:
3735+
CC = ISD::SETULE;
3736+
break;
3737+
case ISD::SETUGE:
3738+
CC = ISD::SETUGT;
3739+
break;
3740+
default:
3741+
llvm_unreachable("Should not happen");
3742+
}
3743+
RHS = DAG.getConstant(31, DL, VT);
3744+
OutCC = changeIntCCToAArch64CC(CC);
3745+
} else if (C.getSExtValue() == -32 &&
3746+
(CC == ISD::SETLE || CC == ISD::SETGT || CC == ISD::SETULE ||
3747+
CC == ISD::SETUGT)) {
3748+
switch (CC) {
3749+
case ISD::SETLE:
3750+
CC = ISD::SETLT;
3751+
break;
3752+
case ISD::SETGT:
3753+
CC = ISD::SETGE;
3754+
break;
3755+
case ISD::SETULE:
3756+
CC = ISD::SETULT;
3757+
break;
3758+
case ISD::SETUGT:
3759+
CC = ISD::SETUGE;
3760+
break;
3761+
default:
3762+
llvm_unreachable("Should not happen");
3763+
}
3764+
RHS = DAG.getConstant((C + 1).getZExtValue(), DL, VT); // -31
3765+
OutCC = changeIntCCToAArch64CC(CC);
3766+
}
3767+
}
37193768
// Otherwise produce a ccmp.
37203769
return emitConditionalComparison(LHS, RHS, CC, CCOp, Predicate, OutCC, DL,
37213770
DAG);

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

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,3 +501,47 @@ entry:
501501
%land.ext = zext i1 %0 to i32
502502
ret i32 %land.ext
503503
}
504+
505+
define i32 @compare_with_neg_32(i32 %a, i32 %b, i32 %c) {
506+
; SDISEL-LABEL: compare_with_neg_32:
507+
; SDISEL: // %bb.0:
508+
; SDISEL-NEXT: cmp w0, w2
509+
; SDISEL-NEXT: ccmn w1, #31, #8, lt
510+
; SDISEL-NEXT: csel w0, w1, w0, ge
511+
; SDISEL-NEXT: ret
512+
;
513+
; GISEL-LABEL: compare_with_neg_32:
514+
; GISEL: // %bb.0:
515+
; GISEL-NEXT: mov w8, #-32 // =0xffffffe0
516+
; GISEL-NEXT: cmp w0, w2
517+
; GISEL-NEXT: ccmp w1, w8, #4, lt
518+
; GISEL-NEXT: csel w0, w1, w0, gt
519+
; GISEL-NEXT: ret
520+
%cmp = icmp sgt i32 %b, -32
521+
%cmp1 = icmp slt i32 %a, %c
522+
%or.cond = and i1 %cmp, %cmp1
523+
%cond = select i1 %or.cond, i32 %b, i32 %a
524+
ret i32 %cond
525+
}
526+
527+
define i32 @compare_with_32(i32 %a, i32 %b, i32 %c) {
528+
; SDISEL-LABEL: compare_with_32:
529+
; SDISEL: // %bb.0:
530+
; SDISEL-NEXT: cmp w0, w2
531+
; SDISEL-NEXT: ccmp w1, #31, #4, lt
532+
; SDISEL-NEXT: csel w0, w1, w0, gt
533+
; SDISEL-NEXT: ret
534+
;
535+
; GISEL-LABEL: compare_with_32:
536+
; GISEL: // %bb.0:
537+
; GISEL-NEXT: mov w8, #32 // =0x20
538+
; GISEL-NEXT: cmp w0, w2
539+
; GISEL-NEXT: ccmp w1, w8, #8, lt
540+
; GISEL-NEXT: csel w0, w1, w0, ge
541+
; GISEL-NEXT: ret
542+
%cmp = icmp sge i32 %b, 32
543+
%cmp1 = icmp slt i32 %a, %c
544+
%or.cond = and i1 %cmp, %cmp1
545+
%cond = select i1 %or.cond, i32 %b, i32 %a
546+
ret i32 %cond
547+
}

0 commit comments

Comments
 (0)