@@ -40,6 +40,25 @@ class ArithConstantOpConversionPattern
4040 }
4141};
4242
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+
4362class CmpIOpConversion : public OpConversionPattern <arith::CmpIOp> {
4463public:
4564 using OpConversionPattern::OpConversionPattern;
@@ -265,6 +284,46 @@ class IntegerOpConversion final : public OpConversionPattern<ArithOp> {
265284 }
266285};
267286
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+
268327class SelectOpConversion : public OpConversionPattern <arith::SelectOp> {
269328public:
270329 using OpConversionPattern<arith::SelectOp>::OpConversionPattern;
@@ -401,6 +460,9 @@ void mlir::populateArithToEmitCPatterns(TypeConverter &typeConverter,
401460 IntegerOpConversion<arith::AddIOp, emitc::AddOp>,
402461 IntegerOpConversion<arith::MulIOp, emitc::MulOp>,
403462 IntegerOpConversion<arith::SubIOp, emitc::SubOp>,
463+ BitwiseOpConversion<arith::AndIOp, emitc::BitwiseAndOp>,
464+ BitwiseOpConversion<arith::OrIOp, emitc::BitwiseOrOp>,
465+ BitwiseOpConversion<arith::XOrIOp, emitc::BitwiseXorOp>,
404466 CmpIOpConversion,
405467 SelectOpConversion,
406468 // Truncation is guaranteed for unsigned types.
0 commit comments