[llvm] [InstCombine] Fold (sub (xor X, (sext C)), (sext C)) => (select C (neg X), X) (PR #79417)

Kai Luo via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 25 23:49:11 PST 2024


https://github.com/bzEq updated https://github.com/llvm/llvm-project/pull/79417

>From 85360d691b8572a1f2d6e42f11dd2694b194507a Mon Sep 17 00:00:00 2001
From: Kai Luo <lkail at cn.ibm.com>
Date: Thu, 25 Jan 2024 07:48:50 +0000
Subject: [PATCH 1/8] Add test

---
 llvm/test/CodeGen/AArch64/absdiff.ll          | 18 +++++++++++++++
 llvm/test/CodeGen/PowerPC/absdiff.ll          | 19 ++++++++++++++++
 llvm/test/CodeGen/X86/absdiff.ll              | 22 +++++++++++++++++++
 .../Transforms/InstCombine/sub-xor-cmp.ll     | 20 +++++++++++++++++
 4 files changed, 79 insertions(+)
 create mode 100644 llvm/test/CodeGen/AArch64/absdiff.ll
 create mode 100644 llvm/test/CodeGen/PowerPC/absdiff.ll
 create mode 100644 llvm/test/CodeGen/X86/absdiff.ll
 create mode 100644 llvm/test/Transforms/InstCombine/sub-xor-cmp.ll

diff --git a/llvm/test/CodeGen/AArch64/absdiff.ll b/llvm/test/CodeGen/AArch64/absdiff.ll
new file mode 100644
index 000000000000000..ca7b5a583cbe51e
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/absdiff.ll
@@ -0,0 +1,18 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
+; RUN: opt -mtriple=aarch64-linux-gnu -passes=instcombine < %s -o - | llc -mtriple=aarch64-linux-gnu -o - | FileCheck %s
+
+define  i64 @absdiff(i64 %0, i64 %1) {
+; CHECK-LABEL: absdiff:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    subs x8, x0, x1
+; CHECK-NEXT:    csetm x9, lo
+; CHECK-NEXT:    cinv x8, x8, lo
+; CHECK-NEXT:    sub x0, x8, x9
+; CHECK-NEXT:    ret
+  %3 = icmp ult i64 %0, %1
+  %4 = sext i1 %3 to i64
+  %5 = sub i64 %0, %1
+  %6 = xor i64 %5, %4
+  %7 = sub i64 %6, %4
+  ret i64 %7
+}
diff --git a/llvm/test/CodeGen/PowerPC/absdiff.ll b/llvm/test/CodeGen/PowerPC/absdiff.ll
new file mode 100644
index 000000000000000..a26482fc6497b8a
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/absdiff.ll
@@ -0,0 +1,19 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
+; RUN: opt -mtriple=powerpc64-linux-gnu -passes=instcombine < %s -o - | llc -mtriple=powerpc64-linux-gnu -o - | FileCheck %s
+
+define  i64 @absdiff(i64 %0, i64 %1) {
+; CHECK-LABEL: absdiff:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subc 5, 3, 4
+; CHECK-NEXT:    subfe 5, 3, 3
+; CHECK-NEXT:    sub 3, 3, 4
+; CHECK-NEXT:    xor 3, 3, 5
+; CHECK-NEXT:    sub 3, 3, 5
+; CHECK-NEXT:    blr
+  %3 = icmp ult i64 %0, %1
+  %4 = sext i1 %3 to i64
+  %5 = sub i64 %0, %1
+  %6 = xor i64 %5, %4
+  %7 = sub i64 %6, %4
+  ret i64 %7
+}
diff --git a/llvm/test/CodeGen/X86/absdiff.ll b/llvm/test/CodeGen/X86/absdiff.ll
new file mode 100644
index 000000000000000..46c7b62e43685b7
--- /dev/null
+++ b/llvm/test/CodeGen/X86/absdiff.ll
@@ -0,0 +1,22 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
+; RUN: opt -mtriple=x86_64-linux-gnu -passes=instcombine < %s -o - | llc -mtriple=x86_64-linux-gnu -o - | FileCheck %s
+
+define  i64 @absdiff(i64 %0, i64 %1) {
+; CHECK-LABEL: absdiff:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    movq %rdi, %rcx
+; CHECK-NEXT:    subq %rsi, %rcx
+; CHECK-NEXT:    setb %al
+; CHECK-NEXT:    negq %rax
+; CHECK-NEXT:    xorq %rcx, %rax
+; CHECK-NEXT:    cmpq %rsi, %rdi
+; CHECK-NEXT:    adcq $0, %rax
+; CHECK-NEXT:    retq
+  %3 = icmp ult i64 %0, %1
+  %4 = sext i1 %3 to i64
+  %5 = sub i64 %0, %1
+  %6 = xor i64 %5, %4
+  %7 = sub i64 %6, %4
+  ret i64 %7
+}
diff --git a/llvm/test/Transforms/InstCombine/sub-xor-cmp.ll b/llvm/test/Transforms/InstCombine/sub-xor-cmp.ll
new file mode 100644
index 000000000000000..0555bc1c365f5a4
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/sub-xor-cmp.ll
@@ -0,0 +1,20 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+
+define  i64 @absdiff(i64 %0, i64 %1) {
+; CHECK-LABEL: define i64 @absdiff(
+; CHECK-SAME: i64 [[TMP0:%.*]], i64 [[TMP1:%.*]]) {
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp ult i64 [[TMP0]], [[TMP1]]
+; CHECK-NEXT:    [[TMP4:%.*]] = sext i1 [[TMP3]] to i64
+; CHECK-NEXT:    [[TMP5:%.*]] = sub i64 [[TMP0]], [[TMP1]]
+; CHECK-NEXT:    [[TMP6:%.*]] = xor i64 [[TMP5]], [[TMP4]]
+; CHECK-NEXT:    [[TMP7:%.*]] = sub i64 [[TMP6]], [[TMP4]]
+; CHECK-NEXT:    ret i64 [[TMP7]]
+;
+  %3 = icmp ult i64 %0, %1
+  %4 = sext i1 %3 to i64
+  %5 = sub i64 %0, %1
+  %6 = xor i64 %5, %4
+  %7 = sub i64 %6, %4
+  ret i64 %7
+}

>From 9073811a3b45c6bee911f5af4ec3f9debd09f62f Mon Sep 17 00:00:00 2001
From: Kai Luo <lkail at cn.ibm.com>
Date: Thu, 25 Jan 2024 06:45:33 +0000
Subject: [PATCH 2/8] (sub (xor X, (sext C)), (sext C)) => (select C (neg X),
 X)

---
 llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index 8a00b75a1f74042..1a13fa4e2099946 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -2448,6 +2448,16 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
     }
   }
 
