From c4efaa633219f5f47402ea2c74a9c1b0a36ba82d Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 4 Aug 2025 13:01:56 +0200 Subject: [PATCH 1/2] [GVN] Add some tests for not condition propagation (NFC) --- llvm/test/Transforms/GVN/condprop.ll | 82 ++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/llvm/test/Transforms/GVN/condprop.ll b/llvm/test/Transforms/GVN/condprop.ll index 3babdd8173a21..27cbd41485bee 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 [[C]] +; CHECK: else: +; CHECK-NEXT: ret i1 [[C]] +; + %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 [[X]] +; + %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 [[C]] +; 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 [[C]] +; + %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) From c9e4be4ed30f44652b8d58e6a32c6f606ffe9a38 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 4 Aug 2025 13:04:37 +0200 Subject: [PATCH 2/2] [GVN] Handle not in equality propagation --- llvm/lib/Transforms/Scalar/GVN.cpp | 5 +++++ llvm/test/Transforms/GVN/condprop.ll | 10 +++++----- 2 files changed, 10 insertions(+), 5 deletions(-) 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 27cbd41485bee..15ffcbff1e157 100644 --- a/llvm/test/Transforms/GVN/condprop.ll +++ b/llvm/test/Transforms/GVN/condprop.ll @@ -1004,9 +1004,9 @@ define i1 @not_cond(i1 %c) { ; CHECK-NEXT: [[C_NOT:%.*]] = xor i1 [[C:%.*]], true ; CHECK-NEXT: br i1 [[C_NOT]], label [[IF:%.*]], label [[ELSE:%.*]] ; CHECK: if: -; CHECK-NEXT: ret i1 [[C]] +; CHECK-NEXT: ret i1 false ; CHECK: else: -; CHECK-NEXT: ret i1 [[C]] +; CHECK-NEXT: ret i1 true ; %c.not = xor i1 %c, true br i1 %c.not, label %if, label %else @@ -1026,7 +1026,7 @@ define i32 @not_cond_icmp(i32 %x) { ; CHECK: if: ; CHECK-NEXT: ret i32 [[X]] ; CHECK: else: -; CHECK-NEXT: ret i32 [[X]] +; CHECK-NEXT: ret i32 42 ; %cmp = icmp eq i32 %x, 42 %cmp.not = xor i1 %cmp, true @@ -1045,7 +1045,7 @@ define i1 @not_cond_logic1(i1 %c, i1 %d) { ; CHECK-NEXT: [[AND:%.*]] = and i1 [[C_NOT]], [[D:%.*]] ; CHECK-NEXT: br i1 [[AND]], label [[IF:%.*]], label [[ELSE:%.*]] ; CHECK: if: -; CHECK-NEXT: ret i1 [[C]] +; CHECK-NEXT: ret i1 false ; CHECK: else: ; CHECK-NEXT: ret i1 [[C]] ; @@ -1068,7 +1068,7 @@ define i1 @not_cond_logic2(i1 %c, i1 %d) { ; CHECK: if: ; CHECK-NEXT: ret i1 [[C]] ; CHECK: else: -; CHECK-NEXT: ret i1 [[C]] +; CHECK-NEXT: ret i1 true ; %c.not = xor i1 %c, true %or = or i1 %c.not, %d