xref: /aosp_15_r20/external/swiftshader/src/Pipeline/SpirvShaderSpec.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1*03ce13f7SAndroid Build Coastguard Worker // Copyright 2019 The SwiftShader Authors. All Rights Reserved.
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*03ce13f7SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*03ce13f7SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*03ce13f7SAndroid Build Coastguard Worker //
7*03ce13f7SAndroid Build Coastguard Worker //    http://www.apache.org/licenses/LICENSE-2.0
8*03ce13f7SAndroid Build Coastguard Worker //
9*03ce13f7SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*03ce13f7SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*03ce13f7SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*03ce13f7SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*03ce13f7SAndroid Build Coastguard Worker // limitations under the License.
14*03ce13f7SAndroid Build Coastguard Worker 
15*03ce13f7SAndroid Build Coastguard Worker #include "SpirvShader.hpp"
16*03ce13f7SAndroid Build Coastguard Worker 
17*03ce13f7SAndroid Build Coastguard Worker #include <spirv/unified1/spirv.hpp>
18*03ce13f7SAndroid Build Coastguard Worker 
19*03ce13f7SAndroid Build Coastguard Worker namespace sw {
20*03ce13f7SAndroid Build Coastguard Worker 
EvalSpecConstantOp(InsnIterator insn)21*03ce13f7SAndroid Build Coastguard Worker void Spirv::EvalSpecConstantOp(InsnIterator insn)
22*03ce13f7SAndroid Build Coastguard Worker {
23*03ce13f7SAndroid Build Coastguard Worker 	auto opcode = static_cast<spv::Op>(insn.word(3));
24*03ce13f7SAndroid Build Coastguard Worker 
25*03ce13f7SAndroid Build Coastguard Worker 	switch(opcode)
26*03ce13f7SAndroid Build Coastguard Worker 	{
27*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpIAdd:
28*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpISub:
29*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpIMul:
30*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpUDiv:
31*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpSDiv:
32*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpUMod:
33*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpSMod:
34*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpSRem:
35*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpShiftRightLogical:
36*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpShiftRightArithmetic:
37*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpShiftLeftLogical:
38*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpBitwiseOr:
39*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpLogicalOr:
40*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpBitwiseAnd:
41*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpLogicalAnd:
42*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpBitwiseXor:
43*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpLogicalEqual:
44*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpIEqual:
45*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpLogicalNotEqual:
46*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpINotEqual:
47*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpULessThan:
48*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpSLessThan:
49*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpUGreaterThan:
50*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpSGreaterThan:
51*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpULessThanEqual:
52*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpSLessThanEqual:
53*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpUGreaterThanEqual:
54*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpSGreaterThanEqual:
55*03ce13f7SAndroid Build Coastguard Worker 		EvalSpecConstantBinaryOp(insn);
56*03ce13f7SAndroid Build Coastguard Worker 		break;
57*03ce13f7SAndroid Build Coastguard Worker 
58*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpSConvert:
59*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpFConvert:
60*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpUConvert:
61*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpSNegate:
62*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpNot:
63*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpLogicalNot:
64*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpQuantizeToF16:
65*03ce13f7SAndroid Build Coastguard Worker 		EvalSpecConstantUnaryOp(insn);
66*03ce13f7SAndroid Build Coastguard Worker 		break;
67*03ce13f7SAndroid Build Coastguard Worker 
68*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpSelect:
69*03ce13f7SAndroid Build Coastguard Worker 		{
70*03ce13f7SAndroid Build Coastguard Worker 			auto &result = CreateConstant(insn);
71*03ce13f7SAndroid Build Coastguard Worker 			const auto &cond = getObject(insn.word(4));
72*03ce13f7SAndroid Build Coastguard Worker 			auto condIsScalar = (getType(cond).componentCount == 1);
73*03ce13f7SAndroid Build Coastguard Worker 			const auto &left = getObject(insn.word(5));
74*03ce13f7SAndroid Build Coastguard Worker 			const auto &right = getObject(insn.word(6));
75*03ce13f7SAndroid Build Coastguard Worker 
76*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < getType(result).componentCount; i++)
77*03ce13f7SAndroid Build Coastguard Worker 			{
78*03ce13f7SAndroid Build Coastguard Worker 				auto sel = cond.constantValue[condIsScalar ? 0 : i];
79*03ce13f7SAndroid Build Coastguard Worker 				result.constantValue[i] = sel ? left.constantValue[i] : right.constantValue[i];
80*03ce13f7SAndroid Build Coastguard Worker 			}
81*03ce13f7SAndroid Build Coastguard Worker 			break;
82*03ce13f7SAndroid Build Coastguard Worker 		}
83*03ce13f7SAndroid Build Coastguard Worker 
84*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpCompositeExtract:
85*03ce13f7SAndroid Build Coastguard Worker 		{
86*03ce13f7SAndroid Build Coastguard Worker 			auto &result = CreateConstant(insn);
87*03ce13f7SAndroid Build Coastguard Worker 			const auto &compositeObject = getObject(insn.word(4));
88*03ce13f7SAndroid Build Coastguard Worker 			auto firstComponent = WalkLiteralAccessChain(compositeObject.typeId(), Span(insn, 5, insn.wordCount() - 5));
89*03ce13f7SAndroid Build Coastguard Worker 
90*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < getType(result).componentCount; i++)
91*03ce13f7SAndroid Build Coastguard Worker 			{
92*03ce13f7SAndroid Build Coastguard Worker 				result.constantValue[i] = compositeObject.constantValue[firstComponent + i];
93*03ce13f7SAndroid Build Coastguard Worker 			}
94*03ce13f7SAndroid Build Coastguard Worker 			break;
95*03ce13f7SAndroid Build Coastguard Worker 		}
96*03ce13f7SAndroid Build Coastguard Worker 
97*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpCompositeInsert:
98*03ce13f7SAndroid Build Coastguard Worker 		{
99*03ce13f7SAndroid Build Coastguard Worker 			auto &result = CreateConstant(insn);
100*03ce13f7SAndroid Build Coastguard Worker 			const auto &newPart = getObject(insn.word(4));
101*03ce13f7SAndroid Build Coastguard Worker 			const auto &oldObject = getObject(insn.word(5));
102*03ce13f7SAndroid Build Coastguard Worker 			auto firstNewComponent = WalkLiteralAccessChain(result.typeId(), Span(insn, 6, insn.wordCount() - 6));
103*03ce13f7SAndroid Build Coastguard Worker 
104*03ce13f7SAndroid Build Coastguard Worker 			// old components before
105*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < firstNewComponent; i++)
106*03ce13f7SAndroid Build Coastguard Worker 			{
107*03ce13f7SAndroid Build Coastguard Worker 				result.constantValue[i] = oldObject.constantValue[i];
108*03ce13f7SAndroid Build Coastguard Worker 			}
109*03ce13f7SAndroid Build Coastguard Worker 			// new part
110*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < getType(newPart).componentCount; i++)
111*03ce13f7SAndroid Build Coastguard Worker 			{
112*03ce13f7SAndroid Build Coastguard Worker 				result.constantValue[firstNewComponent + i] = newPart.constantValue[i];
113*03ce13f7SAndroid Build Coastguard Worker 			}
114*03ce13f7SAndroid Build Coastguard Worker 			// old components after
115*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = firstNewComponent + getType(newPart).componentCount; i < getType(result).componentCount; i++)
116*03ce13f7SAndroid Build Coastguard Worker 			{
117*03ce13f7SAndroid Build Coastguard Worker 				result.constantValue[i] = oldObject.constantValue[i];
118*03ce13f7SAndroid Build Coastguard Worker 			}
119*03ce13f7SAndroid Build Coastguard Worker 			break;
120*03ce13f7SAndroid Build Coastguard Worker 		}
121*03ce13f7SAndroid Build Coastguard Worker 
122*03ce13f7SAndroid Build Coastguard Worker 	case spv::OpVectorShuffle:
123*03ce13f7SAndroid Build Coastguard Worker 		{
124*03ce13f7SAndroid Build Coastguard Worker 			auto &result = CreateConstant(insn);
125*03ce13f7SAndroid Build Coastguard Worker 			const auto &firstHalf = getObject(insn.word(4));
126*03ce13f7SAndroid Build Coastguard Worker 			const auto &secondHalf = getObject(insn.word(5));
127*03ce13f7SAndroid Build Coastguard Worker 
128*03ce13f7SAndroid Build Coastguard Worker 			for(auto i = 0u; i < getType(result).componentCount; i++)
129*03ce13f7SAndroid Build Coastguard Worker 			{
130*03ce13f7SAndroid Build Coastguard Worker 				auto selector = insn.word(6 + i);
131*03ce13f7SAndroid Build Coastguard Worker 				if(selector == static_cast<uint32_t>(-1))
132*03ce13f7SAndroid Build Coastguard Worker 				{
133*03ce13f7SAndroid Build Coastguard Worker 					// Undefined value, we'll use zero
134*03ce13f7SAndroid Build Coastguard Worker 					result.constantValue[i] = 0;
135*03ce13f7SAndroid Build Coastguard Worker 				}
136*03ce13f7SAndroid Build Coastguard Worker 				else if(selector < getType(firstHalf).componentCount)
137*03ce13f7SAndroid Build Coastguard Worker 				{
138*03ce13f7SAndroid Build Coastguard Worker 					result.constantValue[i] = firstHalf.constantValue[selector];
139*03ce13f7SAndroid Build Coastguard Worker 				}
140*03ce13f7SAndroid Build Coastguard Worker 				else
141*03ce13f7SAndroid Build Coastguard Worker 				{
142*03ce13f7SAndroid Build Coastguard Worker 					result.constantValue[i] = secondHalf.constantValue[selector - getType(firstHalf).componentCount];
143*03ce13f7SAndroid Build Coastguard Worker 				}
144*03ce13f7SAndroid Build Coastguard Worker 			}
145*03ce13f7SAndroid Build Coastguard Worker 			break;
146*03ce13f7SAndroid Build Coastguard Worker 		}
147*03ce13f7SAndroid Build Coastguard Worker 
148*03ce13f7SAndroid Build Coastguard Worker 	default:
149*03ce13f7SAndroid Build Coastguard Worker 		// Other spec constant ops are possible, but require capabilities that are
150*03ce13f7SAndroid Build Coastguard Worker 		// not exposed in our Vulkan implementation (eg Kernel), so we should never
151*03ce13f7SAndroid Build Coastguard Worker 		// get here for correct shaders.
152*03ce13f7SAndroid Build Coastguard Worker 		UNSUPPORTED("EvalSpecConstantOp op: %s", OpcodeName(opcode));
153*03ce13f7SAndroid Build Coastguard Worker 	}
154*03ce13f7SAndroid Build Coastguard Worker }
155*03ce13f7SAndroid Build Coastguard Worker 
EvalSpecConstantUnaryOp(InsnIterator insn)156*03ce13f7SAndroid Build Coastguard Worker void Spirv::EvalSpecConstantUnaryOp(InsnIterator insn)
157*03ce13f7SAndroid Build Coastguard Worker {
158*03ce13f7SAndroid Build Coastguard Worker 	auto &result = CreateConstant(insn);
159*03ce13f7SAndroid Build Coastguard Worker 
160*03ce13f7SAndroid Build Coastguard Worker 	auto opcode = static_cast<spv::Op>(insn.word(3));
161*03ce13f7SAndroid Build Coastguard Worker 	const auto &lhs = getObject(insn.word(4));
162*03ce13f7SAndroid Build Coastguard Worker 	auto size = getType(lhs).componentCount;
163*03ce13f7SAndroid Build Coastguard Worker 
164*03ce13f7SAndroid Build Coastguard Worker 	for(auto i = 0u; i < size; i++)
165*03ce13f7SAndroid Build Coastguard Worker 	{
166*03ce13f7SAndroid Build Coastguard Worker 		auto &v = result.constantValue[i];
167*03ce13f7SAndroid Build Coastguard Worker 		auto l = lhs.constantValue[i];
168*03ce13f7SAndroid Build Coastguard Worker 
169*03ce13f7SAndroid Build Coastguard Worker 		switch(opcode)
170*03ce13f7SAndroid Build Coastguard Worker 		{
171*03ce13f7SAndroid Build Coastguard Worker 		case spv::OpSConvert:
172*03ce13f7SAndroid Build Coastguard Worker 		case spv::OpFConvert:
173*03ce13f7SAndroid Build Coastguard Worker 		case spv::OpUConvert:
174*03ce13f7SAndroid Build Coastguard Worker 			UNREACHABLE("Not possible until we have multiple bit widths");
175*03ce13f7SAndroid Build Coastguard Worker 			break;
176*03ce13f7SAndroid Build Coastguard Worker 
177*03ce13f7SAndroid Build Coastguard Worker 		case spv::OpSNegate:
178*03ce13f7SAndroid Build Coastguard Worker 			v = -(int)l;
179*03ce13f7SAndroid Build Coastguard Worker 			break;
180*03ce13f7SAndroid Build Coastguard Worker 		case spv::OpNot:
181*03ce13f7SAndroid Build Coastguard Worker 		case spv::OpLogicalNot:
182*03ce13f7SAndroid Build Coastguard Worker 			v = ~l;
183*03ce13f7SAndroid Build Coastguard Worker 			break;
184*03ce13f7SAndroid Build Coastguard Worker 
185*03ce13f7SAndroid Build Coastguard Worker 		case spv::OpQuantizeToF16:
186*03ce13f7SAndroid Build Coastguard Worker 			{
187*03ce13f7SAndroid Build Coastguard Worker 				// Can do this nicer with host code, but want to perfectly mirror the reactor code we emit.
188*03ce13f7SAndroid Build Coastguard Worker 				auto abs = bit_cast<float>(l & 0x7FFFFFFF);
189*03ce13f7SAndroid Build Coastguard Worker 				auto sign = l & 0x80000000;
190*03ce13f7SAndroid Build Coastguard Worker 				auto isZero = abs < 0.000061035f ? ~0u : 0u;
191*03ce13f7SAndroid Build Coastguard Worker 				auto isInf = abs > 65504.0f ? ~0u : 0u;
192*03ce13f7SAndroid Build Coastguard Worker 				auto isNaN = (abs != abs) ? ~0u : 0u;
193*03ce13f7SAndroid Build Coastguard Worker 				auto isInfOrNan = isInf | isNaN;
194*03ce13f7SAndroid Build Coastguard Worker 				v = l & 0xFFFFE000;
195*03ce13f7SAndroid Build Coastguard Worker 				v &= ~isZero | 0x80000000;
196*03ce13f7SAndroid Build Coastguard Worker 				v = sign | (isInfOrNan & 0x7F800000) | (~isInfOrNan & v);
197*03ce13f7SAndroid Build Coastguard Worker 				v |= isNaN & 0x400000;
198*03ce13f7SAndroid Build Coastguard Worker 			}
199*03ce13f7SAndroid Build Coastguard Worker 			break;
200*03ce13f7SAndroid Build Coastguard Worker 		default:
201*03ce13f7SAndroid Build Coastguard Worker 			UNREACHABLE("EvalSpecConstantUnaryOp op: %s", OpcodeName(opcode));
202*03ce13f7SAndroid Build Coastguard Worker 		}
203*03ce13f7SAndroid Build Coastguard Worker 	}
204*03ce13f7SAndroid Build Coastguard Worker }
205*03ce13f7SAndroid Build Coastguard Worker 
EvalSpecConstantBinaryOp(InsnIterator insn)206*03ce13f7SAndroid Build Coastguard Worker void Spirv::EvalSpecConstantBinaryOp(InsnIterator insn)
207*03ce13f7SAndroid Build Coastguard Worker {
208*03ce13f7SAndroid Build Coastguard Worker 	auto &result = CreateConstant(insn);
209*03ce13f7SAndroid Build Coastguard Worker 
210*03ce13f7SAndroid Build Coastguard Worker 	auto opcode = static_cast<spv::Op>(insn.word(3));
211*03ce13f7SAndroid Build Coastguard Worker 	const auto &lhs = getObject(insn.word(4));
212*03ce13f7SAndroid Build Coastguard Worker 	const auto &rhs = getObject(insn.word(5));
213*03ce13f7SAndroid Build Coastguard Worker 	auto size = getType(lhs).componentCount;
214*03ce13f7SAndroid Build Coastguard Worker 
215*03ce13f7SAndroid Build Coastguard Worker 	for(auto i = 0u; i < size; i++)
216*03ce13f7SAndroid Build Coastguard Worker 	{
217*03ce13f7SAndroid Build Coastguard Worker 		auto &v = result.constantValue[i];
218*03ce13f7SAndroid Build Coastguard Worker 		auto l = lhs.constantValue[i];
219*03ce13f7SAndroid Build Coastguard Worker 		auto r = rhs.constantValue[i];
220*03ce13f7SAndroid Build Coastguard Worker 
221*03ce13f7SAndroid Build Coastguard Worker 		switch(opcode)
222*03ce13f7SAndroid Build Coastguard Worker 		{
223*03ce13f7SAndroid Build Coastguard Worker 		case spv::OpIAdd:
224*03ce13f7SAndroid Build Coastguard Worker 			v = l + r;
225*03ce13f7SAndroid Build Coastguard Worker 			break;
226*03ce13f7SAndroid Build Coastguard Worker 		case spv::OpISub:
227*03ce13f7SAndroid Build Coastguard Worker 			v = l - r;
228*03ce13f7SAndroid Build Coastguard Worker 			break;
229*03ce13f7SAndroid Build Coastguard Worker 		case spv::OpIMul:
230*03ce13f7SAndroid Build Coastguard Worker 			v = l * r;
231*03ce13f7SAndroid Build Coastguard Worker 			break;
232*03ce13f7SAndroid Build Coastguard Worker 		case spv::OpUDiv:
233*03ce13f7SAndroid Build Coastguard Worker 			v = (r == 0) ? 0 : l / r;
234*03ce13f7SAndroid Build Coastguard Worker 			break;
235*03ce13f7SAndroid Build Coastguard Worker 		case spv::OpUMod:
236*03ce13f7SAndroid Build Coastguard Worker 			v = (r == 0) ? 0 : l % r;
237*03ce13f7SAndroid Build Coastguard Worker 			break;
238*03ce13f7SAndroid Build Coastguard Worker 		case spv::OpSDiv:
239*03ce13f7SAndroid Build Coastguard Worker 			if(r == 0) r = UINT32_MAX;
240*03ce13f7SAndroid Build Coastguard Worker 			if(l == static_cast<uint32_t>(INT32_MIN)) l = UINT32_MAX;
241*03ce13f7SAndroid Build Coastguard Worker 			v = static_cast<int32_t>(l) / static_cast<int32_t>(r);
242*03ce13f7SAndroid Build Coastguard Worker 			break;
243*03ce13f7SAndroid Build Coastguard Worker 		case spv::OpSRem:
244*03ce13f7SAndroid Build Coastguard Worker 			if(r == 0) r = UINT32_MAX;
245*03ce13f7SAndroid Build Coastguard Worker 			if(l == static_cast<uint32_t>(INT32_MIN)) l = UINT32_MAX;
246*03ce13f7SAndroid Build Coastguard Worker 			v = static_cast<int32_t>(l) % static_cast<int32_t>(r);
247*03ce13f7SAndroid Build Coastguard Worker 			break;
248*03ce13f7SAndroid Build Coastguard Worker 		case spv::OpSMod:
249*03ce13f7SAndroid Build Coastguard Worker 			if(r == 0) r = UINT32_MAX;
250*03ce13f7SAndroid Build Coastguard Worker 			if(l == static_cast<uint32_t>(INT32_MIN)) l = UINT32_MAX;
251*03ce13f7SAndroid Build Coastguard Worker 			// Test if a signed-multiply would be negative.
252*03ce13f7SAndroid Build Coastguard Worker 			v = static_cast<int32_t>(l) % static_cast<int32_t>(r);
253*03ce13f7SAndroid Build Coastguard Worker 			if((v & 0x80000000) != (r & 0x80000000))
254*03ce13f7SAndroid Build Coastguard Worker 				v += r;
255*03ce13f7SAndroid Build Coastguard Worker 			break;
256*03ce13f7SAndroid Build Coastguard Worker 		case spv::OpShiftRightLogical:
257*03ce13f7SAndroid Build Coastguard Worker 			v = l >> r;
258*03ce13f7SAndroid Build Coastguard Worker 			break;
259*03ce13f7SAndroid Build Coastguard Worker 		case spv::OpShiftRightArithmetic:
260*03ce13f7SAndroid Build Coastguard Worker 			v = static_cast<int32_t>(l) >> r;
261*03ce13f7SAndroid Build Coastguard Worker 			break;
262*03ce13f7SAndroid Build Coastguard Worker 		case spv::OpShiftLeftLogical:
263*03ce13f7SAndroid Build Coastguard Worker 			v = l << r;
264*03ce13f7SAndroid Build Coastguard Worker 			break;
265*03ce13f7SAndroid Build Coastguard Worker 		case spv::OpBitwiseOr:
266*03ce13f7SAndroid Build Coastguard Worker 		case spv::OpLogicalOr:
267*03ce13f7SAndroid Build Coastguard Worker 			v = l | r;
268*03ce13f7SAndroid Build Coastguard Worker 			break;
269*03ce13f7SAndroid Build Coastguard Worker 		case spv::OpBitwiseAnd:
270*03ce13f7SAndroid Build Coastguard Worker 		case spv::OpLogicalAnd:
271*03ce13f7SAndroid Build Coastguard Worker 			v = l & r;
272*03ce13f7SAndroid Build Coastguard Worker 			break;
273*03ce13f7SAndroid Build Coastguard Worker 		case spv::OpBitwiseXor:
274*03ce13f7SAndroid Build Coastguard Worker 			v = l ^ r;
275*03ce13f7SAndroid Build Coastguard Worker 			break;
276*03ce13f7SAndroid Build Coastguard Worker 		case spv::OpLogicalEqual:
277*03ce13f7SAndroid Build Coastguard Worker 		case spv::OpIEqual:
278*03ce13f7SAndroid Build Coastguard Worker 			v = (l == r) ? ~0u : 0u;
279*03ce13f7SAndroid Build Coastguard Worker 			break;
280*03ce13f7SAndroid Build Coastguard Worker 		case spv::OpLogicalNotEqual:
281*03ce13f7SAndroid Build Coastguard Worker 		case spv::OpINotEqual:
282*03ce13f7SAndroid Build Coastguard Worker 			v = (l != r) ? ~0u : 0u;
283*03ce13f7SAndroid Build Coastguard Worker 			break;
284*03ce13f7SAndroid Build Coastguard Worker 		case spv::OpULessThan:
285*03ce13f7SAndroid Build Coastguard Worker 			v = l < r ? ~0u : 0u;
286*03ce13f7SAndroid Build Coastguard Worker 			break;
287*03ce13f7SAndroid Build Coastguard Worker 		case spv::OpSLessThan:
288*03ce13f7SAndroid Build Coastguard Worker 			v = static_cast<int32_t>(l) < static_cast<int32_t>(r) ? ~0u : 0u;
289*03ce13f7SAndroid Build Coastguard Worker 			break;
290*03ce13f7SAndroid Build Coastguard Worker 		case spv::OpUGreaterThan:
291*03ce13f7SAndroid Build Coastguard Worker 			v = l > r ? ~0u : 0u;
292*03ce13f7SAndroid Build Coastguard Worker 			break;
293*03ce13f7SAndroid Build Coastguard Worker 		case spv::OpSGreaterThan:
294*03ce13f7SAndroid Build Coastguard Worker 			v = static_cast<int32_t>(l) > static_cast<int32_t>(r) ? ~0u : 0u;
295*03ce13f7SAndroid Build Coastguard Worker 			break;
296*03ce13f7SAndroid Build Coastguard Worker 		case spv::OpULessThanEqual:
297*03ce13f7SAndroid Build Coastguard Worker 			v = l <= r ? ~0u : 0u;
298*03ce13f7SAndroid Build Coastguard Worker 			break;
299*03ce13f7SAndroid Build Coastguard Worker 		case spv::OpSLessThanEqual:
300*03ce13f7SAndroid Build Coastguard Worker 			v = static_cast<int32_t>(l) <= static_cast<int32_t>(r) ? ~0u : 0u;
301*03ce13f7SAndroid Build Coastguard Worker 			break;
302*03ce13f7SAndroid Build Coastguard Worker 		case spv::OpUGreaterThanEqual:
303*03ce13f7SAndroid Build Coastguard Worker 			v = l >= r ? ~0u : 0u;
304*03ce13f7SAndroid Build Coastguard Worker 			break;
305*03ce13f7SAndroid Build Coastguard Worker 		case spv::OpSGreaterThanEqual:
306*03ce13f7SAndroid Build Coastguard Worker 			v = static_cast<int32_t>(l) >= static_cast<int32_t>(r) ? ~0u : 0u;
307*03ce13f7SAndroid Build Coastguard Worker 			break;
308*03ce13f7SAndroid Build Coastguard Worker 		default:
309*03ce13f7SAndroid Build Coastguard Worker 			UNREACHABLE("EvalSpecConstantBinaryOp op: %s", OpcodeName(opcode));
310*03ce13f7SAndroid Build Coastguard Worker 		}
311*03ce13f7SAndroid Build Coastguard Worker 	}
312*03ce13f7SAndroid Build Coastguard Worker }
313*03ce13f7SAndroid Build Coastguard Worker 
314*03ce13f7SAndroid Build Coastguard Worker }  // namespace sw