Skip to content

Commit e7b65b3

Browse files
committed
[SelectionDAG] Detect impossible conditions using known bits analysis
1 parent 67b5195 commit e7b65b3

File tree

3 files changed

+2186
-16
lines changed

3 files changed

+2186
-16
lines changed

llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13529,6 +13529,84 @@ SDValue DAGCombiner::visitSETCC(SDNode *N) {
1352913529
SDValue N0 = N->getOperand(0), N1 = N->getOperand(1);
1353013530
SDLoc DL(N);
1353113531

13532+
// Detect impossible conditions using known bits analysis.
13533+
if (ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1)) {
13534+
const APInt &C1 = N1C->getAPIntValue();
13535+
KnownBits KnownRHS = KnownBits::makeConstant(C1);
13536+
13537+
// Bail out early if RHS is unknown (shouldn't happen for constants)
13538+
if (KnownRHS.isUnknown())
13539+
return SDValue();
13540+
13541+
std::optional<bool> KnownVal;
13542+
13543+
// Handle special cases first (like GlobalISel does)
13544+
if (KnownRHS.isZero()) {
13545+
// x >=u 0 -> always true
13546+
// x <u 0 -> always false
13547+
if (Cond == ISD::SETUGE)
13548+
KnownVal = true;
13549+
else if (Cond == ISD::SETULT)
13550+
KnownVal = false;
13551+
}
13552+
13553+
// If not handled by special cases, use ICmpInst::compare
13554+
if (!KnownVal) {
13555+
KnownBits KnownLHS = DAG.computeKnownBits(N0);
13556+
13557+
// Convert ISD::CondCode to CmpInst::Predicate
13558+
CmpInst::Predicate Pred;
13559+
switch (Cond) {
13560+
case ISD::SETEQ:
13561+
Pred = CmpInst::ICMP_EQ;
13562+
break;
13563+
case ISD::SETNE:
13564+
Pred = CmpInst::ICMP_NE;
13565+
break;
13566+
case ISD::SETULT:
13567+
Pred = CmpInst::ICMP_ULT;
13568+
break;
13569+
case ISD::SETULE:
13570+
Pred = CmpInst::ICMP_ULE;
13571+
break;
13572+
case ISD::SETUGT:
13573+
Pred = CmpInst::ICMP_UGT;
13574+
break;
13575+
case ISD::SETUGE:
13576+
Pred = CmpInst::ICMP_UGE;
13577+
break;
13578+
case ISD::SETLT:
13579+
Pred = CmpInst::ICMP_SLT;
13580+
break;
13581+
case ISD::SETLE:
13582+
Pred = CmpInst::ICMP_SLE;
13583+
break;
13584+
case ISD::SETGT:
13585+
Pred = CmpInst::ICMP_SGT;
13586+
break;
13587+
case ISD::SETGE:
13588+
Pred = CmpInst::ICMP_SGE;
13589+
break;
13590+
default:
13591+
return SDValue(); // Unsupported predicate
13592+
}
13593+
13594+
// Use the same logic as GlobalISel: ICmpInst::compare
13595+
KnownVal = ICmpInst::compare(KnownLHS, KnownRHS, Pred);
13596+
}
13597+
13598+
// If the comparison result is known, replace with constant
13599+
if (KnownVal) {
13600+
if (*KnownVal) {
13601+
// Use the target's true value for comparisons
13602+
return DAG.getBoolConstant(true, DL, VT, VT);
13603+
} else {
13604+
// False is always 0
13605+
return DAG.getConstant(0, DL, VT);
13606+
}
13607+
}
13608+
}
13609+
1353213610
if (SDValue Combined = SimplifySetCC(VT, N0, N1, Cond, DL, !PreferSetCC)) {
1353313611
// If we prefer to have a setcc, and we don't, we'll try our best to
1353413612
// recreate one using rebuildSetCC.

llvm/test/CodeGen/AArch64/arm64-ccmp.ll

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -597,22 +597,10 @@ define i32 @select_andor32(i32 %v1, i32 %v2, i32 %v3) {
597597
}
598598

599599
define i64 @select_noccmp1(i64 %v1, i64 %v2, i64 %v3, i64 %r) {
600-
; SDISEL-LABEL: select_noccmp1:
601-
; SDISEL: ; %bb.0:
602-
; SDISEL-NEXT: cmp x0, #0
603-
; SDISEL-NEXT: ccmp x0, #13, #4, lt
604-
; SDISEL-NEXT: cset w8, gt
605-
; SDISEL-NEXT: cmp x2, #2
606-
; SDISEL-NEXT: ccmp x2, #4, #4, lt
607-
; SDISEL-NEXT: csinc w8, w8, wzr, le
608-
; SDISEL-NEXT: cmp w8, #0
609-
; SDISEL-NEXT: csel x0, xzr, x3, ne
610-
; SDISEL-NEXT: ret
611-
;
612-
; GISEL-LABEL: select_noccmp1:
613-
; GISEL: ; %bb.0:
614-
; GISEL-NEXT: mov x0, x3
615-
; GISEL-NEXT: ret
600+
; CHECK-LABEL: select_noccmp1:
601+
; CHECK: ; %bb.0:
602+
; CHECK-NEXT: mov x0, x3
603+
; CHECK-NEXT: ret
616604
%c0 = icmp slt i64 %v1, 0
617605
%c1 = icmp sgt i64 %v1, 13
618606
%c2 = icmp slt i64 %v3, 2

0 commit comments

Comments
 (0)