[llvm-branch-commits] [mlir] 2217cac - [mlir][py] better support for arith.constant construction

2024-03-06 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2024-02-28T12:53:53Z
New Revision: 2217caceac600f5c0e84a0d6a55ec036e13ebf6a

URL: 
https://github.com/llvm/llvm-project/commit/2217caceac600f5c0e84a0d6a55ec036e13ebf6a
DIFF: 
https://github.com/llvm/llvm-project/commit/2217caceac600f5c0e84a0d6a55ec036e13ebf6a.diff

LOG: [mlir][py] better support for arith.constant construction

Arithmetic constants for vector types can be constructed from objects
implementing Python buffer protocol such as `array.array`. Note that
until Python 3.12, there is no typing support for buffer protocol
implementers, so the annotations use array explicitly.

Added: 


Modified: 
mlir/python/mlir/dialects/arith.py
mlir/test/python/dialects/arith_dialect.py

Removed: 




diff  --git a/mlir/python/mlir/dialects/arith.py 
b/mlir/python/mlir/dialects/arith.py
index 61c6917393f1f9..83a50c7ef244f1 100644
--- a/mlir/python/mlir/dialects/arith.py
+++ b/mlir/python/mlir/dialects/arith.py
@@ -5,6 +5,8 @@
 from ._arith_ops_gen import *
 from ._arith_ops_gen import _Dialect
 from ._arith_enum_gen import *
+from array import array as _array
+from typing import overload
 
 try:
 from ..ir import *
@@ -43,13 +45,30 @@ def _is_float_type(type: Type):
 class ConstantOp(ConstantOp):
 """Specialization for the constant op class."""
 
+@overload
+def __init__(self, value: Attribute, *, loc=None, ip=None):
+...
+
+@overload
 def __init__(
-self, result: Type, value: Union[int, float, Attribute], *, loc=None, 
ip=None
+self, result: Type, value: Union[int, float, _array], *, loc=None, 
ip=None
 ):
+...
+
+def __init__(self, result, value, *, loc=None, ip=None):
+if value is None:
+assert isinstance(result, Attribute)
+super().__init__(result, loc=loc, ip=ip)
+return
+
 if isinstance(value, int):
 super().__init__(IntegerAttr.get(result, value), loc=loc, ip=ip)
 elif isinstance(value, float):
 super().__init__(FloatAttr.get(result, value), loc=loc, ip=ip)
+elif isinstance(value, _array) and value.typecode in ["i", "l"]:
+super().__init__(DenseIntElementsAttr.get(value, type=result))
+elif isinstance(value, _array) and value.typecode in ["f", "d"]:
+super().__init__(DenseFPElementsAttr.get(value, type=result))
 else:
 super().__init__(value, loc=loc, ip=ip)
 
@@ -79,6 +98,6 @@ def literal_value(self) -> Union[int, float]:
 
 
 def constant(
-result: Type, value: Union[int, float, Attribute], *, loc=None, ip=None
+result: Type, value: Union[int, float, Attribute, _array], *, loc=None, 
ip=None
 ) -> Value:
 return _get_op_result_or_op_results(ConstantOp(result, value, loc=loc, 
ip=ip))

diff  --git a/mlir/test/python/dialects/arith_dialect.py 
b/mlir/test/python/dialects/arith_dialect.py
index 8bb80eed2b8105..ef0e1620bba990 100644
--- a/mlir/test/python/dialects/arith_dialect.py
+++ b/mlir/test/python/dialects/arith_dialect.py
@@ -4,6 +4,7 @@
 from mlir.ir import *
 import mlir.dialects.arith as arith
 import mlir.dialects.func as func
+from array import array
 
 
 def run(f):
@@ -92,3 +93,40 @@ def __str__(self):
 b = a * a
 # CHECK: ArithValue(%2 = arith.mulf %cst_1, %cst_1 : f64)
 print(b)
+
+
+# CHECK-LABEL: TEST: testArrayConstantConstruction
+@run
+def testArrayConstantConstruction():
+with Context(), Location.unknown():
+module = Module.create()
+with InsertionPoint(module.body):
+i32_array = array("i", [1, 2, 3, 4])
+i32 = IntegerType.get_signless(32)
+vec_i32 = VectorType.get([2, 2], i32)
+arith.constant(vec_i32, i32_array)
+arith.ConstantOp(vec_i32, DenseIntElementsAttr.get(i32_array, 
type=vec_i32))
+
+i64_array = array("l", [5, 6, 7, 8])
+i64 = IntegerType.get_signless(64)
+vec_i64 = VectorType.get([1, 4], i64)
+arith.constant(vec_i64, i64_array)
+arith.ConstantOp(vec_i64, DenseIntElementsAttr.get(i64_array, 
type=vec_i64))
+
+f32_array = array("f", [1.0, 2.0, 3.0, 4.0])
+f32 = F32Type.get()
+vec_f32 = VectorType.get([4, 1], f32)
+arith.constant(vec_f32, f32_array)
+arith.ConstantOp(vec_f32, DenseFPElementsAttr.get(f32_array, 
type=vec_f32))
+
+f64_array = array("d", [1.0, 2.0, 3.0, 4.0])
+f64 = F64Type.get()
+vec_f64 = VectorType.get([2, 1, 2], f64)
+arith.constant(vec_f64, f64_array)
+arith.ConstantOp(vec_f64, DenseFPElementsAttr.get(f64_array, 
type=vec_f64))
+
+# CHECK-COUNT-2: arith.constant dense<[{{\[}}1, 2], [3, 4]]> : 
vector<2x2xi32>
+# CHECK-COUNT-2: arith.constant dense<[{{\[}}5, 6, 7, 8]]> : 
vector<1x4xi64>
+# CHECK-COUNT-2: ari

[llvm-branch-commits] [mlir] 1ccfb41 - printf debugging

2024-03-06 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2024-03-06T10:49:17Z
New Revision: 1ccfb41ab32ac27b32919438a11806bd688a030d

URL: 
https://github.com/llvm/llvm-project/commit/1ccfb41ab32ac27b32919438a11806bd688a030d
DIFF: 
https://github.com/llvm/llvm-project/commit/1ccfb41ab32ac27b32919438a11806bd688a030d.diff

LOG: printf debugging

Added: 


Modified: 
mlir/lib/IR/BuiltinAttributes.cpp

Removed: 




diff  --git a/mlir/lib/IR/BuiltinAttributes.cpp 
b/mlir/lib/IR/BuiltinAttributes.cpp
index 89b1ed67f5d067..2f3798ed54f2f3 100644
--- a/mlir/lib/IR/BuiltinAttributes.cpp
+++ b/mlir/lib/IR/BuiltinAttributes.cpp
@@ -1084,6 +1084,11 @@ bool DenseElementsAttr::isValidRawBuffer(ShapedType type,
 return rawBufferWidth == llvm::alignTo<8>(numElements);
   }
 
+  llvm::errs() << "storage width: " << storageWidth
+   << " rawBufferWidth: " << rawBufferWidth
+   << " numElements: " << numElements << "\n";
+  type.dump();
+
   // All other types are 8-bit aligned, so we can just check the buffer width
   // to know if only a single initializer element was passed in.
   if (rawBufferWidth == storageWidth) {



___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] 0c81122 - [mlir][py] better support for arith.constant construction

2024-03-06 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2024-03-06T18:30:09Z
New Revision: 0c81122420979a28d16beddaed85413fd533c324

URL: 
https://github.com/llvm/llvm-project/commit/0c81122420979a28d16beddaed85413fd533c324
DIFF: 
https://github.com/llvm/llvm-project/commit/0c81122420979a28d16beddaed85413fd533c324.diff

LOG: [mlir][py] better support for arith.constant construction

Arithmetic constants for vector types can be constructed from objects
implementing Python buffer protocol such as `array.array`. Note that
until Python 3.12, there is no typing support for buffer protocol
implementers, so the annotations use array explicitly.

Added: 


Modified: 
mlir/python/mlir/dialects/arith.py
mlir/test/python/dialects/arith_dialect.py

Removed: 




diff  --git a/mlir/python/mlir/dialects/arith.py 
b/mlir/python/mlir/dialects/arith.py
index 61c6917393f1f9..92da5df9bce665 100644
--- a/mlir/python/mlir/dialects/arith.py
+++ b/mlir/python/mlir/dialects/arith.py
@@ -5,6 +5,8 @@
 from ._arith_ops_gen import *
 from ._arith_ops_gen import _Dialect
 from ._arith_enum_gen import *
+from array import array as _array
+from typing import overload
 
 try:
 from ..ir import *
@@ -43,13 +45,37 @@ def _is_float_type(type: Type):
 class ConstantOp(ConstantOp):
 """Specialization for the constant op class."""
 
+@overload
+def __init__(self, value: Attribute, *, loc=None, ip=None):
+...
+
+@overload
 def __init__(
-self, result: Type, value: Union[int, float, Attribute], *, loc=None, 
ip=None
+self, result: Type, value: Union[int, float, _array], *, loc=None, 
ip=None
 ):
+...
+
+def __init__(self, result, value, *, loc=None, ip=None):
+if value is None:
+assert isinstance(result, Attribute)
+super().__init__(result, loc=loc, ip=ip)
+return
+
 if isinstance(value, int):
 super().__init__(IntegerAttr.get(result, value), loc=loc, ip=ip)
 elif isinstance(value, float):
 super().__init__(FloatAttr.get(result, value), loc=loc, ip=ip)
+elif isinstance(value, _array):
+if 8 * value.itemsize != result.element_type.width:
+raise ValueError(
+f"Mismatching array element ({8 * value.itemsize}) and 
type ({result.element_type.width}) width."
+)
+if value.typecode in ["i", "l", "q"]:
+super().__init__(DenseIntElementsAttr.get(value, type=result))
+elif value.typecode in ["f", "d"]:
+super().__init__(DenseFPElementsAttr.get(value, type=result))
+else:
+raise ValueError(f'Unsupported typecode: "{value.typecode}".')
 else:
 super().__init__(value, loc=loc, ip=ip)
 
@@ -79,6 +105,6 @@ def literal_value(self) -> Union[int, float]:
 
 
 def constant(
-result: Type, value: Union[int, float, Attribute], *, loc=None, ip=None
+result: Type, value: Union[int, float, Attribute, _array], *, loc=None, 
ip=None
 ) -> Value:
 return _get_op_result_or_op_results(ConstantOp(result, value, loc=loc, 
ip=ip))

diff  --git a/mlir/test/python/dialects/arith_dialect.py 
b/mlir/test/python/dialects/arith_dialect.py
index 8bb80eed2b8105..c9af5e7b46db84 100644
--- a/mlir/test/python/dialects/arith_dialect.py
+++ b/mlir/test/python/dialects/arith_dialect.py
@@ -4,6 +4,7 @@
 from mlir.ir import *
 import mlir.dialects.arith as arith
 import mlir.dialects.func as func
+from array import array
 
 
 def run(f):
@@ -92,3 +93,42 @@ def __str__(self):
 b = a * a
 # CHECK: ArithValue(%2 = arith.mulf %cst_1, %cst_1 : f64)
 print(b)
+
+
+# CHECK-LABEL: TEST: testArrayConstantConstruction
+@run
+def testArrayConstantConstruction():
+with Context(), Location.unknown():
+module = Module.create()
+with InsertionPoint(module.body):
+i32_array = array("i", [1, 2, 3, 4])
+i32 = IntegerType.get_signless(32)
+vec_i32 = VectorType.get([2, 2], i32)
+arith.constant(vec_i32, i32_array)
+arith.ConstantOp(vec_i32, DenseIntElementsAttr.get(i32_array, 
type=vec_i32))
+
+# "q" is the equivalent of `long long` in C and requires at least
+# 64 bit width integers on both Linux and Windows.
+i64_array = array("q", [5, 6, 7, 8])
+i64 = IntegerType.get_signless(64)
+vec_i64 = VectorType.get([1, 4], i64)
+arith.constant(vec_i64, i64_array)
+arith.ConstantOp(vec_i64, DenseIntElementsAttr.get(i64_array, 
type=vec_i64))
+
+f32_array = array("f", [1.0, 2.0, 3.0, 4.0])
+f32 = F32Type.get()
+vec_f32 = VectorType.get([4, 1], f32)
+arith.constant(vec_f32, f32_array)
+arith.ConstantOp(vec_f32, DenseFPElementsAttr.get(f32_array, 
type=vec_f32))
+
+   

[llvm-branch-commits] [flang] 7f10219 - [flang] disable failing test

2024-03-07 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2024-03-07T10:36:58Z
New Revision: 7f102199b862fce58e4b0d94d10f4cf14acb48e1

URL: 
https://github.com/llvm/llvm-project/commit/7f102199b862fce58e4b0d94d10f4cf14acb48e1
DIFF: 
https://github.com/llvm/llvm-project/commit/7f102199b862fce58e4b0d94d10f4cf14acb48e1.diff

LOG: [flang] disable failing test

This test has been failing on Windows for multiple consecutive days
without any action taken. This prevents our CI from finding other
problematic tests.

Added: 


Modified: 
flang/test/Fir/memory-allocation-opt.fir

Removed: 




diff  --git a/flang/test/Fir/memory-allocation-opt.fir 
b/flang/test/Fir/memory-allocation-opt.fir
index cfbca2f83ef8ec..c89d794ccaf8d0 100644
--- a/flang/test/Fir/memory-allocation-opt.fir
+++ b/flang/test/Fir/memory-allocation-opt.fir
@@ -1,4 +1,5 @@
 // RUN: fir-opt --memory-allocation-opt="dynamic-array-on-heap=true 
maximum-array-alloc-size=1024" %s | FileCheck %s
+// XFAIL: *
 
 // Test for size of array being too big.
 



___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] 20815bc - [mlir][py] better support for arith.constant construction

2024-03-07 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2024-03-07T10:38:26Z
New Revision: 20815bc3273ad1d63494ba3f6eda8a9671a94693

URL: 
https://github.com/llvm/llvm-project/commit/20815bc3273ad1d63494ba3f6eda8a9671a94693
DIFF: 
https://github.com/llvm/llvm-project/commit/20815bc3273ad1d63494ba3f6eda8a9671a94693.diff

LOG: [mlir][py] better support for arith.constant construction

Arithmetic constants for vector types can be constructed from objects
implementing Python buffer protocol such as `array.array`. Note that
until Python 3.12, there is no typing support for buffer protocol
implementers, so the annotations use array explicitly.

Added: 


Modified: 
mlir/python/mlir/dialects/arith.py
mlir/test/python/dialects/arith_dialect.py

Removed: 




diff  --git a/mlir/python/mlir/dialects/arith.py 
b/mlir/python/mlir/dialects/arith.py
index 61c6917393f1f9..92da5df9bce665 100644
--- a/mlir/python/mlir/dialects/arith.py
+++ b/mlir/python/mlir/dialects/arith.py
@@ -5,6 +5,8 @@
 from ._arith_ops_gen import *
 from ._arith_ops_gen import _Dialect
 from ._arith_enum_gen import *
+from array import array as _array
+from typing import overload
 
 try:
 from ..ir import *
@@ -43,13 +45,37 @@ def _is_float_type(type: Type):
 class ConstantOp(ConstantOp):
 """Specialization for the constant op class."""
 
+@overload
+def __init__(self, value: Attribute, *, loc=None, ip=None):
+...
+
+@overload
 def __init__(
-self, result: Type, value: Union[int, float, Attribute], *, loc=None, 
ip=None
+self, result: Type, value: Union[int, float, _array], *, loc=None, 
ip=None
 ):
+...
+
+def __init__(self, result, value, *, loc=None, ip=None):
+if value is None:
+assert isinstance(result, Attribute)
+super().__init__(result, loc=loc, ip=ip)
+return
+
 if isinstance(value, int):
 super().__init__(IntegerAttr.get(result, value), loc=loc, ip=ip)
 elif isinstance(value, float):
 super().__init__(FloatAttr.get(result, value), loc=loc, ip=ip)
+elif isinstance(value, _array):
+if 8 * value.itemsize != result.element_type.width:
+raise ValueError(
+f"Mismatching array element ({8 * value.itemsize}) and 
type ({result.element_type.width}) width."
+)
+if value.typecode in ["i", "l", "q"]:
+super().__init__(DenseIntElementsAttr.get(value, type=result))
+elif value.typecode in ["f", "d"]:
+super().__init__(DenseFPElementsAttr.get(value, type=result))
+else:
+raise ValueError(f'Unsupported typecode: "{value.typecode}".')
 else:
 super().__init__(value, loc=loc, ip=ip)
 
@@ -79,6 +105,6 @@ def literal_value(self) -> Union[int, float]:
 
 
 def constant(
-result: Type, value: Union[int, float, Attribute], *, loc=None, ip=None
+result: Type, value: Union[int, float, Attribute, _array], *, loc=None, 
ip=None
 ) -> Value:
 return _get_op_result_or_op_results(ConstantOp(result, value, loc=loc, 
ip=ip))

diff  --git a/mlir/test/python/dialects/arith_dialect.py 
b/mlir/test/python/dialects/arith_dialect.py
index 8bb80eed2b8105..c9af5e7b46db84 100644
--- a/mlir/test/python/dialects/arith_dialect.py
+++ b/mlir/test/python/dialects/arith_dialect.py
@@ -4,6 +4,7 @@
 from mlir.ir import *
 import mlir.dialects.arith as arith
 import mlir.dialects.func as func
+from array import array
 
 
 def run(f):
@@ -92,3 +93,42 @@ def __str__(self):
 b = a * a
 # CHECK: ArithValue(%2 = arith.mulf %cst_1, %cst_1 : f64)
 print(b)
+
+
+# CHECK-LABEL: TEST: testArrayConstantConstruction
+@run
+def testArrayConstantConstruction():
+with Context(), Location.unknown():
+module = Module.create()
+with InsertionPoint(module.body):
+i32_array = array("i", [1, 2, 3, 4])
+i32 = IntegerType.get_signless(32)
+vec_i32 = VectorType.get([2, 2], i32)
+arith.constant(vec_i32, i32_array)
+arith.ConstantOp(vec_i32, DenseIntElementsAttr.get(i32_array, 
type=vec_i32))
+
+# "q" is the equivalent of `long long` in C and requires at least
+# 64 bit width integers on both Linux and Windows.
+i64_array = array("q", [5, 6, 7, 8])
+i64 = IntegerType.get_signless(64)
+vec_i64 = VectorType.get([1, 4], i64)
+arith.constant(vec_i64, i64_array)
+arith.ConstantOp(vec_i64, DenseIntElementsAttr.get(i64_array, 
type=vec_i64))
+
+f32_array = array("f", [1.0, 2.0, 3.0, 4.0])
+f32 = F32Type.get()
+vec_f32 = VectorType.get([4, 1], f32)
+arith.constant(vec_f32, f32_array)
+arith.ConstantOp(vec_f32, DenseFPElementsAttr.get(f32_array, 
type=vec_f32))
+
+   

[llvm-branch-commits] [mlir] b246e0d - [mlir][py] better support for arith.constant construction

2024-03-07 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2024-03-07T10:44:36Z
New Revision: b246e0d0bea735652274000fb73a7b2e46434612

URL: 
https://github.com/llvm/llvm-project/commit/b246e0d0bea735652274000fb73a7b2e46434612
DIFF: 
https://github.com/llvm/llvm-project/commit/b246e0d0bea735652274000fb73a7b2e46434612.diff

LOG: [mlir][py] better support for arith.constant construction

Arithmetic constants for vector types can be constructed from objects
implementing Python buffer protocol such as `array.array`. Note that
until Python 3.12, there is no typing support for buffer protocol
implementers, so the annotations use array explicitly.

Added: 


Modified: 
mlir/python/mlir/dialects/arith.py
mlir/test/python/dialects/arith_dialect.py

Removed: 




diff  --git a/mlir/python/mlir/dialects/arith.py 
b/mlir/python/mlir/dialects/arith.py
index 61c6917393f1f9..92da5df9bce665 100644
--- a/mlir/python/mlir/dialects/arith.py
+++ b/mlir/python/mlir/dialects/arith.py
@@ -5,6 +5,8 @@
 from ._arith_ops_gen import *
 from ._arith_ops_gen import _Dialect
 from ._arith_enum_gen import *
+from array import array as _array
+from typing import overload
 
 try:
 from ..ir import *
@@ -43,13 +45,37 @@ def _is_float_type(type: Type):
 class ConstantOp(ConstantOp):
 """Specialization for the constant op class."""
 
+@overload
+def __init__(self, value: Attribute, *, loc=None, ip=None):
+...
+
+@overload
 def __init__(
-self, result: Type, value: Union[int, float, Attribute], *, loc=None, 
ip=None
+self, result: Type, value: Union[int, float, _array], *, loc=None, 
ip=None
 ):
+...
+
+def __init__(self, result, value, *, loc=None, ip=None):
+if value is None:
+assert isinstance(result, Attribute)
+super().__init__(result, loc=loc, ip=ip)
+return
+
 if isinstance(value, int):
 super().__init__(IntegerAttr.get(result, value), loc=loc, ip=ip)
 elif isinstance(value, float):
 super().__init__(FloatAttr.get(result, value), loc=loc, ip=ip)
+elif isinstance(value, _array):
+if 8 * value.itemsize != result.element_type.width:
+raise ValueError(
+f"Mismatching array element ({8 * value.itemsize}) and 
type ({result.element_type.width}) width."
+)
+if value.typecode in ["i", "l", "q"]:
+super().__init__(DenseIntElementsAttr.get(value, type=result))
+elif value.typecode in ["f", "d"]:
+super().__init__(DenseFPElementsAttr.get(value, type=result))
+else:
+raise ValueError(f'Unsupported typecode: "{value.typecode}".')
 else:
 super().__init__(value, loc=loc, ip=ip)
 
@@ -79,6 +105,6 @@ def literal_value(self) -> Union[int, float]:
 
 
 def constant(
-result: Type, value: Union[int, float, Attribute], *, loc=None, ip=None
+result: Type, value: Union[int, float, Attribute, _array], *, loc=None, 
ip=None
 ) -> Value:
 return _get_op_result_or_op_results(ConstantOp(result, value, loc=loc, 
ip=ip))

diff  --git a/mlir/test/python/dialects/arith_dialect.py 
b/mlir/test/python/dialects/arith_dialect.py
index 8bb80eed2b8105..c9af5e7b46db84 100644
--- a/mlir/test/python/dialects/arith_dialect.py
+++ b/mlir/test/python/dialects/arith_dialect.py
@@ -4,6 +4,7 @@
 from mlir.ir import *
 import mlir.dialects.arith as arith
 import mlir.dialects.func as func
+from array import array
 
 
 def run(f):
@@ -92,3 +93,42 @@ def __str__(self):
 b = a * a
 # CHECK: ArithValue(%2 = arith.mulf %cst_1, %cst_1 : f64)
 print(b)
+
+
+# CHECK-LABEL: TEST: testArrayConstantConstruction
+@run
+def testArrayConstantConstruction():
+with Context(), Location.unknown():
+module = Module.create()
+with InsertionPoint(module.body):
+i32_array = array("i", [1, 2, 3, 4])
+i32 = IntegerType.get_signless(32)
+vec_i32 = VectorType.get([2, 2], i32)
+arith.constant(vec_i32, i32_array)
+arith.ConstantOp(vec_i32, DenseIntElementsAttr.get(i32_array, 
type=vec_i32))
+
+# "q" is the equivalent of `long long` in C and requires at least
+# 64 bit width integers on both Linux and Windows.
+i64_array = array("q", [5, 6, 7, 8])
+i64 = IntegerType.get_signless(64)
+vec_i64 = VectorType.get([1, 4], i64)
+arith.constant(vec_i64, i64_array)
+arith.ConstantOp(vec_i64, DenseIntElementsAttr.get(i64_array, 
type=vec_i64))
+
+f32_array = array("f", [1.0, 2.0, 3.0, 4.0])
+f32 = F32Type.get()
+vec_f32 = VectorType.get([4, 1], f32)
+arith.constant(vec_f32, f32_array)
+arith.ConstantOp(vec_f32, DenseFPElementsAttr.get(f32_array, 
type=vec_f32))
+
+   

[llvm-branch-commits] [mlir] d39cb79 - [mlir][py] better support for arith.constant construction

2024-03-07 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2024-03-07T15:02:35Z
New Revision: d39cb79cddadbb6dc6914a8c9f0a54e0f8ce1329

URL: 
https://github.com/llvm/llvm-project/commit/d39cb79cddadbb6dc6914a8c9f0a54e0f8ce1329
DIFF: 
https://github.com/llvm/llvm-project/commit/d39cb79cddadbb6dc6914a8c9f0a54e0f8ce1329.diff

LOG: [mlir][py] better support for arith.constant construction

Arithmetic constants for vector types can be constructed from objects
implementing Python buffer protocol such as `array.array`. Note that
until Python 3.12, there is no typing support for buffer protocol
implementers, so the annotations use array explicitly.

Added: 


Modified: 
mlir/python/mlir/dialects/arith.py
mlir/test/python/dialects/arith_dialect.py

Removed: 




diff  --git a/mlir/python/mlir/dialects/arith.py 
b/mlir/python/mlir/dialects/arith.py
index 61c6917393f1f9..92da5df9bce665 100644
--- a/mlir/python/mlir/dialects/arith.py
+++ b/mlir/python/mlir/dialects/arith.py
@@ -5,6 +5,8 @@
 from ._arith_ops_gen import *
 from ._arith_ops_gen import _Dialect
 from ._arith_enum_gen import *
+from array import array as _array
+from typing import overload
 
 try:
 from ..ir import *
@@ -43,13 +45,37 @@ def _is_float_type(type: Type):
 class ConstantOp(ConstantOp):
 """Specialization for the constant op class."""
 
+@overload
+def __init__(self, value: Attribute, *, loc=None, ip=None):
+...
+
+@overload
 def __init__(
-self, result: Type, value: Union[int, float, Attribute], *, loc=None, 
ip=None
+self, result: Type, value: Union[int, float, _array], *, loc=None, 
ip=None
 ):
+...
+
+def __init__(self, result, value, *, loc=None, ip=None):
+if value is None:
+assert isinstance(result, Attribute)
+super().__init__(result, loc=loc, ip=ip)
+return
+
 if isinstance(value, int):
 super().__init__(IntegerAttr.get(result, value), loc=loc, ip=ip)
 elif isinstance(value, float):
 super().__init__(FloatAttr.get(result, value), loc=loc, ip=ip)
+elif isinstance(value, _array):
+if 8 * value.itemsize != result.element_type.width:
+raise ValueError(
+f"Mismatching array element ({8 * value.itemsize}) and 
type ({result.element_type.width}) width."
+)
+if value.typecode in ["i", "l", "q"]:
+super().__init__(DenseIntElementsAttr.get(value, type=result))
+elif value.typecode in ["f", "d"]:
+super().__init__(DenseFPElementsAttr.get(value, type=result))
+else:
+raise ValueError(f'Unsupported typecode: "{value.typecode}".')
 else:
 super().__init__(value, loc=loc, ip=ip)
 
@@ -79,6 +105,6 @@ def literal_value(self) -> Union[int, float]:
 
 
 def constant(
-result: Type, value: Union[int, float, Attribute], *, loc=None, ip=None
+result: Type, value: Union[int, float, Attribute, _array], *, loc=None, 
ip=None
 ) -> Value:
 return _get_op_result_or_op_results(ConstantOp(result, value, loc=loc, 
ip=ip))

diff  --git a/mlir/test/python/dialects/arith_dialect.py 
b/mlir/test/python/dialects/arith_dialect.py
index 8bb80eed2b8105..c9af5e7b46db84 100644
--- a/mlir/test/python/dialects/arith_dialect.py
+++ b/mlir/test/python/dialects/arith_dialect.py
@@ -4,6 +4,7 @@
 from mlir.ir import *
 import mlir.dialects.arith as arith
 import mlir.dialects.func as func
+from array import array
 
 
 def run(f):
@@ -92,3 +93,42 @@ def __str__(self):
 b = a * a
 # CHECK: ArithValue(%2 = arith.mulf %cst_1, %cst_1 : f64)
 print(b)
+
+
+# CHECK-LABEL: TEST: testArrayConstantConstruction
+@run
+def testArrayConstantConstruction():
+with Context(), Location.unknown():
+module = Module.create()
+with InsertionPoint(module.body):
+i32_array = array("i", [1, 2, 3, 4])
+i32 = IntegerType.get_signless(32)
+vec_i32 = VectorType.get([2, 2], i32)
+arith.constant(vec_i32, i32_array)
+arith.ConstantOp(vec_i32, DenseIntElementsAttr.get(i32_array, 
type=vec_i32))
+
+# "q" is the equivalent of `long long` in C and requires at least
+# 64 bit width integers on both Linux and Windows.
+i64_array = array("q", [5, 6, 7, 8])
+i64 = IntegerType.get_signless(64)
+vec_i64 = VectorType.get([1, 4], i64)
+arith.constant(vec_i64, i64_array)
+arith.ConstantOp(vec_i64, DenseIntElementsAttr.get(i64_array, 
type=vec_i64))
+
+f32_array = array("f", [1.0, 2.0, 3.0, 4.0])
+f32 = F32Type.get()
+vec_f32 = VectorType.get([4, 1], f32)
+arith.constant(vec_f32, f32_array)
+arith.ConstantOp(vec_f32, DenseFPElementsAttr.get(f32_array, 
type=vec_f32))
+
+   

[llvm-branch-commits] [mlir] 1e73955 - [mlir] Use more C99 comments in C API header files

2021-01-25 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2021-01-25T19:23:06+01:00
New Revision: 1e739552ee96db4b3f2d792976ea849cb6f23650

URL: 
https://github.com/llvm/llvm-project/commit/1e739552ee96db4b3f2d792976ea849cb6f23650
DIFF: 
https://github.com/llvm/llvm-project/commit/1e739552ee96db4b3f2d792976ea849cb6f23650.diff

LOG: [mlir] Use more C99 comments in C API header files

These were left over from the original reformatting commit.

Reviewed By: stellaraccident

Differential Revision: https://reviews.llvm.org/D95357

Added: 


Modified: 
mlir/include/mlir-c/AffineExpr.h
mlir/include/mlir-c/AffineMap.h
mlir/include/mlir-c/BuiltinAttributes.h
mlir/include/mlir-c/BuiltinTypes.h
mlir/include/mlir-c/Diagnostics.h
mlir/include/mlir-c/IR.h
mlir/include/mlir-c/Pass.h
mlir/include/mlir-c/Support.h

Removed: 




