Skip to content

Commit 8c74c54

Browse files
committed
Make (and/or (icmp eq/ne A,C0), (icmp eq/ne A,C1)) where IsPow(dif(C0,C1)) work for more patterns.
`(and/or (icmp eq/ne A,C0), (icmp eq/ne A,C1))` can be lowered to `(icmp eq/ne (and (sub A, (smin C0, C1)), (not (sub (smax C0, C1), (smin C0, C1)))), 0)` generically if `(sub (smax C0, C1), (smin C0,C1))` is a power of 2. This covers the existing case of `(and/or (icmp eq/ne A, C_Pow2),(icmp eq/ne A, -C_Pow2))` as well as other cases. Alive2 Links: EQ: https://alive2.llvm.org/ce/z/mLJiUW NE: https://alive2.llvm.org/ce/z/TKnzUr Differential Revision: https://reviews.llvm.org/D144283
1 parent 85e8305 commit 8c74c54

File tree

3 files changed

+32
-43
lines changed

3 files changed

+32
-43
lines changed

llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5907,8 +5907,8 @@ static SDValue foldAndOrOfSETCC(SDNode *LogicOp, SelectionDAG &DAG) {
59075907
SDValue LHS1 = LHS->getOperand(1);
59085908
SDValue RHS1 = RHS->getOperand(1);
59095909

5910-
// TODO: We don't actually need a splat here, for vectors we just need
5911-
// LaneLHS[N] == -LaneRHS[N];
5910+
// TODO: We don't actually need a splat here, for vectors we just need the
5911+
// invariants to hold for each element.
59125912
auto *LHS1C = isConstOrConstSplat(LHS1);
59135913
auto *RHS1C = isConstOrConstSplat(RHS1);
59145914

@@ -5919,15 +5919,16 @@ static SDValue foldAndOrOfSETCC(SDNode *LogicOp, SelectionDAG &DAG) {
59195919
if (CCL == CCR &&
59205920
CCL == (LogicOp->getOpcode() == ISD::AND ? ISD::SETNE : ISD::SETEQ) &&
59215921
LHS0 == RHS0 && LHS1C && RHS1C && OpVT.isInteger() && LHS.hasOneUse() &&
5922-
RHS.hasOneUse() && LHS1C->getAPIntValue() == (-RHS1C->getAPIntValue())) {
5922+
RHS.hasOneUse()) {
5923+
const APInt &APLhs = LHS1C->getAPIntValue();
5924+
const APInt &APRhs = RHS1C->getAPIntValue();
59235925

59245926
// Preference is to use ISD::ABS or we already have an ISD::ABS (in which
59255927
// case this is just a compare).
5926-
if (TargetPreference == AndOrSETCCFoldKind::ABS ||
5927-
DAG.doesNodeExist(ISD::ABS, DAG.getVTList(OpVT), {LHS0})) {
5928-
APInt C = LHS1C->getAPIntValue();
5929-
if (C.isNegative())
5930-
C = RHS1C->getAPIntValue();
5928+
if (APLhs == (-APRhs) &&
5929+
(TargetPreference == AndOrSETCCFoldKind::ABS ||
5930+
DAG.doesNodeExist(ISD::ABS, DAG.getVTList(OpVT), {LHS0}))) {
5931+
const APInt &C = APLhs.isNegative() ? APRhs : APLhs;
59315932
// (icmp eq A, C) | (icmp eq A, -C)
59325933
// -> (icmp eq Abs(A), C)
59335934
// (icmp ne A, C) & (icmp ne A, -C)
@@ -5936,23 +5937,20 @@ static SDValue foldAndOrOfSETCC(SDNode *LogicOp, SelectionDAG &DAG) {
59365937
return DAG.getNode(ISD::SETCC, DL, VT, AbsOp,
59375938
DAG.getConstant(C, DL, OpVT), LHS.getOperand(2));
59385939
} else if (TargetPreference == AndOrSETCCFoldKind::AddAnd) {
5939-
// With C as a power of 2 and C != 0 and C != INT_MIN:
5940-
// (icmp eq A, C) | (icmp eq A, -C)
5941-
// -> (icmp eq and(add(A, C), ~(C + C)), 0)
5942-
// (icmp ne A, C) & (icmp ne A, -C)w
5943-
// -> (icmp ne and(add(A, C), ~(C + C)), 0)
5944-
const ConstantSDNode *Pow2 = nullptr;
5945-
if (LHS1C->getAPIntValue().isPowerOf2())
5946-
Pow2 = LHS1C;
5947-
else if (RHS1C->getAPIntValue().isPowerOf2())
5948-
Pow2 = RHS1C;
5949-
// isPowerOf2 is only for non-zero powers of 2.
5950-
if (Pow2 != nullptr && !Pow2->getAPIntValue().isMinSignedValue()) {
5951-
const APInt &C = Pow2->getAPIntValue();
5952-
SDValue AddOp =
5953-
DAG.getNode(ISD::ADD, DL, OpVT, LHS0, DAG.getConstant(C, DL, OpVT));
5940+
// A == C0 | A == C1
5941+
// IF IsPow2(smax(C0, C1)-smin(C0, C1))
5942+
// -> ((A - smin(C0, C1)) & ~(smax(C0, C1)-smin(C0, C1))) == 0
5943+
// A != C0 & A != C1
5944+
// IF IsPow2(smax(C0, C1)-smin(C0, C1))
5945+
// -> ((A - smin(C0, C1)) & ~(smax(C0, C1)-smin(C0, C1))) != 0
5946+
const APInt &MaxC = APIntOps::smax(APRhs, APLhs);
5947+
const APInt &MinC = APIntOps::smin(APRhs, APLhs);
5948+
APInt Dif = MaxC - MinC;
5949+
if (!Dif.isZero() && Dif.isPowerOf2()) {
5950+
SDValue AddOp = DAG.getNode(ISD::ADD, DL, OpVT, LHS0,
5951+
DAG.getConstant(-MinC, DL, OpVT));
59545952
SDValue AndOp = DAG.getNode(ISD::AND, DL, OpVT, AddOp,
5955-
DAG.getConstant(~(C + C), DL, OpVT));
5953+
DAG.getConstant(~Dif, DL, OpVT));
59565954
return DAG.getNode(ISD::SETCC, DL, VT, AndOp,
59575955
DAG.getConstant(0, DL, OpVT), LHS.getOperand(2));
59585956
}

llvm/test/CodeGen/X86/icmp-pow2-diff.ll

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -311,12 +311,9 @@ define i1 @andnot_ne_i32(i32 %x) nounwind {
311311
define i1 @addand_ne_i16(i16 %x) nounwind {
312312
; CHECK-LABEL: addand_ne_i16:
313313
; CHECK: # %bb.0:
314-
; CHECK-NEXT: cmpw $-3, %di
315-
; CHECK-NEXT: setne %cl
316-
; CHECK-NEXT: movzwl %di, %eax
317-
; CHECK-NEXT: cmpl $16381, %eax # imm = 0x3FFD
314+
; CHECK-NEXT: addl $3, %edi
315+
; CHECK-NEXT: testl $49151, %edi # imm = 0xBFFF
318316
; CHECK-NEXT: setne %al
319-
; CHECK-NEXT: andb %cl, %al
320317
; CHECK-NEXT: retq
321318
%cmp1 = icmp ne i16 %x, -3
322319
%cmp2 = icmp ne i16 %x, 16381
@@ -362,11 +359,9 @@ define <8 x i1> @addand_ne_v8i16_fail(<8 x i16> %x) nounwind {
362359
define i1 @addand_eq_i32(i32 %x) nounwind {
363360
; CHECK-LABEL: addand_eq_i32:
364361
; CHECK: # %bb.0:
365-
; CHECK-NEXT: cmpl $-1, %edi
366-
; CHECK-NEXT: sete %cl
367-
; CHECK-NEXT: cmpl $7, %edi
362+
; CHECK-NEXT: incl %edi
363+
; CHECK-NEXT: testl $-9, %edi
368364
; CHECK-NEXT: sete %al
369-
; CHECK-NEXT: orb %cl, %al
370365
; CHECK-NEXT: retq
371366
%cmp1 = icmp eq i32 %x, -1
372367
%cmp2 = icmp eq i32 %x, 7
@@ -393,11 +388,9 @@ define i1 @addand_eq_i8_fail_abs_p2_minmax_not(i8 %x) nounwind {
393388
define i1 @addand_ne_i8(i8 %x) nounwind {
394389
; CHECK-LABEL: addand_ne_i8:
395390
; CHECK: # %bb.0:
396-
; CHECK-NEXT: cmpb $59, %dil
397-
; CHECK-NEXT: setne %cl
398-
; CHECK-NEXT: cmpb $-5, %dil
391+
; CHECK-NEXT: addb $5, %dil
392+
; CHECK-NEXT: testb $-65, %dil
399393
; CHECK-NEXT: setne %al
400-
; CHECK-NEXT: andb %cl, %al
401394
; CHECK-NEXT: retq
402395
%cmp1 = icmp ne i8 %x, 59
403396
%cmp2 = icmp ne i8 %x, -5
@@ -424,11 +417,9 @@ define i1 @addand_eq_i64_fail_non_p2_dif(i64 %x) nounwind {
424417
define i1 @addand_eq_i64(i64 %x) nounwind {
425418
; CHECK-LABEL: addand_eq_i64:
426419
; CHECK: # %bb.0:
427-
; CHECK-NEXT: cmpq $768, %rdi # imm = 0x300
428-
; CHECK-NEXT: setne %cl
429-
; CHECK-NEXT: cmpq $-256, %rdi
420+
; CHECK-NEXT: addq $256, %rdi # imm = 0x100
421+
; CHECK-NEXT: testq $-1025, %rdi # imm = 0xFBFF
430422
; CHECK-NEXT: setne %al
431-
; CHECK-NEXT: andb %cl, %al
432423
; CHECK-NEXT: retq
433424
%cmp1 = icmp ne i64 %x, 768
434425
%cmp2 = icmp ne i64 %x, -256

llvm/test/CodeGen/X86/setcc-logic.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -456,8 +456,8 @@ define zeroext i1 @ne_neg1_and_ne_zero(i64 %x) nounwind {
456456
; CHECK-LABEL: ne_neg1_and_ne_zero:
457457
; CHECK: # %bb.0:
458458
; CHECK-NEXT: incq %rdi
459-
; CHECK-NEXT: cmpq $2, %rdi
460-
; CHECK-NEXT: setae %al
459+
; CHECK-NEXT: testq $-2, %rdi
460+
; CHECK-NEXT: setne %al
461461
; CHECK-NEXT: retq
462462
%cmp1 = icmp ne i64 %x, -1
463463
%cmp2 = icmp ne i64 %x, 0

0 commit comments

Comments
 (0)