[ir] Change unary not to a binary equal
This CL removes unary `not` and instead emits `x == false`. When coming
back out of IR we can detect the `== false` and convert back to a `!`.
Bug: tint:1928
Change-Id: I905493182533ac2787ab9fe9245c8b53d51c1298
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/131580
Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: James Price <jrprice@google.com>
diff --git a/src/tint/ir/binary_test.cc b/src/tint/ir/binary_test.cc
index 9b7fd07..6a96633 100644
--- a/src/tint/ir/binary_test.cc
+++ b/src/tint/ir/binary_test.cc
@@ -203,6 +203,25 @@
EXPECT_EQ(2_i, rhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
}
+TEST_F(IR_InstructionTest, CreateNot) {
+ auto& b = CreateEmptyBuilder();
+ const auto* inst =
+ b.builder.Not(b.builder.ir.types.Get<type::Bool>(), b.builder.Constant(true));
+
+ ASSERT_TRUE(inst->Is<Binary>());
+ EXPECT_EQ(inst->GetKind(), Binary::Kind::kEqual);
+
+ ASSERT_TRUE(inst->LHS()->Is<Constant>());
+ auto lhs = inst->LHS()->As<Constant>()->value;
+ ASSERT_TRUE(lhs->Is<constant::Scalar<bool>>());
+ EXPECT_TRUE(lhs->As<constant::Scalar<bool>>()->ValueAs<bool>());
+
+ ASSERT_TRUE(inst->RHS()->Is<Constant>());
+ auto rhs = inst->RHS()->As<Constant>()->value;
+ ASSERT_TRUE(rhs->Is<constant::Scalar<bool>>());
+ EXPECT_FALSE(rhs->As<constant::Scalar<bool>>()->ValueAs<bool>());
+}
+
TEST_F(IR_InstructionTest, CreateShiftLeft) {
auto& b = CreateEmptyBuilder();
diff --git a/src/tint/ir/builder.cc b/src/tint/ir/builder.cc
index 8badd31..e826be4d 100644
--- a/src/tint/ir/builder.cc
+++ b/src/tint/ir/builder.cc
@@ -16,6 +16,8 @@
#include <utility>
+#include "src/tint/constant/scalar.h"
+
namespace tint::ir {
Builder::Builder() {}
@@ -194,8 +196,8 @@
return CreateUnary(Unary::Kind::kNegation, type, val);
}
-Unary* Builder::Not(const type::Type* type, Value* val) {
- return CreateUnary(Unary::Kind::kNot, type, val);
+Binary* Builder::Not(const type::Type* type, Value* val) {
+ return Equal(type, val, Constant(create<constant::Scalar<bool>>(type, false)));
}
ir::Bitcast* Builder::Bitcast(const type::Type* type, Value* val) {
diff --git a/src/tint/ir/builder.h b/src/tint/ir/builder.h
index 24c20d0..ff01e2d 100644
--- a/src/tint/ir/builder.h
+++ b/src/tint/ir/builder.h
@@ -300,7 +300,7 @@
/// @param type the result type of the expression
/// @param val the value
/// @returns the operation
- Unary* Not(const type::Type* type, Value* val);
+ Binary* Not(const type::Type* type, Value* val);
/// Creates a bitcast instruction
/// @param type the result type of the bitcast
diff --git a/src/tint/ir/builder_impl.cc b/src/tint/ir/builder_impl.cc
index 2a42917..2d6530e 100644
--- a/src/tint/ir/builder_impl.cc
+++ b/src/tint/ir/builder_impl.cc
@@ -833,7 +833,7 @@
auto* sem = program_->Sem().Get(expr);
auto* ty = sem->Type()->Clone(clone_ctx_.type_ctx);
- Unary* inst = nullptr;
+ Instruction* inst = nullptr;
switch (expr->op) {
case ast::UnaryOp::kAddressOf:
inst = builder.AddressOf(ty, val.Get());
diff --git a/src/tint/ir/disassembler.cc b/src/tint/ir/disassembler.cc
index ffda493..ec17624 100644
--- a/src/tint/ir/disassembler.cc
+++ b/src/tint/ir/disassembler.cc
@@ -493,9 +493,6 @@
case Unary::Kind::kNegation:
out_ << "negation";
break;
- case Unary::Kind::kNot:
- out_ << "not";
- break;
}
out_ << " ";
EmitValue(u->Val());
diff --git a/src/tint/ir/unary.h b/src/tint/ir/unary.h
index 297e48f1..64301d4 100644
--- a/src/tint/ir/unary.h
+++ b/src/tint/ir/unary.h
@@ -29,7 +29,6 @@
kComplement,
kIndirection,
kNegation,
- kNot,
};
/// Constructor
diff --git a/src/tint/ir/unary_test.cc b/src/tint/ir/unary_test.cc
index ace90eb..e205d8f 100644
--- a/src/tint/ir/unary_test.cc
+++ b/src/tint/ir/unary_test.cc
@@ -87,20 +87,6 @@
EXPECT_EQ(4_i, lhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
}
-TEST_F(IR_InstructionTest, CreateNot) {
- auto& b = CreateEmptyBuilder();
- const auto* inst =
- b.builder.Not(b.builder.ir.types.Get<type::Bool>(), b.builder.Constant(true));
-
- ASSERT_TRUE(inst->Is<Unary>());
- EXPECT_EQ(inst->GetKind(), Unary::Kind::kNot);
-
- ASSERT_TRUE(inst->Val()->Is<Constant>());
- auto lhs = inst->Val()->As<Constant>()->value;
- ASSERT_TRUE(lhs->Is<constant::Scalar<bool>>());
- EXPECT_TRUE(lhs->As<constant::Scalar<bool>>()->ValueAs<bool>());
-}
-
TEST_F(IR_InstructionTest, Unary_Usage) {
auto& b = CreateEmptyBuilder();
const auto* inst =