Skip to content

Commit 35c9085

Browse files
committed
[mlir][llvmir] Support FastmathFlags for LLVM intrinsic operations.
This is required for D126305 code to propagate fastmath attributes for Arith operations that are converted to LLVM IR intrinsics operations. LLVM IR intrinsic operations are using custom assembly format now to avoid printing {fastmathFlags = #llvm.fastmath<none>}, which is too verbose. Reviewed By: rriddle Differential Revision: https://reviews.llvm.org/D136225
1 parent 29378ab commit 35c9085

File tree

21 files changed

+255
-217
lines changed

21 files changed

+255
-217
lines changed

flang/test/Intrinsics/math-codegen.fir

Lines changed: 54 additions & 54 deletions
Large diffs are not rendered by default.

flang/test/Lower/Intrinsics/anint.f90

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<f32> {fir.bindc_name = "a"},
55
! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<f32> {fir.bindc_name = "b"}) {
66
! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref<f32>
7-
! CHECK: %[[VAL_3:.*]] = "llvm.intr.round"(%[[VAL_2]]) : (f32) -> f32
7+
! CHECK: %[[VAL_3:.*]] = llvm.intr.round(%[[VAL_2]]) : (f32) -> f32
88
! CHECK: fir.store %[[VAL_3]] to %[[VAL_1]] : !fir.ref<f32>
99
! CHECK: return
1010
! CHECK: }
@@ -18,7 +18,7 @@ subroutine anint_test(a, b)
1818
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<f64> {fir.bindc_name = "a"},
1919
! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<f64> {fir.bindc_name = "b"}) {
2020
! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref<f64>
21-
! CHECK: %[[VAL_3:.*]] = "llvm.intr.round"(%[[VAL_2]]) : (f64) -> f64
21+
! CHECK: %[[VAL_3:.*]] = llvm.intr.round(%[[VAL_2]]) : (f64) -> f64
2222
! CHECK: fir.store %[[VAL_3]] to %[[VAL_1]] : !fir.ref<f64>
2323
! CHECK: return
2424
! CHECK: }
@@ -32,7 +32,7 @@ subroutine anint_test_real8(a, b)
3232
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<f80> {fir.bindc_name = "a"},
3333
! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<f80> {fir.bindc_name = "b"}) {
3434
! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref<f80>
35-
! CHECK: %[[VAL_3:.*]] = "llvm.intr.round"(%[[VAL_2]]) : (f80) -> f80
35+
! CHECK: %[[VAL_3:.*]] = llvm.intr.round(%[[VAL_2]]) : (f80) -> f80
3636
! CHECK: fir.store %[[VAL_3]] to %[[VAL_1]] : !fir.ref<f80>
3737
! CHECK: return
3838
! CHECK: }

flang/test/Lower/math-lowering.f90

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,8 @@ function test_real4(x)
109109
end function
110110

111111
! ALL-LABEL: @_QPtest_real4
112-
! FAST: {{%[A-Za-z0-9._]+}} = "llvm.intr.round"({{%[A-Za-z0-9._]+}}) : (f32) -> f32
113-
! RELAXED: {{%[A-Za-z0-9._]+}} = "llvm.intr.round"({{%[A-Za-z0-9._]+}}) : (f32) -> f32
112+
! FAST: {{%[A-Za-z0-9._]+}} = llvm.intr.round({{%[A-Za-z0-9._]+}}) : (f32) -> f32
113+
! RELAXED: {{%[A-Za-z0-9._]+}} = llvm.intr.round({{%[A-Za-z0-9._]+}}) : (f32) -> f32
114114
! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @llvm.round.f32({{%[A-Za-z0-9._]+}}) : (f32) -> f32
115115

116116
function test_real8(x)
@@ -119,8 +119,8 @@ function test_real8(x)
119119
end function
120120

121121
! ALL-LABEL: @_QPtest_real8
122-
! FAST: {{%[A-Za-z0-9._]+}} = "llvm.intr.round"({{%[A-Za-z0-9._]+}}) : (f64) -> f64
123-
! RELAXED: {{%[A-Za-z0-9._]+}} = "llvm.intr.round"({{%[A-Za-z0-9._]+}}) : (f64) -> f64
122+
! FAST: {{%[A-Za-z0-9._]+}} = llvm.intr.round({{%[A-Za-z0-9._]+}}) : (f64) -> f64
123+
! RELAXED: {{%[A-Za-z0-9._]+}} = llvm.intr.round({{%[A-Za-z0-9._]+}}) : (f64) -> f64
124124
! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @llvm.round.f64({{%[A-Za-z0-9._]+}}) : (f64) -> f64
125125

