Skip to content

Commit 6df3db4

Browse files
committed
[mlir][LLVM] Add nsw and nuw flags to trunc
This implementation is based on the one already existing for the binary operations. If the nuw keyword is present, and any of the truncated bits are non-zero, the result is a poison value. If the nsw keyword is present, and any of the truncated bits are not the same as the top bit of the truncation result, the result is a poison value.
1 parent 89aaf2c commit 6df3db4

File tree

4 files changed

+39
-1
lines changed

4 files changed

+39
-1
lines changed

mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,23 @@ class LLVM_CastOpWithNNegFlag<string mnemonic, string instName, Type type,
525525
}];
526526
}
527527

528+
class LLVM_CastOpWithOverflowFlag<string mnemonic, string instName, Type type,
529+
Type resultType, list<Trait> traits = []> :
530+
LLVM_Op<mnemonic, !listconcat([Pure], [DeclareOpInterfaceMethods<IntegerOverflowFlagsInterface>], traits)>,
531+
LLVM_Builder<"$res = builder.Create" # instName # "($arg, $_resultType, /*Name=*/\"\", op.hasNoUnsignedWrap(), op.hasNoSignedWrap());"> {
532+
let arguments = (ins type:$arg, EnumProperty<"IntegerOverflowFlags", "", "IntegerOverflowFlags::none">:$overflowFlags);
533+
let results = (outs resultType:$res);
534+
let builders = [LLVM_OneResultOpBuilder];
535+
let assemblyFormat = "$arg attr-dict `` custom<OverflowFlags>($overflowFlags) `:` type($arg) `to` type($res)";
536+
string llvmInstName = instName;
537+
string mlirBuilder = [{
538+
auto op = $_builder.create<$_qualCppClassName>(
539+
$_location, $_resultType, $arg);
540+
moduleImport.setIntegerOverflowFlags(inst, op);
541+
$res = op;
542+
}];
543+
}
544+
528545
def LLVM_BitcastOp : LLVM_CastOp<"bitcast", "BitCast", LLVM_AnyNonAggregate,
529546
LLVM_AnyNonAggregate, [DeclareOpInterfaceMethods<PromotableOpInterface>]> {
530547
let hasFolder = 1;
@@ -554,7 +571,7 @@ def LLVM_ZExtOp : LLVM_CastOpWithNNegFlag<"zext", "ZExt",
554571
let hasFolder = 1;
555572
let hasVerifier = 1;
556573
}
557-
def LLVM_TruncOp : LLVM_CastOp<"trunc", "Trunc",
574+
def LLVM_TruncOp : LLVM_CastOpWithOverflowFlag<"trunc", "Trunc",
558575
LLVM_ScalarOrVectorOf<AnySignlessInteger>,
559576
LLVM_ScalarOrVectorOf<AnySignlessInteger>>;
560577
def LLVM_SIToFPOp : LLVM_CastOp<"sitofp", "SIToFP",

mlir/test/Dialect/LLVMIR/roundtrip.mlir

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,23 @@ func.func @nneg_casts(%arg0: i32, %arg1: i64, %arg2: vector<4xi32>,
338338
llvm.return
339339
}
340340

341+
// CHECK-LABEL: @casts_overflow
342+
// CHECK-SAME: (%[[I32:.*]]: i32, %[[I64:.*]]: i64, %[[V4I32:.*]]: vector<4xi32>, %[[V4I64:.*]]: vector<4xi64>, %[[PTR:.*]]: !llvm.ptr)
343+
func.func @casts_overflow(%arg0: i32, %arg1: i64, %arg2: vector<4xi32>,
344+
%arg3: vector<4xi64>, %arg4: !llvm.ptr) {
345+
// CHECK: = llvm.trunc %[[I64]] overflow<nsw> : i64 to i56
346+
%0 = llvm.trunc %arg1 overflow<nsw> : i64 to i56
347+
// CHECK: = llvm.trunc %[[I64]] overflow<nuw> : i64 to i56
348+
%1 = llvm.trunc %arg1 overflow<nuw> : i64 to i56
349+
// CHECK: = llvm.trunc %[[I64]] overflow<nsw, nuw> : i64 to i56
350+
%2 = llvm.trunc %arg1 overflow<nsw, nuw> : i64 to i56
351+
// CHECK: = llvm.trunc %[[I64]] overflow<nsw, nuw> : i64 to i56
352+
%3 = llvm.trunc %arg1 overflow<nuw, nsw> : i64 to i56
353+
// CHECK: = llvm.trunc %[[V4I64]] overflow<nsw> : vector<4xi64> to vector<4xi56>
354+
%4 = llvm.trunc %arg3 overflow<nsw> : vector<4xi64> to vector<4xi56>
355+
llvm.return
356+
}
357+
341358
// CHECK-LABEL: @vect
342359
func.func @vect(%arg0: vector<4xf32>, %arg1: i32, %arg2: f32, %arg3: !llvm.vec<2 x ptr>) {
343360
// CHECK: = llvm.extractelement {{.*}} : vector<4xf32>

mlir/test/Target/LLVMIR/Import/nsw_nuw.ll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,7 @@ define void @intflag_inst(i64 %arg1, i64 %arg2) {
1010
%3 = mul nsw nuw i64 %arg1, %arg2
1111
; CHECK: llvm.shl %{{.*}}, %{{.*}} overflow<nsw, nuw> : i64
1212
%4 = shl nuw nsw i64 %arg1, %arg2
13+
; CHECK: llvm.trunc %{{.*}} overflow<nsw> : i64 to i32
14+
%5 = trunc nsw i64 %arg1 to i32
1315
ret void
1416
}

mlir/test/Target/LLVMIR/nsw_nuw.mlir

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,7 @@ llvm.func @intflags_func(%arg0: i64, %arg1: i64) {
1010
%2 = llvm.mul %arg0, %arg1 overflow <nsw, nuw> : i64
1111
// CHECK: %{{.*}} = shl nuw nsw i64 %{{.*}}, %{{.*}}
1212
%3 = llvm.shl %arg0, %arg1 overflow <nsw, nuw> : i64
13+
// CHECK: %{{.*}} = trunc nuw i64 %{{.*}} to i32
14+
%4 = llvm.trunc %arg1 overflow<nuw> : i64 to i32
1315
llvm.return
1416
}

0 commit comments

Comments
 (0)