[llvm] [InstCombine] Reducing rust i128::midpoint instructions (PR #99614)

Julius Alexandre via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 19 11:24:42 PDT 2024


https://github.com/medievalghoul updated https://github.com/llvm/llvm-project/pull/99614

>From 9cc66aeb0e039d4e78f626cb27c4333eceecb1fb Mon Sep 17 00:00:00 2001
From: medievalghoul <61852278+medievalghoul at users.noreply.github.com>
Date: Fri, 19 Jul 2024 03:30:01 -0400
Subject: [PATCH 1/5] [InstCombine] Reducing rust i128::midpoint instructions

---
 .../InstCombine/xor_lshr_and_i128.ll          | 142 ++++++++++++++++++
 1 file changed, 142 insertions(+)
 create mode 100644 llvm/test/Transforms/InstCombine/xor_lshr_and_i128.ll

diff --git a/llvm/test/Transforms/InstCombine/xor_lshr_and_i128.ll b/llvm/test/Transforms/InstCombine/xor_lshr_and_i128.ll
new file mode 100644
index 0000000000000..a219a945722d7
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/xor_lshr_and_i128.ll
@@ -0,0 +1,142 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+
+define noundef i128 @xor_lshr_and(i128 noundef %x, i128 noundef %y) unnamed_addr #0 {
+; check-label: define noundef i128 @xor_lshr_and(
+; check-same: i128 noundef [[x:%.*]], i128 noundef [[y:%.*]]) unnamed_addr {
+; check-next:  [[start:.*:]]
+; check-next:    [[xor:%.*]] = xor i128 [[y]], [[x]]
+; check-next:    [[lshr:%.*]] = lshr i128 [[xor]], 1
+; check-next:    [[and:%.*]] = and i128 [[y]], [[x]]
+; check-next:    [[add:%.*]] = add i128 [[lshr]], [[and]]
+; check-next:    ret i128 [[add]]
+;
+; CHECK-LABEL: define noundef i128 @xor_lshr_and(
+; CHECK-SAME: i128 noundef [[X:%.*]], i128 noundef [[Y:%.*]]) unnamed_addr {
+; CHECK-NEXT:  [[START:.*:]]
+; CHECK-NEXT:    [[XOR:%.*]] = xor i128 [[Y]], [[X]]
+; CHECK-NEXT:    [[LSHR:%.*]] = lshr i128 [[XOR]], 1
+; CHECK-NEXT:    [[AND:%.*]] = and i128 [[Y]], [[X]]
+; CHECK-NEXT:    [[ADD:%.*]] = add i128 [[LSHR]], [[AND]]
+; CHECK-NEXT:    ret i128 [[ADD]]
+;
+start:
+  %xor = xor i128 %y, %x
+  %lshr = lshr i128 %xor, 1
+  %and = and i128 %y, %x
+  %add = add i128 %lshr, %and
+  ret i128 %add
+}
+
+define noundef i128 @xor_lshr_and_commuted1(i128 noundef %x, i128 noundef %y) unnamed_addr #0 {
+; CHECK-LABEL: define noundef i128 @xor_lshr_and_commuted1(
+; CHECK-SAME: i128 noundef [[X:%.*]], i128 noundef [[Y:%.*]]) unnamed_addr {
+; CHECK-NEXT:  [[START:.*:]]
+; CHECK-NEXT:    [[AND:%.*]] = and i128 [[Y]], [[X]]
+; CHECK-NEXT:    [[XOR:%.*]] = xor i128 [[Y]], [[X]]
+; CHECK-NEXT:    [[LSHR:%.*]] = lshr i128 [[XOR]], 1
+; CHECK-NEXT:    [[ADD:%.*]] = add i128 [[LSHR]], [[AND]]
+; CHECK-NEXT:    ret i128 [[ADD]]
+;
+start:
+  %and = and i128 %y, %x
+  %xor = xor i128 %y, %x
+  %lshr = lshr i128 %xor, 1
+  %add = add i128 %lshr, %and
+  ret i128 %add
+}
+
+define noundef i128 @xor_lshr_and_commuted2(i128 noundef %x, i128 noundef %y) unnamed_addr #0 {
+; CHECK-LABEL: define noundef i128 @xor_lshr_and_commuted2(
+; CHECK-SAME: i128 noundef [[X:%.*]], i128 noundef [[Y:%.*]]) unnamed_addr {
+; CHECK-NEXT:  [[START:.*:]]
+; CHECK-NEXT:    [[AND:%.*]] = and i128 [[Y]], [[X]]
+; CHECK-NEXT:    [[XOR:%.*]] = xor i128 [[Y]], [[X]]
+; CHECK-NEXT:    [[LSHR:%.*]] = lshr i128 [[XOR]], 1
+; CHECK-NEXT:    [[ADD:%.*]] = add i128 [[LSHR]], [[AND]]
+; CHECK-NEXT:    ret i128 [[ADD]]
+;
+start:
+  %and = and i128 %y, %x
+  %xor = xor i128 %y, %x
+  %lshr = lshr i128 %xor, 1
+  %add = add i128 %lshr, %and
+  ret i128 %add
+}
+
+declare void @use(i8)
+
+define noundef i128 @xor_lshr_and_multi_use(i128 noundef %x, i128 noundef %y) unnamed_addr #0 {
+; CHECK-LABEL: define noundef i128 @xor_lshr_and_multi_use(
+; CHECK-SAME: i128 noundef [[X:%.*]], i128 noundef [[Y:%.*]]) unnamed_addr {
+; CHECK-NEXT:  [[START:.*:]]
+; CHECK-NEXT:    [[XOR:%.*]] = xor i128 [[Y]], [[X]]
+; CHECK-NEXT:    call void @use(i128 [[XOR]])
+; CHECK-NEXT:    [[LSHR:%.*]] = lshr i128 [[XOR]], 1
+; CHECK-NEXT:    call void @use(i128 [[LSHR]])
+; CHECK-NEXT:    [[AND:%.*]] = and i128 [[Y]], [[X]]
+; CHECK-NEXT:    [[ADD:%.*]] = add i128 [[LSHR]], [[AND]]
+; CHECK-NEXT:    ret i128 [[ADD]]
+;
+start:
+  %xor = xor i128 %y, %x
+  call void @use(i128 %xor)
+  %lshr = lshr i128 %xor, 1
+  call void @use(i128 %lshr)
+  %and = and i128 %y, %x
+  %add = add i128 %lshr, %and
+  ret i128 %add
+}
+
+define noundef i128 @xor_lshr_and_negative(i128 noundef %x, i128 noundef %y) unnamed_addr #0 {
+; CHECK-LABEL: define noundef i128 @xor_lshr_and_negative(
+; CHECK-SAME: i128 noundef [[X:%.*]], i128 noundef [[Y:%.*]]) unnamed_addr {
+; CHECK-NEXT:  [[START:.*:]]
+; CHECK-NEXT:    [[XOR:%.*]] = xor i128 [[X]], -1
+; CHECK-NEXT:    [[AND:%.*]] = and i128 [[Y]], [[X]]
+; CHECK-NEXT:    [[ADD:%.*]] = add i128 [[AND]], [[XOR]]
+; CHECK-NEXT:    ret i128 [[ADD]]
+;
+start:
+  %xor = xor i128 %x, -1
+  %and = and i128 %y, %x
+  %add = add i128 %xor, %and
+  ret i128 %add
+}
+
+define noundef i32 @xor_lshr_and_negative2(i32 noundef %x, i32 noundef %y) unnamed_addr #0 {
+; CHECK-LABEL: define noundef i32 @xor_lshr_and_negative2(
+; CHECK-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) unnamed_addr {
+; CHECK-NEXT:  [[START:.*:]]
+; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[Y]], [[X]]
+; CHECK-NEXT:    [[LSHR:%.*]] = lshr i32 [[XOR]], 1
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[Y]], [[X]]
+; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[LSHR]], [[AND]]
+; CHECK-NEXT:    ret i32 [[ADD]]
+;
+start:
+  %xor = xor i32 %y, %x
+  %lshr = lshr i32 %xor, 1
+  %and = and i32 %y, %x
+  %add = add i32 %lshr, %and
+  ret i32 %add
+}
+
+define noundef <2 x i128> @xor_lshr_and_vec(<2 x i128> noundef %x, <2 x i128> noundef %y) unnamed_addr #0 {
+; CHECK-LABEL: define noundef <2 x i128> @xor_lshr_and_vec(
+; CHECK-SAME: <2 x i128> noundef [[X:%.*]], <2 x i128> noundef [[Y:%.*]]) unnamed_addr {
+; CHECK-NEXT:  [[START:.*:]]
+; CHECK-NEXT:    [[XOR:%.*]] = xor <2 x i128> [[Y]], [[X]]
+; CHECK-NEXT:    [[LSHR:%.*]] = lshr <2 x i128> [[XOR]], <i128 1, i128 1>
+; CHECK-NEXT:    [[AND:%.*]] = and <2 x i128> [[Y]], [[X]]
+; CHECK-NEXT:    [[ADD:%.*]] = add <2 x i128> [[LSHR]], [[AND]]
+; CHECK-NEXT:    ret <2 x i128> [[ADD]]
+;
+start:
+  %xor = xor <2 x i128> %y, %x
+  %lshr = lshr <2 x i128> %xor, <i128 1, i128 1>
+  %and = and <2 x i128> %y, %x
+  %add = add <2 x i128> %lshr, %and
+  ret <2 x i128> %add
+}
+