+  {
+    // (sub (xor X, (sext C)), (sext C)) => (select C (neg X), X)
+    Value *C0, *C1, *X;
+    if (match(Op0, m_Xor(m_Value(X), m_SExt(m_Value(C0)))) &&
+        (C0->getType()->getScalarSizeInBits() == 1) &&
+        match(Op1, m_SExt(m_Value(C1))) && (C0 == C1)) {
+      return SelectInst::Create(C0, Builder.CreateNeg(X), X);
+    }
+  }
+
   if (Instruction *R = tryFoldInstWithCtpopWithNot(&I))
     return R;
 

>From 6ef247174203d4a47e16ed5648fbfade3284ecff Mon Sep 17 00:00:00 2001
From: Kai Luo <lkail at cn.ibm.com>
Date: Thu, 25 Jan 2024 07:52:14 +0000
Subject: [PATCH 3/8] Update test

---
 llvm/test/CodeGen/AArch64/absdiff.ll            |  4 +---
 llvm/test/CodeGen/PowerPC/absdiff.ll            | 14 +++++++++-----
 llvm/test/CodeGen/X86/absdiff.ll                | 11 ++++-------
 llvm/test/Transforms/InstCombine/sub-xor-cmp.ll |  9 ++++-----
 4 files changed, 18 insertions(+), 20 deletions(-)