126126
function test_real10(x)
@@ -129,8 +129,8 @@ function test_real10(x)
129129
end function
130130

131131
! ALL-LABEL: @_QPtest_real10
132-
! FAST: {{%[A-Za-z0-9._]+}} = "llvm.intr.round"({{%[A-Za-z0-9._]+}}) : (f80) -> f80
133-
! RELAXED: {{%[A-Za-z0-9._]+}} = "llvm.intr.round"({{%[A-Za-z0-9._]+}}) : (f80) -> f80
132+
! FAST: {{%[A-Za-z0-9._]+}} = llvm.intr.round({{%[A-Za-z0-9._]+}}) : (f80) -> f80
133+
! RELAXED: {{%[A-Za-z0-9._]+}} = llvm.intr.round({{%[A-Za-z0-9._]+}}) : (f80) -> f80
134134
! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @llvm.round.f80({{%[A-Za-z0-9._]+}}) : (f80) -> f80
135135

136136
! TODO: wait until fp128 is supported well in llvm.round

mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define LLVM_INTRINSIC_OPS
33

44
include "mlir/IR/OpBase.td"
5+
include "mlir/Dialect/LLVMIR/LLVMAttrDefs.td"
56
include "mlir/Dialect/LLVMIR/LLVMOpBase.td"
67
include "mlir/Dialect/LLVMIR/LLVMAttrDefs.td"
78
include "mlir/Interfaces/InferTypeOpInterface.td"
@@ -12,38 +13,59 @@ include "mlir/Interfaces/InferTypeOpInterface.td"
1213
// "intr." to avoid potential name clashes.
1314

1415
class LLVM_UnaryIntrOpBase<string func, Type element,
15-
list<Trait> traits = []> :
16+
list<Trait> traits = [],
17+
dag addAttrs = (ins)> :
1618
LLVM_OneResultIntrOp<func, [], [0],
1719
!listconcat([Pure, SameOperandsAndResultType], traits)> {
18-
let arguments = (ins LLVM_ScalarOrVectorOf<element>:$in);
20+
dag args = (ins LLVM_ScalarOrVectorOf<element>:$in);
21+
let arguments = !con(args, addAttrs);
22+
let assemblyFormat = "`(` operands `)` custom<LLVMOpAttrs>(attr-dict) `:` "
23+
"functional-type(operands, results)";
1924
}
2025

2126
class LLVM_UnaryIntrOpI<string func, list<Trait> traits = []> :
2227
LLVM_UnaryIntrOpBase<func, AnySignlessInteger, traits>;
2328

2429
class LLVM_UnaryIntrOpF<string func, list<Trait> traits = []> :
25-
LLVM_UnaryIntrOpBase<func, LLVM_AnyFloat, traits>;
30+
LLVM_UnaryIntrOpBase<func, LLVM_AnyFloat,
31+
!listconcat([DeclareOpInterfaceMethods<FastmathFlagsInterface>],
32+
traits),
33+
(ins DefaultValuedAttr<LLVM_FastmathFlagsAttr,
34+
"{}">:$fastmathFlags)>;
2635

2736
class LLVM_BinarySameArgsIntrOpBase<string func, Type element,
28-
list<Trait> traits = []> :
37+
list<Trait> traits = [],
38+
dag addAttrs = (ins)> :
2939
LLVM_OneResultIntrOp<func, [], [0],
3040
!listconcat([Pure, SameOperandsAndResultType], traits)> {
31-
let arguments = (ins LLVM_ScalarOrVectorOf<element>:$a,
32-
LLVM_ScalarOrVectorOf<element>:$b);
41+
dag args = (ins LLVM_ScalarOrVectorOf<element>:$a,
42+
LLVM_ScalarOrVectorOf<element>:$b);
43+
let arguments = !con(args, addAttrs);
44+
let assemblyFormat = "`(` operands `)` custom<LLVMOpAttrs>(attr-dict) `:` "
45+
"functional-type(operands, results)";
3346
}
3447

3548
class LLVM_BinarySameArgsIntrOpI<string func, list<Trait> traits = []> :
3649
LLVM_BinarySameArgsIntrOpBase<func, AnySignlessInteger, traits>;
3750

