[llvm] [GVN] Replace cmp with not instruction if inv cmp is found (PR #223171)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Sep 12 13:31:34 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Andreas Jonson (andjo403)
<details>
<summary>Changes</summary>
---
Full diff: https://github.com/llvm/llvm-project/pull/223171.diff
2 Files Affected:
- (modified) llvm/lib/Transforms/Scalar/GVN.cpp (+22-10)
- (added) llvm/test/Transforms/GVN/inverse-cmp.ll (+52)
``````````diff
diff --git a/llvm/lib/Transforms/Scalar/GVN.cpp b/llvm/lib/Transforms/Scalar/GVN.cpp
index c8989a4c8e0d4..acad4b311b2cf 100644
--- a/llvm/lib/Transforms/Scalar/GVN.cpp
+++ b/llvm/lib/Transforms/Scalar/GVN.cpp
@@ -3445,18 +3445,30 @@ bool GVNPass::processInstruction(Instruction *I) {
}
}
- // If the number we were assigned was a brand new VN, then we don't
- // need to do a lookup to see if the number already exists
- // somewhere in the domtree: it can't!
- if (Num >= NextNum) {
- LeaderTable.insert(Num, I, I->getParent());
- return false;
- }
-
// Perform fast-path value-number based elimination of values inherited from
- // dominators.
- Value *Repl = findLeader(I->getParent(), Num);
+ // dominators, unless if the number we were assigned was a brand new VN, then
+ // we don't need to do a lookup to see if the number already exists somewhere
+ // in the domtree: it can't!
+ Value *Repl = Num < NextNum ? findLeader(I->getParent(), Num) : nullptr;
if (!Repl) {
+ // substiut cmp instruction with not if possible.
+ if (CmpInst *Cmp = dyn_cast<CmpInst>(I)) {
+ uint32_t NextNumNot = VN.getNextUnusedValueNumber();
+ uint32_t NotNum =
+ VN.lookupOrAddCmp(Cmp->getOpcode(), Cmp->getInversePredicate(),
+ Cmp->getOperand(0), Cmp->getOperand(1));
+ if (NotNum < NextNumNot) {
+ Value *NotRepl = findLeader(I->getParent(), NotNum);
+ if (NotRepl && NotRepl != I) {
+ BinaryOperator *Not = BinaryOperator::CreateNot(
+ NotRepl, NotRepl->getName() + ".not", I->getIterator());
+ Not->setDebugLoc(I->getDebugLoc());
+ I->replaceAllUsesWith(Not);
+ salvageAndRemoveInstruction(I);
+ return true;
+ }
+ }
+ }
// Failure, just remember this instance for future use.
LeaderTable.insert(Num, I, I->getParent());
return false;
diff --git a/llvm/test/Transforms/GVN/inverse-cmp.ll b/llvm/test/Transforms/GVN/inverse-cmp.ll
new file mode 100644
index 0000000000000..b874cd55b873a
--- /dev/null
+++ b/llvm/test/Transforms/GVN/inverse-cmp.ll
@@ -0,0 +1,52 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -passes=gvn -S < %s | FileCheck %s
+
+declare void @use(i1)
+
+define void @inverse_icmp(i32 %x,i32 %y) {
+; CHECK-LABEL: define void @inverse_icmp(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT: [[UGT1:%.*]] = icmp ugt i32 [[X]], [[Y]]
+; CHECK-NEXT: call void @use(i1 [[UGT1]])
+; CHECK-NEXT: [[UGT1_NOT:%.*]] = xor i1 [[UGT1]], true
+; CHECK-NEXT: call void @use(i1 [[UGT1_NOT]])
+; CHECK-NEXT: ret void
+;
+ %ugt1 = icmp ugt i32 %x, %y
+ call void @use(i1 %ugt1)
+ %ule1 = icmp ule i32 %x, %y
+ call void @use(i1 %ule1)
+ ret void
+}
+
+define void @inverse_fcmp(double %x,double %y) {
+; CHECK-LABEL: define void @inverse_fcmp(
+; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) {
+; CHECK-NEXT: [[OGT1:%.*]] = fcmp ogt double [[X]], [[Y]]
+; CHECK-NEXT: call void @use(i1 [[OGT1]])
+; CHECK-NEXT: [[OGT1_NOT:%.*]] = xor i1 [[OGT1]], true
+; CHECK-NEXT: call void @use(i1 [[OGT1_NOT]])
+; CHECK-NEXT: ret void
+;
+ %ogt1 = fcmp ogt double %x, %y
+ call void @use(i1 %ogt1)
+ %ule1 = fcmp ule double %x, %y
+ call void @use(i1 %ule1)
+ ret void
+}
+
+define void @inverse_icmp_swaped(i32 %x,i32 %y) {
+; CHECK-LABEL: define void @inverse_icmp_swaped(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT: [[UGT1:%.*]] = icmp ugt i32 [[X]], [[Y]]
+; CHECK-NEXT: call void @use(i1 [[UGT1]])
+; CHECK-NEXT: [[UGT1_NOT:%.*]] = xor i1 [[UGT1]], true
+; CHECK-NEXT: call void @use(i1 [[UGT1_NOT]])
+; CHECK-NEXT: ret void
+;
+ %ugt = icmp ugt i32 %x, %y
+ call void @use(i1 %ugt)
+ %ule = icmp uge i32 %y, %x
+ call void @use(i1 %ule)
+ ret void
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/223171
More information about the llvm-commits
mailing list