Skip to content

Commit 0d562a0

Browse files
committed
[ExpandMemCmp] Recognize canonical form of (icmp sle/sge X, 0) in getMemCmpOneBlock.
This code recognizes special cases where the result of memcmp is compared with 0. If the compare is sle/sge, then InstCombine canonicalizes to (icmp slt X, 1) or (icmp sgt X, -1). I'm not sure if this is the best fix. After llvm#121530 we will emit a ucmp in the default case instead of (sub (zext (icmp ugt)), (zext (icmp ult))). With that it would be easy to optimize (setgt (ucmp X, Y), -1) in DAGCombine. Tests have not been pre-committed yet.
1 parent a885001 commit 0d562a0

File tree

4 files changed

+25
-50
lines changed

4 files changed

+25
-50
lines changed

llvm/lib/CodeGen/ExpandMemCmp.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -668,7 +668,7 @@ Value *MemCmpExpansion::getMemCmpOneBlock() {
668668
// We can generate more optimal code with a smaller number of operations
669669
if (CI->hasOneUser()) {
670670
auto *UI = cast<Instruction>(*CI->user_begin());
671-
CmpPredicate Pred = ICmpInst::Predicate::BAD_ICMP_PREDICATE;
671+
CmpPredicate Pred;
672672
uint64_t Shift;
673673
bool NeedsZExt = false;
674674
// This is a special case because instead of checking if the result is less
@@ -680,9 +680,19 @@ Value *MemCmpExpansion::getMemCmpOneBlock() {
680680
Shift == (CI->getType()->getIntegerBitWidth() - 1)) {
681681
Pred = ICmpInst::ICMP_SLT;
682682
NeedsZExt = true;
683+
} else if (match(UI, m_ICmp(Pred, m_Specific(CI), m_Zero()))) {
684+
// Compare with 0. Pred is already set.
685+
} else if (match(UI, m_ICmp(Pred, m_Specific(CI), m_AllOnes())) &&
686+
Pred == ICmpInst::ICMP_SGT) {
687+
// Adjust predicate as if it compared with 0.
688+
Pred = ICmpInst::ICMP_SGE;
689+
} else if (match(UI, m_ICmp(Pred, m_Specific(CI), m_One())) &&
690+
Pred == ICmpInst::ICMP_SLT) {
691+
// Adjust predicate as if it compared with 0.
692+
Pred = ICmpInst::ICMP_SLE;
683693
} else {
684-
// In case of a successful match this call will set `Pred` variable
685-
match(UI, m_ICmp(Pred, m_Specific(CI), m_Zero()));
694+
// No match, invalidate Pred.
695+
Pred = ICmpInst::Predicate::BAD_ICMP_PREDICATE;
686696
}
687697
// Generate new code and remove the original memcmp call and the user
688698
if (ICmpInst::isSigned(Pred)) {

llvm/test/CodeGen/AArch64/memcmp.ll

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -267,11 +267,7 @@ define i1 @length4_le(ptr %X, ptr %Y) nounwind {
267267
; CHECK-NEXT: rev w8, w8
268268
; CHECK-NEXT: rev w9, w9
269269
; CHECK-NEXT: cmp w8, w9
270-
; CHECK-NEXT: cset w8, hi
271-
; CHECK-NEXT: cset w9, lo
272-
; CHECK-NEXT: sub w8, w8, w9
273-
; CHECK-NEXT: cmp w8, #1
274-
; CHECK-NEXT: cset w0, lt
270+
; CHECK-NEXT: cset w0, ls
275271
; CHECK-NEXT: ret
276272
%m = tail call i32 @memcmp(ptr %X, ptr %Y, i64 4) nounwind
277273
%c = icmp slt i32 %m, 1
@@ -286,11 +282,7 @@ define i1 @length4_ge(ptr %X, ptr %Y) nounwind {
286282
; CHECK-NEXT: rev w8, w8
287283
; CHECK-NEXT: rev w9, w9
288284
; CHECK-NEXT: cmp w8, w9
289-
; CHECK-NEXT: cset w8, hi
290-
; CHECK-NEXT: cset w9, lo
291-
; CHECK-NEXT: sub w8, w8, w9
292-
; CHECK-NEXT: mvn w8, w8
293-
; CHECK-NEXT: lsr w0, w8, #31
285+
; CHECK-NEXT: cset w0, hs
294286
; CHECK-NEXT: ret
295287
%m = tail call i32 @memcmp(ptr %X, ptr %Y, i64 4) nounwind
296288
%c = icmp sgt i32 %m, -1

llvm/test/CodeGen/RISCV/memcmp.ll

Lines changed: 8 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6702,10 +6702,8 @@ define i1 @memcmp_le_zero(ptr %s1, ptr %s2) nounwind {
67026702
; CHECK-UNALIGNED-RV32-ZBB-NEXT: lw a1, 0(a1)
67036703
; CHECK-UNALIGNED-RV32-ZBB-NEXT: rev8 a0, a0
67046704
; CHECK-UNALIGNED-RV32-ZBB-NEXT: rev8 a1, a1
6705-
; CHECK-UNALIGNED-RV32-ZBB-NEXT: sltu a2, a1, a0
6706-
; CHECK-UNALIGNED-RV32-ZBB-NEXT: sltu a0, a0, a1
6707-
; CHECK-UNALIGNED-RV32-ZBB-NEXT: sub a2, a2, a0
6708-
; CHECK-UNALIGNED-RV32-ZBB-NEXT: slti a0, a2, 1
6705+
; CHECK-UNALIGNED-RV32-ZBB-NEXT: sltu a0, a1, a0
6706+
; CHECK-UNALIGNED-RV32-ZBB-NEXT: xori a0, a0, 1
67096707
; CHECK-UNALIGNED-RV32-ZBB-NEXT: ret
67106708
;
67116709
; CHECK-UNALIGNED-RV64-ZBB-LABEL: memcmp_le_zero:
@@ -6716,10 +6714,8 @@ define i1 @memcmp_le_zero(ptr %s1, ptr %s2) nounwind {
67166714
; CHECK-UNALIGNED-RV64-ZBB-NEXT: rev8 a1, a1
67176715
; CHECK-UNALIGNED-RV64-ZBB-NEXT: srli a0, a0, 32
67186716
; CHECK-UNALIGNED-RV64-ZBB-NEXT: srli a1, a1, 32
6719-
; CHECK-UNALIGNED-RV64-ZBB-NEXT: sltu a2, a1, a0
6720-
; CHECK-UNALIGNED-RV64-ZBB-NEXT: sltu a0, a0, a1
6721-
; CHECK-UNALIGNED-RV64-ZBB-NEXT: sub a2, a2, a0
6722-
; CHECK-UNALIGNED-RV64-ZBB-NEXT: slti a0, a2, 1
6717+
; CHECK-UNALIGNED-RV64-ZBB-NEXT: sltu a0, a1, a0
6718+
; CHECK-UNALIGNED-RV64-ZBB-NEXT: xori a0, a0, 1
67236719
; CHECK-UNALIGNED-RV64-ZBB-NEXT: ret
67246720
;
67256721
; CHECK-UNALIGNED-RV32-ZBKB-LABEL: memcmp_le_zero:
@@ -6728,10 +6724,8 @@ define i1 @memcmp_le_zero(ptr %s1, ptr %s2) nounwind {
67286724
; CHECK-UNALIGNED-RV32-ZBKB-NEXT: lw a1, 0(a1)
67296725
; CHECK-UNALIGNED-RV32-ZBKB-NEXT: rev8 a0, a0
67306726
; CHECK-UNALIGNED-RV32-ZBKB-NEXT: rev8 a1, a1
6731-
; CHECK-UNALIGNED-RV32-ZBKB-NEXT: sltu a2, a1, a0
6732-
; CHECK-UNALIGNED-RV32-ZBKB-NEXT: sltu a0, a0, a1
6733-
; CHECK-UNALIGNED-RV32-ZBKB-NEXT: sub a2, a2, a0
6734-
; CHECK-UNALIGNED-RV32-ZBKB-NEXT: slti a0, a2, 1
6727+
; CHECK-UNALIGNED-RV32-ZBKB-NEXT: sltu a0, a1, a0
6728+
; CHECK-UNALIGNED-RV32-ZBKB-NEXT: xori a0, a0, 1
67356729
; CHECK-UNALIGNED-RV32-ZBKB-NEXT: ret
67366730
;
67376731
; CHECK-UNALIGNED-RV64-ZBKB-LABEL: memcmp_le_zero:
@@ -6742,10 +6736,8 @@ define i1 @memcmp_le_zero(ptr %s1, ptr %s2) nounwind {
67426736
; CHECK-UNALIGNED-RV64-ZBKB-NEXT: rev8 a1, a1
67436737
; CHECK-UNALIGNED-RV64-ZBKB-NEXT: srli a0, a0, 32
67446738
; CHECK-UNALIGNED-RV64-ZBKB-NEXT: srli a1, a1, 32
6745-
; CHECK-UNALIGNED-RV64-ZBKB-NEXT: sltu a2, a1, a0
6746-
; CHECK-UNALIGNED-RV64-ZBKB-NEXT: sltu a0, a0, a1
6747-
; CHECK-UNALIGNED-RV64-ZBKB-NEXT: sub a2, a2, a0
6748-
; CHECK-UNALIGNED-RV64-ZBKB-NEXT: slti a0, a2, 1
6739+
; CHECK-UNALIGNED-RV64-ZBKB-NEXT: sltu a0, a1, a0
6740+
; CHECK-UNALIGNED-RV64-ZBKB-NEXT: xori a0, a0, 1
67496741
; CHECK-UNALIGNED-RV64-ZBKB-NEXT: ret
67506742
;
67516743
; CHECK-UNALIGNED-RV32-V-LABEL: memcmp_le_zero:
@@ -6902,10 +6894,7 @@ define i1 @memcmp_ge_zero(ptr %s1, ptr %s2) nounwind {
69026894
; CHECK-UNALIGNED-RV32-ZBB-NEXT: lw a1, 0(a1)
69036895
; CHECK-UNALIGNED-RV32-ZBB-NEXT: rev8 a0, a0
69046896
; CHECK-UNALIGNED-RV32-ZBB-NEXT: rev8 a1, a1
6905-
; CHECK-UNALIGNED-RV32-ZBB-NEXT: sltu a2, a1, a0
69066897
; CHECK-UNALIGNED-RV32-ZBB-NEXT: sltu a0, a0, a1
6907-
; CHECK-UNALIGNED-RV32-ZBB-NEXT: sub a2, a2, a0
6908-
; CHECK-UNALIGNED-RV32-ZBB-NEXT: slti a0, a2, 0
69096898
; CHECK-UNALIGNED-RV32-ZBB-NEXT: xori a0, a0, 1
69106899
; CHECK-UNALIGNED-RV32-ZBB-NEXT: ret
69116900
;
@@ -6917,10 +6906,7 @@ define i1 @memcmp_ge_zero(ptr %s1, ptr %s2) nounwind {
69176906
; CHECK-UNALIGNED-RV64-ZBB-NEXT: rev8 a1, a1
69186907
; CHECK-UNALIGNED-RV64-ZBB-NEXT: srli a0, a0, 32
69196908
; CHECK-UNALIGNED-RV64-ZBB-NEXT: srli a1, a1, 32
6920-
; CHECK-UNALIGNED-RV64-ZBB-NEXT: sltu a2, a1, a0
69216909
; CHECK-UNALIGNED-RV64-ZBB-NEXT: sltu a0, a0, a1
6922-
; CHECK-UNALIGNED-RV64-ZBB-NEXT: sub a2, a2, a0
6923-
; CHECK-UNALIGNED-RV64-ZBB-NEXT: slti a0, a2, 0
69246910
; CHECK-UNALIGNED-RV64-ZBB-NEXT: xori a0, a0, 1
69256911
; CHECK-UNALIGNED-RV64-ZBB-NEXT: ret
69266912
;
@@ -6930,10 +6916,7 @@ define i1 @memcmp_ge_zero(ptr %s1, ptr %s2) nounwind {
69306916
; CHECK-UNALIGNED-RV32-ZBKB-NEXT: lw a1, 0(a1)
69316917
; CHECK-UNALIGNED-RV32-ZBKB-NEXT: rev8 a0, a0
69326918
; CHECK-UNALIGNED-RV32-ZBKB-NEXT: rev8 a1, a1
6933-
; CHECK-UNALIGNED-RV32-ZBKB-NEXT: sltu a2, a1, a0
69346919
; CHECK-UNALIGNED-RV32-ZBKB-NEXT: sltu a0, a0, a1
6935-
; CHECK-UNALIGNED-RV32-ZBKB-NEXT: sub a2, a2, a0
6936-
; CHECK-UNALIGNED-RV32-ZBKB-NEXT: slti a0, a2, 0
69376920
; CHECK-UNALIGNED-RV32-ZBKB-NEXT: xori a0, a0, 1
69386921
; CHECK-UNALIGNED-RV32-ZBKB-NEXT: ret
69396922
;
@@ -6945,10 +6928,7 @@ define i1 @memcmp_ge_zero(ptr %s1, ptr %s2) nounwind {
69456928
; CHECK-UNALIGNED-RV64-ZBKB-NEXT: rev8 a1, a1
69466929
; CHECK-UNALIGNED-RV64-ZBKB-NEXT: srli a0, a0, 32
69476930
; CHECK-UNALIGNED-RV64-ZBKB-NEXT: srli a1, a1, 32
6948-
; CHECK-UNALIGNED-RV64-ZBKB-NEXT: sltu a2, a1, a0
69496931
; CHECK-UNALIGNED-RV64-ZBKB-NEXT: sltu a0, a0, a1
6950-
; CHECK-UNALIGNED-RV64-ZBKB-NEXT: sub a2, a2, a0
6951-
; CHECK-UNALIGNED-RV64-ZBKB-NEXT: slti a0, a2, 0
69526932
; CHECK-UNALIGNED-RV64-ZBKB-NEXT: xori a0, a0, 1
69536933
; CHECK-UNALIGNED-RV64-ZBKB-NEXT: ret
69546934
;

llvm/test/CodeGen/X86/memcmp.ll

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -267,12 +267,8 @@ define i1 @length4_le(ptr %X, ptr %Y) nounwind {
267267
; X64-NEXT: movl (%rsi), %ecx
268268
; X64-NEXT: bswapl %eax
269269
; X64-NEXT: bswapl %ecx
270-
; X64-NEXT: xorl %edx, %edx
271270
; X64-NEXT: cmpl %ecx, %eax
272-
; X64-NEXT: seta %dl
273-
; X64-NEXT: sbbl $0, %edx
274-
; X64-NEXT: testl %edx, %edx
275-
; X64-NEXT: setle %al
271+
; X64-NEXT: setbe %al
276272
; X64-NEXT: retq
277273
%m = tail call i32 @memcmp(ptr %X, ptr %Y, i64 4) nounwind
278274
%c = icmp slt i32 %m, 1
@@ -286,11 +282,8 @@ define i1 @length4_ge(ptr %X, ptr %Y) nounwind {
286282
; X64-NEXT: movl (%rsi), %ecx
287283
; X64-NEXT: bswapl %eax
288284
; X64-NEXT: bswapl %ecx
289-
; X64-NEXT: xorl %edx, %edx
290285
; X64-NEXT: cmpl %ecx, %eax
291-
; X64-NEXT: seta %dl
292-
; X64-NEXT: sbbl $0, %edx
293-
; X64-NEXT: setns %al
286+
; X64-NEXT: setae %al
294287
; X64-NEXT: retq
295288
%m = tail call i32 @memcmp(ptr %X, ptr %Y, i64 4) nounwind
296289
%c = icmp sgt i32 %m, -1

0 commit comments

Comments
 (0)