[llvm] e044cc5 - [GVN] Handle not in equality propagation (#151942)

via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 5 00:11:28 PDT 2025


Author: Nikita Popov
Date: 2025-08-05T09:11:24+02:00
New Revision: e044cc50eec8b2875b047c242f7afa4bc47046fe

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

LOG: [GVN] Handle not in equality propagation (#151942)

Look through `not` when propagating equalities in GVN. Usually these
will be canonicalized away, but they may be retained due to multi-use or
involvement in logical expressions.

Fixes https://github.com/llvm/llvm-project/issues/143529.

Added: 
    

Modified: 
    llvm/lib/Transforms/Scalar/GVN.cpp
    llvm/test/Transforms/GVN/condprop.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Scalar/GVN.cpp b/llvm/lib/Transforms/Scalar/GVN.cpp
index fa6ee95d33d10..3a73b42455b0d 100644
--- a/llvm/lib/Transforms/Scalar/GVN.cpp
+++ b/llvm/lib/Transforms/Scalar/GVN.cpp
@@ -2683,6 +2683,11 @@ bool GVNPass::propagateEquality(Value *LHS, Value *RHS,
       Worklist.emplace_back(A, ConstantInt::get(A->getType(), IsKnownTrue));
       continue;
     }
+
+    if (match(LHS, m_Not(m_Value(A)))) {
+      Worklist.emplace_back(A, ConstantInt::get(A->getType(), !IsKnownTrue));
+      continue;
+    }
   }
 
   return Changed;

diff  --git a/llvm/test/Transforms/GVN/condprop.ll b/llvm/test/Transforms/GVN/condprop.ll
index 3babdd8173a21..15ffcbff1e157 100644
--- a/llvm/test/Transforms/GVN/condprop.ll
+++ b/llvm/test/Transforms/GVN/condprop.ll
@@ -999,5 +999,87 @@ loop.latch:
   br label %loop
 }
 
+define i1 @not_cond(i1 %c) {
+; CHECK-LABEL: @not_cond(
+; CHECK-NEXT:    [[C_NOT:%.*]] = xor i1 [[C:%.*]], true
+; CHECK-NEXT:    br i1 [[C_NOT]], label [[IF:%.*]], label [[ELSE:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    ret i1 false
+; CHECK:       else:
+; CHECK-NEXT:    ret i1 true
+;
+  %c.not = xor i1 %c, true
+  br i1 %c.not, label %if, label %else
+
+if:
+  ret i1 %c
+
+else:
+  ret i1 %c
+}
+
+define i32 @not_cond_icmp(i32 %x) {
+; CHECK-LABEL: @not_cond_icmp(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[X:%.*]], 42
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = xor i1 [[CMP]], true
+; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[IF:%.*]], label [[ELSE:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    ret i32 [[X]]
+; CHECK:       else:
+; CHECK-NEXT:    ret i32 42
+;
+  %cmp = icmp eq i32 %x, 42
+  %cmp.not = xor i1 %cmp, true
+  br i1 %cmp.not, label %if, label %else
+
+if:
+  ret i32 %x
+
+else:
+  ret i32 %x
+}
+
+define i1 @not_cond_logic1(i1 %c, i1 %d) {
+; CHECK-LABEL: @not_cond_logic1(
+; CHECK-NEXT:    [[C_NOT:%.*]] = xor i1 [[C:%.*]], true
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_NOT]], [[D:%.*]]
+; CHECK-NEXT:    br i1 [[AND]], label [[IF:%.*]], label [[ELSE:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    ret i1 false
+; CHECK:       else:
+; CHECK-NEXT:    ret i1 [[C]]
+;
+  %c.not = xor i1 %c, true
+  %and = and i1 %c.not, %d
+  br i1 %and, label %if, label %else
+
+if:
+  ret i1 %c
+
+else:
+  ret i1 %c
+}
+
+define i1 @not_cond_logic2(i1 %c, i1 %d) {
+; CHECK-LABEL: @not_cond_logic2(
+; CHECK-NEXT:    [[C_NOT:%.*]] = xor i1 [[C:%.*]], true
+; CHECK-NEXT:    [[AND:%.*]] = or i1 [[C_NOT]], [[D:%.*]]
+; CHECK-NEXT:    br i1 [[AND]], label [[IF:%.*]], label [[ELSE:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    ret i1 [[C]]
+; CHECK:       else:
+; CHECK-NEXT:    ret i1 true
+;
+  %c.not = xor i1 %c, true
+  %or = or i1 %c.not, %d
+  br i1 %or, label %if, label %else
+
+if:
+  ret i1 %c
+
+else:
+  ret i1 %c
+}
+
 declare void @use_bool(i1)
 declare void @use_ptr(ptr)


        


More information about the llvm-commits mailing list