Skip to content

Commit b2f1621

Browse files
committed
[DAGCombiner] add and use TLI hook to convert and-of-seteq / or-of-setne to bitwise logic+setcc (PR32401)
This is a generic combine enabled via target hook to reduce icmp logic as discussed in: https://bugs.llvm.org/show_bug.cgi?id=32401 It's likely that other targets will want to enable this hook for scalar transforms, and there are probably other patterns that can use bitwise logic to reduce comparisons. Note that we are missing an IR canonicalization for these patterns, and we will probably prefer the pair-of-compares form in IR (shorter, more likely to fold). Differential Revision: https://reviews.llvm.org/D31483 llvm-svn: 299542
1 parent 6615f2b commit b2f1621

File tree

9 files changed

+65
-35
lines changed

9 files changed

+65
-35
lines changed

llvm/include/llvm/Target/TargetLowering.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,15 @@ class TargetLoweringBase {
437437
return false;
438438
}
439439

440+
/// Use bitwise logic to make pairs of compares more efficient. For example:
441+
/// and (seteq A, B), (seteq C, D) --> seteq (or (xor A, B), (xor C, D)), 0
442+
/// This should be true when it takes more than one instruction to lower
443+
/// setcc (cmp+set on x86 scalar), when bitwise ops are faster than logic on
444+
/// condition bits (crand on PowerPC), and/or when reducing cmp+br is a win.
445+
virtual bool convertSetCCLogicToBitwiseLogic(EVT VT) const {
446+
return false;
447+
}
448+
440449
/// Return the preferred operand type if the target has a quick way to compare
441450
/// integer values of the given size. Assume that any legal integer type can
442451
/// be compared efficiently. Targets may override this to allow illegal wide

llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3255,6 +3255,21 @@ SDValue DAGCombiner::foldLogicOfSetCCs(bool IsAnd, SDValue N0, SDValue N1,
32553255
return DAG.getSetCC(DL, VT, Add, Two, ISD::SETUGE);
32563256
}
32573257