diff --git a/llvm/test/CodeGen/AArch64/absdiff.ll b/llvm/test/CodeGen/AArch64/absdiff.ll
index ca7b5a583cbe51e..88c6fdad0a2030d 100644
--- a/llvm/test/CodeGen/AArch64/absdiff.ll
+++ b/llvm/test/CodeGen/AArch64/absdiff.ll
@@ -5,9 +5,7 @@ define  i64 @absdiff(i64 %0, i64 %1) {
 ; CHECK-LABEL: absdiff:
 ; CHECK:       // %bb.0:
 ; CHECK-NEXT:    subs x8, x0, x1
-; CHECK-NEXT:    csetm x9, lo
-; CHECK-NEXT:    cinv x8, x8, lo
-; CHECK-NEXT:    sub x0, x8, x9
+; CHECK-NEXT:    cneg x0, x8, lo
 ; CHECK-NEXT:    ret
   %3 = icmp ult i64 %0, %1
   %4 = sext i1 %3 to i64
diff --git a/llvm/test/CodeGen/PowerPC/absdiff.ll b/llvm/test/CodeGen/PowerPC/absdiff.ll
index a26482fc6497b8a..c806da988f0a0bf 100644
--- a/llvm/test/CodeGen/PowerPC/absdiff.ll
+++ b/llvm/test/CodeGen/PowerPC/absdiff.ll
@@ -4,11 +4,15 @@
 define  i64 @absdiff(i64 %0, i64 %1) {
 ; CHECK-LABEL: absdiff:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    subc 5, 3, 4
-; CHECK-NEXT:    subfe 5, 3, 3
-; CHECK-NEXT:    sub 3, 3, 4
-; CHECK-NEXT:    xor 3, 3, 5
-; CHECK-NEXT:    sub 3, 3, 5
+; CHECK-NEXT:    sub 5, 3, 4
+; CHECK-NEXT:    neg 6, 5
+; CHECK-NEXT:    cmpld 3, 4
+; CHECK-NEXT:    bc 12, 0, .LBB0_2
+; CHECK-NEXT:  # %bb.1:
+; CHECK-NEXT:    ori 3, 5, 0
+; CHECK-NEXT:    blr
+; CHECK-NEXT:  .LBB0_2:
+; CHECK-NEXT:    addi 3, 6, 0
 ; CHECK-NEXT:    blr
   %3 = icmp ult i64 %0, %1
   %4 = sext i1 %3 to i64
diff --git a/llvm/test/CodeGen/X86/absdiff.ll b/llvm/test/CodeGen/X86/absdiff.ll
index 46c7b62e43685b7..ce9a00935448131 100644
--- a/llvm/test/CodeGen/X86/absdiff.ll
+++ b/llvm/test/CodeGen/X86/absdiff.ll
@@ -4,14 +4,11 @@
 define  i64 @absdiff(i64 %0, i64 %1) {
 ; CHECK-LABEL: absdiff:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    xorl %eax, %eax
-; CHECK-NEXT:    movq %rdi, %rcx
-; CHECK-NEXT:    subq %rsi, %rcx
-; CHECK-NEXT:    setb %al
+; CHECK-NEXT:    movq %rdi, %rax
+; CHECK-NEXT:    subq %rsi, %rax
 ; CHECK-NEXT:    negq %rax
-; CHECK-NEXT:    xorq %rcx, %rax
-; CHECK-NEXT:    cmpq %rsi, %rdi
-; CHECK-NEXT:    adcq $0, %rax
+; CHECK-NEXT:    subq %rsi, %rdi
+; CHECK-NEXT:    cmovaeq %rdi, %rax
 ; CHECK-NEXT:    retq
   %3 = icmp ult i64 %0, %1
   %4 = sext i1 %3 to i64
diff --git a/llvm/test/Transforms/InstCombine/sub-xor-cmp.ll b/llvm/test/Transforms/InstCombine/sub-xor-cmp.ll
index 0555bc1c365f5a4..393f2bd45bb8d77 100644
--- a/llvm/test/Transforms/InstCombine/sub-xor-cmp.ll
+++ b/llvm/test/Transforms/InstCombine/sub-xor-cmp.ll
@@ -5,11 +5,10 @@ define  i64 @absdiff(i64 %0, i64 %1) {
 ; CHECK-LABEL: define i64 @absdiff(
 ; CHECK-SAME: i64 [[TMP0:%.*]], i64 [[TMP1:%.*]]) {
 ; CHECK-NEXT:    [[TMP3:%.*]] = icmp ult i64 [[TMP0]], [[TMP1]]
-; CHECK-NEXT:    [[TMP4:%.*]] = sext i1 [[TMP3]] to i64
-; CHECK-NEXT:    [[TMP5:%.*]] = sub i64 [[TMP0]], [[TMP1]]
-; CHECK-NEXT:    [[TMP6:%.*]] = xor i64 [[TMP5]], [[TMP4]]
-; CHECK-NEXT:    [[TMP7:%.*]] = sub i64 [[TMP6]], [[TMP4]]
-; CHECK-NEXT:    ret i64 [[TMP7]]
+; CHECK-NEXT:    [[TMP4:%.*]] = sub i64 [[TMP0]], [[TMP1]]
+; CHECK-NEXT:    [[TMP5:%.*]] = sub i64 0, [[TMP4]]
+; CHECK-NEXT:    [[TMP6:%.*]] = select i1 [[TMP3]], i64 [[TMP5]], i64 [[TMP4]]
+; CHECK-NEXT:    ret i64 [[TMP6]]
 ;
   %3 = icmp ult i64 %0, %1
   %4 = sext i1 %3 to i64

>From cb8c375ed2f7385470f8a096cf920c71ae6267e3 Mon Sep 17 00:00:00 2001
From: Kai Luo <gluokai at gmail.com>
Date: Fri, 26 Jan 2024 13:06:37 +0800
Subject: [PATCH 4/8] Add codegen comparison

---
 llvm/test/CodeGen/AArch64/absdiff.ll | 35 +++++++++++++++++++++--
 llvm/test/CodeGen/PowerPC/absdiff.ll | 42 ++++++++++++++++++++++++++--
 llvm/test/CodeGen/X86/absdiff.ll     | 39 ++++++++++++++++++++++++--
 3 files changed, 108 insertions(+), 8 deletions(-)

diff --git a/llvm/test/CodeGen/AArch64/absdiff.ll b/llvm/test/CodeGen/AArch64/absdiff.ll
index 88c6fdad0a2030d..0c6677c619d6802 100644
--- a/llvm/test/CodeGen/AArch64/absdiff.ll
+++ b/llvm/test/CodeGen/AArch64/absdiff.ll
@@ -1,11 +1,27 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
-; RUN: opt -mtriple=aarch64-linux-gnu -passes=instcombine < %s -o - | llc -mtriple=aarch64-linux-gnu -o - | FileCheck %s
+; RUN: llc -mtriple=aarch64-linux-gnu -o - | FileCheck %s
 
-define  i64 @absdiff(i64 %0, i64 %1) {
+define i64 @absdiff(i64 %0, i64 %1) {
 ; CHECK-LABEL: absdiff:
 ; CHECK:       // %bb.0:
+; CHECK-NEXT:    sub x8, x1, x0
+; CHECK-NEXT:    subs x9, x0, x1
+; CHECK-NEXT:    csel x0, x8, x9, lo
+; CHECK-NEXT:    ret
+  %3 = icmp ult i64 %0, %1
+  %4 = sub i64 %0, %1
+  %5 = sub i64 %1, %0
+  %6 = select i1 %3, i64 %5, i64 %4
+  ret i64 %6
+}
+
+define i64 @absdiff1(i64 %0, i64 %1) {
+; CHECK-LABEL: absdiff1:
+; CHECK:       // %bb.0:
 ; CHECK-NEXT:    subs x8, x0, x1
-; CHECK-NEXT:    cneg x0, x8, lo
+; CHECK-NEXT:    csetm x9, lo
+; CHECK-NEXT:    cinv x8, x8, lo
+; CHECK-NEXT:    sub x0, x8, x9
 ; CHECK-NEXT:    ret
   %3 = icmp ult i64 %0, %1
   %4 = sext i1 %3 to i64
@@ -14,3 +30,16 @@ define  i64 @absdiff(i64 %0, i64 %1) {
   %7 = sub i64 %6, %4
   ret i64 %7
 }
+
+define i64 @absdiff2(i64 %0, i64 %1) {
+; CHECK-LABEL: absdiff2:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    subs x8, x0, x1
+; CHECK-NEXT:    cneg x0, x8, lo
+; CHECK-NEXT:    ret
+  %3 = icmp ult i64 %0, %1
+  %4 = sub i64 %0, %1
+  %5 = sub i64 0, %4
+  %6 = select i1 %3, i64 %5, i64 %4
+  ret i64 %6
+}
diff --git a/llvm/test/CodeGen/PowerPC/absdiff.ll b/llvm/test/CodeGen/PowerPC/absdiff.ll
index c806da988f0a0bf..a0959e5908241b9 100644
--- a/llvm/test/CodeGen/PowerPC/absdiff.ll
+++ b/llvm/test/CodeGen/PowerPC/absdiff.ll
@@ -1,11 +1,11 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
-; RUN: opt -mtriple=powerpc64-linux-gnu -passes=instcombine < %s -o - | llc -mtriple=powerpc64-linux-gnu -o - | FileCheck %s
+; RUN: llc -mtriple=powerpc64-linux-gnu -o - | FileCheck %s
 
-define  i64 @absdiff(i64 %0, i64 %1) {
+define i64 @absdiff(i64 %0, i64 %1) {
 ; CHECK-LABEL: absdiff:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    sub 5, 3, 4
-; CHECK-NEXT:    neg 6, 5
+; CHECK-NEXT:    sub 6, 4, 3
 ; CHECK-NEXT:    cmpld 3, 4
 ; CHECK-NEXT:    bc 12, 0, .LBB0_2
 ; CHECK-NEXT:  # %bb.1:
@@ -13,6 +13,22 @@ define  i64 @absdiff(i64 %0, i64 %1) {
 ; CHECK-NEXT:    blr
 ; CHECK-NEXT:  .LBB0_2:
 ; CHECK-NEXT:    addi 3, 6, 0
+; CHECK-NEXT:    blr
+  %3 = icmp ult i64 %0, %1
+  %4 = sub i64 %0, %1
+  %5 = sub i64 %1, %0
+  %6 = select i1 %3, i64 %5, i64 %4
+  ret i64 %6
+}
+
+define i64 @absdiff1(i64 %0, i64 %1) {
+; CHECK-LABEL: absdiff1:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    subc 5, 3, 4
+; CHECK-NEXT:    subfe 5, 3, 3
+; CHECK-NEXT:    sub 3, 3, 4
+; CHECK-NEXT:    xor 3, 3, 5
+; CHECK-NEXT:    sub 3, 3, 5
 ; CHECK-NEXT:    blr
   %3 = icmp ult i64 %0, %1
   %4 = sext i1 %3 to i64
@@ -21,3 +37,23 @@ define  i64 @absdiff(i64 %0, i64 %1) {
   %7 = sub i64 %6, %4
   ret i64 %7
 }
+
+define i64 @absdiff2(i64 %0, i64 %1) {
+; CHECK-LABEL: absdiff2:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    sub 5, 3, 4
+; CHECK-NEXT:    neg 6, 5
+; CHECK-NEXT:    cmpld 3, 4
+; CHECK-NEXT:    bc 12, 0, .LBB2_2
+; CHECK-NEXT:  # %bb.1:
+; CHECK-NEXT:    ori 3, 5, 0
+; CHECK-NEXT:    blr
+; CHECK-NEXT:  .LBB2_2:
+; CHECK-NEXT:    addi 3, 6, 0
+; CHECK-NEXT:    blr
+  %3 = icmp ult i64 %0, %1
+  %4 = sub i64 %0, %1
+  %5 = sub i64 0, %4
+  %6 = select i1 %3, i64 %5, i64 %4
+  ret i64 %6
+}
diff --git a/llvm/test/CodeGen/X86/absdiff.ll b/llvm/test/CodeGen/X86/absdiff.ll
index ce9a00935448131..cabb3628f369c4f 100644
--- a/llvm/test/CodeGen/X86/absdiff.ll
+++ b/llvm/test/CodeGen/X86/absdiff.ll
@@ -1,7 +1,7 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
-; RUN: opt -mtriple=x86_64-linux-gnu -passes=instcombine < %s -o - | llc -mtriple=x86_64-linux-gnu -o - | FileCheck %s
+; RUN: llc -mtriple=x86_64-linux-gnu -o - | FileCheck %s
 
-define  i64 @absdiff(i64 %0, i64 %1) {
+define i64 @absdiff(i64 %0, i64 %1) {
 ; CHECK-LABEL: absdiff:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    movq %rdi, %rax
@@ -9,6 +9,25 @@ define  i64 @absdiff(i64 %0, i64 %1) {
 ; CHECK-NEXT:    negq %rax
 ; CHECK-NEXT:    subq %rsi, %rdi
 ; CHECK-NEXT:    cmovaeq %rdi, %rax
+; CHECK-NEXT:    retq
+  %3 = icmp ult i64 %0, %1
+  %4 = sub i64 %0, %1
+  %5 = sub i64 %1, %0
+  %6 = select i1 %3, i64 %5, i64 %4
+  ret i64 %6
+}
+
+define i64 @absdiff1(i64 %0, i64 %1) {
+; CHECK-LABEL: absdiff1:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    movq %rdi, %rcx
+; CHECK-NEXT:    subq %rsi, %rcx
+; CHECK-NEXT:    setb %al
+; CHECK-NEXT:    negq %rax
+; CHECK-NEXT:    xorq %rcx, %rax
+; CHECK-NEXT:    cmpq %rsi, %rdi
+; CHECK-NEXT:    adcq $0, %rax
 ; CHECK-NEXT:    retq
   %3 = icmp ult i64 %0, %1
   %4 = sext i1 %3 to i64
@@ -17,3 +36,19 @@ define  i64 @absdiff(i64 %0, i64 %1) {
   %7 = sub i64 %6, %4
   ret i64 %7
 }
+
+define i64 @absdiff2(i64 %0, i64 %1) {
+; CHECK-LABEL: absdiff2:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    movq %rdi, %rax
+; CHECK-NEXT:    subq %rsi, %rax
+; CHECK-NEXT:    negq %rax
+; CHECK-NEXT:    subq %rsi, %rdi
+; CHECK-NEXT:    cmovaeq %rdi, %rax
+; CHECK-NEXT:    retq
+  %3 = icmp ult i64 %0, %1
+  %4 = sub i64 %0, %1
+  %5 = sub i64 0, %4
+  %6 = select i1 %3, i64 %5, i64 %4
+  ret i64 %6
+}

>From 80ef5c90038ecc1837a620f227933cd642e366b0 Mon Sep 17 00:00:00 2001
From: Kai Luo <gluokai at gmail.com>
Date: Fri, 26 Jan 2024 13:30:42 +0800
Subject: [PATCH 5/8] Fix test

---
 llvm/test/CodeGen/AArch64/absdiff.ll | 2 +-
 llvm/test/CodeGen/PowerPC/absdiff.ll | 2 +-
 llvm/test/CodeGen/X86/absdiff.ll     | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/llvm/test/CodeGen/AArch64/absdiff.ll b/llvm/test/CodeGen/AArch64/absdiff.ll
index 0c6677c619d6802..3d2221e509a41f3 100644
--- a/llvm/test/CodeGen/AArch64/absdiff.ll
+++ b/llvm/test/CodeGen/AArch64/absdiff.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
-; RUN: llc -mtriple=aarch64-linux-gnu -o - | FileCheck %s
+; RUN: llc -mtriple=aarch64-linux-gnu -o - < %s | FileCheck %s
 
 define i64 @absdiff(i64 %0, i64 %1) {
 ; CHECK-LABEL: absdiff:
diff --git a/llvm/test/CodeGen/PowerPC/absdiff.ll b/llvm/test/CodeGen/PowerPC/absdiff.ll
index a0959e5908241b9..2940ace3866b4d0 100644
--- a/llvm/test/CodeGen/PowerPC/absdiff.ll
+++ b/llvm/test/CodeGen/PowerPC/absdiff.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
-; RUN: llc -mtriple=powerpc64-linux-gnu -o - | FileCheck %s
+; RUN: llc -mtriple=powerpc64-linux-gnu -o - < %s | FileCheck %s
 
 define i64 @absdiff(i64 %0, i64 %1) {
 ; CHECK-LABEL: absdiff:
diff --git a/llvm/test/CodeGen/X86/absdiff.ll b/llvm/test/CodeGen/X86/absdiff.ll
index cabb3628f369c4f..0f7e66237676c06 100644
--- a/llvm/test/CodeGen/X86/absdiff.ll
+++ b/llvm/test/CodeGen/X86/absdiff.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
-; RUN: llc -mtriple=x86_64-linux-gnu -o - | FileCheck %s
+; RUN: llc -mtriple=x86_64-linux-gnu -o - < %s | FileCheck %s
 
 define i64 @absdiff(i64 %0, i64 %1) {
 ; CHECK-LABEL: absdiff:

>From d0c3f9f5a5aac4b17db992c085401551ec7e7428 Mon Sep 17 00:00:00 2001
From: Kai Luo <gluokai at gmail.com>
Date: Fri, 26 Jan 2024 14:39:42 +0800
Subject: [PATCH 6/8] Removed codegen tests

---
 llvm/test/CodeGen/AArch64/absdiff.ll | 45 ---------------------
 llvm/test/CodeGen/PowerPC/absdiff.ll | 59 ----------------------------
 llvm/test/CodeGen/X86/absdiff.ll     | 54 -------------------------
 3 files changed, 158 deletions(-)
 delete mode 100644 llvm/test/CodeGen/AArch64/absdiff.ll
 delete mode 100644 llvm/test/CodeGen/PowerPC/absdiff.ll
 delete mode 100644 llvm/test/CodeGen/X86/absdiff.ll

diff --git a/llvm/test/CodeGen/AArch64/absdiff.ll b/llvm/test/CodeGen/AArch64/absdiff.ll
deleted file mode 100644
index 3d2221e509a41f3..000000000000000
--- a/llvm/test/CodeGen/AArch64/absdiff.ll
+++ /dev/null
@@ -1,45 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
-; RUN: llc -mtriple=aarch64-linux-gnu -o - < %s | FileCheck %s
-
-define i64 @absdiff(i64 %0, i64 %1) {
-; CHECK-LABEL: absdiff:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    sub x8, x1, x0
-; CHECK-NEXT:    subs x9, x0, x1
-; CHECK-NEXT:    csel x0, x8, x9, lo
-; CHECK-NEXT:    ret
-  %3 = icmp ult i64 %0, %1
-  %4 = sub i64 %0, %1
-  %5 = sub i64 %1, %0
-  %6 = select i1 %3, i64 %5, i64 %4
-  ret i64 %6
-}
-
-define i64 @absdiff1(i64 %0, i64 %1) {
-; CHECK-LABEL: absdiff1:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    subs x8, x0, x1
-; CHECK-NEXT:    csetm x9, lo
-; CHECK-NEXT:    cinv x8, x8, lo
-; CHECK-NEXT:    sub x0, x8, x9
-; CHECK-NEXT:    ret
-  %3 = icmp ult i64 %0, %1
-  %4 = sext i1 %3 to i64
-  %5 = sub i64 %0, %1
-  %6 = xor i64 %5, %4
-  %7 = sub i64 %6, %4
-  ret i64 %7
-}
-
-define i64 @absdiff2(i64 %0, i64 %1) {
-; CHECK-LABEL: absdiff2:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    subs x8, x0, x1
-; CHECK-NEXT:    cneg x0, x8, lo
-; CHECK-NEXT:    ret
-  %3 = icmp ult i64 %0, %1
-  %4 = sub i64 %0, %1
-  %5 = sub i64 0, %4
-  %6 = select i1 %3, i64 %5, i64 %4
-  ret i64 %6
-}
diff --git a/llvm/test/CodeGen/PowerPC/absdiff.ll b/llvm/test/CodeGen/PowerPC/absdiff.ll
deleted file mode 100644
index 2940ace3866b4d0..000000000000000
--- a/llvm/test/CodeGen/PowerPC/absdiff.ll
+++ /dev/null
@@ -1,59 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
-; RUN: llc -mtriple=powerpc64-linux-gnu -o - < %s | FileCheck %s
-
-define i64 @absdiff(i64 %0, i64 %1) {
-; CHECK-LABEL: absdiff:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    sub 5, 3, 4
-; CHECK-NEXT:    sub 6, 4, 3
-; CHECK-NEXT:    cmpld 3, 4
-; CHECK-NEXT:    bc 12, 0, .LBB0_2
-; CHECK-NEXT:  # %bb.1:
-; CHECK-NEXT:    ori 3, 5, 0
-; CHECK-NEXT:    blr
-; CHECK-NEXT:  .LBB0_2:
-; CHECK-NEXT:    addi 3, 6, 0
-; CHECK-NEXT:    blr
-  %3 = icmp ult i64 %0, %1
-  %4 = sub i64 %0, %1
-  %5 = sub i64 %1, %0
-  %6 = select i1 %3, i64 %5, i64 %4
-  ret i64 %6
-}
-
-define i64 @absdiff1(i64 %0, i64 %1) {
-; CHECK-LABEL: absdiff1:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    subc 5, 3, 4
-; CHECK-NEXT:    subfe 5, 3, 3
-; CHECK-NEXT:    sub 3, 3, 4
-; CHECK-NEXT:    xor 3, 3, 5
-; CHECK-NEXT:    sub 3, 3, 5
-; CHECK-NEXT:    blr
-  %3 = icmp ult i64 %0, %1
-  %4 = sext i1 %3 to i64
-  %5 = sub i64 %0, %1
-  %6 = xor i64 %5, %4
-  %7 = sub i64 %6, %4
-  ret i64 %7
-}
-
-define i64 @absdiff2(i64 %0, i64 %1) {
-; CHECK-LABEL: absdiff2:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    sub 5, 3, 4
-; CHECK-NEXT:    neg 6, 5
-; CHECK-NEXT:    cmpld 3, 4
-; CHECK-NEXT:    bc 12, 0, .LBB2_2
-; CHECK-NEXT:  # %bb.1:
-; CHECK-NEXT:    ori 3, 5, 0
-; CHECK-NEXT:    blr
-; CHECK-NEXT:  .LBB2_2:
-; CHECK-NEXT:    addi 3, 6, 0
-; CHECK-NEXT:    blr
-  %3 = icmp ult i64 %0, %1
-  %4 = sub i64 %0, %1
-  %5 = sub i64 0, %4
-  %6 = select i1 %3, i64 %5, i64 %4
-  ret i64 %6
-}
diff --git a/llvm/test/CodeGen/X86/absdiff.ll b/llvm/test/CodeGen/X86/absdiff.ll
deleted file mode 100644
index 0f7e66237676c06..000000000000000
--- a/llvm/test/CodeGen/X86/absdiff.ll
+++ /dev/null
@@ -1,54 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
-; RUN: llc -mtriple=x86_64-linux-gnu -o - < %s | FileCheck %s
-
-define i64 @absdiff(i64 %0, i64 %1) {
-; CHECK-LABEL: absdiff:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    movq %rdi, %rax
-; CHECK-NEXT:    subq %rsi, %rax
-; CHECK-NEXT:    negq %rax
-; CHECK-NEXT:    subq %rsi, %rdi
-; CHECK-NEXT:    cmovaeq %rdi, %rax
-; CHECK-NEXT:    retq
-  %3 = icmp ult i64 %0, %1
-  %4 = sub i64 %0, %1
-  %5 = sub i64 %1, %0
-  %6 = select i1 %3, i64 %5, i64 %4
-  ret i64 %6
-}
-
-define i64 @absdiff1(i64 %0, i64 %1) {
-; CHECK-LABEL: absdiff1:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    xorl %eax, %eax
-; CHECK-NEXT:    movq %rdi, %rcx
-; CHECK-NEXT:    subq %rsi, %rcx
-; CHECK-NEXT:    setb %al
-; CHECK-NEXT:    negq %rax
-; CHECK-NEXT:    xorq %rcx, %rax
-; CHECK-NEXT:    cmpq %rsi, %rdi
-; CHECK-NEXT:    adcq $0, %rax
-; CHECK-NEXT:    retq
-  %3 = icmp ult i64 %0, %1
-  %4 = sext i1 %3 to i64
-  %5 = sub i64 %0, %1
-  %6 = xor i64 %5, %4
-  %7 = sub i64 %6, %4
-  ret i64 %7
-}
-
-define i64 @absdiff2(i64 %0, i64 %1) {
-; CHECK-LABEL: absdiff2:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    movq %rdi, %rax
-; CHECK-NEXT:    subq %rsi, %rax
-; CHECK-NEXT:    negq %rax
-; CHECK-NEXT:    subq %rsi, %rdi
-; CHECK-NEXT:    cmovaeq %rdi, %rax
-; CHECK-NEXT:    retq
-  %3 = icmp ult i64 %0, %1
-  %4 = sub i64 %0, %1
-  %5 = sub i64 0, %4
-  %6 = select i1 %3, i64 %5, i64 %4
-  ret i64 %6
-}

>From 0c71172003af88c227db2b04a577094103a1ddb0 Mon Sep 17 00:00:00 2001
From: Kai Luo <gluokai at gmail.com>
Date: Fri, 26 Jan 2024 14:46:42 +0800
Subject: [PATCH 7/8] Update
 llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp

Co-authored-by: Yingwei Zheng <dtcxzyw at qq.com>
---
 llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index 1a13fa4e2099946..31b1083737f94e1 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -2453,7 +2453,7 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
     Value *C0, *C1, *X;
     if (match(Op0, m_Xor(m_Value(X), m_SExt(m_Value(C0)))) &&
         (C0->getType()->getScalarSizeInBits() == 1) &&
-        match(Op1, m_SExt(m_Value(C1))) && (C0 == C1)) {
+        match(Op1, m_SExt(m_Specific(C0)))) {
       return SelectInst::Create(C0, Builder.CreateNeg(X), X);
     }
   }

>From 8a5f5d72ee30c7e71da0c1769ae5493ee1d3c7b0 Mon Sep 17 00:00:00 2001
From: Kai Luo <gluokai at gmail.com>
Date: Fri, 26 Jan 2024 15:48:04 +0800
Subject: [PATCH 8/8] Up

---
 .../InstCombine/InstCombineAddSub.cpp         | 17 +++++++----
 .../Transforms/InstCombine/sub-xor-cmp.ll     | 28 +++++++++++++++++++
 2 files changed, 39 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index 31b1083737f94e1..39f11c073aa6626 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -2449,13 +2449,18 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
   }
 
   {
-    // (sub (xor X, (sext C)), (sext C)) => (select C (neg X), X)
-    Value *C0, *C1, *X;
-    if (match(Op0, m_Xor(m_Value(X), m_SExt(m_Value(C0)))) &&
-        (C0->getType()->getScalarSizeInBits() == 1) &&
-        match(Op1, m_SExt(m_Specific(C0)))) {
+    // (sub (xor X, (sext C)), (sext C)) => (select C, (neg X), X)
+    // (sub (sext C), (xor X, (sext C))) => (select C, X, (neg X))
+    Value *C0, *X;
+    auto m_SubXorSext = [&C0, &X](Value *LHS, Value *RHS) {
+      return match(LHS, m_Xor(m_Value(X), m_SExt(m_OneUse(m_Value(C0))))) &&
+             (C0->getType()->getScalarSizeInBits() == 1) &&
+             match(RHS, m_SExt(m_Specific(C0)));
+    };
+    if (m_SubXorSext(Op0, Op1))
       return SelectInst::Create(C0, Builder.CreateNeg(X), X);
-    }
+    if (m_SubXorSext(Op1, Op0))
+      return SelectInst::Create(C0, X, Builder.CreateNeg(X));
   }
 
   if (Instruction *R = tryFoldInstWithCtpopWithNot(&I))
diff --git a/llvm/test/Transforms/InstCombine/sub-xor-cmp.ll b/llvm/test/Transforms/InstCombine/sub-xor-cmp.ll
index 393f2bd45bb8d77..0ed202d7cd86fb7 100644
--- a/llvm/test/Transforms/InstCombine/sub-xor-cmp.ll
+++ b/llvm/test/Transforms/InstCombine/sub-xor-cmp.ll
@@ -1,6 +1,34 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
 
+define i64 @foo(i64 %a, i1 %b) {
+; CHECK-LABEL: define i64 @foo(
+; CHECK-SAME: i64 [[A:%.*]], i1 [[B:%.*]]) {
+; CHECK-NEXT:    [[C:%.*]] = sext i1 [[B]] to i64
+; CHECK-NEXT:    [[D:%.*]] = xor i64 [[C]], [[A]]
+; CHECK-NEXT:    [[R:%.*]] = sub i64 [[D]], [[C]]
+; CHECK-NEXT:    ret i64 [[R]]
+;
+  %c = sext i1 %b to i64
+  %d = xor i64 %a, %c
+  %r = sub i64 %d, %c
+  ret i64 %r
+}
+
+define i64 @bar(i64 %a, i1 %b) {
+; CHECK-LABEL: define i64 @bar(
+; CHECK-SAME: i64 [[A:%.*]], i1 [[B:%.*]]) {
+; CHECK-NEXT:    [[C:%.*]] = sext i1 [[B]] to i64
+; CHECK-NEXT:    [[D:%.*]] = xor i64 [[C]], [[A]]
+; CHECK-NEXT:    [[R:%.*]] = sub i64 [[C]], [[D]]
+; CHECK-NEXT:    ret i64 [[R]]
+;
+  %c = sext i1 %b to i64
+  %d = xor i64 %a, %c
+  %r = sub i64 %c, %d
+  ret i64 %r
+}
+
 define  i64 @absdiff(i64 %0, i64 %1) {
 ; CHECK-LABEL: define i64 @absdiff(
 ; CHECK-SAME: i64 [[TMP0:%.*]], i64 [[TMP1:%.*]]) {



More information about the llvm-commits mailing list