3851
class LLVM_BinarySameArgsIntrOpF<string func, list<Trait> traits = []> :
39-
LLVM_BinarySameArgsIntrOpBase<func, LLVM_AnyFloat, traits>;
52+
LLVM_BinarySameArgsIntrOpBase<func, LLVM_AnyFloat,
53+
!listconcat([DeclareOpInterfaceMethods<FastmathFlagsInterface>],
54+
traits),
55+
(ins DefaultValuedAttr<LLVM_FastmathFlagsAttr,
56+
"{}">:$fastmathFlags)>;
4057

4158
class LLVM_TernarySameArgsIntrOpF<string func, list<Trait> traits = []> :
4259
LLVM_OneResultIntrOp<func, [], [0],
43-
!listconcat([Pure, SameOperandsAndResultType], traits)> {
60+
!listconcat([DeclareOpInterfaceMethods<FastmathFlagsInterface>,
61+
Pure, SameOperandsAndResultType], traits)> {
4462
let arguments = (ins LLVM_ScalarOrVectorOf<AnyFloat>:$a,
4563
LLVM_ScalarOrVectorOf<AnyFloat>:$b,
46-
LLVM_ScalarOrVectorOf<AnyFloat>:$c);
64+
LLVM_ScalarOrVectorOf<AnyFloat>:$c,
65+
DefaultValuedAttr<LLVM_FastmathFlagsAttr,
66+
"{}">:$fastmathFlags);
67+
let assemblyFormat = "`(` operands `)` custom<LLVMOpAttrs>(attr-dict) `:` "
68+
"functional-type(operands, results)";
4769
}
4870

