Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13529,6 +13529,84 @@ SDValue DAGCombiner::visitSETCC(SDNode *N) {
SDValue N0 = N->getOperand(0), N1 = N->getOperand(1);
SDLoc DL(N);

// Detect impossible conditions using known bits analysis.
if (ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1)) {
const APInt &C1 = N1C->getAPIntValue();
KnownBits KnownRHS = KnownBits::makeConstant(C1);

// Bail out early if RHS is unknown (shouldn't happen for constants)
if (KnownRHS.isUnknown())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How can KnownBits::makeConstant ever create an unknown? At the very best this should just be an assert but really I don't think it needs to be here at all.

return SDValue();

std::optional<bool> KnownVal;

// Handle special cases first (like GlobalISel does)
if (KnownRHS.isZero()) {
// x >=u 0 -> always true
// x <u 0 -> always false
if (Cond == ISD::SETUGE)
KnownVal = true;
else if (Cond == ISD::SETULT)
KnownVal = false;
}

// If not handled by special cases, use ICmpInst::compare
if (!KnownVal) {
KnownBits KnownLHS = DAG.computeKnownBits(N0);

// Convert ISD::CondCode to CmpInst::Predicate
CmpInst::Predicate Pred;
switch (Cond) {
case ISD::SETEQ:
Pred = CmpInst::ICMP_EQ;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have an existing ISD::CondCode -> CmpInst::Predicate helper we can use? Or we just call the KnownBits compares directly in the switch

break;
case ISD::SETNE:
Pred = CmpInst::ICMP_NE;
break;
case ISD::SETULT:
Pred = CmpInst::ICMP_ULT;
break;
case ISD::SETULE:
Pred = CmpInst::ICMP_ULE;
break;
case ISD::SETUGT:
Pred = CmpInst::ICMP_UGT;
break;
case ISD::SETUGE:
Pred = CmpInst::ICMP_UGE;
break;
case ISD::SETLT:
Pred = CmpInst::ICMP_SLT;
break;
case ISD::SETLE:
Pred = CmpInst::ICMP_SLE;
break;
case ISD::SETGT:
Pred = CmpInst::ICMP_SGT;
break;
case ISD::SETGE:
Pred = CmpInst::ICMP_SGE;
break;
default:
return SDValue(); // Unsupported predicate
}

// Use the same logic as GlobalISel: ICmpInst::compare
KnownVal = ICmpInst::compare(KnownLHS, KnownRHS, Pred);
}

// If the comparison result is known, replace with constant
if (KnownVal) {
if (*KnownVal) {
// Use the target's true value for comparisons
return DAG.getBoolConstant(true, DL, VT, VT);
} else {
// False is always 0
return DAG.getConstant(0, DL, VT);
}
}
}

if (SDValue Combined = SimplifySetCC(VT, N0, N1, Cond, DL, !PreferSetCC)) {
// If we prefer to have a setcc, and we don't, we'll try our best to
// recreate one using rebuildSetCC.
Expand Down
20 changes: 4 additions & 16 deletions llvm/test/CodeGen/AArch64/arm64-ccmp.ll
Original file line number Diff line number Diff line change
Expand Up @@ -597,22 +597,10 @@ define i32 @select_andor32(i32 %v1, i32 %v2, i32 %v3) {
}

define i64 @select_noccmp1(i64 %v1, i64 %v2, i64 %v3, i64 %r) {
; SDISEL-LABEL: select_noccmp1:
; SDISEL: ; %bb.0:
; SDISEL-NEXT: cmp x0, #0
; SDISEL-NEXT: ccmp x0, #13, #4, lt
; SDISEL-NEXT: cset w8, gt
; SDISEL-NEXT: cmp x2, #2
; SDISEL-NEXT: ccmp x2, #4, #4, lt
; SDISEL-NEXT: csinc w8, w8, wzr, le
; SDISEL-NEXT: cmp w8, #0
; SDISEL-NEXT: csel x0, xzr, x3, ne
; SDISEL-NEXT: ret
;
; GISEL-LABEL: select_noccmp1:
; GISEL: ; %bb.0:
; GISEL-NEXT: mov x0, x3
; GISEL-NEXT: ret
; CHECK-LABEL: select_noccmp1:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I couldn't figure out how this patch works on this case so I downloaded your patch and tried it. But it doesn't optimize this case.

; CHECK: ; %bb.0:
; CHECK-NEXT: mov x0, x3
; CHECK-NEXT: ret
%c0 = icmp slt i64 %v1, 0
%c1 = icmp sgt i64 %v1, 13
%c2 = icmp slt i64 %v3, 2
Expand Down
Loading
Loading