3258+
// Try more general transforms if the predicates match and the only user of
3259+
// the compares is the 'and' or 'or'.
3260+
if (IsInteger && TLI.convertSetCCLogicToBitwiseLogic(OpVT) && CC0 == CC1 &&
3261+
N0.hasOneUse() && N1.hasOneUse()) {
3262+
// and (seteq A, B), (seteq C, D) --> seteq (or (xor A, B), (xor C, D)), 0
3263+
// or (setne A, B), (setne C, D) --> setne (or (xor A, B), (xor C, D)), 0
3264+
if ((IsAnd && CC1 == ISD::SETEQ) || (!IsAnd && CC1 == ISD::SETNE)) {
3265+
SDValue XorL = DAG.getNode(ISD::XOR, SDLoc(N0), OpVT, LL, LR);
3266+
SDValue XorR = DAG.getNode(ISD::XOR, SDLoc(N1), OpVT, RL, RR);
3267+
SDValue Or = DAG.getNode(ISD::OR, DL, OpVT, XorL, XorR);
3268+
SDValue Zero = DAG.getConstant(0, DL, OpVT);
3269+
return DAG.getSetCC(DL, VT, Or, Zero, CC1);
3270+
}
3271+
}
3272+
32583273
// Canonicalize equivalent operands to LL == RL.
32593274
if (LL == RR && LR == RL) {
32603275
CC1 = ISD::getSetCCSwappedOperands(CC1);

llvm/lib/Target/ARM/ARMISelLowering.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,10 @@ class InstrItineraryData;
515515
bool isCheapToSpeculateCttz() const override;
516516
bool isCheapToSpeculateCtlz() const override;
517517

518+
bool convertSetCCLogicToBitwiseLogic(EVT VT) const override {
519+
return VT.isScalarInteger();
520+
}
521+
518522
bool supportSwiftError() const override {
519523
return true;
520524
}

llvm/lib/Target/PowerPC/PPCISelLowering.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,10 @@ namespace llvm {
531531
return true;
532532
}
533533

534+
bool convertSetCCLogicToBitwiseLogic(EVT VT) const override {
535+
return VT.isScalarInteger();
536+
}
537+
534538
bool supportSplitCSR(MachineFunction *MF) const override {
535539
return
536540
MF->getFunction()->getCallingConv() == CallingConv::CXX_FAST_TLS &&

llvm/lib/Target/X86/X86ISelLowering.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -814,6 +814,10 @@ namespace llvm {
814814

815815
bool hasAndNotCompare(SDValue Y) const override;
816816

817+
bool convertSetCCLogicToBitwiseLogic(EVT VT) const override {
818+
return VT.isScalarInteger();
819+
}
820+
817821
/// Vector-sized comparisons are fast using PCMPEQ + PMOVMSK or PTEST.
818822
MVT hasFastEqualityCompare(unsigned NumBits) const override;
819823

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

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,11 @@ define zeroext i1 @ne_neg1_and_ne_zero(i32 %x) nounwind {
2020
define zeroext i1 @and_eq(i32 %a, i32 %b, i32 %c, i32 %d) nounwind {
2121
; CHECK-LABEL: and_eq:
2222
; CHECK: @ BB#0:
23-
; CHECK-NEXT: cmp r2, r3
24-
; CHECK-NEXT: mov r2, #0
25-
; CHECK-NEXT: movweq r2, #1
26-
; CHECK-NEXT: mov r12, #0
27-
; CHECK-NEXT: cmp r0, r1
28-
; CHECK-NEXT: movweq r12, #1
29-
; CHECK-NEXT: and r0, r12, r2
23+
; CHECK-NEXT: eor r2, r2, r3
24+
; CHECK-NEXT: eor r0, r0, r1
25+
; CHECK-NEXT: orrs r0, r0, r2
26+
; CHECK-NEXT: mov r0, #0
27+
; CHECK-NEXT: movweq r0, #1
3028
; CHECK-NEXT: bx lr
3129
%cmp1 = icmp eq i32 %a, %b
3230
%cmp2 = icmp eq i32 %c, %d
@@ -37,13 +35,10 @@ define zeroext i1 @and_eq(i32 %a, i32 %b, i32 %c, i32 %d) nounwind {
3735
define zeroext i1 @or_ne(i32 %a, i32 %b, i32 %c, i32 %d) nounwind {
3836
; CHECK-LABEL: or_ne:
3937
; CHECK: @ BB#0:
40-
; CHECK-NEXT: cmp r2, r3
41-
; CHECK-NEXT: mov r2, #0
42-
; CHECK-NEXT: movwne r2, #1
43-
; CHECK-NEXT: mov r12, #0
44-
; CHECK-NEXT: cmp r0, r1
45-
; CHECK-NEXT: movwne r12, #1
46-
; CHECK-NEXT: orr r0, r12, r2
38+
; CHECK-NEXT: eor r2, r2, r3
39+
; CHECK-NEXT: eor r0, r0, r1
40+
; CHECK-NEXT: orrs r0, r0, r2
41+
; CHECK-NEXT: movwne r0, #1
4742
; CHECK-NEXT: bx lr
4843
%cmp1 = icmp ne i32 %a, %b
4944
%cmp2 = icmp ne i32 %c, %d

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

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -433,11 +433,11 @@ define zeroext i1 @ne_neg1_and_ne_zero(i64 %x) {
433433
define zeroext i1 @and_eq(i16 zeroext %a, i16 zeroext %b, i16 zeroext %c, i16 zeroext %d) {
434434
; CHECK-LABEL: and_eq:
435435
; CHECK: # BB#0:
436-
; CHECK-NEXT: cmpw 0, 3, 4
437-
; CHECK-NEXT: cmpw 1, 5, 6
438-
; CHECK-NEXT: li 3, 1
439-
; CHECK-NEXT: crnand 20, 2, 6
440-
; CHECK-NEXT: isel 3, 0, 3, 20
436+
; CHECK-NEXT: xor 5, 5, 6
437+
; CHECK-NEXT: xor 3, 3, 4
438+
; CHECK-NEXT: or 3, 3, 5
439+
; CHECK-NEXT: cntlzw 3, 3
440+
; CHECK-NEXT: rlwinm 3, 3, 27, 31, 31
441441
; CHECK-NEXT: blr
442442
%cmp1 = icmp eq i16 %a, %b
443443
%cmp2 = icmp eq i16 %c, %d
@@ -448,11 +448,12 @@ define zeroext i1 @and_eq(i16 zeroext %a, i16 zeroext %b, i16 zeroext %c, i16 z
448448
define zeroext i1 @or_ne(i32 %a, i32 %b, i32 %c, i32 %d) {
449449
; CHECK-LABEL: or_ne:
450450
; CHECK: # BB#0:
451-
; CHECK-NEXT: cmpw 0, 3, 4
452-
; CHECK-NEXT: cmpw 1, 5, 6
453-
; CHECK-NEXT: li 3, 1
454-
; CHECK-NEXT: crand 20, 6, 2
455-
; CHECK-NEXT: isel 3, 0, 3, 20
451+
; CHECK-NEXT: xor 5, 5, 6
452+
; CHECK-NEXT: xor 3, 3, 4
453+
; CHECK-NEXT: or 3, 3, 5
454+
; CHECK-NEXT: cntlzw 3, 3
455+
; CHECK-NEXT: nor 3, 3, 3
456+
; CHECK-NEXT: rlwinm 3, 3, 27, 31, 31
456457
; CHECK-NEXT: blr
457458
%cmp1 = icmp ne i32 %a, %b
458459
%cmp2 = icmp ne i32 %c, %d

llvm/test/CodeGen/X86/avx512-cmp.ll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,12 +120,12 @@ entry:
120120
define i32 @test8(i32 %a1, i32 %a2, i32 %a3) {
121121
; ALL-LABEL: test8:
122122
; ALL: ## BB#0:
123+
; ALL-NEXT: notl %edi
124+
; ALL-NEXT: xorl $-2147483648, %esi ## imm = 0x80000000
123125
; ALL-NEXT: testl %edx, %edx
124126
; ALL-NEXT: movl $1, %eax
125127
; ALL-NEXT: cmovel %eax, %edx
126-
; ALL-NEXT: cmpl $-2147483648, %esi ## imm = 0x80000000
127-
; ALL-NEXT: cmovnel %edx, %eax
128-
; ALL-NEXT: cmpl $-1, %edi
128+
; ALL-NEXT: orl %edi, %esi
129129
; ALL-NEXT: cmovnel %edx, %eax
130130
; ALL-NEXT: retq
131131
%tmp1 = icmp eq i32 %a1, -1

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

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -440,11 +440,10 @@ define zeroext i1 @ne_neg1_and_ne_zero(i64 %x) nounwind {
440440
define zeroext i1 @and_eq(i8 %a, i8 %b, i8 %c, i8 %d) nounwind {
441441
; CHECK-LABEL: and_eq:
442442
; CHECK: # BB#0:
443-
; CHECK-NEXT: cmpb %sil, %dil
444-
; CHECK-NEXT: sete %sil
445-
; CHECK-NEXT: cmpb %cl, %dl
443+
; CHECK-NEXT: xorl %esi, %edi
444+
; CHECK-NEXT: xorl %ecx, %edx
445+
; CHECK-NEXT: orb %dl, %dil
446446
; CHECK-NEXT: sete %al
447-
; CHECK-NEXT: andb %sil, %al
448447
; CHECK-NEXT: retq
449448
%cmp1 = icmp eq i8 %a, %b
450449
%cmp2 = icmp eq i8 %c, %d
@@ -455,11 +454,10 @@ define zeroext i1 @and_eq(i8 %a, i8 %b, i8 %c, i8 %d) nounwind {
455454
define zeroext i1 @or_ne(i8 %a, i8 %b, i8 %c, i8 %d) nounwind {
456455
; CHECK-LABEL: or_ne:
457456
; CHECK: # BB#0:
458-
; CHECK-NEXT: cmpb %sil, %dil
459-
; CHECK-NEXT: setne %sil
460-
; CHECK-NEXT: cmpb %cl, %dl
457+
; CHECK-NEXT: xorl %esi, %edi
458+
; CHECK-NEXT: xorl %ecx, %edx
459+
; CHECK-NEXT: orb %dl, %dil
461460
; CHECK-NEXT: setne %al
462-
; CHECK-NEXT: orb %sil, %al
463461
; CHECK-NEXT: retq
464462
%cmp1 = icmp ne i8 %a, %b
465463
%cmp2 = icmp ne i8 %c, %d

0 commit comments

Comments
 (0)