diff  --git a/mlir/include/mlir-c/AffineExpr.h 
b/mlir/include/mlir-c/AffineExpr.h
index d5c6e7b9f29e..5516f29088e4 100644
--- a/mlir/include/mlir-c/AffineExpr.h
+++ b/mlir/include/mlir-c/AffineExpr.h
@@ -17,17 +17,16 @@ extern "C" {
 #endif
 
 
//===--===//
-/** Opaque type declarations.
- *
- * Types are exposed to C bindings as structs containing opaque pointers. They
- * are not supposed to be inspected from C. This allows the underlying
- * representation to change without affecting the API users. The use of structs
- * instead of typedefs enables some type safety as structs are not implicitly
- * convertible to each other.
- *
- * Instances of these types may or may not own the underlying object. The
- * ownership semantics is defined by how an instance of the type was obtained.
- */
+// Opaque type declarations.
+//
+// Types are exposed to C bindings as structs containing opaque pointers. They
+// are not supposed to be inspected from C. This allows the underlying
+// representation to change without affecting the API users. The use of structs
+// instead of typedefs enables some type safety as structs are not implicitly
+// convertible to each other.
+//
+// Instances of these types may or may not own the underlying object. The
+// ownership semantics is defined by how an instance of the type was obtained.
 
//===--===//
 
 #define DEFINE_C_API_STRUCT(name, storage) 
\
@@ -54,9 +53,9 @@ inline static bool mlirAffineExprIsNull(MlirAffineExpr 
affineExpr) {
   return affineExpr.ptr == NULL;
 }
 
-/** Prints an affine expression by sending chunks of the string representation
- * and forwarding `userData to `callback`. Note that the callback may be called
- * several times with consecutive chunks of the string. */
+/// Prints an affine expression by sending chunks of the string representation
+/// and forwarding `userData to `callback`. Note that the callback may be 
called
+/// several times with consecutive chunks of the string.
 MLIR_CAPI_EXPORTED void mlirAffineExprPrint(MlirAffineExpr affineExpr,
 MlirStringCallback callback,
 void *userData);
@@ -64,17 +63,17 @@ MLIR_CAPI_EXPORTED void mlirAffineExprPrint(MlirAffineExpr 
affineExpr,
 /// Prints the affine expression to the standard error stream.
 MLIR_CAPI_EXPORTED void mlirAffineExprDump(MlirAffineExpr affineExpr);
 
-/** Checks whether the given affine expression is made out of only symbols and
- * constants. */
+/// Checks whether the given affine expression is made out of only symbols and
+/// constants.
 MLIR_CAPI_EXPORTED bool
 mlirAffineExprIsSymbolicOrConstant(MlirAffineExpr affineExpr);
 
-/** Checks whether the given affine expression is a pure affine expression, 
i.e.
- * mul, floordiv, ceildic, and mod is only allowed w.r.t constants. */
+/// Checks whether the given affine expression is a pure affine expression, 
i.e.
+/// mul, floordiv, ceildic, and mod is only allowed w.r.t constants.
 MLIR_CAPI_EXPORTED bool mlirAffineExprIsPureAffine(MlirAffineExpr affineExpr);
 
-/** Returns the greatest known integral divisor of this affine expression. The
- * result is always positive. */
+/// Returns the greatest known integral divisor of this affine expression. The
+/// result is always positive.
 MLIR_CAPI_EXPORTED int64_t
 mlirAffineExprGetLargestKnownDivisor(MlirAffineExpr affineExpr);
 
@@ -82,8 +81,8 @@ mlirAffineExprGetLargestKnownDivisor(MlirAffineExpr 
affineExpr);
 MLIR_CAPI_EXPORTED bool mlirAffineExprIsMultipleOf(MlirAffineExpr affineExpr,
int64_t factor);
 
-/** Checks whether the given affine expression involves AffineDimExpr
- * 'position'. */
+/// Checks whether the given affine expression involves AffineDimExpr
+/// 'position'.
 MLIR_CAPI_EXPORTED bool mlirAffineExprIsFunctionOfDim(MlirAffineExpr 
affineExpr,

[llvm-branch-commits] [mlir] f5c7c03 - [mlir] Add C API for IntegerSet

2021-01-25 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2021-01-25T20:16:22+01:00
New Revision: f5c7c031e2493168b3c2cfea3219e2131cc01483

URL: 
https://github.com/llvm/llvm-project/commit/f5c7c031e2493168b3c2cfea3219e2131cc01483
DIFF: 
https://github.com/llvm/llvm-project/commit/f5c7c031e2493168b3c2cfea3219e2131cc01483.diff

LOG: [mlir] Add C API for IntegerSet

Depends On D95357

Reviewed By: stellaraccident

Differential Revision: https://reviews.llvm.org/D95368

Added: 
mlir/include/mlir-c/IntegerSet.h
mlir/include/mlir/CAPI/IntegerSet.h
mlir/lib/CAPI/IR/IntegerSet.cpp

Modified: 
mlir/include/mlir/IR/IntegerSet.h
mlir/lib/CAPI/IR/CMakeLists.txt
mlir/test/CAPI/ir.c

Removed: 




diff  --git a/mlir/include/mlir-c/IntegerSet.h 
b/mlir/include/mlir-c/IntegerSet.h
new file mode 100644
index ..058be414d2ee
--- /dev/null
+++ b/mlir/include/mlir-c/IntegerSet.h
@@ -0,0 +1,131 @@
+//===-- mlir-c/IntegerSet.h - C API for MLIR Affine maps --*- C 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM
+// Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#ifndef MLIR_C_INTEGERSET_H
+#define MLIR_C_INTEGERSET_H
+
+#include "mlir-c/AffineExpr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//===--===//
+// Opaque type declarations.
+//
+// Types are exposed to C bindings as structs containing opaque pointers. They
+// are not supposed to be inspected from C. This allows the underlying
+// representation to change without affecting the API users. The use of structs
+// instead of typedefs enables some type safety as structs are not implicitly
+// convertible to each other.
+//
+// Instances of these types may or may not own the underlying object. The
+// ownership semantics is defined by how an instance of the type was obtained.
+//===--===//
+
+#define DEFINE_C_API_STRUCT(name, storage) 
\
+  struct name {
\
+storage *ptr;  
\
+  };   
\
+  typedef struct name name
+
+DEFINE_C_API_STRUCT(MlirIntegerSet, const void);
+
+#undef DEFINE_C_API_STRUCT
+
+/// Gets the context in which the given integer set lives.
+MLIR_CAPI_EXPORTED MlirContext mlirIntegerSetGetContext(MlirIntegerSet set);
+
+/// Checks whether an integer set is a null object.
+static inline bool mlirIntegerSetIsNull(MlirIntegerSet set) { return !set.ptr; 
}
+
+/// Checks if two integer set objects are equal. This is a "shallow" comparison
+/// of two objects. Only the sets with some small number of constraints are
+/// uniqued and compare equal here. Set objects that represent the same integer
+/// set with 
diff erent constraints may be considered non-equal by this check.
+/// Set 
diff erence followed by an (expensive) emptiness check should be used to
+/// check equivalence of the underlying integer sets.
+MLIR_CAPI_EXPORTED bool mlirIntegerSetEqual(MlirIntegerSet s1,
+MlirIntegerSet s2);
+
+/// Prints an integer set by sending chunks of the string representation and
+/// forwarding `userData to `callback`. Note that the callback may be called
+/// several times with consecutive chunks of the string.
+MLIR_CAPI_EXPORTED void mlirIntegerSetPrint(MlirIntegerSet set,
+MlirStringCallback callback,
+void *userData);
+
+/// Prints an integer set to the standard error stream.
+MLIR_CAPI_EXPORTED void mlirIntegerSetDump(MlirIntegerSet set);
+
+/// Gets or creates a new canonically empty integer set with the give number of
+/// dimensions and symbols in the given context.
+MLIR_CAPI_EXPORTED MlirIntegerSet mlirIntegerSetEmptyGet(MlirContext context,
+ intptr_t numDims,
+ intptr_t numSymbols);
+
+/// Gets or creates a new integer set in the given context. The set is defined
+/// by a list of affine constraints, with the given number of input dimensions
+/// and symbols, which are treated as either equalities (eqFlags is 1) or
+/// inequalities (eqFlags is 0). Both `constraints` and `eqFlags` are expected
+/// to point to at least `numConstraint` consecutive values.
+MLIR_CAPI_EXPORTED MlirIntegerSet
+mlirIntegerSetGet(MlirContext context, intptr_t numDims, intptr_t numSymbols,
+  intptr_t numConstraints, const MlirAffineExpr *constraints,
+ 

[llvm-branch-commits] [mlir] 4fa01f7 - [mlir][CAPI] Fix inline function declaration

2021-01-12 Thread Alex Zinenko via llvm-branch-commits

Author: Vladislav Vinogradov
Date: 2021-01-12T17:05:02+01:00
New Revision: 4fa01f72de6cc48a44afe057c04803711160c92d

URL: 
https://github.com/llvm/llvm-project/commit/4fa01f72de6cc48a44afe057c04803711160c92d
DIFF: 
https://github.com/llvm/llvm-project/commit/4fa01f72de6cc48a44afe057c04803711160c92d.diff

LOG: [mlir][CAPI] Fix inline function declaration

Add `static` keyword, otherwise build fail with linker error for some cases.

Reviewed By: ftynse

Differential Revision: https://reviews.llvm.org/D94496

Added: 


Modified: 
mlir/include/mlir-c/AffineExpr.h

Removed: 




diff  --git a/mlir/include/mlir-c/AffineExpr.h 
b/mlir/include/mlir-c/AffineExpr.h
index ec445682c011..d5c6e7b9f29e 100644
--- a/mlir/include/mlir-c/AffineExpr.h
+++ b/mlir/include/mlir-c/AffineExpr.h
@@ -50,7 +50,7 @@ MLIR_CAPI_EXPORTED bool mlirAffineExprEqual(MlirAffineExpr 
lhs,
 
 /// Returns `true` if the given affine expression is a null expression. Note
 /// constant zero is not a null expression.
-inline bool mlirAffineExprIsNull(MlirAffineExpr affineExpr) {
+inline static bool mlirAffineExprIsNull(MlirAffineExpr affineExpr) {
   return affineExpr.ptr == NULL;
 }
 



___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] 9667d15 - [mlir] Fix for LIT tests

2021-01-12 Thread Alex Zinenko via llvm-branch-commits

Author: Vladislav Vinogradov
Date: 2021-01-12T17:07:23+01:00
New Revision: 9667d15e7496e6d8c313251f22ac157dbbd0c1c2

URL: 
https://github.com/llvm/llvm-project/commit/9667d15e7496e6d8c313251f22ac157dbbd0c1c2
DIFF: 
https://github.com/llvm/llvm-project/commit/9667d15e7496e6d8c313251f22ac157dbbd0c1c2.diff

LOG: [mlir] Fix for LIT tests

Add `MLIR_SPIRV_CPU_RUNNER_ENABLED` to `llvm_canonicalize_cmake_booleans`.

Reviewed By: mehdi_amini

Differential Revision: https://reviews.llvm.org/D94407

Added: 


Modified: 
mlir/test/CMakeLists.txt

Removed: 




diff  --git a/mlir/test/CMakeLists.txt b/mlir/test/CMakeLists.txt
index f6d5af141630..293d93268a11 100644
--- a/mlir/test/CMakeLists.txt
+++ b/mlir/test/CMakeLists.txt
@@ -12,6 +12,7 @@ llvm_canonicalize_cmake_booleans(
   MLIR_CUDA_RUNNER_ENABLED
   MLIR_ROCM_CONVERSIONS_ENABLED
   MLIR_ROCM_RUNNER_ENABLED
+  MLIR_SPIRV_CPU_RUNNER_ENABLED
   MLIR_VULKAN_RUNNER_ENABLED
   )
 



___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] 7fd1850 - [mlir] Update LLVM dialect type documentation

2021-01-12 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2021-01-12T22:38:24+01:00
New Revision: 7fd18508134112edb93852c16923a74bfff99cd2

URL: 
https://github.com/llvm/llvm-project/commit/7fd18508134112edb93852c16923a74bfff99cd2
DIFF: 
https://github.com/llvm/llvm-project/commit/7fd18508134112edb93852c16923a74bfff99cd2.diff

LOG: [mlir] Update LLVM dialect type documentation

Recent commits reconfigured LLVM dialect types to use built-in types whenever
possible. Update the documentation accordingly.

Reviewed By: mehdi_amini

Differential Revision: https://reviews.llvm.org/D94485

Added: 


Modified: 
mlir/docs/Dialects/LLVM.md

Removed: 




diff  --git a/mlir/docs/Dialects/LLVM.md b/mlir/docs/Dialects/LLVM.md
index d232ffab148c..1b85091b0756 100644
--- a/mlir/docs/Dialects/LLVM.md
+++ b/mlir/docs/Dialects/LLVM.md
@@ -130,9 +130,9 @@ Examples:
 %3 = llvm.mlir.constant(dense<1.0> : vector<4xf32>) : vector<4xf32>
 ```
 
-Note that constants use built-in types within the initializer definition: MLIR
-attributes are typed and the attributes used for constants require a built-in
-type.
+Note that constants list the type twice. This is an artifact of the LLVM 
dialect
+not using built-in types, which are used for typed MLIR attributes. The syntax
+will be reevaluated after considering composite constants.
 
 ### Globals
 
@@ -186,33 +186,47 @@ attribute.
 
 ## Types
 
-LLVM dialect defines a set of types that correspond to LLVM IR types. The
-dialect type system is _closed_: types from other dialects are not allowed
-within LLVM dialect aggregate types. This property allows for more concise
-custom syntax and ensures easy translation to LLVM IR.
-
-Similarly to other MLIR context-owned objects, the creation and manipulation of
-LLVM dialect types is thread-safe.
+LLVM dialect uses built-in types whenever possible and defines a set of
+complementary types, which correspond to the LLVM IR types that cannot be
+directly represented with built-in types. Similarly to other MLIR context-owned
+objects, the creation and manipulation of LLVM dialect types is thread-safe.
 
 MLIR does not support module-scoped named type declarations, e.g. `%s = type
 {i32, i32}` in LLVM IR. Instead, types must be fully specified at each use,
 except for recursive types where only the first reference to a named type needs
-to be fully specified. MLIR type aliases are supported for top-level types, 
i.e.
-they cannot be used inside the type due to type system closedness.
+to be fully specified. MLIR [type aliases](LangRef.md#type-aliases) can be used
+to achieve more compact syntax.
 
 The general syntax of LLVM dialect types is `!llvm.`, followed by a type kind
 identifier (e.g., `ptr` for pointer or `struct` for structure) and by an
 optional list of type parameters in angle brackets. The dialect follows MLIR
 style for types with nested angle brackets and keyword specifiers rather than
-using 
diff erent bracket styles to 
diff erentiate types. Inside angle brackets,
-the `!llvm` prefix is omitted for brevity; thanks to closedness of the type
-system, all types are assumed to be defined in the LLVM dialect. For example,
-`!llvm.ptr>` is a pointer to a packed structure type
-containing an 8-bit and a 32-bit integer.
+using 
diff erent bracket styles to 
diff erentiate types. Types inside the angle
+brackets may omit the `!llvm.` prefix for brevity: the parser first attempts to
+find a type (starting with `!` or a built-in type) and falls back to accepting 
a
+keyword. For example, `!llvm.ptr>` and `!llvm.ptr>` are
+equivalent, with the latter being the canonical form, and denote a pointer to a
+pointer to a 32-bit integer.
+
+### Built-in Type Compatibility
+
+LLVM dialect accepts a subset of built-in types that are referred to as _LLVM
+dialect-compatible types_. The following types are compatible:
 
-### Simple Types
+-   Signless integers - `iN` (`IntegerType`).
+-   Floating point types - `bfloat`, `half`, `float`, `double` (`FloatType`).
+-   1D vectors of signless integers or floating point types - `vector`
+(`VectorType`).
 
-The following non-parametric types are supported.
+Note that only a subset of types that can be represented by a given class is
+compatible. For example, signed and unsigned integers are not compatible. LLVM
+provides a function, `bool LLVM::isCompatibleType(Type)`, that can be used as a
+compatibility check.
+
+### Additional Simple Types
+
+The following non-parametric types derived from the LLVM IR are available in 
the
+LLVM dialect:
 
 -   `!llvm.fp128` (`LLVMFP128Type`) - 128-bit floating-point value as per
 IEEE-754-2008.
@@ -231,19 +245,10 @@ The following non-parametric types are supported.
 These types represent a single value (or an absence thereof in case of `void`)
 and correspond to their LLVM IR counterparts.
 
-### Parametric Types
-
- Integer Types
+### Additional Parametric Types
 
-Integer types are parametric in 

[llvm-branch-commits] [mlir] ed205f6 - [mlir] Update doc to omit the usage of LLVMIntegerType

2021-01-14 Thread Alex Zinenko via llvm-branch-commits

Author: lewuathe
Date: 2021-01-14T09:29:24+01:00
New Revision: ed205f63b4a288ccbffc9af58333d09a7cec40dc

URL: 
https://github.com/llvm/llvm-project/commit/ed205f63b4a288ccbffc9af58333d09a7cec40dc
DIFF: 
https://github.com/llvm/llvm-project/commit/ed205f63b4a288ccbffc9af58333d09a7cec40dc.diff

LOG: [mlir] Update doc to omit the usage of LLVMIntegerType

Since [[ https://reviews.llvm.org/D94178 | the LLVMIntegerType was replaced 
with build-in integer type ]], the usage in the tutorial should be also updated 
accordingly.
We need to update chapter 6 for Toy tutorial specifically.

See: https://reviews.llvm.org/D94178

Reviewed By: rriddle

Differential Revision: https://reviews.llvm.org/D94651

Added: 


Modified: 
mlir/docs/Tutorials/Toy/Ch-6.md

Removed: 




diff  --git a/mlir/docs/Tutorials/Toy/Ch-6.md b/mlir/docs/Tutorials/Toy/Ch-6.md
index 1093ae9fe2ba..bddd93688ddb 100644
--- a/mlir/docs/Tutorials/Toy/Ch-6.md
+++ b/mlir/docs/Tutorials/Toy/Ch-6.md
@@ -37,9 +37,9 @@ static FlatSymbolRefAttr getOrInsertPrintf(PatternRewriter 
&rewriter,
 
   // Create a function declaration for printf, the signature is:
   //   * `i32 (i8*, ...)`
-  auto llvmI32Ty = LLVM::LLVMIntegerType::get(context, 32);
+  auto llvmI32Ty = IntegerType::get(context, 32);
   auto llvmI8PtrTy =
-  LLVM::LLVMPointerType::get(LLVM::LLVMIntegerType::get(context, 8));
+  LLVM::LLVMPointerType::get(IntegerType::get(context, 8));
   auto llvmFnType = LLVM::LLVMFunctionType::get(llvmI32Ty, llvmI8PtrTy,
 /*isVarArg=*/true);
 



___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] 6ebeba8 - Support emptiness checks for unbounded FlatAffineConstraints.

2021-01-14 Thread Alex Zinenko via llvm-branch-commits

Author: Arjun P
Date: 2021-01-14T19:33:37+01:00
New Revision: 6ebeba88f51959d763a8f274cdfecea46d51d28c

URL: 
https://github.com/llvm/llvm-project/commit/6ebeba88f51959d763a8f274cdfecea46d51d28c
DIFF: 
https://github.com/llvm/llvm-project/commit/6ebeba88f51959d763a8f274cdfecea46d51d28c.diff

LOG: Support emptiness checks for unbounded FlatAffineConstraints.

With this, we have complete support for emptiness checks. This also paves the 
way for future support to check if two FlatAffineConstraints are equal.

Reviewed By: ftynse

Differential Revision: https://reviews.llvm.org/D94272

Added: 
mlir/include/mlir/Analysis/LinearTransform.h
mlir/lib/Analysis/LinearTransform.cpp
mlir/unittests/Analysis/LinearTransformTest.cpp

Modified: 
mlir/include/mlir/Analysis/AffineStructures.h
mlir/include/mlir/Analysis/Presburger/Fraction.h
mlir/include/mlir/Analysis/Presburger/Matrix.h
mlir/include/mlir/Analysis/Presburger/Simplex.h
mlir/lib/Analysis/AffineStructures.cpp
mlir/lib/Analysis/CMakeLists.txt
mlir/lib/Analysis/Presburger/CMakeLists.txt
mlir/lib/Analysis/Presburger/Matrix.cpp
mlir/lib/Analysis/Presburger/Simplex.cpp
mlir/unittests/Analysis/AffineStructuresTest.cpp
mlir/unittests/Analysis/CMakeLists.txt

Removed: 




diff  --git a/mlir/include/mlir/Analysis/AffineStructures.h 
b/mlir/include/mlir/Analysis/AffineStructures.h
index 25071db100e3..fa80db7d4b63 100644
--- a/mlir/include/mlir/Analysis/AffineStructures.h
+++ b/mlir/include/mlir/Analysis/AffineStructures.h
@@ -13,6 +13,7 @@
 #ifndef MLIR_ANALYSIS_AFFINE_STRUCTURES_H
 #define MLIR_ANALYSIS_AFFINE_STRUCTURES_H
 
+#include "mlir/Analysis/Presburger/Matrix.h"
 #include "mlir/IR/AffineExpr.h"
 #include "mlir/IR/OpDefinition.h"
 #include "mlir/Support/LogicalResult.h"
@@ -153,6 +154,12 @@ class FlatAffineConstraints {
   /// false if a solution exists or all tests were inconclusive.
   bool isIntegerEmpty() const;
 
+  // Returns a matrix where each row is a vector along which the polytope is
+  // bounded. The span of the returned vectors is guaranteed to contain all
+  // such vectors. The returned vectors are NOT guaranteed to be linearly
+  // independent. This function should not be called on empty sets.
+  Matrix getBoundedDirections() const;
+
   /// Find a sample point satisfying the constraints. This uses a branch and
   /// bound algorithm with generalized basis reduction, which always works if
   /// the set is bounded. This should not be called for unbounded sets.

diff  --git a/mlir/include/mlir/Analysis/LinearTransform.h 
b/mlir/include/mlir/Analysis/LinearTransform.h
new file mode 100644
index ..0850f5a00609
--- /dev/null
+++ b/mlir/include/mlir/Analysis/LinearTransform.h
@@ -0,0 +1,48 @@
+//===- LinearTransform.h - MLIR LinearTransform Class ---*- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+// Support for linear transforms and applying them to FlatAffineConstraints.
+//
+//===--===//
+
+#ifndef MLIR_ANALYSIS_LINEARTRANSFORM_H
+#define MLIR_ANALYSIS_LINEARTRANSFORM_H
+
+#include "mlir/Analysis/AffineStructures.h"
+#include "mlir/Analysis/Presburger/Matrix.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace mlir {
+
+class LinearTransform {
+public:
+  explicit LinearTransform(Matrix &&oMatrix);
+  explicit LinearTransform(const Matrix &oMatrix);
+
+  // Returns a linear transform T such that MT is M in column echelon form.
+  // Also returns the number of non-zero columns in MT.
+  //
+  // Specifically, T is such that in every column the first non-zero row is
+  // strictly below that of the previous column, and all columns which have 
only
+  // zeros are at the end.
+  static std::pair
+  makeTransformToColumnEchelon(Matrix m);
+
+  // Returns a FlatAffineConstraints having a constraint vector vT for every
+  // constraint vector v in fac, where T is this transform.
+  FlatAffineConstraints applyTo(const FlatAffineConstraints &fac);
+
+  // Post-multiply the given vector v with this transform, say T, returning vT.
+  SmallVector applyTo(ArrayRef v);
+
+private:
+  Matrix matrix;
+};
+
+} // namespace mlir
+#endif // MLIR_ANALYSIS_LINEARTRANSFORM_H

diff  --git a/mlir/include/mlir/Analysis/Presburger/Fraction.h 
b/mlir/include/mlir/Analysis/Presburger/Fraction.h
index 09996c486ef3..61b0915e559e 100644
--- a/mlir/include/mlir/Analysis/Presburger/Fraction.h
+++ b/mlir/include/mlir/Analysis/Presburger/Fraction.h
@@ -64,6 +64,8 @@ inline bool operator<=(Fraction x, Fraction y) { return 
compare(x, y) <= 0; }
 
 inline bool operator==(Fraction x, Fraction y) 

[llvm-branch-commits] [mlir] aca240b - [mlir] Fix cross-compilation (Linalg ODS gen)

2021-01-18 Thread Alex Zinenko via llvm-branch-commits

Author: Vladislav Vinogradov
Date: 2021-01-18T11:57:55+01:00
New Revision: aca240b4f69e908b31e30b7ccece3c5b1d58426e

URL: 
https://github.com/llvm/llvm-project/commit/aca240b4f69e908b31e30b7ccece3c5b1d58426e
DIFF: 
https://github.com/llvm/llvm-project/commit/aca240b4f69e908b31e30b7ccece3c5b1d58426e.diff

LOG: [mlir] Fix cross-compilation (Linalg ODS gen)

Use cross-compilation approach for `mlir-linalg-ods-gen` application
similar to TblGen tools.

Reviewed By: nicolasvasilache

Differential Revision: https://reviews.llvm.org/D94598

Added: 


Modified: 
mlir/CMakeLists.txt
mlir/include/mlir/Dialect/Linalg/IR/CMakeLists.txt
mlir/tools/CMakeLists.txt
mlir/tools/mlir-linalg-ods-gen/CMakeLists.txt

Removed: 




diff  --git a/mlir/CMakeLists.txt b/mlir/CMakeLists.txt
index 2cf37753ea5c..cbae5fd54823 100644
--- a/mlir/CMakeLists.txt
+++ b/mlir/CMakeLists.txt
@@ -98,6 +98,7 @@ include_directories( ${MLIR_INCLUDE_DIR})
 # MLIR_TABLEGEN_EXE in PARENT_SCOPE which gets lost if that folder is included
 # from another directory like tools
 add_subdirectory(tools/mlir-tblgen)
+add_subdirectory(tools/mlir-linalg-ods-gen)
 
 add_subdirectory(include/mlir)
 add_subdirectory(lib)

diff  --git a/mlir/include/mlir/Dialect/Linalg/IR/CMakeLists.txt 
b/mlir/include/mlir/Dialect/Linalg/IR/CMakeLists.txt
index fe67dcb7a660..09db72806565 100644
--- a/mlir/include/mlir/Dialect/Linalg/IR/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/Linalg/IR/CMakeLists.txt
@@ -11,17 +11,19 @@ function(add_linalg_ods_gen tc_filename output_file)
 PROPERTIES GENERATED TRUE)
   add_custom_command(
 OUTPUT ${GEN_ODS_FILE} ${GEN_CPP_FILE}
-COMMAND mlir-linalg-ods-gen -gen-ods-decl ${TC_SOURCE} > ${GEN_ODS_FILE}
-COMMAND mlir-linalg-ods-gen -gen-impl ${TC_SOURCE} > ${GEN_CPP_FILE}
+COMMAND ${MLIR_LINALG_ODS_GEN_EXE} -gen-ods-decl ${TC_SOURCE} > 
${GEN_ODS_FILE}
+COMMAND ${MLIR_LINALG_ODS_GEN_EXE} -gen-impl ${TC_SOURCE} > ${GEN_CPP_FILE}
 MAIN_DEPENDENCY
 ${TC_SOURCE}
 DEPENDS
-mlir-linalg-ods-gen
+${MLIR_LINALG_ODS_GEN_EXE}
+${MLIR_LINALG_ODS_GEN_TARGET}
 VERBATIM)
   add_custom_target(
 MLIR${output_file}IncGen
 DEPENDS
-mlir-linalg-ods-gen
+${MLIR_LINALG_ODS_GEN_EXE}
+${MLIR_LINALG_ODS_GEN_TARGET}
 ${GEN_ODS_FILE} ${GEN_CPP_FILE})
 endfunction()
 

diff  --git a/mlir/tools/CMakeLists.txt b/mlir/tools/CMakeLists.txt
index ab59514ef6a7..3a60ae25548e 100644
--- a/mlir/tools/CMakeLists.txt
+++ b/mlir/tools/CMakeLists.txt
@@ -1,10 +1,9 @@
 add_subdirectory(mlir-cuda-runner)
 add_subdirectory(mlir-cpu-runner)
-add_subdirectory(mlir-linalg-ods-gen)
 add_subdirectory(mlir-opt)
 add_subdirectory(mlir-reduce)
 add_subdirectory(mlir-rocm-runner)
 add_subdirectory(mlir-shlib)
 add_subdirectory(mlir-spirv-cpu-runner)
 add_subdirectory(mlir-translate)
-add_subdirectory(mlir-vulkan-runner)
\ No newline at end of file
+add_subdirectory(mlir-vulkan-runner)

diff  --git a/mlir/tools/mlir-linalg-ods-gen/CMakeLists.txt 
b/mlir/tools/mlir-linalg-ods-gen/CMakeLists.txt
index bc9a0c1f310a..7a0f79798268 100644
--- a/mlir/tools/mlir-linalg-ods-gen/CMakeLists.txt
+++ b/mlir/tools/mlir-linalg-ods-gen/CMakeLists.txt
@@ -10,3 +10,18 @@ target_link_libraries(mlir-linalg-ods-gen PRIVATE
   MLIRSupport
   MLIRIR
   )
+
+set(MLIR_LINALG_ODS_GEN_EXE mlir-linalg-ods-gen PARENT_SCOPE)
+set(MLIR_LINALG_ODS_GEN_TARGET mlir-linalg-ods-gen PARENT_SCOPE)
+
+if(LLVM_USE_HOST_TOOLS)
+  build_native_tool(mlir-linalg-ods-gen MLIR_LINALG_ODS_GEN_EXE DEPENDS 
mlir-linalg-ods-gen)
+  set(MLIR_LINALG_ODS_GEN_EXE ${MLIR_LINALG_ODS_GEN_EXE} PARENT_SCOPE)
+
+  add_custom_target(mlir-linalg-ods-gen-host DEPENDS 
${MLIR_LINALG_ODS_GEN_EXE})
+  set(MLIR_LINALG_ODS_GEN_TARGET mlir-linalg-ods-gen-host DEPENDS PARENT_SCOPE)
+
+  if(NOT LLVM_BUILD_UTILS)
+set_target_properties(mlir-linalg-ods-gen PROPERTIES EXCLUDE_FROM_ALL ON)
+  endif()
+endif()



___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] 9a60ad2 - [mlir] Clarify docs around LLVM dialect-compatible types

2021-01-19 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2021-01-19T13:42:16+01:00
New Revision: 9a60ad216d2fa2e9701849922bfb0db9917f9c93

URL: 
https://github.com/llvm/llvm-project/commit/9a60ad216d2fa2e9701849922bfb0db9917f9c93
DIFF: 
https://github.com/llvm/llvm-project/commit/9a60ad216d2fa2e9701849922bfb0db9917f9c93.diff

LOG: [mlir] Clarify docs around LLVM dialect-compatible types

Explicitly mention that there is exactly one MLIR type that corresponds
to a given LLVM IR type.

Added: 


Modified: 
mlir/docs/Dialects/LLVM.md

Removed: 




diff  --git a/mlir/docs/Dialects/LLVM.md b/mlir/docs/Dialects/LLVM.md
index b396cdebf067..521c5f4c328b 100644
--- a/mlir/docs/Dialects/LLVM.md
+++ b/mlir/docs/Dialects/LLVM.md
@@ -224,6 +224,11 @@ compatible. For example, signed and unsigned integers are 
not compatible. LLVM
 provides a function, `bool LLVM::isCompatibleType(Type)`, that can be used as a
 compatibility check.
 
+Each LLVM IR type corresponds to *exactly one* MLIR type, either built-in or
+LLVM dialect type. For example, because `i32` is LLVM-compatible, there is no
+`!llvm.i32` type. However, `!llvm.ptr` is defined in the LLVM dialect as
+there is no corresponding built-in type.
+
 ### Additional Simple Types
 
 The following non-parametric types derived from the LLVM IR are available in 
the



___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] 74438ef - [mlir] Use thread_local stack in LLVM dialect type parsing and printing

2021-01-06 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2021-01-06T12:05:24+01:00
New Revision: 74438eff511e71dc33841546d89cb34206551d55

URL: 
https://github.com/llvm/llvm-project/commit/74438eff511e71dc33841546d89cb34206551d55
DIFF: 
https://github.com/llvm/llvm-project/commit/74438eff511e71dc33841546d89cb34206551d55.diff

LOG: [mlir] Use thread_local stack in LLVM dialect type parsing and printing

LLVM dialect type parsing and printing have been using a local stack object
forwarded between recursive functions responsible for parsing or printing
specific types. This stack is necessary to intercept (mutually) recursive
structure types and avoid inifinite recursion. This approach works only thanks
to the closedness of the LLVM dialect type system: types that don't belong to
the dialect are not allowed. Switch the approach to using a `thread_local`
stack inside the functions parsing the structure types. This makes the code
slightly cleaner by avoiding the need to pass the stack object around and, more
importantly, makes it possible to reconsider the closedness of the LLVM dialect
type system. As a nice side effect of this change, container LLVM dialect types
now support type aliases in their body (although it is currently impossible to
also use the alises when printing).

Depends On D93713

Reviewed By: mehdi_amini

Differential Revision: https://reviews.llvm.org/D93714

Added: 


Modified: 
mlir/lib/Dialect/LLVMIR/IR/LLVMTypeSyntax.cpp
mlir/test/Dialect/LLVMIR/types-invalid.mlir
mlir/test/Dialect/LLVMIR/types.mlir

Removed: 




diff  --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMTypeSyntax.cpp 
b/mlir/lib/Dialect/LLVMIR/IR/LLVMTypeSyntax.cpp
index 3d72e254f338..08c00befcf18 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMTypeSyntax.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMTypeSyntax.cpp
@@ -9,6 +9,7 @@
 #include "mlir/Dialect/LLVMIR/LLVMTypes.h"
 #include "mlir/IR/Builders.h"
 #include "mlir/IR/DialectImplementation.h"
+#include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/TypeSwitch.h"
 
@@ -19,8 +20,14 @@ using namespace mlir::LLVM;
 // Printing.
 
//===--===//
 
-static void printTypeImpl(llvm::raw_ostream &os, Type type,
-  llvm::SetVector &stack);
+/// If the given type is compatible with the LLVM dialect, prints it using
+/// internal functions to avoid getting a verbose `!llvm` prefix. Otherwise
+/// prints it as usual.
+static void dispatchPrint(DialectAsmPrinter &printer, Type type) {
+  if (isCompatibleType(type))
+return mlir::LLVM::detail::printType(type, printer);
+  printer.printType(type);
+}
 
 /// Returns the keyword to use for the given type.
 static StringRef getTypeKeyword(Type type) {
@@ -48,76 +55,79 @@ static StringRef getTypeKeyword(Type type) {
   });
 }
 
-/// Prints the body of a structure type. Uses `stack` to avoid printing
-/// recursive structs indefinitely.
-static void printStructTypeBody(llvm::raw_ostream &os, LLVMStructType type,
-llvm::SetVector &stack) {
-  if (type.isIdentified() && type.isOpaque()) {
-os << "opaque";
-return;
-  }
-
-  if (type.isPacked())
-os << "packed ";
-
-  // Put the current type on stack to avoid infinite recursion.
-  os << '(';
-  if (type.isIdentified())
-stack.insert(type.getName());
-  llvm::interleaveComma(type.getBody(), os, [&](Type subtype) {
-printTypeImpl(os, subtype, stack);
+/// Prints a structure type. Keeps track of known struct names to handle self-
+/// or mutually-referring structs without falling into infinite recursion.
+static void printStructType(DialectAsmPrinter &printer, LLVMStructType type) {
+  // This keeps track of the names of identified structure types that are
+  // currently being printed. Since such types can refer themselves, this
+  // tracking is necessary to stop the recursion: the current function may be
+  // called recursively from DialectAsmPrinter::printType after the appropriate
+  // dispatch. We maintain the invariant of this storage being modified
+  // exclusively in this function, and at most one name being added per call.
+  // TODO: consider having such functionality inside DialectAsmPrinter.
+  thread_local llvm::SetVector knownStructNames;
+  unsigned stackSize = knownStructNames.size();
+  (void)stackSize;
+  auto guard = llvm::make_scope_exit([&]() {
+assert(knownStructNames.size() == stackSize &&
+   "malformed identified stack when printing recursive structs");
   });
-  if (type.isIdentified())
-stack.pop_back();
-  os << ')';
-}
 
-/// Prints a structure type. Uses `stack` to keep track of the identifiers of
-/// the structs being printed. Checks if the identifier of a struct is 
contained
-/// in `stack`, i.e. whether a self-reference to a recursive stack is being
-/// printed, and only prints the name to avoid infinite recursio

[llvm-branch-commits] [mlir] 10164a2 - [mlir] Refactor translation of OpenMP dialect ops to LLVM IR

2021-01-07 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2021-01-07T13:33:50+01:00
New Revision: 10164a2e50b4d7064bd02e7403aae6dd319cdd64

URL: 
https://github.com/llvm/llvm-project/commit/10164a2e50b4d7064bd02e7403aae6dd319cdd64
DIFF: 
https://github.com/llvm/llvm-project/commit/10164a2e50b4d7064bd02e7403aae6dd319cdd64.diff

LOG: [mlir] Refactor translation of OpenMP dialect ops to LLVM IR

The original implementation of the OpenMP dialect to LLVM IR translation has
been relying on a stack of insertion points for delayed insertion of branch
instructions that correspond to terminator ops. This is an intrusive into
ModuleTranslation and makes the translation non-local. A recent addition of the
WsLoop translation exercised another approach where the parent op is
responsible for converting terminators of all blocks in its regions. Use this
approach for other OpenMP dialect operations with regions, remove the stack and
deduplicate the code for converting such regions.

Reviewed By: kiranchandramohan

Differential Revision: https://reviews.llvm.org/D94086

Added: 


Modified: 
mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
mlir/lib/Target/LLVMIR/ModuleTranslation.cpp

Removed: 




diff  --git a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h 
b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
index 7691adfeef14..4a1871cac4dc 100644
--- a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
+++ b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
@@ -93,11 +93,11 @@ class ModuleTranslation {
llvm::IRBuilder<> &builder);
   virtual LogicalResult convertOmpMaster(Operation &op,
  llvm::IRBuilder<> &builder);
-  void convertOmpOpRegions(Region ®ion,
+  void convertOmpOpRegions(Region ®ion, StringRef blockName,
DenseMap &valueMapping,
DenseMap &blockMapping,
-   llvm::Instruction *codeGenIPBBTI,
-   llvm::BasicBlock &continuationIP,
+   llvm::BasicBlock &sourceBlock,
+   llvm::BasicBlock &continuationBlock,
llvm::IRBuilder<> &builder,
LogicalResult &bodyGenStatus);
   virtual LogicalResult convertOmpWsLoop(Operation &opInst,
@@ -121,7 +121,8 @@ class ModuleTranslation {
   LogicalResult convertFunctions();
   LogicalResult convertGlobals();
   LogicalResult convertOneFunction(LLVMFuncOp func);
-  LogicalResult convertBlock(Block &bb, bool ignoreArguments);
+  LogicalResult convertBlock(Block &bb, bool ignoreArguments,
+ llvm::IRBuilder<> &builder);
 
   llvm::Constant *getLLVMConstant(llvm::Type *llvmType, Attribute attr,
   Location loc);
@@ -134,14 +135,11 @@ class ModuleTranslation {
 
   /// Builder for LLVM IR generation of OpenMP constructs.
   std::unique_ptr ompBuilder;
+
   /// Precomputed pointer to OpenMP dialect. Note this can be nullptr if the
   /// OpenMP dialect hasn't been loaded (it is always loaded if there are 
OpenMP
   /// operations in the module though).
   const Dialect *ompDialect;
-  /// Stack which stores the target block to which a branch a must be added 
when
-  /// a terminator is seen. A stack is required to handle nested OpenMP 
parallel
-  /// regions.
-  SmallVector ompContinuationIPStack;
 
   /// Mappings between llvm.mlir.global definitions and corresponding globals.
   DenseMap globalsMapping;

diff  --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp 
b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index da9c734fbd80..5ffb11e76a93 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -413,24 +413,11 @@ ModuleTranslation::convertOmpParallel(Operation &opInst,
 
   auto bodyGenCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP,
llvm::BasicBlock &continuationIP) {
-llvm::LLVMContext &llvmContext = llvmModule->getContext();
-
-llvm::BasicBlock *codeGenIPBB = codeGenIP.getBlock();
-llvm::Instruction *codeGenIPBBTI = codeGenIPBB->getTerminator();
-ompContinuationIPStack.push_back(&continuationIP);
-
-// ParallelOp has only `1` region associated with it.
+// ParallelOp has only one region associated with it.
 auto ®ion = cast(opInst).getRegion();
-for (auto &bb : region) {
-  auto *llvmBB = llvm::BasicBlock::Create(
-  llvmContext, "omp.par.region", codeGenIP.getBlock()->getParent());
-  blockMapping[&bb] = llvmBB;
-}
-
-convertOmpOpRegions(region, valueMapping, blockMapping, codeGenIPBBTI,
-continuationIP, builder, bodyGenStatus);
-ompContinuationIPStack.pop_back();
-
+convertOmpOpRegions(region, "omp.par.region", valueMapping, blockMapping,
+*codeGenIP.getBlock(

[llvm-branch-commits] [mlir] c1d58c2 - [mlir] Add fastmath flags support to some LLVM dialect ops

2021-01-07 Thread Alex Zinenko via llvm-branch-commits

Author: Ivan Butygin
Date: 2021-01-07T14:00:09+01:00
New Revision: c1d58c2b0023cd41f0da128f5190fa887d8f6c69

URL: 
https://github.com/llvm/llvm-project/commit/c1d58c2b0023cd41f0da128f5190fa887d8f6c69
DIFF: 
https://github.com/llvm/llvm-project/commit/c1d58c2b0023cd41f0da128f5190fa887d8f6c69.diff

LOG: [mlir] Add fastmath flags support to some LLVM dialect ops

Add fastmath enum, attributes to some llvm dialect ops, 
`FastmathFlagsInterface` op interface, and `translateModuleToLLVMIR` support.

Reviewed By: ftynse

Differential Revision: https://reviews.llvm.org/D92485

Added: 
mlir/include/mlir/Dialect/LLVMIR/LLVMOpsInterfaces.td

Modified: 
mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt
mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.h
mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
mlir/lib/Conversion/SPIRVToLLVM/SPIRVToLLVM.cpp
mlir/lib/Conversion/StandardToLLVM/StandardToLLVM.cpp
mlir/lib/Dialect/LLVMIR/CMakeLists.txt
mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
mlir/test/Dialect/LLVMIR/roundtrip.mlir
mlir/test/Target/llvmir.mlir

Removed: 




diff  --git a/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt 
b/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt
index 6166f3632607..29cef3f0032d 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt
@@ -10,6 +10,8 @@ add_public_tablegen_target(MLIRLLVMOpsIncGen)
 
 add_mlir_doc(LLVMOps -gen-op-doc LLVMOps Dialects/)
 
+add_mlir_interface(LLVMOpsInterfaces)
+
 set(LLVM_TARGET_DEFINITIONS LLVMOps.td)
 mlir_tablegen(LLVMConversions.inc -gen-llvmir-conversions)
 mlir_tablegen(LLVMConversionEnumsToLLVM.inc -gen-enum-to-llvmir-conversions)

diff  --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.h 
b/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.h
index 630bad4914b1..22ff1517f77b 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.h
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.h
@@ -29,6 +29,7 @@
 #include "llvm/IR/Type.h"
 
 #include "mlir/Dialect/LLVMIR/LLVMOpsEnums.h.inc"
+#include "mlir/Dialect/LLVMIR/LLVMOpsInterfaces.h.inc"
 
 namespace llvm {
 class Type;
@@ -46,8 +47,23 @@ class LLVMDialect;
 namespace detail {
 struct LLVMTypeStorage;
 struct LLVMDialectImpl;
+struct BitmaskEnumStorage;
 } // namespace detail
 
+/// An attribute that specifies LLVM instruction fastmath flags.
+class FMFAttr : public Attribute::AttrBase {
+public:
+  using Base::Base;
+
+  static FMFAttr get(FastmathFlags flags, MLIRContext *context);
+
+  FastmathFlags getFlags() const;
+
+  void print(DialectAsmPrinter &p) const;
+  static Attribute parse(DialectAsmParser &parser);
+};
+
 } // namespace LLVM
 } // namespace mlir
 

diff  --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td 
b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index 428ca6783afd..53c42540aa48 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -14,10 +14,39 @@
 #define LLVMIR_OPS
 
 include "mlir/Dialect/LLVMIR/LLVMOpBase.td"
+include "mlir/Dialect/LLVMIR/LLVMOpsInterfaces.td"
 include "mlir/IR/SymbolInterfaces.td"
 include "mlir/Interfaces/ControlFlowInterfaces.td"
 include "mlir/Interfaces/SideEffectInterfaces.td"
 
+def FMFnnan : BitEnumAttrCase<"nnan", 0x1>;
+def FMFninf : BitEnumAttrCase<"ninf", 0x2>;
+def FMFnsz  : BitEnumAttrCase<"nsz", 0x4>;
+def FMFarcp : BitEnumAttrCase<"arcp", 0x8>;
+def FMFcontract : BitEnumAttrCase<"contract", 0x10>;
+def FMFafn  : BitEnumAttrCase<"afn", 0x20>;
+def FMFreassoc  : BitEnumAttrCase<"reassoc", 0x40>;
+def FMFfast : BitEnumAttrCase<"fast", 0x80>;
+
+def FastmathFlags : BitEnumAttr<
+"FastmathFlags",
+"LLVM fastmath flags",
+[FMFnnan, FMFninf, FMFnsz, FMFarcp, FMFcontract, FMFafn, FMFreassoc, 
FMFfast
+]> {
+  let cppNamespace = "::mlir::LLVM";
+}
+
+def LLVM_FMFAttr : DialectAttr<
+LLVM_Dialect,
+CPred<"$_self.isa<::mlir::LLVM::FMFAttr>()">,
+"LLVM fastmath flags"> {
+  let storageType = "::mlir::LLVM::FMFAttr";
+  let returnType = "::mlir::LLVM::FastmathFlags";
+  let convertFromStorage = "$_self.getFlags()";
+  let constBuilderCall =
+  "::mlir::LLVM::FMFAttr::get($0, $_builder.getContext())";
+}
+
 class LLVM_Builder {
   string llvmBuilder = builder;
 }
@@ -77,29 +106,35 @@ class LLVM_ArithmeticOpBase,
 LLVM_Builder<"$res = builder." # builderFunc # "($lhs, $rhs);"> {
-  let arguments = (ins LLVM_ScalarOrVectorOf:$lhs,
-   LLVM_ScalarOrVectorOf:$rhs);
+  dag commonArgs = (ins LLVM_ScalarOrVectorOf:$lhs,
+LLVM_ScalarOrVectorOf:$rhs);
   let results = (outs LLVM_ScalarOrVectorOf:$res);
   let builders = [LLVM_OneResultOpBuilder];
-  let assemblyFormat = "$lhs `,` $rhs attr-dict `:` type($res)";
+  let assemblyFormat = "$lhs `,` $rhs custom(attr-dict) `:` 
type($res)";
 }
 class LLV

[llvm-branch-commits] [mlir] a7cbc32 - [mlir] remove a use of deprecated OpState::setAttr

2021-01-07 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2021-01-07T14:20:36+01:00
New Revision: a7cbc32a916a64e9f61106956ed3866a6086ae6b

URL: 
https://github.com/llvm/llvm-project/commit/a7cbc32a916a64e9f61106956ed3866a6086ae6b
DIFF: 
https://github.com/llvm/llvm-project/commit/a7cbc32a916a64e9f61106956ed3866a6086ae6b.diff

LOG: [mlir] remove a use of deprecated OpState::setAttr

Added: 


Modified: 
mlir/lib/Conversion/StandardToLLVM/StandardToLLVM.cpp

Removed: 




diff  --git a/mlir/lib/Conversion/StandardToLLVM/StandardToLLVM.cpp 
b/mlir/lib/Conversion/StandardToLLVM/StandardToLLVM.cpp
index 5e270881656c..51f34661bece 100644
--- a/mlir/lib/Conversion/StandardToLLVM/StandardToLLVM.cpp
+++ b/mlir/lib/Conversion/StandardToLLVM/StandardToLLVM.cpp
@@ -1894,7 +1894,7 @@ struct ConstantOpLowering : public 
ConvertOpToLLVMPattern {
   for (const NamedAttribute &attr : op->getAttrs()) {
 if (attr.first.strref() == "value")
   continue;
-newOp.setAttr(attr.first, attr.second);
+newOp->setAttr(attr.first, attr.second);
   }
   rewriter.replaceOp(op, newOp->getResults());
   return success();



___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] 906efee - [mlir] don't match the text produced only in debug mode in Python tests

2021-01-07 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2021-01-07T19:57:28+01:00
New Revision: 906efeec0a471be522588bd7cbb7f61459b2b437

URL: 
https://github.com/llvm/llvm-project/commit/906efeec0a471be522588bd7cbb7f61459b2b437
DIFF: 
https://github.com/llvm/llvm-project/commit/906efeec0a471be522588bd7cbb7f61459b2b437.diff

LOG: [mlir] don't match the text produced only in debug mode in Python tests

Some Python bindings tests were using FileCheck to match parts of the
error description produced only in the debug compilation mode. Remove
these parts (but keep the main message) to ensure tests also pass when
running them in the release compilation mode.

Reviewed By: mehdi_amini

Differential Revision: https://reviews.llvm.org/D94221

Added: 


Modified: 
mlir/test/Bindings/Python/ir_attributes.py
mlir/test/Bindings/Python/ir_operation.py

Removed: 




diff  --git a/mlir/test/Bindings/Python/ir_attributes.py 
b/mlir/test/Bindings/Python/ir_attributes.py
index ce85dc3cf87a..91b0a92e989f 100644
--- a/mlir/test/Bindings/Python/ir_attributes.py
+++ b/mlir/test/Bindings/Python/ir_attributes.py
@@ -371,7 +371,7 @@ def testArrayAttr():
 try:
   ArrayAttr.get([42])
 except RuntimeError as e:
-  # CHECK: Error: Invalid attribute when attempting to create an 
ArrayAttribute (Unable to cast Python instance of type  to C++ 
type 'mlir::python::PyAttribute')
+  # CHECK: Error: Invalid attribute when attempting to create an 
ArrayAttribute
   print("Error: ", e)
 run(testArrayAttr)
 

diff  --git a/mlir/test/Bindings/Python/ir_operation.py 
b/mlir/test/Bindings/Python/ir_operation.py
index ba54e83f65e8..034b28ec25bf 100644
--- a/mlir/test/Bindings/Python/ir_operation.py
+++ b/mlir/test/Bindings/Python/ir_operation.py
@@ -566,17 +566,17 @@ def testCreateWithInvalidAttributes():
 try:
   Operation.create("module", attributes={None:StringAttr.get("name")})
 except Exception as e:
-  # CHECK: Invalid attribute key (not a string) when attempting to create 
the operation "module" (Unable to cast Python instance of type  to C++ type
+  # CHECK: Invalid attribute key (not a string) when attempting to create 
the operation "module"
   print(e)
 try:
   Operation.create("module", attributes={42:StringAttr.get("name")})
 except Exception as e:
-  # CHECK: Invalid attribute key (not a string) when attempting to create 
the operation "module" (Unable to cast Python instance of type  to 
C++ type
+  # CHECK: Invalid attribute key (not a string) when attempting to create 
the operation "module"
   print(e)
 try:
   Operation.create("module", attributes={"some_key":ctx})
 except Exception as e:
-  # CHECK: Invalid attribute value for the key "some_key" when attempting 
to create the operation "module" (Unable to cast Python instance of type  to C++ type 'mlir::python::PyAttribute')
+  # CHECK: Invalid attribute value for the key "some_key" when attempting 
to create the operation "module"
   print(e)
 try:
   Operation.create("module", attributes={"some_key":None})



___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] 195ffcd - [MLIR][NFC] remove unnecessary includes form tablegen command

2021-01-08 Thread Alex Zinenko via llvm-branch-commits

Author: Shivam Gupta
Date: 2021-01-08T14:25:52+01:00
New Revision: 195ffcd890f648187cd110965a419c01d6488f66

URL: 
https://github.com/llvm/llvm-project/commit/195ffcd890f648187cd110965a419c01d6488f66
DIFF: 
https://github.com/llvm/llvm-project/commit/195ffcd890f648187cd110965a419c01d6488f66.diff

LOG: [MLIR][NFC] remove unnecessary includes form tablegen command

With [[ https://reviews.llvm.org/D77156 | D77156 ]] includes are not needed 
here.

Reviewed By: ftynse

Differential Revision: https://reviews.llvm.org/D94216

Added: 


Modified: 
mlir/cmake/modules/AddMLIR.cmake

Removed: 




diff  --git a/mlir/cmake/modules/AddMLIR.cmake 
b/mlir/cmake/modules/AddMLIR.cmake
index 9709615c7d66..4cfd351d9758 100644
--- a/mlir/cmake/modules/AddMLIR.cmake
+++ b/mlir/cmake/modules/AddMLIR.cmake
@@ -29,7 +29,7 @@ endfunction()
 # Generate Documentation
 function(add_mlir_doc doc_filename command output_file output_directory)
   set(LLVM_TARGET_DEFINITIONS ${doc_filename}.td)
-  tablegen(MLIR ${output_file}.md ${command} "-I${MLIR_MAIN_INCLUDE_DIR}" 
"-I${MLIR_INCLUDE_DIR}")
+  tablegen(MLIR ${output_file}.md ${command})
   set(GEN_DOC_FILE 
${MLIR_BINARY_DIR}/docs/${output_directory}${output_file}.md)
   add_custom_command(
   OUTPUT ${GEN_DOC_FILE}



___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] 74628c4 - [mlir] Add Python bindings for AffineExpr

2021-01-11 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2021-01-11T19:57:13+01:00
New Revision: 74628c43053b482f35f0f1e6b4eac743fbe425e5

URL: 
https://github.com/llvm/llvm-project/commit/74628c43053b482f35f0f1e6b4eac743fbe425e5
DIFF: 
https://github.com/llvm/llvm-project/commit/74628c43053b482f35f0f1e6b4eac743fbe425e5.diff

LOG: [mlir] Add Python bindings for AffineExpr

This adds the Python bindings for AffineExpr and a couple of utility functions
to the C API. AffineExpr is a top-level context-owned object and is modeled
similarly to attributes and types. It is required, e.g., to build layout maps
of the built-in memref type.

Reviewed By: mehdi_amini

Differential Revision: https://reviews.llvm.org/D94225

Added: 
mlir/test/Bindings/Python/ir_affine_expr.py

Modified: 
mlir/include/mlir-c/AffineExpr.h
mlir/include/mlir-c/Bindings/Python/Interop.h
mlir/lib/Bindings/Python/IRModules.cpp
mlir/lib/Bindings/Python/IRModules.h
mlir/lib/CAPI/IR/AffineExpr.cpp
mlir/test/CAPI/ir.c

Removed: 




diff  --git a/mlir/include/mlir-c/AffineExpr.h 
b/mlir/include/mlir-c/AffineExpr.h
index 93b8e832b44f..2eb8ae03e03d 100644
--- a/mlir/include/mlir-c/AffineExpr.h
+++ b/mlir/include/mlir-c/AffineExpr.h
@@ -45,6 +45,16 @@ DEFINE_C_API_STRUCT(MlirAffineExpr, const void);
 MLIR_CAPI_EXPORTED MlirContext
 mlirAffineExprGetContext(MlirAffineExpr affineExpr);
 
+/// Returns `true` if the two affine expressions are equal.
+MLIR_CAPI_EXPORTED bool mlirAffineExprEqual(MlirAffineExpr lhs,
+MlirAffineExpr rhs);
+
+/// Returns `true` if the given affine expression is a null expression. Note
+/// constant zero is not a null expression.
+inline bool mlirAffineExprIsNull(MlirAffineExpr affineExpr) {
+  return affineExpr.ptr == NULL;
+}
+
 /** Prints an affine expression by sending chunks of the string representation
  * and forwarding `userData to `callback`. Note that the callback may be called
  * several times with consecutive chunks of the string. */
@@ -82,6 +92,9 @@ MLIR_CAPI_EXPORTED bool 
mlirAffineExprIsFunctionOfDim(MlirAffineExpr affineExpr,
 // Affine Dimension Expression.
 
//===--===//
 
+/// Checks whether the given affine expression is a dimension expression.
+MLIR_CAPI_EXPORTED bool mlirAffineExprIsADim(MlirAffineExpr affineExpr);
+
 /// Creates an affine dimension expression with 'position' in the context.
 MLIR_CAPI_EXPORTED MlirAffineExpr mlirAffineDimExprGet(MlirContext ctx,
intptr_t position);
@@ -94,6 +107,9 @@ mlirAffineDimExprGetPosition(MlirAffineExpr affineExpr);
 // Affine Symbol Expression.
 
//===--===//
 
+/// Checks whether the given affine expression is a symbol expression.
+MLIR_CAPI_EXPORTED bool mlirAffineExprIsASymbol(MlirAffineExpr affineExpr);
+
 /// Creates an affine symbol expression with 'position' in the context.
 MLIR_CAPI_EXPORTED MlirAffineExpr mlirAffineSymbolExprGet(MlirContext ctx,
   intptr_t position);
@@ -106,6 +122,9 @@ mlirAffineSymbolExprGetPosition(MlirAffineExpr affineExpr);
 // Affine Constant Expression.
 
//===--===//
 
+/// Checks whether the given affine expression is a constant expression.
+MLIR_CAPI_EXPORTED bool mlirAffineExprIsAConstant(MlirAffineExpr affineExpr);
+
 /// Creates an affine constant expression with 'constant' in the context.
 MLIR_CAPI_EXPORTED MlirAffineExpr mlirAffineConstantExprGet(MlirContext ctx,
 int64_t constant);
@@ -173,6 +192,9 @@ MLIR_CAPI_EXPORTED MlirAffineExpr 
mlirAffineCeilDivExprGet(MlirAffineExpr lhs,
 // Affine Binary Operation Expression.
 
//===--===//
 
+/// Checks whether the given affine expression is binary.
+MLIR_CAPI_EXPORTED bool mlirAffineExprIsABinary(MlirAffineExpr affineExpr);
+
 /** Returns the left hand side affine expression of the given affine binary
  * operation expression. */
 MLIR_CAPI_EXPORTED MlirAffineExpr

diff  --git a/mlir/include/mlir-c/Bindings/Python/Interop.h 
b/mlir/include/mlir-c/Bindings/Python/Interop.h
index ae9d3a84a0a3..d1eda4202345 100644
--- a/mlir/include/mlir-c/Bindings/Python/Interop.h
+++ b/mlir/include/mlir-c/Bindings/Python/Interop.h
@@ -23,10 +23,12 @@
 
 #include 
 
+#include "mlir-c/AffineExpr.h"
 #include "mlir-c/AffineMap.h"
 #include "mlir-c/IR.h"
 #include "mlir-c/Pass.h"
 
+#define MLIR_PYTHON_CAPSULE_AFFINE_EXPR "mlir.ir.AffineExpr._CAPIPtr"
 #define MLIR_PYTHON_CAPSULE_AFFINE_MAP "mlir.ir.AffineMap._CAPIPtr"
 #define MLIR_PYTHON_CAPSULE_ATTRIBUTE "mlir.ir.Attribute._CAPIPtr"
 #define MLIR_PYTHON_CAPSULE_CONTEXT "mlir.ir.C

[llvm-branch-commits] [mlir] e79bd0b - [mlir] More Python bindings for AffineMap

2021-01-11 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2021-01-11T19:57:15+01:00
New Revision: e79bd0b4f25e68130a2ac273d6508ea322028b61

URL: 
https://github.com/llvm/llvm-project/commit/e79bd0b4f25e68130a2ac273d6508ea322028b61
DIFF: 
https://github.com/llvm/llvm-project/commit/e79bd0b4f25e68130a2ac273d6508ea322028b61.diff

LOG: [mlir] More Python bindings for AffineMap

Now that the bindings for AffineExpr have been added, add more bindings for
constructing and inspecting AffineMap that consists of AffineExprs.

Depends On D94225

Reviewed By: mehdi_amini

Differential Revision: https://reviews.llvm.org/D94297

Added: 


Modified: 
mlir/include/mlir-c/AffineExpr.h
mlir/include/mlir-c/AffineMap.h
mlir/lib/Bindings/Python/IRModules.cpp
mlir/lib/CAPI/IR/AffineMap.cpp
mlir/test/Bindings/Python/ir_affine_map.py
mlir/test/CAPI/ir.c

Removed: 




diff  --git a/mlir/include/mlir-c/AffineExpr.h 
b/mlir/include/mlir-c/AffineExpr.h
index 2eb8ae03e03d..ec445682c011 100644
--- a/mlir/include/mlir-c/AffineExpr.h
+++ b/mlir/include/mlir-c/AffineExpr.h
@@ -10,7 +10,6 @@
 #ifndef MLIR_C_AFFINEEXPR_H
 #define MLIR_C_AFFINEEXPR_H
 
-#include "mlir-c/AffineMap.h"
 #include "mlir-c/IR.h"
 
 #ifdef __cplusplus

diff  --git a/mlir/include/mlir-c/AffineMap.h b/mlir/include/mlir-c/AffineMap.h
index c52fe6826251..bf0c7c7b5381 100644
--- a/mlir/include/mlir-c/AffineMap.h
+++ b/mlir/include/mlir-c/AffineMap.h
@@ -10,6 +10,7 @@
 #ifndef MLIR_C_AFFINEMAP_H
 #define MLIR_C_AFFINEMAP_H
 
+#include "mlir-c/AffineExpr.h"
 #include "mlir-c/IR.h"
 
 #ifdef __cplusplus
@@ -67,9 +68,18 @@ MLIR_CAPI_EXPORTED MlirAffineMap 
mlirAffineMapEmptyGet(MlirContext ctx);
 
 /** Creates a zero result affine map of the given dimensions and symbols in the
  * context. The affine map is owned by the context. */
+MLIR_CAPI_EXPORTED MlirAffineMap mlirAffineMapZeroResultGet(
+MlirContext ctx, intptr_t dimCount, intptr_t symbolCount);
+
+/** Creates an affine map with results defined by the given list of affine
+ * expressions. The map resulting map also has the requested number of input
+ * dimensions and symbols, regardless of them being used in the results.
+ */
 MLIR_CAPI_EXPORTED MlirAffineMap mlirAffineMapGet(MlirContext ctx,
   intptr_t dimCount,
-  intptr_t symbolCount);
+  intptr_t symbolCount,
+  intptr_t nAffineExprs,
+  MlirAffineExpr *affineExprs);
 
 /** Creates a single constant result affine map in the context. The affine map
  * is owned by the context. */
@@ -124,6 +134,10 @@ MLIR_CAPI_EXPORTED intptr_t 
mlirAffineMapGetNumSymbols(MlirAffineMap affineMap);
 /// Returns the number of results of the given affine map.
 MLIR_CAPI_EXPORTED intptr_t mlirAffineMapGetNumResults(MlirAffineMap 
affineMap);
 
+/// Returns the result at the given position.
+MLIR_CAPI_EXPORTED MlirAffineExpr
+mlirAffineMapGetResult(MlirAffineMap affineMap, intptr_t pos);
+
 /** Returns the number of inputs (dimensions + symbols) of the given affine
  * map. */
 MLIR_CAPI_EXPORTED intptr_t mlirAffineMapGetNumInputs(MlirAffineMap affineMap);

diff  --git a/mlir/lib/Bindings/Python/IRModules.cpp 
b/mlir/lib/Bindings/Python/IRModules.cpp
index 2d18a7a488e7..81f84b8152f4 100644
--- a/mlir/lib/Bindings/Python/IRModules.cpp
+++ b/mlir/lib/Bindings/Python/IRModules.cpp
@@ -11,6 +11,7 @@
 #include "Globals.h"
 #include "PybindUtils.h"
 
+#include "mlir-c/AffineMap.h"
 #include "mlir-c/Bindings/Python/Interop.h"
 #include "mlir-c/BuiltinAttributes.h"
 #include "mlir-c/BuiltinTypes.h"
@@ -2943,9 +2944,43 @@ PyAffineExpr PyAffineExpr::createFromCapsule(py::object 
capsule) {
 }
 
 
//--
-// PyAffineMap.
+// PyAffineMap and utilities.
 
//--
 
+namespace {
+/// A list of expressions contained in an affine map. Internally these are
+/// stored as a consecutive array leading to inexpensive random access. Both
+/// the map and the expression are owned by the context so we need not bother
+/// with lifetime extension.
+class PyAffineMapExprList
+: public Sliceable {
+public:
+  static constexpr const char *pyClassName = "AffineExprList";
+
+  PyAffineMapExprList(PyAffineMap map, intptr_t startIndex = 0,
+  intptr_t length = -1, intptr_t step = 1)
+  : Sliceable(startIndex,
+  length == -1 ? mlirAffineMapGetNumResults(map) : length,
+  step),
+affineMap(map) {}
+
+  intptr_t getNumElements() { return mlirAffineMapGetNumResults(affineMap); }
+
+  PyAffineExpr getElement(intptr_t pos) {
+return PyAffineExpr(affineMap.getContext(),
+

[llvm-branch-commits] [mlir] 547e3ee - [mlir] Expose MemRef layout in Python bindings

2021-01-11 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2021-01-11T19:57:16+01:00
New Revision: 547e3eef14a8e75a867dfcc6b45cd1f0547d4e07

URL: 
https://github.com/llvm/llvm-project/commit/547e3eef14a8e75a867dfcc6b45cd1f0547d4e07
DIFF: 
https://github.com/llvm/llvm-project/commit/547e3eef14a8e75a867dfcc6b45cd1f0547d4e07.diff

LOG: [mlir] Expose MemRef layout in Python bindings

This wasn't possible before because there was no support for affine expressions
as maps. Now that this support is available, provide the mechanism for
constructing maps with a layout and inspecting it.

Rework the `get` method on MemRefType in Python to avoid needing an explicit
memory space or layout map. Remove the `get_num_maps`, it is too low-level,
using the length of the now-avaiable pseudo-list of layout maps is more
pythonic.

Depends On D94297

Reviewed By: mehdi_amini

Differential Revision: https://reviews.llvm.org/D94302

Added: 


Modified: 
mlir/include/mlir-c/BuiltinTypes.h
mlir/lib/Bindings/Python/IRModules.cpp
mlir/lib/CAPI/IR/BuiltinTypes.cpp
mlir/test/Bindings/Python/ir_types.py

Removed: 




diff  --git a/mlir/include/mlir-c/BuiltinTypes.h 
b/mlir/include/mlir-c/BuiltinTypes.h
index 77898be41565..9712d58ad87a 100644
--- a/mlir/include/mlir-c/BuiltinTypes.h
+++ b/mlir/include/mlir-c/BuiltinTypes.h
@@ -225,7 +225,13 @@ MLIR_CAPI_EXPORTED bool mlirTypeIsAUnrankedMemRef(MlirType 
type);
  * same context as element type. The type is owned by the context. */
 MLIR_CAPI_EXPORTED MlirType mlirMemRefTypeGet(
 MlirType elementType, intptr_t rank, const int64_t *shape, intptr_t 
numMaps,
-MlirAttribute const *affineMaps, unsigned memorySpace);
+MlirAffineMap const *affineMaps, unsigned memorySpace);
+
+/** Same as "mlirMemRefTypeGet" but returns a nullptr-wrapping MlirType o
+ * illegal arguments, emitting appropriate diagnostics. */
+MLIR_CAPI_EXPORTED MlirType mlirMemRefTypeGetChecked(
+MlirType elementType, intptr_t rank, const int64_t *shape, intptr_t 
numMaps,
+MlirAffineMap const *affineMaps, unsigned memorySpace, MlirLocation loc);
 
 /** Creates a MemRef type with the given rank, shape, memory space and element
  * type in the same context as the element type. The type has no affine maps,

diff  --git a/mlir/lib/Bindings/Python/IRModules.cpp 
b/mlir/lib/Bindings/Python/IRModules.cpp
index 81f84b8152f4..218099bedc6f 100644
--- a/mlir/lib/Bindings/Python/IRModules.cpp
+++ b/mlir/lib/Bindings/Python/IRModules.cpp
@@ -2535,6 +2535,8 @@ class PyUnrankedTensorType
   }
 };
 
+class PyMemRefLayoutMapList;
+
 /// Ranked MemRef Type subclass - MemRefType.
 class PyMemRefType : public PyConcreteType {
 public:
@@ -2542,16 +2544,22 @@ class PyMemRefType : public 
PyConcreteType {
   static constexpr const char *pyClassName = "MemRefType";
   using PyConcreteType::PyConcreteType;
 
+  PyMemRefLayoutMapList getLayout();
+
   static void bindDerived(ClassTy &c) {
-// TODO: Add mlirMemRefTypeGet and mlirMemRefTypeGetAffineMap binding
-// once the affine map binding is completed.
 c.def_static(
- "get_contiguous_memref",
- // TODO: Make the location optional and create a default location.
+ "get",
  [](PyType &elementType, std::vector shape,
-unsigned memorySpace, DefaultingPyLocation loc) {
-   MlirType t = mlirMemRefTypeContiguousGetChecked(
-   elementType, shape.size(), shape.data(), memorySpace, loc);
+std::vector layout, unsigned memorySpace,
+DefaultingPyLocation loc) {
+   SmallVector maps;
+   maps.reserve(layout.size());
+   for (PyAffineMap &map : layout)
+ maps.push_back(map);
+
+   MlirType t = mlirMemRefTypeGetChecked(elementType, shape.size(),
+ shape.data(), maps.size(),
+ maps.data(), memorySpace, 
loc);
// TODO: Rework error reporting once diagnostic engine is exposed
// in C API.
if (mlirTypeIsNull(t)) {
@@ -2565,15 +2573,11 @@ class PyMemRefType : public 
PyConcreteType {
}
return PyMemRefType(elementType.getContext(), t);
  },
- py::arg("element_type"), py::arg("shape"), py::arg("memory_space"),
+ py::arg("element_type"), py::arg("shape"),
+ py::arg("layout") = py::list(), py::arg("memory_space") = 0,
  py::arg("loc") = py::none(), "Create a memref type")
-.def_property_readonly(
-"num_affine_maps",
-[](PyMemRefType &self) -> intptr_t {
-  return mlirMemRefTypeGetNumAffineMaps(self);
-},
-"Returns the number of affine layout maps in the given MemRef "
-"type.")
+.def_property_readonly("layout", &PyMemRefType::getLayout,
+   "The list of layout maps of the MemRef type.")

[llvm-branch-commits] [mlir] 20d0cbd - [mlir] Tighten type verifiers for LLVM dialect ops results

2020-12-15 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2020-12-15T23:50:02+01:00
New Revision: 20d0cbd3fadf5a6e78373ab5c9d35e9e5d49f172

URL: 
https://github.com/llvm/llvm-project/commit/20d0cbd3fadf5a6e78373ab5c9d35e9e5d49f172
DIFF: 
https://github.com/llvm/llvm-project/commit/20d0cbd3fadf5a6e78373ab5c9d35e9e5d49f172.diff

LOG: [mlir] Tighten type verifiers for LLVM dialect ops results

Now that we have predicates for LLVM dialect types in ODS, we can use them to
restrict the types allowed in results of LLVM dialect operations. This also
serves as additional documentation for these operations.

Reviewed By: rriddle

Differential Revision: https://reviews.llvm.org/D93329

Added: 


Modified: 
mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
mlir/test/Dialect/LLVMIR/invalid.mlir

Removed: 




diff  --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td 
b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index 807ea8826ef8..da25c0d3f92d 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -94,9 +94,8 @@ class LLVM_ArithmeticOpBase {
   let arguments = (ins LLVM_ScalarOrVectorOf:$lhs,
LLVM_ScalarOrVectorOf:$rhs);
-  let parser =
-  [{ return impl::parseOneResultSameOperandTypeOp(parser, result); }];
-  let printer = [{ mlir::impl::printOneResultOp(this->getOperation(), p); }];
+  let results = (outs LLVM_ScalarOrVectorOf:$res);
+  let assemblyFormat = "$lhs `,` $rhs attr-dict `:` type($res)";
 }
 class LLVM_IntArithmeticOp traits = []> :
@@ -112,9 +111,8 @@ class LLVM_UnaryArithmeticOp,
 LLVM_Builder<"$res = builder." # builderFunc # "($operand);"> {
   let arguments = (ins type:$operand);
-  let parser =
-  [{ return impl::parseOneResultSameOperandTypeOp(parser, result); }];
-  let printer = [{ mlir::impl::printOneResultOp(this->getOperation(), p); }];
+  let results = (outs type:$res);
+  let assemblyFormat = "$operand attr-dict `:` type($res)";
 }
 
 // Integer binary operations.
@@ -157,6 +155,7 @@ def LLVM_ICmpOp : LLVM_OneResultOp<"icmp", [NoSideEffect]> {
   let arguments = (ins ICmpPredicate:$predicate,
LLVM_ScalarOrVectorOf:$lhs,
LLVM_ScalarOrVectorOf:$rhs);
+  let results = (outs LLVM_ScalarOrVectorOf:$res);
   let llvmBuilder = [{
 $res = builder.CreateICmp(getLLVMCmpPredicate($predicate), $lhs, $rhs);
   }];
@@ -204,6 +203,7 @@ def LLVM_FCmpOp : LLVM_OneResultOp<"fcmp", [NoSideEffect]> {
   let arguments = (ins FCmpPredicate:$predicate,
LLVM_ScalarOrVectorOf:$lhs,
LLVM_ScalarOrVectorOf:$rhs);
+  let results = (outs LLVM_ScalarOrVectorOf:$res);
   let llvmBuilder = [{
 $res = builder.CreateFCmp(getLLVMCmpPredicate($predicate), $lhs, $rhs);
   }];
@@ -257,6 +257,7 @@ def LLVM_AllocaOp :
 LLVM_OneResultOp<"alloca"> {
   let arguments = (ins LLVM_AnyInteger:$arraySize,
OptionalAttr:$alignment);
+  let results = (outs LLVM_AnyPointer:$res);
   string llvmBuilder = [{
 auto *inst = builder.CreateAlloca(
   $_resultType->getPointerElementType(), $arraySize);
@@ -280,6 +281,7 @@ def LLVM_GEPOp : LLVM_OneResultOp<"getelementptr", 
[NoSideEffect]>,
  LLVM_Builder<"$res = builder.CreateGEP($base, $indices);"> {
   let arguments = (ins LLVM_ScalarOrVectorOf:$base,
Variadic>:$indices);
+  let results = (outs LLVM_ScalarOrVectorOf:$res);
   let assemblyFormat = [{
 $base `[` $indices `]` attr-dict `:` functional-type(operands, results)
   }];
@@ -291,6 +293,7 @@ def LLVM_LoadOp :
   let arguments = (ins LLVM_PointerTo:$addr,
OptionalAttr:$alignment, UnitAttr:$volatile_,
UnitAttr:$nontemporal);
+  let results = (outs LLVM_Type:$res);
   string llvmBuilder = [{
 auto *inst = builder.CreateLoad($addr, $volatile_);
   }] # setAlignmentCode # setNonTemporalMetadataCode # [{
@@ -330,52 +333,64 @@ def LLVM_StoreOp :
 
 // Casts.
 class LLVM_CastOp traits = []> :
+  Type resultType, list traits = []> :
 LLVM_OneResultOp,
 LLVM_Builder<"$res = builder." # builderFunc # "($arg, $_resultType);"> {
   let arguments = (ins type:$arg);
+  let results = (outs resultType:$res);
   let parser = [{ return mlir::impl::parseCastOp(parser, result); }];
   let printer = [{ mlir::impl::printCastOp(this->getOperation(), p); }];
 }
 def LLVM_BitcastOp : LLVM_CastOp<"bitcast", "CreateBitCast",
- LLVM_AnyNonAggregate>;
+ LLVM_AnyNonAggregate, LLVM_AnyNonAggregate>;
 def LLVM_AddrSpaceCastOp : LLVM_CastOp<"addrspacecast", "CreateAddrSpaceCast",
+   LLVM_ScalarOrVectorOf,
LLVM_ScalarOrVectorOf>;
 def LLVM_IntToPtrOp : LLVM_CastOp<"inttoptr", "CreateIntToPtr",
- 

[llvm-branch-commits] [mlir] 02220f3 - [mlir] NFC: retire LLVM_Zero/OneResultOp from LLVM dialect ODS

2020-12-15 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2020-12-15T23:50:03+01:00
New Revision: 02220f3204980496c8877abb51ba1fd87a108541

URL: 
https://github.com/llvm/llvm-project/commit/02220f3204980496c8877abb51ba1fd87a108541
DIFF: 
https://github.com/llvm/llvm-project/commit/02220f3204980496c8877abb51ba1fd87a108541.diff

LOG: [mlir] NFC: retire LLVM_Zero/OneResultOp from LLVM dialect ODS

These classes were initially introduced to factor out two common parts of LLVM
op definitions: the fact that they have no results or a single result of
LLVM_Type, and the default builders. Neither of the two parts is really
common anymore: many ops have more specific on the result type, and many ops
provide custom builders. The TableGen classes only add conceptual complexity
and make LLVM dialect definition dissimilar to other dialects. Remove them in
favor of explicitly specified builders (results are already specified).

Depends On D93329

Reviewed By: rriddle

Differential Revision: https://reviews.llvm.org/D93330

Added: 


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

Removed: 




diff  --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td 
b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index da25c0d3f92d..59ea92d88330 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -43,16 +43,6 @@ def LLVM_ZeroResultOpBuilder :
 }
   }]>;
 
-class LLVM_TwoBuilders {
-  list builders = [b1, b2];
-}
-
-// Base class for LLVM operations with one result.
-class LLVM_OneResultOp traits = []> :
-LLVM_Op, Results<(outs LLVM_Type:$res)> {
-  let builders = [LLVM_OneResultOpBuilder];
-}
-
 // Compatibility builder that takes an instance of wrapped llvm::VoidType
 // to indicate no result.
 def LLVM_VoidResultTypeOpBuilder :
@@ -66,10 +56,6 @@ def LLVM_VoidResultTypeOpBuilder :
 build($_builder, $_state, operands, attributes);
   }]>;
 
-// Base class for LLVM operations with zero results.
-class LLVM_ZeroResultOp traits = []> :
-LLVM_Op, Results<(outs)>,
-LLVM_TwoBuilders;
 
 // Opaque builder used for terminator operations that contain successors.
 def LLVM_TerminatorPassthroughOpBuilder :
@@ -89,12 +75,13 @@ class LLVM_TerminatorOp 
traits = []> :
 // Class for arithmetic binary operations.
 class LLVM_ArithmeticOpBase traits = []> :
-LLVM_OneResultOp,
 LLVM_Builder<"$res = builder." # builderFunc # "($lhs, $rhs);"> {
   let arguments = (ins LLVM_ScalarOrVectorOf:$lhs,
LLVM_ScalarOrVectorOf:$rhs);
   let results = (outs LLVM_ScalarOrVectorOf:$res);
+  let builders = [LLVM_OneResultOpBuilder];
   let assemblyFormat = "$lhs `,` $rhs attr-dict `:` type($res)";
 }
 class LLVM_IntArithmeticOp traits = []> :
-LLVM_OneResultOp,
 LLVM_Builder<"$res = builder." # builderFunc # "($operand);"> {
   let arguments = (ins type:$operand);
   let results = (outs type:$res);
+  let builders = [LLVM_OneResultOpBuilder];
   let assemblyFormat = "$operand attr-dict `:` type($res)";
 }
 
@@ -151,7 +139,7 @@ def ICmpPredicate : I64EnumAttr<
 }
 
 // Other integer operations.
-def LLVM_ICmpOp : LLVM_OneResultOp<"icmp", [NoSideEffect]> {
+def LLVM_ICmpOp : LLVM_Op<"icmp", [NoSideEffect]> {
   let arguments = (ins ICmpPredicate:$predicate,
LLVM_ScalarOrVectorOf:$lhs,
LLVM_ScalarOrVectorOf:$rhs);
@@ -199,7 +187,7 @@ def FCmpPredicate : I64EnumAttr<
 }
 
 // Other integer operations.
-def LLVM_FCmpOp : LLVM_OneResultOp<"fcmp", [NoSideEffect]> {
+def LLVM_FCmpOp : LLVM_Op<"fcmp", [NoSideEffect]> {
   let arguments = (ins FCmpPredicate:$predicate,
LLVM_ScalarOrVectorOf:$lhs,
LLVM_ScalarOrVectorOf:$rhs);
@@ -252,9 +240,7 @@ class MemoryOpWithAlignmentAndAttributes : 
MemoryOpWithAlignmentBase {
 }
 
 // Memory-related operations.
-def LLVM_AllocaOp :
-MemoryOpWithAlignmentBase,
-LLVM_OneResultOp<"alloca"> {
+def LLVM_AllocaOp : LLVM_Op<"alloca">, MemoryOpWithAlignmentBase {
   let arguments = (ins LLVM_AnyInteger:$arraySize,
OptionalAttr:$alignment);
   let results = (outs LLVM_AnyPointer:$res);
@@ -277,19 +263,18 @@ def LLVM_AllocaOp :
   let printer = [{ printAllocaOp(p, *this); }];
 }
 
-def LLVM_GEPOp : LLVM_OneResultOp<"getelementptr", [NoSideEffect]>,
+def LLVM_GEPOp : LLVM_Op<"getelementptr", [NoSideEffect]>,
  LLVM_Builder<"$res = builder.CreateGEP($base, $indices);"> {
   let arguments = (ins LLVM_ScalarOrVectorOf:$base,
Variadic>:$indices);
   let results = (outs LLVM_ScalarOrVectorOf:$res);
+  let builders = [LLVM_OneResultOpBuilder];
   let assemblyFormat = [{
 $base `[` $indices `]` attr-dict `:` functional-type(operands, results)
   }];
 }
 
-def LLVM_LoadOp :
-MemoryOpWithAlignmentAndAttributes,
-LLVM_OneResultOp<"load"> {
+def LLVM_LoadOp : LLVM_Op<"load">, MemoryOpWithAlignmentAndAttributes {
   let arguments

[llvm-branch-commits] [mlir] 96076a2 - [mlir] Support index and memref types in llvm.mlir.cast

2020-12-17 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2020-12-17T09:21:42+01:00
New Revision: 96076a2edbd63e3e9d6ee0eca0c90d34579b7602

URL: 
https://github.com/llvm/llvm-project/commit/96076a2edbd63e3e9d6ee0eca0c90d34579b7602
DIFF: 
https://github.com/llvm/llvm-project/commit/96076a2edbd63e3e9d6ee0eca0c90d34579b7602.diff

LOG: [mlir] Support index and memref types in llvm.mlir.cast

This operation is designed to support partial conversion, more specifically the
IR state in which some operations expect or produce built-in types and some
operations produce and expect LLVM dialect types. It is reasonable for it to
support cast between built-in types and any equivalent that could be produced
by the type conversion. (At the same time, we don't want the dialect to depend
on the type conversion as it could lead to a dependency cycle). Introduce
support for casting from index to any integer type and back, and from memref to
bare pointer or memref descriptor type and back.

Contrary to what the TODO in the code stated, there are no particular
precautions necessary to handle the bare pointer conversion for memerfs. This
conversion applies exclusively to statically-shaped memrefs, so we can always
recover the full descriptor contents from the type.

This patch simultaneously tightens the verification for other types to only
accept matching pairs of types, e.g., i64 and !llvm.i64, as opposed to the
previous implementation that only checked if the types were generally allowed
byt not for matching, e.g. i64 could be "casted" to !llvm.bfloat, which is not
the intended semantics.

Move the relevant test under test/Dialect/LLVMIR because it is not specific to
the conversion pass, but rather exercises an op in the dialect. If we decide
this op does not belong to the LLVM dialect, both the dialect and the op should
move together.

Reviewed By: silvas, ezhulenev

Differential Revision: https://reviews.llvm.org/D93405

Added: 
mlir/test/Dialect/LLVMIR/dialect-cast.mlir

Modified: 
mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
mlir/test/Conversion/StandardToLLVM/invalid.mlir

Removed: 




diff  --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp 
b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index e3a5de788e49..d70a327824b7 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -1067,40 +1067,190 @@ static void printGlobalOp(OpAsmPrinter &p, GlobalOp 
op) {
 // Verifier for LLVM::DialectCastOp.
 
//===--===//
 
-static LogicalResult verify(DialectCastOp op) {
-  auto verifyMLIRCastType = [&op](Type type) -> LogicalResult {
-if (auto llvmType = type.dyn_cast()) {
-  if (llvmType.isVectorTy())
-llvmType = llvmType.getVectorElementType();
-  if (llvmType.isIntegerTy() || llvmType.isBFloatTy() ||
-  llvmType.isHalfTy() || llvmType.isFloatTy() ||
-  llvmType.isDoubleTy()) {
-return success();
-  }
-  return op.emitOpError("type must be non-index integer types, float "
-"types, or vector of mentioned types.");
+/// Checks if `llvmType` is dialect cast-compatible with `index` type. Does not
+/// report the error, the user is expected to produce an appropriate message.
+// TODO: make the size depend on data layout rather than on the conversion
+// pass option, and pull that information here.
+static LogicalResult verifyCastWithIndex(LLVMType llvmType) {
+  return success(llvmType.isa());
+}
+
+/// Checks if `llvmType` is dialect cast-compatible with built-in `type` and
+/// reports errors to the location of `op`.
+static LogicalResult verifyCast(DialectCastOp op, LLVMType llvmType,
+Type type) {
+  // Index is compatible with any integer.
+  if (type.isIndex()) {
+if (succeeded(verifyCastWithIndex(llvmType)))
+  return success();
+
+return op.emitOpError("invalid cast between index and non-integer type");
+  }
+
+  // Simple one-to-one mappings for floating point types.
+  if (type.isF16()) {
+if (llvmType.isa())
+  return success();
+return op.emitOpError(
+"invalid cast between f16 and a type other than !llvm.half");
+  }
+  if (type.isBF16()) {
+if (llvmType.isa())
+  return success();
+return op->emitOpError(
+"invalid cast between bf16 and a type other than !llvm.bfloat");
+  }
+  if (type.isF32()) {
+if (llvmType.isa())
+  return success();
+return op->emitOpError(
+"invalid cast between f32 and a type other than !llvm.float");
+  }
+  if (type.isF64()) {
+if (llvmType.isa())
+  return success();
+return op->emitOpError(
+"invalid cast between f64 and a type other than !llvm.double");
+  }
+
+  // Singless integers are compatible with LLVM integer of the same bitwidth.
+  if (type.isSignlessInteger()) {
+auto llvmInt = llvmType.dyn_cast();
+

[llvm-branch-commits] [mlir] c275125 - [mlir] partially update LLVM dialect documentation

2020-12-17 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2020-12-17T12:32:34+01:00
New Revision: c2751250f33f61e95e5d9feec95e5b063c601806

URL: 
https://github.com/llvm/llvm-project/commit/c2751250f33f61e95e5d9feec95e5b063c601806
DIFF: 
https://github.com/llvm/llvm-project/commit/c2751250f33f61e95e5d9feec95e5b063c601806.diff

LOG: [mlir] partially update LLVM dialect documentation

Rewrite the parts of the documentation that became stale: context/module
handling and type system. Expand the type system description.

Reviewed By: nicolasvasilache

Differential Revision: https://reviews.llvm.org/D93315

Added: 


Modified: 
mlir/docs/Dialects/LLVM.md

Removed: 




diff  --git a/mlir/docs/Dialects/LLVM.md b/mlir/docs/Dialects/LLVM.md
index 9e2dbd65b4a3..c4607dbd735b 100644
--- a/mlir/docs/Dialects/LLVM.md
+++ b/mlir/docs/Dialects/LLVM.md
@@ -1,49 +1,296 @@
 # 'llvm' Dialect
 
-This dialect wraps the LLVM IR types and instructions into MLIR types and
-operations. It provides several additional operations that are necessary to
-cover for the 
diff erences in the IR structure (e.g., MLIR does not have `phi`
-operations and LLVM IR does not have a `constant` operation).
+This dialect maps [LLVM IR](https://llvm.org/docs/LangRef.html) into MLIR by
+defining the corresponding operations and types. LLVM IR metadata is usually
+represented as MLIR attributes, which offer additional structure verification.
 
-In this document, we use "LLVM IR" to designate the
+We use "LLVM IR" to designate the
 [intermediate representation of LLVM](https://llvm.org/docs/LangRef.html) and
-"LLVM IR _dialect_" to refer to the MLIR dialect reflecting LLVM instructions
-and types.
+"LLVM _dialect_" or "LLVM IR _dialect_" to refer to this MLIR dialect.
+
+Unless explicitly stated otherwise, the semantics of the LLVM dialect 
operations
+must correspond to the semantics of LLVM IR instructions and any divergence is
+considered a bug. The dialect also contains auxiliary operations that smoothen
+the 
diff erences in the IR structure, e.g., MLIR does not have `phi` operations
+and LLVM IR does not have a `constant` operation. These auxiliary operations 
are
+systematically prefixed with `mlir`, e.g. `llvm.mlir.constant` where `llvm.` is
+the dialect namespace prefix.
 
 [TOC]
 
-## Context and Module Association
+## Dependency on LLVM IR
+
+LLVM dialect is not expected to depend on any object that requires an
+`LLVMContext`, such as an LLVM IR instruction or type. Instead, MLIR provides
+thread-safe alternatives compatible with the rest of the infrastructure. The
+dialect is allowed to depend on the LLVM IR objects that don't require a
+context, such as data layout and triple description.
+
+## Module Structure
+
+IR modules use the built-in MLIR `ModuleOp` and support all its features. In
+particular, modules can be named, nested and are subject to symbol visibility.
+Modules can contain any operations, including LLVM functions and globals.
 
-The LLVM IR dialect object _contains_ an LLVM Context and an LLVM Module that 
it
-uses to define, print, parse and manage LLVM IR types. These objects can be
-obtained from the dialect object using `.getLLVMContext()` and
-`getLLVMModule()`. All LLVM IR objects that interact with the LLVM IR dialect
-must exist in the dialect's context.
+### Data Layout and Triple
+
+An IR module may have an optional data layout and triple information attached
+using MLIR attributes `llvm.data_layout` and `llvm.triple`, respectively. Both
+are string attributes with the
+[same syntax](https://llvm.org/docs/LangRef.html#data-layout) as in LLVM IR and
+are verified to be correct. They can be defined as follows.
+
+```mlir
+module attributes {llvm.data_layout = "e",
+   llvm.target_triple = "aarch64-linux-android"} {
+  // module contents
+}
+```
 
 ## Types
 
-The LLVM IR dialect defines a single MLIR type, `LLVM::LLVMType`, that can wrap
-any existing LLVM IR type. Its syntax is as follows
+LLVM dialect defines a set of types that correspond to LLVM IR types. The
+dialect type system is _closed_: types from other dialects are not allowed
+within LLVM dialect aggregate types. This property allows for more concise
+custom syntax and ensures easy translation to LLVM IR.
+
+Similarly to other MLIR context-owned objects, the creation and manipulation of
+LLVM dialect types is thread-safe.
+
+MLIR does not support module-scoped named type declarations, e.g. `%s = type
+{i32, i32}` in LLVM IR. Instead, types must be fully specified at each use,
+except for recursive types where only the first reference to a named type needs
+to be fully specified. MLIR type aliases are supported for top-level types, 
i.e.
+they cannot be used inside the type due to type system closedness.
+
+The general syntax of LLVM dialect types is `!llvm.`, followed by a type kind
+identifier (e.g., `ptr` for pointer or `struct` for structure) and by an
+optional list of type 

[llvm-branch-commits] [mlir] ccdd8c7 - [mlir] Move LLVM Dialect Op documentation to ODS

2020-12-17 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2020-12-17T12:32:35+01:00
New Revision: ccdd8c7759459ef4b9b09820d241081d387be779

URL: 
https://github.com/llvm/llvm-project/commit/ccdd8c7759459ef4b9b09820d241081d387be779
DIFF: 
https://github.com/llvm/llvm-project/commit/ccdd8c7759459ef4b9b09820d241081d387be779.diff

LOG: [mlir] Move LLVM Dialect Op documentation to ODS

This was long overdue. The initial documentation for the LLVM dialect was
introduced before ODS had support for long descriptions. This is now possible,
so the documentation is moved to ODS, which can serve as a single source of
truth. The high-level description of the dialect structure is updated to
reflect that.

Depends On: D93315

Reviewed By: rriddle, mehdi_amini

Differential Revision: https://reviews.llvm.org/D93425

Added: 


Modified: 
mlir/docs/Dialects/LLVM.md
mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt
mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td

Removed: 




diff  --git a/mlir/docs/Dialects/LLVM.md b/mlir/docs/Dialects/LLVM.md
index c4607dbd735b..fbe1a1cfe7ea 100644
--- a/mlir/docs/Dialects/LLVM.md
+++ b/mlir/docs/Dialects/LLVM.md
@@ -47,6 +47,143 @@ module attributes {llvm.data_layout = "e",
 }
 ```
 
+### Functions
+
+LLVM functions are represented by a special operation, `llvm.func`, that has
+syntax similar to that of the built-in function operation but supports
+LLVM-related features such as linkage and variadic argument lists. See detailed
+description in the operation list [below](#llvmfunc-mlirllvmllvmfuncop).
+
+### PHI Nodes and Block Arguments
+
+MLIR uses block arguments instead of PHI nodes to communicate values between
+blocks. Therefore, the LLVM dialect has no operation directly equivalent to
+`phi` in LLVM IR. Instead, all terminators can pass values as successor 
operands
+as these values will be forwarded as block arguments when the control flow is
+transferred.
+
+For example:
+
+```mlir
+^bb1:
+  %0 = llvm.addi %arg0, %cst : !llvm.i32
+  llvm.br ^bb2[%0: !llvm.i32]
+
+// If the control flow comes from ^bb1, %arg1 == %0.
+^bb2(%arg1: !llvm.i32)
+  // ...
+```
+
+is equivalent to LLVM IR
+
+```llvm
+%0:
+  %1 = add i32 %arg0, %cst
+  br %3
+
+%3:
+  %arg1 = phi [%1, %0], //...
+```
+
+Since there is no need to use the block identifier to 
diff erentiate the source
+of 
diff erent values, the LLVM dialect supports terminators that transfer the
+control flow to the same block with 
diff erent arguments. For example:
+
+```mlir
+^bb1:
+  llvm.cond_br %cond, ^bb2[%0: !llvm.i32], ^bb2[%1: !llvm.i32]
+
+^bb2(%arg0: !llvm.i32):
+  // ...
+```
+
+### Context-Level Values
+
+Some value kinds in LLVM IR, such as constants and undefs, are uniqued in
+context and used directly in relevant operations. MLIR does not support such
+values for thread-safety and concept parsimony reasons. Instead, regular values
+are produced by dedicated operations that have the corresponding semantics:
+[`llvm.mlir.constant`](#llvmmlirconstant-mlirllvmconstantop),
+[`llvm.mlir.undef`](#llvmmlirundef-mlirllvmundefop),
+[`llvm.mlir.null`](#llvmmlirnull-mlirnullop). Note how these operations are
+prefixed with `mlir.` to indicate that they don't belong to LLVM IR but are 
only
+necessary to model it in MLIR. The values produced by these operations are
+usable just like any other value.
+
+Examples:
+
+```mlir
+// Create an undefined value of structure type with a 32-bit integer followed
+// by a float.
+%0 = llvm.mlir.undef : !llvm.struct<(i32, float)>
+
+// Null pointer to i8.
+%1 = llvm.mlir.null : !llvm.ptr
+
+// Null pointer to a function with signature void().
+%2 = llvm.mlir.null : !llvm.ptr>
+
+// Constant 42 as i32.
+%3 = llvm.mlir.constant(42 : i32) : !llvm.i32
+
+// Splat dense vector constant.
+%3 = llvm.mlir.constant(dense<1.0> : vector<4xf32>) : !llvm.vec<4 x float>
+```
+
+Note that constants use built-in types within the initializer definition: MLIR
+attributes are typed and the attributes used for constants require a built-in
+type.
+
+### Globals
+
+Global variables are also defined using a special operation,
+[`llvm.mlir.global`](#llvmmlirglobal-mlirllvmglobalop), located at the module
+level. Globals are MLIR symbols and are identified by their name.
+
+Since functions need to be isolated-from-above, i.e. values defined outside the
+function cannot be directly used inside the function, an additional operation,
+[`llvm.mlir.addressof`](#llvmmliraddressof-mlirllvmaddressofop), is provided to
+locally define a value containing the _address_ of a global. The actual value
+can then be loaded from that pointer, or a new value can be stored into it if
+the global is not declared constant. This is similar to LLVM IR where globals
+are accessed through name and have a pointer type.
+
+### Linkage
+
+Module-level named objects in the LLVM dialect, namely functions and globals,
+have an optional _linkage_ attribute derived from LLVM IR
+[linkage types]

[llvm-branch-commits] [mlir] eb4917d - [mlir] Fix syntax error in markdown documentation

2020-12-17 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2020-12-17T14:09:31+01:00
New Revision: eb4917d121e21aaf8406efe3d5e4f1f06cb7c238

URL: 
https://github.com/llvm/llvm-project/commit/eb4917d121e21aaf8406efe3d5e4f1f06cb7c238
DIFF: 
https://github.com/llvm/llvm-project/commit/eb4917d121e21aaf8406efe3d5e4f1f06cb7c238.diff

LOG: [mlir] Fix syntax error in markdown documentation

Added: 


Modified: 
mlir/docs/Dialects/LLVM.md

Removed: 




diff  --git a/mlir/docs/Dialects/LLVM.md b/mlir/docs/Dialects/LLVM.md
index fbe1a1cfe7ea..3b9150f0e69d 100644
--- a/mlir/docs/Dialects/LLVM.md
+++ b/mlir/docs/Dialects/LLVM.md
@@ -434,4 +434,4 @@ MLIR, blocks are not values and don't need a type.
 All operations in the LLVM IR dialect have a custom form in MLIR. The mnemonic
 of an operation is that used in LLVM IR prefixed with "`llvm.`".
 
-[include "Dialects/LLVMOps.md"
+[include "Dialects/LLVMOps.md"]



___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] 0efb0dd - [mlir] Partially update the conversion-to-llvm document

2020-12-17 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2020-12-17T22:00:09+01:00
New Revision: 0efb0dd978014c9ca5ef4cd93516a0cd6e77f185

URL: 
https://github.com/llvm/llvm-project/commit/0efb0dd978014c9ca5ef4cd93516a0cd6e77f185
DIFF: 
https://github.com/llvm/llvm-project/commit/0efb0dd978014c9ca5ef4cd93516a0cd6e77f185.diff

LOG: [mlir] Partially update the conversion-to-llvm document

This document was not updated after the LLVM dialect type system had been
reimplemented and was using an outdated syntax. Rewrite the part of the
document that concerns type conversion and prepare the ground for splitting it
into a document that explains how built-in types are converted and a separate
document that explains how standard types and functions are converted, which
will better correspond to the fact that built-in types do not belong to the
standard dialect.

Reviewed By: rriddle

Differential Revision: https://reviews.llvm.org/D93486

Added: 


Modified: 
mlir/docs/ConversionToLLVMDialect.md

Removed: 




diff  --git a/mlir/docs/ConversionToLLVMDialect.md 
b/mlir/docs/ConversionToLLVMDialect.md
index 27b732015f9f..778eea6184c9 100644
--- a/mlir/docs/ConversionToLLVMDialect.md
+++ b/mlir/docs/ConversionToLLVMDialect.md
@@ -1,16 +1,19 @@
 # Conversion to the LLVM Dialect
 
-Conversion from the Standard to the [LLVM Dialect](Dialects/LLVM.md) can be
-performed by the specialized dialect conversion pass by running:
+Conversion from several dialects that rely on
+[built-in types](LangRef.md#builtin-types) to the
+[LLVM Dialect](Dialects/LLVM.md) is expected to be performed through the
+[Dialect Conversion](DialectConversion.md) infrastructure.
 
-```shell
-mlir-opt -convert-std-to-llvm 
-```
+The conversion of types and that of the overall module structure is described 
in
+this document. Individual conversion passes provide a set of conversion 
patterns
+for ops in 
diff erent dialects, such as `-convert-std-to-llvm` for ops in the
+[Standard dialect](Dialects/Standard.md) and `-convert-vector-to-llvm` in the
+[Vector dialect](Dialects/Vector.md). *Note that some conversions subsume the
+others.*
 
-It performs type and operation conversions for a subset of operations from
-standard dialect (operations on scalars and vectors, control flow operations) 
as
-described in this document. We use the terminology defined by the
-[LLVM IR Dialect description](Dialects/LLVM.md) throughout this document.
+We use the terminology defined by the
+[LLVM Dialect description](Dialects/LLVM.md) throughout this document.
 
 [TOC]
 
@@ -22,19 +25,19 @@ Scalar types are converted to their LLVM counterparts if 
they exist. The
 following conversions are currently implemented:
 
 -   `i*` converts to `!llvm.i*`
+-   `bf16` converts to `!llvm.bfloat`
 -   `f16` converts to `!llvm.half`
 -   `f32` converts to `!llvm.float`
 -   `f64` converts to `!llvm.double`
 
-Note: `bf16` type is not supported by LLVM IR and cannot be converted.
-
 ### Index Type
 
-Index type is converted to a wrapped LLVM IR integer with bitwidth equal to the
-bitwidth of the pointer size as specified by the
-[data layout](https://llvm.org/docs/LangRef.html#data-layout) of the LLVM 
module
-[contained](Dialects/LLVM.md#context-and-module-association) in the LLVM 
Dialect
-object. For example, on x86-64 CPUs it converts to `!llvm.i64`.
+Index type is converted to an LLVM dialect integer type with bitwidth equal to
+the bitwidth of the pointer size as specified by the
+[data layout](Dialects/LLVM.md#data-layout-and-triple) of the closest module.
+For example, on x86-64 CPUs it converts to `!llvm.i64`. This behavior can be
+overridden by the type converter configuration, which is often exposed as a 
pass
+option by conversion passes.
 
 ### Vector Types
 
@@ -45,31 +48,54 @@ size with element type converted using these conversion 
rules. In the
 n-dimensional case, MLIR vectors are converted to (n-1)-dimensional array types
 of one-dimensional vectors.
 
-For example, `vector<4 x f32>` converts to `!llvm<"<4 x float>">` and `vector<4
-x 8 x 16 x f32>` converts to `!llvm<"[4 x [8 x <16 x float>]]">`.
+For example, `vector<4 x f32>` converts to `!llvm.vec<4 x float>` and `vector<4
+x 8 x 16 x f32>` converts to `!llvm.array<4 x array<8 x vec<16 x float>>>`.
 
-### Memref Types
+### Ranked Memref Types
 
 Memref types in MLIR have both static and dynamic information associated with
-them. The dynamic information comprises the buffer pointer as well as sizes and
+them. In the general case, the dynamic information describes dynamic sizes in
+the logical indexing space and any symbols bound to the memref. This dynamic
+information must be present at runtime in the LLVM dialect equivalent type.
+
+In practice, the conversion supports two conventions:
+
+-   the default convention for memrefs in the
+**[strided form](LangRef.md#strided-memref)**;
+-   a "bare pointer" conversion for statically-shaped memrefs with

[llvm-branch-commits] [mlir] 2f5569f - [mlir] remove deprecated string-based OpBuilder from ODS

2020-12-22 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2020-12-22T09:57:49+01:00
New Revision: 2f5569f6f67a30f7774f7c2d2f3d726752a862ae

URL: 
https://github.com/llvm/llvm-project/commit/2f5569f6f67a30f7774f7c2d2f3d726752a862ae
DIFF: 
https://github.com/llvm/llvm-project/commit/2f5569f6f67a30f7774f7c2d2f3d726752a862ae.diff

LOG: [mlir] remove deprecated string-based OpBuilder from ODS

It has been deprecated with a warning for two months, removing.

Reviewed By: mehdi_amini

Differential Revision: https://reviews.llvm.org/D93623

Added: 


Modified: 
mlir/include/mlir/IR/OpBase.td
mlir/test/mlir-tblgen/op-decl.td
mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp

Removed: 




diff  --git a/mlir/include/mlir/IR/OpBase.td b/mlir/include/mlir/IR/OpBase.td
index 0f060b2b1a0a..0ae572c38f49 100644
--- a/mlir/include/mlir/IR/OpBase.td
+++ b/mlir/include/mlir/IR/OpBase.td
@@ -1939,15 +1939,6 @@ def region;
 // Marker used to identify the successor list for an op.
 def successor;
 
-// Base class for custom builders. This is a transient class that will go away
-// when the transition to the DAG form of builder declaration is complete.
-// Should not be used directly.
-class OpBuilderBase {
-  string params = ?;
-  dag dagParams = dp;
-  code body = b;
-}
-
 // Class for defining a custom builder.
 //
 // TableGen generates several generic builders for each op by default (see
@@ -1986,11 +1977,9 @@ class OpBuilderBase {
 // If an empty string is passed in for `body`, then *only* the builder
 // declaration will be generated; this provides a way to define complicated
 // builders entirely in C++.
-class OpBuilderDAG : OpBuilderBase;
-
-// Deprecated version of OpBuilder that takes the builder signature as string.
-class OpBuilder : OpBuilderBase<(ins), b> {
-  let params = p;
+class OpBuilderDAG {
+  dag dagParams = p;
+  code body = b;
 }
 
 // A base decorator class that may optionally be added to OpVariables.
@@ -2068,7 +2057,7 @@ class Op 
props = []> {
   //   ValueRange operands,
   //   ArrayRef attributes);
   // ```
-  list builders = ?;
+  list builders = ?;
 
   // Avoid generating default build functions.  Custom builders must be
   // provided.

diff  --git a/mlir/test/mlir-tblgen/op-decl.td 
b/mlir/test/mlir-tblgen/op-decl.td
index 29438f1836a7..13daca67c475 100644
--- a/mlir/test/mlir-tblgen/op-decl.td
+++ b/mlir/test/mlir-tblgen/op-decl.td
@@ -34,8 +34,7 @@ def NS_AOp : NS_Op<"a_op", [IsolatedFromAbove, 
IsolatedFromAbove]> {
 VariadicRegion:$someRegions
   );
   let builders = [OpBuilderDAG<(ins "Value":$val)>,
-  OpBuilderDAG<(ins CArg<"int", "0">:$integer)>,
-  OpBuilder<"double deprecatedForm">];
+  OpBuilderDAG<(ins CArg<"int", "0">:$integer)>];
   let parser = [{ foo }];
   let printer = [{ bar }];
   let verifier = [{ baz }];
@@ -84,7 +83,6 @@ def NS_AOp : NS_Op<"a_op", [IsolatedFromAbove, 
IsolatedFromAbove]> {
 // CHECK:   ::llvm::Optional< ::llvm::APFloat > attr2();
 // CHECK:   static void build(::mlir::OpBuilder &odsBuilder, 
::mlir::OperationState &odsState, Value val);
 // CHECK:   static void build(::mlir::OpBuilder &odsBuilder, 
::mlir::OperationState &odsState, int integer = 0);
-// CHECK:   static void build(::mlir::OpBuilder &odsBuilder, 
::mlir::OperationState &odsState, double deprecatedForm);
 // CHECK:   static void build(::mlir::OpBuilder &odsBuilder, 
::mlir::OperationState &odsState, ::mlir::Type r, ::mlir::TypeRange s, 
::mlir::Value a, ::mlir::ValueRange b, ::mlir::IntegerAttr attr1, 
/*optional*/::mlir::FloatAttr attr2, unsigned someRegionsCount)
 // CHECK:   static void build(::mlir::OpBuilder &odsBuilder, 
::mlir::OperationState &odsState, ::mlir::Type r, ::mlir::TypeRange s, 
::mlir::Value a, ::mlir::ValueRange b, uint32_t attr1, 
/*optional*/::mlir::FloatAttr attr2, unsigned someRegionsCount)
 // CHECK:   static void build(::mlir::OpBuilder &, ::mlir::OperationState 
&odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, 
::llvm::ArrayRef<::mlir::NamedAttribute> attributes, unsigned numRegions)

diff  --git a/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp 
b/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
index 1c8cbfb9db38..40e1c355daf8 100644
--- a/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
+++ b/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
@@ -1304,8 +1304,7 @@ void OpEmitter::genUseAttrAsResultTypeBuilder() {
 /// Updates the context `fctx` to enable replacement of $_builder and $_state
 /// in the body. Reports errors at `loc`.
 static std::string builderSignatureFromDAG(const DagInit *init,
-   ArrayRef loc,
-   FmtContext &fctx) {
+   ArrayRef loc) {
   auto *defInit = dyn_cast(init->getOperator());
   if (!defInit || !defInit->getDef()->getName().equals("ins"))
 PrintFatalError(loc

[llvm-branch-commits] [mlir] 8de43b9 - [mlir] Remove instance methods from LLVMType

2020-12-22 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2020-12-22T23:34:54+01:00
New Revision: 8de43b926f0e960bbc5b6a53d1b613c46b7c774b

URL: 
https://github.com/llvm/llvm-project/commit/8de43b926f0e960bbc5b6a53d1b613c46b7c774b
DIFF: 
https://github.com/llvm/llvm-project/commit/8de43b926f0e960bbc5b6a53d1b613c46b7c774b.diff

LOG: [mlir] Remove instance methods from LLVMType

LLVMType contains multiple instance methods that were introduced initially for
compatibility with LLVM API. These methods boil down to `cast` followed by
type-specific call. Arguably, they are mostly used in an LLVM cast-follows-isa
anti-pattern. This doesn't connect nicely to the rest of the MLIR
infrastructure and actively prevents it from making the LLVM dialect type
system more open, e.g., reusing built-in types when appropriate. Remove such
instance methods and replaces their uses with apporpriate casts and methods on
derived classes. In some cases, the result may look slightly more verbose, but
most cases should actually use a stricter subtype of LLVMType anyway and avoid
the isa/cast.

Reviewed By: mehdi_amini

Differential Revision: https://reviews.llvm.org/D93680

Added: 


Modified: 
mlir/include/mlir/Conversion/StandardToLLVM/ConvertStandardToLLVM.h
mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
mlir/include/mlir/Dialect/LLVMIR/LLVMTypes.h
mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td
mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp
mlir/lib/Conversion/GPUCommon/ConvertLaunchFuncToRuntimeCalls.cpp
mlir/lib/Conversion/GPUCommon/GPUOpsLowering.h
mlir/lib/Conversion/GPUCommon/OpToFuncCallLowering.h
mlir/lib/Conversion/GPUToVulkan/ConvertLaunchFuncToVulkanCalls.cpp
mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.cpp
mlir/lib/Conversion/StandardToLLVM/StandardToLLVM.cpp
mlir/lib/Conversion/VectorToLLVM/ConvertVectorToLLVM.cpp
mlir/lib/Conversion/VectorToROCDL/VectorToROCDL.cpp
mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
mlir/lib/Dialect/LLVMIR/IR/LLVMTypes.cpp
mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp
mlir/lib/ExecutionEngine/JitRunner.cpp
mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp
mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
mlir/test/Dialect/LLVMIR/invalid.mlir

Removed: 




diff  --git 
a/mlir/include/mlir/Conversion/StandardToLLVM/ConvertStandardToLLVM.h 
b/mlir/include/mlir/Conversion/StandardToLLVM/ConvertStandardToLLVM.h
index 7c069c9cd556..63ff16a84ab8 100644
--- a/mlir/include/mlir/Conversion/StandardToLLVM/ConvertStandardToLLVM.h
+++ b/mlir/include/mlir/Conversion/StandardToLLVM/ConvertStandardToLLVM.h
@@ -446,7 +446,8 @@ class UnrankedMemRefDescriptor : public StructBuilder {
   /// Builds IR extracting the pointer to the first element of the size array.
   static Value sizeBasePtr(OpBuilder &builder, Location loc,
LLVMTypeConverter &typeConverter,
-   Value memRefDescPtr, LLVM::LLVMType elemPtrPtrType);
+   Value memRefDescPtr,
+   LLVM::LLVMPointerType elemPtrPtrType);
   /// Builds IR extracting the size[index] from the descriptor.
   static Value size(OpBuilder &builder, Location loc,
 LLVMTypeConverter typeConverter, Value sizeBasePtr,

diff  --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td 
b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index df022ef47b33..552fe15e6899 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -51,7 +51,7 @@ def LLVM_VoidResultTypeOpBuilder :
   [{
 auto llvmType = resultType.dyn_cast(); (void)llvmType;
 assert(llvmType && "result must be an LLVM type");
-assert(llvmType.isVoidTy() &&
+assert(llvmType.isa() &&
"for zero-result operands, only 'void' is accepted as result type");
 build($_builder, $_state, operands, attributes);
   }]>;
@@ -288,7 +288,7 @@ def LLVM_LoadOp : LLVM_Op<"load">, 
MemoryOpWithAlignmentAndAttributes {
 OpBuilderDAG<(ins "Value":$addr, CArg<"unsigned", "0">:$alignment,
   CArg<"bool", "false">:$isVolatile, CArg<"bool", "false">:$isNonTemporal),
 [{
-  auto type = addr.getType().cast().getPointerElementTy();
+  auto type = addr.getType().cast().getElementType();
   build($_builder, $_state, type, addr, alignment, isVolatile, 
isNonTemporal);
 }]>,
 OpBuilderDAG<(ins "Type":$t, "Value":$addr,
@@ -443,8 +443,8 @@ def LLVM_CallOp : LLVM_Op<"call"> {
 OpBuilderDAG<(ins "LLVMFuncOp":$func, "ValueRange":$operands,
   CArg<"ArrayRef", "{}">:$attributes),
 [{
-  LLVMType resultType = func.getType().getFunctionResultType();
-  if (!resultType.isVoidTy())
+  LLVMType resultType = func.getType().getReturnType();
+  if (!resultType.isa())
 $_state.addTypes(resultType);
   $_state.addAttribute("callee", $_builder.getSymbolRefAttr(func));
   $_state.addAttri

[llvm-branch-commits] [mlir] 65ba0cd - [mlir] Modernize std-to-llvm operation conversion doc

2020-12-23 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2020-12-23T11:19:58+01:00
New Revision: 65ba0cd3955f8c609ff314dc0cda7bc8ded4a083

URL: 
https://github.com/llvm/llvm-project/commit/65ba0cd3955f8c609ff314dc0cda7bc8ded4a083
DIFF: 
https://github.com/llvm/llvm-project/commit/65ba0cd3955f8c609ff314dc0cda7bc8ded4a083.diff

LOG: [mlir] Modernize std-to-llvm operation conversion doc

This was long overdue. Replace the outdated type syntax with the new syntax,
and update the description of how memref load/stores are handled to reflect the
latest changes in the implementation.

Reviewed By: herhut

Differential Revision: https://reviews.llvm.org/D93555

Added: 
mlir/docs/LLVMDialectMemRefConvention.md

Modified: 
mlir/docs/ConversionToLLVMDialect.md

Removed: 




diff  --git a/mlir/docs/ConversionToLLVMDialect.md 
b/mlir/docs/ConversionToLLVMDialect.md
index 778eea6184c9..2b5f98b37686 100644
--- a/mlir/docs/ConversionToLLVMDialect.md
+++ b/mlir/docs/ConversionToLLVMDialect.md
@@ -280,470 +280,3 @@ Examples:
 !llvm.func, ptr, i64)>,
struct<(ptr, ptr, i64)>)> ()>
 ```
-
-## Calling Convention for Standard Calls
-
-
-
-### Result Packing
-
-In case of multi-result functions, the returned values are inserted into a
-structure-typed value before being returned and extracted from it at the call
-site. This transformation is a part of the conversion and is transparent to the
-defines and uses of the values being returned.
-
-Example:
-
-```mlir
-func @foo(%arg0: i32, %arg1: i64) -> (i32, i64) {
-  return %arg0, %arg1 : i32, i64
-}
-func @bar() {
-  %0 = constant 42 : i32
-  %1 = constant 17 : i64
-  %2:2 = call @foo(%0, %1) : (i32, i64) -> (i32, i64)
-  "use_i32"(%2#0) : (i32) -> ()
-  "use_i64"(%2#1) : (i64) -> ()
-}
-
-// is transformed into
-
-func @foo(%arg0: !llvm.i32, %arg1: !llvm.i64) -> !llvm<"{i32, i64}"> {
-  // insert the vales into a structure
-  %0 = llvm.mlir.undef :  !llvm<"{i32, i64}">
-  %1 = llvm.insertvalue %arg0, %0[0] : !llvm<"{i32, i64}">
-  %2 = llvm.insertvalue %arg1, %1[1] : !llvm<"{i32, i64}">
-
-  // return the structure value
-  llvm.return %2 : !llvm<"{i32, i64}">
-}
-func @bar() {
-  %0 = llvm.mlir.constant(42 : i32) : !llvm.i32
-  %1 = llvm.mlir.constant(17) : !llvm.i64
-
-  // call and extract the values from the structure
-  %2 = llvm.call @bar(%0, %1) : (%arg0: !llvm.i32, %arg1: !llvm.i32) -> 
!llvm<"{i32, i64}">
-  %3 = llvm.extractvalue %2[0] : !llvm<"{i32, i64}">
-  %4 = llvm.extractvalue %2[1] : !llvm<"{i32, i64}">
-
-  // use as before
-  "use_i32"(%3) : (!llvm.i32) -> ()
-  "use_i64"(%4) : (!llvm.i64) -> ()
-}
-```
-
-### Calling Convention for Ranked `memref`
-
-Function _arguments_ of `memref` type, ranked or unranked, are _expanded_ into 
a
-list of arguments of non-aggregate types that the memref descriptor defined
-above comprises. That is, the outer struct type and the inner array types are
-replaced with individual arguments.
-
-This convention is implemented in the conversion of `std.func` and `std.call` 
to
-the LLVM dialect, with the former unpacking the descriptor into a set of
-individual values and the latter packing those values back into a descriptor so
-as to make it transparently usable by other operations. Conversions from other
-dialects should take this convention into account.
-
-This specific convention is motivated by the necessity to specify alignment and
-aliasing attributes on the raw pointers underpinning the memref.
-
-Examples:
-
-```mlir
-func @foo(%arg0: memref) -> () {
-  "use"(%arg0) : (memref) -> ()
-  return
-}
-
-// Gets converted to the following.
-
-llvm.func @foo(%arg0: !llvm<"float*">,   // Allocated pointer.
-   %arg1: !llvm<"float*">,   // Aligned pointer.
-   %arg2: !llvm.i64, // Offset.
-   %arg3: !llvm.i64, // Size in dim 0.
-   %arg4: !llvm.i64) {   // Stride in dim 0.
-  // Populate memref descriptor structure.
-  %0 = llvm.mlir.undef : !llvm<"{ float*, float*, i64, [1 x i64], [1 x i64] }">
-  %1 = llvm.insertvalue %arg0, %0[0] : !llvm<"{ float*, float*, i64, [1 x 
i64], [1 x i64] }">
-  %2 = llvm.insertvalue %arg1, %1[1] : !llvm<"{ float*, float*, i64, [1 x 
i64], [1 x i64] }">
-  %3 = llvm.insertvalue %arg2, %2[2] : !llvm<"{ float*, float*, i64, [1 x 
i64], [1 x i64] }">
-  %4 = llvm.insertvalue %arg3, %3[3, 0] : !llvm<"{ float*, float*, i64, [1 x 
i64], [1 x i64] }">
-  %5 = llvm.insertvalue %arg4, %4[4, 0] : !llvm<"{ float*, float*, i64, [1 x 
i64], [1 x i64] }">
-
-  // Descriptor is now usable as a single value.
-  "use"(%5) : (!llvm<"{ float*, float*, i64, [1 x i64], [1 x i64] }">) -> ()
-  llvm.return
-}
-```
-
-```mlir
-func @bar() {
-  %0 = "get"() : () -> (memref)
-  call @foo(%0) : (memref) -> ()
-  return
-}
-
-// Gets converted to the following.
-
-llvm.func @bar() {
-  %0 = "get"() : () -> !llvm<"{ float*, float*, i64, [1 x i64], [1 x i64] }">
-
-  // Unpack the me

[llvm-branch-commits] [mlir] 32a884c - [mlir] Add translation of omp.wsloop to LLVM IR

2020-12-23 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2020-12-23T11:52:28+01:00
New Revision: 32a884c9c52c1216d57835e557233b238d601726

URL: 
https://github.com/llvm/llvm-project/commit/32a884c9c52c1216d57835e557233b238d601726
DIFF: 
https://github.com/llvm/llvm-project/commit/32a884c9c52c1216d57835e557233b238d601726.diff

LOG: [mlir] Add translation of omp.wsloop to LLVM IR

Introduce a translation of OpenMP workshare loop construct to LLVM IR. This is
a minimalist version to enable the pipeline and currently only supports static
loop schedule (default in the specification) on non-collapsed loops. Other
features will be added on per-need basis.

Reviewed By: kiranchandramohan

Differential Revision: https://reviews.llvm.org/D92055

Added: 


Modified: 
mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
mlir/test/Target/openmp-llvm.mlir

Removed: 




diff  --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td 
b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
index f915afcf32c9..6c6230f0c2e8 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
@@ -185,6 +185,11 @@ def WsLoopOp : OpenMP_Op<"wsloop", 
[AttrSizedOperandSegments]> {
   ];
 
   let regions = (region AnyRegion:$region);
+
+  let extraClassDeclaration = [{
+/// Returns the number of loops in the workshape loop nest.
+unsigned getNumLoops() { return lowerBound().size(); }
+  }];
 }
 
 def YieldOp : OpenMP_Op<"yield", [NoSideEffect, ReturnLike, Terminator,

diff  --git a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h 
b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
index d3d289414b38..5259ed7fe182 100644
--- a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
+++ b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
@@ -100,6 +100,9 @@ class ModuleTranslation {
llvm::BasicBlock &continuationIP,
llvm::IRBuilder<> &builder,
LogicalResult &bodyGenStatus);
+  virtual LogicalResult convertOmpWsLoop(Operation &opInst,
+ llvm::IRBuilder<> &builder);
+
   /// Converts the type from MLIR LLVM dialect to LLVM.
   llvm::Type *convertType(LLVMType type);
 

diff  --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp 
b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index ae0745b0be28..0b2cf7de270f 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -536,6 +536,126 @@ LogicalResult 
ModuleTranslation::convertOmpMaster(Operation &opInst,
   return success();
 }
 
+/// Converts an OpenMP workshare loop into LLVM IR using OpenMPIRBuilder.
+LogicalResult ModuleTranslation::convertOmpWsLoop(Operation &opInst,
+  llvm::IRBuilder<> &builder) {
+  auto loop = cast(opInst);
+  // TODO: this should be in the op verifier instead.
+  if (loop.lowerBound().empty())
+return failure();
+
+  if (loop.getNumLoops() != 1)
+return opInst.emitOpError("collapsed loops not yet supported");
+
+  if (loop.schedule_val().hasValue() &&
+  omp::symbolizeClauseScheduleKind(loop.schedule_val().getValue()) !=
+  omp::ClauseScheduleKind::Static)
+return opInst.emitOpError(
+"only static (default) loop schedule is currently supported");
+
+  llvm::Function *func = builder.GetInsertBlock()->getParent();
+  llvm::LLVMContext &llvmContext = llvmModule->getContext();
+
+  // Find the loop configuration.
+  llvm::Value *lowerBound = valueMapping.lookup(loop.lowerBound()[0]);
+  llvm::Value *upperBound = valueMapping.lookup(loop.upperBound()[0]);
+  llvm::Value *step = valueMapping.lookup(loop.step()[0]);
+  llvm::Type *ivType = step->getType();
+  llvm::Value *chunk = loop.schedule_chunk_var()
+   ? valueMapping[loop.schedule_chunk_var()]
+   : llvm::ConstantInt::get(ivType, 1);
+
+  // Set up the source location value for OpenMP runtime.
+  llvm::DISubprogram *subprogram =
+  builder.GetInsertBlock()->getParent()->getSubprogram();
+  const llvm::DILocation *diLoc =
+  debugTranslation->translateLoc(opInst.getLoc(), subprogram);
+  llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder.saveIP(),
+llvm::DebugLoc(diLoc));
+
+  // Generator of the canonical loop body. Produces an SESE region of basic
+  // blocks.
+  // TODO: support error propagation in OpenMPIRBuilder and use it instead of
+  // relying on captured variables.
+  LogicalResult bodyGenStatus = success();
+  auto bodyGen = [&](llvm::OpenMPIRBuilder::InsertPointTy ip, llvm::Value *iv) 
{
+llvm::IRBuilder<>::InsertPointGuard guard(builder);
+
+// Make sure further conversions know about the induction variable.
+value

[llvm-branch-commits] [mlir] 7ed9cfc - [mlir] Remove static constructors from LLVMType

2020-12-23 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2020-12-23T13:12:47+01:00
New Revision: 7ed9cfc7b19fdba9eb441ce1a8ba82cda14d76a8

URL: 
https://github.com/llvm/llvm-project/commit/7ed9cfc7b19fdba9eb441ce1a8ba82cda14d76a8
DIFF: 
https://github.com/llvm/llvm-project/commit/7ed9cfc7b19fdba9eb441ce1a8ba82cda14d76a8.diff

LOG: [mlir] Remove static constructors from LLVMType

LLVMType contains numerous static constructors that were initially introduced
for API compatibility with LLVM. Most of these merely forward to arguments to
`SpecificType::get` (MLIR defines classes for all types, unlike LLVM IR), while
some introduce subtle semantics differences due to different modeling of MLIR
types (e.g., structs are not auto-renamed in case of conflicts). Furthermore,
these constructors don't match MLIR idioms and actively prevent us from making
the LLVM dialect type system more open. Remove them and use `SpecificType::get`
instead.

Depends On D93680

Reviewed By: mehdi_amini

Differential Revision: https://reviews.llvm.org/D93681

Added: 


Modified: 
mlir/examples/toy/Ch6/mlir/LowerToLLVM.cpp
mlir/examples/toy/Ch7/mlir/LowerToLLVM.cpp
mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
mlir/include/mlir/Dialect/LLVMIR/LLVMTypes.h
mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp
mlir/lib/Conversion/GPUCommon/ConvertLaunchFuncToRuntimeCalls.cpp
mlir/lib/Conversion/GPUCommon/GPUOpsLowering.h
mlir/lib/Conversion/GPUCommon/IndexIntrinsicsOpLowering.h
mlir/lib/Conversion/GPUCommon/OpToFuncCallLowering.h
mlir/lib/Conversion/GPUToNVVM/LowerGpuOpsToNVVMOps.cpp
mlir/lib/Conversion/GPUToVulkan/ConvertLaunchFuncToVulkanCalls.cpp
mlir/lib/Conversion/LinalgToLLVM/LinalgToLLVM.cpp
mlir/lib/Conversion/SPIRVToLLVM/ConvertLaunchFuncToLLVMCalls.cpp
mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.cpp
mlir/lib/Conversion/StandardToLLVM/StandardToLLVM.cpp
mlir/lib/Conversion/VectorToLLVM/ConvertVectorToLLVM.cpp
mlir/lib/Conversion/VectorToROCDL/VectorToROCDL.cpp
mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
mlir/lib/Dialect/LLVMIR/IR/LLVMTypes.cpp
mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp
mlir/lib/Dialect/LLVMIR/IR/ROCDLDialect.cpp
mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
mlir/test/lib/Transforms/TestConvertCallOp.cpp

Removed: 




diff  --git a/mlir/examples/toy/Ch6/mlir/LowerToLLVM.cpp 
b/mlir/examples/toy/Ch6/mlir/LowerToLLVM.cpp
index a04b3ecd4dae..6fbf29f4128d 100644
--- a/mlir/examples/toy/Ch6/mlir/LowerToLLVM.cpp
+++ b/mlir/examples/toy/Ch6/mlir/LowerToLLVM.cpp
@@ -111,10 +111,11 @@ class PrintOpLowering : public ConversionPattern {
 
 // Create a function declaration for printf, the signature is:
 //   * `i32 (i8*, ...)`
-auto llvmI32Ty = LLVM::LLVMType::getInt32Ty(context);
-auto llvmI8PtrTy = LLVM::LLVMType::getInt8PtrTy(context);
-auto llvmFnType = LLVM::LLVMType::getFunctionTy(llvmI32Ty, llvmI8PtrTy,
-/*isVarArg=*/true);
+auto llvmI32Ty = LLVM::LLVMIntegerType::get(context, 32);
+auto llvmI8PtrTy =
+LLVM::LLVMPointerType::get(LLVM::LLVMIntegerType::get(context, 8));
+auto llvmFnType = LLVM::LLVMFunctionType::get(llvmI32Ty, llvmI8PtrTy,
+  /*isVarArg=*/true);
 
 // Insert the printf function into the body of the parent module.
 PatternRewriter::InsertionGuard insertGuard(rewriter);
@@ -133,8 +134,8 @@ class PrintOpLowering : public ConversionPattern {
 if (!(global = module.lookupSymbol(name))) {
   OpBuilder::InsertionGuard insertGuard(builder);
   builder.setInsertionPointToStart(module.getBody());
-  auto type = LLVM::LLVMType::getArrayTy(
-  LLVM::LLVMType::getInt8Ty(builder.getContext()), value.size());
+  auto type = LLVM::LLVMArrayType::get(
+  LLVM::LLVMIntegerType::get(builder.getContext(), 8), value.size());
   global = builder.create(loc, type, /*isConstant=*/true,
   LLVM::Linkage::Internal, name,
   builder.getStringAttr(value));
@@ -143,11 +144,13 @@ class PrintOpLowering : public ConversionPattern {
 // Get the pointer to the first character in the global string.
 Value globalPtr = builder.create(loc, global);
 Value cst0 = builder.create(
-loc, LLVM::LLVMType::getInt64Ty(builder.getContext()),
+loc, LLVM::LLVMIntegerType::get(builder.getContext(), 64),
 builder.getIntegerAttr(builder.getIndexType(), 0));
 return builder.create(
-loc, LLVM::LLVMType::getInt8PtrTy(builder.getContext()), globalPtr,
-ArrayRef({cst0, cst0}));
+loc,
+LLVM::LLVMPointerType::get(
+LLVM::LLVMIntegerType::get(builder.getContext(), 8)),
+globalPtr, ArrayRef({cst0, cst0}));
   }
 };
 } // end anonymous namespace

diff  --git 

[llvm-branch-commits] [mlir] 1ec6086 - [mlir] Avoid cloning ops in SCF parallel conversion to CFG

2020-11-23 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2020-11-23T14:01:22+01:00
New Revision: 1ec60862d7024118b2db5bcbb280eafcd9193ac5

URL: 
https://github.com/llvm/llvm-project/commit/1ec60862d7024118b2db5bcbb280eafcd9193ac5
DIFF: 
https://github.com/llvm/llvm-project/commit/1ec60862d7024118b2db5bcbb280eafcd9193ac5.diff

LOG: [mlir] Avoid cloning ops in SCF parallel conversion to CFG

The existing implementation of the conversion from SCF Parallel operation to
SCF "for" loops in order to further convert those loops to branch-based CFG has
been cloning the loop and reduction body operations into the new loop because
ConversionPatternRewriter was missing support for moving blocks while replacing
their arguments. This functionality now available, use it to implement the
conversion and avoid cloning operations, which may lead to doubling of the IR
size during the conversion.

In addition, this fixes an issue with converting nested SCF "if" conditionals
present in "parallel" operations that would cause the conversion infrastructure
to stop because of the repeated application of the pattern converting "newly"
created "if"s (which were in fact just moved). Arguably, this should be fixed
at the infrastructure level and this fix is a workaround.

Reviewed By: herhut

Differential Revision: https://reviews.llvm.org/D91955

Added: 


Modified: 
mlir/lib/Conversion/SCFToStandard/SCFToStandard.cpp
mlir/test/Conversion/SCFToStandard/convert-to-cfg.mlir

Removed: 




diff  --git a/mlir/lib/Conversion/SCFToStandard/SCFToStandard.cpp 
b/mlir/lib/Conversion/SCFToStandard/SCFToStandard.cpp
index 56f6bf2f05fc..b8f3140dee73 100644
--- a/mlir/lib/Conversion/SCFToStandard/SCFToStandard.cpp
+++ b/mlir/lib/Conversion/SCFToStandard/SCFToStandard.cpp
@@ -404,7 +404,6 @@ LogicalResult
 ParallelLowering::matchAndRewrite(ParallelOp parallelOp,
   PatternRewriter &rewriter) const {
   Location loc = parallelOp.getLoc();
-  BlockAndValueMapping mapping;
 
   // For a parallel loop, we essentially need to create an n-dimensional loop
   // nest. We do this by translating to scf.for ops and have those lowered in
@@ -412,6 +411,8 @@ ParallelLowering::matchAndRewrite(ParallelOp parallelOp,
   // values), forward the initial values for the reductions down the loop
   // hierarchy and bubble up the results by modifying the "yield" terminator.
   SmallVector iterArgs = llvm::to_vector<4>(parallelOp.initVals());
+  SmallVector ivs;
+  ivs.reserve(parallelOp.getNumLoops());
   bool first = true;
   SmallVector loopResults(iterArgs);
   for (auto loop_operands :
@@ -420,7 +421,7 @@ ParallelLowering::matchAndRewrite(ParallelOp parallelOp,
 Value iv, lower, upper, step;
 std::tie(iv, lower, upper, step) = loop_operands;
 ForOp forOp = rewriter.create(loc, lower, upper, step, iterArgs);
-mapping.map(iv, forOp.getInductionVar());
+ivs.push_back(forOp.getInductionVar());
 auto iterRange = forOp.getRegionIterArgs();
 iterArgs.assign(iterRange.begin(), iterRange.end());
 
@@ -439,33 +440,33 @@ ParallelLowering::matchAndRewrite(ParallelOp parallelOp,
 rewriter.setInsertionPointToStart(forOp.getBody());
   }
 
-  // Now copy over the contents of the body.
+  // First, merge reduction blocks into the main region.
   SmallVector yieldOperands;
   yieldOperands.reserve(parallelOp.getNumResults());
-  for (auto &op : parallelOp.getBody()->without_terminator()) {
-// Reduction blocks are handled 
diff erently.
+  for (auto &op : *parallelOp.getBody()) {
 auto reduce = dyn_cast(op);
-if (!reduce) {
-  rewriter.clone(op, mapping);
+if (!reduce)
   continue;
-}
 
-// Clone the body of the reduction operation into the body of the loop,
-// using operands of "scf.reduce" and iteration arguments corresponding
-// to the reduction value to replace arguments of the reduction block.
-// Collect operands of "scf.reduce.return" to be returned by a final
-// "scf.yield" instead.
-Value arg = iterArgs[yieldOperands.size()];
 Block &reduceBlock = reduce.reductionOperator().front();
-mapping.map(reduceBlock.getArgument(0), mapping.lookupOrDefault(arg));
-mapping.map(reduceBlock.getArgument(1),
-mapping.lookupOrDefault(reduce.operand()));
-for (auto &nested : reduceBlock.without_terminator())
-  rewriter.clone(nested, mapping);
-yieldOperands.push_back(
-mapping.lookup(reduceBlock.getTerminator()->getOperand(0)));
+Value arg = iterArgs[yieldOperands.size()];
+yieldOperands.push_back(reduceBlock.getTerminator()->getOperand(0));
+rewriter.eraseOp(reduceBlock.getTerminator());
+rewriter.mergeBlockBefore(&reduceBlock, &op, {arg, reduce.operand()});
+rewriter.eraseOp(reduce);
   }
 
+  // Then merge the loop body without the terminator.
+  rewriter.eraseOp(parallelOp.getBody()->getTerminator());
+  Block *newBody = rewriter.getIn

[llvm-branch-commits] [mlir] 31a233d - [mlir] canonicalize away zero-iteration SCF for loops

2020-11-23 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2020-11-23T15:04:31+01:00
New Revision: 31a233d46367636f94c487b51aa2931a1cc9cf79

URL: 
https://github.com/llvm/llvm-project/commit/31a233d46367636f94c487b51aa2931a1cc9cf79
DIFF: 
https://github.com/llvm/llvm-project/commit/31a233d46367636f94c487b51aa2931a1cc9cf79.diff

LOG: [mlir] canonicalize away zero-iteration SCF for loops

An SCF 'for' loop does not iterate if its lower bound is equal to its upper
bound. Remove loops where both bounds are the same SSA value as such bounds are
guaranteed to be equal. Similarly, remove 'parallel' loops where at least one
pair of respective lower/upper bounds is specified by the same SSA value.

Reviewed By: gysit

Differential Revision: https://reviews.llvm.org/D91880

Added: 


Modified: 
mlir/lib/Dialect/SCF/SCF.cpp
mlir/test/Dialect/SCF/canonicalize.mlir

Removed: 




diff  --git a/mlir/lib/Dialect/SCF/SCF.cpp b/mlir/lib/Dialect/SCF/SCF.cpp
index 5da9f7c29cab..48b1b473f86d 100644
--- a/mlir/lib/Dialect/SCF/SCF.cpp
+++ b/mlir/lib/Dialect/SCF/SCF.cpp
@@ -521,6 +521,13 @@ struct SimplifyTrivialLoops : public 
OpRewritePattern {
 
   LogicalResult matchAndRewrite(ForOp op,
 PatternRewriter &rewriter) const override {
+// If the upper bound is the same as the lower bound, the loop does not
+// iterate, just remove it.
+if (op.lowerBound() == op.upperBound()) {
+  rewriter.replaceOp(op, op.getIterOperands());
+  return success();
+}
+
 auto lb = op.lowerBound().getDefiningOp();
 auto ub = op.upperBound().getDefiningOp();
 if (!lb || !ub)
@@ -1066,11 +1073,30 @@ struct CollapseSingleIterationLoops : public 
OpRewritePattern {
 return success();
   }
 };
+
+/// Removes parallel loops in which at least one lower/upper bound pair 
consists
+/// of the same values - such loops have an empty iteration domain.
+struct RemoveEmptyParallelLoops : public OpRewritePattern {
+  using OpRewritePattern::OpRewritePattern;
+
+  LogicalResult matchAndRewrite(ParallelOp op,
+PatternRewriter &rewriter) const override {
+for (auto dim : llvm::zip(op.lowerBound(), op.upperBound())) {
+  if (std::get<0>(dim) == std::get<1>(dim)) {
+rewriter.replaceOp(op, op.initVals());
+return success();
+  }
+}
+return failure();
+  }
+};
+
 } // namespace
 
 void ParallelOp::getCanonicalizationPatterns(OwningRewritePatternList &results,
  MLIRContext *context) {
-  results.insert(context);
+  results.insert(
+  context);
 }
 
 
//===--===//

diff  --git a/mlir/test/Dialect/SCF/canonicalize.mlir 
b/mlir/test/Dialect/SCF/canonicalize.mlir
index faac86b94cdb..d57563461241 100644
--- a/mlir/test/Dialect/SCF/canonicalize.mlir
+++ b/mlir/test/Dialect/SCF/canonicalize.mlir
@@ -32,30 +32,6 @@ func @single_iteration(%A: memref) {
 
 // -
 
-func @no_iteration(%A: memref) {
-  %c0 = constant 0 : index
-  %c1 = constant 1 : index
-  scf.parallel (%i0, %i1) = (%c0, %c0) to (%c1, %c0) step (%c1, %c1) {
-%c42 = constant 42 : i32
-store %c42, %A[%i0, %i1] : memref
-scf.yield
-  }
-  return
-}
-
-// CHECK-LABEL:   func @no_iteration(
-// CHECK-SAME:[[ARG0:%.*]]: memref) {
-// CHECK:   [[C0:%.*]] = constant 0 : index
-// CHECK:   [[C1:%.*]] = constant 1 : index
-// CHECK:   [[C42:%.*]] = constant 42 : i32
-// CHECK:   scf.parallel ([[V1:%.*]]) = ([[C0]]) to ([[C0]]) step 
([[C1]]) {
-// CHECK: store [[C42]], [[ARG0]]{{\[}}[[C0]], [[V1]]] : 
memref
-// CHECK: scf.yield
-// CHECK:   }
-// CHECK:   return
-
-// -
-
 func @one_unused(%cond: i1) -> (index) {
   %c0 = constant 0 : index
   %c1 = constant 1 : index
@@ -241,6 +217,22 @@ func @remove_zero_iteration_loop() {
   return
 }
 
+// CHECK-LABEL: @remove_zero_iteration_loop_vals
+func @remove_zero_iteration_loop_vals(%arg0: index) {
+  %c2 = constant 2 : index
+  // CHECK: %[[INIT:.*]] = "test.init"
+  %init = "test.init"() : () -> i32
+  // CHECK-NOT: scf.for
+  // CHECK-NOT: test.op
+  %0 = scf.for %i = %arg0 to %arg0 step %c2 iter_args(%arg = %init) -> (i32) {
+%1 = "test.op"(%i, %arg) : (index, i32) -> i32
+scf.yield %1 : i32
+  }
+  // CHECK: "test.consume"(%[[INIT]])
+  "test.consume"(%0) : (i32) -> ()
+  return
+}
+
 // CHECK-LABEL: @replace_single_iteration_loop
 func @replace_single_iteration_loop() {
   // CHECK: %[[LB:.*]] = constant 42
@@ -278,3 +270,24 @@ func @replace_single_iteration_loop_non_unit_step() {
   "test.consume"(%0) : (i32) -> ()
   return
 }
+
+// CHECK-LABEL: @remove_empty_parallel_loop
+func @remove_empty_parallel_loop(%lb: index, %ub: index, %s: index) {
+  // CHECK: %[[INIT:.*]] = "test.init"
+  %init = "test.init"() : () -> f32
+  // CHECK-NOT: s

[llvm-branch-commits] [mlir] f7d033f - [mlir] Support WsLoopOp in OpenMP to LLVM dialect conversion

2020-11-23 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2020-11-23T23:28:02+01:00
New Revision: f7d033f4d80f476246a70f165e7455639818f907

URL: 
https://github.com/llvm/llvm-project/commit/f7d033f4d80f476246a70f165e7455639818f907
DIFF: 
https://github.com/llvm/llvm-project/commit/f7d033f4d80f476246a70f165e7455639818f907.diff

LOG: [mlir] Support WsLoopOp in OpenMP to LLVM dialect conversion

It is a simple conversion that only requires to change the region argument
types, generalize it from ParallelOp.

Reviewed By: kiranchandramohan

Differential Revision: https://reviews.llvm.org/D91989

Added: 


Modified: 
mlir/lib/Conversion/OpenMPToLLVM/OpenMPToLLVM.cpp
mlir/test/Conversion/OpenMPToLLVM/convert-to-llvmir.mlir

Removed: 




diff  --git a/mlir/lib/Conversion/OpenMPToLLVM/OpenMPToLLVM.cpp 
b/mlir/lib/Conversion/OpenMPToLLVM/OpenMPToLLVM.cpp
index cfb553da407c..91e97ca1ec50 100644
--- a/mlir/lib/Conversion/OpenMPToLLVM/OpenMPToLLVM.cpp
+++ b/mlir/lib/Conversion/OpenMPToLLVM/OpenMPToLLVM.cpp
@@ -16,18 +16,23 @@
 using namespace mlir;
 
 namespace {
-struct ParallelOpConversion : public ConvertToLLVMPattern {
-  explicit ParallelOpConversion(MLIRContext *context,
-LLVMTypeConverter &typeConverter)
-  : ConvertToLLVMPattern(omp::ParallelOp::getOperationName(), context,
+/// A pattern that converts the region arguments in a single-region OpenMP
+/// operation to the LLVM dialect. The body of the region is not modified and 
is
+/// expected to either be processed by the conversion infrastructure or already
+/// contain ops compatible with LLVM dialect types.
+template 
+struct RegionOpConversion : public ConvertToLLVMPattern {
+  explicit RegionOpConversion(MLIRContext *context,
+  LLVMTypeConverter &typeConverter)
+  : ConvertToLLVMPattern(OpType::getOperationName(), context,
  typeConverter) {}
 
   LogicalResult
   matchAndRewrite(Operation *op, ArrayRef operands,
   ConversionPatternRewriter &rewriter) const override {
-auto curOp = cast(op);
-auto newOp = rewriter.create(curOp.getLoc(), TypeRange(),
-  operands, curOp.getAttrs());
+auto curOp = cast(op);
+auto newOp = rewriter.create(curOp.getLoc(), TypeRange(), operands,
+ curOp.getAttrs());
 rewriter.inlineRegionBefore(curOp.region(), newOp.region(),
 newOp.region().end());
 if (failed(rewriter.convertRegionTypes(&newOp.region(), typeConverter)))
@@ -42,7 +47,8 @@ struct ParallelOpConversion : public ConvertToLLVMPattern {
 void mlir::populateOpenMPToLLVMConversionPatterns(
 MLIRContext *context, LLVMTypeConverter &converter,
 OwningRewritePatternList &patterns) {
-  patterns.insert(context, converter);
+  patterns.insert,
+  RegionOpConversion>(context, converter);
 }
 
 namespace {
@@ -63,8 +69,8 @@ void ConvertOpenMPToLLVMPass::runOnOperation() {
   populateOpenMPToLLVMConversionPatterns(context, converter, patterns);
 
   LLVMConversionTarget target(getContext());
-  target.addDynamicallyLegalOp(
-  [&](omp::ParallelOp op) { return converter.isLegal(&op.getRegion()); });
+  target.addDynamicallyLegalOp(
+  [&](Operation *op) { return converter.isLegal(&op->getRegion(0)); });
   target.addLegalOp();
   if (failed(applyPartialConversion(module, target, std::move(patterns

diff  --git a/mlir/test/Conversion/OpenMPToLLVM/convert-to-llvmir.mlir 
b/mlir/test/Conversion/OpenMPToLLVM/convert-to-llvmir.mlir
index d38a6ea7e3a9..62ea39f078b2 100644
--- a/mlir/test/Conversion/OpenMPToLLVM/convert-to-llvmir.mlir
+++ b/mlir/test/Conversion/OpenMPToLLVM/convert-to-llvmir.mlir
@@ -28,3 +28,22 @@ func @branch_loop() {
   }
   return
 }
+
+// CHECK-LABEL: @wsloop
+// CHECK: (%[[ARG0:.*]]: !llvm.i64, %[[ARG1:.*]]: !llvm.i64, %[[ARG2:.*]]: 
!llvm.i64, %[[ARG3:.*]]: !llvm.i64, %[[ARG4:.*]]: !llvm.i64, %[[ARG5:.*]]: 
!llvm.i64)
+func @wsloop(%arg0: index, %arg1: index, %arg2: index, %arg3: index, %arg4: 
index, %arg5: index) {
+  // CHECK: omp.parallel
+  omp.parallel {
+// CHECK: omp.wsloop
+// CHECK: (%[[ARG0]], %[[ARG1]], %[[ARG2]], %[[ARG3]], %[[ARG4]], 
%[[ARG5]])
+"omp.wsloop"(%arg0, %arg1, %arg2, %arg3, %arg4, %arg5) ( {
+// CHECK: ^{{.*}}(%[[ARG6:.*]]: !llvm.i64, %[[ARG7:.*]]: !llvm.i64):
+^bb0(%arg6: index, %arg7: index):  // no predecessors
+  // CHECK: "test.payload"(%[[ARG6]], %[[ARG7]]) : (!llvm.i64, !llvm.i64) 
-> ()
+  "test.payload"(%arg6, %arg7) : (index, index) -> ()
+  omp.yield
+}) {operand_segment_sizes = dense<[2, 2, 2, 0, 0, 0, 0, 0, 0]> : 
vector<9xi32>} : (index, index, index, index, index, index) -> ()
+omp.terminator
+  }
+  return
+}



___
llvm-branch-commits mailing list
llvm-branch-commits@lists.

[llvm-branch-commits] [mlir] 63d3198 - [mlir] Fix typos and broken links in LangRef

2020-11-27 Thread Alex Zinenko via llvm-branch-commits

Author: Felipe de Azevedo Piovezan
Date: 2020-11-27T14:07:32+01:00
New Revision: 63d3198cedbca8cf51ce2c73e6c2192cc819d079

URL: 
https://github.com/llvm/llvm-project/commit/63d3198cedbca8cf51ce2c73e6c2192cc819d079
DIFF: 
https://github.com/llvm/llvm-project/commit/63d3198cedbca8cf51ce2c73e6c2192cc819d079.diff

LOG: [mlir] Fix typos and broken links in LangRef

Many pages have had their titles renamed over time,
causing broken links to spread throughout the documentation.

Reviewed By: ftynse

Differential Revision: https://reviews.llvm.org/D92093

Added: 


Modified: 
mlir/docs/LangRef.md
mlir/docs/Rationale/Rationale.md

Removed: 




diff  --git a/mlir/docs/LangRef.md b/mlir/docs/LangRef.md
index 9cd3e657b4d3..82272d1b729f 100644
--- a/mlir/docs/LangRef.md
+++ b/mlir/docs/LangRef.md
@@ -34,7 +34,7 @@ system](#type-system).  [Operations](#operations) are 
contained in
 [Blocks](#blocks) and Blocks are contained in [Regions](#regions). Operations
 are also ordered within their containing block and Blocks are ordered in their
 containing region, although this order may or may not be semantically
-meaningful in a given [kind of region](Interfaces.md#regionkindinterface)).
+meaningful in a given [kind of region](Interfaces.md#regionkindinterfaces)).
 Operations may also contain regions, enabling hierarchical structures to be
 represented.
 
@@ -55,8 +55,8 @@ allowing operation semantics to be described abstractly using
 [Traits](Traits.md) and [Interfaces](Interfaces.md), enabling transformations
 to operate on operations more generically.  Traits often describe verification
 constraints on valid IR, enabling complex invariants to be captured and
-checked. (see
-[docs/Tutorials/Toy/Ch-2/#op-vs-operation-using-mlir-operations])
+checked. (see [Op vs
+Operation](docs/Tutorials/Toy/Ch-2/#op-vs-operation-using-mlir-operations))
 
 One obvious application of MLIR is to represent an
 [SSA-based](https://en.wikipedia.org/wiki/Static_single_assignment_form) IR,
@@ -438,7 +438,7 @@ block-arg-list ::= `(` value-id-and-type-list? `)`
 A *Block* is an ordered list of operations, concluding with a single
 [terminator operation](#terminator-operations). In [SSACFG
 regions](#control-flow-and-ssacfg-regions), each block represents a compiler
-[basic block] (https://en.wikipedia.org/wiki/Basic_block) where instructions
+[basic block](https://en.wikipedia.org/wiki/Basic_block) where instructions
 inside the block are executed in order and terminator operations implement
 control flow branches between basic blocks.
 
@@ -505,7 +505,7 @@ regions: [SSACFG 
regions](#control-flow-and-ssacfg-regions), which describe
 control flow between blocks, and [Graph regions](#graph-regions), which do not
 require control flow between block. The kinds of regions within an operation
 are described using the
-[RegionKindInterface](Interfaces.md#regionkindinterface).
+[RegionKindInterface](Interfaces.md#regionkindinterfaces).
 
 Regions do not have a name or an address, only the blocks contained in a
 region do. Regions must be contained within operations and have no type or
@@ -561,7 +561,7 @@ defined in a region can never be used outside of the region.
 ### Control Flow and SSACFG Regions
 
 In MLIR, control flow semantics of a region is indicated by
-[RegionKind::SSACFG](Interfaces.md#regionkindinterface).  Informally, these
+[RegionKind::SSACFG](Interfaces.md#regionkindinterfaces).  Informally, these
 regions support semantics where operations in a region 'execute
 sequentially'. Before an operation executes, its operands have well-defined
 values. After an operation executes, the operands have the same values and
@@ -647,7 +647,7 @@ directly used values remain live.
 ### Graph Regions
 
 In MLIR, graph-like semantics in a region is indicated by
-[RegionKind::Graph](Interfaces.md#regionkindinterface). Graph regions are
+[RegionKind::Graph](Interfaces.md#regionkindinterfaces). Graph regions are
 appropriate for concurrent semantics without control flow, or for modeling
 generic directed graph data structures. Graph regions are appropriate for
 representing cyclic relationships between coupled values where there is no
@@ -869,7 +869,7 @@ function-type ::= type-list-parens `->` function-result-type
 ```
 
 MLIR supports first-class functions: for example, the
-[`constant` operation](Dialects/Standard.md#constant-operation) produces the
+[`constant` operation](Dialects/Standard.md#stdconstant-constantop) produces 
the
 address of a function as a value. This value may be passed to and
 returned from functions, merged across control flow boundaries with
 [block arguments](#blocks), and called with the
@@ -888,10 +888,11 @@ index-type ::= `index`
 ```
 
 The `index` type is a signless integer whose size is equal to the natural
-machine word of the target 
([rationale](Rationale/Rationale.md#signless-types)) and is
-used by the affine constructs in MLIR

[llvm-branch-commits] [mlir] 240dd92 - [OpenMPIRBuilder] forward arguments as pointers to outlined function

2020-12-02 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2020-12-02T14:59:41+01:00
New Revision: 240dd92432ebbfbf24ef85779f2cdf93e6ddf605

URL: 
https://github.com/llvm/llvm-project/commit/240dd92432ebbfbf24ef85779f2cdf93e6ddf605
DIFF: 
https://github.com/llvm/llvm-project/commit/240dd92432ebbfbf24ef85779f2cdf93e6ddf605.diff

LOG: [OpenMPIRBuilder] forward arguments as pointers to outlined function

OpenMPIRBuilder::createParallel outlines the body region of the parallel
construct into a new function that accepts any value previously defined outside
the region as a function argument. This function is called back by OpenMP
runtime function __kmpc_fork_call, which expects trailing arguments to be
pointers. If the region uses a value that is not of a pointer type, e.g. a
struct, the produced code would be invalid. In such cases, make createParallel
emit IR that stores the value on stack and pass the pointer to the outlined
function instead. The outlined function then loads the value back and uses as
normal.

Reviewed By: jdoerfert, llitchev

Differential Revision: https://reviews.llvm.org/D92189

Added: 


Modified: 
clang/lib/CodeGen/CGStmtOpenMP.cpp
clang/test/OpenMP/parallel_codegen.cpp
llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
llvm/lib/Transforms/IPO/OpenMPOpt.cpp
llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
mlir/lib/Target/LLVMIR/ModuleTranslation.cpp

Removed: 




diff  --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp 
b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index 2fb4144930df..5e8d98cfe5ef 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -1693,7 +1693,7 @@ void CodeGenFunction::EmitOMPParallelDirective(const 
OMPParallelDirective &S) {
 //
 // TODO: This defaults to shared right now.
 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
- llvm::Value &Val, llvm::Value *&ReplVal) {
+ llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
   // The next line is appropriate only for variables (Val) with the
   // data-sharing attribute "shared".
   ReplVal = &Val;

diff  --git a/clang/test/OpenMP/parallel_codegen.cpp 
b/clang/test/OpenMP/parallel_codegen.cpp
index bceab0637f6a..83561ce6f6a8 100644
--- a/clang/test/OpenMP/parallel_codegen.cpp
+++ b/clang/test/OpenMP/parallel_codegen.cpp
@@ -133,22 +133,26 @@ int main (int argc, char **argv) {
 // CHECK-DEBUG-DAG:   define internal void [[OMP_OUTLINED]](i32* noalias 
%.global_tid., i32* noalias %.bound_tid., i64 [[VLA_SIZE:%.+]], i32* {{.+}} 
[[VLA_ADDR:%[^)]+]])
 // CHECK-DEBUG-DAG:   call void [[OMP_OUTLINED_DEBUG]]
 
+// Note that OpenMPIRBuilder puts the trailing arguments in a 
diff erent order:
+// arguments that are wrapped into additional pointers precede the other
+// arguments. This is expected and not problematic because both the call and 
the
+// function are generated from the same place, and the function is internal.
 // ALL:   define linkonce_odr {{[a-z\_\b]*[ ]?i32}} [[TMAIN]](i8** %argc)
 // ALL:   store i8** %argc, i8*** [[ARGC_ADDR:%.+]],
 // CHECK:   call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, 
...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC_2]], i32 2, void 
(i32*, i32*, ...)* bitcast (void (i32*, i32*, i8***, i{{64|32}})* 
[[OMP_OUTLINED:@.+]] to void (i32*, i32*, ...)*), i8*** [[ARGC_ADDR]], 
i{{64|32}} %{{.+}})
-// IRBUILDER:   call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, 
...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC_2]], i32 2, void 
(i32*, i32*, ...)* bitcast (void (i32*, i32*, i8***, i{{64|32}})* 
[[OMP_OUTLINED:@.+]] to void (i32*, i32*, ...)*), i8*** [[ARGC_ADDR]], 
i{{64|32}} %{{.+}})
+// IRBUILDER:   call {{.*}}void (%struct.ident_t*, i32, void (i32*, i32*, 
...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[DEF_LOC_2]], i32 2, void 
(i32*, i32*, ...)* bitcast (void (i32*, i32*, i{{64|32}}*, i8***)* 
[[OMP_OUTLINED:@.+]] to void (i32*, i32*, ...)*), i{{64|32}}* %{{.+}}, i8*** 
[[ARGC_ADDR]])
 // ALL:  ret i32 0
 // ALL-NEXT:  }
 // ALL-DEBUG:   define linkonce_odr i32 [[TMAIN]](i8** %argc)
 
 // CHECK-DEBUG:   store i8** %argc, i8*** [[ARGC_ADDR:%.+]],
 // CHECK-DEBUG:   call void (%struct.ident_t*, i32, void (i32*, i32*, 
...)*, ...) @__kmpc_fork_call(%struct.ident_t* @{{.*}}, i32 2, void (i32*, 
i32*, ...)* bitcast (void (i32*, i32*, i8***, i64)* [[OMP_OUTLINED:@.+]] to 
void (i32*, i32*, ...)*), i8*** [[ARGC_ADDR]], i64 %{{.+}})
-// IRBUILDER-DEBUG:   call void (%struct.ident_t*, i32, void (i32*, i32*, 
...)*, ...) @__kmpc_fork_call(%struct.ident_t* @{{.*}}, i32 2, void (i32*, 
i32*, ...)* bitcast (void (i32*, i32*, i8***, i64)* [[OMP_OUTLINED:@.+]] to 
void (i32*, i32*, ...)*), i8*** [[ARGC_ADDR]], i64 %{{.+}})
+// IRBUILDER-DEBUG:   call void (%struct.ident_t*, i32, void (i32*, i32*, 
...)*, ...)

[llvm-branch-commits] [llvm] c102c78 - [OpenMPIRBuilder] introduce createStaticWorkshareLoop

2020-12-07 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2020-12-07T22:30:59+01:00
New Revision: c102c783cd08cb1bf9119fe33cce34f6d1563881

URL: 
https://github.com/llvm/llvm-project/commit/c102c783cd08cb1bf9119fe33cce34f6d1563881
DIFF: 
https://github.com/llvm/llvm-project/commit/c102c783cd08cb1bf9119fe33cce34f6d1563881.diff

LOG: [OpenMPIRBuilder] introduce createStaticWorkshareLoop

Introduce a function that creates a statically-scheduled workshare loop
out of a canonical loop created earlier by the OpenMPIRBuilder. This
basically amounts to injecting runtime calls to the preheader and the
after block and updating the trip count. Static scheduling kind is
currently hardcoded and needs to be extracted from the runtime library
into common TableGen definitions.

Differential Revision: https://reviews.llvm.org/D92476

Added: 


Modified: 
llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp

Removed: 




diff  --git a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h 
b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
index a09605bb1023..2e4bb20c7998 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
+++ b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
@@ -260,6 +260,32 @@ class OpenMPIRBuilder {
  Value *Start, Value *Stop, Value 
*Step,
  bool IsSigned, bool InclusiveStop);
 
+  /// Modifies the canonical loop to be a statically-scheduled workshare loop.
+  ///
+  /// This takes a \p LoopInfo representing a canonical loop, such as the one
+  /// created by \p createCanonicalLoop and emits additional instructions to
+  /// turn it into a workshare loop. In particular, it calls to an OpenMP
+  /// runtime function in the preheader to obtain the loop bounds to be used in
+  /// the current thread, updates the relevant instructions in the canonical
+  /// loop and calls to an OpenMP runtime finalization function after the loop.
+  ///
+  /// \param Loc  The source location description, the insertion location
+  /// is not used.
+  /// \param CLI  A descriptor of the canonical loop to workshare.
+  /// \param AllocaIP An insertion point for Alloca instructions usable in the
+  /// preheader of the loop.
+  /// \param NeedsBarrier Indicates whether a barrier must be insterted after
+  /// the loop.
+  /// \param ChunkThe size of loop chunk considered as a unit when
+  /// scheduling. If \p nullptr, defaults to 1.
+  ///
+  /// \returns Updated CanonicalLoopInfo.
+  CanonicalLoopInfo *createStaticWorkshareLoop(const LocationDescription &Loc,
+   CanonicalLoopInfo *CLI,
+   InsertPointTy AllocaIP,
+   bool NeedsBarrier,
+   Value *Chunk = nullptr);
+
   /// Generator for '#omp flush'
   ///
   /// \param Loc The location where the flush directive was encountered
@@ -636,7 +662,9 @@ class OpenMPIRBuilder {
 ///  |Cond---\
 ///  | | |
 ///  |Body   |
-///  | | |
+///  || ||
+///  |   <...>   |
+///  || ||
 ///   \--Latch   |
 ///  |
 /// Exit
@@ -644,7 +672,9 @@ class OpenMPIRBuilder {
 ///After
 ///
 /// Code in the header, condition block, latch and exit block must not have any
-/// side-effect.
+/// side-effect. The body block is the single entry point into the loop body,
+/// which may contain arbitrary control flow as long as all control paths
+/// eventually branch to the latch block.
 ///
 /// Defined outside OpenMPIRBuilder because one cannot forward-declare nested
 /// classes.
@@ -701,7 +731,7 @@ class CanonicalLoopInfo {
   /// statements/cancellations).
   BasicBlock *getAfter() const { return After; }
 
-  /// Returns the llvm::Value containing the number of loop iterations. I must
+  /// Returns the llvm::Value containing the number of loop iterations. It must
   /// be valid in the preheader and always interpreted as an unsigned integer 
of
   /// any bit-width.
   Value *getTripCount() const {

diff  --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp 
b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
index 044e69da8665..6587a3637c90 100644
--- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -999,6 +999,118 @@ CanonicalLoopInfo *OpenMPIRBuilder::createCanonicalLoop(
   return createCanonicalLoop(Builder.saveIP(), BodyGen, TripCount);
 }
 
+// Returns an LLVM function to call for initializing loop bounds using OpenMP
+// static scheduling depending on `type`. Only i32 and i64 are supported by the
+// runtime. Always interpret integers as unsigned similarly to
+// CanonicalLoopInfo.
+static Fu

[llvm-branch-commits] [mlir] 2fe30a3 - [mlir] properly support min/max in affine parallelization

2020-12-08 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2020-12-08T10:43:35+01:00
New Revision: 2fe30a3534dad9f982a3d840b4bfa4870b2ba5bc

URL: 
https://github.com/llvm/llvm-project/commit/2fe30a3534dad9f982a3d840b4bfa4870b2ba5bc
DIFF: 
https://github.com/llvm/llvm-project/commit/2fe30a3534dad9f982a3d840b4bfa4870b2ba5bc.diff

LOG: [mlir] properly support min/max in affine parallelization

The existing implementation of the affine parallelization silently copies over
the lower and upper bound maps from affine.for to affine.parallel. However, the
semantics of these maps differ between these two ops: in affine.for, a max(min)
of results is taken for the lower(upper) bound; in affine.parallel, multiple
induction variables can be defined an each result corresponds to one induction
variable. Thus the existing implementation could generate invalid IR or IR that
passes the verifier but has different semantics than the original code. Fix the
parallelization utility to emit dedicated min/max operations before the
affine.parallel in such cases. Disallow parallelization if min/max would have
been in an operation without the AffineScope trait, e.g., in another loop,
since the result of these operations is not considered a valid affine dimension
identifier and may not be properly handled by the affine analyses.

Reviewed By: wsmoses

Differential Revision: https://reviews.llvm.org/D92763

Added: 


Modified: 
mlir/lib/Dialect/Affine/Utils/Utils.cpp
mlir/test/Dialect/Affine/parallelize.mlir

Removed: 




diff  --git a/mlir/lib/Dialect/Affine/Utils/Utils.cpp 
b/mlir/lib/Dialect/Affine/Utils/Utils.cpp
index 7892dfbc7a48..e5f5a6d8998f 100644
--- a/mlir/lib/Dialect/Affine/Utils/Utils.cpp
+++ b/mlir/lib/Dialect/Affine/Utils/Utils.cpp
@@ -134,11 +134,43 @@ static AffineIfOp hoistAffineIfOp(AffineIfOp ifOp, 
Operation *hoistOverOp) {
 void mlir::affineParallelize(AffineForOp forOp) {
   Location loc = forOp.getLoc();
   OpBuilder outsideBuilder(forOp);
+
+  // If a loop has a 'max' in the lower bound, emit it outside the parallel 
loop
+  // as it does not have implicit 'max' behavior.
+  AffineMap lowerBoundMap = forOp.getLowerBoundMap();
+  ValueRange lowerBoundOperands = forOp.getLowerBoundOperands();
+  AffineMap upperBoundMap = forOp.getUpperBoundMap();
+  ValueRange upperBoundOperands = forOp.getUpperBoundOperands();
+
+  bool needsMax = lowerBoundMap.getNumResults() > 1;
+  bool needsMin = upperBoundMap.getNumResults() > 1;
+  AffineMap identityMap;
+  if (needsMax || needsMin) {
+if (forOp->getParentOp() &&
+!forOp->getParentOp()->hasTrait())
+  return;
+
+identityMap = AffineMap::getMultiDimIdentityMap(1, loc->getContext());
+  }
+  if (needsMax) {
+auto maxOp = outsideBuilder.create(loc, lowerBoundMap,
+lowerBoundOperands);
+lowerBoundMap = identityMap;
+lowerBoundOperands = maxOp->getResults();
+  }
+
+  // Same for the upper bound.
+  if (needsMin) {
+auto minOp = outsideBuilder.create(loc, upperBoundMap,
+upperBoundOperands);
+upperBoundMap = identityMap;
+upperBoundOperands = minOp->getResults();
+  }
+
   // Creating empty 1-D affine.parallel op.
   AffineParallelOp newPloop = outsideBuilder.create(
-  loc, llvm::None, llvm::None, forOp.getLowerBoundMap(),
-  forOp.getLowerBoundOperands(), forOp.getUpperBoundMap(),
-  forOp.getUpperBoundOperands());
+  loc, llvm::None, llvm::None, lowerBoundMap, lowerBoundOperands,
+  upperBoundMap, upperBoundOperands);
   // Steal the body of the old affine for op and erase it.
   newPloop.region().takeBody(forOp.region());
   forOp.erase();

diff  --git a/mlir/test/Dialect/Affine/parallelize.mlir 
b/mlir/test/Dialect/Affine/parallelize.mlir
index 8e6cb05f46a0..cbc80a092e76 100644
--- a/mlir/test/Dialect/Affine/parallelize.mlir
+++ b/mlir/test/Dialect/Affine/parallelize.mlir
@@ -114,3 +114,33 @@ func @non_affine_load() {
   }
   return
 }
+
+// CHECK-LABEL: for_with_minmax
+func @for_with_minmax(%m: memref, %lb0: index, %lb1: index,
+  %ub0: index, %ub1: index) {
+  // CHECK: %[[lb:.*]] = affine.max
+  // CHECK: %[[ub:.*]] = affine.min
+  // CHECK: affine.parallel (%{{.*}}) = (%[[lb]]) to (%[[ub]])
+  affine.for %i = max affine_map<(d0, d1) -> (d0, d1)>(%lb0, %lb1)
+  to min affine_map<(d0, d1) -> (d0, d1)>(%ub0, %ub1) {
+affine.load %m[%i] : memref
+  }
+  return
+}
+
+// CHECK-LABEL: nested_for_with_minmax
+func @nested_for_with_minmax(%m: memref, %lb0: index,
+ %ub0: index, %ub1: index) {
+  // CHECK: affine.parallel
+  affine.for %j = 0 to 10 {
+// Cannot parallelize the inner loop because we would need to compute
+// affine.max for its lower bound inside the loop, and that is not (yet)
+// considered as a valid affine dimension.
+// CHECK: affine.for
+affine.for %

[llvm-branch-commits] [mlir] 80766ec - [mlir] Add an option to control the number of loops in affine parallelizer

2020-12-08 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2020-12-08T10:44:37+01:00
New Revision: 80766ecc65096deeb4ff6f03562dcad94c54b862

URL: 
https://github.com/llvm/llvm-project/commit/80766ecc65096deeb4ff6f03562dcad94c54b862
DIFF: 
https://github.com/llvm/llvm-project/commit/80766ecc65096deeb4ff6f03562dcad94c54b862.diff

LOG: [mlir] Add an option to control the number of loops in affine parallelizer

Add a pass option to control the number of nested parallel loops produced by
the parallelization passes. This is useful to build end-to-end passes targeting
systems that don't need multiple parallel dimensions (e.g., CPUs typically need
only one).

Reviewed By: wsmoses, chelini

Differential Revision: https://reviews.llvm.org/D92765

Added: 


Modified: 
mlir/include/mlir/Dialect/Affine/Passes.td
mlir/lib/Dialect/Affine/Transforms/AffineParallelize.cpp
mlir/test/Dialect/Affine/parallelize.mlir

Removed: 




diff  --git a/mlir/include/mlir/Dialect/Affine/Passes.td 
b/mlir/include/mlir/Dialect/Affine/Passes.td
index ace272692d66..9f2aac7b685a 100644
--- a/mlir/include/mlir/Dialect/Affine/Passes.td
+++ b/mlir/include/mlir/Dialect/Affine/Passes.td
@@ -118,6 +118,11 @@ def AffineVectorize : 
FunctionPass<"affine-super-vectorize"> {
 def AffineParallelize : FunctionPass<"affine-parallelize"> {
   let summary = "Convert affine.for ops into 1-D affine.parallel";
   let constructor = "mlir::createAffineParallelizePass()";
+  let options = [
+Option<"maxNested", "max-nested", "unsigned", /*default=*/"-1u",
+   "Maximum number of nested parallel loops to produce. "
+   "Defaults to unlimited (UINT_MAX).">,
+  ];
 }
 
 def AffineLoopNormalize : FunctionPass<"affine-loop-normalize"> {

diff  --git a/mlir/lib/Dialect/Affine/Transforms/AffineParallelize.cpp 
b/mlir/lib/Dialect/Affine/Transforms/AffineParallelize.cpp
index b3651e202245..d8511be326dd 100644
--- a/mlir/lib/Dialect/Affine/Transforms/AffineParallelize.cpp
+++ b/mlir/lib/Dialect/Affine/Transforms/AffineParallelize.cpp
@@ -36,13 +36,28 @@ struct AffineParallelize : public 
AffineParallelizeBase {
 
 void AffineParallelize::runOnFunction() {
   FuncOp f = getFunction();
-  SmallVector parallelizableLoops;
+
+  // The walker proceeds in post-order, but we need to process outer loops 
first
+  // to control the number of outer parallel loops, so push candidate loops to
+  // the front of a deque.
+  std::deque parallelizableLoops;
   f.walk([&](AffineForOp loop) {
 if (isLoopParallel(loop))
-  parallelizableLoops.push_back(loop);
+  parallelizableLoops.push_front(loop);
   });
-  for (AffineForOp loop : parallelizableLoops)
-affineParallelize(loop);
+
+  for (AffineForOp loop : parallelizableLoops) {
+unsigned numParentParallelOps = 0;
+for (Operation *op = loop->getParentOp();
+ op != nullptr && !op->hasTrait();
+ op = op->getParentOp()) {
+  if (isa(op))
+++numParentParallelOps;
+}
+
+if (numParentParallelOps < maxNested)
+  affineParallelize(loop);
+  }
 }
 
 std::unique_ptr> mlir::createAffineParallelizePass() {

diff  --git a/mlir/test/Dialect/Affine/parallelize.mlir 
b/mlir/test/Dialect/Affine/parallelize.mlir
index cbc80a092e76..08aaa7f32fc8 100644
--- a/mlir/test/Dialect/Affine/parallelize.mlir
+++ b/mlir/test/Dialect/Affine/parallelize.mlir
@@ -1,4 +1,5 @@
 // RUN: mlir-opt %s -allow-unregistered-dialect -affine-parallelize| FileCheck 
%s
+// RUN: mlir-opt %s -allow-unregistered-dialect 
-affine-parallelize='max-nested=1' | FileCheck --check-prefix=MAX-NESTED %s
 
 // CHECK-LABEL:func @reduce_window_max() {
 func @reduce_window_max() {
@@ -144,3 +145,18 @@ func @nested_for_with_minmax(%m: memref, %lb0: 
index,
   }
   return
 }
+
+// MAX-NESTED-LABEL: @max_nested
+func @max_nested(%m: memref, %lb0: index, %lb1: index,
+ %ub0: index, %ub1: index) {
+  // MAX-NESTED: affine.parallel
+  affine.for %i = affine_map<(d0) -> (d0)>(%lb0) to affine_map<(d0) -> 
(d0)>(%ub0) {
+// MAX-NESTED: affine.for
+affine.for %j = affine_map<(d0) -> (d0)>(%lb1) to affine_map<(d0) -> 
(d0)>(%ub1) {
+  affine.load %m[%i, %j] : memref
+}
+  }
+  return
+}
+
+



___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] f31704f - [OpenMPIRBuilder] Put the barrier in the exit block in createWorkshapeLoop

2020-12-09 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2020-12-09T11:33:04+01:00
New Revision: f31704f8ae32a24147fac686f4e922c5c762cfe0

URL: 
https://github.com/llvm/llvm-project/commit/f31704f8ae32a24147fac686f4e922c5c762cfe0
DIFF: 
https://github.com/llvm/llvm-project/commit/f31704f8ae32a24147fac686f4e922c5c762cfe0.diff

LOG: [OpenMPIRBuilder] Put the barrier in the exit block in createWorkshapeLoop

The original code was inserting the barrier at the location given by the
caller. Make sure it is always inserted at the end of the loop exit block
instead.

Reviewed By: Meinersbur

Differential Revision: https://reviews.llvm.org/D92849

Added: 


Modified: 
llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp

Removed: 




diff  --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp 
b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
index 6587a3637c90..609184af6ce8 100644
--- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -1104,7 +1104,8 @@ CanonicalLoopInfo 
*OpenMPIRBuilder::createStaticWorkshareLoop(
 
   // Add the barrier if requested.
   if (NeedsBarrier)
-createBarrier(Loc, omp::Directive::OMPD_for, /* ForceSimpleCall */ false,
+createBarrier(LocationDescription(Builder.saveIP(), Loc.DL),
+  omp::Directive::OMPD_for, /* ForceSimpleCall */ false,
   /* CheckCancelFlag */ false);
 
   CLI->assertOK();

diff  --git a/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp 
b/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
index 1ad2264d3e39..6e69af725ccb 100644
--- a/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
+++ b/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
@@ -1155,6 +1155,13 @@ TEST_F(OpenMPIRBuilderTest, StaticWorkShareLoop) {
   // increment and in the statement that adds the lower bound to it.
   Value *IV = CLI->getIndVar();
   EXPECT_EQ(std::distance(IV->use_begin(), IV->use_end()), 3);
+
+  // The exit block should contain the "fini" call and the barrier call,
+  // plus the call to obtain the thread ID.
+  BasicBlock *ExitBlock = CLI->getExit();
+  size_t NumCallsInExitBlock =
+  count_if(*ExitBlock, [](Instruction &I) { return isa(I); });
+  EXPECT_EQ(NumCallsInExitBlock, 3u);
 }
 
 TEST_F(OpenMPIRBuilderTest, MasterDirective) {



___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] db884da - [mlir] Explicitly track branch instructions in translation to LLVM IR

2020-12-10 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2020-12-10T11:08:58+01:00
New Revision: db884dafb7b5771e6ae01e8252f1520fac3e1c77

URL: 
https://github.com/llvm/llvm-project/commit/db884dafb7b5771e6ae01e8252f1520fac3e1c77
DIFF: 
https://github.com/llvm/llvm-project/commit/db884dafb7b5771e6ae01e8252f1520fac3e1c77.diff

LOG: [mlir] Explicitly track branch instructions in translation to LLVM IR

The current implementation of the translation to LLVM IR relies on the
existence of a one-to-one mapping between MLIR blocks and LLVM IR basic blocks
in order to configure PHI nodes with appropriate source blocks. The one-to-one
mapping model is broken in presence of OpenMP operations that use LLVM's
OpenMPIRBuilder, which produces multiple blocks under the hood. This can lead
to invalid LLVM IR being emitted if OpenMPIRBuilder moved the branch operation
into a basic block different from the one it was originally created in;
specifically, a block that is not a direct predecessor could be used in the PHI
node. Instead, keep track of the mapping between MLIR LLVM dialect branch
operations and their LLVM IR counterparts and take the parent basic block of
the LLVM IR instruction at the moment of connecting the PHI nodes to
predecessors.

This behavior cannot be triggered as of now, but will be once we introduce the
conversion of OpenMP workshare loops.

Reviewed By: kiranchandramohan

Differential Revision: https://reviews.llvm.org/D92845

Added: 


Modified: 
mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
mlir/lib/Target/LLVMIR/ModuleTranslation.cpp

Removed: 




diff  --git a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h 
b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
index 996c8de06e37..d3d289414b38 100644
--- a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
+++ b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h
@@ -151,6 +151,11 @@ class ModuleTranslation {
   llvm::StringMap functionMapping;
   DenseMap valueMapping;
   DenseMap blockMapping;
+
+  /// A mapping between MLIR LLVM dialect terminators and LLVM IR terminators
+  /// they are converted to. This allows for conneting PHI nodes to the source
+  /// values after all operations are converted.
+  DenseMap branchMapping;
 };
 
 } // namespace LLVM

diff  --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp 
b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index c20b19f2d5ca..057f57409940 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -340,9 +340,10 @@ static Value getPHISourceValue(Block *current, Block *pred,
 
 /// Connect the PHI nodes to the results of preceding blocks.
 template 
-static void
-connectPHINodes(T &func, const DenseMap &valueMapping,
-const DenseMap &blockMapping) {
+static void connectPHINodes(
+T &func, const DenseMap &valueMapping,
+const DenseMap &blockMapping,
+const DenseMap &branchMapping) {
   // Skip the first block, it cannot be branched to and its arguments 
correspond
   // to the arguments of the LLVM function.
   for (auto it = std::next(func.begin()), eit = func.end(); it != eit; ++it) {
@@ -355,9 +356,17 @@ connectPHINodes(T &func, const DenseMap &valueMapping,
   auto &phiNode = numberedPhiNode.value();
   unsigned index = numberedPhiNode.index();
   for (auto *pred : bb->getPredecessors()) {
+// Find the LLVM IR block that contains the converted terminator
+// instruction and use it in the PHI node. Note that this block is not
+// necessarily the same as blockMapping.lookup(pred), some operations
+// (in particular, OpenMP operations using OpenMPIRBuilder) may have
+// split the blocks.
+llvm::Instruction *terminator =
+branchMapping.lookup(pred->getTerminator());
+assert(terminator && "missing the mapping for a terminator");
 phiNode.addIncoming(valueMapping.lookup(getPHISourceValue(
 bb, pred, numArguments, index)),
-blockMapping.lookup(pred));
+terminator->getParent());
   }
 }
   }
@@ -476,7 +485,7 @@ void ModuleTranslation::convertOmpOpRegions(
   }
   // Finally, after all blocks have been traversed and values mapped,
   // connect the PHI nodes to the results of preceding blocks.
-  connectPHINodes(region, valueMapping, blockMapping);
+  connectPHINodes(region, valueMapping, blockMapping, branchMapping);
 }
 
 LogicalResult ModuleTranslation::convertOmpMaster(Operation &opInst,
@@ -682,7 +691,9 @@ LogicalResult ModuleTranslation::convertOperation(Operation 
&opInst,
   // Emit branches.  We need to look up the remapped blocks and ignore the 
block
   // arguments that were transformed into PHI nodes.
   if (auto brOp = dyn_cast(opInst)) {
-builder.CreateBr(blockMapping[brOp.getSuccessor()]);
+llvm::BranchInst *branch =
+builder.Creat

[llvm-branch-commits] [mlir] dacfb24 - [mlir] Support inlining into affine operations

2020-12-11 Thread Alex Zinenko via llvm-branch-commits

Author: Alex Zinenko
Date: 2020-12-11T16:24:27+01:00
New Revision: dacfb24b301d2f0422f2c7a23e2919e2f35cd932

URL: 
https://github.com/llvm/llvm-project/commit/dacfb24b301d2f0422f2c7a23e2919e2f35cd932
DIFF: 
https://github.com/llvm/llvm-project/commit/dacfb24b301d2f0422f2c7a23e2919e2f35cd932.diff

LOG: [mlir] Support inlining into affine operations

Introduce support for inlining into affine operations. This uses the generic
inline infrastructure and boils down to checking that, if applied, the inlining
doesn't violate the affine dimension/symbol value categorization. Given valid
IR, only the values that are valid dimensions/symbols thanks to being top-level
in their affine scope need special handling.

Reviewed By: rriddle

Differential Revision: https://reviews.llvm.org/D92770

Added: 


Modified: 
mlir/lib/Dialect/Affine/IR/AffineOps.cpp
mlir/test/Dialect/Affine/inlining.mlir

Removed: 




diff  --git a/mlir/lib/Dialect/Affine/IR/AffineOps.cpp 
b/mlir/lib/Dialect/Affine/IR/AffineOps.cpp
index 005db18c54e5..d1d577799b39 100644
--- a/mlir/lib/Dialect/Affine/IR/AffineOps.cpp
+++ b/mlir/lib/Dialect/Affine/IR/AffineOps.cpp
@@ -9,6 +9,7 @@
 #include "mlir/Dialect/Affine/IR/AffineOps.h"
 #include "mlir/Dialect/Affine/IR/AffineValueMap.h"
 #include "mlir/Dialect/StandardOps/IR/Ops.h"
+#include "mlir/IR/BlockAndValueMapping.h"
 #include "mlir/IR/BuiltinOps.h"
 #include "mlir/IR/IntegerSet.h"
 #include "mlir/IR/Matchers.h"
@@ -25,6 +26,99 @@ using llvm::dbgs;
 
 #define DEBUG_TYPE "affine-analysis"
 
+/// A utility function to check if a value is defined at the top level of
+/// `region` or is an argument of `region`. A value of index type defined at 
the
+/// top level of a `AffineScope` region is always a valid symbol for all
+/// uses in that region.
+static bool isTopLevelValue(Value value, Region *region) {
+  if (auto arg = value.dyn_cast())
+return arg.getParentRegion() == region;
+  return value.getDefiningOp()->getParentRegion() == region;
+}
+
+/// Checks if `value` known to be a legal affine dimension or symbol in `src`
+/// region remains legal if the operation that uses it is inlined into `dest`
+/// with the given value mapping. `legalityCheck` is either `isValidDim` or
+/// `isValidSymbol`, depending on the value being required to remain a valid
+/// dimension or symbol.
+static bool
+remainsLegalAfterInline(Value value, Region *src, Region *dest,
+const BlockAndValueMapping &mapping,
+function_ref legalityCheck) {
+  // If the value is a valid dimension for any other reason than being
+  // a top-level value, it will remain valid: constants get inlined
+  // with the function, transitive affine applies also get inlined and
+  // will be checked themselves, etc.
+  if (!isTopLevelValue(value, src))
+return true;
+
+  // If it's a top-level value because it's a block operand, i.e. a
+  // function argument, check whether the value replacing it after
+  // inlining is a valid dimension in the new region.
+  if (value.isa())
+return legalityCheck(mapping.lookup(value), dest);
+
+  // If it's a top-level value beacuse it's defined in the region,
+  // it can only be inlined if the defining op is a constant or a
+  // `dim`, which can appear anywhere and be valid, since the defining
+  // op won't be top-level anymore after inlining.
+  Attribute operandCst;
+  return matchPattern(value.getDefiningOp(), m_Constant(&operandCst)) ||
+ value.getDefiningOp();
+}
+
+/// Checks if all values known to be legal affine dimensions or symbols in 
`src`
+/// remain so if their respective users are inlined into `dest`.
+static bool
+remainsLegalAfterInline(ValueRange values, Region *src, Region *dest,
+const BlockAndValueMapping &mapping,
+function_ref legalityCheck) {
+  return llvm::all_of(values, [&](Value v) {
+return remainsLegalAfterInline(v, src, dest, mapping, legalityCheck);
+  });
+}
+
+/// Checks if an affine read or write operation remains legal after inlining
+/// from `src` to `dest`.
+template 
+static bool remainsLegalAfterInline(OpTy op, Region *src, Region *dest,
+const BlockAndValueMapping &mapping) {
+  static_assert(llvm::is_one_of::value,
+"only ops with affine read/write interface are supported");
+
+  AffineMap map = op.getAffineMap();
+  ValueRange dimOperands = op.getMapOperands().take_front(map.getNumDims());
+  ValueRange symbolOperands =
+  op.getMapOperands().take_back(map.getNumSymbols());
+  if (!remainsLegalAfterInline(
+  dimOperands, src, dest, mapping,
+  static_cast(isValidDim)))
+return false;
+  if (!remainsLegalAfterInline(
+  symbolOperands, src, dest, mapping,
+  static_cast(isValidSymbol)))
+return false;
+  return true;
+}
+
+/// Checks if an affine apply operation 

[llvm-branch-commits] [mlir] [draft] Dialect Conversion without Rollback (PR #93412)

2024-05-28 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -1053,3 +1055,241 @@ LogicalResult mlir::applyOpPatternsAndFold(
   });
   return converged;
 }
+
+//===--===//
+// One-Shot Dialect Conversion Infrastructure
+//===--===//
+
+namespace {
+/// A conversion rewriter for the One-Shot Dialect Conversion. This rewriter
+/// immediately materializes all IR changes. It derives from
+/// `ConversionPatternRewriter` so that the existing conversion patterns can
+/// be used with the One-Shot Dialect Conversion.
+class OneShotConversionPatternRewriter : public ConversionPatternRewriter {
+public:
+  OneShotConversionPatternRewriter(MLIRContext *ctx)
+  : ConversionPatternRewriter(ctx) {}
+
+  bool canRecoverFromRewriteFailure() const override { return false; }
+
+  void replaceOp(Operation *op, ValueRange newValues) override;
+
+  void replaceOp(Operation *op, Operation *newOp) override {
+replaceOp(op, newOp->getResults());
+  }
+
+  void eraseOp(Operation *op) override { PatternRewriter::eraseOp(op); }
+
+  void eraseBlock(Block *block) override { PatternRewriter::eraseBlock(block); 
}
+
+  void inlineBlockBefore(Block *source, Block *dest, Block::iterator before,
+ ValueRange argValues = std::nullopt) override {
+PatternRewriter::inlineBlockBefore(source, dest, before, argValues);
+  }
+  using PatternRewriter::inlineBlockBefore;
+
+  void startOpModification(Operation *op) override {
+PatternRewriter::startOpModification(op);
+  }
+
+  void finalizeOpModification(Operation *op) override {
+PatternRewriter::finalizeOpModification(op);
+  }
+
+  void cancelOpModification(Operation *op) override {
+PatternRewriter::cancelOpModification(op);
+  }
+
+  void setCurrentTypeConverter(const TypeConverter *converter) override {
+typeConverter = converter;
+  }
+
+  const TypeConverter *getCurrentTypeConverter() const override {
+return typeConverter;
+  }
+
+  LogicalResult getAdapterOperands(StringRef valueDiagTag,
+   std::optional inputLoc,
+   ValueRange values,
+   SmallVector &remapped) override;
+
+private:
+  /// Build an unrealized_conversion_cast op or look it up in the cache.
+  Value buildUnrealizedConversionCast(Location loc, Type type, Value value);
+
+  /// The current type converter.
+  const TypeConverter *typeConverter;
+
+  /// A cache for unrealized_conversion_casts. To ensure that identical casts
+  /// are not built multiple times.
+  DenseMap, Value> castCache;

ftynse wrote:

Hmm, is it possible that the same original value is casted to multiple 
_different_ types within the same conversion? Type converter is currently 
unaware of the surrounding context, so it's unclear to me how that could happen.

https://github.com/llvm/llvm-project/pull/93412
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [draft] Dialect Conversion without Rollback (PR #93412)

2024-05-28 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -1819,6 +1822,22 @@ detail::ConversionPatternRewriterImpl 
&ConversionPatternRewriter::getImpl() {
   return *impl;
 }
 
+void ConversionPatternRewriter::setCurrentTypeConverter(
+const TypeConverter *converter) {
+  impl->currentTypeConverter = converter;
+}
+
+const TypeConverter *
+ConversionPatternRewriter::getCurrentTypeConverter() const {
+  return impl->currentTypeConverter;
+}
+
+LogicalResult ConversionPatternRewriter::getAdapterOperands(

ftynse wrote:

Nit: can we agree on Adapter/Adaptor spelling? E.g., we already have 
`OpAdaptor`.

https://github.com/llvm/llvm-project/pull/93412
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [draft] Dialect Conversion without Rollback (PR #93412)

2024-05-28 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -321,15 +323,15 @@ class RandomizedWorklist : public Worklist {
 /// to the worklist in the beginning.
 class GreedyPatternRewriteDriver : public RewriterBase::Listener {
 protected:
-  explicit GreedyPatternRewriteDriver(MLIRContext *ctx,
+  explicit GreedyPatternRewriteDriver(PatternRewriter &rewriter,
   const FrozenRewritePatternSet &patterns,
   const GreedyRewriteConfig &config);
 
   /// Add the given operation to the worklist.
   void addSingleOpToWorklist(Operation *op);
 
   /// Add the given operation and its ancestors to the worklist.
-  void addToWorklist(Operation *op);
+  virtual void addToWorklist(Operation *op);

ftynse wrote:

Do we have an estimate of how much overhead adding a vtable to this class 
introduces?

https://github.com/llvm/llvm-project/pull/93412
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [draft] Dialect Conversion without Rollback (PR #93412)

2024-05-28 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -1053,3 +1055,241 @@ LogicalResult mlir::applyOpPatternsAndFold(
   });
   return converged;
 }
+
+//===--===//
+// One-Shot Dialect Conversion Infrastructure
+//===--===//
+
+namespace {
+/// A conversion rewriter for the One-Shot Dialect Conversion. This rewriter
+/// immediately materializes all IR changes. It derives from
+/// `ConversionPatternRewriter` so that the existing conversion patterns can
+/// be used with the One-Shot Dialect Conversion.
+class OneShotConversionPatternRewriter : public ConversionPatternRewriter {
+public:
+  OneShotConversionPatternRewriter(MLIRContext *ctx)
+  : ConversionPatternRewriter(ctx) {}
+
+  bool canRecoverFromRewriteFailure() const override { return false; }
+
+  void replaceOp(Operation *op, ValueRange newValues) override;
+
+  void replaceOp(Operation *op, Operation *newOp) override {
+replaceOp(op, newOp->getResults());
+  }
+
+  void eraseOp(Operation *op) override { PatternRewriter::eraseOp(op); }
+
+  void eraseBlock(Block *block) override { PatternRewriter::eraseBlock(block); 
}
+
+  void inlineBlockBefore(Block *source, Block *dest, Block::iterator before,
+ ValueRange argValues = std::nullopt) override {
+PatternRewriter::inlineBlockBefore(source, dest, before, argValues);
+  }
+  using PatternRewriter::inlineBlockBefore;
+
+  void startOpModification(Operation *op) override {
+PatternRewriter::startOpModification(op);
+  }
+
+  void finalizeOpModification(Operation *op) override {
+PatternRewriter::finalizeOpModification(op);
+  }
+
+  void cancelOpModification(Operation *op) override {
+PatternRewriter::cancelOpModification(op);
+  }

ftynse wrote:

Would these still be necessary after the old driver is removed?

https://github.com/llvm/llvm-project/pull/93412
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][linalg] Add transform operator for Winograd Conv2D algorithm (PR #96182)

2024-06-21 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -3480,6 +3480,31 @@ DiagnosedSilenceableFailure 
transform::MapCopyToThreadsOp::applyToOne(
   return DiagnosedSilenceableFailure::success();
 }
 
+//===--===//
+// WinogradConv2DOp
+//===--===//
+
+DiagnosedSilenceableFailure transform::WinogradConv2DOp::applyToOne(
+transform::TransformRewriter &rewriter, linalg::LinalgOp target,
+transform::ApplyToEachResultList &results,
+transform::TransformState &state) {
+  rewriter.setInsertionPoint(target);
+  auto maybeTransformed =
+  TypeSwitch>(target)
+  .Case([&](linalg::Conv2DNhwcFhwcOp op) {
+return winogradConv2D(rewriter, op, getM(), getR());
+  })
+  .Default([&](Operation *op) {
+return rewriter.notifyMatchFailure(op, "not supported");

ftynse wrote:

Let's rather `emitSilenceableFailure()` with this message to the user. The 
rewriter messages are not printed AFAIK.

https://github.com/llvm/llvm-project/pull/96182
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][linalg] Add transform operator for Winograd Conv2D algorithm (PR #96182)

2024-06-21 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -2587,4 +2587,55 @@ def MapCopyToThreadsOp :
   }];
 }
 
+//===--===//
+// Winograd Conv2D
+//===--===//
+
+def WinogradConv2DOp : Op {
+  let description = [{
+Winograd Conv2D algorithm will convert linalg Conv2D operator into batched

ftynse wrote:

```suggestion
Winograd Conv2D algorithm will convert linalg Conv2D operation into batched
```

Nit: these are called operations, not operators, in MLIR.

https://github.com/llvm/llvm-project/pull/96182
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][linalg] Add transform operator for Winograd Conv2D algorithm (PR #96182)

2024-06-21 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -0,0 +1,88 @@
+// RUN: mlir-opt %s -transform-interpreter -canonicalize --split-input-file | 
FileCheck %s
+
+func.func @conv2d(%arg0: tensor<2x10x10x5xf32>, %arg1: tensor<2x3x3x5xf32>, 
%arg2: tensor<1xf32>) -> tensor<2x8x8x2xf32> {
+  %0 = tensor.empty() : tensor<2x8x8x2xf32>
+  %1 = linalg.generic {indexing_maps = [affine_map<(d0, d1, d2, d3) -> (0)>, 
affine_map<(d0, d1, d2, d3) -> (d0, d1, d2, d3)>], iterator_types = 
["parallel", "parallel", "parallel", "parallel"]} ins(%arg2 : tensor<1xf32>) 
outs(%0 : tensor<2x8x8x2xf32>) {
+  ^bb0(%in: f32, %out: f32):
+linalg.yield %in : f32
+  } -> tensor<2x8x8x2xf32>
+  %2 = linalg.conv_2d_nhwc_fhwc {dilations = dense<1> : tensor<2xi64>, strides 
= dense<1> : tensor<2xi64>} ins(%arg0, %arg1 : tensor<2x10x10x5xf32>, 
tensor<2x3x3x5xf32>) outs(%1 : tensor<2x8x8x2xf32>) -> tensor<2x8x8x2xf32>
+  return %2 : tensor<2x8x8x2xf32>
+}
+
+module attributes {transform.with_named_sequence} {
+  transform.named_sequence @__transform_main(%arg1: !transform.any_op 
{transform.readonly}) {
+%0 = transform.structured.match ops{["linalg.conv_2d_nhwc_fhwc"]} in %arg1 
: (!transform.any_op) -> !transform.any_op
+%1 = transform.structured.winograd_conv2d %0 { m = 4, r = 3 } : 
(!transform.any_op) -> (!transform.any_op)
+transform.yield
+  }
+}
+
+// CHECK: #[[$MAP0:.+]] = affine_map<(d0, d1, d2, d3) -> (0)>
+// CHECK: #[[$MAP1:.+]] = affine_map<(d0, d1, d2, d3) -> (d0, d1, d2, d3)>
+// CHECK-LABEL: func.func @conv2d
+// CHECK-SAME:  (%[[ARG0:.*]]: tensor<2x10x10x5xf32>, %[[ARG1:.*]]: 
tensor<2x3x3x5xf32>, %[[ARG2:.*]]: tensor<1xf32>) -> tensor<2x8x8x2xf32> {
+// CHECK:%[[S0:.*]] = tensor.empty() : tensor<2x8x8x2xf32>
+// CHECK-NEXT:   %[[S1:.*]] = linalg.generic {indexing_maps = [#[[$MAP0]], 
#[[$MAP1]]], iterator_types = ["parallel", "parallel", "parallel", "parallel"]} 
ins(%[[ARG2]] : tensor<1xf32>) outs(%[[S0]] : tensor<2x8x8x2xf32>) {
+// CHECK-NEXT:   ^bb0(%[[IN:.*]]: f32, %[[OUT:.*]]: f32):
+// CHECK-NEXT: linalg.yield %[[IN]] : f32
+// CHECK-NEXT:   } -> tensor<2x8x8x2xf32>
+// CHECK-NEXT:   %[[S2:.*]] = tensor.empty() : tensor<2x2x6x6x5x2xf32>
+// CHECK-NEXT:   %[[S3:.*]] = linalg.winograd_filter_transform m(4) r(3) 
ins(%[[ARG1]] : tensor<2x3x3x5xf32>) outs(%[[S2]] : tensor<2x2x6x6x5x2xf32>) -> 
tensor<2x2x6x6x5x2xf32>
+// CHECK-NEXT:   %[[S4:.*]] = tensor.empty() : tensor<2x2x6x6x2x5xf32>
+// CHECK-NEXT:   %[[S5:.*]] = linalg.winograd_input_transform m(4) r(3) 
ins(%[[ARG0]] : tensor<2x10x10x5xf32>) outs(%[[S4]] : tensor<2x2x6x6x2x5xf32>) 
-> tensor<2x2x6x6x2x5xf32>
+// CHECK-NEXT:   %[[COLLAPSED:.*]] = tensor.collapse_shape %[[S3]] {{\[}}[0, 
1, 2, 3], [4], [5]] : tensor<2x2x6x6x5x2xf32> into tensor<144x5x2xf32>
+// CHECK-NEXT:   %[[COLLAPSED_0:.*]] = tensor.collapse_shape %[[S5]] {{\[}}[0, 
1, 2, 3], [4], [5]] : tensor<2x2x6x6x2x5xf32> into tensor<144x2x5xf32>
+// CHECK-NEXT:   %[[S6:.*]] = tensor.empty() : tensor<144x2x2xf32>
+// CHECK-NEXT:   %[[S7:.*]] = linalg.batch_matmul ins(%[[COLLAPSED_0]], 
%[[COLLAPSED]] : tensor<144x2x5xf32>, tensor<144x5x2xf32>) outs(%[[S6]] : 
tensor<144x2x2xf32>) -> tensor<144x2x2xf32>
+// CHECK-NEXT:   %[[EXPANDED:.*]] = tensor.expand_shape %[[S7]] {{\[}}[0, 1, 
2, 3], [4], [5]] output_shape [2, 2, 6, 6, 2, 2] : tensor<144x2x2xf32> into 
tensor<2x2x6x6x2x2xf32>
+// CHECK-NEXT:   %[[S8:.*]] = linalg.winograd_output_transform m(4) r(3) 
ins(%[[EXPANDED]] : tensor<2x2x6x6x2x2xf32>) outs(%[[S1]] : 
tensor<2x8x8x2xf32>) -> tensor<2x8x8x2xf32>
+// CHECK-NEXT:   return %[[S8]] : tensor<2x8x8x2xf32>
+// CHECK-NEXT: }

ftynse wrote:

Since we are already testing the op production logic elsewhere, we don't need 
to re-test it here. It is sufficient to check that it worked at the high level, 
e.g.:

```
CHECK: winograd_filter_transform m(4) r(3)
CHECK: winograd_input_transform
CHECK: match_matmul
CHECK: winograd_output_transform
```

https://github.com/llvm/llvm-project/pull/96182
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][linalg] Add transform operator for Winograd Conv2D algorithm (PR #96182)

2024-06-21 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -2587,4 +2587,55 @@ def MapCopyToThreadsOp :
   }];
 }
 
+//===--===//
+// Winograd Conv2D
+//===--===//
+
+def WinogradConv2DOp : Op {
+  let description = [{
+Winograd Conv2D algorithm will convert linalg Conv2D operator into batched
+matrix multiply. Before the matrix multiply, it will convert filter and
+input into a format suitable for batched matrix multiply. After the matrix
+multiply, it will convert output to the final result tensor.
+
+The algorithm F(m x m, r x r) is
+
+Y = A^T x [(G x g x G^T) @ (B^T x d x B)] x A
+
+The size of output Y is m x m. The size of filter g is r x r. The size of
+input d is (m + r - 1) x (m + r - 1). A^T, A, G^T, G, B^T, and B are
+transformation matrices.
+
+ Return modes:
+
+This operation fails if `target` is unsupported. Otherwise, the operation

ftynse wrote:

```suggestion
This operation produces a silenceable failure if `target` is unsupported. 
Otherwise, the operation
```

https://github.com/llvm/llvm-project/pull/96182
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][linalg] Add transform operator for Winograd Conv2D algorithm (PR #96182)

2024-06-21 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -0,0 +1,88 @@
+// RUN: mlir-opt %s -transform-interpreter -canonicalize --split-input-file | 
FileCheck %s
+
+func.func @conv2d(%arg0: tensor<2x10x10x5xf32>, %arg1: tensor<2x3x3x5xf32>, 
%arg2: tensor<1xf32>) -> tensor<2x8x8x2xf32> {
+  %0 = tensor.empty() : tensor<2x8x8x2xf32>
+  %1 = linalg.generic {indexing_maps = [affine_map<(d0, d1, d2, d3) -> (0)>, 
affine_map<(d0, d1, d2, d3) -> (d0, d1, d2, d3)>], iterator_types = 
["parallel", "parallel", "parallel", "parallel"]} ins(%arg2 : tensor<1xf32>) 
outs(%0 : tensor<2x8x8x2xf32>) {
+  ^bb0(%in: f32, %out: f32):
+linalg.yield %in : f32
+  } -> tensor<2x8x8x2xf32>
+  %2 = linalg.conv_2d_nhwc_fhwc {dilations = dense<1> : tensor<2xi64>, strides 
= dense<1> : tensor<2xi64>} ins(%arg0, %arg1 : tensor<2x10x10x5xf32>, 
tensor<2x3x3x5xf32>) outs(%1 : tensor<2x8x8x2xf32>) -> tensor<2x8x8x2xf32>
+  return %2 : tensor<2x8x8x2xf32>
+}
+
+module attributes {transform.with_named_sequence} {
+  transform.named_sequence @__transform_main(%arg1: !transform.any_op 
{transform.readonly}) {
+%0 = transform.structured.match ops{["linalg.conv_2d_nhwc_fhwc"]} in %arg1 
: (!transform.any_op) -> !transform.any_op
+%1 = transform.structured.winograd_conv2d %0 { m = 4, r = 3 } : 
(!transform.any_op) -> (!transform.any_op)
+transform.yield
+  }
+}
+
+// CHECK: #[[$MAP0:.+]] = affine_map<(d0, d1, d2, d3) -> (0)>
+// CHECK: #[[$MAP1:.+]] = affine_map<(d0, d1, d2, d3) -> (d0, d1, d2, d3)>
+// CHECK-LABEL: func.func @conv2d
+// CHECK-SAME:  (%[[ARG0:.*]]: tensor<2x10x10x5xf32>, %[[ARG1:.*]]: 
tensor<2x3x3x5xf32>, %[[ARG2:.*]]: tensor<1xf32>) -> tensor<2x8x8x2xf32> {
+// CHECK:%[[S0:.*]] = tensor.empty() : tensor<2x8x8x2xf32>
+// CHECK-NEXT:   %[[S1:.*]] = linalg.generic {indexing_maps = [#[[$MAP0]], 
#[[$MAP1]]], iterator_types = ["parallel", "parallel", "parallel", "parallel"]} 
ins(%[[ARG2]] : tensor<1xf32>) outs(%[[S0]] : tensor<2x8x8x2xf32>) {
+// CHECK-NEXT:   ^bb0(%[[IN:.*]]: f32, %[[OUT:.*]]: f32):
+// CHECK-NEXT: linalg.yield %[[IN]] : f32
+// CHECK-NEXT:   } -> tensor<2x8x8x2xf32>
+// CHECK-NEXT:   %[[S2:.*]] = tensor.empty() : tensor<2x2x6x6x5x2xf32>
+// CHECK-NEXT:   %[[S3:.*]] = linalg.winograd_filter_transform m(4) r(3) 
ins(%[[ARG1]] : tensor<2x3x3x5xf32>) outs(%[[S2]] : tensor<2x2x6x6x5x2xf32>) -> 
tensor<2x2x6x6x5x2xf32>
+// CHECK-NEXT:   %[[S4:.*]] = tensor.empty() : tensor<2x2x6x6x2x5xf32>
+// CHECK-NEXT:   %[[S5:.*]] = linalg.winograd_input_transform m(4) r(3) 
ins(%[[ARG0]] : tensor<2x10x10x5xf32>) outs(%[[S4]] : tensor<2x2x6x6x2x5xf32>) 
-> tensor<2x2x6x6x2x5xf32>
+// CHECK-NEXT:   %[[COLLAPSED:.*]] = tensor.collapse_shape %[[S3]] {{\[}}[0, 
1, 2, 3], [4], [5]] : tensor<2x2x6x6x5x2xf32> into tensor<144x5x2xf32>
+// CHECK-NEXT:   %[[COLLAPSED_0:.*]] = tensor.collapse_shape %[[S5]] {{\[}}[0, 
1, 2, 3], [4], [5]] : tensor<2x2x6x6x2x5xf32> into tensor<144x2x5xf32>
+// CHECK-NEXT:   %[[S6:.*]] = tensor.empty() : tensor<144x2x2xf32>
+// CHECK-NEXT:   %[[S7:.*]] = linalg.batch_matmul ins(%[[COLLAPSED_0]], 
%[[COLLAPSED]] : tensor<144x2x5xf32>, tensor<144x5x2xf32>) outs(%[[S6]] : 
tensor<144x2x2xf32>) -> tensor<144x2x2xf32>
+// CHECK-NEXT:   %[[EXPANDED:.*]] = tensor.expand_shape %[[S7]] {{\[}}[0, 1, 
2, 3], [4], [5]] output_shape [2, 2, 6, 6, 2, 2] : tensor<144x2x2xf32> into 
tensor<2x2x6x6x2x2xf32>
+// CHECK-NEXT:   %[[S8:.*]] = linalg.winograd_output_transform m(4) r(3) 
ins(%[[EXPANDED]] : tensor<2x2x6x6x2x2xf32>) outs(%[[S1]] : 
tensor<2x8x8x2xf32>) -> tensor<2x8x8x2xf32>
+// CHECK-NEXT:   return %[[S8]] : tensor<2x8x8x2xf32>
+// CHECK-NEXT: }
+
+// -
+
+func.func @conv2d_unaligned(%arg0: tensor<2x11x11x5xf32>, %arg1: 
tensor<2x3x3x5xf32>, %arg2: tensor<1xf32>) -> tensor<2x9x9x2xf32> {
+  %0 = tensor.empty() : tensor<2x9x9x2xf32>
+  %1 = linalg.generic {indexing_maps = [affine_map<(d0, d1, d2, d3) -> (0)>, 
affine_map<(d0, d1, d2, d3) -> (d0, d1, d2, d3)>], iterator_types = 
["parallel", "parallel", "parallel", "parallel"]} ins(%arg2 : tensor<1xf32>) 
outs(%0 : tensor<2x9x9x2xf32>) {
+  ^bb0(%in: f32, %out: f32):
+linalg.yield %in : f32
+  } -> tensor<2x9x9x2xf32>
+  %2 = linalg.conv_2d_nhwc_fhwc {dilations = dense<1> : tensor<2xi64>, strides 
= dense<1> : tensor<2xi64>} ins(%arg0, %arg1 : tensor<2x11x11x5xf32>, 
tensor<2x3x3x5xf32>) outs(%1 : tensor<2x9x9x2xf32>) -> tensor<2x9x9x2xf32>
+  return %2 : tensor<2x9x9x2xf32>
+}
+
+module attributes {transform.with_named_sequence} {
+  transform.named_sequence @__transform_main(%arg1: !transform.any_op 
{transform.readonly}) {
+%0 = transform.structured.match ops{["linalg.conv_2d_nhwc_fhwc"]} in %arg1 
: (!transform.any_op) -> !transform.any_op
+%1 = transform.structured.winograd_conv2d %0 { m = 4, r = 3 } : 
(!transform.any_op) -> (!transform.any_op)
+transform.yield
+  }
+}
+
+// CHECK: #[[$MAP0:.+]] = affine_map<(d0, d1, d2, d3) -> (0)>
+// CHECK: #[[$MAP1:.+]] = affine_map<(d0, d1, d2, d3) -> (d0, d1, d2, d3)>
+// CHECK-LABEL: func.func @conv2d_unaligned

[llvm-branch-commits] [mlir] [mlir][linalg] Add transform operator for Winograd Conv2D algorithm (PR #96182)

2024-06-21 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -3480,6 +3480,31 @@ DiagnosedSilenceableFailure 
transform::MapCopyToThreadsOp::applyToOne(
   return DiagnosedSilenceableFailure::success();
 }
 
+//===--===//
+// WinogradConv2DOp
+//===--===//
+
+DiagnosedSilenceableFailure transform::WinogradConv2DOp::applyToOne(
+transform::TransformRewriter &rewriter, linalg::LinalgOp target,
+transform::ApplyToEachResultList &results,
+transform::TransformState &state) {
+  rewriter.setInsertionPoint(target);
+  auto maybeTransformed =
+  TypeSwitch>(target)
+  .Case([&](linalg::Conv2DNhwcFhwcOp op) {
+return winogradConv2D(rewriter, op, getM(), getR());
+  })
+  .Default([&](Operation *op) {
+return rewriter.notifyMatchFailure(op, "not supported");
+  });
+
+  if (failed(maybeTransformed))
+return emitDefaultSilenceableFailure(target);

ftynse wrote:

It would be nice if `windogradConv2D` was returning some error code or was 
taking a callback to print error messages to instead of giving a default 
message here. Non-blocking.

https://github.com/llvm/llvm-project/pull/96182
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][linalg] Decompose winograd operators (PR #96183)

2024-06-24 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -36,6 +189,92 @@ constexpr TransformMapKeyTy F_2_3{2, 3};
 constexpr TransformMapKeyTy F_4_3{4, 3};
 constexpr TransformMapKeyTy F_2_5{2, 5};
 
+struct TransformMatrix {

ftynse wrote:

Please document top-level entities.

https://github.com/llvm/llvm-project/pull/96183
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][linalg] Decompose winograd operators (PR #96183)

2024-06-24 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -23,6 +26,156 @@ namespace linalg {
 
 namespace {
 
+// clang-format off
+// Winograd Conv2D uses a minimal 2D filtering algorithm to calculate its
+// result. The formula of minimal 2D filtering algorithm F(m x m, r x r),
+// m is the output dimension and r is the filter dimension, is
+//
+// Y = A^T x [ (G x g x G^T) x (B^T x d x B) ] x A
+//
+// g is filter and d is input data. We need to prepare 6 constant
+// transformation matrices, G, G^T, B^T, B, A^T, and A for this formula.
+//
+// The following tables define these constant transformation matrices for
+// F(2 x 2, 3 x 3), F(4 x 4, 3 x 3), and F(2 x 2, 5 x 5)
+constexpr float G_2x2_3x3[] = {
+   -1, 0,   0,
+ 1./2, -1./2, 1./2,
+ 1./2,  1./2, 1./2,
+0, 0,1
+};
+
+constexpr float GT_2x2_3x3[] = {
+   -1,  1./2, 1./2, 0,
+0, -1./2, 1./2, 0,
+0,  1./2, 1./2, 1
+};

ftynse wrote:

Have you considered introducing a (potentially `constexpr`) transpose function 
or some sort of transposed access iterator instead of hardcoding transposed 
matrices?

https://github.com/llvm/llvm-project/pull/96183
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][linalg] Decompose winograd operators (PR #96183)

2024-06-24 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -48,6 +287,261 @@ Value collapse2DData(RewriterBase &rewriter, Location loc, 
Value data) {
   reassociation);
 }
 
+// This function transforms the filter. The data layout of the filter is FHWC.
+// The transformation matrix is 2-dimension. We need to extract H x W from
+// FHWC first. We need to generate 2 levels of loops to iterate on F and C.
+// After the transformation, we get
+//
+// scf.for %f = lo_f to hi_f step 1
+//   scf.for %c = lo_c to hi_c step 1
+// %extracted = extract filter from filter
+// %ret = linalg.matmul G, %extracted
+// %ret = linalg.matmul %ret, GT
+// %inserted = insert %ret into filter
+//
+Value filterTransform(RewriterBase &rewriter, Location loc, Value filter,
+  Value retValue, int64_t m, int64_t r,
+  bool leftTransform = true, bool rightTransform = true) {
+  // Map from (m, r) to G transform matrix.
+  static const llvm::SmallDenseMap
+  GMatrices = {
+  {F_2_3, TransformMatrix(G_2x2_3x3, 4, 3)},
+  {F_4_3, TransformMatrix(G_4x4_3x3, 6, 3)},
+  {F_2_5, TransformMatrix(G_2x2_5x5, 6, 5)},
+  };
+
+  // Map from (m, r) to GT transform matrix.
+  static const llvm::SmallDenseMap
+  GTMatrices = {
+  {F_2_3, TransformMatrix(GT_2x2_3x3, 3, 4)},
+  {F_4_3, TransformMatrix(GT_4x4_3x3, 3, 6)},
+  {F_2_5, TransformMatrix(GT_2x2_5x5, 5, 6)},
+  };
+
+  auto filterType = cast(filter.getType());
+  Type elementType = filterType.getElementType();
+  auto filterShape = filterType.getShape(); // F, H, W, C
+  int64_t filterF = filterShape[0];
+  int64_t filterH = filterShape[1];
+  int64_t filterW = filterShape[2];
+  int64_t filterC = filterShape[3];
+
+  if (filterH != r && filterH != 1)
+return Value();
+  if (filterW != r && filterW != 1)
+return Value();
+
+  // Return shape is 
+  auto zeroIdx = rewriter.create(loc, 0);
+  auto fUpperBound = rewriter.create(loc, filterF);
+  auto cUpperBound = rewriter.create(loc, filterC);
+  auto oneStep = rewriter.create(loc, 1);
+  auto outerForOp =
+  rewriter.create(loc, zeroIdx, fUpperBound, oneStep, 
retValue);
+  Block *outerForBody = outerForOp.getBody();
+  rewriter.setInsertionPointToStart(outerForBody);
+  Value FIter = outerForBody->getArgument(0);
+
+  auto innerForOp = rewriter.create(
+  loc, zeroIdx, cUpperBound, oneStep, outerForOp.getRegionIterArgs()[0]);

ftynse wrote:

Ditto. there must be a better-named function for this.

https://github.com/llvm/llvm-project/pull/96183
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][linalg] Decompose winograd operators (PR #96183)

2024-06-24 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -48,6 +287,261 @@ Value collapse2DData(RewriterBase &rewriter, Location loc, 
Value data) {
   reassociation);
 }
 
+// This function transforms the filter. The data layout of the filter is FHWC.
+// The transformation matrix is 2-dimension. We need to extract H x W from
+// FHWC first. We need to generate 2 levels of loops to iterate on F and C.
+// After the transformation, we get
+//
+// scf.for %f = lo_f to hi_f step 1
+//   scf.for %c = lo_c to hi_c step 1
+// %extracted = extract filter from filter
+// %ret = linalg.matmul G, %extracted
+// %ret = linalg.matmul %ret, GT
+// %inserted = insert %ret into filter
+//
+Value filterTransform(RewriterBase &rewriter, Location loc, Value filter,
+  Value retValue, int64_t m, int64_t r,
+  bool leftTransform = true, bool rightTransform = true) {
+  // Map from (m, r) to G transform matrix.
+  static const llvm::SmallDenseMap
+  GMatrices = {
+  {F_2_3, TransformMatrix(G_2x2_3x3, 4, 3)},
+  {F_4_3, TransformMatrix(G_4x4_3x3, 6, 3)},
+  {F_2_5, TransformMatrix(G_2x2_5x5, 6, 5)},
+  };
+
+  // Map from (m, r) to GT transform matrix.
+  static const llvm::SmallDenseMap
+  GTMatrices = {
+  {F_2_3, TransformMatrix(GT_2x2_3x3, 3, 4)},
+  {F_4_3, TransformMatrix(GT_4x4_3x3, 3, 6)},
+  {F_2_5, TransformMatrix(GT_2x2_5x5, 5, 6)},
+  };
+
+  auto filterType = cast(filter.getType());
+  Type elementType = filterType.getElementType();
+  auto filterShape = filterType.getShape(); // F, H, W, C
+  int64_t filterF = filterShape[0];
+  int64_t filterH = filterShape[1];
+  int64_t filterW = filterShape[2];
+  int64_t filterC = filterShape[3];
+
+  if (filterH != r && filterH != 1)
+return Value();
+  if (filterW != r && filterW != 1)
+return Value();
+
+  // Return shape is 
+  auto zeroIdx = rewriter.create(loc, 0);
+  auto fUpperBound = rewriter.create(loc, filterF);
+  auto cUpperBound = rewriter.create(loc, filterC);
+  auto oneStep = rewriter.create(loc, 1);
+  auto outerForOp =
+  rewriter.create(loc, zeroIdx, fUpperBound, oneStep, 
retValue);
+  Block *outerForBody = outerForOp.getBody();
+  rewriter.setInsertionPointToStart(outerForBody);
+  Value FIter = outerForBody->getArgument(0);
+
+  auto innerForOp = rewriter.create(
+  loc, zeroIdx, cUpperBound, oneStep, outerForOp.getRegionIterArgs()[0]);
+  Block *innerForBody = innerForOp.getBody();
+  rewriter.setInsertionPointToStart(innerForBody);
+  Value CIter = innerForBody->getArgument(0);
+
+  // Extract (H, W) from (F, H, W, C)
+  auto extractFilter = extract2DData(
+  rewriter, loc, filter, FIter, CIter, /*outLoopIdx=*/0,
+  /*inLoopIdx=*/3, /*heightIdx=*/1, /*widthIdx=*/2, /*srcSize=*/4);
+
+  TransformMapKeyTy key = {m, r};
+  int64_t retRows = 1;
+  Value matmulRetValue = extractFilter;
+  if (leftTransform) {
+// Get constant transform matrix G
+auto it = GMatrices.find(key);
+if (it == GMatrices.end())
+  return Value();
+const TransformMatrix &GMatrix = it->second;
+
+retRows = GMatrix.rows;
+auto matmulType = RankedTensorType::get({retRows, filterW}, elementType);
+auto init = rewriter.create(loc, matmulType.getShape(),
+ elementType);
+
+Value G = create2DTransformMatrix(rewriter, loc, GMatrix, elementType);

ftynse wrote:

I wonder if we rather want to provide these matrices as global memrefs instead 
of creating locally every time. Have you considered that?

https://github.com/llvm/llvm-project/pull/96183
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][linalg] Decompose winograd operators (PR #96183)

2024-06-24 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -323,5 +1089,12 @@ void populateWinogradConv2DPatterns(RewritePatternSet 
&patterns, int64_t m,
   patterns.insert(context, m, r);
 }
 
+void populateDecomposeWinogradOpsPatterns(RewritePatternSet &patterns) {
+  MLIRContext *context = patterns.getContext();
+  patterns.insert(context);
+  patterns.insert(context);
+  patterns.insert(context);

ftynse wrote:

```suggestion
  patterns.insert(context);
```

https://github.com/llvm/llvm-project/pull/96183
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][linalg] Decompose winograd operators (PR #96183)

2024-06-24 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -100,6 +594,161 @@ Value matrixMultiply(RewriterBase &rewriter, Location loc,
   return expandOutput;
 }
 
+// This function transforms the output. The data layout of the output is HWNF.
+// The transformation matrix is 2-dimension. We need to extract H x W from
+// HWNF first. We need to generate 2 levels of loops to iterate on N and F.
+// After the transformation, we get
+//
+// scf.for %n = lo_n to hi_n step 1
+//   scf.for %f = lo_f to hi_f step 1
+// %extracted = extract input from result
+// %ret = linalg.matmul AT, %extracted
+// %ret = linalg.matmul %ret, A
+// %inserted = insert %ret into ret
+//
+Value outputTransform(RewriterBase &rewriter, Location loc, Value value,
+  Value output, int64_t m, int64_t r,
+  bool leftTransform = true, bool rightTransform = true) {
+  // Map from (m, r) to AT transform matrix.
+  static const llvm::SmallDenseMap
+  ATMatrices = {
+  {F_2_3, TransformMatrix(AT_2x2_3x3, 2, 4)},
+  {F_4_3, TransformMatrix(AT_4x4_3x3, 4, 6, 32)},
+  {F_2_5, TransformMatrix(AT_2x2_5x5, 2, 6, 16)},
+  };
+
+  // Map from (m, r) to A transform matrix.
+  static const llvm::SmallDenseMap
+  AMatrices = {
+  {F_2_3, TransformMatrix(A_2x2_3x3, 4, 2)},
+  {F_4_3, TransformMatrix(A_4x4_3x3, 6, 4, 32)},
+  {F_2_5, TransformMatrix(A_2x2_5x5, 6, 2, 16)},
+  };
+
+  auto valueType = cast(value.getType());
+  Type elementType = valueType.getElementType();
+  auto valueShape = valueType.getShape(); // TileH, TileW, H, W, N, F
+  int64_t valueH = valueShape[2];
+  int64_t valueW = valueShape[3];
+  int64_t valueN = valueShape[4];
+  int64_t valueF = valueShape[5];
+  int64_t alphaH = leftTransform ? m + r - 1 : 1;
+  int64_t alphaW = rightTransform ? m + r - 1 : 1;
+
+  if (valueH != alphaH && valueH != 1)
+return Value();
+  if (valueW != alphaW && valueW != 1)
+return Value();
+
+  auto zeroIdx = rewriter.create(loc, 0);
+  auto nUpperBound = rewriter.create(loc, valueN);
+  auto fUpperBound = rewriter.create(loc, valueF);
+  auto oneStep = rewriter.create(loc, 1);
+
+  auto outerForOp =
+  rewriter.create(loc, zeroIdx, nUpperBound, oneStep, output);
+  Block *outerForBody = outerForOp.getBody();
+  rewriter.setInsertionPointToStart(outerForBody);
+  Value NIter = outerForBody->getArgument(0);
+
+  auto innerForOp = rewriter.create(
+  loc, zeroIdx, fUpperBound, oneStep, outerForOp.getRegionIterArgs()[0]);
+  Block *innerForBody = innerForOp.getBody();
+  rewriter.setInsertionPointToStart(innerForBody);
+  Value FIter = innerForBody->getArgument(0);
+
+  // Extract (H, W) from (1, 1, H, W, N, F)
+  auto extractValue = extract2DData(
+  rewriter, loc, value, NIter, FIter, /*outLoopIdx=*/4,
+  /*inLoopIdx=*/5, /*heightIdx=*/2, /*widthIdx=*/3, /*srcSize=*/6);
+
+  TransformMapKeyTy key = {m, r};
+  int64_t retRows = 1;
+  int64_t retCols = 1;
+  int64_t leftScalarFactor = 1;
+  int64_t rightScalarFactor = 1;
+  Value matmulRetValue = extractValue;
+  if (leftTransform) {
+// Get constant transform matrix AT
+auto it = ATMatrices.find(key);
+if (it == ATMatrices.end())
+  return Value();
+const TransformMatrix &ATMatrix = it->second;
+
+leftScalarFactor = ATMatrix.scalarFactor;
+retRows = ATMatrix.rows;
+auto matmulType = RankedTensorType::get({retRows, valueW}, elementType);
+auto init = rewriter.create(loc, matmulType.getShape(),
+ elementType);
+
+Value AT = create2DTransformMatrix(rewriter, loc, ATMatrix, elementType);
+// Multiply AT x m
+auto matmulOp = rewriter.create(
+loc, matmulType, ValueRange{AT, matmulRetValue}, ValueRange{init});
+matmulRetValue = matmulOp.getResult(0);
+  }
+
+  if (rightTransform) {
+// Get constant transform matrix T
+auto it = AMatrices.find(key);
+if (it == AMatrices.end())
+  return Value();
+const TransformMatrix &AMatrix = it->second;
+
+rightScalarFactor = AMatrix.scalarFactor;
+auto matmulType =
+RankedTensorType::get({retRows, AMatrix.cols}, elementType);
+retCols = AMatrix.cols;
+auto init = rewriter.create(loc, matmulType.getShape(),
+ elementType);
+
+Value A = create2DTransformMatrix(rewriter, loc, AMatrix, elementType);
+// Multiply y = (AT x m) x A
+auto matmulOp = rewriter.create(
+loc, matmulType, ValueRange{matmulRetValue, A}, ValueRange{init});
+matmulRetValue = matmulOp.getResult(0);
+  }
+
+  // Multiply scalar factor.
+  Value scalarFactor = rewriter.create(
+  loc, FloatAttr::get(elementType, leftScalarFactor * rightScalarFactor));
+  auto matmulType = RankedTensorType::get({retRows, retCols}, elementType);
+  auto init =
+  rewriter.create(loc, matmulType.getShape(), 
elementType);
+
+  auto identityAffineMap = rewriter.getMultiDimIdentityMap(2);
+  Smal

[llvm-branch-commits] [mlir] [mlir][linalg] Decompose winograd operators (PR #96183)

2024-06-24 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -100,6 +594,161 @@ Value matrixMultiply(RewriterBase &rewriter, Location loc,
   return expandOutput;
 }
 
+// This function transforms the output. The data layout of the output is HWNF.
+// The transformation matrix is 2-dimension. We need to extract H x W from
+// HWNF first. We need to generate 2 levels of loops to iterate on N and F.
+// After the transformation, we get
+//
+// scf.for %n = lo_n to hi_n step 1
+//   scf.for %f = lo_f to hi_f step 1
+// %extracted = extract input from result
+// %ret = linalg.matmul AT, %extracted
+// %ret = linalg.matmul %ret, A
+// %inserted = insert %ret into ret
+//
+Value outputTransform(RewriterBase &rewriter, Location loc, Value value,
+  Value output, int64_t m, int64_t r,
+  bool leftTransform = true, bool rightTransform = true) {
+  // Map from (m, r) to AT transform matrix.
+  static const llvm::SmallDenseMap
+  ATMatrices = {
+  {F_2_3, TransformMatrix(AT_2x2_3x3, 2, 4)},
+  {F_4_3, TransformMatrix(AT_4x4_3x3, 4, 6, 32)},
+  {F_2_5, TransformMatrix(AT_2x2_5x5, 2, 6, 16)},
+  };
+
+  // Map from (m, r) to A transform matrix.
+  static const llvm::SmallDenseMap
+  AMatrices = {
+  {F_2_3, TransformMatrix(A_2x2_3x3, 4, 2)},
+  {F_4_3, TransformMatrix(A_4x4_3x3, 6, 4, 32)},
+  {F_2_5, TransformMatrix(A_2x2_5x5, 6, 2, 16)},
+  };
+
+  auto valueType = cast(value.getType());
+  Type elementType = valueType.getElementType();
+  auto valueShape = valueType.getShape(); // TileH, TileW, H, W, N, F
+  int64_t valueH = valueShape[2];
+  int64_t valueW = valueShape[3];
+  int64_t valueN = valueShape[4];
+  int64_t valueF = valueShape[5];
+  int64_t alphaH = leftTransform ? m + r - 1 : 1;
+  int64_t alphaW = rightTransform ? m + r - 1 : 1;
+
+  if (valueH != alphaH && valueH != 1)
+return Value();
+  if (valueW != alphaW && valueW != 1)
+return Value();
+
+  auto zeroIdx = rewriter.create(loc, 0);
+  auto nUpperBound = rewriter.create(loc, valueN);
+  auto fUpperBound = rewriter.create(loc, valueF);
+  auto oneStep = rewriter.create(loc, 1);
+
+  auto outerForOp =
+  rewriter.create(loc, zeroIdx, nUpperBound, oneStep, output);
+  Block *outerForBody = outerForOp.getBody();
+  rewriter.setInsertionPointToStart(outerForBody);
+  Value NIter = outerForBody->getArgument(0);
+
+  auto innerForOp = rewriter.create(
+  loc, zeroIdx, fUpperBound, oneStep, outerForOp.getRegionIterArgs()[0]);
+  Block *innerForBody = innerForOp.getBody();
+  rewriter.setInsertionPointToStart(innerForBody);
+  Value FIter = innerForBody->getArgument(0);
+
+  // Extract (H, W) from (1, 1, H, W, N, F)
+  auto extractValue = extract2DData(
+  rewriter, loc, value, NIter, FIter, /*outLoopIdx=*/4,
+  /*inLoopIdx=*/5, /*heightIdx=*/2, /*widthIdx=*/3, /*srcSize=*/6);
+
+  TransformMapKeyTy key = {m, r};
+  int64_t retRows = 1;
+  int64_t retCols = 1;
+  int64_t leftScalarFactor = 1;
+  int64_t rightScalarFactor = 1;
+  Value matmulRetValue = extractValue;
+  if (leftTransform) {
+// Get constant transform matrix AT
+auto it = ATMatrices.find(key);
+if (it == ATMatrices.end())
+  return Value();
+const TransformMatrix &ATMatrix = it->second;
+
+leftScalarFactor = ATMatrix.scalarFactor;
+retRows = ATMatrix.rows;
+auto matmulType = RankedTensorType::get({retRows, valueW}, elementType);
+auto init = rewriter.create(loc, matmulType.getShape(),
+ elementType);
+
+Value AT = create2DTransformMatrix(rewriter, loc, ATMatrix, elementType);
+// Multiply AT x m
+auto matmulOp = rewriter.create(
+loc, matmulType, ValueRange{AT, matmulRetValue}, ValueRange{init});
+matmulRetValue = matmulOp.getResult(0);
+  }
+
+  if (rightTransform) {
+// Get constant transform matrix T
+auto it = AMatrices.find(key);
+if (it == AMatrices.end())
+  return Value();
+const TransformMatrix &AMatrix = it->second;
+
+rightScalarFactor = AMatrix.scalarFactor;
+auto matmulType =
+RankedTensorType::get({retRows, AMatrix.cols}, elementType);
+retCols = AMatrix.cols;
+auto init = rewriter.create(loc, matmulType.getShape(),
+ elementType);
+
+Value A = create2DTransformMatrix(rewriter, loc, AMatrix, elementType);
+// Multiply y = (AT x m) x A
+auto matmulOp = rewriter.create(
+loc, matmulType, ValueRange{matmulRetValue, A}, ValueRange{init});
+matmulRetValue = matmulOp.getResult(0);
+  }
+
+  // Multiply scalar factor.
+  Value scalarFactor = rewriter.create(
+  loc, FloatAttr::get(elementType, leftScalarFactor * rightScalarFactor));
+  auto matmulType = RankedTensorType::get({retRows, retCols}, elementType);
+  auto init =
+  rewriter.create(loc, matmulType.getShape(), 
elementType);
+
+  auto identityAffineMap = rewriter.getMultiDimIdentityMap(2);
+  Smal

[llvm-branch-commits] [mlir] [mlir][linalg] Decompose winograd operators (PR #96183)

2024-06-24 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -100,6 +594,161 @@ Value matrixMultiply(RewriterBase &rewriter, Location loc,
   return expandOutput;
 }
 
+// This function transforms the output. The data layout of the output is HWNF.
+// The transformation matrix is 2-dimension. We need to extract H x W from
+// HWNF first. We need to generate 2 levels of loops to iterate on N and F.
+// After the transformation, we get
+//
+// scf.for %n = lo_n to hi_n step 1
+//   scf.for %f = lo_f to hi_f step 1
+// %extracted = extract input from result
+// %ret = linalg.matmul AT, %extracted
+// %ret = linalg.matmul %ret, A
+// %inserted = insert %ret into ret
+//
+Value outputTransform(RewriterBase &rewriter, Location loc, Value value,
+  Value output, int64_t m, int64_t r,
+  bool leftTransform = true, bool rightTransform = true) {
+  // Map from (m, r) to AT transform matrix.
+  static const llvm::SmallDenseMap
+  ATMatrices = {
+  {F_2_3, TransformMatrix(AT_2x2_3x3, 2, 4)},
+  {F_4_3, TransformMatrix(AT_4x4_3x3, 4, 6, 32)},
+  {F_2_5, TransformMatrix(AT_2x2_5x5, 2, 6, 16)},
+  };
+
+  // Map from (m, r) to A transform matrix.
+  static const llvm::SmallDenseMap
+  AMatrices = {
+  {F_2_3, TransformMatrix(A_2x2_3x3, 4, 2)},
+  {F_4_3, TransformMatrix(A_4x4_3x3, 6, 4, 32)},
+  {F_2_5, TransformMatrix(A_2x2_5x5, 6, 2, 16)},
+  };
+
+  auto valueType = cast(value.getType());
+  Type elementType = valueType.getElementType();
+  auto valueShape = valueType.getShape(); // TileH, TileW, H, W, N, F
+  int64_t valueH = valueShape[2];
+  int64_t valueW = valueShape[3];
+  int64_t valueN = valueShape[4];
+  int64_t valueF = valueShape[5];
+  int64_t alphaH = leftTransform ? m + r - 1 : 1;
+  int64_t alphaW = rightTransform ? m + r - 1 : 1;
+
+  if (valueH != alphaH && valueH != 1)
+return Value();
+  if (valueW != alphaW && valueW != 1)
+return Value();
+
+  auto zeroIdx = rewriter.create(loc, 0);
+  auto nUpperBound = rewriter.create(loc, valueN);
+  auto fUpperBound = rewriter.create(loc, valueF);
+  auto oneStep = rewriter.create(loc, 1);
+
+  auto outerForOp =
+  rewriter.create(loc, zeroIdx, nUpperBound, oneStep, output);
+  Block *outerForBody = outerForOp.getBody();
+  rewriter.setInsertionPointToStart(outerForBody);
+  Value NIter = outerForBody->getArgument(0);
+
+  auto innerForOp = rewriter.create(
+  loc, zeroIdx, fUpperBound, oneStep, outerForOp.getRegionIterArgs()[0]);
+  Block *innerForBody = innerForOp.getBody();
+  rewriter.setInsertionPointToStart(innerForBody);
+  Value FIter = innerForBody->getArgument(0);

ftynse wrote:

FYI, there's a `mlir::scf::buildLoopNest` somewhere that may space you the 
boilerplate.

https://github.com/llvm/llvm-project/pull/96183
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][linalg] Decompose winograd operators (PR #96183)

2024-06-24 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -48,6 +287,261 @@ Value collapse2DData(RewriterBase &rewriter, Location loc, 
Value data) {
   reassociation);
 }
 
+// This function transforms the filter. The data layout of the filter is FHWC.
+// The transformation matrix is 2-dimension. We need to extract H x W from
+// FHWC first. We need to generate 2 levels of loops to iterate on F and C.
+// After the transformation, we get
+//
+// scf.for %f = lo_f to hi_f step 1
+//   scf.for %c = lo_c to hi_c step 1
+// %extracted = extract filter from filter
+// %ret = linalg.matmul G, %extracted
+// %ret = linalg.matmul %ret, GT
+// %inserted = insert %ret into filter
+//

ftynse wrote:

```suggestion
/// This function transforms the filter. The data layout of the filter is FHWC.
/// The transformation matrix is 2-dimension. We need to extract H x W from
/// FHWC first. We need to generate 2 levels of loops to iterate on F and C.
/// After the transformation, we get
///
/// scf.for %f = lo_f to hi_f step 1
///   scf.for %c = lo_c to hi_c step 1
/// %extracted = extract filter from filter
/// %ret = linalg.matmul G, %extracted
/// %ret = linalg.matmul %ret, GT
/// %inserted = insert %ret into filter
///
```

https://github.com/llvm/llvm-project/pull/96183
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][linalg] Decompose winograd operators (PR #96183)

2024-06-24 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -289,6 +938,123 @@ FailureOr winogradConv2DHelper(RewriterBase 
&rewriter,
   return transformedOutput.getDefiningOp();
 }
 
+FailureOr
+decomposeWinogradFilterTransformHelper(RewriterBase &rewriter,
+   linalg::WinogradFilterTransformOp op) {
+  Location loc = op.getLoc();
+  Value filter = op.getFilter();
+  auto filterType = cast(filter.getType());
+  auto filterShape = filterType.getShape();
+  int64_t filterH = filterShape[1];
+  int64_t filterW = filterShape[2];
+
+  // For F(m x 1, r x 1), we only need to do left side transform.
+  bool leftTransform = filterH != 1;
+  // For F(1 x m, 1 x r), we only need to do right side transform.
+  bool rightTransform = filterW != 1;
+  Value transformedFilter =
+  filterTransform(rewriter, loc, filter, op.getOutput(), op.getM(),
+  op.getR(), leftTransform, rightTransform);
+  if (!transformedFilter)
+return failure();
+
+  rewriter.replaceOp(op, transformedFilter);
+
+  return transformedFilter.getDefiningOp();
+}
+
+FailureOr
+decomposeWinogradInputTransformHelper(RewriterBase &rewriter,
+  linalg::WinogradInputTransformOp op) {
+  Location loc = op.getLoc();
+  Value input = op.getInput();
+  auto inputType = cast(input.getType());
+  auto inputShape = inputType.getShape();
+  int64_t inputH = inputShape[1];
+  int64_t inputW = inputShape[2];
+
+  // For F(m x 1, r x 1), we only need to do left side transform.
+  bool leftTransform = inputH != 1;
+  // For F(1 x m, 1 x r), we only need to do right side transform.
+  bool rightTransform = inputW != 1;
+  Value transformedInput =
+  inputTransform(rewriter, loc, op.getInput(), op.getOutput(), op.getM(),
+ op.getR(), leftTransform, rightTransform);
+  if (!transformedInput)
+return failure();
+
+  rewriter.replaceOp(op, transformedInput);
+
+  return transformedInput.getDefiningOp();
+}
+
+FailureOr
+decomposeWinogradOutputTransformHelper(RewriterBase &rewriter,
+   linalg::WinogradOutputTransformOp op) {
+  Location loc = op.getLoc();
+  Value value = op.getValue();
+  auto valueType = cast(value.getType());
+  auto valueShape = valueType.getShape();
+  int64_t valueH = valueShape[2];
+  int64_t valueW = valueShape[3];
+
+  // For F(m x 1, r x 1), we only need to do left side transform.
+  bool leftTransform = valueH != 1;
+  // For F(1 x m, 1 x r), we only need to do right side transform.
+  bool rightTransform = valueW != 1;
+  Value transformedOutput =
+  outputTransform(rewriter, loc, value, op.getOutput(), op.getM(),
+  op.getR(), leftTransform, rightTransform);
+  if (!transformedOutput)
+return failure();
+
+  rewriter.replaceOp(op, transformedOutput);
+
+  return transformedOutput.getDefiningOp();
+}
+
+class DecomposeWinogradFilterTransform final
+: public OpRewritePattern {
+public:
+  using OpRewritePattern::OpRewritePattern;
+
+  LogicalResult matchAndRewrite(linalg::WinogradFilterTransformOp op,
+PatternRewriter &rewriter) const override {
+if (failed(decomposeWinogradFilterTransformHelper(rewriter, op)))
+  return failure();
+
+return success();
+  }
+};
+
+class DecomposeWinogradInputTransform final
+: public OpRewritePattern {
+public:
+  using OpRewritePattern::OpRewritePattern;
+
+  LogicalResult matchAndRewrite(linalg::WinogradInputTransformOp op,
+PatternRewriter &rewriter) const override {
+if (failed(decomposeWinogradInputTransformHelper(rewriter, op)))
+  return failure();
+
+return success();

ftynse wrote:

```suggestion
return decomposeWinogradInputTransformHelper(rewriter, op);
```

https://github.com/llvm/llvm-project/pull/96183
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][linalg] Decompose winograd operators (PR #96183)

2024-06-24 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -36,6 +189,92 @@ constexpr TransformMapKeyTy F_2_3{2, 3};
 constexpr TransformMapKeyTy F_4_3{4, 3};
 constexpr TransformMapKeyTy F_2_5{2, 5};
 
+struct TransformMatrix {
+  TransformMatrix(const float *table, int64_t rows, int64_t cols,
+  int64_t scalarFactor = 1)
+  : table(table), rows(rows), cols(cols), scalarFactor(scalarFactor) {}
+
+  const float *table;
+  int64_t rows;
+  int64_t cols;
+  int64_t scalarFactor;
+};
+
+Value create2DTransformMatrix(RewriterBase &rewriter, Location loc,
+  TransformMatrix transform, Type type) {
+  ArrayRef const_vec(transform.table, transform.rows * transform.cols);

ftynse wrote:

Nit: camelBack
```suggestion
  ArrayRef constVec(transform.table, transform.rows * transform.cols);
```

https://github.com/llvm/llvm-project/pull/96183
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][linalg] Decompose winograd operators (PR #96183)

2024-06-24 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -48,6 +287,261 @@ Value collapse2DData(RewriterBase &rewriter, Location loc, 
Value data) {
   reassociation);
 }
 
+// This function transforms the filter. The data layout of the filter is FHWC.
+// The transformation matrix is 2-dimension. We need to extract H x W from
+// FHWC first. We need to generate 2 levels of loops to iterate on F and C.
+// After the transformation, we get
+//
+// scf.for %f = lo_f to hi_f step 1
+//   scf.for %c = lo_c to hi_c step 1
+// %extracted = extract filter from filter
+// %ret = linalg.matmul G, %extracted
+// %ret = linalg.matmul %ret, GT
+// %inserted = insert %ret into filter
+//
+Value filterTransform(RewriterBase &rewriter, Location loc, Value filter,
+  Value retValue, int64_t m, int64_t r,
+  bool leftTransform = true, bool rightTransform = true) {
+  // Map from (m, r) to G transform matrix.
+  static const llvm::SmallDenseMap
+  GMatrices = {
+  {F_2_3, TransformMatrix(G_2x2_3x3, 4, 3)},
+  {F_4_3, TransformMatrix(G_4x4_3x3, 6, 3)},
+  {F_2_5, TransformMatrix(G_2x2_5x5, 6, 5)},
+  };
+
+  // Map from (m, r) to GT transform matrix.
+  static const llvm::SmallDenseMap
+  GTMatrices = {
+  {F_2_3, TransformMatrix(GT_2x2_3x3, 3, 4)},
+  {F_4_3, TransformMatrix(GT_4x4_3x3, 3, 6)},
+  {F_2_5, TransformMatrix(GT_2x2_5x5, 5, 6)},
+  };
+
+  auto filterType = cast(filter.getType());
+  Type elementType = filterType.getElementType();
+  auto filterShape = filterType.getShape(); // F, H, W, C
+  int64_t filterF = filterShape[0];
+  int64_t filterH = filterShape[1];
+  int64_t filterW = filterShape[2];
+  int64_t filterC = filterShape[3];
+
+  if (filterH != r && filterH != 1)
+return Value();
+  if (filterW != r && filterW != 1)
+return Value();
+
+  // Return shape is 
+  auto zeroIdx = rewriter.create(loc, 0);
+  auto fUpperBound = rewriter.create(loc, filterF);
+  auto cUpperBound = rewriter.create(loc, filterC);
+  auto oneStep = rewriter.create(loc, 1);
+  auto outerForOp =
+  rewriter.create(loc, zeroIdx, fUpperBound, oneStep, 
retValue);
+  Block *outerForBody = outerForOp.getBody();
+  rewriter.setInsertionPointToStart(outerForBody);
+  Value FIter = outerForBody->getArgument(0);

ftynse wrote:

There must be a function on `scf::ForOp` that returns the induction variable 
and avoids magic constant zero here.

https://github.com/llvm/llvm-project/pull/96183
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][linalg] Implement TilingInterface for winograd operators (PR #96184)

2024-06-24 Thread Oleksandr Alex Zinenko via llvm-branch-commits

https://github.com/ftynse commented:

I think @MaheshRavishankar should take a look at the interface implementation 
details.

https://github.com/llvm/llvm-project/pull/96184
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][linalg] Implement TilingInterface for winograd operators (PR #96184)

2024-06-24 Thread Oleksandr Alex Zinenko via llvm-branch-commits

https://github.com/ftynse edited https://github.com/llvm/llvm-project/pull/96184
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][linalg] Implement TilingInterface for winograd operators (PR #96184)

2024-06-24 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -2760,6 +2760,89 @@ LogicalResult WinogradFilterTransformOp::verify() {
   return success();
 }
 
+SmallVector
+WinogradFilterTransformOp::getIterationDomain(OpBuilder &builder) {
+  Location loc = getLoc();
+  Value zero = builder.create(loc, 0);
+  Value one = builder.create(loc, 1);
+  Value output = getOutput();
+  SmallVector loopBounds(6);
+  for (unsigned dim = 0; dim < 6; ++dim) {
+loopBounds[dim].offset = zero;
+loopBounds[dim].size = getDimValue(builder, loc, output, dim);
+loopBounds[dim].stride = one;
+  }
+  return loopBounds;
+}
+
+SmallVector
+WinogradFilterTransformOp::getLoopIteratorTypes() {
+  SmallVector iteratorTypes(6,
+ 
utils::IteratorType::parallel);
+  return iteratorTypes;
+}
+
+Value getValueFromOpFoldResult(OpFoldResult opFoldResult, OpBuilder &builder,
+   Location loc) {
+  if (auto val = opFoldResult.dyn_cast()) {
+return val;
+  } else if (auto attr = opFoldResult.dyn_cast()) {
+auto intAttr = cast(attr);
+return builder.create(loc, intAttr);
+  }

ftynse wrote:

I suspect this might already exist somewhere in the arith dialect.

https://github.com/llvm/llvm-project/pull/96184
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][linalg] Implement TilingInterface for winograd operators (PR #96184)

2024-06-24 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -2638,4 +2638,41 @@ def WinogradConv2DOp : Op {
+  let description = [{
+Decompose winograd operators. It will convert filter, input and output
+transform operators into a combination of scf, tensor, and linalg

ftynse wrote:

Nit: operations

https://github.com/llvm/llvm-project/pull/96184
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][linalg] Implement TilingInterface for winograd operators (PR #96184)

2024-06-24 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -2760,6 +2760,89 @@ LogicalResult WinogradFilterTransformOp::verify() {
   return success();
 }
 
+SmallVector
+WinogradFilterTransformOp::getIterationDomain(OpBuilder &builder) {
+  Location loc = getLoc();
+  Value zero = builder.create(loc, 0);
+  Value one = builder.create(loc, 1);
+  Value output = getOutput();
+  SmallVector loopBounds(6);
+  for (unsigned dim = 0; dim < 6; ++dim) {
+loopBounds[dim].offset = zero;
+loopBounds[dim].size = getDimValue(builder, loc, output, dim);
+loopBounds[dim].stride = one;
+  }
+  return loopBounds;
+}
+
+SmallVector
+WinogradFilterTransformOp::getLoopIteratorTypes() {
+  SmallVector iteratorTypes(6,
+ 
utils::IteratorType::parallel);
+  return iteratorTypes;
+}
+
+Value getValueFromOpFoldResult(OpFoldResult opFoldResult, OpBuilder &builder,
+   Location loc) {
+  if (auto val = opFoldResult.dyn_cast()) {
+return val;
+  } else if (auto attr = opFoldResult.dyn_cast()) {
+auto intAttr = cast(attr);
+return builder.create(loc, intAttr);
+  }
+  // This should never happen if OpFoldResult is correctly formed.

ftynse wrote:

Then this should be an assertion.

https://github.com/llvm/llvm-project/pull/96184
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][linalg] Implement TilingInterface for winograd operators (PR #96184)

2024-06-24 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -2760,6 +2760,89 @@ LogicalResult WinogradFilterTransformOp::verify() {
   return success();
 }
 
+SmallVector
+WinogradFilterTransformOp::getIterationDomain(OpBuilder &builder) {
+  Location loc = getLoc();
+  Value zero = builder.create(loc, 0);
+  Value one = builder.create(loc, 1);

ftynse wrote:

IIRC, `Range` contains list of `OpFoldResult`, meaning we can put attributes 
there and not materialize operations for these constants.

https://github.com/llvm/llvm-project/pull/96184
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][Transforms][NFC] Dialect Conversion: Move argument materialization logic (PR #96329)

2024-06-24 Thread Oleksandr Alex Zinenko via llvm-branch-commits

https://github.com/ftynse approved this pull request.


https://github.com/llvm/llvm-project/pull/96329
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][linalg] Implement TilingInterface for winograd operators (PR #96184)

2024-07-11 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -2810,9 +2819,117 @@ LogicalResult WinogradInputTransformOp::verify() {
   if (failed(verifyCompatibleShape(expectedOutputShape, outputShape))) {
 return emitOpError("the output shape is not expected");
   }
+
   return success();
 }
 
+SmallVector
+WinogradInputTransformOp::getIterationDomain(OpBuilder &builder) {
+  Location loc = getLoc();
+  auto indexType = builder.getIndexType();
+  auto zeroAttr = builder.getIntegerAttr(indexType, 0);
+  auto oneAttr = builder.getIntegerAttr(indexType, 1);
+  Value output = getOutput();
+  SmallVector loopBounds(6);
+  for (unsigned dim = 0; dim < 6; ++dim) {
+loopBounds[dim].offset = zeroAttr;
+loopBounds[dim].size = getDimValue(builder, loc, output, dim);
+loopBounds[dim].stride = oneAttr;
+  }
+  return loopBounds;
+}
+
+SmallVector
+WinogradInputTransformOp::getLoopIteratorTypes() {
+  SmallVector iteratorTypes(6,
+ 
utils::IteratorType::parallel);
+  return iteratorTypes;
+}
+
+LogicalResult WinogradInputTransformOp::getResultTilePosition(
+OpBuilder &builder, unsigned resultNumber, ArrayRef offsets,
+ArrayRef sizes, SmallVector &resultOffsets,
+SmallVector &resultSizes) {
+  auto zeroAttr = builder.getI64IntegerAttr(0);
+  auto oneAttr = builder.getI64IntegerAttr(1);
+
+  resultOffsets.push_back(zeroAttr);
+  resultOffsets.push_back(zeroAttr);
+  resultOffsets.push_back(offsets[2]);
+  resultOffsets.push_back(offsets[3]);
+  resultOffsets.push_back(zeroAttr);
+  resultOffsets.push_back(zeroAttr);
+  resultSizes.push_back(sizes[0]);
+  resultSizes.push_back(sizes[1]);
+  resultSizes.push_back(oneAttr);
+  resultSizes.push_back(oneAttr);
+  resultSizes.push_back(sizes[4]);
+  resultSizes.push_back(sizes[5]);
+
+  return success();
+}
+
+FailureOr
+WinogradInputTransformOp::getTiledImplementation(OpBuilder &builder,
+ ArrayRef 
offsets,
+ ArrayRef sizes) 
{
+  auto oneAttr = builder.getI64IntegerAttr(1);
+  auto zeroAttr = builder.getI64IntegerAttr(0);
+  Value input = getInput();
+  auto inputType = cast(input.getType());
+  auto inputShape = inputType.getShape();

ftynse wrote:

Please expand `auto` unless the type is obvious from statement-level context 
(builders on the RHS are fine, but I don't remember what `getShape` returns as 
a type).

https://github.com/llvm/llvm-project/pull/96184
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][linalg] Implement TilingInterface for winograd operators (PR #96184)

2024-07-11 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -2810,9 +2819,117 @@ LogicalResult WinogradInputTransformOp::verify() {
   if (failed(verifyCompatibleShape(expectedOutputShape, outputShape))) {
 return emitOpError("the output shape is not expected");
   }
+
   return success();
 }
 
+SmallVector
+WinogradInputTransformOp::getIterationDomain(OpBuilder &builder) {
+  Location loc = getLoc();
+  auto indexType = builder.getIndexType();
+  auto zeroAttr = builder.getIntegerAttr(indexType, 0);
+  auto oneAttr = builder.getIntegerAttr(indexType, 1);
+  Value output = getOutput();
+  SmallVector loopBounds(6);
+  for (unsigned dim = 0; dim < 6; ++dim) {
+loopBounds[dim].offset = zeroAttr;
+loopBounds[dim].size = getDimValue(builder, loc, output, dim);
+loopBounds[dim].stride = oneAttr;
+  }
+  return loopBounds;
+}
+
+SmallVector
+WinogradInputTransformOp::getLoopIteratorTypes() {
+  SmallVector iteratorTypes(6,
+ 
utils::IteratorType::parallel);
+  return iteratorTypes;
+}
+
+LogicalResult WinogradInputTransformOp::getResultTilePosition(
+OpBuilder &builder, unsigned resultNumber, ArrayRef offsets,
+ArrayRef sizes, SmallVector &resultOffsets,
+SmallVector &resultSizes) {
+  auto zeroAttr = builder.getI64IntegerAttr(0);
+  auto oneAttr = builder.getI64IntegerAttr(1);
+
+  resultOffsets.push_back(zeroAttr);
+  resultOffsets.push_back(zeroAttr);
+  resultOffsets.push_back(offsets[2]);
+  resultOffsets.push_back(offsets[3]);
+  resultOffsets.push_back(zeroAttr);
+  resultOffsets.push_back(zeroAttr);
+  resultSizes.push_back(sizes[0]);
+  resultSizes.push_back(sizes[1]);
+  resultSizes.push_back(oneAttr);
+  resultSizes.push_back(oneAttr);
+  resultSizes.push_back(sizes[4]);
+  resultSizes.push_back(sizes[5]);

ftynse wrote:

Nit: something like `resultOffsets.append({zeroAttr, zeroAttr, offsets[2], 
offsets[3], zeroAttr, zeroAttr})` may be more readable.

https://github.com/llvm/llvm-project/pull/96184
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][linalg] Implement TilingInterface for winograd operators (PR #96184)

2024-07-11 Thread Oleksandr Alex Zinenko via llvm-branch-commits

https://github.com/ftynse edited https://github.com/llvm/llvm-project/pull/96184
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][linalg] Implement TilingInterface for winograd operators (PR #96184)

2024-07-11 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -2810,9 +2819,117 @@ LogicalResult WinogradInputTransformOp::verify() {
   if (failed(verifyCompatibleShape(expectedOutputShape, outputShape))) {
 return emitOpError("the output shape is not expected");
   }
+
   return success();
 }
 
+SmallVector
+WinogradInputTransformOp::getIterationDomain(OpBuilder &builder) {
+  Location loc = getLoc();
+  auto indexType = builder.getIndexType();
+  auto zeroAttr = builder.getIntegerAttr(indexType, 0);
+  auto oneAttr = builder.getIntegerAttr(indexType, 1);
+  Value output = getOutput();
+  SmallVector loopBounds(6);
+  for (unsigned dim = 0; dim < 6; ++dim) {
+loopBounds[dim].offset = zeroAttr;
+loopBounds[dim].size = getDimValue(builder, loc, output, dim);
+loopBounds[dim].stride = oneAttr;
+  }
+  return loopBounds;
+}
+
+SmallVector
+WinogradInputTransformOp::getLoopIteratorTypes() {
+  SmallVector iteratorTypes(6,
+ 
utils::IteratorType::parallel);
+  return iteratorTypes;
+}
+
+LogicalResult WinogradInputTransformOp::getResultTilePosition(
+OpBuilder &builder, unsigned resultNumber, ArrayRef offsets,
+ArrayRef sizes, SmallVector &resultOffsets,
+SmallVector &resultSizes) {
+  auto zeroAttr = builder.getI64IntegerAttr(0);
+  auto oneAttr = builder.getI64IntegerAttr(1);
+
+  resultOffsets.push_back(zeroAttr);
+  resultOffsets.push_back(zeroAttr);
+  resultOffsets.push_back(offsets[2]);
+  resultOffsets.push_back(offsets[3]);
+  resultOffsets.push_back(zeroAttr);
+  resultOffsets.push_back(zeroAttr);
+  resultSizes.push_back(sizes[0]);
+  resultSizes.push_back(sizes[1]);
+  resultSizes.push_back(oneAttr);
+  resultSizes.push_back(oneAttr);
+  resultSizes.push_back(sizes[4]);
+  resultSizes.push_back(sizes[5]);
+
+  return success();
+}
+
+FailureOr
+WinogradInputTransformOp::getTiledImplementation(OpBuilder &builder,
+ ArrayRef 
offsets,
+ ArrayRef sizes) 
{
+  auto oneAttr = builder.getI64IntegerAttr(1);
+  auto zeroAttr = builder.getI64IntegerAttr(0);
+  Value input = getInput();
+  auto inputType = cast(input.getType());
+  auto inputShape = inputType.getShape();
+  int64_t inputH = inputShape[1];
+  int64_t inputW = inputShape[2];
+  int64_t m = getM();
+  int64_t r = getR();
+  int64_t alpha = m + r - 1;
+  int64_t alphaH = inputH != 1 ? alpha : 1;
+  int64_t alphaW = inputW != 1 ? alpha : 1;
+  auto alphaHAttr = builder.getI64IntegerAttr(alphaH);
+  auto alphaWAttr = builder.getI64IntegerAttr(alphaW);
+
+  Location loc = getLoc();
+  SmallVector tiledOperands;
+  SmallVector sliceOffsets, sliceSizes;
+
+  auto context = builder.getContext();
+  auto affineMap =
+  AffineMap::get(1, 0, {builder.getAffineDimExpr(0) * m}, context);
+  Value mappedOffset1 = builder.create(
+  loc, affineMap, getValueFromOpFoldResult(offsets[2], builder, loc));
+  Value mappedOffset2 = builder.create(
+  loc, affineMap, getValueFromOpFoldResult(offsets[3], builder, loc));
+
+  sliceOffsets.push_back(zeroAttr);
+  sliceOffsets.push_back(mappedOffset1);
+  sliceOffsets.push_back(mappedOffset2);
+  sliceOffsets.push_back(zeroAttr);
+  sliceSizes.push_back(sizes[4]);
+  sliceSizes.push_back(alphaHAttr);
+  sliceSizes.push_back(alphaWAttr);
+  sliceSizes.push_back(sizes[5]);
+  SmallVector inputStrides(4, oneAttr);
+  tiledOperands.emplace_back(builder.create(
+  loc, getInput(), sliceOffsets, sliceSizes, inputStrides));
+
+  sliceOffsets.clear();
+  sliceSizes.clear();

ftynse wrote:

I'd rather declare new vectors for this.

https://github.com/llvm/llvm-project/pull/96184
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][linalg] Implement TilingInterface for winograd operators (PR #96184)

2024-07-11 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -2810,9 +2819,117 @@ LogicalResult WinogradInputTransformOp::verify() {
   if (failed(verifyCompatibleShape(expectedOutputShape, outputShape))) {
 return emitOpError("the output shape is not expected");
   }
+
   return success();
 }
 
+SmallVector
+WinogradInputTransformOp::getIterationDomain(OpBuilder &builder) {
+  Location loc = getLoc();
+  auto indexType = builder.getIndexType();
+  auto zeroAttr = builder.getIntegerAttr(indexType, 0);
+  auto oneAttr = builder.getIntegerAttr(indexType, 1);
+  Value output = getOutput();
+  SmallVector loopBounds(6);
+  for (unsigned dim = 0; dim < 6; ++dim) {
+loopBounds[dim].offset = zeroAttr;
+loopBounds[dim].size = getDimValue(builder, loc, output, dim);
+loopBounds[dim].stride = oneAttr;
+  }
+  return loopBounds;
+}
+
+SmallVector
+WinogradInputTransformOp::getLoopIteratorTypes() {
+  SmallVector iteratorTypes(6,
+ 
utils::IteratorType::parallel);
+  return iteratorTypes;
+}
+
+LogicalResult WinogradInputTransformOp::getResultTilePosition(
+OpBuilder &builder, unsigned resultNumber, ArrayRef offsets,
+ArrayRef sizes, SmallVector &resultOffsets,
+SmallVector &resultSizes) {
+  auto zeroAttr = builder.getI64IntegerAttr(0);
+  auto oneAttr = builder.getI64IntegerAttr(1);
+
+  resultOffsets.push_back(zeroAttr);
+  resultOffsets.push_back(zeroAttr);
+  resultOffsets.push_back(offsets[2]);
+  resultOffsets.push_back(offsets[3]);
+  resultOffsets.push_back(zeroAttr);
+  resultOffsets.push_back(zeroAttr);
+  resultSizes.push_back(sizes[0]);
+  resultSizes.push_back(sizes[1]);
+  resultSizes.push_back(oneAttr);
+  resultSizes.push_back(oneAttr);
+  resultSizes.push_back(sizes[4]);
+  resultSizes.push_back(sizes[5]);
+
+  return success();
+}
+
+FailureOr
+WinogradInputTransformOp::getTiledImplementation(OpBuilder &builder,
+ ArrayRef 
offsets,
+ ArrayRef sizes) 
{
+  auto oneAttr = builder.getI64IntegerAttr(1);
+  auto zeroAttr = builder.getI64IntegerAttr(0);
+  Value input = getInput();
+  auto inputType = cast(input.getType());
+  auto inputShape = inputType.getShape();
+  int64_t inputH = inputShape[1];
+  int64_t inputW = inputShape[2];
+  int64_t m = getM();
+  int64_t r = getR();
+  int64_t alpha = m + r - 1;
+  int64_t alphaH = inputH != 1 ? alpha : 1;
+  int64_t alphaW = inputW != 1 ? alpha : 1;
+  auto alphaHAttr = builder.getI64IntegerAttr(alphaH);
+  auto alphaWAttr = builder.getI64IntegerAttr(alphaW);
+
+  Location loc = getLoc();
+  SmallVector tiledOperands;
+  SmallVector sliceOffsets, sliceSizes;
+
+  auto context = builder.getContext();
+  auto affineMap =
+  AffineMap::get(1, 0, {builder.getAffineDimExpr(0) * m}, context);
+  Value mappedOffset1 = builder.create(
+  loc, affineMap, getValueFromOpFoldResult(offsets[2], builder, loc));
+  Value mappedOffset2 = builder.create(
+  loc, affineMap, getValueFromOpFoldResult(offsets[3], builder, loc));
+
+  sliceOffsets.push_back(zeroAttr);
+  sliceOffsets.push_back(mappedOffset1);
+  sliceOffsets.push_back(mappedOffset2);
+  sliceOffsets.push_back(zeroAttr);
+  sliceSizes.push_back(sizes[4]);
+  sliceSizes.push_back(alphaHAttr);
+  sliceSizes.push_back(alphaWAttr);
+  sliceSizes.push_back(sizes[5]);
+  SmallVector inputStrides(4, oneAttr);
+  tiledOperands.emplace_back(builder.create(
+  loc, getInput(), sliceOffsets, sliceSizes, inputStrides));
+
+  sliceOffsets.clear();
+  sliceSizes.clear();
+  if (failed(getResultTilePosition(builder, 1, offsets, sizes, sliceOffsets,
+   sliceSizes)))
+return failure();
+
+  SmallVector outputStrides(6, oneAttr);
+  tiledOperands.emplace_back(builder.create(
+  loc, getOutput(), sliceOffsets, sliceSizes, outputStrides));
+
+  SmallVector resultTypes;

ftynse wrote:

```suggestion
  SmallVector resultTypes;
```

https://github.com/llvm/llvm-project/pull/96184
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][linalg] Implement TilingInterface for winograd operators (PR #96184)

2024-07-11 Thread Oleksandr Alex Zinenko via llvm-branch-commits

https://github.com/ftynse commented:

Looks okay to me in general. Something went wrong with rebases so I see code 
that doesn't belong to this change. Let me know when you merged the bases and I 
can click-approve this one.

https://github.com/llvm/llvm-project/pull/96184
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][linalg] Implement TilingInterface for winograd operators (PR #96184)

2024-07-11 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -2776,6 +2776,15 @@ LogicalResult WinogradFilterTransformOp::verify() {
 // WinogradInputTransformOp
 
//===--===//
 
+Value getValueFromOpFoldResult(OpFoldResult opFoldResult, OpBuilder &builder,
+   Location loc) {
+  if (auto attr = opFoldResult.dyn_cast()) {
+auto intAttr = cast(attr);
+return builder.create(loc, intAttr);
+  }
+  return opFoldResult.get();
+}

ftynse wrote:

https://github.com/llvm/llvm-project/blob/main/mlir/include/mlir/Dialect/Arith/Utils/Utils.h#L68-L72
 it already exists

https://github.com/llvm/llvm-project/pull/96184
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][linalg] Implement TilingInterface for winograd operators (PR #96184)

2024-07-11 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -2810,9 +2819,117 @@ LogicalResult WinogradInputTransformOp::verify() {
   if (failed(verifyCompatibleShape(expectedOutputShape, outputShape))) {
 return emitOpError("the output shape is not expected");
   }
+
   return success();
 }
 
+SmallVector
+WinogradInputTransformOp::getIterationDomain(OpBuilder &builder) {
+  Location loc = getLoc();
+  auto indexType = builder.getIndexType();
+  auto zeroAttr = builder.getIntegerAttr(indexType, 0);
+  auto oneAttr = builder.getIntegerAttr(indexType, 1);
+  Value output = getOutput();
+  SmallVector loopBounds(6);
+  for (unsigned dim = 0; dim < 6; ++dim) {
+loopBounds[dim].offset = zeroAttr;
+loopBounds[dim].size = getDimValue(builder, loc, output, dim);
+loopBounds[dim].stride = oneAttr;
+  }
+  return loopBounds;
+}
+
+SmallVector
+WinogradInputTransformOp::getLoopIteratorTypes() {
+  SmallVector iteratorTypes(6,
+ 
utils::IteratorType::parallel);
+  return iteratorTypes;
+}
+
+LogicalResult WinogradInputTransformOp::getResultTilePosition(
+OpBuilder &builder, unsigned resultNumber, ArrayRef offsets,
+ArrayRef sizes, SmallVector &resultOffsets,
+SmallVector &resultSizes) {
+  auto zeroAttr = builder.getI64IntegerAttr(0);
+  auto oneAttr = builder.getI64IntegerAttr(1);
+
+  resultOffsets.push_back(zeroAttr);
+  resultOffsets.push_back(zeroAttr);
+  resultOffsets.push_back(offsets[2]);
+  resultOffsets.push_back(offsets[3]);
+  resultOffsets.push_back(zeroAttr);
+  resultOffsets.push_back(zeroAttr);
+  resultSizes.push_back(sizes[0]);
+  resultSizes.push_back(sizes[1]);
+  resultSizes.push_back(oneAttr);
+  resultSizes.push_back(oneAttr);
+  resultSizes.push_back(sizes[4]);
+  resultSizes.push_back(sizes[5]);
+
+  return success();
+}
+
+FailureOr
+WinogradInputTransformOp::getTiledImplementation(OpBuilder &builder,
+ ArrayRef 
offsets,
+ ArrayRef sizes) 
{
+  auto oneAttr = builder.getI64IntegerAttr(1);
+  auto zeroAttr = builder.getI64IntegerAttr(0);
+  Value input = getInput();
+  auto inputType = cast(input.getType());
+  auto inputShape = inputType.getShape();

ftynse wrote:

Here and below.

https://github.com/llvm/llvm-project/pull/96184
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][Transform] `apply_conversion_patterns`: Update handles (PR #83950)

2024-03-05 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -632,7 +663,11 @@ LogicalResult 
transform::ApplyConversionPatternsOp::verify() {
 
 void transform::ApplyConversionPatternsOp::getEffects(
 SmallVectorImpl &effects) {
-  transform::consumesHandle(getTarget(), effects);
+  if (!getPreserveHandles()) {
+transform::consumesHandle(getTarget(), effects);
+  } else {
+transform::onlyReadsHandle(getTarget(), effects);
+  }

ftynse wrote:

Nit: I don't recall if dialect conversion could rewrite the top-level op or 
not. If it can, it may need to still consume the handle...

https://github.com/llvm/llvm-project/pull/83950
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][Transform] `apply_conversion_patterns`: Update handles (PR #83950)

2024-03-05 Thread Oleksandr Alex Zinenko via llvm-branch-commits

https://github.com/ftynse edited https://github.com/llvm/llvm-project/pull/83950
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][Transform] `apply_conversion_patterns`: Update handles (PR #83950)

2024-03-05 Thread Oleksandr Alex Zinenko via llvm-branch-commits

https://github.com/ftynse approved this pull request.


https://github.com/llvm/llvm-project/pull/83950
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][Transform] `apply_conversion_patterns`: Update handles (PR #83950)

2024-03-05 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -190,19 +190,29 @@ def ApplyConversionPatternsOp : 
TransformDialectOp<"apply_conversion_patterns",
 The `legal_ops`, `illegal_ops`, `legal_dialects`, `illegal_dialects`
 attributes specify the conversion target.
 
-This transform consumes the `target` handle and modifies the payload. It
-does not produce any handles.
+This transform modifies the payload. By default, it consumes the `target`
+handle. It does not produce any handles.
+
+If the `preserve_handles` attribute is set, this transform does not consume
+the `target` handle and instead updates handles based on notifications from
+a tracking listener that is attached to the dialect conversion, similar to
+`transform.apply_patterns`. Only replacements via `RewriterBase::replaceOp`
+or `replaceOpWithNewOp` are considered "payload op replacements". In
+contrast to `transform.apply_patterns`, we allow replacement ops even if 
the

ftynse wrote:

Nit: could you provide the rationale as to why op name change is allowed here? 
Presumably because conversion is expected to intentionally change names to 
another dialect.

https://github.com/llvm/llvm-project/pull/83950
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] release/18.x: [MLIR] [Transforms] Let `transform.structured.convert_to_loops` return handles to loops (#83984) (PR #85942)

2024-03-29 Thread Oleksandr Alex Zinenko via llvm-branch-commits

ftynse wrote:

https://github.com/llvm/llvm-project/commit/0597644a6466ae9148b0b41cb8f95d5022e045c2
 looks like a bugfix, but 
https://github.com/llvm/llvm-project/commit/47bc565ca7990a2de20af4030baf08ac62739aca
 is a arguably a new feature and likely should not be backported. What is the 
reason for backporting the latter? 

https://github.com/llvm/llvm-project/pull/85942
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] release/18.x: [mlir][transform] replace original op to loop ops (#83537) (PR #87080)

2024-03-29 Thread Oleksandr Alex Zinenko via llvm-branch-commits

https://github.com/ftynse approved this pull request.


https://github.com/llvm/llvm-project/pull/87080
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [MLIR] Add apply_patterns.vector.arm_sve.lower_contraction TD Op (PR #140572)

2025-05-20 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -93,3 +99,15 @@ func.func @test_vector_contract_to_usmmla(
 
   return %2 : vector<4x[4]xi32>
 }
+
+module attributes {transform.with_named_sequence} {
+  transform.named_sequence @__transform_main(%module: !transform.any_op 
{transform.readonly}) {
+%func = transform.structured.match ops{["func.func"]} in %module : 
(!transform.any_op) -> !transform.op<"func.func">
+  
+transform.apply_patterns to %func {
+  transform.apply_patterns.vector.arm_sve.lower_contraction
+} : !transform.op<"func.func">
+
+transform.yield
+  }
+}

ftynse wrote:

Nit: trailing newline please (may require configuring your editor 
appropriately).

https://github.com/llvm/llvm-project/pull/140572
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [MLIR] Add apply_patterns.vector.arm_sve.lower_contraction TD Op (PR #140572)

2025-05-20 Thread Oleksandr Alex Zinenko via llvm-branch-commits

https://github.com/ftynse approved this pull request.


https://github.com/llvm/llvm-project/pull/140572
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir] NFC - refactor id builder and avoid leaking impl details (PR #146922)

2025-07-04 Thread Oleksandr Alex Zinenko via llvm-branch-commits

https://github.com/ftynse approved this pull request.


https://github.com/llvm/llvm-project/pull/146922
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][SCF][GPU] Add DeviceMaskingAttrInterface support to scf::Foral… (PR #146943)

2025-07-04 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -744,8 +758,7 @@ static DiagnosedSilenceableFailure
 getThreadIdBuilder(std::optional transformOp,
scf::ForallOp forallOp, ArrayRef blockSizes,
int64_t warpSize, GpuIdBuilder &gpuIdBuilder) {
-  auto mappingAttr = cast(
-  forallOp.getMapping()->getValue().front());
+  auto mappingAttr = forallOp.getDeviceMappingAttrs().front();

ftynse wrote:

Nit: now that there's no more cast on the RHS, please expand `auto`.

https://github.com/llvm/llvm-project/pull/146943
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][SCF][GPU] Add DeviceMaskingAttrInterface support to scf::Foral… (PR #146943)

2025-07-04 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -78,7 +78,8 @@ struct GpuIdBuilder {
 /// If `useLinearMapping` is true, the `idBuilder` method returns nD values
 /// used for indexing rewrites as well as 1D sizes for predicate generation.
 struct GpuBlockIdBuilder : public GpuIdBuilder {
-  GpuBlockIdBuilder(MLIRContext *ctx, bool useLinearMapping = false);

ftynse wrote:

Could you please the comments above to reflect this new argument? Here and 
below.

https://github.com/llvm/llvm-project/pull/146943
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][SCF][GPU] Add DeviceMaskingAttrInterface support to scf::Foral… (PR #146943)

2025-07-04 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -60,8 +60,51 @@ def DeviceMappingAttrInterface : 
AttrInterface<"DeviceMappingAttrInterface"> {
   ];
 }
 
+def DeviceMaskingAttrInterface : AttrInterface<"DeviceMaskingAttrInterface"> {
+  let cppNamespace = "::mlir";
+  let description = [{
+Attribute interface describing how to filter the processing units that a
+region is mapped to.
+
+A popcount can be applied to determine the logical linear index that a
+physical processing unit is responsible for.
+  }];
+
+ let methods = [
+InterfaceMethod<
+  /*desc=*/[{
+Return the logical active id for a given physical id.
+Expects a physicalLinearMappingId of I64Type.
+  }],
+  /*retTy=*/"Value",
+  /*methodName=*/"getLogicalLinearMappingId",
+  /*args=*/(ins "OpBuilder&":$builder, "Value":$physicalLinearMappingId)
+>,
+InterfaceMethod<
+  /*desc=*/[{
+Return the dynamic condition determining whether a given physical id is
+active under the mask.
+Expects a physicalLinearMappingId of I64Type.
+  }],
+  /*retTy=*/"Value",
+  /*methodName=*/"getIsActiveIdPredicate",
+  /*args=*/(ins "OpBuilder&":$builder, "Value":$physicalLinearMappingId)
+>,
+InterfaceMethod<
+  /*desc=*/[{
+Return the maximal number of pysical ids supported.

ftynse wrote:

```suggestion
Return the maximal number of physical ids supported.
```

https://github.com/llvm/llvm-project/pull/146943
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][SCF][GPU] Add DeviceMaskingAttrInterface support to scf::Foral… (PR #146943)

2025-07-04 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -60,8 +60,51 @@ def DeviceMappingAttrInterface : 
AttrInterface<"DeviceMappingAttrInterface"> {
   ];
 }
 
+def DeviceMaskingAttrInterface : AttrInterface<"DeviceMaskingAttrInterface"> {
+  let cppNamespace = "::mlir";
+  let description = [{
+Attribute interface describing how to filter the processing units that a
+region is mapped to.
+
+A popcount can be applied to determine the logical linear index that a
+physical processing unit is responsible for.
+  }];
+
+ let methods = [
+InterfaceMethod<
+  /*desc=*/[{
+Return the logical active id for a given physical id.
+Expects a physicalLinearMappingId of I64Type.
+  }],
+  /*retTy=*/"Value",
+  /*methodName=*/"getLogicalLinearMappingId",

ftynse wrote:

Optional naming nit: `bulidFoo` or `createFoo` instead of `getFoo` will make it 
clearer that some IR is being constructed.

https://github.com/llvm/llvm-project/pull/146943
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][SCF][GPU] Add DeviceMaskingAttrInterface support to scf::Foral… (PR #146943)

2025-07-04 Thread Oleksandr Alex Zinenko via llvm-branch-commits


@@ -60,8 +60,51 @@ def DeviceMappingAttrInterface : 
AttrInterface<"DeviceMappingAttrInterface"> {
   ];
 }
 
+def DeviceMaskingAttrInterface : AttrInterface<"DeviceMaskingAttrInterface"> {
+  let cppNamespace = "::mlir";
+  let description = [{
+Attribute interface describing how to filter the processing units that a
+region is mapped to.
+
+A popcount can be applied to determine the logical linear index that a
+physical processing unit is responsible for.
+  }];

ftynse wrote:

Could you please document what is understood by physical and logical ID here 
and how either of those can be linear.

https://github.com/llvm/llvm-project/pull/146943
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir][SCF][GPU] Add DeviceMaskingAttrInterface support to scf::Foral… (PR #146943)

2025-07-04 Thread Oleksandr Alex Zinenko via llvm-branch-commits

https://github.com/ftynse edited 
https://github.com/llvm/llvm-project/pull/146943
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


  1   2   >