[llvm] [InstCombine] Preserve disjoint or after folding casted bitwise logic (PR #136815)

Jim Lin via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 25 00:10:09 PDT 2025


https://github.com/tclin914 updated https://github.com/llvm/llvm-project/pull/136815

>From 803e4e050585d5582b9ddb201d99773b48f8bd4c Mon Sep 17 00:00:00 2001
From: Jim Lin <jim at andestech.com>
Date: Wed, 23 Apr 2025 10:24:08 +0800
Subject: [PATCH 1/2] [RISCV] Pre-commit test

---
 .../test/Transforms/InstCombine/and-xor-or.ll | 54 +++++++++++++++++++
 1 file changed, 54 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/and-xor-or.ll b/llvm/test/Transforms/InstCombine/and-xor-or.ll
index 74d1f2119a2ad..e540878dc39d6 100644
--- a/llvm/test/Transforms/InstCombine/and-xor-or.ll
+++ b/llvm/test/Transforms/InstCombine/and-xor-or.ll
@@ -4334,6 +4334,33 @@ define i16 @or_zext_zext_2_use1(i8 %x, i8 %y) {
   ret i16 %r
 }
 
+define i16 @or_disjoint_zext_zext(i8 %x, i4 %y) {
+; CHECK-LABEL: define {{[^@]+}}@or_disjoint_zext_zext
+; CHECK-SAME: (i8 [[X:%.*]], i4 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i4 [[Y]] to i8
+; CHECK-NEXT:    [[R1:%.*]] = or i8 [[X]], [[TMP1]]
+; CHECK-NEXT:    [[R:%.*]] = zext i8 [[R1]] to i16
+; CHECK-NEXT:    ret i16 [[R]]
+;
+  %zx = zext i8 %x to i16
+  %zy = zext i4 %y to i16
+  %r = or disjoint i16 %zy, %zx
+  ret i16 %r
+}
+
+define i16 @or_disjoint_zext_zext_2(i8 %x, i8 %y) {
+; CHECK-LABEL: define {{[^@]+}}@or_disjoint_zext_zext_2
+; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
+; CHECK-NEXT:    [[R1:%.*]] = or i8 [[Y]], [[X]]
+; CHECK-NEXT:    [[R:%.*]] = zext i8 [[R1]] to i16
+; CHECK-NEXT:    ret i16 [[R]]
+;
+  %zx = zext i8 %x to i16
+  %zy = zext i8 %y to i16
+  %r = or disjoint i16 %zy, %zx
+  ret i16 %r
+}
+
 define <2 x i16> @xor_zext_zext(<2 x i8> %x, <2 x i4> %y) {
 ; CHECK-LABEL: define {{[^@]+}}@xor_zext_zext
 ; CHECK-SAME: (<2 x i8> [[X:%.*]], <2 x i4> [[Y:%.*]]) {
@@ -4463,6 +4490,33 @@ define i16 @or_sext_sext_2_use1(i8 %x, i8 %y) {
   ret i16 %r
 }
 
+define i16 @or_disjoint_sext_sext(i8 %x, i4 %y) {
+; CHECK-LABEL: define {{[^@]+}}@or_disjoint_sext_sext
+; CHECK-SAME: (i8 [[X:%.*]], i4 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP1:%.*]] = sext i4 [[Y]] to i8
+; CHECK-NEXT:    [[R1:%.*]] = or i8 [[X]], [[TMP1]]
+; CHECK-NEXT:    [[R:%.*]] = sext i8 [[R1]] to i16
+; CHECK-NEXT:    ret i16 [[R]]
+;
+  %sx = sext i8 %x to i16
+  %sy = sext i4 %y to i16
+  %r = or disjoint i16 %sx, %sy
+  ret i16 %r
+}
+
+define i16 @or_disjoint_sext_sext_2(i8 %x, i8 %y) {
+; CHECK-LABEL: define {{[^@]+}}@or_disjoint_sext_sext_2
+; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
+; CHECK-NEXT:    [[R1:%.*]] = or i8 [[X]], [[Y]]
+; CHECK-NEXT:    [[R:%.*]] = sext i8 [[R1]] to i16
+; CHECK-NEXT:    ret i16 [[R]]
+;
+  %sx = sext i8 %x to i16
+  %sy = sext i8 %y to i16
+  %r = or disjoint i16 %sx, %sy
+  ret i16 %r
+}
+
 define i16 @xor_sext_sext(i8 %x, i4 %y) {
 ; CHECK-LABEL: define {{[^@]+}}@xor_sext_sext
 ; CHECK-SAME: (i8 [[X:%.*]], i4 [[Y:%.*]]) {

>From c283dabe3463097fe48ccba7e211aceb5e09d854 Mon Sep 17 00:00:00 2001
From: Jim Lin <jim at andestech.com>
Date: Wed, 23 Apr 2025 11:32:35 +0800
Subject: [PATCH 2/2] [InstCombine] Keep or disjoint after folding casted
 bitwise logic

Optimize
`or disjoint (zext/sext a) (zext/sext b))`
to
`(zext/sext (or disjoint a, b))`
without losing disjoint.

Confirmed by: https://alive2.llvm.org/ce/z/kQ5fJv.
---
 llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp | 3 +++
 llvm/test/Transforms/InstCombine/and-xor-or.ll          | 8 ++++----
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 9aede25649c7c..56bde15cabbed 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -1869,6 +1869,9 @@ Instruction *InstCombinerImpl::foldCastedBitwiseLogic(BinaryOperator &I) {
 
     // Do the logic op in the intermediate width, then widen more.
     Value *NarrowLogic = Builder.CreateBinOp(LogicOpc, X, Y, I.getName());
+    if (auto *Disjoint = dyn_cast<PossiblyDisjointInst>(&I);
+        Disjoint && Disjoint->isDisjoint())
+      cast<PossiblyDisjointInst>(NarrowLogic)->setIsDisjoint(true);
     return CastInst::Create(CastOpcode, NarrowLogic, DestTy);
   }
 
diff --git a/llvm/test/Transforms/InstCombine/and-xor-or.ll b/llvm/test/Transforms/InstCombine/and-xor-or.ll
index e540878dc39d6..8046f340a7173 100644
--- a/llvm/test/Transforms/InstCombine/and-xor-or.ll
+++ b/llvm/test/Transforms/InstCombine/and-xor-or.ll
@@ -4338,7 +4338,7 @@ define i16 @or_disjoint_zext_zext(i8 %x, i4 %y) {
 ; CHECK-LABEL: define {{[^@]+}}@or_disjoint_zext_zext
 ; CHECK-SAME: (i8 [[X:%.*]], i4 [[Y:%.*]]) {
 ; CHECK-NEXT:    [[TMP1:%.*]] = zext i4 [[Y]] to i8
-; CHECK-NEXT:    [[R1:%.*]] = or i8 [[X]], [[TMP1]]
+; CHECK-NEXT:    [[R1:%.*]] = or disjoint i8 [[X]], [[TMP1]]
 ; CHECK-NEXT:    [[R:%.*]] = zext i8 [[R1]] to i16
 ; CHECK-NEXT:    ret i16 [[R]]
 ;
@@ -4351,7 +4351,7 @@ define i16 @or_disjoint_zext_zext(i8 %x, i4 %y) {
 define i16 @or_disjoint_zext_zext_2(i8 %x, i8 %y) {
 ; CHECK-LABEL: define {{[^@]+}}@or_disjoint_zext_zext_2
 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
-; CHECK-NEXT:    [[R1:%.*]] = or i8 [[Y]], [[X]]
+; CHECK-NEXT:    [[R1:%.*]] = or disjoint i8 [[Y]], [[X]]
 ; CHECK-NEXT:    [[R:%.*]] = zext i8 [[R1]] to i16
 ; CHECK-NEXT:    ret i16 [[R]]
 ;
@@ -4494,7 +4494,7 @@ define i16 @or_disjoint_sext_sext(i8 %x, i4 %y) {
 ; CHECK-LABEL: define {{[^@]+}}@or_disjoint_sext_sext
 ; CHECK-SAME: (i8 [[X:%.*]], i4 [[Y:%.*]]) {
 ; CHECK-NEXT:    [[TMP1:%.*]] = sext i4 [[Y]] to i8
-; CHECK-NEXT:    [[R1:%.*]] = or i8 [[X]], [[TMP1]]
+; CHECK-NEXT:    [[R1:%.*]] = or disjoint i8 [[X]], [[TMP1]]
 ; CHECK-NEXT:    [[R:%.*]] = sext i8 [[R1]] to i16
 ; CHECK-NEXT:    ret i16 [[R]]
 ;
@@ -4507,7 +4507,7 @@ define i16 @or_disjoint_sext_sext(i8 %x, i4 %y) {
 define i16 @or_disjoint_sext_sext_2(i8 %x, i8 %y) {
 ; CHECK-LABEL: define {{[^@]+}}@or_disjoint_sext_sext_2
 ; CHECK-SAME: (i8 [[X:%.*]], i8 [[Y:%.*]]) {
-; CHECK-NEXT:    [[R1:%.*]] = or i8 [[X]], [[Y]]
+; CHECK-NEXT:    [[R1:%.*]] = or disjoint i8 [[X]], [[Y]]
 ; CHECK-NEXT:    [[R:%.*]] = sext i8 [[R1]] to i16
 ; CHECK-NEXT:    ret i16 [[R]]
 ;



More information about the llvm-commits mailing list