>From 87a34e6a2b143b822177422c1853a885371b60fa Mon Sep 17 00:00:00 2001
From: medievalghoul <61852278+medievalghoul at users.noreply.github.com>
Date: Fri, 19 Jul 2024 04:51:50 -0400
Subject: [PATCH 2/5] added the transformations

---
 .../InstCombine/InstCombineAddSub.cpp         | 44 +++++++++++++++++++
 .../InstCombine/xor_lshr_and_i128.ll          | 32 +++++++++-----
 2 files changed, 65 insertions(+), 11 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index 0a55f4762fdf0..b857150fec2a3 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -1483,6 +1483,47 @@ static Instruction *foldBoxMultiply(BinaryOperator &I) {
   return nullptr;
 }
 
+// Relating to the i128::midpoint in rust nightly 
+// we're finding this expression: ((Y ^ X) >> 1 + (Y & X))
+// with the i128 data type and reducing the amount of asm instructions
+// generated.
+static Instruction *foldMidpointExpression(BinaryOperator &I) {
+  Value *X, *Y;
+
+  if (!I.getType()->isIntegerTy(128))
+    return nullptr;
+
+  if (!match(&I, m_Add(m_LShr(m_Xor(m_Value(X), m_Value(Y)), m_ConstantInt()),
+                      m_And(m_Value(X), m_Value(Y)))))
+    return nullptr;
+
+  IRBuilder<> Builder(&I); 
+  Module *Mod = I.getModule();
+
+  // Create the call llvm.uadd.with.overflow.i128
+  Function *UAddWithOverflow = Intrinsic::getDeclaration(Mod, Intrinsic::uadd_with_overflow, 
+      Type::getInt128Ty(Mod->getContext()));
+  CallInst *UAddCall = Builder.CreateCall(UAddWithOverflow, {Y, X});
+  UAddCall->setTailCall();  // Mark the call as a tail call
+  
+  // Extract the sum and the 
+  Value *Sum = Builder.CreateExtractValue(UAddCall, 0);
+  Value *Overflow = Builder.CreateExtractValue(UAddCall, 1);
+
+  // Create the right shift for the sum element of
+  // overflow
+  Value *LShrVal = Builder.CreateLShr(Sum, ConstantInt::get(Type::getInt128Ty(I.getContext()), 1));
+
+  // Create the select instruction
+  Value *SelectVal = Builder.CreateSelect(Overflow,
+      ConstantInt::get(Type::getInt128Ty(I.getContext()), APInt(128, 1).shl(127)), 
+      ConstantInt::get(Type::getInt128Ty(I.getContext()), 0));
+
+  Instruction *OrVal = BinaryOperator::CreateOr(LShrVal, SelectVal);
+
+  return OrVal;
+}
+
 Instruction *InstCombinerImpl::visitAdd(BinaryOperator &I) {
   if (Value *V = simplifyAddInst(I.getOperand(0), I.getOperand(1),
                                  I.hasNoSignedWrap(), I.hasNoUnsignedWrap(),
@@ -1505,6 +1546,9 @@ Instruction *InstCombinerImpl::visitAdd(BinaryOperator &I) {
   if (Instruction *R = foldBoxMultiply(I))
     return R;
 
+  if (Instruction *R = foldMidpointExpression(I))
+    return R;
+  
   if (Instruction *R = factorizeMathWithShlOps(I, Builder))
     return R;
 
diff --git a/llvm/test/Transforms/InstCombine/xor_lshr_and_i128.ll b/llvm/test/Transforms/InstCombine/xor_lshr_and_i128.ll
index a219a945722d7..7f3da1ddad427 100644
--- a/llvm/test/Transforms/InstCombine/xor_lshr_and_i128.ll
+++ b/llvm/test/Transforms/InstCombine/xor_lshr_and_i128.ll
@@ -14,10 +14,12 @@ define noundef i128 @xor_lshr_and(i128 noundef %x, i128 noundef %y) unnamed_addr
 ; CHECK-LABEL: define noundef i128 @xor_lshr_and(
 ; CHECK-SAME: i128 noundef [[X:%.*]], i128 noundef [[Y:%.*]]) unnamed_addr {
 ; CHECK-NEXT:  [[START:.*:]]
-; CHECK-NEXT:    [[XOR:%.*]] = xor i128 [[Y]], [[X]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call { i128, i1 } @llvm.uadd.with.overflow.i128(i128 [[X]], i128 [[Y]])
+; CHECK-NEXT:    [[XOR:%.*]] = extractvalue { i128, i1 } [[TMP0]], 0
+; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { i128, i1 } [[TMP0]], 1
 ; CHECK-NEXT:    [[LSHR:%.*]] = lshr i128 [[XOR]], 1
-; CHECK-NEXT:    [[AND:%.*]] = and i128 [[Y]], [[X]]
-; CHECK-NEXT:    [[ADD:%.*]] = add i128 [[LSHR]], [[AND]]
+; CHECK-NEXT:    [[TMP4:%.*]] = select i1 [[TMP2]], i128 -170141183460469231731687303715884105728, i128 0
+; CHECK-NEXT:    [[ADD:%.*]] = or disjoint i128 [[LSHR]], [[TMP4]]
 ; CHECK-NEXT:    ret i128 [[ADD]]
 ;
 start:
@@ -32,10 +34,12 @@ define noundef i128 @xor_lshr_and_commuted1(i128 noundef %x, i128 noundef %y) un
 ; CHECK-LABEL: define noundef i128 @xor_lshr_and_commuted1(
 ; CHECK-SAME: i128 noundef [[X:%.*]], i128 noundef [[Y:%.*]]) unnamed_addr {
 ; CHECK-NEXT:  [[START:.*:]]
-; CHECK-NEXT:    [[AND:%.*]] = and i128 [[Y]], [[X]]
-; CHECK-NEXT:    [[XOR:%.*]] = xor i128 [[Y]], [[X]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call { i128, i1 } @llvm.uadd.with.overflow.i128(i128 [[X]], i128 [[Y]])
+; CHECK-NEXT:    [[XOR:%.*]] = extractvalue { i128, i1 } [[TMP0]], 0
+; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { i128, i1 } [[TMP0]], 1
 ; CHECK-NEXT:    [[LSHR:%.*]] = lshr i128 [[XOR]], 1
-; CHECK-NEXT:    [[ADD:%.*]] = add i128 [[LSHR]], [[AND]]
+; CHECK-NEXT:    [[TMP4:%.*]] = select i1 [[TMP2]], i128 -170141183460469231731687303715884105728, i128 0
+; CHECK-NEXT:    [[ADD:%.*]] = or disjoint i128 [[LSHR]], [[TMP4]]
 ; CHECK-NEXT:    ret i128 [[ADD]]
 ;
 start:
@@ -50,10 +54,12 @@ define noundef i128 @xor_lshr_and_commuted2(i128 noundef %x, i128 noundef %y) un
 ; CHECK-LABEL: define noundef i128 @xor_lshr_and_commuted2(
 ; CHECK-SAME: i128 noundef [[X:%.*]], i128 noundef [[Y:%.*]]) unnamed_addr {
 ; CHECK-NEXT:  [[START:.*:]]
-; CHECK-NEXT:    [[AND:%.*]] = and i128 [[Y]], [[X]]
-; CHECK-NEXT:    [[XOR:%.*]] = xor i128 [[Y]], [[X]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call { i128, i1 } @llvm.uadd.with.overflow.i128(i128 [[X]], i128 [[Y]])
+; CHECK-NEXT:    [[XOR:%.*]] = extractvalue { i128, i1 } [[TMP0]], 0
+; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { i128, i1 } [[TMP0]], 1
 ; CHECK-NEXT:    [[LSHR:%.*]] = lshr i128 [[XOR]], 1
-; CHECK-NEXT:    [[ADD:%.*]] = add i128 [[LSHR]], [[AND]]
+; CHECK-NEXT:    [[TMP4:%.*]] = select i1 [[TMP2]], i128 -170141183460469231731687303715884105728, i128 0
+; CHECK-NEXT:    [[ADD:%.*]] = or disjoint i128 [[LSHR]], [[TMP4]]
 ; CHECK-NEXT:    ret i128 [[ADD]]
 ;
 start:
@@ -74,8 +80,12 @@ define noundef i128 @xor_lshr_and_multi_use(i128 noundef %x, i128 noundef %y) un
 ; CHECK-NEXT:    call void @use(i128 [[XOR]])
 ; CHECK-NEXT:    [[LSHR:%.*]] = lshr i128 [[XOR]], 1
 ; CHECK-NEXT:    call void @use(i128 [[LSHR]])
-; CHECK-NEXT:    [[AND:%.*]] = and i128 [[Y]], [[X]]
-; CHECK-NEXT:    [[ADD:%.*]] = add i128 [[LSHR]], [[AND]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call { i128, i1 } @llvm.uadd.with.overflow.i128(i128 [[X]], i128 [[Y]])
+; CHECK-NEXT:    [[TMP1:%.*]] = extractvalue { i128, i1 } [[TMP0]], 0
+; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { i128, i1 } [[TMP0]], 1
+; CHECK-NEXT:    [[TMP3:%.*]] = lshr i128 [[TMP1]], 1
+; CHECK-NEXT:    [[TMP4:%.*]] = select i1 [[TMP2]], i128 -170141183460469231731687303715884105728, i128 0
+; CHECK-NEXT:    [[ADD:%.*]] = or disjoint i128 [[TMP3]], [[TMP4]]
 ; CHECK-NEXT:    ret i128 [[ADD]]
 ;
 start:

>From 73ce201390bf8336d761439965806b8b3899a144 Mon Sep 17 00:00:00 2001
From: medievalghoul <61852278+medievalghoul at users.noreply.github.com>
Date: Fri, 19 Jul 2024 14:11:51 -0400
Subject: [PATCH 3/5] Removed junk: Reupload of the test without transformation

---
 .../InstCombine/xor_lshr_and_i128.ll          | 83 +++++++------------
 1 file changed, 32 insertions(+), 51 deletions(-)

diff --git a/llvm/test/Transforms/InstCombine/xor_lshr_and_i128.ll b/llvm/test/Transforms/InstCombine/xor_lshr_and_i128.ll
index 7f3da1ddad427..656c1095179ad 100644
--- a/llvm/test/Transforms/InstCombine/xor_lshr_and_i128.ll
+++ b/llvm/test/Transforms/InstCombine/xor_lshr_and_i128.ll
@@ -1,25 +1,14 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
 
-define noundef i128 @xor_lshr_and(i128 noundef %x, i128 noundef %y) unnamed_addr #0 {
-; check-label: define noundef i128 @xor_lshr_and(
-; check-same: i128 noundef [[x:%.*]], i128 noundef [[y:%.*]]) unnamed_addr {
-; check-next:  [[start:.*:]]
-; check-next:    [[xor:%.*]] = xor i128 [[y]], [[x]]
-; check-next:    [[lshr:%.*]] = lshr i128 [[xor]], 1
-; check-next:    [[and:%.*]] = and i128 [[y]], [[x]]
-; check-next:    [[add:%.*]] = add i128 [[lshr]], [[and]]
-; check-next:    ret i128 [[add]]
-;
-; CHECK-LABEL: define noundef i128 @xor_lshr_and(
-; CHECK-SAME: i128 noundef [[X:%.*]], i128 noundef [[Y:%.*]]) unnamed_addr {
+define i128 @xor_lshr_and(i128 %x, i128 %y) {
+; CHECK-LABEL: define i128 @xor_lshr_and(
+; CHECK-SAME: i128 [[X:%.*]], i128 [[Y:%.*]]) {
 ; CHECK-NEXT:  [[START:.*:]]
-; CHECK-NEXT:    [[TMP0:%.*]] = tail call { i128, i1 } @llvm.uadd.with.overflow.i128(i128 [[X]], i128 [[Y]])
-; CHECK-NEXT:    [[XOR:%.*]] = extractvalue { i128, i1 } [[TMP0]], 0
-; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { i128, i1 } [[TMP0]], 1
+; CHECK-NEXT:    [[XOR:%.*]] = xor i128 [[Y]], [[X]]
 ; CHECK-NEXT:    [[LSHR:%.*]] = lshr i128 [[XOR]], 1
-; CHECK-NEXT:    [[TMP4:%.*]] = select i1 [[TMP2]], i128 -170141183460469231731687303715884105728, i128 0
-; CHECK-NEXT:    [[ADD:%.*]] = or disjoint i128 [[LSHR]], [[TMP4]]
+; CHECK-NEXT:    [[AND:%.*]] = and i128 [[Y]], [[X]]
+; CHECK-NEXT:    [[ADD:%.*]] = add i128 [[LSHR]], [[AND]]
 ; CHECK-NEXT:    ret i128 [[ADD]]
 ;
 start:
@@ -30,16 +19,14 @@ start:
   ret i128 %add
 }
 
-define noundef i128 @xor_lshr_and_commuted1(i128 noundef %x, i128 noundef %y) unnamed_addr #0 {
-; CHECK-LABEL: define noundef i128 @xor_lshr_and_commuted1(
-; CHECK-SAME: i128 noundef [[X:%.*]], i128 noundef [[Y:%.*]]) unnamed_addr {
+define i128 @xor_lshr_and_commuted1(i128 %x, i128 %y) {
+; CHECK-LABEL: define i128 @xor_lshr_and_commuted1(
+; CHECK-SAME: i128 [[X:%.*]], i128 [[Y:%.*]]) {
 ; CHECK-NEXT:  [[START:.*:]]
-; CHECK-NEXT:    [[TMP0:%.*]] = tail call { i128, i1 } @llvm.uadd.with.overflow.i128(i128 [[X]], i128 [[Y]])
-; CHECK-NEXT:    [[XOR:%.*]] = extractvalue { i128, i1 } [[TMP0]], 0
-; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { i128, i1 } [[TMP0]], 1
+; CHECK-NEXT:    [[AND:%.*]] = and i128 [[Y]], [[X]]
+; CHECK-NEXT:    [[XOR:%.*]] = xor i128 [[Y]], [[X]]
 ; CHECK-NEXT:    [[LSHR:%.*]] = lshr i128 [[XOR]], 1
-; CHECK-NEXT:    [[TMP4:%.*]] = select i1 [[TMP2]], i128 -170141183460469231731687303715884105728, i128 0
-; CHECK-NEXT:    [[ADD:%.*]] = or disjoint i128 [[LSHR]], [[TMP4]]
+; CHECK-NEXT:    [[ADD:%.*]] = add i128 [[LSHR]], [[AND]]
 ; CHECK-NEXT:    ret i128 [[ADD]]
 ;
 start:
@@ -50,16 +37,14 @@ start:
   ret i128 %add
 }
 
-define noundef i128 @xor_lshr_and_commuted2(i128 noundef %x, i128 noundef %y) unnamed_addr #0 {
-; CHECK-LABEL: define noundef i128 @xor_lshr_and_commuted2(
-; CHECK-SAME: i128 noundef [[X:%.*]], i128 noundef [[Y:%.*]]) unnamed_addr {
+define i128 @xor_lshr_and_commuted2(i128 %x, i128 %y) {
+; CHECK-LABEL: define i128 @xor_lshr_and_commuted2(
+; CHECK-SAME: i128 [[X:%.*]], i128 [[Y:%.*]]) {
 ; CHECK-NEXT:  [[START:.*:]]
-; CHECK-NEXT:    [[TMP0:%.*]] = tail call { i128, i1 } @llvm.uadd.with.overflow.i128(i128 [[X]], i128 [[Y]])
-; CHECK-NEXT:    [[XOR:%.*]] = extractvalue { i128, i1 } [[TMP0]], 0
-; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { i128, i1 } [[TMP0]], 1
+; CHECK-NEXT:    [[AND:%.*]] = and i128 [[Y]], [[X]]
+; CHECK-NEXT:    [[XOR:%.*]] = xor i128 [[Y]], [[X]]
 ; CHECK-NEXT:    [[LSHR:%.*]] = lshr i128 [[XOR]], 1
-; CHECK-NEXT:    [[TMP4:%.*]] = select i1 [[TMP2]], i128 -170141183460469231731687303715884105728, i128 0
-; CHECK-NEXT:    [[ADD:%.*]] = or disjoint i128 [[LSHR]], [[TMP4]]
+; CHECK-NEXT:    [[ADD:%.*]] = add i128 [[LSHR]], [[AND]]
 ; CHECK-NEXT:    ret i128 [[ADD]]
 ;
 start:
@@ -72,20 +57,16 @@ start:
 
 declare void @use(i8)
 
-define noundef i128 @xor_lshr_and_multi_use(i128 noundef %x, i128 noundef %y) unnamed_addr #0 {
-; CHECK-LABEL: define noundef i128 @xor_lshr_and_multi_use(
-; CHECK-SAME: i128 noundef [[X:%.*]], i128 noundef [[Y:%.*]]) unnamed_addr {
+define i128 @xor_lshr_and_multi_use(i128 %x, i128 %y) {
+; CHECK-LABEL: define i128 @xor_lshr_and_multi_use(
+; CHECK-SAME: i128 [[X:%.*]], i128 [[Y:%.*]]) {
 ; CHECK-NEXT:  [[START:.*:]]
 ; CHECK-NEXT:    [[XOR:%.*]] = xor i128 [[Y]], [[X]]
 ; CHECK-NEXT:    call void @use(i128 [[XOR]])
 ; CHECK-NEXT:    [[LSHR:%.*]] = lshr i128 [[XOR]], 1
 ; CHECK-NEXT:    call void @use(i128 [[LSHR]])
-; CHECK-NEXT:    [[TMP0:%.*]] = tail call { i128, i1 } @llvm.uadd.with.overflow.i128(i128 [[X]], i128 [[Y]])
-; CHECK-NEXT:    [[TMP1:%.*]] = extractvalue { i128, i1 } [[TMP0]], 0
-; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { i128, i1 } [[TMP0]], 1
-; CHECK-NEXT:    [[TMP3:%.*]] = lshr i128 [[TMP1]], 1
-; CHECK-NEXT:    [[TMP4:%.*]] = select i1 [[TMP2]], i128 -170141183460469231731687303715884105728, i128 0
-; CHECK-NEXT:    [[ADD:%.*]] = or disjoint i128 [[TMP3]], [[TMP4]]
+; CHECK-NEXT:    [[AND:%.*]] = and i128 [[Y]], [[X]]
+; CHECK-NEXT:    [[ADD:%.*]] = add i128 [[LSHR]], [[AND]]
 ; CHECK-NEXT:    ret i128 [[ADD]]
 ;
 start:
@@ -98,9 +79,9 @@ start:
   ret i128 %add
 }
 
-define noundef i128 @xor_lshr_and_negative(i128 noundef %x, i128 noundef %y) unnamed_addr #0 {
-; CHECK-LABEL: define noundef i128 @xor_lshr_and_negative(
-; CHECK-SAME: i128 noundef [[X:%.*]], i128 noundef [[Y:%.*]]) unnamed_addr {
+define i128 @xor_lshr_and_negative(i128 %x, i128 %y) {
+; CHECK-LABEL: define i128 @xor_lshr_and_negative(
+; CHECK-SAME: i128 [[X:%.*]], i128 [[Y:%.*]]) {
 ; CHECK-NEXT:  [[START:.*:]]
 ; CHECK-NEXT:    [[XOR:%.*]] = xor i128 [[X]], -1
 ; CHECK-NEXT:    [[AND:%.*]] = and i128 [[Y]], [[X]]
@@ -114,9 +95,9 @@ start:
   ret i128 %add
 }
 
-define noundef i32 @xor_lshr_and_negative2(i32 noundef %x, i32 noundef %y) unnamed_addr #0 {
-; CHECK-LABEL: define noundef i32 @xor_lshr_and_negative2(
-; CHECK-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) unnamed_addr {
+define i32 @xor_lshr_and_negative2(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @xor_lshr_and_negative2(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
 ; CHECK-NEXT:  [[START:.*:]]
 ; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[Y]], [[X]]
 ; CHECK-NEXT:    [[LSHR:%.*]] = lshr i32 [[XOR]], 1
@@ -132,9 +113,9 @@ start:
   ret i32 %add
 }
 
-define noundef <2 x i128> @xor_lshr_and_vec(<2 x i128> noundef %x, <2 x i128> noundef %y) unnamed_addr #0 {
-; CHECK-LABEL: define noundef <2 x i128> @xor_lshr_and_vec(
-; CHECK-SAME: <2 x i128> noundef [[X:%.*]], <2 x i128> noundef [[Y:%.*]]) unnamed_addr {
+define <2 x i128> @xor_lshr_and_vec(<2 x i128> %x, <2 x i128> %y) {
+; CHECK-LABEL: define <2 x i128> @xor_lshr_and_vec(
+; CHECK-SAME: <2 x i128> [[X:%.*]], <2 x i128> [[Y:%.*]]) {
 ; CHECK-NEXT:  [[START:.*:]]
 ; CHECK-NEXT:    [[XOR:%.*]] = xor <2 x i128> [[Y]], [[X]]
 ; CHECK-NEXT:    [[LSHR:%.*]] = lshr <2 x i128> [[XOR]], <i128 1, i128 1>

>From b2611e5dac2e41e498fe2f1838c5c3864959bb19 Mon Sep 17 00:00:00 2001
From: medievalghoul <61852278+medievalghoul at users.noreply.github.com>
Date: Fri, 19 Jul 2024 14:21:56 -0400
Subject: [PATCH 4/5] changed pattern matching

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

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index b857150fec2a3..3020e81e917bb 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -1494,7 +1494,7 @@ static Instruction *foldMidpointExpression(BinaryOperator &I) {
     return nullptr;
 
   if (!match(&I, m_Add(m_LShr(m_Xor(m_Value(X), m_Value(Y)), m_ConstantInt()),
-                      m_And(m_Value(X), m_Value(Y)))))
+                      m_c_And(m_Deferred(X), m_Deferred(Y)))))
     return nullptr;
 
   IRBuilder<> Builder(&I); 
@@ -1548,7 +1548,7 @@ Instruction *InstCombinerImpl::visitAdd(BinaryOperator &I) {
 
   if (Instruction *R = foldMidpointExpression(I))
     return R;
-  
+
   if (Instruction *R = factorizeMathWithShlOps(I, Builder))
     return R;
 

>From be6de10dbb4a9809d0e008de7dccd0cd4beb4614 Mon Sep 17 00:00:00 2001
From: medievalghoul <61852278+medievalghoul at users.noreply.github.com>
Date: Fri, 19 Jul 2024 14:24:07 -0400
Subject: [PATCH 5/5] Removed junk: Reupload of the test with transformation

---
 .../InstCombine/xor_lshr_and_i128.ll          | 32 ++++++++++++-------
 1 file changed, 21 insertions(+), 11 deletions(-)

diff --git a/llvm/test/Transforms/InstCombine/xor_lshr_and_i128.ll b/llvm/test/Transforms/InstCombine/xor_lshr_and_i128.ll
index 656c1095179ad..fb0243082d142 100644
--- a/llvm/test/Transforms/InstCombine/xor_lshr_and_i128.ll
+++ b/llvm/test/Transforms/InstCombine/xor_lshr_and_i128.ll
@@ -5,10 +5,12 @@ define i128 @xor_lshr_and(i128 %x, i128 %y) {
 ; CHECK-LABEL: define i128 @xor_lshr_and(
 ; CHECK-SAME: i128 [[X:%.*]], i128 [[Y:%.*]]) {
 ; CHECK-NEXT:  [[START:.*:]]
-; CHECK-NEXT:    [[XOR:%.*]] = xor i128 [[Y]], [[X]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call { i128, i1 } @llvm.uadd.with.overflow.i128(i128 [[X]], i128 [[Y]])
+; CHECK-NEXT:    [[XOR:%.*]] = extractvalue { i128, i1 } [[TMP0]], 0
+; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { i128, i1 } [[TMP0]], 1
 ; CHECK-NEXT:    [[LSHR:%.*]] = lshr i128 [[XOR]], 1
-; CHECK-NEXT:    [[AND:%.*]] = and i128 [[Y]], [[X]]
-; CHECK-NEXT:    [[ADD:%.*]] = add i128 [[LSHR]], [[AND]]
+; CHECK-NEXT:    [[TMP4:%.*]] = select i1 [[TMP2]], i128 -170141183460469231731687303715884105728, i128 0
+; CHECK-NEXT:    [[ADD:%.*]] = or disjoint i128 [[LSHR]], [[TMP4]]
 ; CHECK-NEXT:    ret i128 [[ADD]]
 ;
 start:
@@ -23,10 +25,12 @@ define i128 @xor_lshr_and_commuted1(i128 %x, i128 %y) {
 ; CHECK-LABEL: define i128 @xor_lshr_and_commuted1(
 ; CHECK-SAME: i128 [[X:%.*]], i128 [[Y:%.*]]) {
 ; CHECK-NEXT:  [[START:.*:]]
-; CHECK-NEXT:    [[AND:%.*]] = and i128 [[Y]], [[X]]
-; CHECK-NEXT:    [[XOR:%.*]] = xor i128 [[Y]], [[X]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call { i128, i1 } @llvm.uadd.with.overflow.i128(i128 [[X]], i128 [[Y]])
+; CHECK-NEXT:    [[XOR:%.*]] = extractvalue { i128, i1 } [[TMP0]], 0
+; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { i128, i1 } [[TMP0]], 1
 ; CHECK-NEXT:    [[LSHR:%.*]] = lshr i128 [[XOR]], 1
-; CHECK-NEXT:    [[ADD:%.*]] = add i128 [[LSHR]], [[AND]]
+; CHECK-NEXT:    [[TMP4:%.*]] = select i1 [[TMP2]], i128 -170141183460469231731687303715884105728, i128 0
+; CHECK-NEXT:    [[ADD:%.*]] = or disjoint i128 [[LSHR]], [[TMP4]]
 ; CHECK-NEXT:    ret i128 [[ADD]]
 ;
 start:
@@ -41,10 +45,12 @@ define i128 @xor_lshr_and_commuted2(i128 %x, i128 %y) {
 ; CHECK-LABEL: define i128 @xor_lshr_and_commuted2(
 ; CHECK-SAME: i128 [[X:%.*]], i128 [[Y:%.*]]) {
 ; CHECK-NEXT:  [[START:.*:]]
-; CHECK-NEXT:    [[AND:%.*]] = and i128 [[Y]], [[X]]
-; CHECK-NEXT:    [[XOR:%.*]] = xor i128 [[Y]], [[X]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call { i128, i1 } @llvm.uadd.with.overflow.i128(i128 [[X]], i128 [[Y]])
+; CHECK-NEXT:    [[XOR:%.*]] = extractvalue { i128, i1 } [[TMP0]], 0
+; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { i128, i1 } [[TMP0]], 1
 ; CHECK-NEXT:    [[LSHR:%.*]] = lshr i128 [[XOR]], 1
-; CHECK-NEXT:    [[ADD:%.*]] = add i128 [[LSHR]], [[AND]]
+; CHECK-NEXT:    [[TMP4:%.*]] = select i1 [[TMP2]], i128 -170141183460469231731687303715884105728, i128 0
+; CHECK-NEXT:    [[ADD:%.*]] = or disjoint i128 [[LSHR]], [[TMP4]]
 ; CHECK-NEXT:    ret i128 [[ADD]]
 ;
 start:
@@ -65,8 +71,12 @@ define i128 @xor_lshr_and_multi_use(i128 %x, i128 %y) {
 ; CHECK-NEXT:    call void @use(i128 [[XOR]])
 ; CHECK-NEXT:    [[LSHR:%.*]] = lshr i128 [[XOR]], 1
 ; CHECK-NEXT:    call void @use(i128 [[LSHR]])
-; CHECK-NEXT:    [[AND:%.*]] = and i128 [[Y]], [[X]]
-; CHECK-NEXT:    [[ADD:%.*]] = add i128 [[LSHR]], [[AND]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call { i128, i1 } @llvm.uadd.with.overflow.i128(i128 [[X]], i128 [[Y]])
+; CHECK-NEXT:    [[TMP1:%.*]] = extractvalue { i128, i1 } [[TMP0]], 0
+; CHECK-NEXT:    [[TMP2:%.*]] = extractvalue { i128, i1 } [[TMP0]], 1
+; CHECK-NEXT:    [[TMP3:%.*]] = lshr i128 [[TMP1]], 1
+; CHECK-NEXT:    [[TMP4:%.*]] = select i1 [[TMP2]], i128 -170141183460469231731687303715884105728, i128 0
+; CHECK-NEXT:    [[ADD:%.*]] = or disjoint i128 [[TMP3]], [[TMP4]]
 ; CHECK-NEXT:    ret i128 [[ADD]]
 ;
 start:



More information about the llvm-commits mailing list