[llvm] [RISCV] Keep or disjoint after folding casted bitwise logic (PR #136815)
Jim Lin via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 22 22:53:02 PDT 2025
https://github.com/tclin914 created https://github.com/llvm/llvm-project/pull/136815
Optimize
`or disjoint (zext/sext a) (zext/sext b))`
to
`(zext/sext (or disjoint a, b))`
without losing disjoint.
Confirmed here: https://alive2.llvm.org/ce/z/kQ5fJv.
>From 7637bdee590b9c1e2e4589ca1503eee51ddcd025 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 | 28 +++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/llvm/test/Transforms/InstCombine/and-xor-or.ll b/llvm/test/Transforms/InstCombine/and-xor-or.ll
index 5a58995f6c315..b61e95f85d98a 100644
--- a/llvm/test/Transforms/InstCombine/and-xor-or.ll
+++ b/llvm/test/Transforms/InstCombine/and-xor-or.ll
@@ -4274,6 +4274,20 @@ define i16 @or_zext_zext(i8 %x, i4 %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: [[TMP2:%.*]] = or i8 [[X]], [[TMP1]]
+; CHECK-NEXT: [[R:%.*]] = zext i8 [[TMP2]] 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 <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:%.*]]) {
@@ -4316,6 +4330,20 @@ define i16 @or_sext_sext(i8 %x, i4 %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: [[TMP2:%.*]] = or i8 [[X]], [[TMP1]]
+; CHECK-NEXT: [[R:%.*]] = sext i8 [[TMP2]] 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 @xor_sext_sext(i8 %x, i4 %y) {
; CHECK-LABEL: define {{[^@]+}}@xor_sext_sext
; CHECK-SAME: (i8 [[X:%.*]], i4 [[Y:%.*]]) {
>From f9ad6345ad267aefbf273a39ce9227c73e30c941 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] [RISCV] 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.
---
.../InstCombine/InstCombineAndOrXor.cpp | 40 ++++++++++---------
.../test/Transforms/InstCombine/and-xor-or.ll | 4 +-
2 files changed, 23 insertions(+), 21 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index f1b225c0f238a..90ec7429d2403 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -1846,27 +1846,29 @@ Instruction *InstCombinerImpl::foldCastedBitwiseLogic(BinaryOperator &I) {
if (CastOpcode != Cast1->getOpcode())
return nullptr;
- // If the source types do not match, but the casts are matching extends, we
- // can still narrow the logic op.
- if (SrcTy != Cast1->getSrcTy()) {
- Value *X, *Y;
- if (match(Cast0, m_OneUse(m_ZExtOrSExt(m_Value(X)))) &&
- match(Cast1, m_OneUse(m_ZExtOrSExt(m_Value(Y))))) {
- // Cast the narrower source to the wider source type.
- unsigned XNumBits = X->getType()->getScalarSizeInBits();
- unsigned YNumBits = Y->getType()->getScalarSizeInBits();
- if (XNumBits < YNumBits)
- X = Builder.CreateCast(CastOpcode, X, Y->getType());
- else
- Y = Builder.CreateCast(CastOpcode, Y, X->getType());
- // Do the logic op in the intermediate width, then widen more.
- Value *NarrowLogic = Builder.CreateBinOp(LogicOpc, X, Y);
- return CastInst::Create(CastOpcode, NarrowLogic, DestTy);
- }
+ Value *X, *Y;
+ if (match(Cast0, m_OneUse(m_ZExtOrSExt(m_Value(X)))) &&
+ match(Cast1, m_OneUse(m_ZExtOrSExt(m_Value(Y))))) {
+ // Cast the narrower source to the wider source type.
+ unsigned XNumBits = X->getType()->getScalarSizeInBits();
+ unsigned YNumBits = Y->getType()->getScalarSizeInBits();
+ // If the source types do not match, but the casts are matching extends, we
+ // can still narrow the logic op.
+ if (XNumBits < YNumBits)
+ X = Builder.CreateCast(CastOpcode, X, Y->getType());
+ else if (YNumBits < XNumBits)
+ Y = Builder.CreateCast(CastOpcode, Y, X->getType());
+
+ // Do the logic op in the intermediate width, then widen more.
+ Value *NarrowLogic = Builder.CreateBinOp(LogicOpc, X, Y);
+ if (auto *Disjoint = dyn_cast<PossiblyDisjointInst>(&I);
+ Disjoint && Disjoint->isDisjoint())
+ cast<PossiblyDisjointInst>(NarrowLogic)->setIsDisjoint(true);
+ return CastInst::Create(CastOpcode, NarrowLogic, DestTy);
+ }
- // Give up for other cast opcodes.
+ if (SrcTy != Cast1->getSrcTy())
return nullptr;
- }
Value *Cast0Src = Cast0->getOperand(0);
Value *Cast1Src = Cast1->getOperand(0);
diff --git a/llvm/test/Transforms/InstCombine/and-xor-or.ll b/llvm/test/Transforms/InstCombine/and-xor-or.ll
index b61e95f85d98a..101c5890a1a13 100644
--- a/llvm/test/Transforms/InstCombine/and-xor-or.ll
+++ b/llvm/test/Transforms/InstCombine/and-xor-or.ll
@@ -4278,7 +4278,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: [[TMP2:%.*]] = or i8 [[X]], [[TMP1]]
+; CHECK-NEXT: [[TMP2:%.*]] = or disjoint i8 [[X]], [[TMP1]]
; CHECK-NEXT: [[R:%.*]] = zext i8 [[TMP2]] to i16
; CHECK-NEXT: ret i16 [[R]]
;
@@ -4334,7 +4334,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: [[TMP2:%.*]] = or i8 [[X]], [[TMP1]]
+; CHECK-NEXT: [[TMP2:%.*]] = or disjoint i8 [[X]], [[TMP1]]
; CHECK-NEXT: [[R:%.*]] = sext i8 [[TMP2]] to i16
; CHECK-NEXT: ret i16 [[R]]
;
More information about the llvm-commits
mailing list