Skip to content

Commit bf601ba

Browse files
authored
[mlir][LLVM] Add nsw and nuw flags to trunc (#115509)
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 e19d740 commit bf601ba

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 `` custom<OverflowFlags>($overflowFlags) attr-dict `:` 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)