[spirv-reader][ir] Add Not support for spec constants

Add support for the `OpNot` command to the spec constant instructions.

Bug: 402726637
Change-Id: I03211a6fd3cc59a96f7d3e73f89c4b47be68b436
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/237396
Reviewed-by: James Price <jrprice@google.com>
Commit-Queue: dan sinclair <dsinclair@chromium.org>
diff --git a/src/tint/lang/spirv/reader/lower/builtins_test.cc b/src/tint/lang/spirv/reader/lower/builtins_test.cc
index ac934bd..80440d9 100644
--- a/src/tint/lang/spirv/reader/lower/builtins_test.cc
+++ b/src/tint/lang/spirv/reader/lower/builtins_test.cc
@@ -8501,6 +8501,53 @@
     EXPECT_EQ(expect, str());
 }
 
+TEST_F(SpirvReader_BuiltinsTest, SpecConstantOp_Not) {
+    auto* ep = b.ComputeFunction("foo");
+
+    capabilities = core::ir::Capabilities{core::ir::Capability::kAllowOverrides};
+
+    b.Append(b.ir.root_block, [&] {
+        b.CallExplicit<spirv::ir::BuiltinCall>(ty.i32(), spirv::BuiltinFn::kNot, Vector{ty.i32()},
+                                               1_i);
+    });
+
+    b.Append(ep->Block(), [&] {  //
+        b.CallExplicit<spirv::ir::BuiltinCall>(ty.i32(), spirv::BuiltinFn::kNot, Vector{ty.i32()},
+                                               1_i);
+        b.Return(ep);
+    });
+
+    auto src = R"(
+$B1: {  # root
+  %1:i32 = spirv.not<i32> 1i
+}
+
+%foo = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %3:i32 = spirv.not<i32> 1i
+    ret
+  }
+}
+)";
+    EXPECT_EQ(src, str());
+    Run(Builtins);
+
+    auto expect = R"(
+$B1: {  # root
+  %1:i32 = complement 1i
+}
+
+%foo = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %3:i32 = complement 1i
+    ret
+  }
+}
+)";
+
+    EXPECT_EQ(expect, str());
+}
+
 TEST_F(SpirvReader_BuiltinsTest, Not_Scalar_Signed_Signed) {
     auto* ep = b.ComputeFunction("foo");
 
diff --git a/src/tint/lang/spirv/reader/parser/parser.cc b/src/tint/lang/spirv/reader/parser/parser.cc
index 080f67b..18bf5a8 100644
--- a/src/tint/lang/spirv/reader/parser/parser.cc
+++ b/src/tint/lang/spirv/reader/parser/parser.cc
@@ -208,6 +208,9 @@
                         case spv::Op::OpLogicalNotEqual:
                             EmitBinary(inst, core::BinaryOp::kNotEqual, 3);
                             break;
+                        case spv::Op::OpNot:
+                            EmitSpirvExplicitBuiltinCall(inst, spirv::BuiltinFn::kNot, 3);
+                            break;
                         default:
                             TINT_ICE() << "Unknown spec constant operation: " << op;
                     }
@@ -1871,10 +1874,12 @@
         Emit(b_.Call(Type(inst.type_id()), fn, Args(inst, 2)), inst.result_id());
     }
 
-    void EmitSpirvExplicitBuiltinCall(const spvtools::opt::Instruction& inst, spirv::BuiltinFn fn) {
+    void EmitSpirvExplicitBuiltinCall(const spvtools::opt::Instruction& inst,
+                                      spirv::BuiltinFn fn,
+                                      uint32_t first_operand_idx = 2) {
         Emit(b_.CallExplicit<spirv::ir::BuiltinCall>(Type(inst.type_id()), fn,
                                                      Vector{Type(inst.type_id())->DeepestElement()},
-                                                     Args(inst, 2)),
+                                                     Args(inst, first_operand_idx)),
              inst.result_id());
     }
 
diff --git a/src/tint/lang/spirv/reader/parser/var_test.cc b/src/tint/lang/spirv/reader/parser/var_test.cc
index c0c5c65..27c30b9 100644
--- a/src/tint/lang/spirv/reader/parser/var_test.cc
+++ b/src/tint/lang/spirv/reader/parser/var_test.cc
@@ -904,5 +904,41 @@
 )");
 }
 
+TEST_F(SpirvParserTest, Var_OpSpecConstantOp_Not) {
+    EXPECT_IR(R"(
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpName %cond "myconst"
+       %void = OpTypeVoid
+       %bool = OpTypeBool
+        %i32 = OpTypeInt 32 1
+      %false = OpSpecConstantFalse %bool
+       %true = OpSpecConstantTrue %bool
+        %one = OpConstant %i32 1
+       %cond = OpSpecConstantOp %i32 Not %one
+     %voidfn = OpTypeFunction %void
+       %main = OpFunction %void None %voidfn
+ %main_entry = OpLabel
+          %1 = OpNot %i32 %cond
+               OpReturn
+               OpFunctionEnd
+)",
+              R"(
+$B1: {  # root
+  %1:i32 = spirv.not<i32> 1i
+  %myconst:i32 = override %1
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+  $B2: {
+    %4:i32 = spirv.not<i32> %myconst
+    ret
+  }
+}
+)");
+}
+
 }  // namespace
 }  // namespace tint::spirv::reader