@@ -40,6 +40,25 @@ class ArithConstantOpConversionPattern
40
40
}
41
41
};
42
42
43
+ // / Get the signed or unsigned type corresponding to \p ty.
44
+ Type adaptIntegralTypeSignedness (Type ty, bool needsUnsigned) {
45
+ if (isa<IntegerType>(ty)) {
46
+ if (ty.isUnsignedInteger () != needsUnsigned) {
47
+ auto signedness = needsUnsigned
48
+ ? IntegerType::SignednessSemantics::Unsigned
49
+ : IntegerType::SignednessSemantics::Signed;
50
+ return IntegerType::get (ty.getContext (), ty.getIntOrFloatBitWidth (),
51
+ signedness);
52
+ }
53
+ }
54
+ return ty;
55
+ }
56
+
57
+ // / Insert a cast operation to type \p ty if \p val does not have this type.
58
+ Value adaptValueType (Value val, ConversionPatternRewriter &rewriter, Type ty) {
59
+ return rewriter.createOrFold <emitc::CastOp>(val.getLoc (), ty, val);
60
+ }
61
+
43
62
class CmpIOpConversion : public OpConversionPattern <arith::CmpIOp> {
44
63
public:
45
64
using OpConversionPattern::OpConversionPattern;
@@ -265,6 +284,46 @@ class IntegerOpConversion final : public OpConversionPattern<ArithOp> {
265
284
}
266
285
};
267
286
287
+ template <typename ArithOp, typename EmitCOp>
288
+ class BitwiseOpConversion : public OpConversionPattern <ArithOp> {
289
+ public:
290
+ using OpConversionPattern<ArithOp>::OpConversionPattern;
291
+
292
+ LogicalResult
293
+ matchAndRewrite (ArithOp op, typename ArithOp::Adaptor adaptor,
294
+ ConversionPatternRewriter &rewriter) const override {
295
+
296
+ Type type = this ->getTypeConverter ()->convertType (op.getType ());
297
+ if (!isa_and_nonnull<IntegerType>(type)) {
298
+ return rewriter.notifyMatchFailure (
299
+ op,
300
+ " expected integer type, vector/tensor support not yet implemented" );
301
+ }
302
+
303
+ // Bitwise ops can be performed directly on booleans
304
+ if (type.isInteger (1 )) {
305
+ rewriter.replaceOpWithNewOp <EmitCOp>(op, type, adaptor.getLhs (),
306
+ adaptor.getRhs ());
307
+ return success ();
308
+ }
309
+
310
+ // Bitwise ops are defined by the C standard on unsigned operands.
311
+ Type arithmeticType =
312
+ adaptIntegralTypeSignedness (type, /* needsUnsigned=*/ true );
313
+
314
+ Value lhs = adaptValueType (adaptor.getLhs (), rewriter, arithmeticType);
315
+ Value rhs = adaptValueType (adaptor.getRhs (), rewriter, arithmeticType);
316
+
317
+ Value arithmeticResult = rewriter.template create <EmitCOp>(
318
+ op.getLoc (), arithmeticType, lhs, rhs);
319
+
320
+ Value result = adaptValueType (arithmeticResult, rewriter, type);
321
+
322
+ rewriter.replaceOp (op, result);
323
+ return success ();
324
+ }
325
+ };
326
+
268
327
class SelectOpConversion : public OpConversionPattern <arith::SelectOp> {
269
328
public:
270
329
using OpConversionPattern<arith::SelectOp>::OpConversionPattern;
@@ -401,6 +460,9 @@ void mlir::populateArithToEmitCPatterns(TypeConverter &typeConverter,
401
460
IntegerOpConversion<arith::AddIOp, emitc::AddOp>,
402
461
IntegerOpConversion<arith::MulIOp, emitc::MulOp>,
403
462
IntegerOpConversion<arith::SubIOp, emitc::SubOp>,
463
+ BitwiseOpConversion<arith::AndIOp, emitc::BitwiseAndOp>,
464
+ BitwiseOpConversion<arith::OrIOp, emitc::BitwiseOrOp>,
465
+ BitwiseOpConversion<arith::XOrIOp, emitc::BitwiseXorOp>,
404
466
CmpIOpConversion,
405
467
SelectOpConversion,
406
468
// Truncation is guaranteed for unsigned types.
0 commit comments