// RUN: mlir-opt -split-input-file -convert-arith-to-emitc %s | FileCheck %s
// CHECK-LABEL: arith_constants
func.func @arith_constants() {
// CHECK: emitc.constant
// CHECK-SAME: value = 0
// CHECK-SAME: () -> !emitc.size_t
%c_index = arith.constant 0 : index
// CHECK: emitc.constant
// CHECK-SAME: value = 0 : i32
%c_signless_int_32 = arith.constant 0 : i32
// CHECK: emitc.constant
// CHECK-SAME: value = 0.{{0+}}e+00 : f32
%c_float_32 = arith.constant 0.0 : f32
// CHECK: emitc.constant
// CHECK-SAME: value = dense<0> : tensor<i32>
%c_tensor_single_value = arith.constant dense<0> : tensor<i32>
// CHECK: emitc.constant
// CHECK-SAME: value{{.*}}[1, 2], [-3, 9], [0, 0], [2, -1]{{.*}}tensor<4x2xi64>
%c_tensor_value = arith.constant dense<[[1, 2], [-3, 9], [0, 0], [2, -1]]> : tensor<4x2xi64>
return
}
// -----
func.func @arith_ops(%arg0: f32, %arg1: f32) {
// CHECK: [[V0:[^ ]*]] = emitc.add %arg0, %arg1 : (f32, f32) -> f32
%0 = arith.addf %arg0, %arg1 : f32
// CHECK: [[V1:[^ ]*]] = emitc.div %arg0, %arg1 : (f32, f32) -> f32
%1 = arith.divf %arg0, %arg1 : f32
// CHECK: [[V2:[^ ]*]] = emitc.mul %arg0, %arg1 : (f32, f32) -> f32
%2 = arith.mulf %arg0, %arg1 : f32
// CHECK: [[V3:[^ ]*]] = emitc.sub %arg0, %arg1 : (f32, f32) -> f32
%3 = arith.subf %arg0, %arg1 : f32
return
}
// -----
// CHECK-LABEL: arith_integer_ops
func.func @arith_integer_ops(%arg0: i32, %arg1: i32) {
// CHECK: %[[C1:[^ ]*]] = emitc.cast %arg0 : i32 to ui32
// CHECK: %[[C2:[^ ]*]] = emitc.cast %arg1 : i32 to ui32
// CHECK: %[[ADD:[^ ]*]] = emitc.add %[[C1]], %[[C2]] : (ui32, ui32) -> ui32
// CHECK: %[[C3:[^ ]*]] = emitc.cast %[[ADD]] : ui32 to i32
%0 = arith.addi %arg0, %arg1 : i32
// CHECK: %[[C1:[^ ]*]] = emitc.cast %arg0 : i32 to ui32
// CHECK: %[[C2:[^ ]*]] = emitc.cast %arg1 : i32 to ui32
// CHECK: %[[SUB:[^ ]*]] = emitc.sub %[[C1]], %[[C2]] : (ui32, ui32) -> ui32
// CHECK: %[[C3:[^ ]*]] = emitc.cast %[[SUB]] : ui32 to i32
%1 = arith.subi %arg0, %arg1 : i32
// CHECK: %[[C1:[^ ]*]] = emitc.cast %arg0 : i32 to ui32
// CHECK: %[[C2:[^ ]*]] = emitc.cast %arg1 : i32 to ui32
// CHECK: %[[MUL:[^ ]*]] = emitc.mul %[[C1]], %[[C2]] : (ui32, ui32) -> ui32
// CHECK: %[[C3:[^ ]*]] = emitc.cast %[[MUL]] : ui32 to i32
%2 = arith.muli %arg0, %arg1 : i32
return
}
// -----
// CHECK-LABEL: arith_integer_ops_signed_nsw
func.func @arith_integer_ops_signed_nsw(%arg0: i32, %arg1: i32) {
// CHECK: emitc.add %arg0, %arg1 : (i32, i32) -> i32
%0 = arith.addi %arg0, %arg1 overflow<nsw> : i32
// CHECK: emitc.sub %arg0, %arg1 : (i32, i32) -> i32
%1 = arith.subi %arg0, %arg1 overflow<nsw> : i32
// CHECK: emitc.mul %arg0, %arg1 : (i32, i32) -> i32
%2 = arith.muli %arg0, %arg1 overflow<nsw> : i32
return
}
// -----
// CHECK-LABEL: arith_index
func.func @arith_index(%arg0: i32, %arg1: i32) {
// CHECK: %[[CST0:.*]] = emitc.cast %{{.*}} : {{.*}} to !emitc.size_t
%cst0 = arith.index_cast %arg0 : i32 to index
// CHECK: %[[CST1:.*]] = emitc.cast %{{.*}} : {{.*}} to !emitc.size_t
%cst1 = arith.index_cast %arg1 : i32 to index
// CHECK: emitc.add %[[CST0]], %[[CST1]] : (!emitc.size_t, !emitc.size_t) -> !emitc.size_t
%0 = arith.addi %cst0, %cst1 : index
// CHECK: emitc.sub %[[CST0]], %[[CST1]] : (!emitc.size_t, !emitc.size_t) -> !emitc.size_t
%1 = arith.subi %cst0, %cst1 : index
// CHECK: emitc.mul %[[CST0]], %[[CST1]] : (!emitc.size_t, !emitc.size_t) -> !emitc.size_t
%2 = arith.muli %cst0, %cst1 : index
return
}
// -----
// CHECK-LABEL: arith_bitwise
// CHECK-SAME: %[[ARG0:.*]]: i32, %[[ARG1:.*]]: i32
func.func @arith_bitwise(%arg0: i32, %arg1: i32) {
// CHECK: %[[C1:[^ ]*]] = emitc.cast %[[ARG0]] : i32 to ui32
// CHECK: %[[C2:[^ ]*]] = emitc.cast %[[ARG1]] : i32 to ui32
// CHECK: %[[AND:[^ ]*]] = emitc.bitwise_and %[[C1]], %[[C2]] : (ui32, ui32) -> ui32
// CHECK: %[[C3:[^ ]*]] = emitc.cast %[[AND]] : ui32 to i32
%0 = arith.andi %arg0, %arg1 : i32
// CHECK: %[[C1:[^ ]*]] = emitc.cast %[[ARG0]] : i32 to ui32
// CHECK: %[[C2:[^ ]*]] = emitc.cast %[[ARG1]] : i32 to ui32
// CHECK: %[[OR:[^ ]*]] = emitc.bitwise_or %[[C1]], %[[C2]] : (ui32, ui32) -> ui32
// CHECK: %[[C3:[^ ]*]] = emitc.cast %[[OR]] : ui32 to i32
%1 = arith.ori %arg0, %arg1 : i32
// CHECK: %[[C1:[^ ]*]] = emitc.cast %[[ARG0]] : i32 to ui32
// CHECK: %[[C2:[^ ]*]] = emitc.cast %[[ARG1]] : i32 to ui32
// CHECK: %[[XOR:[^ ]*]] = emitc.bitwise_xor %[[C1]], %[[C2]] : (ui32, ui32) -> ui32
// CHECK: %[[C3:[^ ]*]] = emitc.cast %[[XOR]] : ui32 to i32
%2 = arith.xori %arg0, %arg1 : i32
return
}
// -----
// CHECK-LABEL: arith_bitwise_bool
// CHECK-SAME: %[[ARG0:.*]]: i1, %[[ARG1:.*]]: i1
func.func @arith_bitwise_bool(%arg0: i1, %arg1: i1) {
// CHECK: %[[AND:[^ ]*]] = emitc.bitwise_and %[[ARG0]], %[[ARG1]] : (i1, i1) -> i1
%0 = arith.andi %arg0, %arg1 : i1
// CHECK: %[[OR:[^ ]*]] = emitc.bitwise_or %[[ARG0]], %[[ARG1]] : (i1, i1) -> i1
%1 = arith.ori %arg0, %arg1 : i1
// CHECK: %[[xor:[^ ]*]] = emitc.bitwise_xor %[[ARG0]], %[[ARG1]] : (i1, i1) -> i1
%2 = arith.xori %arg0, %arg1 : i1
return
}
// -----
// CHECK-LABEL: arith_signed_integer_div_rem
func.func @arith_signed_integer_div_rem(%arg0: i32, %arg1: i32) {
// CHECK: emitc.div %arg0, %arg1 : (i32, i32) -> i32
%0 = arith.divsi %arg0, %arg1 : i32
// CHECK: emitc.rem %arg0, %arg1 : (i32, i32) -> i32
%1 = arith.remsi %arg0, %arg1 : i32
return
}
// -----
// CHECK-LABEL: arith_shift_left
// CHECK-SAME: %[[ARG0:.*]]: i32, %[[ARG1:.*]]: i32
func.func @arith_shift_left(%arg0: i32, %arg1: i32) {
// CHECK-DAG: %[[C1:[^ ]*]] = emitc.cast %[[ARG0]] : i32 to ui32
// CHECK-DAG: %[[C2:[^ ]*]] = emitc.cast %[[ARG1]] : i32 to ui32
// CHECK-DAG: %[[SizeConstant:[^ ]*]] = "emitc.constant"{{.*}}value = 32
// CHECK-DAG: %[[CmpNoExcess:[^ ]*]] = emitc.cmp lt, %[[C2]], %[[SizeConstant]] : (ui32, ui32) -> i1
// CHECK-DAG: %[[Zero:[^ ]*]] = "emitc.constant"{{.*}}value = 0
// CHECK: %[[ShiftRes:[^ ]*]] = emitc.expression : ui32
// CHECK: %[[SHL:[^ ]*]] = emitc.bitwise_left_shift %[[C1]], %[[C2]] : (ui32, ui32) -> ui32
// CHECK: %[[Ternary:[^ ]*]] = emitc.conditional %[[CmpNoExcess]], %[[SHL]], %[[Zero]] : ui32
// CHECK: emitc.yield %[[Ternary]] : ui32
// CHECK: emitc.cast %[[ShiftRes]] : ui32 to i32
%1 = arith.shli %arg0, %arg1 : i32
return
}
// -----
// CHECK-LABEL: arith_shift_right
// CHECK-SAME: %[[ARG0:.*]]: i32, %[[ARG1:.*]]: i32
func.func @arith_shift_right(%arg0: i32, %arg1: i32) {
// CHECK-DAG: %[[C1:[^ ]*]] = emitc.cast %[[ARG0]] : i32 to ui32
// CHECK-DAG: %[[C2:[^ ]*]] = emitc.cast %[[ARG1]] : i32 to ui32
// CHECK-DAG: %[[SizeConstant:[^ ]*]] = "emitc.constant"{{.*}}value = 32{{.*}}ui32
// CHECK-DAG: %[[CmpNoExcess:[^ ]*]] = emitc.cmp lt, %[[C2]], %[[SizeConstant]] : (ui32, ui32) -> i1
// CHECK-DAG: %[[Zero:[^ ]*]] = "emitc.constant"{{.*}}value = 0{{.*}}ui32
// CHECK: %[[ShiftRes:[^ ]*]] = emitc.expression : ui32
// CHECK: %[[SHR:[^ ]*]] = emitc.bitwise_right_shift %[[C1]], %[[C2]] : (ui32, ui32) -> ui32
// CHECK: %[[Ternary:[^ ]*]] = emitc.conditional %[[CmpNoExcess]], %[[SHR]], %[[Zero]] : ui32
// CHECK: emitc.yield %[[Ternary]] : ui32
// CHECK: emitc.cast %[[ShiftRes]] : ui32 to i32
%2 = arith.shrui %arg0, %arg1 : i32
// CHECK-DAG: %[[SC2:[^ ]*]] = emitc.cast %[[ARG1]] : i32 to ui32
// CHECK-DAG: %[[SSizeConstant:[^ ]*]] = "emitc.constant"{{.*}}value = 32{{.*}}ui32
// CHECK-DAG: %[[SCmpNoExcess:[^ ]*]] = emitc.cmp lt, %[[SC2]], %[[SSizeConstant]] : (ui32, ui32) -> i1
// CHECK-DAG: %[[SZero:[^ ]*]] = "emitc.constant"{{.*}}value = 0{{.*}}i32
// CHECK: %[[SShiftRes:[^ ]*]] = emitc.expression : i32
// CHECK: %[[SHRSI:[^ ]*]] = emitc.bitwise_right_shift %[[ARG0]], %[[SC2]] : (i32, ui32) -> i32
// CHECK: %[[STernary:[^ ]*]] = emitc.conditional %[[SCmpNoExcess]], %[[SHRSI]], %[[SZero]] : i32
// CHECK: emitc.yield %[[STernary]] : i32
%3 = arith.shrsi %arg0, %arg1 : i32
return
}
// -----
// CHECK-LABEL: arith_shift_left_index
// CHECK-SAME: %[[AMOUNT:.*]]: i32
func.func @arith_shift_left_index(%amount: i32) {
%cst0 = "arith.constant"() {value = 42 : index} : () -> (index)
%cast1 = arith.index_cast %amount : i32 to index
// CHECK-DAG: %[[C1:[^ ]*]] = "emitc.constant"(){{.*}}value = 42{{.*}}!emitc.size_t
// CHECK-DAG: %[[Cast1:[^ ]*]] = emitc.cast %[[AMOUNT]] : i32 to !emitc.ptrdiff_t
// CHECK-DAG: %[[AmountIdx:[^ ]*]] = emitc.cast %[[Cast1]] : !emitc.ptrdiff_t to !emitc.size_t
// CHECK-DAG: %[[Byte:[^ ]*]] = "emitc.constant"{{.*}}value = 8{{.*}}index
// CHECK-DAG: %[[SizeOf:[^ ]*]] = emitc.call_opaque "sizeof"(%[[Byte]]) : (!emitc.size_t) -> !emitc.size_t
// CHECK-DAG: %[[SizeConstant:[^ ]*]] = emitc.mul %[[Byte]], %[[SizeOf]] : (!emitc.size_t, !emitc.size_t) -> !emitc.size_t
// CHECK-DAG: %[[CmpNoExcess:[^ ]*]] = emitc.cmp lt, %[[AmountIdx]], %[[SizeConstant]] : (!emitc.size_t, !emitc.size_t) -> i1
// CHECK-DAG: %[[Zero:[^ ]*]] = "emitc.constant"{{.*}}value = 0
// CHECK: %[[ShiftRes:[^ ]*]] = emitc.expression : !emitc.size_t
// CHECK: %[[SHL:[^ ]*]] = emitc.bitwise_left_shift %[[C1]], %[[AmountIdx]] : (!emitc.size_t, !emitc.size_t) -> !emitc.size_t
// CHECK: %[[Ternary:[^ ]*]] = emitc.conditional %[[CmpNoExcess]], %[[SHL]], %[[Zero]] : !emitc.size_t
// CHECK: emitc.yield %[[Ternary]] : !emitc.size_t
%1 = arith.shli %cst0, %cast1 : index
return
}
// -----
// CHECK-LABEL: arith_shift_right_index
// CHECK-SAME: %[[AMOUNT:.*]]: i32
func.func @arith_shift_right_index(%amount: i32) {
// CHECK-DAG: %[[C1:[^ ]*]] = "emitc.constant"(){{.*}}value = 42{{.*}}!emitc.size_t
// CHECK-DAG: %[[Cast1:[^ ]*]] = emitc.cast %[[AMOUNT]] : i32 to !emitc.ptrdiff_t
// CHECK-DAG: %[[AmountIdx:[^ ]*]] = emitc.cast %[[Cast1]] : !emitc.ptrdiff_t to !emitc.size_t
%arg0 = "arith.constant"() {value = 42 : index} : () -> (index)
%arg1 = arith.index_cast %amount : i32 to index
// CHECK-DAG: %[[Byte:[^ ]*]] = "emitc.constant"{{.*}}value = 8{{.*}}index
// CHECK-DAG: %[[SizeOf:[^ ]*]] = emitc.call_opaque "sizeof"(%[[Byte]]) : (!emitc.size_t) -> !emitc.size_t
// CHECK-DAG: %[[SizeConstant:[^ ]*]] = emitc.mul %[[Byte]], %[[SizeOf]] : (!emitc.size_t, !emitc.size_t) -> !emitc.size_t
// CHECK-DAG: %[[CmpNoExcess:[^ ]*]] = emitc.cmp lt, %[[AmountIdx]], %[[SizeConstant]] : (!emitc.size_t, !emitc.size_t) -> i1
// CHECK-DAG: %[[Zero:[^ ]*]] = "emitc.constant"{{.*}}value = 0{{.*}}!emitc.size_t
// CHECK: %[[ShiftRes:[^ ]*]] = emitc.expression : !emitc.size_t
// CHECK: %[[SHR:[^ ]*]] = emitc.bitwise_right_shift %[[C1]], %[[AmountIdx]] : (!emitc.size_t, !emitc.size_t) -> !emitc.size_t
// CHECK: %[[Ternary:[^ ]*]] = emitc.conditional %[[CmpNoExcess]], %[[SHR]], %[[Zero]] : !emitc.size_t
// CHECK: emitc.yield %[[Ternary]] : !emitc.size_t
%2 = arith.shrui %arg0, %arg1 : index
// CHECK-DAG: %[[SC1:[^ ]*]] = emitc.cast %[[C1]] : !emitc.size_t to !emitc.ptrdiff_t
// CHECK-DAG: %[[SByte:[^ ]*]] = "emitc.constant"{{.*}}value = 8{{.*}}index{{.*}}!emitc.size_t
// CHECK-DAG: %[[SSizeOf:[^ ]*]] = emitc.call_opaque "sizeof"(%[[SByte]]) : (!emitc.size_t) -> !emitc.size_t
// CHECK-DAG: %[[SSizeConstant:[^ ]*]] = emitc.mul %[[SByte]], %[[SSizeOf]] : (!emitc.size_t, !emitc.size_t) -> !emitc.size_t
// CHECK-DAG: %[[SCmpNoExcess:[^ ]*]] = emitc.cmp lt, %[[AmountIdx]], %[[SSizeConstant]] : (!emitc.size_t, !emitc.size_t) -> i1
// CHECK-DAG: %[[SZero:[^ ]*]] = "emitc.constant"{{.*}}value = 0{{.*}}!emitc.ptrdiff_t
// CHECK: %[[SShiftRes:[^ ]*]] = emitc.expression : !emitc.ptrdiff_t
// CHECK: %[[SHRSI:[^ ]*]] = emitc.bitwise_right_shift %[[SC1]], %[[AmountIdx]] : (!emitc.ptrdiff_t, !emitc.size_t) -> !emitc.ptrdiff_t
// CHECK: %[[STernary:[^ ]*]] = emitc.conditional %[[SCmpNoExcess]], %[[SHRSI]], %[[SZero]] : !emitc.ptrdiff_t
// CHECK: emitc.yield %[[STernary]] : !emitc.ptrdiff_t
// CHECK: emitc.cast %[[SShiftRes]] : !emitc.ptrdiff_t to !emitc.size_t
%3 = arith.shrsi %arg0, %arg1 : index
return
}
// -----
func.func @arith_select(%arg0: i1, %arg1: tensor<8xi32>, %arg2: tensor<8xi32>) -> () {
// CHECK: [[V0:[^ ]*]] = emitc.conditional %arg0, %arg1, %arg2 : tensor<8xi32>
%0 = arith.select %arg0, %arg1, %arg2 : i1, tensor<8xi32>
return
}
// -----
func.func @arith_cmpf_false(%arg0: f32, %arg1: f32) -> i1 {
// CHECK-LABEL: arith_cmpf_false
// CHECK-SAME: ([[Arg0:[^ ]*]]: f32, [[Arg1:[^ ]*]]: f32)
// CHECK-DAG: [[False:[^ ]*]] = "emitc.constant"() <{value = false}> : () -> i1
%false = arith.cmpf false, %arg0, %arg1 : f32
// CHECK: return [[False]]
return %false: i1
}
// -----
func.func @arith_cmpf_oeq(%arg0: f32, %arg1: f32) -> i1 {
// CHECK-LABEL: arith_cmpf_oeq
// CHECK-SAME: ([[Arg0:[^ ]*]]: f32, [[Arg1:[^ ]*]]: f32)
// CHECK-DAG: [[EQ:[^ ]*]] = emitc.cmp eq, [[Arg0]], [[Arg1]] : (f32, f32) -> i1
// CHECK-DAG: [[NotNaNArg0:[^ ]*]] = emitc.cmp eq, [[Arg0]], [[Arg0]] : (f32, f32) -> i1
// CHECK-DAG: [[NotNaNArg1:[^ ]*]] = emitc.cmp eq, [[Arg1]], [[Arg1]] : (f32, f32) -> i1
// CHECK-DAG: [[Ordered:[^ ]*]] = emitc.logical_and [[NotNaNArg0]], [[NotNaNArg1]] : i1, i1
// CHECK-DAG: [[OEQ:[^ ]*]] = emitc.logical_and [[Ordered]], [[EQ]] : i1, i1
%oeq = arith.cmpf oeq, %arg0, %arg1 : f32
// CHECK: return [[OEQ]]
return %oeq: i1
}
// -----
func.func @arith_cmpf_ogt(%arg0: f32, %arg1: f32) -> i1 {
// CHECK-LABEL: arith_cmpf_ogt
// CHECK-SAME: ([[Arg0:[^ ]*]]: f32, [[Arg1:[^ ]*]]: f32)
// CHECK-DAG: [[GT:[^ ]*]] = emitc.cmp gt, [[Arg0]], [[Arg1]] : (f32, f32) -> i1
// CHECK-DAG: [[NotNaNArg0:[^ ]*]] = emitc.cmp eq, [[Arg0]], [[Arg0]] : (f32, f32) -> i1
// CHECK-DAG: [[NotNaNArg1:[^ ]*]] = emitc.cmp eq, [[Arg1]], [[Arg1]] : (f32, f32) -> i1
// CHECK-DAG: [[Ordered:[^ ]*]] = emitc.logical_and [[NotNaNArg0]], [[NotNaNArg1]] : i1, i1
// CHECK-DAG: [[OGT:[^ ]*]] = emitc.logical_and [[Ordered]], [[GT]] : i1, i1
%ogt = arith.cmpf ogt, %arg0, %arg1 : f32
// CHECK: return [[OGT]]
return %ogt: i1
}
// -----
func.func @arith_cmpf_oge(%arg0: f32, %arg1: f32) -> i1 {
// CHECK-LABEL: arith_cmpf_oge
// CHECK-SAME: ([[Arg0:[^ ]*]]: f32, [[Arg1:[^ ]*]]: f32)
// CHECK-DAG: [[GE:[^ ]*]] = emitc.cmp ge, [[Arg0]], [[Arg1]] : (f32, f32) -> i1
// CHECK-DAG: [[NotNaNArg0:[^ ]*]] = emitc.cmp eq, [[Arg0]], [[Arg0]] : (f32, f32) -> i1
// CHECK-DAG: [[NotNaNArg1:[^ ]*]] = emitc.cmp eq, [[Arg1]], [[Arg1]] : (f32, f32) -> i1
// CHECK-DAG: [[Ordered:[^ ]*]] = emitc.logical_and [[NotNaNArg0]], [[NotNaNArg1]] : i1, i1
// CHECK-DAG: [[OGE:[^ ]*]] = emitc.logical_and [[Ordered]], [[GE]] : i1, i1
%oge = arith.cmpf oge, %arg0, %arg1 : f32
// CHECK: return [[OGE]]
return %oge: i1
}
// -----
func.func @arith_cmpf_olt(%arg0: f32, %arg1: f32) -> i1 {
// CHECK-LABEL: arith_cmpf_olt
// CHECK-SAME: ([[Arg0:[^ ]*]]: f32, [[Arg1:[^ ]*]]: f32)
// CHECK-DAG: [[LT:[^ ]*]] = emitc.cmp lt, [[Arg0]], [[Arg1]] : (f32, f32) -> i1
// CHECK-DAG: [[NotNaNArg0:[^ ]*]] = emitc.cmp eq, [[Arg0]], [[Arg0]] : (f32, f32) -> i1
// CHECK-DAG: [[NotNaNArg1:[^ ]*]] = emitc.cmp eq, [[Arg1]], [[Arg1]] : (f32, f32) -> i1
// CHECK-DAG: [[Ordered:[^ ]*]] = emitc.logical_and [[NotNaNArg0]], [[NotNaNArg1]] : i1, i1
// CHECK-DAG: [[OLT:[^ ]*]] = emitc.logical_and [[Ordered]], [[LT]] : i1, i1
%olt = arith.cmpf olt, %arg0, %arg1 : f32
// CHECK: return [[OLT]]
return %olt: i1
}
// -----
func.func @arith_cmpf_ole(%arg0: f32, %arg1: f32) -> i1 {
// CHECK-LABEL: arith_cmpf_ole
// CHECK-SAME: ([[Arg0:[^ ]*]]: f32, [[Arg1:[^ ]*]]: f32)
// CHECK-DAG: [[LT:[^ ]*]] = emitc.cmp le, [[Arg0]], [[Arg1]] : (f32, f32) -> i1
// CHECK-DAG: [[NotNaNArg0:[^ ]*]] = emitc.cmp eq, [[Arg0]], [[Arg0]] : (f32, f32) -> i1
// CHECK-DAG: [[NotNaNArg1:[^ ]*]] = emitc.cmp eq, [[Arg1]], [[Arg1]] : (f32, f32) -> i1
// CHECK-DAG: [[Ordered:[^ ]*]] = emitc.logical_and [[NotNaNArg0]], [[NotNaNArg1]] : i1, i1
// CHECK-DAG: [[OLE:[^ ]*]] = emitc.logical_and [[Ordered]], [[LT]] : i1, i1
%ole = arith.cmpf ole, %arg0, %arg1 : f32
// CHECK: return [[OLE]]
return %ole: i1
}
// -----
func.func @arith_cmpf_one(%arg0: f32, %arg1: f32) -> i1 {
// CHECK-LABEL: arith_cmpf_one
// CHECK-SAME: ([[Arg0:[^ ]*]]: f32, [[Arg1:[^ ]*]]: f32)
// CHECK-DAG: [[NEQ:[^ ]*]] = emitc.cmp ne, [[Arg0]], [[Arg1]] : (f32, f32) -> i1
// CHECK-DAG: [[NotNaNArg0:[^ ]*]] = emitc.cmp eq, [[Arg0]], [[Arg0]] : (f32, f32) -> i1
// CHECK-DAG: [[NotNaNArg1:[^ ]*]] = emitc.cmp eq, [[Arg1]], [[Arg1]] : (f32, f32) -> i1
// CHECK-DAG: [[Ordered:[^ ]*]] = emitc.logical_and [[NotNaNArg0]], [[NotNaNArg1]] : i1, i1
// CHECK-DAG: [[ONE:[^ ]*]] = emitc.logical_and [[Ordered]], [[NEQ]] : i1, i1
%one = arith.cmpf one, %arg0, %arg1 : f32
// CHECK: return [[ONE]]
return %one: i1
}
// -----
func.func @arith_cmpf_ord(%arg0: f32, %arg1: f32) -> i1 {
// CHECK-LABEL: arith_cmpf_ord
// CHECK-SAME: ([[Arg0:[^ ]*]]: f32, [[Arg1:[^ ]*]]: f32)
// CHECK-DAG: [[NotNaNArg0:[^ ]*]] = emitc.cmp eq, [[Arg0]], [[Arg0]] : (f32, f32) -> i1
// CHECK-DAG: [[NotNaNArg1:[^ ]*]] = emitc.cmp eq, [[Arg1]], [[Arg1]] : (f32, f32) -> i1
// CHECK-DAG: [[Ordered:[^ ]*]] = emitc.logical_and [[NotNaNArg0]], [[NotNaNArg1]] : i1, i1
%ord = arith.cmpf ord, %arg0, %arg1 : f32
// CHECK: return [[Ordered]]
return %ord: i1
}
// -----
func.func @arith_cmpf_ueq(%arg0: f32, %arg1: f32) -> i1 {
// CHECK-LABEL: arith_cmpf_ueq
// CHECK-SAME: ([[Arg0:[^ ]*]]: f32, [[Arg1:[^ ]*]]: f32)
// CHECK-DAG: [[EQ:[^ ]*]] = emitc.cmp eq, [[Arg0]], [[Arg1]] : (f32, f32) -> i1
// CHECK-DAG: [[NaNArg0:[^ ]*]] = emitc.cmp ne, [[Arg0]], [[Arg0]] : (f32, f32) -> i1
// CHECK-DAG: [[NaNArg1:[^ ]*]] = emitc.cmp ne, [[Arg1]], [[Arg1]] : (f32, f32) -> i1
// CHECK-DAG: [[Unordered:[^ ]*]] = emitc.logical_or [[NaNArg0]], [[NaNArg1]] : i1, i1
// CHECK-DAG: [[UEQ:[^ ]*]] = emitc.logical_or [[Unordered]], [[EQ]] : i1, i1
%ueq = arith.cmpf ueq, %arg0, %arg1 : f32
// CHECK: return [[UEQ]]
return %ueq: i1
}
// -----
func.func @arith_cmpf_ugt(%arg0: f32, %arg1: f32) -> i1 {
// CHECK-LABEL: arith_cmpf_ugt
// CHECK-SAME: ([[Arg0:[^ ]*]]: f32, [[Arg1:[^ ]*]]: f32)
// CHECK-DAG: [[GT:[^ ]*]] = emitc.cmp gt, [[Arg0]], [[Arg1]] : (f32, f32) -> i1
// CHECK-DAG: [[NaNArg0:[^ ]*]] = emitc.cmp ne, [[Arg0]], [[Arg0]] : (f32, f32) -> i1
// CHECK-DAG: [[NaNArg1:[^ ]*]] = emitc.cmp ne, [[Arg1]], [[Arg1]] : (f32, f32) -> i1
// CHECK-DAG: [[Unordered:[^ ]*]] = emitc.logical_or [[NaNArg0]], [[NaNArg1]] : i1, i1
// CHECK-DAG: [[UGT:[^ ]*]] = emitc.logical_or [[Unordered]], [[GT]] : i1, i1
%ugt = arith.cmpf ugt, %arg0, %arg1 : f32
// CHECK: return [[UGT]]
return %ugt: i1
}
// -----
func.func @arith_cmpf_uge(%arg0: f32, %arg1: f32) -> i1 {
// CHECK-LABEL: arith_cmpf_uge
// CHECK-SAME: ([[Arg0:[^ ]*]]: f32, [[Arg1:[^ ]*]]: f32)
// CHECK-DAG: [[GE:[^ ]*]] = emitc.cmp ge, [[Arg0]], [[Arg1]] : (f32, f32) -> i1
// CHECK-DAG: [[NaNArg0:[^ ]*]] = emitc.cmp ne, [[Arg0]], [[Arg0]] : (f32, f32) -> i1
// CHECK-DAG: [[NaNArg1:[^ ]*]] = emitc.cmp ne, [[Arg1]], [[Arg1]] : (f32, f32) -> i1
// CHECK-DAG: [[Unordered:[^ ]*]] = emitc.logical_or [[NaNArg0]], [[NaNArg1]] : i1, i1
// CHECK-DAG: [[UGE:[^ ]*]] = emitc.logical_or [[Unordered]], [[GE]] : i1, i1
%uge = arith.cmpf uge, %arg0, %arg1 : f32
// CHECK: return [[UGE]]
return %uge: i1
}
// -----
func.func @arith_cmpf_ult(%arg0: f32, %arg1: f32) -> i1 {
// CHECK-LABEL: arith_cmpf_ult
// CHECK-SAME: ([[Arg0:[^ ]*]]: f32, [[Arg1:[^ ]*]]: f32)
// CHECK-DAG: [[LT:[^ ]*]] = emitc.cmp lt, [[Arg0]], [[Arg1]] : (f32, f32) -> i1
// CHECK-DAG: [[NaNArg0:[^ ]*]] = emitc.cmp ne, [[Arg0]], [[Arg0]] : (f32, f32) -> i1
// CHECK-DAG: [[NaNArg1:[^ ]*]] = emitc.cmp ne, [[Arg1]], [[Arg1]] : (f32, f32) -> i1
// CHECK-DAG: [[Unordered:[^ ]*]] = emitc.logical_or [[NaNArg0]], [[NaNArg1]] : i1, i1
// CHECK-DAG: [[ULT:[^ ]*]] = emitc.logical_or [[Unordered]], [[LT]] : i1, i1
%ult = arith.cmpf ult, %arg0, %arg1 : f32
// CHECK: return [[ULT]]
return %ult: i1
}
// -----
func.func @arith_cmpf_ule(%arg0: f32, %arg1: f32) -> i1 {
// CHECK-LABEL: arith_cmpf_ule
// CHECK-SAME: ([[Arg0:[^ ]*]]: f32, [[Arg1:[^ ]*]]: f32)
// CHECK-DAG: [[LE:[^ ]*]] = emitc.cmp le, [[Arg0]], [[Arg1]] : (f32, f32) -> i1
// CHECK-DAG: [[NaNArg0:[^ ]*]] = emitc.cmp ne, [[Arg0]], [[Arg0]] : (f32, f32) -> i1
// CHECK-DAG: [[NaNArg1:[^ ]*]] = emitc.cmp ne, [[Arg1]], [[Arg1]] : (f32, f32) -> i1
// CHECK-DAG: [[Unordered:[^ ]*]] = emitc.logical_or [[NaNArg0]], [[NaNArg1]] : i1, i1
// CHECK-DAG: [[ULE:[^ ]*]] = emitc.logical_or [[Unordered]], [[LE]] : i1, i1
%ule = arith.cmpf ule, %arg0, %arg1 : f32
// CHECK: return [[ULE]]
return %ule: i1
}
// -----
func.func @arith_cmpf_une(%arg0: f32, %arg1: f32) -> i1 {
// CHECK-LABEL: arith_cmpf_une
// CHECK-SAME: ([[Arg0:[^ ]*]]: f32, [[Arg1:[^ ]*]]: f32)
// CHECK-DAG: [[NEQ:[^ ]*]] = emitc.cmp ne, [[Arg0]], [[Arg1]] : (f32, f32) -> i1
// CHECK-DAG: [[NaNArg0:[^ ]*]] = emitc.cmp ne, [[Arg0]], [[Arg0]] : (f32, f32) -> i1
// CHECK-DAG: [[NaNArg1:[^ ]*]] = emitc.cmp ne, [[Arg1]], [[Arg1]] : (f32, f32) -> i1
// CHECK-DAG: [[Unordered:[^ ]*]] = emitc.logical_or [[NaNArg0]], [[NaNArg1]] : i1, i1
// CHECK-DAG: [[UNE:[^ ]*]] = emitc.logical_or [[Unordered]], [[NEQ]] : i1, i1
%une = arith.cmpf une, %arg0, %arg1 : f32
// CHECK: return [[UNE]]
return %une: i1
}
// -----
func.func @arith_cmpf_uno(%arg0: f32, %arg1: f32) -> i1 {
// CHECK-LABEL: arith_cmpf_uno
// CHECK-SAME: ([[Arg0:[^ ]*]]: f32, [[Arg1:[^ ]*]]: f32)
// CHECK-DAG: [[NaNArg0:[^ ]*]] = emitc.cmp ne, [[Arg0]], [[Arg0]] : (f32, f32) -> i1
// CHECK-DAG: [[NaNArg1:[^ ]*]] = emitc.cmp ne, [[Arg1]], [[Arg1]] : (f32, f32) -> i1
// CHECK-DAG: [[Unordered:[^ ]*]] = emitc.logical_or [[NaNArg0]], [[NaNArg1]] : i1, i1
%uno = arith.cmpf uno, %arg0, %arg1 : f32
// CHECK: return [[Unordered]]
return %uno: i1
}
// -----
func.func @arith_cmpf_true(%arg0: f32, %arg1: f32) -> i1 {
// CHECK-LABEL: arith_cmpf_true
// CHECK-SAME: ([[Arg0:[^ ]*]]: f32, [[Arg1:[^ ]*]]: f32)
// CHECK-DAG: [[True:[^ ]*]] = "emitc.constant"() <{value = true}> : () -> i1
%ueq = arith.cmpf true, %arg0, %arg1 : f32
// CHECK: return [[True]]
return %ueq: i1
}
// -----
func.func @arith_cmpi_eq(%arg0: i32, %arg1: i32) -> i1 {
// CHECK-LABEL: arith_cmpi_eq
// CHECK-SAME: ([[Arg0:[^ ]*]]: i32, [[Arg1:[^ ]*]]: i32)
// CHECK-DAG: [[EQ:[^ ]*]] = emitc.cmp eq, [[Arg0]], [[Arg1]] : (i32, i32) -> i1
%eq = arith.cmpi eq, %arg0, %arg1 : i32
// CHECK: return [[EQ]]
return %eq: i1
}
func.func @arith_cmpi_ult(%arg0: i32, %arg1: i32) -> i1 {
// CHECK-LABEL: arith_cmpi_ult
// CHECK-SAME: ([[Arg0:[^ ]*]]: i32, [[Arg1:[^ ]*]]: i32)
// CHECK-DAG: [[CastArg0:[^ ]*]] = emitc.cast [[Arg0]] : i32 to ui32
// CHECK-DAG: [[CastArg1:[^ ]*]] = emitc.cast [[Arg1]] : i32 to ui32
// CHECK-DAG: [[ULT:[^ ]*]] = emitc.cmp lt, [[CastArg0]], [[CastArg1]] : (ui32, ui32) -> i1
%ult = arith.cmpi ult, %arg0, %arg1 : i32
// CHECK: return [[ULT]]
return %ult: i1
}
func.func @arith_cmpi_predicates(%arg0: i32, %arg1: i32) {
// CHECK: emitc.cmp lt, {{.*}} : (ui32, ui32) -> i1
%ult = arith.cmpi ult, %arg0, %arg1 : i32
// CHECK: emitc.cmp lt, {{.*}} : (i32, i32) -> i1
%slt = arith.cmpi slt, %arg0, %arg1 : i32
// CHECK: emitc.cmp le, {{.*}} : (ui32, ui32) -> i1
%ule = arith.cmpi ule, %arg0, %arg1 : i32
// CHECK: emitc.cmp le, {{.*}} : (i32, i32) -> i1
%sle = arith.cmpi sle, %arg0, %arg1 : i32
// CHECK: emitc.cmp gt, {{.*}} : (ui32, ui32) -> i1
%ugt = arith.cmpi ugt, %arg0, %arg1 : i32
// CHECK: emitc.cmp gt, {{.*}} : (i32, i32) -> i1
%sgt = arith.cmpi sgt, %arg0, %arg1 : i32
// CHECK: emitc.cmp ge, {{.*}} : (ui32, ui32) -> i1
%uge = arith.cmpi uge, %arg0, %arg1 : i32
// CHECK: emitc.cmp ge, {{.*}} : (i32, i32) -> i1
%sge = arith.cmpi sge, %arg0, %arg1 : i32
// CHECK: emitc.cmp eq, {{.*}} : (i32, i32) -> i1
%eq = arith.cmpi eq, %arg0, %arg1 : i32
// CHECK: emitc.cmp ne, {{.*}} : (i32, i32) -> i1
%ne = arith.cmpi ne, %arg0, %arg1 : i32
return
}
func.func @arith_cmpi_index(%arg0: i32, %arg1: i32) -> i1 {
// CHECK-LABEL: arith_cmpi_index
// CHECK: %[[Cst0:.*]] = emitc.cast %{{.*}} : {{.*}} to !emitc.size_t
%idx0 = arith.index_cast %arg0 : i32 to index
// CHECK: %[[Cst1:.*]] = emitc.cast %{{.*}} : {{.*}} to !emitc.size_t
%idx1 = arith.index_cast %arg0 : i32 to index
// CHECK-DAG: [[ULT:[^ ]*]] = emitc.cmp lt, %[[Cst0]], %[[Cst1]] : (!emitc.size_t, !emitc.size_t) -> i1
%ult = arith.cmpi ult, %idx0, %idx1 : index
// CHECK-DAG: %[[CastArg0:[^ ]*]] = emitc.cast %[[Cst0]] : !emitc.size_t to !emitc.ptrdiff_t
// CHECK-DAG: %[[CastArg1:[^ ]*]] = emitc.cast %[[Cst1]] : !emitc.size_t to !emitc.ptrdiff_t
// CHECK-DAG: %[[SLT:[^ ]*]] = emitc.cmp lt, %[[CastArg0]], %[[CastArg1]] : (!emitc.ptrdiff_t, !emitc.ptrdiff_t) -> i1
%slt = arith.cmpi slt, %idx0, %idx1 : index
// CHECK: return %[[SLT]]
return %slt: i1
}
// -----
func.func @arith_negf(%arg0: f32) -> f32 {
// CHECK-LABEL: arith_negf
// CHECK-SAME: %[[Arg0:[^ ]*]]: f32
// CHECK: %[[N:[^ ]*]] = emitc.unary_minus %[[Arg0]] : (f32) -> f32
%n = arith.negf %arg0 : f32
// CHECK: return %[[N]]
return %n: f32
}
// -----
func.func @arith_float_to_int_cast_ops(%arg0: f32, %arg1: f64) {
// CHECK: emitc.cast %arg0 : f32 to i32
%0 = arith.fptosi %arg0 : f32 to i32
// CHECK: emitc.cast %arg1 : f64 to i32
%1 = arith.fptosi %arg1 : f64 to i32
// CHECK: emitc.cast %arg0 : f32 to i16
%2 = arith.fptosi %arg0 : f32 to i16
// CHECK: emitc.cast %arg1 : f64 to i16
%3 = arith.fptosi %arg1 : f64 to i16
// CHECK: %[[CAST0:.*]] = emitc.cast %arg0 : f32 to ui32
// CHECK: emitc.cast %[[CAST0]] : ui32 to i32
%4 = arith.fptoui %arg0 : f32 to i32
return
}
func.func @arith_int_to_float_cast_ops(%arg0: i8, %arg1: i64) {
// CHECK: emitc.cast %arg0 : i8 to f32
%0 = arith.sitofp %arg0 : i8 to f32
// CHECK: emitc.cast %arg1 : i64 to f32
%1 = arith.sitofp %arg1 : i64 to f32
// CHECK: %[[CAST_UNS:.*]] = emitc.cast %arg0 : i8 to ui8
// CHECK: emitc.cast %[[CAST_UNS]] : ui8 to f32
%2 = arith.uitofp %arg0 : i8 to f32
return
}
// -----
func.func @arith_trunci(%arg0: i32) -> i8 {
// CHECK-LABEL: arith_trunci
// CHECK-SAME: (%[[Arg0:[^ ]*]]: i32)
// CHECK: %[[CastUI:.*]] = emitc.cast %[[Arg0]] : i32 to ui32
// CHECK: %[[Trunc:.*]] = emitc.cast %[[CastUI]] : ui32 to ui8
// CHECK: emitc.cast %[[Trunc]] : ui8 to i8
%truncd = arith.trunci %arg0 : i32 to i8
// CHECK: %[[Const:.*]] = "emitc.constant"
// CHECK-SAME: value = 1
// CHECK-SAME: () -> i32
// CHECK: %[[AndOne:.*]] = emitc.bitwise_and %[[Arg0]], %[[Const]] : (i32, i32) -> i32
// CHECK: %[[Conv:.*]] = emitc.cast %[[AndOne]] : i32 to i1
%bool = arith.trunci %arg0 : i32 to i1
return %truncd : i8
}
// -----
func.func @arith_trunci_to_i1(%arg0: i32) -> i1 {
// CHECK-LABEL: arith_trunci_to_i1
// CHECK-SAME: (%[[Arg0:[^ ]*]]: i32)
// CHECK: %[[Const:.*]] = "emitc.constant"
// CHECK-SAME: value = 1
// CHECK: %[[And:.*]] = emitc.bitwise_and %[[Arg0]], %[[Const]] : (i32, i32) -> i32
// CHECK: emitc.cast %[[And]] : i32 to i1
%truncd = arith.trunci %arg0 : i32 to i1
return %truncd : i1
}
// -----
func.func @arith_extsi(%arg0: i32) {
// CHECK-LABEL: arith_extsi
// CHECK-SAME: ([[Arg0:[^ ]*]]: i32)
// CHECK: emitc.cast [[Arg0]] : i32 to i64
%extd = arith.extsi %arg0 : i32 to i64
return
}
// -----
func.func @arith_extui(%arg0: i32) {
// CHECK-LABEL: arith_extui
// CHECK-SAME: (%[[Arg0:[^ ]*]]: i32)
// CHECK: %[[Conv0:.*]] = emitc.cast %[[Arg0]] : i32 to ui32
// CHECK: %[[Conv1:.*]] = emitc.cast %[[Conv0]] : ui32 to ui64
// CHECK: emitc.cast %[[Conv1]] : ui64 to i64
%extd = arith.extui %arg0 : i32 to i64
return
}
// -----
func.func @arith_extui_i1_to_i32(%arg0: i1) {
// CHECK-LABEL: arith_extui_i1_to_i32
// CHECK-SAME: (%[[Arg0:[^ ]*]]: i1)
// CHECK: %[[Conv0:.*]] = emitc.cast %[[Arg0]] : i1 to ui1
// CHECK: %[[Conv1:.*]] = emitc.cast %[[Conv0]] : ui1 to ui32
// CHECK: emitc.cast %[[Conv1]] : ui32 to i32
%idx = arith.extui %arg0 : i1 to i32
return
}
// -----
func.func @arith_index_cast(%arg0: i32) -> i32 {
// CHECK-LABEL: arith_index_cast
// CHECK-SAME: (%[[Arg0:[^ ]*]]: i32)
// CHECK: %[[Conv0:.*]] = emitc.cast %[[Arg0]] : i32 to !emitc.ptrdiff_t
// CHECK: %[[Conv1:.*]] = emitc.cast %[[Conv0]] : !emitc.ptrdiff_t to !emitc.size_t
%idx = arith.index_cast %arg0 : i32 to index
// CHECK: %[[Conv2:.*]] = emitc.cast %[[Conv1]] : !emitc.size_t to !emitc.ptrdiff_t
// CHECK: %[[Conv3:.*]] = emitc.cast %[[Conv2]] : !emitc.ptrdiff_t to i32
%int = arith.index_cast %idx : index to i32
// CHECK: %[[Const:.*]] = "emitc.constant"
// CHECK-SAME: value = 1
// CHECK-SAME: () -> !emitc.size_t
// CHECK: %[[AndOne:.*]] = emitc.bitwise_and %[[Conv1]], %[[Const]] : (!emitc.size_t, !emitc.size_t) -> !emitc.size_t
// CHECK: %[[Conv4:.*]] = emitc.cast %[[AndOne]] : !emitc.size_t to i1
%bool = arith.index_cast %idx : index to i1
return %int : i32
}
// -----
func.func @arith_index_castui(%arg0: i32) -> i32 {
// CHECK-LABEL: arith_index_castui
// CHECK-SAME: (%[[Arg0:[^ ]*]]: i32)
// CHECK: %[[Conv0:.*]] = emitc.cast %[[Arg0]] : i32 to ui32
// CHECK: %[[Conv1:.*]] = emitc.cast %[[Conv0]] : ui32 to !emitc.size_t
%idx = arith.index_castui %arg0 : i32 to index
// CHECK: %[[Conv2:.*]] = emitc.cast %[[Conv1]] : !emitc.size_t to ui32
// CHECK: %[[Conv3:.*]] = emitc.cast %[[Conv2]] : ui32 to i32
%int = arith.index_castui %idx : index to i32
// CHECK: %[[Const:.*]] = "emitc.constant"
// CHECK-SAME: value = 1
// CHECK-SAME: () -> !emitc.size_t
// CHECK: %[[AndOne:.*]] = emitc.bitwise_and %[[Conv1]], %[[Const]] : (!emitc.size_t, !emitc.size_t) -> !emitc.size_t
// CHECK: %[[Conv4:.*]] = emitc.cast %[[AndOne]] : !emitc.size_t to i1
%bool = arith.index_castui %idx : index to i1
return %int : i32
}
// -----
func.func @arith_divui_remui(%arg0: i32, %arg1: i32) -> i32 {
// CHECK-LABEL: arith_divui_remui
// CHECK-SAME: (%[[Arg0:[^ ]*]]: i32, %[[Arg1:[^ ]*]]: i32)
// CHECK: %[[Conv0:.*]] = emitc.cast %[[Arg0]] : i32 to ui32
// CHECK: %[[Conv1:.*]] = emitc.cast %[[Arg1]] : i32 to ui32
// CHECK: %[[Div:.*]] = emitc.div %[[Conv0]], %[[Conv1]] : (ui32, ui32) -> ui32
%div = arith.divui %arg0, %arg1 : i32
// CHECK: %[[Conv2:.*]] = emitc.cast %[[Arg0]] : i32 to ui32
// CHECK: %[[Conv3:.*]] = emitc.cast %[[Arg1]] : i32 to ui32
// CHECK: %[[Rem:.*]] = emitc.rem %[[Conv2]], %[[Conv3]] : (ui32, ui32) -> ui32
%rem = arith.remui %arg0, %arg1 : i32
return %div : i32
}