diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td index dd0251eb6a285..81e9f69f15acf 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td @@ -525,6 +525,23 @@ class LLVM_CastOpWithNNegFlag traits = []> : + LLVM_Op], traits)>, + LLVM_Builder<"$res = builder.Create" # instName # "($arg, $_resultType, /*Name=*/\"\", op.hasNoUnsignedWrap(), op.hasNoSignedWrap());"> { + let arguments = (ins type:$arg, EnumProperty<"IntegerOverflowFlags", "", "IntegerOverflowFlags::none">:$overflowFlags); + let results = (outs resultType:$res); + let builders = [LLVM_OneResultOpBuilder]; + let assemblyFormat = "$arg `` custom($overflowFlags) attr-dict `:` type($arg) `to` type($res)"; + string llvmInstName = instName; + string mlirBuilder = [{ + auto op = $_builder.create<$_qualCppClassName>( + $_location, $_resultType, $arg); + moduleImport.setIntegerOverflowFlags(inst, op); + $res = op; + }]; +} + def LLVM_BitcastOp : LLVM_CastOp<"bitcast", "BitCast", LLVM_AnyNonAggregate, LLVM_AnyNonAggregate, [DeclareOpInterfaceMethods]> { let hasFolder = 1; @@ -554,7 +571,7 @@ def LLVM_ZExtOp : LLVM_CastOpWithNNegFlag<"zext", "ZExt", let hasFolder = 1; let hasVerifier = 1; } -def LLVM_TruncOp : LLVM_CastOp<"trunc", "Trunc", +def LLVM_TruncOp : LLVM_CastOpWithOverflowFlag<"trunc", "Trunc", LLVM_ScalarOrVectorOf, LLVM_ScalarOrVectorOf>; def LLVM_SIToFPOp : LLVM_CastOp<"sitofp", "SIToFP", diff --git a/mlir/test/Dialect/LLVMIR/roundtrip.mlir b/mlir/test/Dialect/LLVMIR/roundtrip.mlir index 193ab53e6e820..aa558bad2299c 100644 --- a/mlir/test/Dialect/LLVMIR/roundtrip.mlir +++ b/mlir/test/Dialect/LLVMIR/roundtrip.mlir @@ -338,6 +338,23 @@ func.func @nneg_casts(%arg0: i32, %arg1: i64, %arg2: vector<4xi32>, llvm.return } +// CHECK-LABEL: @casts_overflow +// CHECK-SAME: (%[[I32:.*]]: i32, %[[I64:.*]]: i64, %[[V4I32:.*]]: vector<4xi32>, %[[V4I64:.*]]: vector<4xi64>, %[[PTR:.*]]: !llvm.ptr) +func.func @casts_overflow(%arg0: i32, %arg1: i64, %arg2: vector<4xi32>, + %arg3: vector<4xi64>, %arg4: !llvm.ptr) { +// CHECK: = llvm.trunc %[[I64]] overflow : i64 to i56 + %0 = llvm.trunc %arg1 overflow : i64 to i56 +// CHECK: = llvm.trunc %[[I64]] overflow : i64 to i56 + %1 = llvm.trunc %arg1 overflow : i64 to i56 +// CHECK: = llvm.trunc %[[I64]] overflow : i64 to i56 + %2 = llvm.trunc %arg1 overflow : i64 to i56 +// CHECK: = llvm.trunc %[[I64]] overflow : i64 to i56 + %3 = llvm.trunc %arg1 overflow : i64 to i56 +// CHECK: = llvm.trunc %[[V4I64]] overflow : vector<4xi64> to vector<4xi56> + %4 = llvm.trunc %arg3 overflow : vector<4xi64> to vector<4xi56> + llvm.return +} + // CHECK-LABEL: @vect func.func @vect(%arg0: vector<4xf32>, %arg1: i32, %arg2: f32, %arg3: !llvm.vec<2 x ptr>) { // CHECK: = llvm.extractelement {{.*}} : vector<4xf32> diff --git a/mlir/test/Target/LLVMIR/Import/nsw_nuw.ll b/mlir/test/Target/LLVMIR/Import/nsw_nuw.ll index d08098a5e5dfe..4af799da36dc0 100644 --- a/mlir/test/Target/LLVMIR/Import/nsw_nuw.ll +++ b/mlir/test/Target/LLVMIR/Import/nsw_nuw.ll @@ -10,5 +10,7 @@ define void @intflag_inst(i64 %arg1, i64 %arg2) { %3 = mul nsw nuw i64 %arg1, %arg2 ; CHECK: llvm.shl %{{.*}}, %{{.*}} overflow : i64 %4 = shl nuw nsw i64 %arg1, %arg2 + ; CHECK: llvm.trunc %{{.*}} overflow : i64 to i32 + %5 = trunc nsw i64 %arg1 to i32 ret void } diff --git a/mlir/test/Target/LLVMIR/nsw_nuw.mlir b/mlir/test/Target/LLVMIR/nsw_nuw.mlir index 6843c2ef0299c..584aa05a04f7c 100644 --- a/mlir/test/Target/LLVMIR/nsw_nuw.mlir +++ b/mlir/test/Target/LLVMIR/nsw_nuw.mlir @@ -10,5 +10,7 @@ llvm.func @intflags_func(%arg0: i64, %arg1: i64) { %2 = llvm.mul %arg0, %arg1 overflow : i64 // CHECK: %{{.*}} = shl nuw nsw i64 %{{.*}}, %{{.*}} %3 = llvm.shl %arg0, %arg1 overflow : i64 + // CHECK: %{{.*}} = trunc nuw i64 %{{.*}} to i32 + %4 = llvm.trunc %arg1 overflow : i64 to i32 llvm.return }