@@ -118,4 +118,101 @@ void legalizeBinaryOp(IRInst* inst)
118
118
}
119
119
}
120
120
121
+ void legalizeLogicalAndOr (IRInst* inst)
122
+ {
123
+ switch (inst->getOp ())
124
+ {
125
+ case kIROp_And :
126
+ case kIROp_Or :
127
+ {
128
+ IRBuilder builder (inst);
129
+ builder.setInsertBefore (inst);
130
+
131
+ // Logical-AND and logical-OR takes boolean types as its operands.
132
+ // If they are not, legalize them by casting to boolean type.
133
+ //
134
+ SLANG_ASSERT (inst->getOperandCount () == 2 );
135
+ for (UInt i = 0 ; i < 2 ; i++)
136
+ {
137
+ auto operand = inst->getOperand (i);
138
+ auto operandDataType = operand->getDataType ();
139
+
140
+ if (auto vecType = as<IRVectorType>(operandDataType))
141
+ {
142
+ if (!as<IRBoolType>(vecType->getElementType ()))
143
+ {
144
+ // Cast operand to vector<bool,N>
145
+ auto elemCount = vecType->getElementCount ();
146
+ auto vb = builder.getVectorType (builder.getBoolType (), elemCount);
147
+ auto v = builder.emitCast (vb, operand);
148
+ builder.replaceOperand (inst->getOperands () + i, v);
149
+ }
150
+ }
151
+ else if (!as<IRBoolType>(operandDataType))
152
+ {
153
+ // Cast operand to bool
154
+ auto s = builder.emitCast (builder.getBoolType (), operand);
155
+ builder.replaceOperand (inst->getOperands () + i, s);
156
+ }
157
+ }
158
+
159
+ // Legalize the return type; mostly for SPIRV.
160
+ // The return type of OpLogicalOr must be boolean type.
161
+ // If not, we need to recreate the instruction with boolean return type.
162
+ // Then, we have to cast it back to the original type so that other instrucitons that
163
+ // use have the matching types.
164
+ //
165
+ auto dataType = inst->getDataType ();
166
+ auto lhs = inst->getOperand (0 );
167
+ auto rhs = inst->getOperand (1 );
168
+ IRInst* newInst = nullptr ;
169
+
170
+ if (auto vecType = as<IRVectorType>(dataType))
171
+ {
172
+ if (!as<IRBoolType>(vecType->getElementType ()))
173
+ {
174
+ // Return type should be vector<bool,N>
175
+ auto elemCount = vecType->getElementCount ();
176
+ auto vb = builder.getVectorType (builder.getBoolType (), elemCount);
177
+
178
+ if (inst->getOp () == kIROp_And )
179
+ {
180
+ newInst = builder.emitAnd (vb, lhs, rhs);
181
+ }
182
+ else
183
+ {
184
+ newInst = builder.emitOr (vb, lhs, rhs);
185
+ }
186
+ newInst = builder.emitCast (dataType, newInst);
187
+ }
188
+ }
189
+ else if (!as<IRBoolType>(dataType))
190
+ {
191
+ // Return type should be bool
192
+ if (inst->getOp () == kIROp_And )
193
+ {
194
+ newInst = builder.emitAnd (builder.getBoolType (), lhs, rhs);
195
+ }
196
+ else
197
+ {
198
+ newInst = builder.emitOr (builder.getBoolType (), lhs, rhs);
199
+ }
200
+ newInst = builder.emitCast (dataType, newInst);
201
+ }
202
+
203
+ if (newInst && inst != newInst)
204
+ {
205
+ inst->replaceUsesWith (newInst);
206
+ inst->removeAndDeallocate ();
207
+ }
208
+ }
209
+ break ;
210
+ }
211
+
212
+ for (auto child : inst->getModifiableChildren ())
213
+ {
214
+ legalizeLogicalAndOr (child);
215
+ }
216
+ }
217
+
121
218
} // namespace Slang
0 commit comments