[llvm] 53a2fd9 - [DAGCombiner] Combine (fshl A, B, S) | (fshr C, D, BW-S) --> (fshl (A|C), (B|D), S) (#180889)

via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 10 18:53:44 PDT 2026


Author: Craig Topper
Date: 2026-03-10T18:53:40-07:00
New Revision: 53a2fd99aa7d55051db03b6f389814c6b6741502

URL: https://github.com/llvm/llvm-project/commit/53a2fd99aa7d55051db03b6f389814c6b6741502
DIFF: https://github.com/llvm/llvm-project/commit/53a2fd99aa7d55051db03b6f389814c6b6741502.diff

LOG: [DAGCombiner] Combine (fshl A, B, S) | (fshr C, D, BW-S) --> (fshl (A|C), (B|D), S) (#180889)

This is similar to the FSHL/FSHR handling in
hoistLogicOpWithSameOpcodeHands.
Here the opcodes aren't exactly the same, but the operations are
equivalent.

Fixes regressions from #180888

Added: 
    

Modified: 
    llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
    llvm/test/CodeGen/X86/icmp-shift-opt.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index a2353fe2a2993..8c18d8bb625be 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -8535,6 +8535,24 @@ static SDValue visitORCommutative(SelectionDAG &DAG, SDValue N0, SDValue N1,
     }
   }
 
+  // (fshl A, B, S0) | (fshr C, D, S1) --> fshl (A|C), (B|D), S0
+  // iff S0 + S1 == bitwidth(S1)
+  if (N0.getOpcode() == ISD::FSHL && N1.getOpcode() == ISD::FSHR &&
+      N0.hasOneUse() && N1.hasOneUse()) {
+    auto *S0 = dyn_cast<ConstantSDNode>(N0.getOperand(2));
+    auto *S1 = dyn_cast<ConstantSDNode>(N1.getOperand(2));
+    if (S0 && S1 && S0->getZExtValue() < BW && S1->getZExtValue() < BW &&
+        S0->getZExtValue() == (BW - S1->getZExtValue())) {
+      SDValue A = N0.getOperand(0);
+      SDValue B = N0.getOperand(1);
+      SDValue C = N1.getOperand(0);
+      SDValue D = N1.getOperand(1);
+      SDValue NewLHS = DAG.getNode(ISD::OR, DL, VT, A, C);
+      SDValue NewRHS = DAG.getNode(ISD::OR, DL, VT, B, D);
+      return DAG.getNode(ISD::FSHL, DL, VT, NewLHS, NewRHS, N0.getOperand(2));
+    }
+  }
+
   // Attempt to match a legalized build_pair-esque pattern:
   // or(shl(aext(Hi),BW/2),zext(Lo))
   SDValue Lo, Hi;

diff  --git a/llvm/test/CodeGen/X86/icmp-shift-opt.ll b/llvm/test/CodeGen/X86/icmp-shift-opt.ll
index 7ba7f6212d517..0296c2a011e25 100644
--- a/llvm/test/CodeGen/X86/icmp-shift-opt.ll
+++ b/llvm/test/CodeGen/X86/icmp-shift-opt.ll
@@ -83,14 +83,12 @@ define i1 @opt_setcc_srl_eq_zero(i128 %a) nounwind {
 ; X86-NEXT:    movl %esp, %ebp
 ; X86-NEXT:    andl $-16, %esp
 ; X86-NEXT:    subl $16, %esp
-; X86-NEXT:    movl 16(%ebp), %eax
+; X86-NEXT:    movl 8(%ebp), %eax
 ; X86-NEXT:    movl 12(%ebp), %ecx
+; X86-NEXT:    shrl $17, %eax
 ; X86-NEXT:    orl 20(%ebp), %ecx
-; X86-NEXT:    movl %eax, %edx
-; X86-NEXT:    shldl $15, %ecx, %edx
-; X86-NEXT:    orl 8(%ebp), %eax
-; X86-NEXT:    shrdl $17, %ecx, %eax
-; X86-NEXT:    orl %edx, %eax
+; X86-NEXT:    orl 16(%ebp), %ecx
+; X86-NEXT:    orl %eax, %ecx
 ; X86-NEXT:    sete %al
 ; X86-NEXT:    movl %ebp, %esp
 ; X86-NEXT:    popl %ebp
@@ -114,14 +112,12 @@ define i1 @opt_setcc_srl_ne_zero(i128 %a) nounwind {
 ; X86-NEXT:    movl %esp, %ebp
 ; X86-NEXT:    andl $-16, %esp
 ; X86-NEXT:    subl $16, %esp
-; X86-NEXT:    movl 16(%ebp), %eax
+; X86-NEXT:    movl 8(%ebp), %eax
 ; X86-NEXT:    movl 12(%ebp), %ecx
+; X86-NEXT:    shrl $17, %eax
 ; X86-NEXT:    orl 20(%ebp), %ecx
-; X86-NEXT:    movl %eax, %edx
-; X86-NEXT:    shldl $15, %ecx, %edx
-; X86-NEXT:    orl 8(%ebp), %eax
-; X86-NEXT:    shrdl $17, %ecx, %eax
-; X86-NEXT:    orl %edx, %eax
+; X86-NEXT:    orl 16(%ebp), %ecx
+; X86-NEXT:    orl %eax, %ecx
 ; X86-NEXT:    setne %al
 ; X86-NEXT:    movl %ebp, %esp
 ; X86-NEXT:    popl %ebp


        


More information about the llvm-commits mailing list