[llvm] 316c076 - [X86] Fix X86 conditional load/store optimization for non-constant operands (#163353)

via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 15 06:47:13 PDT 2025


Author: azwolski
Date: 2025-10-15T14:47:09+01:00
New Revision: 316c0766942a1ed87e1a440efaa2fa4d0bad0418

URL: https://github.com/llvm/llvm-project/commit/316c0766942a1ed87e1a440efaa2fa4d0bad0418
DIFF: https://github.com/llvm/llvm-project/commit/316c0766942a1ed87e1a440efaa2fa4d0bad0418.diff

LOG: [X86] Fix X86 conditional load/store optimization for non-constant operands (#163353)

This PR fixes a bug in combineX86CloadCstore where an optimization was
being applied too broadly, causing incorrect code generation.

Without any assumptions about `X` this transformation is only valid when
`Y` is a non zero power of two/single-bit mask.
```cpp
      // res, flags2 = sub 0, (and (xor X, -1), Y)
      // cload/cstore ..., cond_ne, flag2
      // ->
      // res, flags2 = sub 0, (and X, Y)
      // cload/cstore ..., cond_e, flag2
```

We can restrict the optimization to most important case, so only apply
when `llvm::isOneConstant(Op1.getOperand(1))`. It might be not trivial
to find code that creates a SelectionDag with other values of `Y`.

Basline test: https://github.com/llvm/llvm-project/pull/163354

Added: 
    

Modified: 
    llvm/lib/Target/X86/X86ISelLowering.cpp
    llvm/test/CodeGen/X86/apx/cf.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index c32b1a66356ea..a0b64ff370b10 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -58342,11 +58342,12 @@ static SDValue combineX86CloadCstore(SDNode *N, SelectionDAG &DAG) {
   } else if (Op1.getOpcode() == ISD::AND && Sub.getValue(0).use_empty()) {
     SDValue Src = Op1;
     SDValue Op10 = Op1.getOperand(0);
-    if (Op10.getOpcode() == ISD::XOR && isAllOnesConstant(Op10.getOperand(1))) {
-      // res, flags2 = sub 0, (and (xor X, -1), Y)
+    if (Op10.getOpcode() == ISD::XOR && isAllOnesConstant(Op10.getOperand(1)) &&
+        llvm::isOneConstant(Op1.getOperand(1))) {
+      // res, flags2 = sub 0, (and (xor X, -1), 1)
       // cload/cstore ..., cond_ne, flag2
       // ->
-      // res, flags2 = sub 0, (and X, Y)
+      // res, flags2 = sub 0, (and X, 1)
       // cload/cstore ..., cond_e, flag2
       Src = DAG.getNode(ISD::AND, DL, Op1.getValueType(), Op10.getOperand(0),
                         Op1.getOperand(1));

diff  --git a/llvm/test/CodeGen/X86/apx/cf.ll b/llvm/test/CodeGen/X86/apx/cf.ll
index af9d944428d3c..de9caa5b6d989 100644
--- a/llvm/test/CodeGen/X86/apx/cf.ll
+++ b/llvm/test/CodeGen/X86/apx/cf.ll
@@ -235,9 +235,10 @@ define void @and_cond(i32 %a, i1 %b) {
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    testl %edi, %edi
 ; CHECK-NEXT:    setg %al
+; CHECK-NEXT:    notb %sil
 ; CHECK-NEXT:    xorl %ecx, %ecx
 ; CHECK-NEXT:    testb %al, %sil
-; CHECK-NEXT:    cfcmovel %ecx, 0
+; CHECK-NEXT:    cfcmovnel %ecx, 0
 ; CHECK-NEXT:    retq
   %is_pos = icmp sgt i32 %a, 0
   %not_b = xor i1 %b, true


        


More information about the llvm-commits mailing list