[llvm] [RISCV] Keep or disjoint after folding casted bitwise logic (PR #136815)

via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 22 22:53:35 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Jim Lin (tclin914)

<details>
<summary>Changes</summary>

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.

---
Full diff: https://github.com/llvm/llvm-project/pull/136815.diff


2 Files Affected:

- (modified) llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp (+21-19) 
- (modified) llvm/test/Transforms/InstCombine/and-xor-or.ll (+28) 


``````````diff
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 5a58995f6c315..101c5890a1a13 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 disjoint 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 disjoint 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:%.*]]) {

``````````

</details>


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


More information about the llvm-commits mailing list