4971
class LLVM_CountZerosIntrOp<string func, list<Trait> traits = []> :
@@ -83,9 +105,14 @@ def LLVM_RoundOp : LLVM_UnaryIntrOpF<"round">;
83105
def LLVM_FTruncOp : LLVM_UnaryIntrOpF<"trunc">;
84106
def LLVM_SqrtOp : LLVM_UnaryIntrOpF<"sqrt">;
85107
def LLVM_PowOp : LLVM_BinarySameArgsIntrOpF<"pow">;
86-
def LLVM_PowIOp : LLVM_OneResultIntrOp<"powi"> {
87-
let arguments = (ins LLVM_ScalarOrVectorOf<LLVM_AnyFloat>:$val,
88-
AnySignlessInteger:$power);
108+
def LLVM_PowIOp : LLVM_OneResultIntrOp<"powi", [], [0,1],
109+
[DeclareOpInterfaceMethods<FastmathFlagsInterface>, Pure]> {
110+
let arguments =
111+
(ins LLVM_ScalarOrVectorOf<LLVM_AnyFloat>:$val,
112+
AnySignlessInteger:$power,
113+
DefaultValuedAttr<LLVM_FastmathFlagsAttr, "{}">:$fastmathFlags);
114+
let assemblyFormat = "`(` operands `)` custom<LLVMOpAttrs>(attr-dict) `:` "
115+
"functional-type(operands, results)";
89116
}
90117
def LLVM_BitReverseOp : LLVM_UnaryIntrOpI<"bitreverse">;
91118
def LLVM_CountLeadingZerosOp : LLVM_CountZerosIntrOp<"ctlz">;

mlir/lib/Dialect/LLVMIR/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ add_mlir_dialect_library(MLIRLLVMDialect
44
IR/FunctionCallUtils.cpp
55
IR/LLVMAttrs.cpp
66
IR/LLVMDialect.cpp
7-
IR/LLVMIntrinsicOps.cpp
87
IR/LLVMTypes.cpp
98
IR/LLVMTypeSyntax.cpp
109

mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2612,6 +2612,9 @@ void LLVMDialect::initialize() {
26122612
#define GET_OP_CLASSES
26132613
#include "mlir/Dialect/LLVMIR/LLVMOps.cpp.inc"
26142614

2615+
#define GET_OP_CLASSES
2616+
#include "mlir/Dialect/LLVMIR/LLVMIntrinsicOps.cpp.inc"
2617+
26152618
LogicalResult LLVMDialect::verifyDataLayoutString(
26162619
StringRef descr, llvm::function_ref<void(const Twine &)> reportError) {
26172620
llvm::Expected<llvm::DataLayout> maybeDataLayout =

mlir/lib/Dialect/LLVMIR/IR/LLVMIntrinsicOps.cpp

Lines changed: 0 additions & 7 deletions
This file was deleted.

mlir/test/Conversion/ArithToLLVM/arith-to-llvm.mlir

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -429,22 +429,22 @@ func.func @select(%arg0 : i1, %arg1 : i32, %arg2 : i32) -> i32 {
429429

430430
// CHECK-LABEL: @minmaxi
431431
func.func @minmaxi(%arg0 : i32, %arg1 : i32) -> i32 {
432-
// CHECK: = "llvm.intr.smin"(%arg0, %arg1) : (i32, i32) -> i32
432+
// CHECK: = llvm.intr.smin(%arg0, %arg1) : (i32, i32) -> i32
433433
%0 = arith.minsi %arg0, %arg1 : i32
434-
// CHECK: = "llvm.intr.smax"(%arg0, %arg1) : (i32, i32) -> i32
434+
// CHECK: = llvm.intr.smax(%arg0, %arg1) : (i32, i32) -> i32
435435
%1 = arith.maxsi %arg0, %arg1 : i32
436-
// CHECK: = "llvm.intr.umin"(%arg0, %arg1) : (i32, i32) -> i32
436+
// CHECK: = llvm.intr.umin(%arg0, %arg1) : (i32, i32) -> i32
437437
%2 = arith.minui %arg0, %arg1 : i32
438-
// CHECK: = "llvm.intr.umax"(%arg0, %arg1) : (i32, i32) -> i32
438+
// CHECK: = llvm.intr.umax(%arg0, %arg1) : (i32, i32) -> i32
439439
%3 = arith.maxui %arg0, %arg1 : i32
440440
return %0 : i32
441441
}
442442

443443
// CHECK-LABEL: @minmaxf
444444
func.func @minmaxf(%arg0 : f32, %arg1 : f32) -> f32 {
445-
// CHECK: = "llvm.intr.minnum"(%arg0, %arg1) : (f32, f32) -> f32
445+
// CHECK: = llvm.intr.minnum(%arg0, %arg1) : (f32, f32) -> f32
446446
%0 = arith.minf %arg0, %arg1 : f32
447-
// CHECK: = "llvm.intr.maxnum"(%arg0, %arg1) : (f32, f32) -> f32
447+
// CHECK: = llvm.intr.maxnum(%arg0, %arg1) : (f32, f32) -> f32
448448
%1 = arith.maxf %arg0, %arg1 : f32
449449
return %0 : f32
450450
}

mlir/test/Conversion/ComplexToLLVM/convert-to-llvm.mlir

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,6 @@ func.func @complex_abs(%arg: complex<f32>) -> f32 {
147147
// CHECK-DAG: %[[REAL_SQ:.*]] = llvm.fmul %[[REAL]], %[[REAL]] : f32
148148
// CHECK-DAG: %[[IMAG_SQ:.*]] = llvm.fmul %[[IMAG]], %[[IMAG]] : f32
149149
// CHECK: %[[SQ_NORM:.*]] = llvm.fadd %[[REAL_SQ]], %[[IMAG_SQ]] : f32
150-
// CHECK: %[[NORM:.*]] = "llvm.intr.sqrt"(%[[SQ_NORM]]) : (f32) -> f32
150+
// CHECK: %[[NORM:.*]] = llvm.intr.sqrt(%[[SQ_NORM]]) : (f32) -> f32
151151
// CHECK: return %[[NORM]] : f32
152152

mlir/test/Conversion/ComplexToLLVM/full-conversion.mlir

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,6 @@ func.func @complex_abs(%arg: complex<f32>) -> f32 {
6666
// CHECK-DAG: %[[REAL_SQ:.*]] = llvm.fmul %[[REAL]], %[[REAL]] : f32
6767
// CHECK-DAG: %[[IMAG_SQ:.*]] = llvm.fmul %[[IMAG]], %[[IMAG]] : f32
6868
// CHECK: %[[SQ_NORM:.*]] = llvm.fadd %[[REAL_SQ]], %[[IMAG_SQ]] : f32
69-
// CHECK: %[[NORM:.*]] = "llvm.intr.sqrt"(%[[SQ_NORM]]) : (f32) -> f32
69+
// CHECK: %[[NORM:.*]] = llvm.intr.sqrt(%[[SQ_NORM]]) : (f32) -> f32
7070
// CHECK: llvm.return %[[NORM]] : f32
7171

0 commit comments

Comments
 (0)