forked from OSchip/llvm-project
Introduce custom format for the LLVM IR Dialect
Historically, the LLVM IR dialect has been using the generic form of MLIR operation syntax. It is verbose and often redundant. Introduce the custom printing and parsing for all existing operations in the LLVM IR dialect. Update the relevant documentation and tests. -- PiperOrigin-RevId: 241617393
This commit is contained in:
parent
04f766c2ed
commit
736bef7386
|
@ -207,21 +207,21 @@ func @bar() {
|
|||
|
||||
func @foo(%arg0: !llvm.type<"i32">, %arg1: !llvm.type<"i64">) -> !llvm.type<"{i32, i64}"> {
|
||||
// insert the vales into a structure
|
||||
%0 = "llvm.undef"() : () -> !llvm.type<"{i32, i64}">
|
||||
%1 = "llvm.insertvalue"(%arg0, %0) {position: [0]} : (!llvm.type<"i32">, !llvm.type<"{i32, i64}">) -> !llvm.type<"{i32, i64}">
|
||||
%2 = "llvm.insertvalue"(%arg1, %1) {position: [1]} : (!llvm.type<"i64">, !llvm.type<"{i32, i64}">) -> !llvm.type<"{i32, i64}">
|
||||
%0 = llvm.undef : !llvm.type<"{i32, i64}">
|
||||
%1 = llvm.insertvalue %arg0, %0[0] : !llvm.type<"{i32, i64}">
|
||||
%2 = llvm.insertvalue %arg1, %1[1] : !llvm.type<"{i32, i64}">
|
||||
|
||||
// return the structure value
|
||||
"llvm.return"(%2) : !llvm.type<"{i32, i64}"> -> ()
|
||||
llvm.return %2 : !llvm.type<"{i32, i64}">
|
||||
}
|
||||
func @bar() {
|
||||
%0 = "llvm.constant" {value: 42} : !llvm.type<"i32">
|
||||
%1 = "llvm.constant" {value: 17} : !llvm.type<"i64">
|
||||
%0 = llvm.constant(42 : i32) : !llvm.type<"i32">
|
||||
%1 = llvm.constant(17) : !llvm.type<"i64">
|
||||
|
||||
// call and extract the values from the structure
|
||||
%2 = "llvm.call"(%0, %1) {callee: @bar} : (%arg0: !llvm.type<"i32">, %arg1: !llvm.type<"i64">) -> !llvm.type<"{i32, i64}">
|
||||
%3 = "llvm.extractvalue"(%2) {position: [0]} : (!llvm.type<"{i32, i64}"> -> !llvm.type<"i32">
|
||||
%4 = "llvm.extractvalue"(%2) {position: [1]} : (!llvm.type<"{i32, i64}"> -> !llvm.type<"i64">
|
||||
%2 = llvm.call @bar(%0, %1) : (%arg0: !llvm.type<"i32">, %arg1: !llvm.type<"i64">) -> !llvm.type<"{i32, i64}">
|
||||
%3 = llvm.extractvalue %2[0] : !llvm.type<"{i32, i64}">
|
||||
%4 = llvm.extractvalue %2[1] : !llvm.type<"{i32, i64}">
|
||||
|
||||
// use as before
|
||||
"use_i32"(%3) : (!llvm.type<"i32">) -> ()
|
||||
|
@ -264,11 +264,11 @@ leads to a new basic block being inserted,
|
|||
before the conversion to the LLVM IR dialect:
|
||||
|
||||
```mlir {.mlir}
|
||||
"llvm.cond_br"(%0)[^bb1(%1 : !llvm.type<"i32">), ^dummy] : (!llvm.type<"i1">) -> ()
|
||||
llvm.cond_br %0, ^bb1(%1 : !llvm.type<"i32">), ^dummy
|
||||
^bb1(%3 : !llvm.type<"i32">):
|
||||
"use"(%3) : (!llvm.type<"i32">) -> ()
|
||||
^dummy:
|
||||
"llvm.br"()[^bb1(%2 : !llvm.type<"i32">)] : () -> ()
|
||||
llvm.br ^bb1(%2 : !llvm.type<"i32">)
|
||||
```
|
||||
|
||||
## Memref Model
|
||||
|
@ -308,7 +308,7 @@ An access to a zero-dimensional memref is converted into a plain load:
|
|||
%0 = load %m[] : memref<f32>
|
||||
|
||||
// after
|
||||
%0 = "llvm.load"(%m) : (!llvm.type<"float*">) -> (!llvm.type<"float">)
|
||||
%0 = llvm.load %m : !llvm.type<"float*">
|
||||
```
|
||||
|
||||
An access to a memref with indices:
|
||||
|
@ -321,34 +321,34 @@ is transformed into the equivalent of the following code:
|
|||
|
||||
```mlir {.mlir}
|
||||
// obtain the buffer pointer
|
||||
%b = "llvm.extractvalue"(%m) {position: [0]} : (!llvm.type<"{float*, i64, i64}">) -> !llvm.type<"float*">
|
||||
%b = llvm.extractvalue %m[0] : !llvm.type<"{float*, i64, i64}">
|
||||
|
||||
// obtain the components for the index
|
||||
%sub1 = "llvm.constant" {value: 1} : () -> !llvm.type<"i64"> // first subscript
|
||||
%sz2 = "llvm.extractvalue"(%m) {position: [1]}
|
||||
: (!llvm.type<"{float*, i64, i64}">) -> !llvm.type<"float*"> // second size (dynamic, second descriptor element)
|
||||
%sub2 = "llvm.constant" {value: 2} : () -> !llvm.type<"i64"> // second subscript
|
||||
%sz3 = "llvm.constant" {value: 13} : () -> !llvm.type<"i64"> // third size (static)
|
||||
%sub3 = "llvm.constant" {value: 3} : () -> !llvm.type<"i64"> // third subscript
|
||||
%sz4 = "llvm.extractvalue"(%m) {position: [1]}
|
||||
: (!llvm.type<"{float*, i64, i64}">) -> !llvm.type<"float*"> // fourth size (dynamic, third descriptor element)
|
||||
%sub4 = "llvm.constant" {value: 4} : () -> !llvm.type<"i64"> // fourth subscript
|
||||
%sub1 = llvm.constant(1) : !llvm.type<"i64"> // first subscript
|
||||
%sz2 = llvm.extractvalue %m[1]
|
||||
: !llvm.type<"{float*, i64, i64}"> // second size (dynamic, second descriptor element)
|
||||
%sub2 = llvm.constant(2) : !llvm.type<"i64"> // second subscript
|
||||
%sz3 = llvm.constant(13) : !llvm.type<"i64"> // third size (static)
|
||||
%sub3 = llvm.constant(3) : !llvm.type<"i64"> // third subscript
|
||||
%sz4 = llvm.extractvalue %m[1]
|
||||
: !llvm.type<"{float*, i64, i64}"> // fourth size (dynamic, third descriptor element)
|
||||
%sub4 = llvm.constant(4) : !llvm.type<"i64"> // fourth subscript
|
||||
|
||||
// compute the linearized index
|
||||
// %sub4 + %sub3 * %sz4 + %sub2 * (%sz3 * %sz4) + %sub1 * (%sz2 * %sz3 * %sz4) =
|
||||
// = ((%sub1 * %sz2 + %sub2) * %sz3 + %sub3) * %sz4 + %sub4
|
||||
%idx0 = "llvm.mul"(%sub1, %sz2) : (!llvm.type<"i64">, !llvm.type<"i64">) -> !llvm.type<"i64">
|
||||
%idx1 = "llvm.add"(%idx0, %sub2) : (!llvm.type<"i64">, !llvm.type<"i64">) -> !llvm.type<"i64">
|
||||
%idx2 = "llvm.mul"(%idx1, %sz3) : (!llvm.type<"i64">, !llvm.type<"i64">) -> !llvm.type<"i64">
|
||||
%idx3 = "llvm.add"(%idx2, %sub3) : (!llvm.type<"i64">, !llvm.type<"i64">) -> !llvm.type<"i64">
|
||||
%idx4 = "llvm.mul"(%idx3, %sz4) : (!llvm.type<"i64">, !llvm.type<"i64">) -> !llvm.type<"i64">
|
||||
%idx5 = "llvm.add"(%idx4, %sub4) : (!llvm.type<"i64">, !llvm.type<"i64">) -> !llvm.type<"i64">
|
||||
%idx0 = llvm.mul %sub1, %sz2 : !llvm.type<"i64">
|
||||
%idx1 = llvm.add %idx0, %sub : !llvm.type<"i64">
|
||||
%idx2 = llvm.mul %idx1, %sz3 : !llvm.type<"i64">
|
||||
%idx3 = llvm.add %idx2, %sub3 : !llvm.type<"i64">
|
||||
%idx4 = llvm.mul %idx3, %sz4 : !llvm.type<"i64">
|
||||
%idx5 = llvm.add %idx4, %sub4 : !llvm.type<"i64">
|
||||
|
||||
// obtain the element address
|
||||
%a = "llvm.getelementptr"(%b, %idx5) : (!llvm.type<"float*">, !llvm.type<"i64">) -> !llvm.type<"float*">
|
||||
%a = llvm.getelementptr %b[%idx5] : (!llvm.type<"float*">, !llvm.type<"i64">) -> !llvm.type<"float*">
|
||||
|
||||
// perform the actual load
|
||||
%0 = "llvm.load"(%a) : (!llvm.type<"float*">) -> !llvm.type<"float">
|
||||
%0 = llvm.load %a : !llvm.type<"float*">
|
||||
```
|
||||
|
||||
In practice, the subscript and size extraction will be interleaved with the
|
||||
|
|
|
@ -47,9 +47,8 @@ specific LLVM IR type.
|
|||
|
||||
## Operations {#operations}
|
||||
|
||||
All operations in the LLVM IR dialect use the generic (verbose) form of MLIR
|
||||
operations. The mnemonic of an operation is that used in LLVM IR prefixed with
|
||||
"`llvm.`".
|
||||
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.`".
|
||||
|
||||
### LLVM IR operations
|
||||
|
||||
|
@ -74,10 +73,10 @@ Examples:
|
|||
|
||||
```mlir {.mlir}
|
||||
// Integer addition.
|
||||
%0 = "llvm.add"(%a, %b) : (!llvm<"i32">, !llvm<"i32">) -> !llvm<"i32">
|
||||
%0 = llvm.add %a, %b : !llvm<"i32">
|
||||
|
||||
// Unsigned integer division.
|
||||
%1 = "llvm.udiv"(%a, %b) : (!llvm<"i32">, !llvm<"i32">) -> !llvm<"i32">
|
||||
%1 = llvm.udiv %a, %b : !llvm<"i32">
|
||||
```
|
||||
|
||||
#### Floating point binary arithmetic operations
|
||||
|
@ -95,16 +94,16 @@ Examples:
|
|||
|
||||
```mlir {.mlir}
|
||||
// Float addition.
|
||||
%0 = "llvm.fadd"(%a, %b) : (!llvm<"float">, !llvm<"float">) -> !llvm<"float">
|
||||
%0 = llvm.fadd %a, %b : !llvm<"float">
|
||||
|
||||
// Float division.
|
||||
%1 = "llvm.fdiv"(%a, %b) : (!llvm<"float">, !llvm<"float">) -> !llvm<"float">
|
||||
%1 = llvm.fdiv %a, %b : !llvm<"float">
|
||||
```
|
||||
|
||||
#### Memory-related operations
|
||||
|
||||
- `<r> = alloca <size>`
|
||||
- `<r> = getelementptr <address>, <index> (, <index>)+`
|
||||
- `<r> = alloca <size> x <type>`
|
||||
- `<r> = getelementptr <address>[<index> (, <index>)+]`
|
||||
- `<r> = load <address>`
|
||||
- `store <value>, <address>`
|
||||
|
||||
|
@ -120,45 +119,44 @@ Examples:
|
|||
|
||||
```mlir {.mlir}
|
||||
// Allocate an array of 4 floats on stack
|
||||
%c4 = "llvm.constant" {value: 4 : i64} : !llvm<"i64">
|
||||
%0 = "llvm.alloca"(%c4) : (!llvm<"i64">) -> !llvm<"float*">
|
||||
%c4 = llvm.constant(4) : !llvm<"i64">
|
||||
%0 = llvm.alloca %c4 x !llvm<"float"> : (!llvm<"i64">) -> !llvm<"float*">
|
||||
|
||||
// Get the second element of the array (note 0-based indexing).
|
||||
%c1 = "llvm.constant" {value: 1 : i64} : !llvm<"i64">
|
||||
%1 = "llvm.getelementptr"(%0, %c1) : (!llvm<"float*">, !llvm<"i64">)
|
||||
%c1 = llvm.constant(1) : !llvm<"i64">
|
||||
%1 = llvm.getelementptr %0[%c1] : (!llvm<"float*">, !llvm<"i64">)
|
||||
-> !llvm<"float*">
|
||||
|
||||
// Store a constant into this element.
|
||||
%cf = "llvm.constant" {value: 42.0 : f32} : !llvm<"float">
|
||||
"llvm.store" %cf, %1 : (!llvm<"float">, !llvm<"float*">) -> ()
|
||||
%cf = llvm.constant(42.0 : f32) : !llvm<"float">
|
||||
llvm.store %cf, %1 : !llvm<"float*">
|
||||
|
||||
// Load the value from this element.
|
||||
%3 = "llvm.load" %1 : (!llvm<"float*">) -> (!llvm<"float">)
|
||||
%3 = llvm.load %1 : !llvm<"float*">
|
||||
```
|
||||
|
||||
#### Operations on values of aggregate type.
|
||||
|
||||
- `<value> = extractvalue <struct> {position: [<index> (, <index>)+]}`
|
||||
- `<struct> = insertvalue <value>,<struct> {position: [<index> (, <index>)+]}`
|
||||
- `<value> = extractvalue <struct>[<index> (, <index>)+]`
|
||||
- `<struct> = insertvalue <value>, <struct>[<index> (, <index>)+]`
|
||||
|
||||
In these operations, `<struct>` must be a value of wrapped LLVM IR structure
|
||||
type and `<value>` must be a value that corresponds to one of the (nested)
|
||||
structure element types.
|
||||
|
||||
The `position` attribute is a mandatory array attribute containing integer
|
||||
attributes. It identifies the 0-based position of the element in the (nested)
|
||||
structure type.
|
||||
Note the use of integer literals to designate subscripts, which is made possbile
|
||||
by `extractvalue` and `insertvalue` must have constant subscripts. Internally,
|
||||
they are modeled as array attributes.
|
||||
|
||||
Examples:
|
||||
|
||||
```mlir {.mlir}
|
||||
// Get the value third element of the second element of a structure.
|
||||
%0 = "llvm.extractvalue"(%s) {position: [1, 2]} : (!llvm<"{i32, {i1, i8, i16}">) -> !llvm<"i16">
|
||||
%0 = llvm.extractvalue %s[1, 2] : !llvm<"{i32, {i1, i8, i16}">
|
||||
|
||||
// Insert the value to the third element of the second element of a structure.
|
||||
// Note that this returns a new structure-typed value.
|
||||
%1 = "llvm.insertvalue"(%0, %s) {position: [1, 2]} :
|
||||
(!llvm<"i16">, !llvm<"{i32, {i1, i8, i16}">) -> !llvm<"{i32, {i1, i8, i16}">
|
||||
%1 = llvm.insertvalue %0, %s[1, 2] : !llvm<"{i32, {i1, i8, i16}">
|
||||
```
|
||||
|
||||
#### Terminator operations.
|
||||
|
@ -185,21 +183,20 @@ Examples:
|
|||
```mlir {.mlir}
|
||||
// Branch without arguments.
|
||||
^bb0:
|
||||
"llvm.br"() [^bb0] : () -> ()
|
||||
llvm.br ^bb0
|
||||
|
||||
// Branch and pass arguments.
|
||||
^bb1(%arg: !llvm<"i32">):
|
||||
"llvm.br"() [^bb1(%arg : !llvm<"i32">)] : () -> ()
|
||||
llvm.br ^bb1(%arg : !llvm<"i32">)
|
||||
|
||||
// Conditionally branch and pass arguments to one of the blocks.
|
||||
"llvm.cond_br"(%cond) [^bb0, %bb1(%arg : !llvm<"i32">)] : (!llvm<"i1">) -> ()
|
||||
llvm.cond_br %cond, ^bb0, %bb1(%arg : !llvm<"i32">)
|
||||
|
||||
// It's okay to use the same block without arguments, but probably useless.
|
||||
"llvm.cond_br"(%cond) [^bb0, ^bb0] : (!llvm<"i1">) -> ()
|
||||
llvm.cond_br %cond, ^bb0, ^bb0
|
||||
|
||||
// ERROR: Passing different arguments to the same block in a conditional branch.
|
||||
"llvm.cond_br"(%cond) [^bb1(%0 : !llvm<"i32">),
|
||||
^bb1(%1 : !llvm<"i32">)] : (!llvm<"i1">) -> ()
|
||||
llvm.cond_br %cond, ^bb1(%0 : !llvm<"i32">), ^bb1(%1 : !llvm<"i32">)
|
||||
|
||||
```
|
||||
|
||||
|
@ -213,42 +210,41 @@ this behavior by providing a variadic `call` operation for 0- and 1-result
|
|||
functions. Even though MLIR supports multi-result functions, LLVM IR dialect
|
||||
disallows them.
|
||||
|
||||
The `call` operation supports both direct and indirect calls. Direct calls
|
||||
require the `callee` attribute of function type to be present. Otherwise, the
|
||||
call is considered indirect and expects the function as its first argument.
|
||||
The `call` instruction supports both direct and indirect calls. Direct calls
|
||||
start with a function name (`@`-prefixed) and indirect calls start with an SSA
|
||||
value (`%`-prefixed). The direct callee, if present, is stored as a function
|
||||
attribute `callee`. The trailing type of the instruction is always the MLIR
|
||||
function type, which may be different from the indirect callee that has the
|
||||
wrapped LLVM IR function type.
|
||||
|
||||
Examples:
|
||||
|
||||
```mlir {.mlir}
|
||||
// Direct call without arguments and with one result.
|
||||
%0 = "llvm.call"() {callee: @foo : () -> (!llvm<"float">)}
|
||||
: () -> (!llvm<"float">)
|
||||
%0 = llvm.call @foo() : () -> (!llvm<"float">)
|
||||
|
||||
// Direct call with arguments and without a result.
|
||||
"llvm.call"(%0) {callee: @bar : (!llvm<"float">) -> ()}
|
||||
: (!llvm<"float">) -> ()
|
||||
llvm.call @bar(%0) : (!llvm<"float">) -> ()
|
||||
|
||||
// Indirect call with an argument and without a result.
|
||||
"llvm.call"(%1, %0) : ((!llvm<"float">) -> (), !llvm<"float">) -> ()
|
||||
llvm.call %1(%0) : (!llvm<"float">) -> ()
|
||||
```
|
||||
|
||||
#### Miscellaneous operations.
|
||||
|
||||
Integer comparisons: `icmp <lhs>, <rhs> {predicate: <int>}`. The following
|
||||
predicate values are supported:
|
||||
Integer comparisons: `icmp "predicate" <lhs>, <rhs>`. The following predicate
|
||||
values are supported:
|
||||
|
||||
- `0` - equality comparison;
|
||||
- `1` - inequality comparison;
|
||||
- `2` - signed less-than comparison
|
||||
- `3` - signed less-than-or-equal comparison
|
||||
- `4` - signed greater-than comparison
|
||||
- `5` - signed greater-than-or-equal comparison
|
||||
- `6` - unsigned less-than comparison
|
||||
- `7` - unsigned less-than-or-equal comparison
|
||||
- `8` - unsigned greater-than comparison
|
||||
- `9` - unsigned greater-than-or-equal comparison
|
||||
|
||||
Note: these constant values correspond to those used by MLIR's `cmpi` operation.
|
||||
- `eq` - equality comparison;
|
||||
- `ne` - inequality comparison;
|
||||
- `slt` - signed less-than comparison
|
||||
- `sle` - signed less-than-or-equal comparison
|
||||
- `sgt` - signed greater-than comparison
|
||||
- `sge` - signed greater-than-or-equal comparison
|
||||
- `ult` - unsigned less-than comparison
|
||||
- `ule` - unsigned less-than-or-equal comparison
|
||||
- `ugt` - unsigned greater-than comparison
|
||||
- `uge` - unsigned greater-than-or-equal comparison
|
||||
|
||||
Bitwise reinterpretation: `bitcast <value>`.
|
||||
|
||||
|
@ -266,21 +262,25 @@ constants must be created as SSA values before being used in other operations.
|
|||
`llvm.constant` creates such values for scalars and vectors. It has a mandatory
|
||||
`value` attribute, which may be an integer, floating point attribute; splat,
|
||||
dense or sparse attribute containing integers or floats. The type of the
|
||||
attribute is one the corresponding MLIR standard types. The operation produces a
|
||||
new SSA value of the specified LLVM IR dialect type.
|
||||
attribute is one the corresponding MLIR standard types. It may be omitted for
|
||||
`i64` and `f64` types that are implied. The operation produces a new SSA value
|
||||
of the specified LLVM IR dialect type. The type of that value _must_ correspond
|
||||
to the attribute type converted to LLVM IR.
|
||||
|
||||
Examples:
|
||||
|
||||
```mlir {.mlir}
|
||||
// Integer constant
|
||||
%0 = "llvm.constant"() {value: 42 : i32} -> !llvm<"i32">
|
||||
// Integer constant, internal i32 is mandatory
|
||||
%0 = llvm.constant(42 : i32) : !llvm<"i32">
|
||||
|
||||
// Floating point constant
|
||||
%1 = "llvm.constant"() {value: 42.0 : f32} -> !llvm<"float">
|
||||
// It's okay to omit i64.
|
||||
%1 = llvm.constant(42) : !llvm<"i64">
|
||||
|
||||
// Splat vector constant
|
||||
%2 = "llvm.constant"() {value: splat<vector<4xf32>, 1.0>}
|
||||
-> !llvm<"<4 x float>">
|
||||
// Floating point constant.
|
||||
%2 = llvm.constant(42.0 : f32) : !llvm<"float">
|
||||
|
||||
// Splat vector constant,.
|
||||
%3 = llvm.constant(splat<vector<4xf32>, 1.0>) : !llvm<"<4 x float>">
|
||||
```
|
||||
|
||||
#### `llvm.undef` {#undef-operation}
|
||||
|
@ -294,5 +294,5 @@ Example:
|
|||
|
||||
```mlir {.mlir}
|
||||
// Create a structure with a 32-bit integer followed by a float.
|
||||
%0 = "llvm.undef"() -> !llvm<"{i32, float}">
|
||||
%0 = llvm.undef : !llvm<"{i32, float}">
|
||||
```
|
||||
|
|
|
@ -170,6 +170,15 @@ public:
|
|||
/// This parses... a comma!
|
||||
virtual bool parseComma() = 0;
|
||||
|
||||
/// Parse a `:` token.
|
||||
virtual bool parseColon() = 0;
|
||||
|
||||
/// Parse a '(' token.
|
||||
virtual bool parseLParen() = 0;
|
||||
|
||||
/// Parse a ')' token.
|
||||
virtual bool parseRParen() = 0;
|
||||
|
||||
/// This parses an equal(=) token!
|
||||
virtual bool parseEqual() = 0;
|
||||
|
||||
|
@ -270,6 +279,12 @@ public:
|
|||
/// be passed to resolveFunctionName when a function type is available.
|
||||
virtual bool parseFunctionName(StringRef &result, llvm::SMLoc &loc) = 0;
|
||||
|
||||
/// Parse a function name like '@foo` if present and return the name without
|
||||
/// the sigil in `result`. Return true if the next token is not a function
|
||||
/// name and keep `result` unchanged.
|
||||
virtual bool parseOptionalFunctionName(StringRef &result,
|
||||
llvm::SMLoc &loc) = 0;
|
||||
|
||||
/// This is the representation of an operand reference.
|
||||
struct OperandType {
|
||||
llvm::SMLoc location; // Location of the token.
|
||||
|
|
|
@ -135,7 +135,10 @@ class LLVM_ArithmeticOp<string mnemonic, string builderFunc,
|
|||
LLVM_OneResultOp<mnemonic,
|
||||
!listconcat([NoSideEffect, SameValueType], traits)>,
|
||||
Arguments<(ins LLVM_Type:$lhs, LLVM_Type:$rhs)>,
|
||||
LLVM_Builder<"$res = builder." # builderFunc # "($lhs, $rhs);">;
|
||||
LLVM_Builder<"$res = builder." # builderFunc # "($lhs, $rhs);"> {
|
||||
let parser = [{ return impl::parseBinaryOp(parser, result); }];
|
||||
let printer = [{ printLLVMBinaryOp(p, this->getOperation()); }];
|
||||
}
|
||||
|
||||
// Integer binary operations.
|
||||
def LLVM_AddOp : LLVM_ArithmeticOp<"add", "CreateAdd", [Commutative]>;
|
||||
|
@ -154,6 +157,8 @@ def LLVM_ICmpOp : LLVM_OneResultOp<"icmp", [NoSideEffect]>,
|
|||
$res = builder.CreateICmp(getLLVMCmpPredicate(
|
||||
static_cast<CmpIPredicate>($predicate.getZExtValue())), $lhs, $rhs);
|
||||
}];
|
||||
let parser = [{ return parseICmpOp(parser, result); }];
|
||||
let printer = [{ printICmpOp(p, *this); }];
|
||||
}
|
||||
|
||||
// Floating point binary operations.
|
||||
|
@ -169,20 +174,33 @@ def LLVM_AllocaOp : LLVM_OneResultOp<"alloca">,
|
|||
string llvmBuilder = [{
|
||||
$res = builder.CreateAlloca($_resultType, $arraySize);
|
||||
}];
|
||||
let parser = [{ return parseAllocaOp(parser, result); }];
|
||||
let printer = [{ printAllocaOp(p, *this); }];
|
||||
}
|
||||
def LLVM_GEPOp : LLVM_OneResultOp<"getelementptr", [NoSideEffect]>,
|
||||
Arguments<(ins LLVM_Type:$base, Variadic<LLVM_Type>:$indices)>,
|
||||
LLVM_Builder<"$res = builder.CreateGEP($base, $indices);">;
|
||||
LLVM_Builder<"$res = builder.CreateGEP($base, $indices);"> {
|
||||
let parser = [{ return parseGEPOp(parser, result); }];
|
||||
let printer = [{ printGEPOp(p, *this); }];
|
||||
}
|
||||
def LLVM_LoadOp : LLVM_OneResultOp<"load">, Arguments<(ins LLVM_Type:$addr)>,
|
||||
LLVM_Builder<"$res = builder.CreateLoad($addr);">;
|
||||
LLVM_Builder<"$res = builder.CreateLoad($addr);"> {
|
||||
let parser = [{ return parseLoadOp(parser, result); }];
|
||||
let printer = [{ printLoadOp(p, *this); }];
|
||||
}
|
||||
def LLVM_StoreOp : LLVM_ZeroResultOp<"store">,
|
||||
Arguments<(ins LLVM_Type:$value, LLVM_Type:$addr)>,
|
||||
LLVM_Builder<"builder.CreateStore($value, $addr);">;
|
||||
LLVM_Builder<"builder.CreateStore($value, $addr);"> {
|
||||
let parser = [{ return parseStoreOp(parser, result); }];
|
||||
let printer = [{ printStoreOp(p, *this); }];
|
||||
}
|
||||
def LLVM_BitcastOp
|
||||
: LLVM_OneResultOp<"bitcast", [NoSideEffect]>,
|
||||
Arguments<(ins LLVM_Type:$arg)>,
|
||||
LLVM_Builder<"$res = builder.CreateBitCast($arg, $_resultType);">;
|
||||
|
||||
LLVM_Builder<"$res = builder.CreateBitCast($arg, $_resultType);"> {
|
||||
let parser = [{ return parseBitcastOp(parser, result); }];
|
||||
let printer = [{ printBitcastOp(p, *this); }];
|
||||
}
|
||||
|
||||
// Call-related operations.
|
||||
def LLVM_CallOp : LLVM_Op<"call">,
|
||||
|
@ -196,6 +214,8 @@ def LLVM_CallOp : LLVM_Op<"call">,
|
|||
return emitOpError("must have 0 or 1 result");
|
||||
return success();
|
||||
}];
|
||||
let parser = [{ return parseCallOp(parser, result); }];
|
||||
let printer = [{ printCallOp(p, *this); }];
|
||||
}
|
||||
def LLVM_ExtractValueOp : LLVM_OneResultOp<"extractvalue", [NoSideEffect]>,
|
||||
Arguments<(ins LLVM_Type:$container,
|
||||
|
@ -203,6 +223,8 @@ def LLVM_ExtractValueOp : LLVM_OneResultOp<"extractvalue", [NoSideEffect]>,
|
|||
string llvmBuilder = [{
|
||||
$res = builder.CreateExtractValue($container, extractPosition($position));
|
||||
}];
|
||||
let parser = [{ return parseExtractValueOp(parser, result); }];
|
||||
let printer = [{ printExtractValueOp(p, *this); }];
|
||||
}
|
||||
def LLVM_InsertValueOp : LLVM_OneResultOp<"insertvalue", [NoSideEffect]>,
|
||||
Arguments<(ins LLVM_Type:$container, LLVM_Type:$value,
|
||||
|
@ -211,6 +233,8 @@ def LLVM_InsertValueOp : LLVM_OneResultOp<"insertvalue", [NoSideEffect]>,
|
|||
$res = builder.CreateInsertValue($container, $value,
|
||||
extractPosition($position));
|
||||
}];
|
||||
let parser = [{ return parseInsertValueOp(parser, result); }];
|
||||
let printer = [{ printInsertValueOp(p, *this); }];
|
||||
}
|
||||
|
||||
// Misc operations.
|
||||
|
@ -219,16 +243,24 @@ def LLVM_SelectOp
|
|||
Arguments<(ins LLVM_Type:$condition, LLVM_Type:$trueValue,
|
||||
LLVM_Type:$falseValue)>,
|
||||
LLVM_Builder<
|
||||
"$res = builder.CreateSelect($condition, $trueValue, $falseValue);">;
|
||||
"$res = builder.CreateSelect($condition, $trueValue, $falseValue);"> {
|
||||
let parser = [{ return parseSelectOp(parser, result); }];
|
||||
let printer = [{ printSelectOp(p, *this); }];
|
||||
}
|
||||
|
||||
// Terminators.
|
||||
def LLVM_BrOp : LLVM_TerminatorOp<"br", [NoSideEffect]>;
|
||||
def LLVM_BrOp : LLVM_TerminatorOp<"br", [NoSideEffect]> {
|
||||
let parser = [{ return parseBrOp(parser, result); }];
|
||||
let printer = [{ printBrOp(p, *this); }];
|
||||
}
|
||||
def LLVM_CondBrOp : LLVM_TerminatorOp<"cond_br", [NoSideEffect]> {
|
||||
let verifier = [{
|
||||
if (getNumSuccessors() != 2)
|
||||
return emitOpError("expected exactly two successors");
|
||||
return success();
|
||||
}];
|
||||
let parser = [{ return parseCondBrOp(parser, result); }];
|
||||
let printer = [{ printCondBrOp(p, *this); }];
|
||||
}
|
||||
def LLVM_ReturnOp : LLVM_TerminatorOp<"return", [NoSideEffect]> {
|
||||
string llvmBuilder = [{
|
||||
|
@ -243,15 +275,25 @@ def LLVM_ReturnOp : LLVM_TerminatorOp<"return", [NoSideEffect]> {
|
|||
return emitOpError("expects at most 1 operand");
|
||||
return success();
|
||||
}];
|
||||
|
||||
let parser = [{ return parseReturnOp(parser, result); }];
|
||||
let printer = [{ printReturnOp(p, *this); }];
|
||||
}
|
||||
|
||||
// Pseudo-operations (do not appear in LLVM IR but necessary for the dialect to
|
||||
// work correctly).
|
||||
def LLVM_UndefOp : LLVM_OneResultOp<"undef", [NoSideEffect]>,
|
||||
LLVM_Builder<"$res = llvm::UndefValue::get($_resultType);">;
|
||||
LLVM_Builder<"$res = llvm::UndefValue::get($_resultType);"> {
|
||||
let parser = [{ return parseUndefOp(parser, result); }];
|
||||
let printer = [{ printUndefOp(p, *this); }];
|
||||
}
|
||||
def LLVM_ConstantOp
|
||||
: LLVM_OneResultOp<"constant", [NoSideEffect]>,
|
||||
Arguments<(ins AnyAttr:$value)>,
|
||||
LLVM_Builder<"$res = getLLVMConstant($_resultType, $value, $_location);">;
|
||||
LLVM_Builder<"$res = getLLVMConstant($_resultType, $value, $_location);">
|
||||
{
|
||||
let parser = [{ return parseConstantOp(parser, result); }];
|
||||
let printer = [{ printConstantOp(p, *this); }];
|
||||
}
|
||||
|
||||
#endif // LLVMIR_OPS
|
||||
|
|
|
@ -20,11 +20,13 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "mlir/LLVMIR/LLVMDialect.h"
|
||||
#include "mlir/IR/Builders.h"
|
||||
#include "mlir/IR/MLIRContext.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "mlir/IR/StandardTypes.h"
|
||||
|
||||
#include "llvm/AsmParser/Parser.h"
|
||||
#include "llvm/IR/Attributes.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/Type.h"
|
||||
#include "llvm/Support/SourceMgr.h"
|
||||
|
||||
|
@ -60,7 +62,806 @@ llvm::Type *LLVMType::getUnderlyingType() const {
|
|||
return getImpl()->underlyingType;
|
||||
}
|
||||
|
||||
/*---- LLVM IR Dialect and its registration ----------------------------- */
|
||||
static void printLLVMBinaryOp(OpAsmPrinter *p, Operation *op) {
|
||||
// Fallback to the generic form if the op is not well-formed (may happen
|
||||
// during incomplete rewrites, and used for debugging).
|
||||
const auto *abstract = op->getAbstractOperation();
|
||||
assert(abstract && "pretty printing an unregistered operation");
|
||||
|
||||
auto resultType = op->getResult(0)->getType();
|
||||
if (resultType != op->getOperand(0)->getType() ||
|
||||
resultType != op->getOperand(1)->getType())
|
||||
return p->printGenericOp(op);
|
||||
|
||||
*p << op->getName().getStringRef() << ' ' << *op->getOperand(0) << ", "
|
||||
<< *op->getOperand(1);
|
||||
p->printOptionalAttrDict(op->getAttrs());
|
||||
*p << " : " << op->getResult(0)->getType();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Printing/parsing for LLVM::ICmpOp.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Return an array of mnemonics for ICmpPredicates indexed by its value.
|
||||
static const char *const *getICmpPredicateNames() {
|
||||
static const char *predicateNames[]{/*EQ*/ "eq",
|
||||
/*NE*/ "ne",
|
||||
/*SLT*/ "slt",
|
||||
/*SLE*/ "sle",
|
||||
/*SGT*/ "sgt",
|
||||
/*SGE*/ "sge",
|
||||
/*ULT*/ "ult",
|
||||
/*ULE*/ "ule",
|
||||
/*UGT*/ "ugt",
|
||||
/*UGE*/ "uge"};
|
||||
return predicateNames;
|
||||
};
|
||||
|
||||
// Returns a value of the ICmp predicate corresponding to the given mnemonic.
|
||||
// Returns -1 if there is no such mnemonic.
|
||||
static int getICmpPredicateByName(StringRef name) {
|
||||
return llvm::StringSwitch<int>(name)
|
||||
.Case("eq", 0)
|
||||
.Case("ne", 1)
|
||||
.Case("slt", 2)
|
||||
.Case("sle", 3)
|
||||
.Case("sgt", 4)
|
||||
.Case("sge", 5)
|
||||
.Case("ult", 6)
|
||||
.Case("ule", 7)
|
||||
.Case("ugt", 8)
|
||||
.Case("uge", 9)
|
||||
.Default(-1);
|
||||
}
|
||||
|
||||
static void printICmpOp(OpAsmPrinter *p, ICmpOp &op) {
|
||||
*p << op.getOperationName() << " \""
|
||||
<< getICmpPredicateNames()[op.predicate().getZExtValue()] << "\" "
|
||||
<< *op.getOperand(0) << ", " << *op.getOperand(1);
|
||||
p->printOptionalAttrDict(op.getAttrs(), {"predicate"});
|
||||
*p << " : " << op.lhs()->getType();
|
||||
}
|
||||
|
||||
// <operation> ::= `llvm.icmp` string-literal ssa-use `,` ssa-use
|
||||
// attribute-dict? `:` type
|
||||
static bool parseICmpOp(OpAsmParser *parser, OperationState *result) {
|
||||
Builder &builder = parser->getBuilder();
|
||||
|
||||
Attribute predicate;
|
||||
SmallVector<NamedAttribute, 4> attrs;
|
||||
OpAsmParser::OperandType lhs, rhs;
|
||||
Type type;
|
||||
llvm::SMLoc predicateLoc, trailingTypeLoc;
|
||||
if (parser->getCurrentLocation(&predicateLoc) ||
|
||||
parser->parseAttribute(predicate, "predicate", attrs) ||
|
||||
parser->parseOperand(lhs) || parser->parseComma() ||
|
||||
parser->parseOperand(rhs) || parser->parseOptionalAttributeDict(attrs) ||
|
||||
parser->parseColon() || parser->getCurrentLocation(&trailingTypeLoc) ||
|
||||
parser->parseType(type) ||
|
||||
parser->resolveOperand(lhs, type, result->operands) ||
|
||||
parser->resolveOperand(rhs, type, result->operands))
|
||||
return true;
|
||||
|
||||
// Replace the string attribute `predicate` with an integer attribute.
|
||||
auto predicateStr = predicate.dyn_cast<StringAttr>();
|
||||
if (!predicateStr)
|
||||
return parser->emitError(predicateLoc,
|
||||
"expected 'predicate' attribute of string type");
|
||||
int predicateValue = getICmpPredicateByName(predicateStr.getValue());
|
||||
if (predicateValue == -1)
|
||||
return parser->emitError(
|
||||
predicateLoc,
|
||||
"'" + Twine(predicateStr.getValue()) +
|
||||
"' is an incorrect value of the 'predicate' attribute");
|
||||
|
||||
attrs[0].second = parser->getBuilder().getI64IntegerAttr(predicateValue);
|
||||
|
||||
// The result type is either i1 or a vector type <? x i1> if the inputs are
|
||||
// vectors.
|
||||
LLVMDialect *dialect = static_cast<LLVMDialect *>(
|
||||
builder.getContext()->getRegisteredDialect("llvm"));
|
||||
llvm::Type *llvmResultType = llvm::Type::getInt1Ty(dialect->getLLVMContext());
|
||||
auto argType = type.dyn_cast<LLVM::LLVMType>();
|
||||
if (!argType)
|
||||
return parser->emitError(trailingTypeLoc, "expected LLVM IR dialect type");
|
||||
if (argType.getUnderlyingType()->isVectorTy())
|
||||
llvmResultType = llvm::VectorType::get(
|
||||
llvmResultType, argType.getUnderlyingType()->getVectorNumElements());
|
||||
auto resultType = builder.getType<LLVM::LLVMType>(llvmResultType);
|
||||
|
||||
result->attributes = attrs;
|
||||
result->addTypes({resultType});
|
||||
return false;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Printing/parsing for LLVM::AllocaOp.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static void printAllocaOp(OpAsmPrinter *p, AllocaOp &op) {
|
||||
auto *llvmPtrTy = op.getType().cast<LLVM::LLVMType>().getUnderlyingType();
|
||||
auto *llvmElemTy = llvm::cast<llvm::PointerType>(llvmPtrTy)->getElementType();
|
||||
auto elemTy = LLVM::LLVMType::get(op.getContext(), llvmElemTy);
|
||||
|
||||
auto funcTy = FunctionType::get({op.arraySize()->getType()}, {op.getType()},
|
||||
op.getContext());
|
||||
|
||||
*p << op.getOperationName() << ' ' << *op.arraySize() << " x " << elemTy;
|
||||
p->printOptionalAttrDict(op.getAttrs());
|
||||
*p << " : " << funcTy;
|
||||
}
|
||||
|
||||
// <operation> ::= `llvm.alloca` ssa-use `x` type attribute-dict?
|
||||
// `:` type `,` type
|
||||
static bool parseAllocaOp(OpAsmParser *parser, OperationState *result) {
|
||||
SmallVector<NamedAttribute, 4> attrs;
|
||||
OpAsmParser::OperandType arraySize;
|
||||
Type type, elemType;
|
||||
llvm::SMLoc trailingTypeLoc;
|
||||
if (parser->parseOperand(arraySize) || parser->parseKeyword("x") ||
|
||||
parser->parseType(elemType) ||
|
||||
parser->parseOptionalAttributeDict(attrs) || parser->parseColon() ||
|
||||
parser->getCurrentLocation(&trailingTypeLoc) || parser->parseType(type))
|
||||
return true;
|
||||
|
||||
// Extract the result type from the trailing function type.
|
||||
auto funcType = type.dyn_cast<FunctionType>();
|
||||
if (!funcType || funcType.getNumInputs() != 1 ||
|
||||
funcType.getNumResults() != 1)
|
||||
return parser->emitError(
|
||||
trailingTypeLoc,
|
||||
"expected trailing function type with one argument and one result");
|
||||
|
||||
if (parser->resolveOperand(arraySize, funcType.getInput(0), result->operands))
|
||||
return true;
|
||||
|
||||
result->attributes = attrs;
|
||||
result->addTypes({funcType.getResult(0)});
|
||||
return false;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Printing/parsing for LLVM::GEPOp.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static void printGEPOp(OpAsmPrinter *p, GEPOp &op) {
|
||||
SmallVector<Type, 8> types;
|
||||
for (auto *operand : op.getOperands())
|
||||
types.push_back(operand->getType());
|
||||
auto funcTy =
|
||||
FunctionType::get(types, op.getResult()->getType(), op.getContext());
|
||||
|
||||
*p << op.getOperationName() << ' ' << *op.base() << '[';
|
||||
p->printOperands(std::next(op.operand_begin()), op.operand_end());
|
||||
*p << ']';
|
||||
p->printOptionalAttrDict(op.getAttrs());
|
||||
*p << " : " << funcTy;
|
||||
}
|
||||
|
||||
// <operation> ::= `llvm.getelementptr` ssa-use `[` ssa-use-list `]`
|
||||
// attribute-dict? `:` type
|
||||
static bool parseGEPOp(OpAsmParser *parser, OperationState *result) {
|
||||
SmallVector<NamedAttribute, 4> attrs;
|
||||
OpAsmParser::OperandType base;
|
||||
SmallVector<OpAsmParser::OperandType, 8> indices;
|
||||
Type type;
|
||||
llvm::SMLoc trailingTypeLoc;
|
||||
if (parser->parseOperand(base) ||
|
||||
parser->parseOperandList(indices, /*requiredOperandCount=*/-1,
|
||||
OpAsmParser::Delimiter::Square) ||
|
||||
parser->parseOptionalAttributeDict(attrs) || parser->parseColon() ||
|
||||
parser->getCurrentLocation(&trailingTypeLoc) || parser->parseType(type))
|
||||
return true;
|
||||
|
||||
// Deconstruct the trailing function type to extract the types of the base
|
||||
// pointer and result (same type) and the types of the indices.
|
||||
auto funcType = type.dyn_cast<FunctionType>();
|
||||
if (!funcType || funcType.getNumResults() != 1 ||
|
||||
funcType.getNumInputs() == 0)
|
||||
return parser->emitError(trailingTypeLoc,
|
||||
"expected trailing function type with at least "
|
||||
"one argument and one result");
|
||||
|
||||
if (parser->resolveOperand(base, funcType.getInput(0), result->operands) ||
|
||||
parser->resolveOperands(indices, funcType.getInputs().drop_front(),
|
||||
parser->getNameLoc(), result->operands))
|
||||
return true;
|
||||
|
||||
result->attributes = attrs;
|
||||
result->addTypes(funcType.getResults());
|
||||
return false;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Printing/parsing for LLVM::LoadOp.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static void printLoadOp(OpAsmPrinter *p, LoadOp &op) {
|
||||
*p << op.getOperationName() << ' ' << *op.addr();
|
||||
p->printOptionalAttrDict(op.getAttrs());
|
||||
*p << " : " << op.addr()->getType();
|
||||
}
|
||||
|
||||
// Extract the pointee type from the LLVM pointer type wrapped in MLIR. Return
|
||||
// the resulting type wrapped in MLIR, or nullptr on error.
|
||||
static Type getLoadStoreElementType(OpAsmParser *parser, Type type,
|
||||
llvm::SMLoc trailingTypeLoc) {
|
||||
auto llvmTy = type.dyn_cast<LLVM::LLVMType>();
|
||||
if (!llvmTy)
|
||||
return parser->emitError(trailingTypeLoc, "expected LLVM IR dialect type"),
|
||||
nullptr;
|
||||
auto *llvmPtrTy = dyn_cast<llvm::PointerType>(llvmTy.getUnderlyingType());
|
||||
if (!llvmPtrTy)
|
||||
return parser->emitError(trailingTypeLoc, "expected LLVM pointer type"),
|
||||
nullptr;
|
||||
auto elemTy = LLVM::LLVMType::get(parser->getBuilder().getContext(),
|
||||
llvmPtrTy->getElementType());
|
||||
return elemTy;
|
||||
}
|
||||
|
||||
// <operation> ::= `llvm.load` ssa-use attribute-dict? `:` type
|
||||
static bool parseLoadOp(OpAsmParser *parser, OperationState *result) {
|
||||
SmallVector<NamedAttribute, 4> attrs;
|
||||
OpAsmParser::OperandType addr;
|
||||
Type type;
|
||||
llvm::SMLoc trailingTypeLoc;
|
||||
|
||||
if (parser->parseOperand(addr) || parser->parseOptionalAttributeDict(attrs) ||
|
||||
parser->parseColon() || parser->getCurrentLocation(&trailingTypeLoc) ||
|
||||
parser->parseType(type) ||
|
||||
parser->resolveOperand(addr, type, result->operands))
|
||||
return true;
|
||||
|
||||
Type elemTy = getLoadStoreElementType(parser, type, trailingTypeLoc);
|
||||
|
||||
result->attributes = attrs;
|
||||
result->addTypes(elemTy);
|
||||
return false;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Printing/parsing for LLVM::StoreOp.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static void printStoreOp(OpAsmPrinter *p, StoreOp &op) {
|
||||
*p << op.getOperationName() << ' ' << *op.value() << ", " << *op.addr();
|
||||
p->printOptionalAttrDict(op.getAttrs());
|
||||
*p << " : " << op.addr()->getType();
|
||||
}
|
||||
|
||||
// <operation> ::= `llvm.store` ssa-use `,` ssa-use attribute-dict? `:` type
|
||||
static bool parseStoreOp(OpAsmParser *parser, OperationState *result) {
|
||||
SmallVector<NamedAttribute, 4> attrs;
|
||||
OpAsmParser::OperandType addr, value;
|
||||
Type type;
|
||||
llvm::SMLoc trailingTypeLoc;
|
||||
|
||||
if (parser->parseOperand(value) || parser->parseComma() ||
|
||||
parser->parseOperand(addr) || parser->parseOptionalAttributeDict(attrs) ||
|
||||
parser->parseColon() || parser->getCurrentLocation(&trailingTypeLoc) ||
|
||||
parser->parseType(type))
|
||||
return true;
|
||||
|
||||
Type elemTy = getLoadStoreElementType(parser, type, trailingTypeLoc);
|
||||
if (!elemTy)
|
||||
return true;
|
||||
|
||||
if (parser->resolveOperand(value, elemTy, result->operands) ||
|
||||
parser->resolveOperand(addr, type, result->operands))
|
||||
return true;
|
||||
|
||||
result->attributes = attrs;
|
||||
return false;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Printing/parsing for LLVM::BitcastOp.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static void printBitcastOp(OpAsmPrinter *p, BitcastOp &op) {
|
||||
*p << op.getOperationName() << ' ' << *op.arg();
|
||||
p->printOptionalAttrDict(op.getAttrs());
|
||||
*p << " : " << op.arg()->getType() << " to " << op.getType();
|
||||
}
|
||||
|
||||
// <operation> ::= `llvm.bitcast` ssa-use attribute-dict? `:` type `to` type
|
||||
static bool parseBitcastOp(OpAsmParser *parser, OperationState *result) {
|
||||
SmallVector<NamedAttribute, 4> attrs;
|
||||
OpAsmParser::OperandType arg;
|
||||
Type sourceType, type;
|
||||
|
||||
if (parser->parseOperand(arg) || parser->parseOptionalAttributeDict(attrs) ||
|
||||
parser->parseColonType(sourceType) || parser->parseKeyword("to") ||
|
||||
parser->parseType(type) ||
|
||||
parser->resolveOperand(arg, sourceType, result->operands))
|
||||
return true;
|
||||
|
||||
result->attributes = attrs;
|
||||
result->addTypes(type);
|
||||
return false;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Printing/parsing for LLVM::CallOp.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static void printCallOp(OpAsmPrinter *p, CallOp &op) {
|
||||
auto callee = op.callee();
|
||||
bool isDirect = callee.hasValue();
|
||||
|
||||
// Print the direct callee if present as a function attribute, or an indirect
|
||||
// callee (first operand) otherwise.
|
||||
*p << op.getOperationName() << ' ';
|
||||
if (isDirect)
|
||||
*p << '@' << callee.getValue()->getName().strref();
|
||||
else
|
||||
*p << *op.getOperand(0);
|
||||
|
||||
*p << '(';
|
||||
p->printOperands(std::next(op.operand_begin(), callee.hasValue() ? 0 : 1),
|
||||
op.operand_end());
|
||||
*p << ')';
|
||||
|
||||
p->printOptionalAttrDict(op.getAttrs(), {"callee"});
|
||||
|
||||
if (isDirect) {
|
||||
*p << " : " << callee.getValue()->getType();
|
||||
return;
|
||||
}
|
||||
|
||||
// Reconstruct the function MLIR function type from LLVM function type,
|
||||
// and print it.
|
||||
auto operandType = op.getOperand(0)->getType().cast<LLVM::LLVMType>();
|
||||
auto *llvmPtrType =
|
||||
dyn_cast<llvm::PointerType>(operandType.getUnderlyingType());
|
||||
assert(llvmPtrType &&
|
||||
"operand #0 must have LLVM pointer type for indirect calls");
|
||||
auto *llvmType = dyn_cast<llvm::FunctionType>(llvmPtrType->getElementType());
|
||||
assert(llvmType &&
|
||||
"operand #0 must have LLVM Function pointer type for indirect calls");
|
||||
|
||||
auto *llvmResultType = llvmType->getReturnType();
|
||||
SmallVector<Type, 1> resultTypes;
|
||||
if (!llvmResultType->isVoidTy())
|
||||
resultTypes.push_back(LLVM::LLVMType::get(op.getContext(), llvmResultType));
|
||||
|
||||
SmallVector<Type, 8> argTypes;
|
||||
argTypes.reserve(llvmType->getNumParams());
|
||||
for (int i = 0, e = llvmType->getNumParams(); i < e; ++i)
|
||||
argTypes.push_back(
|
||||
LLVM::LLVMType::get(op.getContext(), llvmType->getParamType(i)));
|
||||
|
||||
*p << " : " << FunctionType::get(argTypes, resultTypes, op.getContext());
|
||||
}
|
||||
|
||||
// <operation> ::= `llvm.call` (function-id | ssa-use) `(` ssa-use-list `)`
|
||||
// attribute-dict? `:` function-type
|
||||
static bool parseCallOp(OpAsmParser *parser, OperationState *result) {
|
||||
SmallVector<NamedAttribute, 4> attrs;
|
||||
SmallVector<OpAsmParser::OperandType, 8> operands;
|
||||
Type type;
|
||||
StringRef calleeName;
|
||||
llvm::SMLoc calleeLoc, trailingTypeLoc;
|
||||
|
||||
// Parse an operand list that will, in practice, contain 0 or 1 operand. In
|
||||
// case of an indirect call, there will be 1 operand before `(`. In case of a
|
||||
// direct call, there will be no operands and the parser will stop at the
|
||||
// function identifier without complaining.
|
||||
if (parser->parseOperandList(operands))
|
||||
return true;
|
||||
bool isDirect = operands.empty();
|
||||
|
||||
// Optionally parse a function identifier.
|
||||
if (isDirect)
|
||||
if (parser->parseFunctionName(calleeName, calleeLoc))
|
||||
return true;
|
||||
|
||||
if (parser->parseOperandList(operands, /*requiredOperandCount=*/-1,
|
||||
OpAsmParser::Delimiter::Paren) ||
|
||||
parser->parseOptionalAttributeDict(attrs) || parser->parseColon() ||
|
||||
parser->getCurrentLocation(&trailingTypeLoc) || parser->parseType(type))
|
||||
return true;
|
||||
|
||||
auto funcType = type.dyn_cast<FunctionType>();
|
||||
if (!funcType)
|
||||
return parser->emitError(trailingTypeLoc, "expected function type");
|
||||
if (isDirect) {
|
||||
// Add the direct callee as an Op attribute.
|
||||
Function *func;
|
||||
if (parser->resolveFunctionName(calleeName, funcType, calleeLoc, func))
|
||||
return true;
|
||||
auto funcAttr = parser->getBuilder().getFunctionAttr(func);
|
||||
attrs.push_back(parser->getBuilder().getNamedAttr("callee", funcAttr));
|
||||
|
||||
// Make sure types match.
|
||||
if (parser->resolveOperands(operands, funcType.getInputs(),
|
||||
parser->getNameLoc(), result->operands))
|
||||
return true;
|
||||
result->addTypes(funcType.getResults());
|
||||
} else {
|
||||
// Construct the LLVM IR Dialect function type that the first operand
|
||||
// should match.
|
||||
if (funcType.getNumResults() > 1)
|
||||
return parser->emitError(trailingTypeLoc,
|
||||
"expected function with 0 or 1 result");
|
||||
|
||||
Builder &builder = parser->getBuilder();
|
||||
auto *llvmDialect = static_cast<LLVM::LLVMDialect *>(
|
||||
builder.getContext()->getRegisteredDialect("llvm"));
|
||||
llvm::Type *llvmResultType;
|
||||
Type wrappedResultType;
|
||||
if (funcType.getNumResults() == 0) {
|
||||
llvmResultType = llvm::Type::getVoidTy(llvmDialect->getLLVMContext());
|
||||
wrappedResultType = builder.getType<LLVM::LLVMType>(llvmResultType);
|
||||
} else {
|
||||
wrappedResultType = funcType.getResult(0);
|
||||
auto wrappedLLVMResultType = wrappedResultType.dyn_cast<LLVM::LLVMType>();
|
||||
if (!wrappedLLVMResultType)
|
||||
return parser->emitError(trailingTypeLoc,
|
||||
"expected result to have LLVM type");
|
||||
llvmResultType = wrappedLLVMResultType.getUnderlyingType();
|
||||
}
|
||||
|
||||
SmallVector<llvm::Type *, 8> argTypes;
|
||||
argTypes.reserve(funcType.getNumInputs());
|
||||
for (int i = 0, e = funcType.getNumInputs(); i < e; ++i) {
|
||||
auto argType = funcType.getInput(i).dyn_cast<LLVM::LLVMType>();
|
||||
if (!argType)
|
||||
return parser->emitError(trailingTypeLoc,
|
||||
"expected LLVM types as inputs");
|
||||
argTypes.push_back(argType.getUnderlyingType());
|
||||
}
|
||||
auto *llvmFuncType = llvm::FunctionType::get(llvmResultType, argTypes,
|
||||
/*isVarArg=*/false);
|
||||
auto wrappedFuncType =
|
||||
builder.getType<LLVM::LLVMType>(llvmFuncType->getPointerTo());
|
||||
|
||||
auto funcArguments =
|
||||
ArrayRef<OpAsmParser::OperandType>(operands).drop_front();
|
||||
|
||||
// Make sure that the first operand (indirect callee) matches the wrapped
|
||||
// LLVM IR function type, and that the types of the other call operands
|
||||
// match the types of the function arguments.
|
||||
if (parser->resolveOperand(operands[0], wrappedFuncType,
|
||||
result->operands) ||
|
||||
parser->resolveOperands(funcArguments, funcType.getInputs(),
|
||||
parser->getNameLoc(), result->operands))
|
||||
return true;
|
||||
|
||||
result->addTypes(wrappedResultType);
|
||||
}
|
||||
|
||||
result->attributes = attrs;
|
||||
return false;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Printing/parsing for LLVM::ExtractValueOp.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static void printExtractValueOp(OpAsmPrinter *p, ExtractValueOp &op) {
|
||||
*p << op.getOperationName() << ' ' << *op.container() << op.position();
|
||||
p->printOptionalAttrDict(op.getAttrs(), {"position"});
|
||||
*p << " : " << op.container()->getType();
|
||||
}
|
||||
|
||||
// Extract the type at `position` in the wrapped LLVM IR aggregate type
|
||||
// `containerType`. Position is an integer array attribute where each value
|
||||
// is a zero-based position of the element in the aggregate type. Return the
|
||||
// resulting type wrapped in MLIR, or nullptr on error.
|
||||
static LLVM::LLVMType getInsertExtractValueElementType(OpAsmParser *parser,
|
||||
Type containerType,
|
||||
Attribute positionAttr,
|
||||
llvm::SMLoc attributeLoc,
|
||||
llvm::SMLoc typeLoc) {
|
||||
auto wrappedContainerType = containerType.dyn_cast<LLVM::LLVMType>();
|
||||
if (!wrappedContainerType)
|
||||
return parser->emitError(typeLoc, "expected LLVM IR Dialect type"), nullptr;
|
||||
|
||||
auto positionArrayAttr = positionAttr.dyn_cast<ArrayAttr>();
|
||||
if (!positionArrayAttr)
|
||||
return parser->emitError(attributeLoc, "expected an array attribute"),
|
||||
nullptr;
|
||||
|
||||
// Infer the element type from the structure type: iteratively step inside the
|
||||
// type by taking the element type, indexed by the position attribute for
|
||||
// stuctures. Check the position index before accessing, it is supposed to be
|
||||
// in bounds.
|
||||
llvm::Type *llvmContainerType = wrappedContainerType.getUnderlyingType();
|
||||
for (Attribute subAttr : positionArrayAttr) {
|
||||
auto positionElementAttr = subAttr.dyn_cast<IntegerAttr>();
|
||||
if (!positionElementAttr)
|
||||
return parser->emitError(attributeLoc,
|
||||
"expected an array of integer literals"),
|
||||
nullptr;
|
||||
int position = positionElementAttr.getInt();
|
||||
if (llvmContainerType->isArrayTy()) {
|
||||
if (position < 0 || position >= llvmContainerType->getArrayNumElements())
|
||||
return parser->emitError(attributeLoc, "position out of bounds"),
|
||||
nullptr;
|
||||
llvmContainerType = llvmContainerType->getArrayElementType();
|
||||
} else if (llvmContainerType->isStructTy()) {
|
||||
if (position < 0 || position >= llvmContainerType->getStructNumElements())
|
||||
return parser->emitError(attributeLoc, "position out of bounds"),
|
||||
nullptr;
|
||||
llvmContainerType = llvmContainerType->getStructElementType(position);
|
||||
} else {
|
||||
return parser->emitError(typeLoc,
|
||||
"expected wrapped LLVM IR structure/array type"),
|
||||
nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Builder &builder = parser->getBuilder();
|
||||
return builder.getType<LLVM::LLVMType>(llvmContainerType);
|
||||
}
|
||||
|
||||
// <operation> ::= `llvm.extractvalue` ssa-use
|
||||
// `[` integer-literal (`,` integer-literal)* `]`
|
||||
// attribute-dict? `:` type
|
||||
static bool parseExtractValueOp(OpAsmParser *parser, OperationState *result) {
|
||||
SmallVector<NamedAttribute, 4> attrs;
|
||||
OpAsmParser::OperandType container;
|
||||
Type containerType;
|
||||
Attribute positionAttr;
|
||||
llvm::SMLoc attributeLoc, trailingTypeLoc;
|
||||
|
||||
if (parser->parseOperand(container) ||
|
||||
parser->getCurrentLocation(&attributeLoc) ||
|
||||
parser->parseAttribute(positionAttr, "position", attrs) ||
|
||||
parser->parseOptionalAttributeDict(attrs) || parser->parseColon() ||
|
||||
parser->getCurrentLocation(&trailingTypeLoc) ||
|
||||
parser->parseType(containerType) ||
|
||||
parser->resolveOperand(container, containerType, result->operands))
|
||||
return true;
|
||||
|
||||
auto elementType = getInsertExtractValueElementType(
|
||||
parser, containerType, positionAttr, attributeLoc, trailingTypeLoc);
|
||||
if (!elementType)
|
||||
return true;
|
||||
|
||||
result->attributes = attrs;
|
||||
result->addTypes(elementType);
|
||||
return false;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Printing/parsing for LLVM::InsertValueOp.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static void printInsertValueOp(OpAsmPrinter *p, InsertValueOp &op) {
|
||||
*p << op.getOperationName() << ' ' << *op.value() << ", " << *op.container()
|
||||
<< op.position();
|
||||
p->printOptionalAttrDict(op.getAttrs(), {"position"});
|
||||
*p << " : " << op.container()->getType();
|
||||
}
|
||||
|
||||
// <operation> ::= `llvm.insertvaluevalue` ssa-use `,` ssa-use
|
||||
// `[` integer-literal (`,` integer-literal)* `]`
|
||||
// attribute-dict? `:` type
|
||||
static bool parseInsertValueOp(OpAsmParser *parser, OperationState *result) {
|
||||
OpAsmParser::OperandType container, value;
|
||||
Type containerType;
|
||||
Attribute positionAttr;
|
||||
llvm::SMLoc attributeLoc, trailingTypeLoc;
|
||||
|
||||
if (parser->parseOperand(value) || parser->parseComma() ||
|
||||
parser->parseOperand(container) ||
|
||||
parser->getCurrentLocation(&attributeLoc) ||
|
||||
parser->parseAttribute(positionAttr, "position", result->attributes) ||
|
||||
parser->parseOptionalAttributeDict(result->attributes) ||
|
||||
parser->parseColon() || parser->getCurrentLocation(&trailingTypeLoc) ||
|
||||
parser->parseType(containerType))
|
||||
return true;
|
||||
|
||||
auto valueType = getInsertExtractValueElementType(
|
||||
parser, containerType, positionAttr, attributeLoc, trailingTypeLoc);
|
||||
if (!valueType)
|
||||
return true;
|
||||
|
||||
if (parser->resolveOperand(container, containerType, result->operands) ||
|
||||
parser->resolveOperand(value, valueType, result->operands))
|
||||
return true;
|
||||
|
||||
result->addTypes(containerType);
|
||||
return false;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Printing/parsing for LLVM::SelectOp.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static void printSelectOp(OpAsmPrinter *p, SelectOp &op) {
|
||||
*p << op.getOperationName() << ' ' << *op.condition() << ", "
|
||||
<< *op.trueValue() << ", " << *op.falseValue();
|
||||
p->printOptionalAttrDict(op.getAttrs());
|
||||
*p << " : " << op.condition()->getType() << ", " << op.trueValue()->getType();
|
||||
}
|
||||
|
||||
// <operation> ::= `llvm.select` ssa-use `,` ssa-use `,` ssa-use
|
||||
// attribute-dict? `:` type, type
|
||||
static bool parseSelectOp(OpAsmParser *parser, OperationState *result) {
|
||||
OpAsmParser::OperandType condition, trueValue, falseValue;
|
||||
Type conditionType, argType;
|
||||
|
||||
if (parser->parseOperand(condition) || parser->parseComma() ||
|
||||
parser->parseOperand(trueValue) || parser->parseComma() ||
|
||||
parser->parseOperand(falseValue) ||
|
||||
parser->parseOptionalAttributeDict(result->attributes) ||
|
||||
parser->parseColonType(conditionType) || parser->parseComma() ||
|
||||
parser->parseType(argType))
|
||||
return true;
|
||||
|
||||
if (parser->resolveOperand(condition, conditionType, result->operands) ||
|
||||
parser->resolveOperand(trueValue, argType, result->operands) ||
|
||||
parser->resolveOperand(falseValue, argType, result->operands))
|
||||
return true;
|
||||
|
||||
result->addTypes(argType);
|
||||
return false;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Printing/parsing for LLVM::BrOp.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static void printBrOp(OpAsmPrinter *p, BrOp &op) {
|
||||
*p << op.getOperationName() << ' ';
|
||||
p->printSuccessorAndUseList(op.getOperation(), 0);
|
||||
p->printOptionalAttrDict(op.getAttrs());
|
||||
}
|
||||
|
||||
// <operation> ::= `llvm.br` bb-id (`[` ssa-use-and-type-list `]`)?
|
||||
// attribute-dict?
|
||||
static bool parseBrOp(OpAsmParser *parser, OperationState *result) {
|
||||
Block *dest;
|
||||
SmallVector<Value *, 4> operands;
|
||||
if (parser->parseSuccessorAndUseList(dest, operands) ||
|
||||
parser->parseOptionalAttributeDict(result->attributes))
|
||||
return true;
|
||||
|
||||
result->addSuccessor(dest, operands);
|
||||
return false;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Printing/parsing for LLVM::CondBrOp.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static void printCondBrOp(OpAsmPrinter *p, CondBrOp &op) {
|
||||
*p << op.getOperationName() << ' ' << *op.getOperand(0) << ", ";
|
||||
p->printSuccessorAndUseList(op.getOperation(), 0);
|
||||
*p << ", ";
|
||||
p->printSuccessorAndUseList(op.getOperation(), 1);
|
||||
p->printOptionalAttrDict(op.getAttrs());
|
||||
}
|
||||
|
||||
// <operation> ::= `llvm.cond_br` ssa-use `,`
|
||||
// bb-id (`[` ssa-use-and-type-list `]`)? `,`
|
||||
// bb-id (`[` ssa-use-and-type-list `]`)? attribute-dict?
|
||||
static bool parseCondBrOp(OpAsmParser *parser, OperationState *result) {
|
||||
Block *trueDest;
|
||||
Block *falseDest;
|
||||
SmallVector<Value *, 4> trueOperands;
|
||||
SmallVector<Value *, 4> falseOperands;
|
||||
OpAsmParser::OperandType condition;
|
||||
|
||||
Builder &builder = parser->getBuilder();
|
||||
auto *llvmDialect = static_cast<LLVM::LLVMDialect *>(
|
||||
builder.getContext()->getRegisteredDialect("llvm"));
|
||||
auto i1Type = builder.getType<LLVM::LLVMType>(
|
||||
llvm::Type::getInt1Ty(llvmDialect->getLLVMContext()));
|
||||
|
||||
if (parser->parseOperand(condition) || parser->parseComma() ||
|
||||
parser->parseSuccessorAndUseList(trueDest, trueOperands) ||
|
||||
parser->parseComma() ||
|
||||
parser->parseSuccessorAndUseList(falseDest, falseOperands) ||
|
||||
parser->parseOptionalAttributeDict(result->attributes) ||
|
||||
parser->resolveOperand(condition, i1Type, result->operands))
|
||||
return true;
|
||||
|
||||
result->addSuccessor(trueDest, trueOperands);
|
||||
result->addSuccessor(falseDest, falseOperands);
|
||||
return false;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Printing/parsing for LLVM::ReturnOp.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static void printReturnOp(OpAsmPrinter *p, ReturnOp &op) {
|
||||
*p << op.getOperationName();
|
||||
p->printOptionalAttrDict(op.getAttrs());
|
||||
assert(op.getNumOperands() <= 1);
|
||||
|
||||
if (op.getNumOperands() == 0)
|
||||
return;
|
||||
|
||||
*p << ' ' << *op.getOperand(0) << " : " << op.getOperand(0)->getType();
|
||||
}
|
||||
|
||||
// <operation> ::= `llvm.return` ssa-use-list attribute-dict? `:`
|
||||
// type-list-no-parens
|
||||
static bool parseReturnOp(OpAsmParser *parser, OperationState *result) {
|
||||
SmallVector<OpAsmParser::OperandType, 1> operands;
|
||||
Type type;
|
||||
|
||||
if (parser->parseOperandList(operands) ||
|
||||
parser->parseOptionalAttributeDict(result->attributes))
|
||||
return true;
|
||||
if (operands.empty())
|
||||
return false;
|
||||
|
||||
if (parser->parseColonType(type) ||
|
||||
parser->resolveOperand(operands[0], type, result->operands))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Printing/parsing for LLVM::UndefOp.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static void printUndefOp(OpAsmPrinter *p, UndefOp &op) {
|
||||
*p << op.getOperationName();
|
||||
p->printOptionalAttrDict(op.getAttrs());
|
||||
*p << " : " << op.res()->getType();
|
||||
}
|
||||
|
||||
// <operation> ::= `llvm.undef` attribute-dict? : type
|
||||
static bool parseUndefOp(OpAsmParser *parser, OperationState *result) {
|
||||
Type type;
|
||||
|
||||
if (parser->parseOptionalAttributeDict(result->attributes) ||
|
||||
parser->parseColonType(type))
|
||||
return true;
|
||||
|
||||
result->addTypes(type);
|
||||
return false;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Printing/parsing for LLVM::ConstantOp.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static void printConstantOp(OpAsmPrinter *p, ConstantOp &op) {
|
||||
*p << op.getOperationName() << '(' << op.value();
|
||||
// Print attribute types other than i64 and f64 because attribute parsing will
|
||||
// assume those in absence of explicit attribute type.
|
||||
if (auto intAttr = op.value().dyn_cast<IntegerAttr>()) {
|
||||
auto type = intAttr.getType();
|
||||
if (!type.isInteger(64))
|
||||
*p << " : " << intAttr.getType();
|
||||
} else if (auto floatAttr = op.value().dyn_cast<FloatAttr>()) {
|
||||
auto type = floatAttr.getType();
|
||||
if (!type.isF64())
|
||||
*p << " : " << type;
|
||||
}
|
||||
*p << ')';
|
||||
p->printOptionalAttrDict(op.getAttrs(), {"value"});
|
||||
*p << " : " << op.res()->getType();
|
||||
}
|
||||
|
||||
// <operation> ::= `llvm.constant` `(` attribute `)` attribute-list? : type
|
||||
static bool parseConstantOp(OpAsmParser *parser, OperationState *result) {
|
||||
Attribute valueAttr;
|
||||
Type type;
|
||||
|
||||
if (parser->parseLParen() ||
|
||||
parser->parseAttribute(valueAttr, "value", result->attributes) ||
|
||||
parser->parseRParen() ||
|
||||
parser->parseOptionalAttributeDict(result->attributes) ||
|
||||
parser->parseColonType(type))
|
||||
return true;
|
||||
|
||||
result->addTypes(type);
|
||||
return false;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// LLVMDialect initialization, type parsing, and registration.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
LLVMDialect::LLVMDialect(MLIRContext *context)
|
||||
: Dialect("llvm", context), module("LLVMDialectModule", llvmContext) {
|
||||
|
|
|
@ -3057,6 +3057,9 @@ public:
|
|||
bool parseComma() override {
|
||||
return parser.parseToken(Token::comma, "expected ','");
|
||||
}
|
||||
bool parseColon() override {
|
||||
return parser.parseToken(Token::colon, "expected ':'");
|
||||
}
|
||||
bool parseEqual() override {
|
||||
return parser.parseToken(Token::equal, "expected '='");
|
||||
}
|
||||
|
@ -3142,10 +3145,19 @@ public:
|
|||
/// Parse a function name like '@foo' and return the name in a form that can
|
||||
/// be passed to resolveFunctionName when a function type is available.
|
||||
virtual bool parseFunctionName(StringRef &result, llvm::SMLoc &loc) {
|
||||
if (parseOptionalFunctionName(result, loc))
|
||||
return emitError(loc, "expected function name");
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Parse a function name like '@foo` if present and return the name without
|
||||
/// the sigil in `result`. Return true if the next token is not a function
|
||||
/// name and keep `result` unchanged.
|
||||
bool parseOptionalFunctionName(StringRef &result, llvm::SMLoc &loc) override {
|
||||
loc = parser.getToken().getLoc();
|
||||
|
||||
if (parser.getToken().isNot(Token::at_identifier))
|
||||
return emitError(loc, "expected function name");
|
||||
return true;
|
||||
|
||||
result = parser.getTokenSpelling();
|
||||
parser.consumeToken(Token::at_identifier);
|
||||
|
@ -3167,6 +3179,14 @@ public:
|
|||
return parser.parseSuccessorAndUseList(dest, operands);
|
||||
}
|
||||
|
||||
bool parseLParen() override {
|
||||
return parser.parseToken(Token::l_paren, "expected '('");
|
||||
}
|
||||
|
||||
bool parseRParen() override {
|
||||
return parser.parseToken(Token::r_paren, "expected ')'");
|
||||
}
|
||||
|
||||
bool parseOperandList(SmallVectorImpl<OperandType> &result,
|
||||
int requiredOperandCount = -1,
|
||||
Delimiter delimiter = Delimiter::None) override {
|
||||
|
|
|
@ -20,12 +20,12 @@ func @fifth_order_right(%arg0: () -> (() -> (() -> (() -> ()))))
|
|||
|
||||
//CHECK-LABEL: func @pass_through(%arg0: !llvm<"void ()*">) -> !llvm<"void ()*"> {
|
||||
func @pass_through(%arg0: () -> ()) -> (() -> ()) {
|
||||
//CHECK-NEXT: "llvm.br"()[^bb1(%arg0 : !llvm<"void ()*">)] : () -> ()
|
||||
// CHECK-NEXT: llvm.br ^bb1(%arg0 : !llvm<"void ()*">)
|
||||
br ^bb1(%arg0 : () -> ())
|
||||
|
||||
//CHECK-NEXT: ^bb1(%0: !llvm<"void ()*">): // pred: ^bb0
|
||||
^bb1(%bbarg: () -> ()):
|
||||
//CHECK-NEXT: "llvm.return"(%0) : (!llvm<"void ()*">) -> ()
|
||||
// CHECK-NEXT: llvm.return %0 : !llvm<"void ()*">
|
||||
return %bbarg : () -> ()
|
||||
}
|
||||
|
||||
|
@ -34,19 +34,19 @@ func @body(i32)
|
|||
|
||||
// CHECK-LABEL: func @indirect_const_call(%arg0: !llvm<"i32">) {
|
||||
func @indirect_const_call(%arg0: i32) {
|
||||
// CHECK-NEXT: %0 = "llvm.constant"() {value: @body : (!llvm<"i32">) -> ()} : () -> !llvm<"void (i32)*">
|
||||
// CHECK-NEXT: %0 = llvm.constant(@body : (!llvm<"i32">) -> ()) : !llvm<"void (i32)*">
|
||||
%0 = constant @body : (i32) -> ()
|
||||
// CHECK-NEXT: "llvm.call"(%0, %arg0) : (!llvm<"void (i32)*">, !llvm<"i32">) -> ()
|
||||
// CHECK-NEXT: llvm.call %0(%arg0) : (!llvm<"i32">) -> ()
|
||||
call_indirect %0(%arg0) : (i32) -> ()
|
||||
// CHECK-NEXT: "llvm.return"() : () -> ()
|
||||
// CHECK-NEXT: llvm.return
|
||||
return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: func @indirect_call(%arg0: !llvm<"i32 (float)*">, %arg1: !llvm<"float">) -> !llvm<"i32"> {
|
||||
func @indirect_call(%arg0: (f32) -> i32, %arg1: f32) -> i32 {
|
||||
// CHECK-NEXT: %0 = "llvm.call"(%arg0, %arg1) : (!llvm<"i32 (float)*">, !llvm<"float">) -> !llvm<"i32">
|
||||
// CHECK-NEXT: %0 = llvm.call %arg0(%arg1) : (!llvm<"float">) -> !llvm<"i32">
|
||||
%0 = call_indirect %arg0(%arg1) : (f32) -> i32
|
||||
// CHECK-NEXT: "llvm.return"(%0) : (!llvm<"i32">) -> ()
|
||||
// CHECK-NEXT: llvm.return %0 : !llvm<"i32">
|
||||
return %0 : i32
|
||||
}
|
||||
|
||||
|
|
|
@ -8,288 +8,288 @@ func @check_arguments(%static: memref<10x20xf32>, %dynamic : memref<?x?xf32>, %m
|
|||
|
||||
// CHECK-LABEL: func @check_static_return(%arg0: !llvm<"float*">) -> !llvm<"float*"> {
|
||||
func @check_static_return(%static : memref<32x18xf32>) -> memref<32x18xf32> {
|
||||
// CHECK-NEXT: "llvm.return"(%arg0) : (!llvm<"float*">) -> ()
|
||||
// CHECK-NEXT: llvm.return %arg0 : !llvm<"float*">
|
||||
return %static : memref<32x18xf32>
|
||||
}
|
||||
|
||||
// CHECK-LABEL: func @zero_d_alloc() -> !llvm<"float*"> {
|
||||
func @zero_d_alloc() -> memref<f32> {
|
||||
// CHECK-NEXT: %0 = "llvm.constant"() {value: 1 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: %1 = "llvm.constant"() {value: 4 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: %2 = "llvm.mul"(%0, %1) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: %3 = "llvm.call"(%2) {callee: @malloc : (!llvm<"i64">) -> !llvm<"i8*">} : (!llvm<"i64">) -> !llvm<"i8*">
|
||||
// CHECK-NEXT: %4 = "llvm.bitcast"(%3) : (!llvm<"i8*">) -> !llvm<"float*">
|
||||
// CHECK-NEXT: %0 = llvm.constant(1 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: %1 = llvm.constant(4 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: %2 = llvm.mul %0, %1 : !llvm<"i64">
|
||||
// CHECK-NEXT: %3 = llvm.call @malloc(%2) : (!llvm<"i64">) -> !llvm<"i8*">
|
||||
// CHECK-NEXT: %4 = llvm.bitcast %3 : !llvm<"i8*"> to !llvm<"float*">
|
||||
%0 = alloc() : memref<f32>
|
||||
return %0 : memref<f32>
|
||||
}
|
||||
|
||||
// CHECK-LABEL: func @zero_d_dealloc(%arg0: !llvm<"float*">) {
|
||||
func @zero_d_dealloc(%arg0: memref<f32>) {
|
||||
// CHECK-NEXT: %0 = "llvm.bitcast"(%arg0) : (!llvm<"float*">) -> !llvm<"i8*">
|
||||
// CHECK-NEXT: "llvm.call"(%0) {callee: @free : (!llvm<"i8*">) -> ()} : (!llvm<"i8*">) -> ()
|
||||
// CHECK-NEXT: %0 = llvm.bitcast %arg0 : !llvm<"float*"> to !llvm<"i8*">
|
||||
// CHECK-NEXT: llvm.call @free(%0) : (!llvm<"i8*">) -> ()
|
||||
dealloc %arg0 : memref<f32>
|
||||
return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: func @mixed_alloc(%arg0: !llvm<"i64">, %arg1: !llvm<"i64">) -> !llvm<"{ float*, i64, i64 }"> {
|
||||
func @mixed_alloc(%arg0: index, %arg1: index) -> memref<?x42x?xf32> {
|
||||
// CHECK-NEXT: %0 = "llvm.constant"() {value: 42 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: %1 = "llvm.mul"(%arg0, %0) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: %2 = "llvm.mul"(%1, %arg1) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: %3 = "llvm.constant"() {value: 4 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: %4 = "llvm.mul"(%2, %3) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: %5 = "llvm.call"(%4) {callee: @malloc : (!llvm<"i64">) -> !llvm<"i8*">} : (!llvm<"i64">) -> !llvm<"i8*">
|
||||
// CHECK-NEXT: %6 = "llvm.bitcast"(%5) : (!llvm<"i8*">) -> !llvm<"float*">
|
||||
// CHECK-NEXT: %7 = "llvm.undef"() : () -> !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %8 = "llvm.insertvalue"(%7, %6) {position: [0]} : (!llvm<"{ float*, i64, i64 }">, !llvm<"float*">) -> !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %9 = "llvm.insertvalue"(%8, %arg0) {position: [1]} : (!llvm<"{ float*, i64, i64 }">, !llvm<"i64">) -> !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %10 = "llvm.insertvalue"(%9, %arg1) {position: [2]} : (!llvm<"{ float*, i64, i64 }">, !llvm<"i64">) -> !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %0 = llvm.constant(42 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: %1 = llvm.mul %arg0, %0 : !llvm<"i64">
|
||||
// CHECK-NEXT: %2 = llvm.mul %1, %arg1 : !llvm<"i64">
|
||||
// CHECK-NEXT: %3 = llvm.constant(4 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: %4 = llvm.mul %2, %3 : !llvm<"i64">
|
||||
// CHECK-NEXT: %5 = llvm.call @malloc(%4) : (!llvm<"i64">) -> !llvm<"i8*">
|
||||
// CHECK-NEXT: %6 = llvm.bitcast %5 : !llvm<"i8*"> to !llvm<"float*">
|
||||
// CHECK-NEXT: %7 = llvm.undef : !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %8 = llvm.insertvalue %6, %7[0] : !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %9 = llvm.insertvalue %arg0, %8[1] : !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %10 = llvm.insertvalue %arg1, %9[2] : !llvm<"{ float*, i64, i64 }">
|
||||
%0 = alloc(%arg0, %arg1) : memref<?x42x?xf32>
|
||||
return %0 : memref<?x42x?xf32>
|
||||
}
|
||||
|
||||
// CHECK-LABEL: func @mixed_dealloc(%arg0: !llvm<"{ float*, i64, i64 }">) {
|
||||
func @mixed_dealloc(%arg0: memref<?x42x?xf32>) {
|
||||
// CHECK-NEXT: %0 = "llvm.extractvalue"(%arg0) {position: [0]} : (!llvm<"{ float*, i64, i64 }">) -> !llvm<"float*">
|
||||
// CHECK-NEXT: %1 = "llvm.bitcast"(%0) : (!llvm<"float*">) -> !llvm<"i8*">
|
||||
// CHECK-NEXT: "llvm.call"(%1) {callee: @free : (!llvm<"i8*">) -> ()} : (!llvm<"i8*">) -> ()
|
||||
// CHECK-NEXT: %0 = llvm.extractvalue %arg0[0] : !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %1 = llvm.bitcast %0 : !llvm<"float*"> to !llvm<"i8*">
|
||||
// CHECK-NEXT: llvm.call @free(%1) : (!llvm<"i8*">) -> ()
|
||||
dealloc %arg0 : memref<?x42x?xf32>
|
||||
// CHECK-NEXT: "llvm.return"() : () -> ()
|
||||
// CHECK-NEXT: llvm.return
|
||||
return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: func @dynamic_alloc(%arg0: !llvm<"i64">, %arg1: !llvm<"i64">) -> !llvm<"{ float*, i64, i64 }"> {
|
||||
func @dynamic_alloc(%arg0: index, %arg1: index) -> memref<?x?xf32> {
|
||||
// CHECK-NEXT: %0 = "llvm.mul"(%arg0, %arg1) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: %1 = "llvm.constant"() {value: 4 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: %2 = "llvm.mul"(%0, %1) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: %3 = "llvm.call"(%2) {callee: @malloc : (!llvm<"i64">) -> !llvm<"i8*">} : (!llvm<"i64">) -> !llvm<"i8*">
|
||||
// CHECK-NEXT: %4 = "llvm.bitcast"(%3) : (!llvm<"i8*">) -> !llvm<"float*">
|
||||
// CHECK-NEXT: %5 = "llvm.undef"() : () -> !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %6 = "llvm.insertvalue"(%5, %4) {position: [0]} : (!llvm<"{ float*, i64, i64 }">, !llvm<"float*">) -> !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %7 = "llvm.insertvalue"(%6, %arg0) {position: [1]} : (!llvm<"{ float*, i64, i64 }">, !llvm<"i64">) -> !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %8 = "llvm.insertvalue"(%7, %arg1) {position: [2]} : (!llvm<"{ float*, i64, i64 }">, !llvm<"i64">) -> !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %0 = llvm.mul %arg0, %arg1 : !llvm<"i64">
|
||||
// CHECK-NEXT: %1 = llvm.constant(4 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: %2 = llvm.mul %0, %1 : !llvm<"i64">
|
||||
// CHECK-NEXT: %3 = llvm.call @malloc(%2) : (!llvm<"i64">) -> !llvm<"i8*">
|
||||
// CHECK-NEXT: %4 = llvm.bitcast %3 : !llvm<"i8*"> to !llvm<"float*">
|
||||
// CHECK-NEXT: %5 = llvm.undef : !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %6 = llvm.insertvalue %4, %5[0] : !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %7 = llvm.insertvalue %arg0, %6[1] : !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %8 = llvm.insertvalue %arg1, %7[2] : !llvm<"{ float*, i64, i64 }">
|
||||
%0 = alloc(%arg0, %arg1) : memref<?x?xf32>
|
||||
return %0 : memref<?x?xf32>
|
||||
}
|
||||
|
||||
// CHECK-LABEL: func @dynamic_dealloc(%arg0: !llvm<"{ float*, i64, i64 }">) {
|
||||
func @dynamic_dealloc(%arg0: memref<?x?xf32>) {
|
||||
// CHECK-NEXT: %0 = "llvm.extractvalue"(%arg0) {position: [0]} : (!llvm<"{ float*, i64, i64 }">) -> !llvm<"float*">
|
||||
// CHECK-NEXT: %1 = "llvm.bitcast"(%0) : (!llvm<"float*">) -> !llvm<"i8*">
|
||||
// CHECK-NEXT: "llvm.call"(%1) {callee: @free : (!llvm<"i8*">) -> ()} : (!llvm<"i8*">) -> ()
|
||||
// CHECK-NEXT: %0 = llvm.extractvalue %arg0[0] : !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %1 = llvm.bitcast %0 : !llvm<"float*"> to !llvm<"i8*">
|
||||
// CHECK-NEXT: llvm.call @free(%1) : (!llvm<"i8*">) -> ()
|
||||
dealloc %arg0 : memref<?x?xf32>
|
||||
return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: func @static_alloc() -> !llvm<"float*"> {
|
||||
func @static_alloc() -> memref<32x18xf32> {
|
||||
// CHECK-NEXT: %0 = "llvm.constant"() {value: 32 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: %1 = "llvm.constant"() {value: 18 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: %2 = "llvm.mul"(%0, %1) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: %3 = "llvm.constant"() {value: 4 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: %4 = "llvm.mul"(%2, %3) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: %5 = "llvm.call"(%4) {callee: @malloc : (!llvm<"i64">) -> !llvm<"i8*">} : (!llvm<"i64">) -> !llvm<"i8*">
|
||||
// CHECK-NEXT: %6 = "llvm.bitcast"(%5) : (!llvm<"i8*">) -> !llvm<"float*">
|
||||
// CHECK-NEXT: %0 = llvm.constant(32 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: %1 = llvm.constant(18 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: %2 = llvm.mul %0, %1 : !llvm<"i64">
|
||||
// CHECK-NEXT: %3 = llvm.constant(4 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: %4 = llvm.mul %2, %3 : !llvm<"i64">
|
||||
// CHECK-NEXT: %5 = llvm.call @malloc(%4) : (!llvm<"i64">) -> !llvm<"i8*">
|
||||
// CHECK-NEXT: %6 = llvm.bitcast %5 : !llvm<"i8*"> to !llvm<"float*">
|
||||
%0 = alloc() : memref<32x18xf32>
|
||||
return %0 : memref<32x18xf32>
|
||||
}
|
||||
|
||||
// CHECK-LABEL: func @static_dealloc(%arg0: !llvm<"float*">) {
|
||||
func @static_dealloc(%static: memref<10x8xf32>) {
|
||||
// CHECK-NEXT: %0 = "llvm.bitcast"(%arg0) : (!llvm<"float*">) -> !llvm<"i8*">
|
||||
// CHECK-NEXT: "llvm.call"(%0) {callee: @free : (!llvm<"i8*">) -> ()} : (!llvm<"i8*">) -> ()
|
||||
// CHECK-NEXT: %0 = llvm.bitcast %arg0 : !llvm<"float*"> to !llvm<"i8*">
|
||||
// CHECK-NEXT: llvm.call @free(%0) : (!llvm<"i8*">) -> ()
|
||||
dealloc %static : memref<10x8xf32>
|
||||
return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: func @zero_d_load(%arg0: !llvm<"float*">) -> !llvm<"float"> {
|
||||
func @zero_d_load(%arg0: memref<f32>) -> f32 {
|
||||
// CHECK-NEXT: %0 = "llvm.load"(%arg0) : (!llvm<"float*">) -> !llvm<"float">
|
||||
// CHECK-NEXT: %0 = llvm.load %arg0 : !llvm<"float*">
|
||||
%0 = load %arg0[] : memref<f32>
|
||||
return %0 : f32
|
||||
}
|
||||
|
||||
// CHECK-LABEL: func @static_load
|
||||
func @static_load(%static : memref<10x42xf32>, %i : index, %j : index) {
|
||||
// CHECK-NEXT: %0 = "llvm.constant"() {value: 10 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: %1 = "llvm.constant"() {value: 42 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: %2 = "llvm.mul"(%arg1, %1) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: %3 = "llvm.add"(%2, %arg2) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: %4 = "llvm.getelementptr"(%arg0, %3) : (!llvm<"float*">, !llvm<"i64">) -> !llvm<"float*">
|
||||
// CHECK-NEXT: %5 = "llvm.load"(%4) : (!llvm<"float*">) -> !llvm<"float">
|
||||
// CHECK-NEXT: %0 = llvm.constant(10 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: %1 = llvm.constant(42 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: %2 = llvm.mul %arg1, %1 : !llvm<"i64">
|
||||
// CHECK-NEXT: %3 = llvm.add %2, %arg2 : !llvm<"i64">
|
||||
// CHECK-NEXT: %4 = llvm.getelementptr %arg0[%3] : (!llvm<"float*">, !llvm<"i64">) -> !llvm<"float*">
|
||||
// CHECK-NEXT: %5 = llvm.load %4 : !llvm<"float*">
|
||||
%0 = load %static[%i, %j] : memref<10x42xf32>
|
||||
return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: func @mixed_load
|
||||
func @mixed_load(%mixed : memref<42x?xf32>, %i : index, %j : index) {
|
||||
// CHECK-NEXT: %0 = "llvm.constant"() {value: 42 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: %1 = "llvm.extractvalue"(%arg0) {position: [1]} : (!llvm<"{ float*, i64 }">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: %2 = "llvm.mul"(%arg1, %1) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: %3 = "llvm.add"(%2, %arg2) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: %4 = "llvm.extractvalue"(%arg0) {position: [0]} : (!llvm<"{ float*, i64 }">) -> !llvm<"float*">
|
||||
// CHECK-NEXT: %5 = "llvm.getelementptr"(%4, %3) : (!llvm<"float*">, !llvm<"i64">) -> !llvm<"float*">
|
||||
// CHECK-NEXT: %6 = "llvm.load"(%5) : (!llvm<"float*">) -> !llvm<"float">
|
||||
// CHECK-NEXT: %0 = llvm.constant(42 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: %1 = llvm.extractvalue %arg0[1] : !llvm<"{ float*, i64 }">
|
||||
// CHECK-NEXT: %2 = llvm.mul %arg1, %1 : !llvm<"i64">
|
||||
// CHECK-NEXT: %3 = llvm.add %2, %arg2 : !llvm<"i64">
|
||||
// CHECK-NEXT: %4 = llvm.extractvalue %arg0[0] : !llvm<"{ float*, i64 }">
|
||||
// CHECK-NEXT: %5 = llvm.getelementptr %4[%3] : (!llvm<"float*">, !llvm<"i64">) -> !llvm<"float*">
|
||||
// CHECK-NEXT: %6 = llvm.load %5 : !llvm<"float*">
|
||||
%0 = load %mixed[%i, %j] : memref<42x?xf32>
|
||||
return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: func @dynamic_load
|
||||
func @dynamic_load(%dynamic : memref<?x?xf32>, %i : index, %j : index) {
|
||||
// CHECK-NEXT: %0 = "llvm.extractvalue"(%arg0) {position: [1]} : (!llvm<"{ float*, i64, i64 }">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: %1 = "llvm.extractvalue"(%arg0) {position: [2]} : (!llvm<"{ float*, i64, i64 }">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: %2 = "llvm.mul"(%arg1, %1) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: %3 = "llvm.add"(%2, %arg2) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: %4 = "llvm.extractvalue"(%arg0) {position: [0]} : (!llvm<"{ float*, i64, i64 }">) -> !llvm<"float*">
|
||||
// CHECK-NEXT: %5 = "llvm.getelementptr"(%4, %3) : (!llvm<"float*">, !llvm<"i64">) -> !llvm<"float*">
|
||||
// CHECK-NEXT: %6 = "llvm.load"(%5) : (!llvm<"float*">) -> !llvm<"float">
|
||||
// CHECK-NEXT: %0 = llvm.extractvalue %arg0[1] : !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %1 = llvm.extractvalue %arg0[2] : !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %2 = llvm.mul %arg1, %1 : !llvm<"i64">
|
||||
// CHECK-NEXT: %3 = llvm.add %2, %arg2 : !llvm<"i64">
|
||||
// CHECK-NEXT: %4 = llvm.extractvalue %arg0[0] : !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %5 = llvm.getelementptr %4[%3] : (!llvm<"float*">, !llvm<"i64">) -> !llvm<"float*">
|
||||
// CHECK-NEXT: %6 = llvm.load %5 : !llvm<"float*">
|
||||
%0 = load %dynamic[%i, %j] : memref<?x?xf32>
|
||||
return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: func @zero_d_store(%arg0: !llvm<"float*">, %arg1: !llvm<"float">) {
|
||||
func @zero_d_store(%arg0: memref<f32>, %arg1: f32) {
|
||||
// CHECK-NEXT: "llvm.store"(%arg1, %arg0) : (!llvm<"float">, !llvm<"float*">) -> ()
|
||||
// CHECK-NEXT: llvm.store %arg1, %arg0 : !llvm<"float*">
|
||||
store %arg1, %arg0[] : memref<f32>
|
||||
return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: func @static_store
|
||||
func @static_store(%static : memref<10x42xf32>, %i : index, %j : index, %val : f32) {
|
||||
// CHECK-NEXT: %0 = "llvm.constant"() {value: 10 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: %1 = "llvm.constant"() {value: 42 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: %2 = "llvm.mul"(%arg1, %1) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: %3 = "llvm.add"(%2, %arg2) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: %4 = "llvm.getelementptr"(%arg0, %3) : (!llvm<"float*">, !llvm<"i64">) -> !llvm<"float*">
|
||||
// CHECK-NEXT: "llvm.store"(%arg3, %4) : (!llvm<"float">, !llvm<"float*">) -> ()
|
||||
// CHECK-NEXT: %0 = llvm.constant(10 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: %1 = llvm.constant(42 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: %2 = llvm.mul %arg1, %1 : !llvm<"i64">
|
||||
// CHECK-NEXT: %3 = llvm.add %2, %arg2 : !llvm<"i64">
|
||||
// CHECK-NEXT: %4 = llvm.getelementptr %arg0[%3] : (!llvm<"float*">, !llvm<"i64">) -> !llvm<"float*">
|
||||
// CHECK-NEXT: llvm.store %arg3, %4 : !llvm<"float*">
|
||||
store %val, %static[%i, %j] : memref<10x42xf32>
|
||||
return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: func @dynamic_store
|
||||
func @dynamic_store(%dynamic : memref<?x?xf32>, %i : index, %j : index, %val : f32) {
|
||||
// CHECK-NEXT: %0 = "llvm.extractvalue"(%arg0) {position: [1]} : (!llvm<"{ float*, i64, i64 }">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: %1 = "llvm.extractvalue"(%arg0) {position: [2]} : (!llvm<"{ float*, i64, i64 }">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: %2 = "llvm.mul"(%arg1, %1) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: %3 = "llvm.add"(%2, %arg2) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: %4 = "llvm.extractvalue"(%arg0) {position: [0]} : (!llvm<"{ float*, i64, i64 }">) -> !llvm<"float*">
|
||||
// CHECK-NEXT: %5 = "llvm.getelementptr"(%4, %3) : (!llvm<"float*">, !llvm<"i64">) -> !llvm<"float*">
|
||||
// CHECK-NEXT: "llvm.store"(%arg3, %5) : (!llvm<"float">, !llvm<"float*">) -> ()
|
||||
// CHECK-NEXT: %0 = llvm.extractvalue %arg0[1] : !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %1 = llvm.extractvalue %arg0[2] : !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %2 = llvm.mul %arg1, %1 : !llvm<"i64">
|
||||
// CHECK-NEXT: %3 = llvm.add %2, %arg2 : !llvm<"i64">
|
||||
// CHECK-NEXT: %4 = llvm.extractvalue %arg0[0] : !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %5 = llvm.getelementptr %4[%3] : (!llvm<"float*">, !llvm<"i64">) -> !llvm<"float*">
|
||||
// CHECK-NEXT: llvm.store %arg3, %5 : !llvm<"float*">
|
||||
store %val, %dynamic[%i, %j] : memref<?x?xf32>
|
||||
return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: func @mixed_store
|
||||
func @mixed_store(%mixed : memref<42x?xf32>, %i : index, %j : index, %val : f32) {
|
||||
// CHECK-NEXT: %0 = "llvm.constant"() {value: 42 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: %1 = "llvm.extractvalue"(%arg0) {position: [1]} : (!llvm<"{ float*, i64 }">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: %2 = "llvm.mul"(%arg1, %1) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: %3 = "llvm.add"(%2, %arg2) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: %4 = "llvm.extractvalue"(%arg0) {position: [0]} : (!llvm<"{ float*, i64 }">) -> !llvm<"float*">
|
||||
// CHECK-NEXT: %5 = "llvm.getelementptr"(%4, %3) : (!llvm<"float*">, !llvm<"i64">) -> !llvm<"float*">
|
||||
// CHECK-NEXT: "llvm.store"(%arg3, %5) : (!llvm<"float">, !llvm<"float*">) -> ()
|
||||
// CHECK-NEXT: %0 = llvm.constant(42 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: %1 = llvm.extractvalue %arg0[1] : !llvm<"{ float*, i64 }">
|
||||
// CHECK-NEXT: %2 = llvm.mul %arg1, %1 : !llvm<"i64">
|
||||
// CHECK-NEXT: %3 = llvm.add %2, %arg2 : !llvm<"i64">
|
||||
// CHECK-NEXT: %4 = llvm.extractvalue %arg0[0] : !llvm<"{ float*, i64 }">
|
||||
// CHECK-NEXT: %5 = llvm.getelementptr %4[%3] : (!llvm<"float*">, !llvm<"i64">) -> !llvm<"float*">
|
||||
// CHECK-NEXT: llvm.store %arg3, %5 : !llvm<"float*">
|
||||
store %val, %mixed[%i, %j] : memref<42x?xf32>
|
||||
return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: func @memref_cast_static_to_dynamic
|
||||
func @memref_cast_static_to_dynamic(%static : memref<10x42xf32>) {
|
||||
// CHECK-NEXT: %0 = "llvm.undef"() : () -> !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %1 = "llvm.insertvalue"(%0, %arg0) {position: [0]} : (!llvm<"{ float*, i64, i64 }">, !llvm<"float*">) -> !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %2 = "llvm.constant"() {value: 10 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: %3 = "llvm.insertvalue"(%1, %2) {position: [1]} : (!llvm<"{ float*, i64, i64 }">, !llvm<"i64">) -> !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %4 = "llvm.constant"() {value: 42 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: %5 = "llvm.insertvalue"(%3, %4) {position: [2]} : (!llvm<"{ float*, i64, i64 }">, !llvm<"i64">) -> !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %0 = llvm.undef : !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %1 = llvm.insertvalue %arg0, %0[0] : !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %2 = llvm.constant(10 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: %3 = llvm.insertvalue %2, %1[1] : !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %4 = llvm.constant(42 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: %5 = llvm.insertvalue %4, %3[2] : !llvm<"{ float*, i64, i64 }">
|
||||
%0 = memref_cast %static : memref<10x42xf32> to memref<?x?xf32>
|
||||
return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: func @memref_cast_static_to_mixed
|
||||
func @memref_cast_static_to_mixed(%static : memref<10x42xf32>) {
|
||||
// CHECK-NEXT: %0 = "llvm.undef"() : () -> !llvm<"{ float*, i64 }">
|
||||
// CHECK-NEXT: %1 = "llvm.insertvalue"(%0, %arg0) {position: [0]} : (!llvm<"{ float*, i64 }">, !llvm<"float*">) -> !llvm<"{ float*, i64 }">
|
||||
// CHECK-NEXT: %2 = "llvm.constant"() {value: 10 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: %3 = "llvm.insertvalue"(%1, %2) {position: [1]} : (!llvm<"{ float*, i64 }">, !llvm<"i64">) -> !llvm<"{ float*, i64 }">
|
||||
// CHECK-NEXT: %0 = llvm.undef : !llvm<"{ float*, i64 }">
|
||||
// CHECK-NEXT: %1 = llvm.insertvalue %arg0, %0[0] : !llvm<"{ float*, i64 }">
|
||||
// CHECK-NEXT: %2 = llvm.constant(10 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: %3 = llvm.insertvalue %2, %1[1] : !llvm<"{ float*, i64 }">
|
||||
%0 = memref_cast %static : memref<10x42xf32> to memref<?x42xf32>
|
||||
return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: func @memref_cast_dynamic_to_static
|
||||
func @memref_cast_dynamic_to_static(%dynamic : memref<?x?xf32>) {
|
||||
// CHECK-NEXT: %0 = "llvm.extractvalue"(%arg0) {position: [0]} : (!llvm<"{ float*, i64, i64 }">) -> !llvm<"float*">
|
||||
// CHECK-NEXT: %0 = llvm.extractvalue %arg0[0] : !llvm<"{ float*, i64, i64 }">
|
||||
%0 = memref_cast %dynamic : memref<?x?xf32> to memref<10x12xf32>
|
||||
return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: func @memref_cast_dynamic_to_mixed
|
||||
func @memref_cast_dynamic_to_mixed(%dynamic : memref<?x?xf32>) {
|
||||
// CHECK-NEXT: %0 = "llvm.extractvalue"(%arg0) {position: [0]} : (!llvm<"{ float*, i64, i64 }">) -> !llvm<"float*">
|
||||
// CHECK-NEXT: %1 = "llvm.undef"() : () -> !llvm<"{ float*, i64 }">
|
||||
// CHECK-NEXT: %2 = "llvm.insertvalue"(%1, %0) {position: [0]} : (!llvm<"{ float*, i64 }">, !llvm<"float*">) -> !llvm<"{ float*, i64 }">
|
||||
// CHECK-NEXT: %3 = "llvm.extractvalue"(%arg0) {position: [1]} : (!llvm<"{ float*, i64, i64 }">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: %4 = "llvm.insertvalue"(%2, %3) {position: [1]} : (!llvm<"{ float*, i64 }">, !llvm<"i64">) -> !llvm<"{ float*, i64 }">
|
||||
// CHECK-NEXT: %0 = llvm.extractvalue %arg0[0] : !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %1 = llvm.undef : !llvm<"{ float*, i64 }">
|
||||
// CHECK-NEXT: %2 = llvm.insertvalue %0, %1[0] : !llvm<"{ float*, i64 }">
|
||||
// CHECK-NEXT: %3 = llvm.extractvalue %arg0[1] : !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %4 = llvm.insertvalue %3, %2[1] : !llvm<"{ float*, i64 }">
|
||||
%0 = memref_cast %dynamic : memref<?x?xf32> to memref<?x12xf32>
|
||||
return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: func @memref_cast_mixed_to_dynamic
|
||||
func @memref_cast_mixed_to_dynamic(%mixed : memref<42x?xf32>) {
|
||||
// CHECK-NEXT: %0 = "llvm.extractvalue"(%arg0) {position: [0]} : (!llvm<"{ float*, i64 }">) -> !llvm<"float*">
|
||||
// CHECK-NEXT: %1 = "llvm.undef"() : () -> !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %2 = "llvm.insertvalue"(%1, %0) {position: [0]} : (!llvm<"{ float*, i64, i64 }">, !llvm<"float*">) -> !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %3 = "llvm.constant"() {value: 42 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: %4 = "llvm.insertvalue"(%2, %3) {position: [1]} : (!llvm<"{ float*, i64, i64 }">, !llvm<"i64">) -> !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %5 = "llvm.extractvalue"(%arg0) {position: [1]} : (!llvm<"{ float*, i64 }">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: %6 = "llvm.insertvalue"(%4, %5) {position: [2]} : (!llvm<"{ float*, i64, i64 }">, !llvm<"i64">) -> !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %0 = llvm.extractvalue %arg0[0] : !llvm<"{ float*, i64 }">
|
||||
// CHECK-NEXT: %1 = llvm.undef : !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %2 = llvm.insertvalue %0, %1[0] : !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %3 = llvm.constant(42 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: %4 = llvm.insertvalue %3, %2[1] : !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: %5 = llvm.extractvalue %arg0[1] : !llvm<"{ float*, i64 }">
|
||||
// CHECK-NEXT: %6 = llvm.insertvalue %5, %4[2] : !llvm<"{ float*, i64, i64 }">
|
||||
%0 = memref_cast %mixed : memref<42x?xf32> to memref<?x?xf32>
|
||||
return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: func @memref_cast_mixed_to_static
|
||||
func @memref_cast_mixed_to_static(%mixed : memref<42x?xf32>) {
|
||||
// CHECK-NEXT: %0 = "llvm.extractvalue"(%arg0) {position: [0]} : (!llvm<"{ float*, i64 }">) -> !llvm<"float*">
|
||||
// CHECK-NEXT: %0 = llvm.extractvalue %arg0[0] : !llvm<"{ float*, i64 }">
|
||||
%0 = memref_cast %mixed : memref<42x?xf32> to memref<42x1xf32>
|
||||
return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: func @memref_cast_mixed_to_mixed
|
||||
func @memref_cast_mixed_to_mixed(%mixed : memref<42x?xf32>) {
|
||||
// CHECK-NEXT: %0 = "llvm.extractvalue"(%arg0) {position: [0]} : (!llvm<"{ float*, i64 }">) -> !llvm<"float*">
|
||||
// CHECK-NEXT: %1 = "llvm.undef"() : () -> !llvm<"{ float*, i64 }">
|
||||
// CHECK-NEXT: %2 = "llvm.insertvalue"(%1, %0) {position: [0]} : (!llvm<"{ float*, i64 }">, !llvm<"float*">) -> !llvm<"{ float*, i64 }">
|
||||
// CHECK-NEXT: %3 = "llvm.constant"() {value: 42 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: %4 = "llvm.insertvalue"(%2, %3) {position: [1]} : (!llvm<"{ float*, i64 }">, !llvm<"i64">) -> !llvm<"{ float*, i64 }">
|
||||
// CHECK-NEXT: %0 = llvm.extractvalue %arg0[0] : !llvm<"{ float*, i64 }">
|
||||
// CHECK-NEXT: %1 = llvm.undef : !llvm<"{ float*, i64 }">
|
||||
// CHECK-NEXT: %2 = llvm.insertvalue %0, %1[0] : !llvm<"{ float*, i64 }">
|
||||
// CHECK-NEXT: %3 = llvm.constant(42 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: %4 = llvm.insertvalue %3, %2[1] : !llvm<"{ float*, i64 }">
|
||||
%0 = memref_cast %mixed : memref<42x?xf32> to memref<?x1xf32>
|
||||
return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: func @mixed_memref_dim(%arg0: !llvm<"{ float*, i64, i64, i64 }">)
|
||||
func @mixed_memref_dim(%mixed : memref<42x?x?x13x?xf32>) {
|
||||
// CHECK-NEXT: %0 = "llvm.constant"() {value: 42 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: %0 = llvm.constant(42 : index) : !llvm<"i64">
|
||||
%0 = dim %mixed, 0 : memref<42x?x?x13x?xf32>
|
||||
// CHECK-NEXT: %1 = "llvm.extractvalue"(%arg0) {position: [1]} : (!llvm<"{ float*, i64, i64, i64 }">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: %1 = llvm.extractvalue %arg0[1] : !llvm<"{ float*, i64, i64, i64 }">
|
||||
%1 = dim %mixed, 1 : memref<42x?x?x13x?xf32>
|
||||
// CHECK-NEXT: %2 = "llvm.extractvalue"(%arg0) {position: [2]} : (!llvm<"{ float*, i64, i64, i64 }">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: %2 = llvm.extractvalue %arg0[2] : !llvm<"{ float*, i64, i64, i64 }">
|
||||
%2 = dim %mixed, 2 : memref<42x?x?x13x?xf32>
|
||||
// CHECK-NEXT: %3 = "llvm.constant"() {value: 13 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: %3 = llvm.constant(13 : index) : !llvm<"i64">
|
||||
%3 = dim %mixed, 3 : memref<42x?x?x13x?xf32>
|
||||
// CHECK-NEXT: %4 = "llvm.extractvalue"(%arg0) {position: [3]} : (!llvm<"{ float*, i64, i64, i64 }">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: %4 = llvm.extractvalue %arg0[3] : !llvm<"{ float*, i64, i64, i64 }">
|
||||
%4 = dim %mixed, 4 : memref<42x?x?x13x?xf32>
|
||||
return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: func @static_memref_dim(%arg0: !llvm<"float*">)
|
||||
func @static_memref_dim(%static : memref<42x32x15x13x27xf32>) {
|
||||
// CHECK-NEXT: %0 = "llvm.constant"() {value: 42 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: %0 = llvm.constant(42 : index) : !llvm<"i64">
|
||||
%0 = dim %static, 0 : memref<42x32x15x13x27xf32>
|
||||
// CHECK-NEXT: %1 = "llvm.constant"() {value: 32 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: %1 = llvm.constant(32 : index) : !llvm<"i64">
|
||||
%1 = dim %static, 1 : memref<42x32x15x13x27xf32>
|
||||
// CHECK-NEXT: %2 = "llvm.constant"() {value: 15 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: %2 = llvm.constant(15 : index) : !llvm<"i64">
|
||||
%2 = dim %static, 2 : memref<42x32x15x13x27xf32>
|
||||
// CHECK-NEXT: %3 = "llvm.constant"() {value: 13 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: %3 = llvm.constant(13 : index) : !llvm<"i64">
|
||||
%3 = dim %static, 3 : memref<42x32x15x13x27xf32>
|
||||
// CHECK-NEXT: %4 = "llvm.constant"() {value: 27 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: %4 = llvm.constant(27 : index) : !llvm<"i64">
|
||||
%4 = dim %static, 4 : memref<42x32x15x13x27xf32>
|
||||
return
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// RUN: mlir-opt -convert-to-llvmir %s | FileCheck %s
|
||||
|
||||
// CHECK-LABEL: func @empty() {
|
||||
// CHECK-NEXT: "llvm.return"() : () -> ()
|
||||
// CHECK-NEXT: llvm.return
|
||||
// CHECK-NEXT: }
|
||||
func @empty() {
|
||||
^bb0:
|
||||
|
@ -14,30 +14,30 @@ func @body(index)
|
|||
// CHECK-LABEL: func @simple_loop() {
|
||||
func @simple_loop() {
|
||||
^bb0:
|
||||
// CHECK-NEXT: "llvm.br"()[^bb1] : () -> ()
|
||||
// CHECK-NEXT: llvm.br ^bb1
|
||||
br ^bb1
|
||||
|
||||
// CHECK-NEXT: ^bb1: // pred: ^bb0
|
||||
// CHECK-NEXT: {{.*}} = "llvm.constant"() {value: 1 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = "llvm.constant"() {value: 42 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: "llvm.br"()[^bb2({{.*}} : !llvm<"i64">)] : () -> ()
|
||||
// CHECK-NEXT: {{.*}} = llvm.constant(1 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = llvm.constant(42 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: llvm.br ^bb2({{.*}} : !llvm<"i64">)
|
||||
^bb1: // pred: ^bb0
|
||||
%c1 = constant 1 : index
|
||||
%c42 = constant 42 : index
|
||||
br ^bb2(%c1 : index)
|
||||
|
||||
// CHECK: ^bb2({{.*}}: !llvm<"i64">): // 2 preds: ^bb1, ^bb3
|
||||
// CHECK-NEXT: {{.*}} = "llvm.icmp"({{.*}}, {{.*}}) {predicate: 2} : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i1">
|
||||
// CHECK-NEXT: "llvm.cond_br"({{.*}})[^bb3, ^bb4] : (!llvm<"i1">) -> ()
|
||||
// CHECK-NEXT: {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : !llvm<"i64">
|
||||
// CHECK-NEXT: llvm.cond_br {{.*}}, ^bb3, ^bb4
|
||||
^bb2(%0: index): // 2 preds: ^bb1, ^bb3
|
||||
%1 = cmpi "slt", %0, %c42 : index
|
||||
cond_br %1, ^bb3, ^bb4
|
||||
|
||||
// CHECK: ^bb3: // pred: ^bb2
|
||||
// CHECK-NEXT: "llvm.call"({{.*}}) {callee: @body : (!llvm<"i64">) -> ()} : (!llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: {{.*}} = "llvm.constant"() {value: 1 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = "llvm.add"({{.*}}, {{.*}}) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: "llvm.br"()[^bb2({{.*}} : !llvm<"i64">)] : () -> ()
|
||||
// CHECK-NEXT: llvm.call @body({{.*}}) : (!llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: {{.*}} = llvm.constant(1 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = llvm.add {{.*}}, {{.*}} : !llvm<"i64">
|
||||
// CHECK-NEXT: llvm.br ^bb2({{.*}} : !llvm<"i64">)
|
||||
^bb3: // pred: ^bb2
|
||||
call @body(%0) : (index) -> ()
|
||||
%c1_0 = constant 1 : index
|
||||
|
@ -45,14 +45,14 @@ func @simple_loop() {
|
|||
br ^bb2(%2 : index)
|
||||
|
||||
// CHECK: ^bb4: // pred: ^bb2
|
||||
// CHECK-NEXT: "llvm.return"() : () -> ()
|
||||
// CHECK-NEXT: llvm.return
|
||||
^bb4: // pred: ^bb2
|
||||
return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: func @simple_caller() {
|
||||
// CHECK-NEXT: "llvm.call"() {callee: @simple_loop : () -> ()} : () -> ()
|
||||
// CHECK-NEXT: "llvm.return"() : () -> ()
|
||||
// CHECK-NEXT: llvm.call @simple_loop() : () -> ()
|
||||
// CHECK-NEXT: llvm.return
|
||||
// CHECK-NEXT: }
|
||||
func @simple_caller() {
|
||||
^bb0:
|
||||
|
@ -61,9 +61,9 @@ func @simple_caller() {
|
|||
}
|
||||
|
||||
// CHECK-LABEL: func @ml_caller() {
|
||||
// CHECK-NEXT: "llvm.call"() {callee: @simple_loop : () -> ()} : () -> ()
|
||||
// CHECK-NEXT: "llvm.call"() {callee: @more_imperfectly_nested_loops : () -> ()} : () -> ()
|
||||
// CHECK-NEXT: "llvm.return"() : () -> ()
|
||||
// CHECK-NEXT: llvm.call @simple_loop() : () -> ()
|
||||
// CHECK-NEXT: llvm.call @more_imperfectly_nested_loops() : () -> ()
|
||||
// CHECK-NEXT: llvm.return
|
||||
// CHECK-NEXT: }
|
||||
func @ml_caller() {
|
||||
^bb0:
|
||||
|
@ -78,37 +78,37 @@ func @body_args(index) -> index
|
|||
func @other(index, i32) -> i32
|
||||
|
||||
// CHECK-LABEL: func @func_args(%arg0: !llvm<"i32">, %arg1: !llvm<"i32">) -> !llvm<"i32"> {
|
||||
// CHECK-NEXT: {{.*}} = "llvm.constant"() {value: 0 : i32} : () -> !llvm<"i32">
|
||||
// CHECK-NEXT: "llvm.br"()[^bb1] : () -> ()
|
||||
// CHECK-NEXT: {{.*}} = llvm.constant(0 : i32) : !llvm<"i32">
|
||||
// CHECK-NEXT: llvm.br ^bb1
|
||||
func @func_args(i32, i32) -> i32 {
|
||||
^bb0(%arg0: i32, %arg1: i32):
|
||||
%c0_i32 = constant 0 : i32
|
||||
br ^bb1
|
||||
|
||||
// CHECK-NEXT: ^bb1: // pred: ^bb0
|
||||
// CHECK-NEXT: {{.*}} = "llvm.constant"() {value: 0 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = "llvm.constant"() {value: 42 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: "llvm.br"()[^bb2({{.*}} : !llvm<"i64">)] : () -> ()
|
||||
// CHECK-NEXT: {{.*}} = llvm.constant(0 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = llvm.constant(42 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: llvm.br ^bb2({{.*}} : !llvm<"i64">)
|
||||
^bb1: // pred: ^bb0
|
||||
%c0 = constant 0 : index
|
||||
%c42 = constant 42 : index
|
||||
br ^bb2(%c0 : index)
|
||||
|
||||
// CHECK-NEXT: ^bb2({{.*}}: !llvm<"i64">): // 2 preds: ^bb1, ^bb3
|
||||
// CHECK-NEXT: {{.*}} = "llvm.icmp"({{.*}}, {{.*}}) {predicate: 2} : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i1">
|
||||
// CHECK-NEXT: "llvm.cond_br"({{.*}})[^bb3, ^bb4] : (!llvm<"i1">) -> ()
|
||||
// CHECK-NEXT: {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : !llvm<"i64">
|
||||
// CHECK-NEXT: llvm.cond_br {{.*}}, ^bb3, ^bb4
|
||||
^bb2(%0: index): // 2 preds: ^bb1, ^bb3
|
||||
%1 = cmpi "slt", %0, %c42 : index
|
||||
cond_br %1, ^bb3, ^bb4
|
||||
|
||||
// CHECK-NEXT: ^bb3: // pred: ^bb2
|
||||
// CHECK-NEXT: {{.*}} = "llvm.call"({{.*}}) {callee: @body_args : (!llvm<"i64">) -> !llvm<"i64">} : (!llvm<"i64">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = "llvm.call"({{.*}}, %arg0) {callee: @other : (!llvm<"i64">, !llvm<"i32">) -> !llvm<"i32">} : (!llvm<"i64">, !llvm<"i32">) -> !llvm<"i32">
|
||||
// CHECK-NEXT: {{.*}} = "llvm.call"({{.*}}, {{.*}}) {callee: @other : (!llvm<"i64">, !llvm<"i32">) -> !llvm<"i32">} : (!llvm<"i64">, !llvm<"i32">) -> !llvm<"i32">
|
||||
// CHECK-NEXT: {{.*}} = "llvm.call"({{.*}}, %arg1) {callee: @other : (!llvm<"i64">, !llvm<"i32">) -> !llvm<"i32">} : (!llvm<"i64">, !llvm<"i32">) -> !llvm<"i32">
|
||||
// CHECK-NEXT: {{.*}} = "llvm.constant"() {value: 1 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = "llvm.add"({{.*}}, {{.*}}) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: "llvm.br"()[^bb2({{.*}} : !llvm<"i64">)] : () -> ()
|
||||
// CHECK-NEXT: {{.*}} = llvm.call @body_args({{.*}}) : (!llvm<"i64">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = llvm.call @other({{.*}}, %arg0) : (!llvm<"i64">, !llvm<"i32">) -> !llvm<"i32">
|
||||
// CHECK-NEXT: {{.*}} = llvm.call @other({{.*}}, {{.*}}) : (!llvm<"i64">, !llvm<"i32">) -> !llvm<"i32">
|
||||
// CHECK-NEXT: {{.*}} = llvm.call @other({{.*}}, %arg1) : (!llvm<"i64">, !llvm<"i32">) -> !llvm<"i32">
|
||||
// CHECK-NEXT: {{.*}} = llvm.constant(1 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = llvm.add {{.*}}, {{.*}} : !llvm<"i64">
|
||||
// CHECK-NEXT: llvm.br ^bb2({{.*}} : !llvm<"i64">)
|
||||
^bb3: // pred: ^bb2
|
||||
%2 = call @body_args(%0) : (index) -> index
|
||||
%3 = call @other(%2, %arg0) : (index, i32) -> i32
|
||||
|
@ -119,9 +119,9 @@ func @func_args(i32, i32) -> i32 {
|
|||
br ^bb2(%6 : index)
|
||||
|
||||
// CHECK-NEXT: ^bb4: // pred: ^bb2
|
||||
// CHECK-NEXT: {{.*}} = "llvm.constant"() {value: 0 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = "llvm.call"({{.*}}, {{.*}}) {callee: @other : (!llvm<"i64">, !llvm<"i32">) -> !llvm<"i32">} : (!llvm<"i64">, !llvm<"i32">) -> !llvm<"i32">
|
||||
// CHECK-NEXT: "llvm.return"({{.*}}) : (!llvm<"i32">) -> ()
|
||||
// CHECK-NEXT: {{.*}} = llvm.constant(0 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = llvm.call @other({{.*}}, {{.*}}) : (!llvm<"i64">, !llvm<"i32">) -> !llvm<"i32">
|
||||
// CHECK-NEXT: llvm.return {{.*}} : !llvm<"i32">
|
||||
^bb4: // pred: ^bb2
|
||||
%c0_0 = constant 0 : index
|
||||
%7 = call @other(%c0_0, %c0_i32) : (index, i32) -> i32
|
||||
|
@ -138,55 +138,55 @@ func @body2(index, index)
|
|||
func @post(index)
|
||||
|
||||
// CHECK-LABEL: func @imperfectly_nested_loops() {
|
||||
// CHECK-NEXT: "llvm.br"()[^bb1] : () -> ()
|
||||
// CHECK-NEXT: llvm.br ^bb1
|
||||
func @imperfectly_nested_loops() {
|
||||
^bb0:
|
||||
br ^bb1
|
||||
|
||||
// CHECK-NEXT: ^bb1: // pred: ^bb0
|
||||
// CHECK-NEXT: {{.*}} = "llvm.constant"() {value: 0 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = "llvm.constant"() {value: 42 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: "llvm.br"()[^bb2({{.*}} : !llvm<"i64">)] : () -> ()
|
||||
// CHECK-NEXT: {{.*}} = llvm.constant(0 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = llvm.constant(42 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: llvm.br ^bb2({{.*}} : !llvm<"i64">)
|
||||
^bb1: // pred: ^bb0
|
||||
%c0 = constant 0 : index
|
||||
%c42 = constant 42 : index
|
||||
br ^bb2(%c0 : index)
|
||||
|
||||
// CHECK-NEXT: ^bb2({{.*}}: !llvm<"i64">): // 2 preds: ^bb1, ^bb7
|
||||
// CHECK-NEXT: {{.*}} = "llvm.icmp"({{.*}}, {{.*}}) {predicate: 2} : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i1">
|
||||
// CHECK-NEXT: "llvm.cond_br"({{.*}})[^bb3, ^bb8] : (!llvm<"i1">) -> ()
|
||||
// CHECK-NEXT: {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : !llvm<"i64">
|
||||
// CHECK-NEXT: llvm.cond_br {{.*}}, ^bb3, ^bb8
|
||||
^bb2(%0: index): // 2 preds: ^bb1, ^bb7
|
||||
%1 = cmpi "slt", %0, %c42 : index
|
||||
cond_br %1, ^bb3, ^bb8
|
||||
|
||||
// CHECK-NEXT: ^bb3:
|
||||
// CHECK-NEXT: "llvm.call"({{.*}}) {callee: @pre : (!llvm<"i64">) -> ()} : (!llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: "llvm.br"()[^bb4] : () -> ()
|
||||
// CHECK-NEXT: llvm.call @pre({{.*}}) : (!llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: llvm.br ^bb4
|
||||
^bb3: // pred: ^bb2
|
||||
call @pre(%0) : (index) -> ()
|
||||
br ^bb4
|
||||
|
||||
// CHECK-NEXT: ^bb4: // pred: ^bb3
|
||||
// CHECK-NEXT: {{.*}} = "llvm.constant"() {value: 7 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = "llvm.constant"() {value: 56 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: "llvm.br"()[^bb5({{.*}} : !llvm<"i64">)] : () -> ()
|
||||
// CHECK-NEXT: {{.*}} = llvm.constant(7 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = llvm.constant(56 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: llvm.br ^bb5({{.*}} : !llvm<"i64">)
|
||||
^bb4: // pred: ^bb3
|
||||
%c7 = constant 7 : index
|
||||
%c56 = constant 56 : index
|
||||
br ^bb5(%c7 : index)
|
||||
|
||||
// CHECK-NEXT: ^bb5({{.*}}: !llvm<"i64">): // 2 preds: ^bb4, ^bb6
|
||||
// CHECK-NEXT: {{.*}} = "llvm.icmp"({{.*}}, {{.*}}) {predicate: 2} : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i1">
|
||||
// CHECK-NEXT: "llvm.cond_br"({{.*}})[^bb6, ^bb7] : (!llvm<"i1">) -> ()
|
||||
// CHECK-NEXT: {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : !llvm<"i64">
|
||||
// CHECK-NEXT: llvm.cond_br {{.*}}, ^bb6, ^bb7
|
||||
^bb5(%2: index): // 2 preds: ^bb4, ^bb6
|
||||
%3 = cmpi "slt", %2, %c56 : index
|
||||
cond_br %3, ^bb6, ^bb7
|
||||
|
||||
// CHECK-NEXT: ^bb6: // pred: ^bb5
|
||||
// CHECK-NEXT: "llvm.call"({{.*}}, {{.*}}) {callee: @body2 : (!llvm<"i64">, !llvm<"i64">) -> ()} : (!llvm<"i64">, !llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: {{.*}} = "llvm.constant"() {value: 2 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = "llvm.add"({{.*}}, {{.*}}) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: "llvm.br"()[^bb5({{.*}} : !llvm<"i64">)] : () -> ()
|
||||
// CHECK-NEXT: llvm.call @body2({{.*}}, {{.*}}) : (!llvm<"i64">, !llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: {{.*}} = llvm.constant(2 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = llvm.add {{.*}}, {{.*}} : !llvm<"i64">
|
||||
// CHECK-NEXT: llvm.br ^bb5({{.*}} : !llvm<"i64">)
|
||||
^bb6: // pred: ^bb5
|
||||
call @body2(%0, %2) : (index, index) -> ()
|
||||
%c2 = constant 2 : index
|
||||
|
@ -194,10 +194,10 @@ func @imperfectly_nested_loops() {
|
|||
br ^bb5(%4 : index)
|
||||
|
||||
// CHECK-NEXT: ^bb7: // pred: ^bb5
|
||||
// CHECK-NEXT: "llvm.call"({{.*}}) {callee: @post : (!llvm<"i64">) -> ()} : (!llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: {{.*}} = "llvm.constant"() {value: 1 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = "llvm.add"({{.*}}, {{.*}}) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: "llvm.br"()[^bb2({{.*}} : !llvm<"i64">)] : () -> ()
|
||||
// CHECK-NEXT: llvm.call @post({{.*}}) : (!llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: {{.*}} = llvm.constant(1 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = llvm.add {{.*}}, {{.*}} : !llvm<"i64">
|
||||
// CHECK-NEXT: llvm.br ^bb2({{.*}} : !llvm<"i64">)
|
||||
^bb7: // pred: ^bb5
|
||||
call @post(%0) : (index) -> ()
|
||||
%c1 = constant 1 : index
|
||||
|
@ -205,7 +205,7 @@ func @imperfectly_nested_loops() {
|
|||
br ^bb2(%5 : index)
|
||||
|
||||
// CHECK-NEXT: ^bb8: // pred: ^bb2
|
||||
// CHECK-NEXT: "llvm.return"() : () -> ()
|
||||
// CHECK-NEXT: llvm.return
|
||||
^bb8: // pred: ^bb2
|
||||
return
|
||||
}
|
||||
|
@ -218,51 +218,51 @@ func @body3(index, index)
|
|||
|
||||
// A complete function transformation check.
|
||||
// CHECK-LABEL: func @more_imperfectly_nested_loops() {
|
||||
// CHECK-NEXT: "llvm.br"()[^bb1] : () -> ()
|
||||
// CHECK-NEXT: ^bb1: // pred: ^bb0
|
||||
// CHECK-NEXT: {{.*}} = "llvm.constant"() {value: 0 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = "llvm.constant"() {value: 42 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: "llvm.br"()[^bb2({{.*}} : !llvm<"i64">)] : () -> ()
|
||||
// CHECK-NEXT: ^bb2({{.*}}: !llvm<"i64">): // 2 preds: ^bb1, ^bb11
|
||||
// CHECK-NEXT: {{.*}} = "llvm.icmp"({{.*}}, {{.*}}) {predicate: 2} : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i1">
|
||||
// CHECK-NEXT: "llvm.cond_br"({{.*}})[^bb3, ^bb12] : (!llvm<"i1">) -> ()
|
||||
// CHECK-NEXT: ^bb3: // pred: ^bb2
|
||||
// CHECK-NEXT: "llvm.call"({{.*}}) {callee: @pre : (!llvm<"i64">) -> ()} : (!llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: "llvm.br"()[^bb4] : () -> ()
|
||||
// CHECK-NEXT: ^bb4: // pred: ^bb3
|
||||
// CHECK-NEXT: {{.*}} = "llvm.constant"() {value: 7 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = "llvm.constant"() {value: 56 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: "llvm.br"()[^bb5({{.*}} : !llvm<"i64">)] : () -> ()
|
||||
// CHECK-NEXT: ^bb5({{.*}}: !llvm<"i64">): // 2 preds: ^bb4, ^bb6
|
||||
// CHECK-NEXT: {{.*}} = "llvm.icmp"({{.*}}, {{.*}}) {predicate: 2} : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i1">
|
||||
// CHECK-NEXT: "llvm.cond_br"({{.*}})[^bb6, ^bb7] : (!llvm<"i1">) -> ()
|
||||
// CHECK-NEXT: ^bb6: // pred: ^bb5
|
||||
// CHECK-NEXT: "llvm.call"({{.*}}, {{.*}}) {callee: @body2 : (!llvm<"i64">, !llvm<"i64">) -> ()} : (!llvm<"i64">, !llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: {{.*}} = "llvm.constant"() {value: 2 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = "llvm.add"({{.*}}, {{.*}}) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: "llvm.br"()[^bb5({{.*}} : !llvm<"i64">)] : () -> ()
|
||||
// CHECK-NEXT: ^bb7: // pred: ^bb5
|
||||
// CHECK-NEXT: "llvm.call"({{.*}}) {callee: @mid : (!llvm<"i64">) -> ()} : (!llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: "llvm.br"()[^bb8] : () -> ()
|
||||
// CHECK-NEXT: ^bb8: // pred: ^bb7
|
||||
// CHECK-NEXT: {{.*}} = "llvm.constant"() {value: 18 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = "llvm.constant"() {value: 37 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: "llvm.br"()[^bb9({{.*}} : !llvm<"i64">)] : () -> ()
|
||||
// CHECK-NEXT: ^bb9({{.*}}: !llvm<"i64">): // 2 preds: ^bb8, ^bb10
|
||||
// CHECK-NEXT: {{.*}} = "llvm.icmp"({{.*}}, {{.*}}) {predicate: 2} : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i1">
|
||||
// CHECK-NEXT: "llvm.cond_br"({{.*}})[^bb10, ^bb11] : (!llvm<"i1">) -> ()
|
||||
// CHECK-NEXT: ^bb10: // pred: ^bb9
|
||||
// CHECK-NEXT: "llvm.call"({{.*}}, {{.*}}) {callee: @body3 : (!llvm<"i64">, !llvm<"i64">) -> ()} : (!llvm<"i64">, !llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: {{.*}} = "llvm.constant"() {value: 3 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = "llvm.add"({{.*}}, {{.*}}) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: "llvm.br"()[^bb9({{.*}} : !llvm<"i64">)] : () -> ()
|
||||
// CHECK-NEXT: ^bb11: // pred: ^bb9
|
||||
// CHECK-NEXT: "llvm.call"({{.*}}) {callee: @post : (!llvm<"i64">) -> ()} : (!llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: {{.*}} = "llvm.constant"() {value: 1 : index} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = "llvm.add"({{.*}}, {{.*}}) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: "llvm.br"()[^bb2({{.*}} : !llvm<"i64">)] : () -> ()
|
||||
// CHECK-NEXT: ^bb12: // pred: ^bb2
|
||||
// CHECK-NEXT: "llvm.return"() : () -> ()
|
||||
// CHECK-NEXT: llvm.br ^bb1
|
||||
// CHECK-NEXT:^bb1: // pred: ^bb0
|
||||
// CHECK-NEXT: {{.*}} = llvm.constant(0 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = llvm.constant(42 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: llvm.br ^bb2({{.*}} : !llvm<"i64">)
|
||||
// CHECK-NEXT:^bb2({{.*}}: !llvm<"i64">): // 2 preds: ^bb1, ^bb11
|
||||
// CHECK-NEXT: {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : !llvm<"i64">
|
||||
// CHECK-NEXT: llvm.cond_br {{.*}}, ^bb3, ^bb12
|
||||
// CHECK-NEXT:^bb3: // pred: ^bb2
|
||||
// CHECK-NEXT: llvm.call @pre({{.*}}) : (!llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: llvm.br ^bb4
|
||||
// CHECK-NEXT:^bb4: // pred: ^bb3
|
||||
// CHECK-NEXT: {{.*}} = llvm.constant(7 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = llvm.constant(56 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: llvm.br ^bb5({{.*}} : !llvm<"i64">)
|
||||
// CHECK-NEXT:^bb5({{.*}}: !llvm<"i64">): // 2 preds: ^bb4, ^bb6
|
||||
// CHECK-NEXT: {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : !llvm<"i64">
|
||||
// CHECK-NEXT: llvm.cond_br {{.*}}, ^bb6, ^bb7
|
||||
// CHECK-NEXT:^bb6: // pred: ^bb5
|
||||
// CHECK-NEXT: llvm.call @body2({{.*}}, {{.*}}) : (!llvm<"i64">, !llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: {{.*}} = llvm.constant(2 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = llvm.add {{.*}}, {{.*}} : !llvm<"i64">
|
||||
// CHECK-NEXT: llvm.br ^bb5({{.*}} : !llvm<"i64">)
|
||||
// CHECK-NEXT:^bb7: // pred: ^bb5
|
||||
// CHECK-NEXT: llvm.call @mid({{.*}}) : (!llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: llvm.br ^bb8
|
||||
// CHECK-NEXT:^bb8: // pred: ^bb7
|
||||
// CHECK-NEXT: {{.*}} = llvm.constant(18 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = llvm.constant(37 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: llvm.br ^bb9({{.*}} : !llvm<"i64">)
|
||||
// CHECK-NEXT:^bb9({{.*}}: !llvm<"i64">): // 2 preds: ^bb8, ^bb10
|
||||
// CHECK-NEXT: {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : !llvm<"i64">
|
||||
// CHECK-NEXT: llvm.cond_br {{.*}}, ^bb10, ^bb11
|
||||
// CHECK-NEXT:^bb10: // pred: ^bb9
|
||||
// CHECK-NEXT: llvm.call @body3({{.*}}, {{.*}}) : (!llvm<"i64">, !llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: {{.*}} = llvm.constant(3 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = llvm.add {{.*}}, {{.*}} : !llvm<"i64">
|
||||
// CHECK-NEXT: llvm.br ^bb9({{.*}} : !llvm<"i64">)
|
||||
// CHECK-NEXT:^bb11: // pred: ^bb9
|
||||
// CHECK-NEXT: llvm.call @post({{.*}}) : (!llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: {{.*}} = llvm.constant(1 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = llvm.add {{.*}}, {{.*}} : !llvm<"i64">
|
||||
// CHECK-NEXT: llvm.br ^bb2({{.*}} : !llvm<"i64">)
|
||||
// CHECK-NEXT:^bb12: // pred: ^bb2
|
||||
// CHECK-NEXT: llvm.return
|
||||
// CHECK-NEXT: }
|
||||
func @more_imperfectly_nested_loops() {
|
||||
^bb0:
|
||||
|
@ -323,17 +323,17 @@ func @get_memref() -> (memref<42x?x10x?xf32>)
|
|||
// CHECK-LABEL: func @multireturn() -> !llvm<"{ i64, float, { float*, i64, i64 } }"> {
|
||||
func @multireturn() -> (i64, f32, memref<42x?x10x?xf32>) {
|
||||
^bb0:
|
||||
// CHECK-NEXT: {{.*}} = "llvm.call"() {callee: @get_i64 : () -> !llvm<"i64">} : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = "llvm.call"() {callee: @get_f32 : () -> !llvm<"float">} : () -> !llvm<"float">
|
||||
// CHECK-NEXT: {{.*}} = "llvm.call"() {callee: @get_memref : () -> !llvm<"{ float*, i64, i64 }">} : () -> !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: {{.*}} = llvm.call @get_i64() : () -> !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = llvm.call @get_f32() : () -> !llvm<"float">
|
||||
// CHECK-NEXT: {{.*}} = llvm.call @get_memref() : () -> !llvm<"{ float*, i64, i64 }">
|
||||
%0 = call @get_i64() : () -> (i64)
|
||||
%1 = call @get_f32() : () -> (f32)
|
||||
%2 = call @get_memref() : () -> (memref<42x?x10x?xf32>)
|
||||
// CHECK-NEXT: {{.*}} = "llvm.undef"() : () -> !llvm<"{ i64, float, { float*, i64, i64 } }">
|
||||
// CHECK-NEXT: {{.*}} = "llvm.insertvalue"({{.*}}, {{.*}}) {position: [0]} : (!llvm<"{ i64, float, { float*, i64, i64 } }">, !llvm<"i64">) -> !llvm<"{ i64, float, { float*, i64, i64 } }">
|
||||
// CHECK-NEXT: {{.*}} = "llvm.insertvalue"({{.*}}, {{.*}}) {position: [1]} : (!llvm<"{ i64, float, { float*, i64, i64 } }">, !llvm<"float">) -> !llvm<"{ i64, float, { float*, i64, i64 } }">
|
||||
// CHECK-NEXT: {{.*}} = "llvm.insertvalue"({{.*}}, {{.*}}) {position: [2]} : (!llvm<"{ i64, float, { float*, i64, i64 } }">, !llvm<"{ float*, i64, i64 }">) -> !llvm<"{ i64, float, { float*, i64, i64 } }">
|
||||
// CHECK-NEXT: "llvm.return"({{.*}}) : (!llvm<"{ i64, float, { float*, i64, i64 } }">) -> ()
|
||||
// CHECK-NEXT: {{.*}} = llvm.undef : !llvm<"{ i64, float, { float*, i64, i64 } }">
|
||||
// CHECK-NEXT: {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[0] : !llvm<"{ i64, float, { float*, i64, i64 } }">
|
||||
// CHECK-NEXT: {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[1] : !llvm<"{ i64, float, { float*, i64, i64 } }">
|
||||
// CHECK-NEXT: {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[2] : !llvm<"{ i64, float, { float*, i64, i64 } }">
|
||||
// CHECK-NEXT: llvm.return {{.*}} : !llvm<"{ i64, float, { float*, i64, i64 } }">
|
||||
return %0, %1, %2 : i64, f32, memref<42x?x10x?xf32>
|
||||
}
|
||||
|
||||
|
@ -341,16 +341,16 @@ func @multireturn() -> (i64, f32, memref<42x?x10x?xf32>) {
|
|||
// CHECK-LABEL: func @multireturn_caller() {
|
||||
func @multireturn_caller() {
|
||||
^bb0:
|
||||
// CHECK-NEXT: {{.*}} = "llvm.call"() {callee: @multireturn : () -> !llvm<"{ i64, float, { float*, i64, i64 } }">} : () -> !llvm<"{ i64, float, { float*, i64, i64 } }">
|
||||
// CHECK-NEXT: {{.*}} = "llvm.extractvalue"({{.*}}) {position: [0]} : (!llvm<"{ i64, float, { float*, i64, i64 } }">) -> !llvm<"i64">
|
||||
// CHECK-NEXT: {{.*}} = "llvm.extractvalue"({{.*}}) {position: [1]} : (!llvm<"{ i64, float, { float*, i64, i64 } }">) -> !llvm<"float">
|
||||
// CHECK-NEXT: {{.*}} = "llvm.extractvalue"({{.*}}) {position: [2]} : (!llvm<"{ i64, float, { float*, i64, i64 } }">) -> !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK-NEXT: {{.*}} = llvm.call @multireturn() : () -> !llvm<"{ i64, float, { float*, i64, i64 } }">
|
||||
// CHECK-NEXT: {{.*}} = llvm.extractvalue {{.*}}[0] : !llvm<"{ i64, float, { float*, i64, i64 } }">
|
||||
// CHECK-NEXT: {{.*}} = llvm.extractvalue {{.*}}[1] : !llvm<"{ i64, float, { float*, i64, i64 } }">
|
||||
// CHECK-NEXT: {{.*}} = llvm.extractvalue {{.*}}[2] : !llvm<"{ i64, float, { float*, i64, i64 } }">
|
||||
%0:3 = call @multireturn() : () -> (i64, f32, memref<42x?x10x?xf32>)
|
||||
%1 = constant 42 : i64
|
||||
// CHECK: {{.*}} = "llvm.add"({{.*}}, {{.*}}) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
// CHECK: {{.*}} = llvm.add {{.*}}, {{.*}} : !llvm<"i64">
|
||||
%2 = addi %0#0, %1 : i64
|
||||
%3 = constant 42.0 : f32
|
||||
// CHECK: {{.*}} = "llvm.fadd"({{.*}}, {{.*}}) : (!llvm<"float">, !llvm<"float">) -> !llvm<"float">
|
||||
// CHECK: {{.*}} = llvm.fadd {{.*}}, {{.*}} : !llvm<"float">
|
||||
%4 = addf %0#1, %3 : f32
|
||||
%5 = constant 0 : index
|
||||
return
|
||||
|
@ -359,21 +359,21 @@ func @multireturn_caller() {
|
|||
// CHECK-LABEL: func @vector_ops(%arg0: !llvm<"<4 x float>">, %arg1: !llvm<"<4 x i1>">, %arg2: !llvm<"<4 x i64>">) -> !llvm<"<4 x float>"> {
|
||||
func @vector_ops(vector<4xf32>, vector<4xi1>, vector<4xi64>) -> vector<4xf32> {
|
||||
^bb0(%arg0: vector<4xf32>, %arg1: vector<4xi1>, %arg2: vector<4xi64>):
|
||||
// CHECK-NEXT: {{.*}} = "llvm.constant"() {value: splat<vector<4xf32>, 4.200000e+01>} : () -> !llvm<"<4 x float>">
|
||||
// CHECK-NEXT: %0 = llvm.constant(splat<vector<4xf32>, 4.200000e+01>) : !llvm<"<4 x float>">
|
||||
%0 = constant splat<vector<4xf32>, 42.> : vector<4xf32>
|
||||
// CHECK-NEXT: {{.*}} = "llvm.fadd"(%arg0, {{.*}}) : (!llvm<"<4 x float>">, !llvm<"<4 x float>">) -> !llvm<"<4 x float>">
|
||||
// CHECK-NEXT: %1 = llvm.fadd %arg0, %0 : !llvm<"<4 x float>">
|
||||
%1 = addf %arg0, %0 : vector<4xf32>
|
||||
// CHECK-NEXT: {{.*}} = "llvm.sdiv"(%arg2, %arg2) : (!llvm<"<4 x i64>">, !llvm<"<4 x i64>">) -> !llvm<"<4 x i64>">
|
||||
// CHECK-NEXT: %2 = llvm.sdiv %arg2, %arg2 : !llvm<"<4 x i64>">
|
||||
%3 = divis %arg2, %arg2 : vector<4xi64>
|
||||
// CHECK-NEXT: {{.*}} = "llvm.udiv"(%arg2, %arg2) : (!llvm<"<4 x i64>">, !llvm<"<4 x i64>">) -> !llvm<"<4 x i64>">
|
||||
// CHECK-NEXT: %3 = llvm.udiv %arg2, %arg2 : !llvm<"<4 x i64>">
|
||||
%4 = diviu %arg2, %arg2 : vector<4xi64>
|
||||
// CHECK-NEXT: {{.*}} = "llvm.srem"(%arg2, %arg2) : (!llvm<"<4 x i64>">, !llvm<"<4 x i64>">) -> !llvm<"<4 x i64>">
|
||||
// CHECK-NEXT: %4 = llvm.srem %arg2, %arg2 : !llvm<"<4 x i64>">
|
||||
%5 = remis %arg2, %arg2 : vector<4xi64>
|
||||
// CHECK-NEXT: {{.*}} = "llvm.urem"(%arg2, %arg2) : (!llvm<"<4 x i64>">, !llvm<"<4 x i64>">) -> !llvm<"<4 x i64>">
|
||||
// CHECK-NEXT: %5 = llvm.urem %arg2, %arg2 : !llvm<"<4 x i64>">
|
||||
%6 = remiu %arg2, %arg2 : vector<4xi64>
|
||||
// CHECK-NEXT: {{.*}} = "llvm.fdiv"(%arg0, {{.*}}) : (!llvm<"<4 x float>">, !llvm<"<4 x float>">) -> !llvm<"<4 x float>">
|
||||
// CHECK-NEXT: %6 = llvm.fdiv %arg0, %0 : !llvm<"<4 x float>">
|
||||
%7 = divf %arg0, %0 : vector<4xf32>
|
||||
// CHECK-NEXT: {{.*}} = "llvm.frem"(%arg0, {{.*}}) : (!llvm<"<4 x float>">, !llvm<"<4 x float>">) -> !llvm<"<4 x float>">
|
||||
// CHECK-NEXT: %7 = llvm.frem %arg0, %0 : !llvm<"<4 x float>">
|
||||
%8 = remf %arg0, %0 : vector<4xf32>
|
||||
return %1 : vector<4xf32>
|
||||
}
|
||||
|
@ -381,25 +381,25 @@ func @vector_ops(vector<4xf32>, vector<4xi1>, vector<4xi64>) -> vector<4xf32> {
|
|||
// CHECK-LABEL: @ops
|
||||
func @ops(f32, f32, i32, i32) -> (f32, i32) {
|
||||
^bb0(%arg0: f32, %arg1: f32, %arg2: i32, %arg3: i32):
|
||||
// CHECK-NEXT: {{.*}} = "llvm.fsub"(%arg0, %arg1) : (!llvm<"float">, !llvm<"float">) -> !llvm<"float">
|
||||
// CHECK-NEXT: %0 = llvm.fsub %arg0, %arg1 : !llvm<"float">
|
||||
%0 = subf %arg0, %arg1: f32
|
||||
// CHECK-NEXT: {{.*}} = "llvm.sub"(%arg2, %arg3) : (!llvm<"i32">, !llvm<"i32">) -> !llvm<"i32">
|
||||
// CHECK-NEXT: %1 = llvm.sub %arg2, %arg3 : !llvm<"i32">
|
||||
%1 = subi %arg2, %arg3: i32
|
||||
// CHECK-NEXT: {{.*}} = "llvm.icmp"(%arg2, {{.*}}) {predicate: 2} : (!llvm<"i32">, !llvm<"i32">) -> !llvm<"i1">
|
||||
// CHECK-NEXT: %2 = llvm.icmp "slt" %arg2, %1 : !llvm<"i32">
|
||||
%2 = cmpi "slt", %arg2, %1 : i32
|
||||
// CHECK-NEXT: {{.*}} = "llvm.sdiv"(%arg2, %arg3) : (!llvm<"i32">, !llvm<"i32">) -> !llvm<"i32">
|
||||
// CHECK-NEXT: %3 = llvm.sdiv %arg2, %arg3 : !llvm<"i32">
|
||||
%4 = divis %arg2, %arg3 : i32
|
||||
// CHECK-NEXT: {{.*}} = "llvm.udiv"(%arg2, %arg3) : (!llvm<"i32">, !llvm<"i32">) -> !llvm<"i32">
|
||||
// CHECK-NEXT: %4 = llvm.udiv %arg2, %arg3 : !llvm<"i32">
|
||||
%5 = diviu %arg2, %arg3 : i32
|
||||
// CHECK-NEXT: {{.*}} = "llvm.srem"(%arg2, %arg3) : (!llvm<"i32">, !llvm<"i32">) -> !llvm<"i32">
|
||||
// CHECK-NEXT: %5 = llvm.srem %arg2, %arg3 : !llvm<"i32">
|
||||
%6 = remis %arg2, %arg3 : i32
|
||||
// CHECK-NEXT: {{.*}} = "llvm.urem"(%arg2, %arg3) : (!llvm<"i32">, !llvm<"i32">) -> !llvm<"i32">
|
||||
// CHECK-NEXT: %6 = llvm.urem %arg2, %arg3 : !llvm<"i32">
|
||||
%7 = remiu %arg2, %arg3 : i32
|
||||
// CHECK-NEXT: {{.*}} = "llvm.select"({{.*}}, %arg2, %arg3) : (!llvm<"i1">, !llvm<"i32">, !llvm<"i32">) -> !llvm<"i32">
|
||||
// CHECK-NEXT: %7 = llvm.select %2, %arg2, %arg3 : !llvm<"i1">, !llvm<"i32">
|
||||
%8 = select %2, %arg2, %arg3 : i32
|
||||
// CHECK-NEXT: {{.*}} = "llvm.fdiv"(%arg0, %arg1) : (!llvm<"float">, !llvm<"float">) -> !llvm<"float">
|
||||
// CHECK-NEXT: %8 = llvm.fdiv %arg0, %arg1 : !llvm<"float">
|
||||
%9 = divf %arg0, %arg1 : f32
|
||||
// CHECK-NEXT: {{.*}} = "llvm.frem"(%arg0, %arg1) : (!llvm<"float">, !llvm<"float">) -> !llvm<"float">
|
||||
// CHECK-NEXT: %9 = llvm.frem %arg0, %arg1 : !llvm<"float">
|
||||
%10 = remf %arg0, %arg1 : f32
|
||||
|
||||
return %0, %4 : f32, i32
|
||||
|
@ -407,35 +407,35 @@ func @ops(f32, f32, i32, i32) -> (f32, i32) {
|
|||
|
||||
// CHECK-LABEL: @dfs_block_order
|
||||
func @dfs_block_order() -> (i32) {
|
||||
// CHECK-NEXT: {{.*}} = "llvm.constant"() {value: 42 : i32} : () -> !llvm<"i32">
|
||||
// CHECK-NEXT: %0 = llvm.constant(42 : i32) : !llvm<"i32">
|
||||
%0 = constant 42 : i32
|
||||
// CHECK-NEXT: "llvm.br"()[^bb2] : () -> ()
|
||||
// CHECK-NEXT: llvm.br ^bb2
|
||||
br ^bb2
|
||||
|
||||
// CHECK-NEXT: ^bb1:
|
||||
// CHECK-NEXT: {{.*}} = "llvm.add"({{.*}}, {{.*}}) : (!llvm<"i32">, !llvm<"i32">) -> !llvm<"i32">
|
||||
// CHECK-NEXT: "llvm.return"({{.*}}) : (!llvm<"i32">) -> ()
|
||||
// CHECK-NEXT: %1 = llvm.add %0, %2 : !llvm<"i32">
|
||||
// CHECK-NEXT: llvm.return %1 : !llvm<"i32">
|
||||
^bb1:
|
||||
%2 = addi %0, %1 : i32
|
||||
return %2 : i32
|
||||
|
||||
// CHECK-NEXT: ^bb2:
|
||||
^bb2:
|
||||
// CHECK-NEXT: {{.*}} = "llvm.constant"() {value: 55 : i32} : () -> !llvm<"i32">
|
||||
// CHECK-NEXT: %2 = llvm.constant(55 : i32) : !llvm<"i32">
|
||||
%1 = constant 55 : i32
|
||||
// CHECK-NEXT: "llvm.br"()[^bb1] : () -> ()
|
||||
// CHECK-NEXT: llvm.br ^bb1
|
||||
br ^bb1
|
||||
}
|
||||
// CHECK-LABEL: func @cond_br_same_target(%arg0: !llvm<"i1">, %arg1: !llvm<"i32">, %arg2: !llvm<"i32">)
|
||||
func @cond_br_same_target(%arg0: i1, %arg1: i32, %arg2 : i32) -> (i32) {
|
||||
// CHECK-NEXT: "llvm.cond_br"(%arg0)[^[[origBlock:bb[0-9]+]](%arg1 : !llvm<"i32">), ^[[dummyBlock:bb[0-9]+]]] : (!llvm<"i1">) -> ()
|
||||
// CHECK-NEXT: llvm.cond_br %arg0, ^[[origBlock:bb[0-9]+]](%arg1 : !llvm<"i32">), ^[[dummyBlock:bb[0-9]+]]
|
||||
cond_br %arg0, ^bb1(%arg1 : i32), ^bb1(%arg2 : i32)
|
||||
|
||||
// CHECK: ^[[origBlock]](%0: !llvm<"i32">):
|
||||
// CHECK-NEXT: "llvm.return"(%0) : (!llvm<"i32">) -> ()
|
||||
// CHECK-NEXT: llvm.return %0 : !llvm<"i32">
|
||||
^bb1(%0 : i32):
|
||||
return %0 : i32
|
||||
|
||||
// CHECK: ^[[dummyBlock]]:
|
||||
// CHECK-NEXT: "llvm.br"()[^[[origBlock]](%arg2 : !llvm<"i32">)] : () -> ()
|
||||
// CHECK-NEXT: llvm.br ^[[origBlock]](%arg2 : !llvm<"i32">)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,226 @@
|
|||
// RUN: mlir-opt %s -verify
|
||||
// RUN: mlir-opt %s -split-input-file -verify
|
||||
|
||||
// expected-error@+1{{llvm.noalias argument attribute of non boolean type}}
|
||||
func @invalid_noalias(%arg0: !llvm<"i32"> {llvm.noalias: 3}) {
|
||||
"llvm.return"() : () -> ()
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Check that parser errors are properly produced and do not crash the compiler.
|
||||
|
||||
// -----
|
||||
|
||||
func @icmp_non_string(%arg0 : !llvm<"i32">, %arg1 : !llvm<"i16">) {
|
||||
// expected-error@+1 {{expected 'predicate' attribute of string type}}
|
||||
llvm.icmp 42 %arg0, %arg0 : !llvm<"i32">
|
||||
return
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func @icmp_wrong_string(%arg0 : !llvm<"i32">, %arg1 : !llvm<"i16">) {
|
||||
// expected-error@+1 {{'foo' is an incorrect value of the 'predicate' attribute}}
|
||||
llvm.icmp "foo" %arg0, %arg0 : !llvm<"i32">
|
||||
return
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func @alloca_missing_input_result_type(%size : !llvm<"i64">) {
|
||||
// expected-error@+1 {{expected trailing function type with one argument and one result}}
|
||||
llvm.alloca %size x !llvm<"i32"> : () -> ()
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func @alloca_missing_input_type() {
|
||||
// expected-error@+1 {{expected trailing function type with one argument and one result}}
|
||||
llvm.alloca %size x !llvm<"i32"> : () -> (!llvm<"i32*">)
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func @alloca_mising_result_type() {
|
||||
// expected-error@+1 {{expected trailing function type with one argument and one result}}
|
||||
llvm.alloca %size x !llvm<"i32"> : (!llvm<"i64">) -> ()
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func @alloca_non_function_type() {
|
||||
// expected-error@+1 {{expected trailing function type with one argument and one result}}
|
||||
llvm.alloca %size x !llvm<"i32"> : !llvm<"i32*">
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func @gep_missing_input_result_type(%pos : !llvm<"i64">, %base : !llvm<"float*">) {
|
||||
// expected-error@+1 {{expected trailing function type with at least one argument and one result}}
|
||||
llvm.getelementptr %base[%pos] : () -> ()
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func @gep_missing_input_type(%pos : !llvm<"i64">, %base : !llvm<"float*">) {
|
||||
// expected-error@+1 {{expected trailing function type with at least one argument and one result}}
|
||||
llvm.getelementptr %base[%pos] : () -> (!llvm<"float*">)
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func @gep_missing_result_type(%pos : !llvm<"i64">, %base : !llvm<"float*">) {
|
||||
// expected-error@+1 {{expected trailing function type with at least one argument and one result}}
|
||||
llvm.getelementptr %base[%pos] : (!llvm<"float *">, !llvm<"i64">) -> ()
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func @gep_non_function_type(%pos : !llvm<"i64">, %base : !llvm<"float*">) {
|
||||
// expected-error@+1 {{expected trailing function type with at least one argument and one result}}
|
||||
llvm.getelementptr %base[%pos] : !llvm<"float*">
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func @load_non_llvm_type(%foo : memref<f32>) {
|
||||
// expected-error@+1 {{expected LLVM IR dialect type}}
|
||||
llvm.load %foo : memref<f32>
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func @load_non_ptr_type(%foo : !llvm<"float">) {
|
||||
// expected-error@+1 {{expected LLVM pointer type}}
|
||||
llvm.load %foo : !llvm<"float">
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func @store_non_llvm_type(%foo : memref<f32>, %bar : !llvm<"float">) {
|
||||
// expected-error@+1 {{expected LLVM IR dialect type}}
|
||||
llvm.store %bar, %foo : memref<f32>
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func @store_non_ptr_type(%foo : !llvm<"float">, %bar : !llvm<"float">) {
|
||||
// expected-error@+1 {{expected LLVM pointer type}}
|
||||
llvm.store %bar, %foo : !llvm<"float">
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func @call_non_function_type(%callee : !llvm<"i8(i8)">, %arg : !llvm<"i8">) {
|
||||
// expected-error@+1 {{expected function type}}
|
||||
llvm.call %callee(%arg) : !llvm<"i8(i8)">
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func @call_too_many_results(%callee : () -> (i32,i32)) {
|
||||
// expected-error@+1 {{expected function with 0 or 1 result}}
|
||||
llvm.call %callee() : () -> (i32, i32)
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func @call_non_llvm_result(%callee : () -> (i32)) {
|
||||
// expected-error@+1 {{expected result to have LLVM type}}
|
||||
llvm.call %callee() : () -> (i32)
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func @call_non_llvm_input(%callee : (i32) -> (), %arg : i32) {
|
||||
// expected-error@+1 {{expected LLVM types as inputs}}
|
||||
llvm.call %callee(%arg) : (i32) -> ()
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func @insertvalue_non_llvm_type(%a : i32, %b : i32) {
|
||||
// expected-error@+1 {{expected LLVM IR Dialect type}}
|
||||
llvm.insertvalue %a, %b[0] : i32
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func @insertvalue_non_array_position() {
|
||||
// Note the double-type, otherwise attribute parsing consumes the trailing
|
||||
// type of the op as the (wrong) attribute type.
|
||||
// expected-error@+1 {{expected an array attribute}}
|
||||
llvm.insertvalue %a, %b 0 : i32 : !llvm<"{i32}">
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func @insertvlaue_non_integer_position() {
|
||||
// expected-error@+1 {{expected an array of integer literals}}
|
||||
llvm.insertvalue %a, %b[0.0] : !llvm<"{i32}">
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func @insertvalue_struct_out_of_bounds() {
|
||||
// expected-error@+1 {{position out of bounds}}
|
||||
llvm.insertvalue %a, %b[1] : !llvm<"{i32}">
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func @insertvalue_array_out_of_bounds() {
|
||||
// expected-error@+1 {{position out of bounds}}
|
||||
llvm.insertvalue %a, %b[1] : !llvm<"[1 x i32]">
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func @insertvalue_wrong_nesting() {
|
||||
// expected-error@+1 {{expected wrapped LLVM IR structure/array type}}
|
||||
llvm.insertvalue %a, %b[0,0] : !llvm<"{i32}">
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func @extractvalue_non_llvm_type(%a : i32, %b : i32) {
|
||||
// expected-error@+1 {{expected LLVM IR Dialect type}}
|
||||
llvm.extractvalue %b[0] : i32
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func @extractvalue_non_array_position() {
|
||||
// Note the double-type, otherwise attribute parsing consumes the trailing
|
||||
// type of the op as the (wrong) attribute type.
|
||||
// expected-error@+1 {{expected an array attribute}}
|
||||
llvm.extractvalue %b 0 : i32 : !llvm<"{i32}">
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func @extractvlaue_non_integer_position() {
|
||||
// expected-error@+1 {{expected an array of integer literals}}
|
||||
llvm.extractvalue %b[0.0] : !llvm<"{i32}">
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func @extractvalue_struct_out_of_bounds() {
|
||||
// expected-error@+1 {{position out of bounds}}
|
||||
llvm.extractvalue %b[1] : !llvm<"{i32}">
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func @extractvalue_array_out_of_bounds() {
|
||||
// expected-error@+1 {{position out of bounds}}
|
||||
llvm.extractvalue %b[1] : !llvm<"[1 x i32]">
|
||||
}
|
||||
|
||||
// -----
|
||||
|
||||
func @extractvalue_wrong_nesting() {
|
||||
// expected-error@+1 {{expected wrapped LLVM IR structure/array type}}
|
||||
llvm.extractvalue %b[0,0] : !llvm<"{i32}">
|
||||
}
|
||||
|
|
|
@ -4,135 +4,140 @@
|
|||
func @ops(%arg0 : !llvm<"i32">, %arg1 : !llvm<"float">) {
|
||||
// Integer artithmetics binary operations.
|
||||
//
|
||||
// CHECK-NEXT: %0 = "llvm.add"(%arg0, %arg0) : (!llvm<"i32">, !llvm<"i32">) -> !llvm<"i32">
|
||||
// CHECK-NEXT: %1 = "llvm.sub"(%arg0, %arg0) : (!llvm<"i32">, !llvm<"i32">) -> !llvm<"i32">
|
||||
// CHECK-NEXT: %2 = "llvm.mul"(%arg0, %arg0) : (!llvm<"i32">, !llvm<"i32">) -> !llvm<"i32">
|
||||
// CHECK-NEXT: %3 = "llvm.udiv"(%arg0, %arg0) : (!llvm<"i32">, !llvm<"i32">) -> !llvm<"i32">
|
||||
// CHECK-NEXT: %4 = "llvm.sdiv"(%arg0, %arg0) : (!llvm<"i32">, !llvm<"i32">) -> !llvm<"i32">
|
||||
// CHECK-NEXT: %5 = "llvm.urem"(%arg0, %arg0) : (!llvm<"i32">, !llvm<"i32">) -> !llvm<"i32">
|
||||
// CHECK-NEXT: %6 = "llvm.srem"(%arg0, %arg0) : (!llvm<"i32">, !llvm<"i32">) -> !llvm<"i32">
|
||||
// CHECK-NEXT: %7 = "llvm.icmp"(%arg0, %arg0) {predicate: 1} : (!llvm<"i32">, !llvm<"i32">) -> !llvm<"i1">
|
||||
%0 = "llvm.add"(%arg0, %arg0) : (!llvm<"i32">, !llvm<"i32">) -> !llvm<"i32">
|
||||
%1 = "llvm.sub"(%arg0, %arg0) : (!llvm<"i32">, !llvm<"i32">) -> !llvm<"i32">
|
||||
%2 = "llvm.mul"(%arg0, %arg0) : (!llvm<"i32">, !llvm<"i32">) -> !llvm<"i32">
|
||||
%3 = "llvm.udiv"(%arg0, %arg0) : (!llvm<"i32">, !llvm<"i32">) -> !llvm<"i32">
|
||||
%4 = "llvm.sdiv"(%arg0, %arg0) : (!llvm<"i32">, !llvm<"i32">) -> !llvm<"i32">
|
||||
%5 = "llvm.urem"(%arg0, %arg0) : (!llvm<"i32">, !llvm<"i32">) -> !llvm<"i32">
|
||||
%6 = "llvm.srem"(%arg0, %arg0) : (!llvm<"i32">, !llvm<"i32">) -> !llvm<"i32">
|
||||
%7 = "llvm.icmp"(%arg0, %arg0) {predicate: 1} : (!llvm<"i32">, !llvm<"i32">) -> !llvm<"i1">
|
||||
// CHECK-NEXT: %0 = llvm.add %arg0, %arg0 : !llvm<"i32">
|
||||
// CHECK-NEXT: %1 = llvm.sub %arg0, %arg0 : !llvm<"i32">
|
||||
// CHECK-NEXT: %2 = llvm.mul %arg0, %arg0 : !llvm<"i32">
|
||||
// CHECK-NEXT: %3 = llvm.udiv %arg0, %arg0 : !llvm<"i32">
|
||||
// CHECK-NEXT: %4 = llvm.sdiv %arg0, %arg0 : !llvm<"i32">
|
||||
// CHECK-NEXT: %5 = llvm.urem %arg0, %arg0 : !llvm<"i32">
|
||||
// CHECK-NEXT: %6 = llvm.srem %arg0, %arg0 : !llvm<"i32">
|
||||
// CHECK-NEXT: %7 = llvm.icmp "ne" %arg0, %arg0 : !llvm<"i32">
|
||||
%0 = llvm.add %arg0, %arg0 : !llvm<"i32">
|
||||
%1 = llvm.sub %arg0, %arg0 : !llvm<"i32">
|
||||
%2 = llvm.mul %arg0, %arg0 : !llvm<"i32">
|
||||
%3 = llvm.udiv %arg0, %arg0 : !llvm<"i32">
|
||||
%4 = llvm.sdiv %arg0, %arg0 : !llvm<"i32">
|
||||
%5 = llvm.urem %arg0, %arg0 : !llvm<"i32">
|
||||
%6 = llvm.srem %arg0, %arg0 : !llvm<"i32">
|
||||
%7 = llvm.icmp "ne" %arg0, %arg0 : !llvm<"i32">
|
||||
|
||||
// Floating point binary operations.
|
||||
//
|
||||
// CHECK-NEXT: %8 = "llvm.fadd"(%arg1, %arg1) : (!llvm<"float">, !llvm<"float">) -> !llvm<"float">
|
||||
// CHECK-NEXT: %9 = "llvm.fsub"(%arg1, %arg1) : (!llvm<"float">, !llvm<"float">) -> !llvm<"float">
|
||||
// CHECK-NEXT: %10 = "llvm.fmul"(%arg1, %arg1) : (!llvm<"float">, !llvm<"float">) -> !llvm<"float">
|
||||
// CHECK-NEXT: %11 = "llvm.fdiv"(%arg1, %arg1) : (!llvm<"float">, !llvm<"float">) -> !llvm<"float">
|
||||
// CHECK-NEXT: %12 = "llvm.frem"(%arg1, %arg1) : (!llvm<"float">, !llvm<"float">) -> !llvm<"float">
|
||||
%8 = "llvm.fadd"(%arg1, %arg1) : (!llvm<"float">, !llvm<"float">) -> !llvm<"float">
|
||||
%9 = "llvm.fsub"(%arg1, %arg1) : (!llvm<"float">, !llvm<"float">) -> !llvm<"float">
|
||||
%10 = "llvm.fmul"(%arg1, %arg1) : (!llvm<"float">, !llvm<"float">) -> !llvm<"float">
|
||||
%11 = "llvm.fdiv"(%arg1, %arg1) : (!llvm<"float">, !llvm<"float">) -> !llvm<"float">
|
||||
%12 = "llvm.frem"(%arg1, %arg1) : (!llvm<"float">, !llvm<"float">) -> !llvm<"float">
|
||||
// CHECK-NEXT: %8 = llvm.fadd %arg1, %arg1 : !llvm<"float">
|
||||
// CHECK-NEXT: %9 = llvm.fsub %arg1, %arg1 : !llvm<"float">
|
||||
// CHECK-NEXT: %10 = llvm.fmul %arg1, %arg1 : !llvm<"float">
|
||||
// CHECK-NEXT: %11 = llvm.fdiv %arg1, %arg1 : !llvm<"float">
|
||||
// CHECK-NEXT: %12 = llvm.frem %arg1, %arg1 : !llvm<"float">
|
||||
%8 = llvm.fadd %arg1, %arg1 : !llvm<"float">
|
||||
%9 = llvm.fsub %arg1, %arg1 : !llvm<"float">
|
||||
%10 = llvm.fmul %arg1, %arg1 : !llvm<"float">
|
||||
%11 = llvm.fdiv %arg1, %arg1 : !llvm<"float">
|
||||
%12 = llvm.frem %arg1, %arg1 : !llvm<"float">
|
||||
|
||||
// Memory-related operations.
|
||||
//
|
||||
// CHECK-NEXT: %13 = "llvm.alloca"(%arg0) : (!llvm<"i32">) -> !llvm<"double*">
|
||||
// CHECK-NEXT: %14 = "llvm.getelementptr"(%13, %arg0, %arg0) : (!llvm<"double*">, !llvm<"i32">, !llvm<"i32">) -> !llvm<"double*">
|
||||
// CHECK-NEXT: %15 = "llvm.load"(%14) : (!llvm<"double*">) -> !llvm<"double">
|
||||
// CHECK-NEXT: "llvm.store"(%15, %13) : (!llvm<"double">, !llvm<"double*">) -> ()
|
||||
// CHECK-NEXT: %16 = "llvm.bitcast"(%13) : (!llvm<"double*">) -> !llvm<"i64*">
|
||||
%13 = "llvm.alloca"(%arg0) : (!llvm<"i32">) -> !llvm<"double*">
|
||||
%14 = "llvm.getelementptr"(%13, %arg0, %arg0) : (!llvm<"double*">, !llvm<"i32">, !llvm<"i32">) -> !llvm<"double*">
|
||||
%15 = "llvm.load"(%14) : (!llvm<"double*">) -> !llvm<"double">
|
||||
"llvm.store"(%15, %13) : (!llvm<"double">, !llvm<"double*">) -> ()
|
||||
%16 = "llvm.bitcast"(%13) : (!llvm<"double*">) -> !llvm<"i64*">
|
||||
// CHECK-NEXT: %13 = llvm.alloca %arg0 x !llvm<"double"> : (!llvm<"i32">) -> !llvm<"double*">
|
||||
// CHECK-NEXT: %14 = llvm.getelementptr %13[%arg0, %arg0] : (!llvm<"double*">, !llvm<"i32">, !llvm<"i32">) -> !llvm<"double*">
|
||||
// CHECK-NEXT: %15 = llvm.load %14 : !llvm<"double*">
|
||||
// CHECK-NEXT: llvm.store %15, %13 : !llvm<"double*">
|
||||
// CHECK-NEXT: %16 = llvm.bitcast %13 : !llvm<"double*"> to !llvm<"i64*">
|
||||
%13 = llvm.alloca %arg0 x !llvm<"double"> : (!llvm<"i32">) -> !llvm<"double*">
|
||||
%14 = llvm.getelementptr %13[%arg0, %arg0] : (!llvm<"double*">, !llvm<"i32">, !llvm<"i32">) -> !llvm<"double*">
|
||||
%15 = llvm.load %14 : !llvm<"double*">
|
||||
llvm.store %15, %13 : !llvm<"double*">
|
||||
%16 = llvm.bitcast %13 : !llvm<"double*"> to !llvm<"i64*">
|
||||
|
||||
// Function call-related operations.
|
||||
//
|
||||
// CHECK-NEXT: %17 = "llvm.call"(%arg0) {callee: @foo : (!llvm<"i32">) -> !llvm<"{ i32, double, i32 }">} : (!llvm<"i32">) -> !llvm<"{ i32, double, i32 }">
|
||||
// CHECK-NEXT: %18 = "llvm.extractvalue"(%17) {position: [0]} : (!llvm<"{ i32, double, i32 }">) -> !llvm<"i32">
|
||||
// CHECK-NEXT: %19 = "llvm.insertvalue"(%17, %18) {position: [2]} : (!llvm<"{ i32, double, i32 }">, !llvm<"i32">) -> !llvm<"{ i32, double, i32 }">
|
||||
%17 = "llvm.call"(%arg0) {callee: @foo : (!llvm<"i32">) -> !llvm<"{ i32, double, i32 }">}
|
||||
: (!llvm<"i32">) -> !llvm<"{ i32, double, i32 }">
|
||||
%18 = "llvm.extractvalue"(%17) {position: [0]} : (!llvm<"{ i32, double, i32 }">) -> !llvm<"i32">
|
||||
%19 = "llvm.insertvalue"(%17, %18) {position: [2]} : (!llvm<"{ i32, double, i32 }">, !llvm<"i32">) -> !llvm<"{ i32, double, i32 }">
|
||||
// CHECK-NEXT: %17 = llvm.call @foo(%arg0) : (!llvm<"i32">) -> !llvm<"{ i32, double, i32 }">
|
||||
// CHECK-NEXT: %18 = llvm.extractvalue %17[0] : !llvm<"{ i32, double, i32 }">
|
||||
// CHECK-NEXT: %19 = llvm.insertvalue %18, %17[2] : !llvm<"{ i32, double, i32 }">
|
||||
// CHECK-NEXT: %20 = llvm.constant(@foo : (!llvm<"i32">) -> !llvm<"{ i32, double, i32 }">) : !llvm<"{ i32, double, i32 } (i32)*">
|
||||
// CHECK-NEXT: %21 = llvm.call %20(%arg0) : (!llvm<"i32">) -> !llvm<"{ i32, double, i32 }">
|
||||
%17 = llvm.call @foo(%arg0) : (!llvm<"i32">) -> !llvm<"{ i32, double, i32 }">
|
||||
%18 = llvm.extractvalue %17[0] : !llvm<"{ i32, double, i32 }">
|
||||
%19 = llvm.insertvalue %18, %17[2] : !llvm<"{ i32, double, i32 }">
|
||||
%20 = llvm.constant(@foo : (!llvm<"i32">) -> !llvm<"{ i32, double, i32 }">) : !llvm<"{ i32, double, i32 } (i32)*">
|
||||
%21 = llvm.call %20(%arg0) : (!llvm<"i32">) -> !llvm<"{ i32, double, i32 }">
|
||||
|
||||
|
||||
// Terminator operations and their successors.
|
||||
//
|
||||
// CHECK: "llvm.br"()[^bb1] : () -> ()
|
||||
"llvm.br"()[^bb1] : () -> ()
|
||||
// CHECK: llvm.br ^bb1
|
||||
llvm.br ^bb1
|
||||
|
||||
^bb1:
|
||||
// CHECK: "llvm.cond_br"(%7)[^bb2, ^bb1] : (!llvm<"i1">) -> ()
|
||||
"llvm.cond_br"(%7)[^bb2,^bb1] : (!llvm<"i1">) -> ()
|
||||
// CHECK: llvm.cond_br %7, ^bb2, ^bb1
|
||||
llvm.cond_br %7, ^bb2, ^bb1
|
||||
|
||||
^bb2:
|
||||
// CHECK: %20 = "llvm.pseudo.undef"() : () -> !llvm<"{ i32, double, i32 }">
|
||||
// CHECK-NEXT: %21 = "llvm.pseudo.constant"() {value: 42} : () -> !llvm<"i47">
|
||||
%20 = "llvm.pseudo.undef"() : () -> !llvm<"{ i32, double, i32 }">
|
||||
%21 = "llvm.pseudo.constant"() {value: 42} : () -> !llvm<"i47">
|
||||
// CHECK: %22 = llvm.undef : !llvm<"{ i32, double, i32 }">
|
||||
// CHECK-NEXT: %23 = llvm.constant(42) : !llvm<"i47">
|
||||
%22 = llvm.undef : !llvm<"{ i32, double, i32 }">
|
||||
%23 = llvm.constant(42) : !llvm<"i47">
|
||||
|
||||
// Misc operations.
|
||||
// CHECK: %22 = "llvm.select"(%7, %0, %1) : (!llvm<"i1">, !llvm<"i32">, !llvm<"i32">) -> !llvm<"i32">
|
||||
// CHECK-NEXT: "llvm.return"() : () -> ()
|
||||
%22 = "llvm.select"(%7, %0, %1) : (!llvm<"i1">, !llvm<"i32">, !llvm<"i32">) -> !llvm<"i32">
|
||||
"llvm.return"() : () -> ()
|
||||
// CHECK: %24 = llvm.select %7, %0, %1 : !llvm<"i1">, !llvm<"i32">
|
||||
// CHECK-NEXT: llvm.return
|
||||
%24 = llvm.select %7, %0, %1 : !llvm<"i1">, !llvm<"i32">
|
||||
llvm.return
|
||||
}
|
||||
|
||||
// An larger self-contained function.
|
||||
// CHECK-LABEL:func @foo(%arg0: !llvm<"i32">) -> !llvm<"{ i32, double, i32 }"> {
|
||||
func @foo(%arg0: !llvm<"i32">) -> !llvm<"{ i32, double, i32 }"> {
|
||||
// CHECK-NEXT: %0 = "llvm.pseudo.constant"() {value: 3} : () -> !llvm<"i32">
|
||||
// CHECK-NEXT: %1 = "llvm.pseudo.constant"() {value: 3} : () -> !llvm<"i32">
|
||||
// CHECK-NEXT: %2 = "llvm.pseudo.constant"() {value: 4.200000e+01} : () -> !llvm<"double">
|
||||
// CHECK-NEXT: %3 = "llvm.pseudo.constant"() {value: 4.200000e+01} : () -> !llvm<"double">
|
||||
// CHECK-NEXT: %4 = "llvm.add"(%0, %1) : (!llvm<"i32">, !llvm<"i32">) -> !llvm<"i32">
|
||||
// CHECK-NEXT: %5 = "llvm.mul"(%4, %1) : (!llvm<"i32">, !llvm<"i32">) -> !llvm<"i32">
|
||||
// CHECK-NEXT: %6 = "llvm.fadd"(%2, %3) : (!llvm<"double">, !llvm<"double">) -> !llvm<"double">
|
||||
// CHECK-NEXT: %7 = "llvm.fsub"(%3, %6) : (!llvm<"double">, !llvm<"double">) -> !llvm<"double">
|
||||
// CHECK-NEXT: %8 = "llvm.pseudo.constant"() {value: 1} : () -> !llvm<"i1">
|
||||
// CHECK-NEXT: "llvm.cond_br"(%8)[^bb1(%4 : !llvm<"i32">), ^bb2(%4 : !llvm<"i32">)] : (!llvm<"i1">) -> ()
|
||||
%0 = "llvm.pseudo.constant"() {value: 3} : () -> !llvm<"i32">
|
||||
%1 = "llvm.pseudo.constant"() {value: 3} : () -> !llvm<"i32">
|
||||
%2 = "llvm.pseudo.constant"() {value: 4.200000e+01} : () -> !llvm<"double">
|
||||
%3 = "llvm.pseudo.constant"() {value: 4.200000e+01} : () -> !llvm<"double">
|
||||
%4 = "llvm.add"(%0, %1) : (!llvm<"i32">, !llvm<"i32">) -> !llvm<"i32">
|
||||
%5 = "llvm.mul"(%4, %1) : (!llvm<"i32">, !llvm<"i32">) -> !llvm<"i32">
|
||||
%6 = "llvm.fadd"(%2, %3) : (!llvm<"double">, !llvm<"double">) -> !llvm<"double">
|
||||
%7 = "llvm.fsub"(%3, %6) : (!llvm<"double">, !llvm<"double">) -> !llvm<"double">
|
||||
%8 = "llvm.pseudo.constant"() {value: 1} : () -> !llvm<"i1">
|
||||
"llvm.cond_br"(%8)[^bb1(%4 : !llvm<"i32">), ^bb2(%4 : !llvm<"i32">)] : (!llvm<"i1">) -> ()
|
||||
// CHECK-NEXT:^bb1(%9: !llvm<"i32">): // pred: ^bb0
|
||||
// CHECK-NEXT: %10 = "llvm.call"(%9) {callee: @foo : (!llvm<"i32">) -> !llvm<"{ i32, double, i32 }">} : (!llvm<"i32">) -> !llvm<"{ i32, double, i32 }">
|
||||
// CHECK-NEXT: %11 = "llvm.extractvalue"(%10) {position: [0]} : (!llvm<"{ i32, double, i32 }">) -> !llvm<"i32">
|
||||
// CHECK-NEXT: %12 = "llvm.extractvalue"(%10) {position: [1]} : (!llvm<"{ i32, double, i32 }">) -> !llvm<"double">
|
||||
// CHECK-NEXT: %13 = "llvm.extractvalue"(%10) {position: [2]} : (!llvm<"{ i32, double, i32 }">) -> !llvm<"i32">
|
||||
// CHECK-NEXT: %14 = "llvm.pseudo.undef"() : () -> !llvm<"{ i32, double, i32 }">
|
||||
// CHECK-NEXT: %15 = "llvm.insertvalue"(%14, %5) {position: [0]} : (!llvm<"{ i32, double, i32 }">, !llvm<"i32">) -> !llvm<"{ i32, double, i32 }">
|
||||
// CHECK-NEXT: %16 = "llvm.insertvalue"(%15, %7) {position: [1]} : (!llvm<"{ i32, double, i32 }">, !llvm<"double">) -> !llvm<"{ i32, double, i32 }">
|
||||
// CHECK-NEXT: %17 = "llvm.insertvalue"(%16, %11) {position: [2]} : (!llvm<"{ i32, double, i32 }">, !llvm<"i32">) -> !llvm<"{ i32, double, i32 }">
|
||||
// CHECK-NEXT: "llvm.return"(%17) : (!llvm<"{ i32, double, i32 }">) -> ()
|
||||
^bb1(%9: !llvm<"i32">): // pred: ^bb0
|
||||
%10 = "llvm.call"(%9) {callee: @foo : (!llvm<"i32">) -> !llvm<"{ i32, double, i32 }">} : (!llvm<"i32">) -> !llvm<"{ i32, double, i32 }">
|
||||
%11 = "llvm.extractvalue"(%10) {position: [0]} : (!llvm<"{ i32, double, i32 }">) -> !llvm<"i32">
|
||||
%12 = "llvm.extractvalue"(%10) {position: [1]} : (!llvm<"{ i32, double, i32 }">) -> !llvm<"double">
|
||||
%13 = "llvm.extractvalue"(%10) {position: [2]} : (!llvm<"{ i32, double, i32 }">) -> !llvm<"i32">
|
||||
%14 = "llvm.pseudo.undef"() : () -> !llvm<"{ i32, double, i32 }">
|
||||
%15 = "llvm.insertvalue"(%14, %5) {position: [0]} : (!llvm<"{ i32, double, i32 }">, !llvm<"i32">) -> !llvm<"{ i32, double, i32 }">
|
||||
%16 = "llvm.insertvalue"(%15, %7) {position: [1]} : (!llvm<"{ i32, double, i32 }">, !llvm<"double">) -> !llvm<"{ i32, double, i32 }">
|
||||
%17 = "llvm.insertvalue"(%16, %11) {position: [2]} : (!llvm<"{ i32, double, i32 }">, !llvm<"i32">) -> !llvm<"{ i32, double, i32 }">
|
||||
"llvm.return"(%17) : (!llvm<"{ i32, double, i32 }">) -> ()
|
||||
// CHECK-NEXT:^bb2(%18: !llvm<"i32">): // pred: ^bb0
|
||||
// CHECK-NEXT: %19 = "llvm.pseudo.undef"() : () -> !llvm<"{ i32, double, i32 }">
|
||||
// CHECK-NEXT: %20 = "llvm.insertvalue"(%19, %18) {position: [0]} : (!llvm<"{ i32, double, i32 }">, !llvm<"i32">) -> !llvm<"{ i32, double, i32 }">
|
||||
// CHECK-NEXT: %21 = "llvm.insertvalue"(%20, %7) {position: [1]} : (!llvm<"{ i32, double, i32 }">, !llvm<"double">) -> !llvm<"{ i32, double, i32 }">
|
||||
// CHECK-NEXT: %22 = "llvm.insertvalue"(%21, %5) {position: [2]} : (!llvm<"{ i32, double, i32 }">, !llvm<"i32">) -> !llvm<"{ i32, double, i32 }">
|
||||
// CHECK-NEXT: "llvm.return"(%22) : (!llvm<"{ i32, double, i32 }">) -> ()
|
||||
^bb2(%18: !llvm<"i32">): // pred: ^bb0
|
||||
%19 = "llvm.pseudo.undef"() : () -> !llvm<"{ i32, double, i32 }">
|
||||
%20 = "llvm.insertvalue"(%19, %18) {position: [0]} : (!llvm<"{ i32, double, i32 }">, !llvm<"i32">) -> !llvm<"{ i32, double, i32 }">
|
||||
%21 = "llvm.insertvalue"(%20, %7) {position: [1]} : (!llvm<"{ i32, double, i32 }">, !llvm<"double">) -> !llvm<"{ i32, double, i32 }">
|
||||
%22 = "llvm.insertvalue"(%21, %5) {position: [2]} : (!llvm<"{ i32, double, i32 }">, !llvm<"i32">) -> !llvm<"{ i32, double, i32 }">
|
||||
"llvm.return"(%22) : (!llvm<"{ i32, double, i32 }">) -> ()
|
||||
}
|
||||
// CHECK-NEXT: %0 = llvm.constant(3) : !llvm<"i32">
|
||||
// CHECK-NEXT: %1 = llvm.constant(3) : !llvm<"i32">
|
||||
// CHECK-NEXT: %2 = llvm.constant(4.200000e+01) : !llvm<"double">
|
||||
// CHECK-NEXT: %3 = llvm.constant(4.200000e+01) : !llvm<"double">
|
||||
// CHECK-NEXT: %4 = llvm.add %0, %1 : !llvm<"i32">
|
||||
// CHECK-NEXT: %5 = llvm.mul %4, %1 : !llvm<"i32">
|
||||
// CHECK-NEXT: %6 = llvm.fadd %2, %3 : !llvm<"double">
|
||||
// CHECK-NEXT: %7 = llvm.fsub %3, %6 : !llvm<"double">
|
||||
// CHECK-NEXT: %8 = llvm.constant(1) : !llvm<"i1">
|
||||
// CHECK-NEXT: llvm.cond_br %8, ^bb1(%4 : !llvm<"i32">), ^bb2(%4 : !llvm<"i32">)
|
||||
%0 = llvm.constant(3) : !llvm<"i32">
|
||||
%1 = llvm.constant(3) : !llvm<"i32">
|
||||
%2 = llvm.constant(4.200000e+01) : !llvm<"double">
|
||||
%3 = llvm.constant(4.200000e+01) : !llvm<"double">
|
||||
%4 = llvm.add %0, %1 : !llvm<"i32">
|
||||
%5 = llvm.mul %4, %1 : !llvm<"i32">
|
||||
%6 = llvm.fadd %2, %3 : !llvm<"double">
|
||||
%7 = llvm.fsub %3, %6 : !llvm<"double">
|
||||
%8 = llvm.constant(1) : !llvm<"i1">
|
||||
llvm.cond_br %8, ^bb1(%4 : !llvm<"i32">), ^bb2(%4 : !llvm<"i32">)
|
||||
|
||||
// CHECK-NEXT:^bb1(%9: !llvm<"i32">):
|
||||
// CHECK-NEXT: %10 = llvm.call @foo(%9) : (!llvm<"i32">) -> !llvm<"{ i32, double, i32 }">
|
||||
// CHECK-NEXT: %11 = llvm.extractvalue %10[0] : !llvm<"{ i32, double, i32 }">
|
||||
// CHECK-NEXT: %12 = llvm.extractvalue %10[1] : !llvm<"{ i32, double, i32 }">
|
||||
// CHECK-NEXT: %13 = llvm.extractvalue %10[2] : !llvm<"{ i32, double, i32 }">
|
||||
// CHECK-NEXT: %14 = llvm.undef : !llvm<"{ i32, double, i32 }">
|
||||
// CHECK-NEXT: %15 = llvm.insertvalue %5, %14[0] : !llvm<"{ i32, double, i32 }">
|
||||
// CHECK-NEXT: %16 = llvm.insertvalue %7, %15[1] : !llvm<"{ i32, double, i32 }">
|
||||
// CHECK-NEXT: %17 = llvm.insertvalue %11, %16[2] : !llvm<"{ i32, double, i32 }">
|
||||
// CHECK-NEXT: llvm.return %17 : !llvm<"{ i32, double, i32 }">
|
||||
^bb1(%9: !llvm<"i32">):
|
||||
%10 = llvm.call @foo(%9) : (!llvm<"i32">) -> !llvm<"{ i32, double, i32 }">
|
||||
%11 = llvm.extractvalue %10[0] : !llvm<"{ i32, double, i32 }">
|
||||
%12 = llvm.extractvalue %10[1] : !llvm<"{ i32, double, i32 }">
|
||||
%13 = llvm.extractvalue %10[2] : !llvm<"{ i32, double, i32 }">
|
||||
%14 = llvm.undef : !llvm<"{ i32, double, i32 }">
|
||||
%15 = llvm.insertvalue %5, %14[0] : !llvm<"{ i32, double, i32 }">
|
||||
%16 = llvm.insertvalue %7, %15[1] : !llvm<"{ i32, double, i32 }">
|
||||
%17 = llvm.insertvalue %11, %16[2] : !llvm<"{ i32, double, i32 }">
|
||||
llvm.return %17 : !llvm<"{ i32, double, i32 }">
|
||||
|
||||
// CHECK-NEXT:^bb2(%18: !llvm<"i32">): // pred: ^bb0
|
||||
// CHECK-NEXT: %19 = llvm.undef : !llvm<"{ i32, double, i32 }">
|
||||
// CHECK-NEXT: %20 = llvm.insertvalue %18, %19[0] : !llvm<"{ i32, double, i32 }">
|
||||
// CHECK-NEXT: %21 = llvm.insertvalue %7, %20[1] : !llvm<"{ i32, double, i32 }">
|
||||
// CHECK-NEXT: %22 = llvm.insertvalue %5, %21[2] : !llvm<"{ i32, double, i32 }">
|
||||
// CHECK-NEXT: llvm.return %22 : !llvm<"{ i32, double, i32 }">
|
||||
^bb2(%18: !llvm<"i32">): // pred: ^bb0
|
||||
%19 = llvm.undef : !llvm<"{ i32, double, i32 }">
|
||||
%20 = llvm.insertvalue %18, %19[0] : !llvm<"{ i32, double, i32 }">
|
||||
%21 = llvm.insertvalue %7, %20[1] : !llvm<"{ i32, double, i32 }">
|
||||
%22 = llvm.insertvalue %5, %21[2] : !llvm<"{ i32, double, i32 }">
|
||||
llvm.return %22 : !llvm<"{ i32, double, i32 }">
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ func @malloc(!llvm<"i64">) -> !llvm<"i8*">
|
|||
// CHECK-NEXT: ret void
|
||||
// CHECK-NEXT: }
|
||||
func @empty() {
|
||||
"llvm.return"() : () -> ()
|
||||
llvm.return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: declare void @body(i64)
|
||||
|
@ -28,38 +28,38 @@ func @body(!llvm<"i64">)
|
|||
// CHECK-LABEL: define void @simple_loop() {
|
||||
func @simple_loop() {
|
||||
// CHECK: br label %[[SIMPLE_bb1:[0-9]+]]
|
||||
"llvm.br"()[^bb1] : () -> ()
|
||||
llvm.br ^bb1
|
||||
|
||||
// Constants are inlined in LLVM rather than a separate instruction.
|
||||
// CHECK: [[SIMPLE_bb1]]:
|
||||
// CHECK-NEXT: br label %[[SIMPLE_bb2:[0-9]+]]
|
||||
^bb1: // pred: ^bb0
|
||||
%0 = "llvm.constant"() {value: 1 : index} : () -> !llvm<"i64">
|
||||
%1 = "llvm.constant"() {value: 42 : index} : () -> !llvm<"i64">
|
||||
"llvm.br"()[^bb2(%0 : !llvm<"i64">)] : () -> ()
|
||||
%0 = llvm.constant(1 : index) : !llvm<"i64">
|
||||
%1 = llvm.constant(42 : index) : !llvm<"i64">
|
||||
llvm.br ^bb2(%0 : !llvm<"i64">)
|
||||
|
||||
// CHECK: [[SIMPLE_bb2]]:
|
||||
// CHECK-NEXT: %{{[0-9]+}} = phi i64 [ %{{[0-9]+}}, %[[SIMPLE_bb3:[0-9]+]] ], [ 1, %[[SIMPLE_bb1]] ]
|
||||
// CHECK-NEXT: %{{[0-9]+}} = icmp slt i64 %{{[0-9]+}}, 42
|
||||
// CHECK-NEXT: br i1 %{{[0-9]+}}, label %[[SIMPLE_bb3]], label %[[SIMPLE_bb4:[0-9]+]]
|
||||
^bb2(%2: !llvm<"i64">): // 2 preds: ^bb1, ^bb3
|
||||
%3 = "llvm.icmp"(%2, %1) {predicate: 2} : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i1">
|
||||
"llvm.cond_br"(%3)[^bb3, ^bb4] : (!llvm<"i1">) -> ()
|
||||
%3 = llvm.icmp "slt" %2, %1 : !llvm<"i64">
|
||||
llvm.cond_br %3, ^bb3, ^bb4
|
||||
|
||||
// CHECK: [[SIMPLE_bb3]]:
|
||||
// CHECK-NEXT: call void @body(i64 %{{[0-9]+}})
|
||||
// CHECK-NEXT: %{{[0-9]+}} = add i64 %{{[0-9]+}}, 1
|
||||
// CHECK-NEXT: br label %[[SIMPLE_bb2]]
|
||||
^bb3: // pred: ^bb2
|
||||
"llvm.call"(%2) {callee: @body : (!llvm<"i64">) -> ()} : (!llvm<"i64">) -> ()
|
||||
%4 = "llvm.constant"() {value: 1 : index} : () -> !llvm<"i64">
|
||||
%5 = "llvm.add"(%2, %4) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
"llvm.br"()[^bb2(%5 : !llvm<"i64">)] : () -> ()
|
||||
llvm.call @body(%2) : (!llvm<"i64">) -> ()
|
||||
%4 = llvm.constant(1 : index) : !llvm<"i64">
|
||||
%5 = llvm.add %2, %4 : !llvm<"i64">
|
||||
llvm.br ^bb2(%5 : !llvm<"i64">)
|
||||
|
||||
// CHECK: [[SIMPLE_bb4]]:
|
||||
// CHECK-NEXT: ret void
|
||||
^bb4: // pred: ^bb2
|
||||
"llvm.return"() : () -> ()
|
||||
llvm.return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define void @simple_caller() {
|
||||
|
@ -67,8 +67,8 @@ func @simple_loop() {
|
|||
// CHECK-NEXT: ret void
|
||||
// CHECK-NEXT: }
|
||||
func @simple_caller() {
|
||||
"llvm.call"() {callee: @simple_loop : () -> ()} : () -> ()
|
||||
"llvm.return"() : () -> ()
|
||||
llvm.call @simple_loop() : () -> ()
|
||||
llvm.return
|
||||
}
|
||||
|
||||
//func @simple_indirect_caller() {
|
||||
|
@ -84,9 +84,9 @@ func @simple_caller() {
|
|||
// CHECK-NEXT: ret void
|
||||
// CHECK-NEXT: }
|
||||
func @ml_caller() {
|
||||
"llvm.call"() {callee: @simple_loop : () -> ()} : () -> ()
|
||||
"llvm.call"() {callee: @more_imperfectly_nested_loops : () -> ()} : () -> ()
|
||||
"llvm.return"() : () -> ()
|
||||
llvm.call @simple_loop() : () -> ()
|
||||
llvm.call @more_imperfectly_nested_loops() : () -> ()
|
||||
llvm.return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: declare i64 @body_args(i64)
|
||||
|
@ -97,23 +97,23 @@ func @other(!llvm<"i64">, !llvm<"i32">) -> !llvm<"i32">
|
|||
// CHECK-LABEL: define i32 @func_args(i32, i32) {
|
||||
// CHECK-NEXT: br label %[[ARGS_bb1:[0-9]+]]
|
||||
func @func_args(%arg0: !llvm<"i32">, %arg1: !llvm<"i32">) -> !llvm<"i32"> {
|
||||
%0 = "llvm.constant"() {value: 0 : i32} : () -> !llvm<"i32">
|
||||
"llvm.br"()[^bb1] : () -> ()
|
||||
%0 = llvm.constant(0 : i32) : !llvm<"i32">
|
||||
llvm.br ^bb1
|
||||
|
||||
// CHECK: [[ARGS_bb1]]:
|
||||
// CHECK-NEXT: br label %[[ARGS_bb2:[0-9]+]]
|
||||
^bb1: // pred: ^bb0
|
||||
%1 = "llvm.constant"() {value: 0 : index} : () -> !llvm<"i64">
|
||||
%2 = "llvm.constant"() {value: 42 : index} : () -> !llvm<"i64">
|
||||
"llvm.br"()[^bb2(%1 : !llvm<"i64">)] : () -> ()
|
||||
%1 = llvm.constant(0 : index) : !llvm<"i64">
|
||||
%2 = llvm.constant(42 : index) : !llvm<"i64">
|
||||
llvm.br ^bb2(%1 : !llvm<"i64">)
|
||||
|
||||
// CHECK: [[ARGS_bb2]]:
|
||||
// CHECK-NEXT: %5 = phi i64 [ %12, %[[ARGS_bb3:[0-9]+]] ], [ 0, %[[ARGS_bb1]] ]
|
||||
// CHECK-NEXT: %6 = icmp slt i64 %5, 42
|
||||
// CHECK-NEXT: br i1 %6, label %[[ARGS_bb3]], label %[[ARGS_bb4:[0-9]+]]
|
||||
^bb2(%3: !llvm<"i64">): // 2 preds: ^bb1, ^bb3
|
||||
%4 = "llvm.icmp"(%3, %2) {predicate: 2} : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i1">
|
||||
"llvm.cond_br"(%4)[^bb3, ^bb4] : (!llvm<"i1">) -> ()
|
||||
%4 = llvm.icmp "slt" %3, %2 : !llvm<"i64">
|
||||
llvm.cond_br %4, ^bb3, ^bb4
|
||||
|
||||
// CHECK: [[ARGS_bb3]]:
|
||||
// CHECK-NEXT: %8 = call i64 @body_args(i64 %5)
|
||||
|
@ -123,21 +123,21 @@ func @func_args(%arg0: !llvm<"i32">, %arg1: !llvm<"i32">) -> !llvm<"i32"> {
|
|||
// CHECK-NEXT: %12 = add i64 %5, 1
|
||||
// CHECK-NEXT: br label %[[ARGS_bb2]]
|
||||
^bb3: // pred: ^bb2
|
||||
%5 = "llvm.call"(%3) {callee: @body_args : (!llvm<"i64">) -> !llvm<"i64">} : (!llvm<"i64">) -> !llvm<"i64">
|
||||
%6 = "llvm.call"(%5, %arg0) {callee: @other : (!llvm<"i64">, !llvm<"i32">) -> !llvm<"i32">} : (!llvm<"i64">, !llvm<"i32">) -> !llvm<"i32">
|
||||
%7 = "llvm.call"(%5, %6) {callee: @other : (!llvm<"i64">, !llvm<"i32">) -> !llvm<"i32">} : (!llvm<"i64">, !llvm<"i32">) -> !llvm<"i32">
|
||||
%8 = "llvm.call"(%5, %arg1) {callee: @other : (!llvm<"i64">, !llvm<"i32">) -> !llvm<"i32">} : (!llvm<"i64">, !llvm<"i32">) -> !llvm<"i32">
|
||||
%9 = "llvm.constant"() {value: 1 : index} : () -> !llvm<"i64">
|
||||
%10 = "llvm.add"(%3, %9) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
"llvm.br"()[^bb2(%10 : !llvm<"i64">)] : () -> ()
|
||||
%5 = llvm.call @body_args(%3) : (!llvm<"i64">) -> !llvm<"i64">
|
||||
%6 = llvm.call @other(%5, %arg0) : (!llvm<"i64">, !llvm<"i32">) -> !llvm<"i32">
|
||||
%7 = llvm.call @other(%5, %6) : (!llvm<"i64">, !llvm<"i32">) -> !llvm<"i32">
|
||||
%8 = llvm.call @other(%5, %arg1) : (!llvm<"i64">, !llvm<"i32">) -> !llvm<"i32">
|
||||
%9 = llvm.constant(1 : index) : !llvm<"i64">
|
||||
%10 = llvm.add %3, %9 : !llvm<"i64">
|
||||
llvm.br ^bb2(%10 : !llvm<"i64">)
|
||||
|
||||
// CHECK: [[ARGS_bb4]]:
|
||||
// CHECK-NEXT: %14 = call i32 @other(i64 0, i32 0)
|
||||
// CHECK-NEXT: ret i32 %14
|
||||
^bb4: // pred: ^bb2
|
||||
%11 = "llvm.constant"() {value: 0 : index} : () -> !llvm<"i64">
|
||||
%12 = "llvm.call"(%11, %0) {callee: @other : (!llvm<"i64">, !llvm<"i32">) -> !llvm<"i32">} : (!llvm<"i64">, !llvm<"i32">) -> !llvm<"i32">
|
||||
"llvm.return"(%12) : (!llvm<"i32">) -> ()
|
||||
%11 = llvm.constant(0 : index) : !llvm<"i64">
|
||||
%12 = llvm.call @other(%11, %0) : (!llvm<"i64">, !llvm<"i32">) -> !llvm<"i32">
|
||||
llvm.return %12 : !llvm<"i32">
|
||||
}
|
||||
|
||||
// CHECK: declare void @pre(i64)
|
||||
|
@ -152,69 +152,69 @@ func @post(!llvm<"i64">)
|
|||
// CHECK-LABEL: define void @imperfectly_nested_loops() {
|
||||
// CHECK-NEXT: br label %[[IMPER_bb1:[0-9]+]]
|
||||
func @imperfectly_nested_loops() {
|
||||
"llvm.br"()[^bb1] : () -> ()
|
||||
llvm.br ^bb1
|
||||
|
||||
// CHECK: [[IMPER_bb1]]:
|
||||
// CHECK-NEXT: br label %[[IMPER_bb2:[0-9]+]]
|
||||
^bb1: // pred: ^bb0
|
||||
%0 = "llvm.constant"() {value: 0 : index} : () -> !llvm<"i64">
|
||||
%1 = "llvm.constant"() {value: 42 : index} : () -> !llvm<"i64">
|
||||
"llvm.br"()[^bb2(%0 : !llvm<"i64">)] : () -> ()
|
||||
%0 = llvm.constant(0 : index) : !llvm<"i64">
|
||||
%1 = llvm.constant(42 : index) : !llvm<"i64">
|
||||
llvm.br ^bb2(%0 : !llvm<"i64">)
|
||||
|
||||
// CHECK: [[IMPER_bb2]]:
|
||||
// CHECK-NEXT: %3 = phi i64 [ %13, %[[IMPER_bb7:[0-9]+]] ], [ 0, %[[IMPER_bb1]] ]
|
||||
// CHECK-NEXT: %4 = icmp slt i64 %3, 42
|
||||
// CHECK-NEXT: br i1 %4, label %[[IMPER_bb3:[0-9]+]], label %[[IMPER_bb8:[0-9]+]]
|
||||
^bb2(%2: !llvm<"i64">): // 2 preds: ^bb1, ^bb7
|
||||
%3 = "llvm.icmp"(%2, %1) {predicate: 2} : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i1">
|
||||
"llvm.cond_br"(%3)[^bb3, ^bb8] : (!llvm<"i1">) -> ()
|
||||
%3 = llvm.icmp "slt" %2, %1 : !llvm<"i64">
|
||||
llvm.cond_br %3, ^bb3, ^bb8
|
||||
|
||||
// CHECK: [[IMPER_bb3]]:
|
||||
// CHECK-NEXT: call void @pre(i64 %3)
|
||||
// CHECK-NEXT: br label %[[IMPER_bb4:[0-9]+]]
|
||||
^bb3: // pred: ^bb2
|
||||
"llvm.call"(%2) {callee: @pre : (!llvm<"i64">) -> ()} : (!llvm<"i64">) -> ()
|
||||
"llvm.br"()[^bb4] : () -> ()
|
||||
llvm.call @pre(%2) : (!llvm<"i64">) -> ()
|
||||
llvm.br ^bb4
|
||||
|
||||
// CHECK: [[IMPER_bb4]]:
|
||||
// CHECK-NEXT: br label %[[IMPER_bb5:[0-9]+]]
|
||||
^bb4: // pred: ^bb3
|
||||
%4 = "llvm.constant"() {value: 7 : index} : () -> !llvm<"i64">
|
||||
%5 = "llvm.constant"() {value: 56 : index} : () -> !llvm<"i64">
|
||||
"llvm.br"()[^bb5(%4 : !llvm<"i64">)] : () -> ()
|
||||
%4 = llvm.constant(7 : index) : !llvm<"i64">
|
||||
%5 = llvm.constant(56 : index) : !llvm<"i64">
|
||||
llvm.br ^bb5(%4 : !llvm<"i64">)
|
||||
|
||||
// CHECK: [[IMPER_bb5]]:
|
||||
// CHECK-NEXT: %8 = phi i64 [ %11, %[[IMPER_bb6:[0-9]+]] ], [ 7, %[[IMPER_bb4]] ]
|
||||
// CHECK-NEXT: %9 = icmp slt i64 %8, 56
|
||||
// CHECK-NEXT: br i1 %9, label %[[IMPER_bb6]], label %[[IMPER_bb7]]
|
||||
^bb5(%6: !llvm<"i64">): // 2 preds: ^bb4, ^bb6
|
||||
%7 = "llvm.icmp"(%6, %5) {predicate: 2} : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i1">
|
||||
"llvm.cond_br"(%7)[^bb6, ^bb7] : (!llvm<"i1">) -> ()
|
||||
%7 = llvm.icmp "slt" %6, %5 : !llvm<"i64">
|
||||
llvm.cond_br %7, ^bb6, ^bb7
|
||||
|
||||
// CHECK: [[IMPER_bb6]]:
|
||||
// CHECK-NEXT: call void @body2(i64 %3, i64 %8)
|
||||
// CHECK-NEXT: %11 = add i64 %8, 2
|
||||
// CHECK-NEXT: br label %[[IMPER_bb5]]
|
||||
^bb6: // pred: ^bb5
|
||||
"llvm.call"(%2, %6) {callee: @body2 : (!llvm<"i64">, !llvm<"i64">) -> ()} : (!llvm<"i64">, !llvm<"i64">) -> ()
|
||||
%8 = "llvm.constant"() {value: 2 : index} : () -> !llvm<"i64">
|
||||
%9 = "llvm.add"(%6, %8) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
"llvm.br"()[^bb5(%9 : !llvm<"i64">)] : () -> ()
|
||||
llvm.call @body2(%2, %6) : (!llvm<"i64">, !llvm<"i64">) -> ()
|
||||
%8 = llvm.constant(2 : index) : !llvm<"i64">
|
||||
%9 = llvm.add %6, %8 : !llvm<"i64">
|
||||
llvm.br ^bb5(%9 : !llvm<"i64">)
|
||||
|
||||
// CHECK: [[IMPER_bb7]]:
|
||||
// CHECK-NEXT: call void @post(i64 %3)
|
||||
// CHECK-NEXT: %13 = add i64 %3, 1
|
||||
// CHECK-NEXT: br label %[[IMPER_bb2]]
|
||||
^bb7: // pred: ^bb5
|
||||
"llvm.call"(%2) {callee: @post : (!llvm<"i64">) -> ()} : (!llvm<"i64">) -> ()
|
||||
%10 = "llvm.constant"() {value: 1 : index} : () -> !llvm<"i64">
|
||||
%11 = "llvm.add"(%2, %10) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
"llvm.br"()[^bb2(%11 : !llvm<"i64">)] : () -> ()
|
||||
llvm.call @post(%2) : (!llvm<"i64">) -> ()
|
||||
%10 = llvm.constant(1 : index) : !llvm<"i64">
|
||||
%11 = llvm.add %2, %10 : !llvm<"i64">
|
||||
llvm.br ^bb2(%11 : !llvm<"i64">)
|
||||
|
||||
// CHECK: [[IMPER_bb8]]:
|
||||
// CHECK-NEXT: ret void
|
||||
^bb8: // pred: ^bb2
|
||||
"llvm.return"() : () -> ()
|
||||
llvm.return
|
||||
}
|
||||
|
||||
// CHECK: declare void @mid(i64)
|
||||
|
@ -266,51 +266,51 @@ func @body3(!llvm<"i64">, !llvm<"i64">)
|
|||
// CHECK-NEXT: ret void
|
||||
// CHECK-NEXT: }
|
||||
func @more_imperfectly_nested_loops() {
|
||||
"llvm.br"()[^bb1] : () -> ()
|
||||
^bb1: // pred: ^bb0
|
||||
%0 = "llvm.constant"() {value: 0 : index} : () -> !llvm<"i64">
|
||||
%1 = "llvm.constant"() {value: 42 : index} : () -> !llvm<"i64">
|
||||
"llvm.br"()[^bb2(%0 : !llvm<"i64">)] : () -> ()
|
||||
^bb2(%2: !llvm<"i64">): // 2 preds: ^bb1, ^bb11
|
||||
%3 = "llvm.icmp"(%2, %1) {predicate: 2} : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i1">
|
||||
"llvm.cond_br"(%3)[^bb3, ^bb12] : (!llvm<"i1">) -> ()
|
||||
^bb3: // pred: ^bb2
|
||||
"llvm.call"(%2) {callee: @pre : (!llvm<"i64">) -> ()} : (!llvm<"i64">) -> ()
|
||||
"llvm.br"()[^bb4] : () -> ()
|
||||
^bb4: // pred: ^bb3
|
||||
%4 = "llvm.constant"() {value: 7 : index} : () -> !llvm<"i64">
|
||||
%5 = "llvm.constant"() {value: 56 : index} : () -> !llvm<"i64">
|
||||
"llvm.br"()[^bb5(%4 : !llvm<"i64">)] : () -> ()
|
||||
^bb5(%6: !llvm<"i64">): // 2 preds: ^bb4, ^bb6
|
||||
%7 = "llvm.icmp"(%6, %5) {predicate: 2} : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i1">
|
||||
"llvm.cond_br"(%7)[^bb6, ^bb7] : (!llvm<"i1">) -> ()
|
||||
^bb6: // pred: ^bb5
|
||||
"llvm.call"(%2, %6) {callee: @body2 : (!llvm<"i64">, !llvm<"i64">) -> ()} : (!llvm<"i64">, !llvm<"i64">) -> ()
|
||||
%8 = "llvm.constant"() {value: 2 : index} : () -> !llvm<"i64">
|
||||
%9 = "llvm.add"(%6, %8) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
"llvm.br"()[^bb5(%9 : !llvm<"i64">)] : () -> ()
|
||||
^bb7: // pred: ^bb5
|
||||
"llvm.call"(%2) {callee: @mid : (!llvm<"i64">) -> ()} : (!llvm<"i64">) -> ()
|
||||
"llvm.br"()[^bb8] : () -> ()
|
||||
^bb8: // pred: ^bb7
|
||||
%10 = "llvm.constant"() {value: 18 : index} : () -> !llvm<"i64">
|
||||
%11 = "llvm.constant"() {value: 37 : index} : () -> !llvm<"i64">
|
||||
"llvm.br"()[^bb9(%10 : !llvm<"i64">)] : () -> ()
|
||||
^bb9(%12: !llvm<"i64">): // 2 preds: ^bb8, ^bb10
|
||||
%13 = "llvm.icmp"(%12, %11) {predicate: 2} : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i1">
|
||||
"llvm.cond_br"(%13)[^bb10, ^bb11] : (!llvm<"i1">) -> ()
|
||||
^bb10: // pred: ^bb9
|
||||
"llvm.call"(%2, %12) {callee: @body3 : (!llvm<"i64">, !llvm<"i64">) -> ()} : (!llvm<"i64">, !llvm<"i64">) -> ()
|
||||
%14 = "llvm.constant"() {value: 3 : index} : () -> !llvm<"i64">
|
||||
%15 = "llvm.add"(%12, %14) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
"llvm.br"()[^bb9(%15 : !llvm<"i64">)] : () -> ()
|
||||
^bb11: // pred: ^bb9
|
||||
"llvm.call"(%2) {callee: @post : (!llvm<"i64">) -> ()} : (!llvm<"i64">) -> ()
|
||||
%16 = "llvm.constant"() {value: 1 : index} : () -> !llvm<"i64">
|
||||
%17 = "llvm.add"(%2, %16) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
"llvm.br"()[^bb2(%17 : !llvm<"i64">)] : () -> ()
|
||||
^bb12: // pred: ^bb2
|
||||
"llvm.return"() : () -> ()
|
||||
llvm.br ^bb1
|
||||
^bb1: // pred: ^bb0
|
||||
%0 = llvm.constant(0 : index) : !llvm<"i64">
|
||||
%1 = llvm.constant(42 : index) : !llvm<"i64">
|
||||
llvm.br ^bb2(%0 : !llvm<"i64">)
|
||||
^bb2(%2: !llvm<"i64">): // 2 preds: ^bb1, ^bb11
|
||||
%3 = llvm.icmp "slt" %2, %1 : !llvm<"i64">
|
||||
llvm.cond_br %3, ^bb3, ^bb12
|
||||
^bb3: // pred: ^bb2
|
||||
llvm.call @pre(%2) : (!llvm<"i64">) -> ()
|
||||
llvm.br ^bb4
|
||||
^bb4: // pred: ^bb3
|
||||
%4 = llvm.constant(7 : index) : !llvm<"i64">
|
||||
%5 = llvm.constant(56 : index) : !llvm<"i64">
|
||||
llvm.br ^bb5(%4 : !llvm<"i64">)
|
||||
^bb5(%6: !llvm<"i64">): // 2 preds: ^bb4, ^bb6
|
||||
%7 = llvm.icmp "slt" %6, %5 : !llvm<"i64">
|
||||
llvm.cond_br %7, ^bb6, ^bb7
|
||||
^bb6: // pred: ^bb5
|
||||
llvm.call @body2(%2, %6) : (!llvm<"i64">, !llvm<"i64">) -> ()
|
||||
%8 = llvm.constant(2 : index) : !llvm<"i64">
|
||||
%9 = llvm.add %6, %8 : !llvm<"i64">
|
||||
llvm.br ^bb5(%9 : !llvm<"i64">)
|
||||
^bb7: // pred: ^bb5
|
||||
llvm.call @mid(%2) : (!llvm<"i64">) -> ()
|
||||
llvm.br ^bb8
|
||||
^bb8: // pred: ^bb7
|
||||
%10 = llvm.constant(18 : index) : !llvm<"i64">
|
||||
%11 = llvm.constant(37 : index) : !llvm<"i64">
|
||||
llvm.br ^bb9(%10 : !llvm<"i64">)
|
||||
^bb9(%12: !llvm<"i64">): // 2 preds: ^bb8, ^bb10
|
||||
%13 = llvm.icmp "slt" %12, %11 : !llvm<"i64">
|
||||
llvm.cond_br %13, ^bb10, ^bb11
|
||||
^bb10: // pred: ^bb9
|
||||
llvm.call @body3(%2, %12) : (!llvm<"i64">, !llvm<"i64">) -> ()
|
||||
%14 = llvm.constant(3 : index) : !llvm<"i64">
|
||||
%15 = llvm.add %12, %14 : !llvm<"i64">
|
||||
llvm.br ^bb9(%15 : !llvm<"i64">)
|
||||
^bb11: // pred: ^bb9
|
||||
llvm.call @post(%2) : (!llvm<"i64">) -> ()
|
||||
%16 = llvm.constant(1 : index) : !llvm<"i64">
|
||||
%17 = llvm.add %2, %16 : !llvm<"i64">
|
||||
llvm.br ^bb2(%17 : !llvm<"i64">)
|
||||
^bb12: // pred: ^bb2
|
||||
llvm.return
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -322,17 +322,17 @@ func @memref_alloc() {
|
|||
// CHECK-NEXT: %{{[0-9]+}} = call i8* @malloc(i64 400)
|
||||
// CHECK-NEXT: %{{[0-9]+}} = bitcast i8* %{{[0-9]+}} to float*
|
||||
// CHECK-NEXT: %{{[0-9]+}} = insertvalue { float* } undef, float* %{{[0-9]+}}, 0
|
||||
%0 = "llvm.constant"() {value: 10 : index} : () -> !llvm<"i64">
|
||||
%1 = "llvm.constant"() {value: 10 : index} : () -> !llvm<"i64">
|
||||
%2 = "llvm.mul"(%0, %1) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%3 = "llvm.undef"() : () -> !llvm<"{ float* }">
|
||||
%4 = "llvm.constant"() {value: 4 : index} : () -> !llvm<"i64">
|
||||
%5 = "llvm.mul"(%2, %4) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%6 = "llvm.call"(%5) {callee: @malloc : (!llvm<"i64">) -> !llvm<"i8*">} : (!llvm<"i64">) -> !llvm<"i8*">
|
||||
%7 = "llvm.bitcast"(%6) : (!llvm<"i8*">) -> !llvm<"float*">
|
||||
%8 = "llvm.insertvalue"(%3, %7) {position: [0]} : (!llvm<"{ float* }">, !llvm<"float*">) -> !llvm<"{ float* }">
|
||||
%0 = llvm.constant(10 : index) : !llvm<"i64">
|
||||
%1 = llvm.constant(10 : index) : !llvm<"i64">
|
||||
%2 = llvm.mul %0, %1 : !llvm<"i64">
|
||||
%3 = llvm.undef : !llvm<"{ float* }">
|
||||
%4 = llvm.constant(4 : index) : !llvm<"i64">
|
||||
%5 = llvm.mul %2, %4 : !llvm<"i64">
|
||||
%6 = llvm.call @malloc(%5) : (!llvm<"i64">) -> !llvm<"i8*">
|
||||
%7 = llvm.bitcast %6 : !llvm<"i8*"> to !llvm<"float*">
|
||||
%8 = llvm.insertvalue %7, %3[0] : !llvm<"{ float* }">
|
||||
// CHECK-NEXT: ret void
|
||||
"llvm.return"() : () -> ()
|
||||
llvm.return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: declare i64 @get_index()
|
||||
|
@ -344,66 +344,66 @@ func @store_load_static() {
|
|||
// CHECK-NEXT: %{{[0-9]+}} = call i8* @malloc(i64 40)
|
||||
// CHECK-NEXT: %{{[0-9]+}} = bitcast i8* %{{[0-9]+}} to float*
|
||||
// CHECK-NEXT: %{{[0-9]+}} = insertvalue { float* } undef, float* %{{[0-9]+}}, 0
|
||||
%0 = "llvm.constant"() {value: 10 : index} : () -> !llvm<"i64">
|
||||
%1 = "llvm.undef"() : () -> !llvm<"{ float* }">
|
||||
%2 = "llvm.constant"() {value: 4 : index} : () -> !llvm<"i64">
|
||||
%3 = "llvm.mul"(%0, %2) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%4 = "llvm.call"(%3) {callee: @malloc : (!llvm<"i64">) -> !llvm<"i8*">} : (!llvm<"i64">) -> !llvm<"i8*">
|
||||
%5 = "llvm.bitcast"(%4) : (!llvm<"i8*">) -> !llvm<"float*">
|
||||
%6 = "llvm.insertvalue"(%1, %5) {position: [0]} : (!llvm<"{ float* }">, !llvm<"float*">) -> !llvm<"{ float* }">
|
||||
%7 = "llvm.constant"() {value: 1.000000e+00 : f32} : () -> !llvm<"float">
|
||||
"llvm.br"()[^bb1] : () -> ()
|
||||
%0 = llvm.constant(10 : index) : !llvm<"i64">
|
||||
%1 = llvm.undef : !llvm<"{ float* }">
|
||||
%2 = llvm.constant(4 : index) : !llvm<"i64">
|
||||
%3 = llvm.mul %0, %2 : !llvm<"i64">
|
||||
%4 = llvm.call @malloc(%3) : (!llvm<"i64">) -> !llvm<"i8*">
|
||||
%5 = llvm.bitcast %4 : !llvm<"i8*"> to !llvm<"float*">
|
||||
%6 = llvm.insertvalue %5, %1[0] : !llvm<"{ float* }">
|
||||
%7 = llvm.constant(1.000000e+00 : f32) : !llvm<"float">
|
||||
llvm.br ^bb1
|
||||
^bb1: // pred: ^bb0
|
||||
%8 = "llvm.constant"() {value: 0 : index} : () -> !llvm<"i64">
|
||||
%9 = "llvm.constant"() {value: 10 : index} : () -> !llvm<"i64">
|
||||
"llvm.br"()[^bb2(%8 : !llvm<"i64">)] : () -> ()
|
||||
%8 = llvm.constant(0 : index) : !llvm<"i64">
|
||||
%9 = llvm.constant(10 : index) : !llvm<"i64">
|
||||
llvm.br ^bb2(%8 : !llvm<"i64">)
|
||||
// CHECK: %{{[0-9]+}} = phi i64 [ %{{[0-9]+}}, %{{[0-9]+}} ], [ 0, %{{[0-9]+}} ]
|
||||
^bb2(%10: !llvm<"i64">): // 2 preds: ^bb1, ^bb3
|
||||
// CHECK-NEXT: %{{[0-9]+}} = icmp slt i64 %{{[0-9]+}}, 10
|
||||
%11 = "llvm.icmp"(%10, %9) {predicate: 2} : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i1">
|
||||
%11 = llvm.icmp "slt" %10, %9 : !llvm<"i64">
|
||||
// CHECK-NEXT: br i1 %{{[0-9]+}}, label %{{[0-9]+}}, label %{{[0-9]+}}
|
||||
"llvm.cond_br"(%11)[^bb3, ^bb4] : (!llvm<"i1">) -> ()
|
||||
llvm.cond_br %11, ^bb3, ^bb4
|
||||
^bb3: // pred: ^bb2
|
||||
// CHECK: %{{[0-9]+}} = extractvalue { float* } %{{[0-9]+}}, 0
|
||||
// CHECK-NEXT: %{{[0-9]+}} = getelementptr float, float* %{{[0-9]+}}, i64 %{{[0-9]+}}
|
||||
// CHECK-NEXT: store float 1.000000e+00, float* %{{[0-9]+}}
|
||||
%12 = "llvm.constant"() {value: 10 : index} : () -> !llvm<"i64">
|
||||
%13 = "llvm.extractvalue"(%6) {position: [0]} : (!llvm<"{ float* }">) -> !llvm<"float*">
|
||||
%14 = "llvm.getelementptr"(%13, %10) : (!llvm<"float*">, !llvm<"i64">) -> !llvm<"float*">
|
||||
"llvm.store"(%7, %14) : (!llvm<"float">, !llvm<"float*">) -> ()
|
||||
%15 = "llvm.constant"() {value: 1 : index} : () -> !llvm<"i64">
|
||||
%12 = llvm.constant(10 : index) : !llvm<"i64">
|
||||
%13 = llvm.extractvalue %6[0] : !llvm<"{ float* }">
|
||||
%14 = llvm.getelementptr %13[%10] : (!llvm<"float*">, !llvm<"i64">) -> !llvm<"float*">
|
||||
llvm.store %7, %14 : !llvm<"float*">
|
||||
%15 = llvm.constant(1 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: %{{[0-9]+}} = add i64 %{{[0-9]+}}, 1
|
||||
%16 = "llvm.add"(%10, %15) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%16 = llvm.add %10, %15 : !llvm<"i64">
|
||||
// CHECK-NEXT: br label %{{[0-9]+}}
|
||||
"llvm.br"()[^bb2(%16 : !llvm<"i64">)] : () -> ()
|
||||
llvm.br ^bb2(%16 : !llvm<"i64">)
|
||||
^bb4: // pred: ^bb2
|
||||
"llvm.br"()[^bb5] : () -> ()
|
||||
llvm.br ^bb5
|
||||
^bb5: // pred: ^bb4
|
||||
%17 = "llvm.constant"() {value: 0 : index} : () -> !llvm<"i64">
|
||||
%18 = "llvm.constant"() {value: 10 : index} : () -> !llvm<"i64">
|
||||
"llvm.br"()[^bb6(%17 : !llvm<"i64">)] : () -> ()
|
||||
%17 = llvm.constant(0 : index) : !llvm<"i64">
|
||||
%18 = llvm.constant(10 : index) : !llvm<"i64">
|
||||
llvm.br ^bb6(%17 : !llvm<"i64">)
|
||||
// CHECK: %{{[0-9]+}} = phi i64 [ %{{[0-9]+}}, %{{[0-9]+}} ], [ 0, %{{[0-9]+}} ]
|
||||
^bb6(%19: !llvm<"i64">): // 2 preds: ^bb5, ^bb7
|
||||
// CHECK-NEXT: %{{[0-9]+}} = icmp slt i64 %{{[0-9]+}}, 10
|
||||
%20 = "llvm.icmp"(%19, %18) {predicate: 2} : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i1">
|
||||
%20 = llvm.icmp "slt" %19, %18 : !llvm<"i64">
|
||||
// CHECK-NEXT: br i1 %{{[0-9]+}}, label %{{[0-9]+}}, label %{{[0-9]+}}
|
||||
"llvm.cond_br"(%20)[^bb7, ^bb8] : (!llvm<"i1">) -> ()
|
||||
llvm.cond_br %20, ^bb7, ^bb8
|
||||
^bb7: // pred: ^bb6
|
||||
// CHECK: %{{[0-9]+}} = extractvalue { float* } %{{[0-9]+}}, 0
|
||||
// CHECK-NEXT: %{{[0-9]+}} = getelementptr float, float* %{{[0-9]+}}, i64 %{{[0-9]+}}
|
||||
// CHECK-NEXT: %{{[0-9]+}} = load float, float* %{{[0-9]+}}
|
||||
%21 = "llvm.constant"() {value: 10 : index} : () -> !llvm<"i64">
|
||||
%22 = "llvm.extractvalue"(%6) {position: [0]} : (!llvm<"{ float* }">) -> !llvm<"float*">
|
||||
%23 = "llvm.getelementptr"(%22, %19) : (!llvm<"float*">, !llvm<"i64">) -> !llvm<"float*">
|
||||
%24 = "llvm.load"(%23) : (!llvm<"float*">) -> !llvm<"float">
|
||||
%25 = "llvm.constant"() {value: 1 : index} : () -> !llvm<"i64">
|
||||
%21 = llvm.constant(10 : index) : !llvm<"i64">
|
||||
%22 = llvm.extractvalue %6[0] : !llvm<"{ float* }">
|
||||
%23 = llvm.getelementptr %22[%19] : (!llvm<"float*">, !llvm<"i64">) -> !llvm<"float*">
|
||||
%24 = llvm.load %23 : !llvm<"float*">
|
||||
%25 = llvm.constant(1 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: %{{[0-9]+}} = add i64 %{{[0-9]+}}, 1
|
||||
%26 = "llvm.add"(%19, %25) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%26 = llvm.add %19, %25 : !llvm<"i64">
|
||||
// CHECK-NEXT: br label %{{[0-9]+}}
|
||||
"llvm.br"()[^bb6(%26 : !llvm<"i64">)] : () -> ()
|
||||
llvm.br ^bb6(%26 : !llvm<"i64">)
|
||||
^bb8: // pred: ^bb6
|
||||
// CHECK: ret void
|
||||
"llvm.return"() : () -> ()
|
||||
llvm.return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define void @store_load_dynamic(i64)
|
||||
|
@ -413,72 +413,72 @@ func @store_load_dynamic(%arg0: !llvm<"i64">) {
|
|||
// CHECK-NEXT: %{{[0-9]+}} = bitcast i8* %{{[0-9]+}} to float*
|
||||
// CHECK-NEXT: %{{[0-9]+}} = insertvalue { float*, i64 } undef, float* %{{[0-9]+}}, 0
|
||||
// CHECK-NEXT: %{{[0-9]+}} = insertvalue { float*, i64 } %{{[0-9]+}}, i64 %{{[0-9]+}}, 1
|
||||
%0 = "llvm.undef"() : () -> !llvm<"{ float*, i64 }">
|
||||
%1 = "llvm.constant"() {value: 4 : index} : () -> !llvm<"i64">
|
||||
%2 = "llvm.mul"(%arg0, %1) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%3 = "llvm.call"(%2) {callee: @malloc : (!llvm<"i64">) -> !llvm<"i8*">} : (!llvm<"i64">) -> !llvm<"i8*">
|
||||
%4 = "llvm.bitcast"(%3) : (!llvm<"i8*">) -> !llvm<"float*">
|
||||
%5 = "llvm.insertvalue"(%0, %4) {position: [0]} : (!llvm<"{ float*, i64 }">, !llvm<"float*">) -> !llvm<"{ float*, i64 }">
|
||||
%6 = "llvm.insertvalue"(%5, %arg0) {position: [1]} : (!llvm<"{ float*, i64 }">, !llvm<"i64">) -> !llvm<"{ float*, i64 }">
|
||||
%7 = "llvm.constant"() {value: 1.000000e+00 : f32} : () -> !llvm<"float">
|
||||
%0 = llvm.undef : !llvm<"{ float*, i64 }">
|
||||
%1 = llvm.constant(4 : index) : !llvm<"i64">
|
||||
%2 = llvm.mul %arg0, %1 : !llvm<"i64">
|
||||
%3 = llvm.call @malloc(%2) : (!llvm<"i64">) -> !llvm<"i8*">
|
||||
%4 = llvm.bitcast %3 : !llvm<"i8*"> to !llvm<"float*">
|
||||
%5 = llvm.insertvalue %4, %0[0] : !llvm<"{ float*, i64 }">
|
||||
%6 = llvm.insertvalue %arg0, %5[1] : !llvm<"{ float*, i64 }">
|
||||
%7 = llvm.constant(1.000000e+00 : f32) : !llvm<"float">
|
||||
// CHECK-NEXT: br label %{{[0-9]+}}
|
||||
"llvm.br"()[^bb1] : () -> ()
|
||||
llvm.br ^bb1
|
||||
^bb1: // pred: ^bb0
|
||||
%8 = "llvm.constant"() {value: 0 : index} : () -> !llvm<"i64">
|
||||
"llvm.br"()[^bb2(%8 : !llvm<"i64">)] : () -> ()
|
||||
%8 = llvm.constant(0 : index) : !llvm<"i64">
|
||||
llvm.br ^bb2(%8 : !llvm<"i64">)
|
||||
// CHECK: %{{[0-9]+}} = phi i64 [ %{{[0-9]+}}, %{{[0-9]+}} ], [ 0, %{{[0-9]+}} ]
|
||||
^bb2(%9: !llvm<"i64">): // 2 preds: ^bb1, ^bb3
|
||||
// CHECK-NEXT: %{{[0-9]+}} = icmp slt i64 %{{[0-9]+}}, %{{[0-9]+}}
|
||||
%10 = "llvm.icmp"(%9, %arg0) {predicate: 2} : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i1">
|
||||
%10 = llvm.icmp "slt" %9, %arg0 : !llvm<"i64">
|
||||
// CHECK-NEXT: br i1 %{{[0-9]+}}, label %{{[0-9]+}}, label %{{[0-9]+}}
|
||||
"llvm.cond_br"(%10)[^bb3, ^bb4] : (!llvm<"i1">) -> ()
|
||||
llvm.cond_br %10, ^bb3, ^bb4
|
||||
^bb3: // pred: ^bb2
|
||||
// CHECK: %{{[0-9]+}} = extractvalue { float*, i64 } %{{[0-9]+}}, 1
|
||||
// CHECK-NEXT: %{{[0-9]+}} = extractvalue { float*, i64 } %{{[0-9]+}}, 0
|
||||
// CHECK-NEXT: %{{[0-9]+}} = getelementptr float, float* %{{[0-9]+}}, i64 %{{[0-9]+}}
|
||||
// CHECK-NEXT: store float 1.000000e+00, float* %{{[0-9]+}}
|
||||
%11 = "llvm.extractvalue"(%6) {position: [1]} : (!llvm<"{ float*, i64 }">) -> !llvm<"i64">
|
||||
%12 = "llvm.extractvalue"(%6) {position: [0]} : (!llvm<"{ float*, i64 }">) -> !llvm<"float*">
|
||||
%13 = "llvm.getelementptr"(%12, %9) : (!llvm<"float*">, !llvm<"i64">) -> !llvm<"float*">
|
||||
"llvm.store"(%7, %13) : (!llvm<"float">, !llvm<"float*">) -> ()
|
||||
%14 = "llvm.constant"() {value: 1 : index} : () -> !llvm<"i64">
|
||||
%11 = llvm.extractvalue %6[1] : !llvm<"{ float*, i64 }">
|
||||
%12 = llvm.extractvalue %6[0] : !llvm<"{ float*, i64 }">
|
||||
%13 = llvm.getelementptr %12[%9] : (!llvm<"float*">, !llvm<"i64">) -> !llvm<"float*">
|
||||
llvm.store %7, %13 : !llvm<"float*">
|
||||
%14 = llvm.constant(1 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: %{{[0-9]+}} = add i64 %{{[0-9]+}}, 1
|
||||
%15 = "llvm.add"(%9, %14) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%15 = llvm.add %9, %14 : !llvm<"i64">
|
||||
// CHECK-NEXT: br label %{{[0-9]+}}
|
||||
"llvm.br"()[^bb2(%15 : !llvm<"i64">)] : () -> ()
|
||||
llvm.br ^bb2(%15 : !llvm<"i64">)
|
||||
^bb4: // pred: ^bb3
|
||||
"llvm.br"()[^bb5] : () -> ()
|
||||
llvm.br ^bb5
|
||||
^bb5: // pred: ^bb4
|
||||
%16 = "llvm.constant"() {value: 0 : index} : () -> !llvm<"i64">
|
||||
"llvm.br"()[^bb6(%16 : !llvm<"i64">)] : () -> ()
|
||||
%16 = llvm.constant(0 : index) : !llvm<"i64">
|
||||
llvm.br ^bb6(%16 : !llvm<"i64">)
|
||||
// CHECK: %{{[0-9]+}} = phi i64 [ %{{[0-9]+}}, %{{[0-9]+}} ], [ 0, %{{[0-9]+}} ]
|
||||
^bb6(%17: !llvm<"i64">): // 2 preds: ^bb5, ^bb7
|
||||
// CHECK-NEXT: %{{[0-9]+}} = icmp slt i64 %{{[0-9]+}}, %{{[0-9]+}}
|
||||
%18 = "llvm.icmp"(%17, %arg0) {predicate: 2} : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i1">
|
||||
%18 = llvm.icmp "slt" %17, %arg0 : !llvm<"i64">
|
||||
// CHECK-NEXT: br i1 %{{[0-9]+}}, label %{{[0-9]+}}, label %{{[0-9]+}}
|
||||
"llvm.cond_br"(%18)[^bb7, ^bb8] : (!llvm<"i1">) -> ()
|
||||
llvm.cond_br %18, ^bb7, ^bb8
|
||||
^bb7: // pred: ^bb6
|
||||
// CHECK: %{{[0-9]+}} = extractvalue { float*, i64 } %{{[0-9]+}}, 1
|
||||
// CHECK-NEXT: %{{[0-9]+}} = extractvalue { float*, i64 } %{{[0-9]+}}, 0
|
||||
// CHECK-NEXT: %{{[0-9]+}} = getelementptr float, float* %{{[0-9]+}}, i64 %{{[0-9]+}}
|
||||
// CHECK-NEXT: %{{[0-9]+}} = load float, float* %{{[0-9]+}}
|
||||
%19 = "llvm.extractvalue"(%6) {position: [1]} : (!llvm<"{ float*, i64 }">) -> !llvm<"i64">
|
||||
%20 = "llvm.extractvalue"(%6) {position: [0]} : (!llvm<"{ float*, i64 }">) -> !llvm<"float*">
|
||||
%21 = "llvm.getelementptr"(%20, %17) : (!llvm<"float*">, !llvm<"i64">) -> !llvm<"float*">
|
||||
%22 = "llvm.load"(%21) : (!llvm<"float*">) -> !llvm<"float">
|
||||
%23 = "llvm.constant"() {value: 1 : index} : () -> !llvm<"i64">
|
||||
%19 = llvm.extractvalue %6[1] : !llvm<"{ float*, i64 }">
|
||||
%20 = llvm.extractvalue %6[0] : !llvm<"{ float*, i64 }">
|
||||
%21 = llvm.getelementptr %20[%17] : (!llvm<"float*">, !llvm<"i64">) -> !llvm<"float*">
|
||||
%22 = llvm.load %21 : !llvm<"float*">
|
||||
%23 = llvm.constant(1 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: %{{[0-9]+}} = add i64 %{{[0-9]+}}, 1
|
||||
%24 = "llvm.add"(%17, %23) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%24 = llvm.add %17, %23 : !llvm<"i64">
|
||||
// CHECK-NEXT: br label %{{[0-9]+}}
|
||||
"llvm.br"()[^bb6(%24 : !llvm<"i64">)] : () -> ()
|
||||
llvm.br ^bb6(%24 : !llvm<"i64">)
|
||||
^bb8: // pred: ^bb6
|
||||
// CHECK: ret void
|
||||
"llvm.return"() : () -> ()
|
||||
llvm.return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define void @store_load_mixed(i64)
|
||||
func @store_load_mixed(%arg0: !llvm<"i64">) {
|
||||
%0 = "llvm.constant"() {value: 10 : index} : () -> !llvm<"i64">
|
||||
%0 = llvm.constant(10 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: %{{[0-9]+}} = mul i64 2, %{{[0-9]+}}
|
||||
// CHECK-NEXT: %{{[0-9]+}} = mul i64 %{{[0-9]+}}, 4
|
||||
// CHECK-NEXT: %{{[0-9]+}} = mul i64 %{{[0-9]+}}, 10
|
||||
|
@ -488,28 +488,28 @@ func @store_load_mixed(%arg0: !llvm<"i64">) {
|
|||
// CHECK-NEXT: %{{[0-9]+}} = insertvalue { float*, i64, i64 } undef, float* %{{[0-9]+}}, 0
|
||||
// CHECK-NEXT: %{{[0-9]+}} = insertvalue { float*, i64, i64 } %{{[0-9]+}}, i64 %{{[0-9]+}}, 1
|
||||
// CHECK-NEXT: %{{[0-9]+}} = insertvalue { float*, i64, i64 } %{{[0-9]+}}, i64 10, 2
|
||||
%1 = "llvm.constant"() {value: 2 : index} : () -> !llvm<"i64">
|
||||
%2 = "llvm.constant"() {value: 4 : index} : () -> !llvm<"i64">
|
||||
%3 = "llvm.mul"(%1, %arg0) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%4 = "llvm.mul"(%3, %2) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%5 = "llvm.mul"(%4, %0) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%6 = "llvm.undef"() : () -> !llvm<"{ float*, i64, i64 }">
|
||||
%7 = "llvm.constant"() {value: 4 : index} : () -> !llvm<"i64">
|
||||
%8 = "llvm.mul"(%5, %7) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%9 = "llvm.call"(%8) {callee: @malloc : (!llvm<"i64">) -> !llvm<"i8*">} : (!llvm<"i64">) -> !llvm<"i8*">
|
||||
%10 = "llvm.bitcast"(%9) : (!llvm<"i8*">) -> !llvm<"float*">
|
||||
%11 = "llvm.insertvalue"(%6, %10) {position: [0]} : (!llvm<"{ float*, i64, i64 }">, !llvm<"float*">) -> !llvm<"{ float*, i64, i64 }">
|
||||
%12 = "llvm.insertvalue"(%11, %arg0) {position: [1]} : (!llvm<"{ float*, i64, i64 }">, !llvm<"i64">) -> !llvm<"{ float*, i64, i64 }">
|
||||
%13 = "llvm.insertvalue"(%12, %0) {position: [2]} : (!llvm<"{ float*, i64, i64 }">, !llvm<"i64">) -> !llvm<"{ float*, i64, i64 }">
|
||||
%1 = llvm.constant(2 : index) : !llvm<"i64">
|
||||
%2 = llvm.constant(4 : index) : !llvm<"i64">
|
||||
%3 = llvm.mul %1, %arg0 : !llvm<"i64">
|
||||
%4 = llvm.mul %3, %2 : !llvm<"i64">
|
||||
%5 = llvm.mul %4, %0 : !llvm<"i64">
|
||||
%6 = llvm.undef : !llvm<"{ float*, i64, i64 }">
|
||||
%7 = llvm.constant(4 : index) : !llvm<"i64">
|
||||
%8 = llvm.mul %5, %7 : !llvm<"i64">
|
||||
%9 = llvm.call @malloc(%8) : (!llvm<"i64">) -> !llvm<"i8*">
|
||||
%10 = llvm.bitcast %9 : !llvm<"i8*"> to !llvm<"float*">
|
||||
%11 = llvm.insertvalue %10, %6[0] : !llvm<"{ float*, i64, i64 }">
|
||||
%12 = llvm.insertvalue %arg0, %11[1] : !llvm<"{ float*, i64, i64 }">
|
||||
%13 = llvm.insertvalue %0, %12[2] : !llvm<"{ float*, i64, i64 }">
|
||||
|
||||
// CHECK-NEXT: %{{[0-9]+}} = call i64 @get_index()
|
||||
// CHECK-NEXT: %{{[0-9]+}} = call i64 @get_index()
|
||||
%14 = "llvm.constant"() {value: 1 : index} : () -> !llvm<"i64">
|
||||
%15 = "llvm.constant"() {value: 2 : index} : () -> !llvm<"i64">
|
||||
%16 = "llvm.call"() {callee: @get_index : () -> !llvm<"i64">} : () -> !llvm<"i64">
|
||||
%17 = "llvm.call"() {callee: @get_index : () -> !llvm<"i64">} : () -> !llvm<"i64">
|
||||
%18 = "llvm.constant"() {value: 4.200000e+01 : f32} : () -> !llvm<"float">
|
||||
%19 = "llvm.constant"() {value: 2 : index} : () -> !llvm<"i64">
|
||||
%14 = llvm.constant(1 : index) : !llvm<"i64">
|
||||
%15 = llvm.constant(2 : index) : !llvm<"i64">
|
||||
%16 = llvm.call @get_index() : () -> !llvm<"i64">
|
||||
%17 = llvm.call @get_index() : () -> !llvm<"i64">
|
||||
%18 = llvm.constant(4.200000e+01 : f32) : !llvm<"float">
|
||||
%19 = llvm.constant(2 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: %{{[0-9]+}} = extractvalue { float*, i64, i64 } %{{[0-9]+}}, 1
|
||||
// CHECK-NEXT: %{{[0-9]+}} = extractvalue { float*, i64, i64 } %{{[0-9]+}}, 2
|
||||
// CHECK-NEXT: %{{[0-9]+}} = mul i64 1, %{{[0-9]+}}
|
||||
|
@ -521,18 +521,18 @@ func @store_load_mixed(%arg0: !llvm<"i64">) {
|
|||
// CHECK-NEXT: %{{[0-9]+}} = extractvalue { float*, i64, i64 } %{{[0-9]+}}, 0
|
||||
// CHECK-NEXT: %{{[0-9]+}} = getelementptr float, float* %{{[0-9]+}}, i64 %{{[0-9]+}}
|
||||
// CHECK-NEXT: store float 4.200000e+01, float* %{{[0-9]+}}
|
||||
%20 = "llvm.extractvalue"(%13) {position: [1]} : (!llvm<"{ float*, i64, i64 }">) -> !llvm<"i64">
|
||||
%21 = "llvm.constant"() {value: 4 : index} : () -> !llvm<"i64">
|
||||
%22 = "llvm.extractvalue"(%13) {position: [2]} : (!llvm<"{ float*, i64, i64 }">) -> !llvm<"i64">
|
||||
%23 = "llvm.mul"(%14, %20) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%24 = "llvm.add"(%23, %15) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%25 = "llvm.mul"(%24, %21) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%26 = "llvm.add"(%25, %16) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%27 = "llvm.mul"(%26, %22) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%28 = "llvm.add"(%27, %17) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%29 = "llvm.extractvalue"(%13) {position: [0]} : (!llvm<"{ float*, i64, i64 }">) -> !llvm<"float*">
|
||||
%30 = "llvm.getelementptr"(%29, %28) : (!llvm<"float*">, !llvm<"i64">) -> !llvm<"float*">
|
||||
"llvm.store"(%18, %30) : (!llvm<"float">, !llvm<"float*">) -> ()
|
||||
%20 = llvm.extractvalue %13[1] : !llvm<"{ float*, i64, i64 }">
|
||||
%21 = llvm.constant(4 : index) : !llvm<"i64">
|
||||
%22 = llvm.extractvalue %13[2] : !llvm<"{ float*, i64, i64 }">
|
||||
%23 = llvm.mul %14, %20 : !llvm<"i64">
|
||||
%24 = llvm.add %23, %15 : !llvm<"i64">
|
||||
%25 = llvm.mul %24, %21 : !llvm<"i64">
|
||||
%26 = llvm.add %25, %16 : !llvm<"i64">
|
||||
%27 = llvm.mul %26, %22 : !llvm<"i64">
|
||||
%28 = llvm.add %27, %17 : !llvm<"i64">
|
||||
%29 = llvm.extractvalue %13[0] : !llvm<"{ float*, i64, i64 }">
|
||||
%30 = llvm.getelementptr %29[%28] : (!llvm<"float*">, !llvm<"i64">) -> !llvm<"float*">
|
||||
llvm.store %18, %30 : !llvm<"float*">
|
||||
// CHECK-NEXT: %{{[0-9]+}} = extractvalue { float*, i64, i64 } %{{[0-9]+}}, 1
|
||||
// CHECK-NEXT: %{{[0-9]+}} = extractvalue { float*, i64, i64 } %{{[0-9]+}}, 2
|
||||
// CHECK-NEXT: %{{[0-9]+}} = mul i64 %{{[0-9]+}}, %{{[0-9]+}}
|
||||
|
@ -544,97 +544,97 @@ func @store_load_mixed(%arg0: !llvm<"i64">) {
|
|||
// CHECK-NEXT: %{{[0-9]+}} = extractvalue { float*, i64, i64 } %{{[0-9]+}}, 0
|
||||
// CHECK-NEXT: %{{[0-9]+}} = getelementptr float, float* %{{[0-9]+}}, i64 %{{[0-9]+}}
|
||||
// CHECK-NEXT: %{{[0-9]+}} = load float, float* %{{[0-9]+}}
|
||||
%31 = "llvm.constant"() {value: 2 : index} : () -> !llvm<"i64">
|
||||
%32 = "llvm.extractvalue"(%13) {position: [1]} : (!llvm<"{ float*, i64, i64 }">) -> !llvm<"i64">
|
||||
%33 = "llvm.constant"() {value: 4 : index} : () -> !llvm<"i64">
|
||||
%34 = "llvm.extractvalue"(%13) {position: [2]} : (!llvm<"{ float*, i64, i64 }">) -> !llvm<"i64">
|
||||
%35 = "llvm.mul"(%17, %32) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%36 = "llvm.add"(%35, %16) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%37 = "llvm.mul"(%36, %33) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%38 = "llvm.add"(%37, %15) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%39 = "llvm.mul"(%38, %34) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%40 = "llvm.add"(%39, %14) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%41 = "llvm.extractvalue"(%13) {position: [0]} : (!llvm<"{ float*, i64, i64 }">) -> !llvm<"float*">
|
||||
%42 = "llvm.getelementptr"(%41, %40) : (!llvm<"float*">, !llvm<"i64">) -> !llvm<"float*">
|
||||
%43 = "llvm.load"(%42) : (!llvm<"float*">) -> !llvm<"float">
|
||||
%31 = llvm.constant(2 : index) : !llvm<"i64">
|
||||
%32 = llvm.extractvalue %13[1] : !llvm<"{ float*, i64, i64 }">
|
||||
%33 = llvm.constant(4 : index) : !llvm<"i64">
|
||||
%34 = llvm.extractvalue %13[2] : !llvm<"{ float*, i64, i64 }">
|
||||
%35 = llvm.mul %17, %32 : !llvm<"i64">
|
||||
%36 = llvm.add %35, %16 : !llvm<"i64">
|
||||
%37 = llvm.mul %36, %33 : !llvm<"i64">
|
||||
%38 = llvm.add %37, %15 : !llvm<"i64">
|
||||
%39 = llvm.mul %38, %34 : !llvm<"i64">
|
||||
%40 = llvm.add %39, %14 : !llvm<"i64">
|
||||
%41 = llvm.extractvalue %13[0] : !llvm<"{ float*, i64, i64 }">
|
||||
%42 = llvm.getelementptr %41[%40] : (!llvm<"float*">, !llvm<"i64">) -> !llvm<"float*">
|
||||
%43 = llvm.load %42 : !llvm<"float*">
|
||||
// CHECK-NEXT: ret void
|
||||
"llvm.return"() : () -> ()
|
||||
llvm.return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define { float*, i64 } @memref_args_rets({ float* }, { float*, i64 }, { float*, i64 }) {
|
||||
func @memref_args_rets(%arg0: !llvm<"{ float* }">, %arg1: !llvm<"{ float*, i64 }">, %arg2: !llvm<"{ float*, i64 }">) -> !llvm<"{ float*, i64 }"> {
|
||||
%0 = "llvm.constant"() {value: 7 : index} : () -> !llvm<"i64">
|
||||
%0 = llvm.constant(7 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: %{{[0-9]+}} = call i64 @get_index()
|
||||
%1 = "llvm.call"() {callee: @get_index : () -> !llvm<"i64">} : () -> !llvm<"i64">
|
||||
%2 = "llvm.constant"() {value: 4.200000e+01 : f32} : () -> !llvm<"float">
|
||||
%1 = llvm.call @get_index() : () -> !llvm<"i64">
|
||||
%2 = llvm.constant(4.200000e+01 : f32) : !llvm<"float">
|
||||
// CHECK-NEXT: %{{[0-9]+}} = extractvalue { float* } %{{[0-9]+}}, 0
|
||||
// CHECK-NEXT: %{{[0-9]+}} = getelementptr float, float* %{{[0-9]+}}, i64 7
|
||||
// CHECK-NEXT: store float 4.200000e+01, float* %{{[0-9]+}}
|
||||
%3 = "llvm.constant"() {value: 10 : index} : () -> !llvm<"i64">
|
||||
%4 = "llvm.extractvalue"(%arg0) {position: [0]} : (!llvm<"{ float* }">) -> !llvm<"float*">
|
||||
%5 = "llvm.getelementptr"(%4, %0) : (!llvm<"float*">, !llvm<"i64">) -> !llvm<"float*">
|
||||
"llvm.store"(%2, %5) : (!llvm<"float">, !llvm<"float*">) -> ()
|
||||
%3 = llvm.constant(10 : index) : !llvm<"i64">
|
||||
%4 = llvm.extractvalue %arg0[0] : !llvm<"{ float* }">
|
||||
%5 = llvm.getelementptr %4[%0] : (!llvm<"float*">, !llvm<"i64">) -> !llvm<"float*">
|
||||
llvm.store %2, %5 : !llvm<"float*">
|
||||
// CHECK-NEXT: %{{[0-9]+}} = extractvalue { float*, i64 } %{{[0-9]+}}, 1
|
||||
// CHECK-NEXT: %{{[0-9]+}} = extractvalue { float*, i64 } %{{[0-9]+}}, 0
|
||||
// CHECK-NEXT: %{{[0-9]+}} = getelementptr float, float* %{{[0-9]+}}, i64 7
|
||||
// CHECK-NEXT: store float 4.200000e+01, float* %{{[0-9]+}}
|
||||
%6 = "llvm.extractvalue"(%arg1) {position: [1]} : (!llvm<"{ float*, i64 }">) -> !llvm<"i64">
|
||||
%7 = "llvm.extractvalue"(%arg1) {position: [0]} : (!llvm<"{ float*, i64 }">) -> !llvm<"float*">
|
||||
%8 = "llvm.getelementptr"(%7, %0) : (!llvm<"float*">, !llvm<"i64">) -> !llvm<"float*">
|
||||
"llvm.store"(%2, %8) : (!llvm<"float">, !llvm<"float*">) -> ()
|
||||
%6 = llvm.extractvalue %arg1[1] : !llvm<"{ float*, i64 }">
|
||||
%7 = llvm.extractvalue %arg1[0] : !llvm<"{ float*, i64 }">
|
||||
%8 = llvm.getelementptr %7[%0] : (!llvm<"float*">, !llvm<"i64">) -> !llvm<"float*">
|
||||
llvm.store %2, %8 : !llvm<"float*">
|
||||
// CHECK-NEXT: %{{[0-9]+}} = extractvalue { float*, i64 } %{{[0-9]+}}, 1
|
||||
// CHECK-NEXT: %{{[0-9]+}} = mul i64 7, %{{[0-9]+}}
|
||||
// CHECK-NEXT: %{{[0-9]+}} = add i64 %{{[0-9]+}}, %{{[0-9]+}}
|
||||
// CHECK-NEXT: %{{[0-9]+}} = extractvalue { float*, i64 } %{{[0-9]+}}, 0
|
||||
// CHECK-NEXT: %{{[0-9]+}} = getelementptr float, float* %{{[0-9]+}}, i64 %{{[0-9]+}}
|
||||
// CHECK-NEXT: store float 4.200000e+01, float* %{{[0-9]+}}
|
||||
%9 = "llvm.constant"() {value: 10 : index} : () -> !llvm<"i64">
|
||||
%10 = "llvm.extractvalue"(%arg2) {position: [1]} : (!llvm<"{ float*, i64 }">) -> !llvm<"i64">
|
||||
%11 = "llvm.mul"(%0, %10) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%12 = "llvm.add"(%11, %1) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%13 = "llvm.extractvalue"(%arg2) {position: [0]} : (!llvm<"{ float*, i64 }">) -> !llvm<"float*">
|
||||
%14 = "llvm.getelementptr"(%13, %12) : (!llvm<"float*">, !llvm<"i64">) -> !llvm<"float*">
|
||||
"llvm.store"(%2, %14) : (!llvm<"float">, !llvm<"float*">) -> ()
|
||||
%9 = llvm.constant(10 : index) : !llvm<"i64">
|
||||
%10 = llvm.extractvalue %arg2[1] : !llvm<"{ float*, i64 }">
|
||||
%11 = llvm.mul %0, %10 : !llvm<"i64">
|
||||
%12 = llvm.add %11, %1 : !llvm<"i64">
|
||||
%13 = llvm.extractvalue %arg2[0] : !llvm<"{ float*, i64 }">
|
||||
%14 = llvm.getelementptr %13[%12] : (!llvm<"float*">, !llvm<"i64">) -> !llvm<"float*">
|
||||
llvm.store %2, %14 : !llvm<"float*">
|
||||
// CHECK-NEXT: %{{[0-9]+}} = mul i64 10, %{{[0-9]+}}
|
||||
// CHECK-NEXT: %{{[0-9]+}} = mul i64 %{{[0-9]+}}, 4
|
||||
// CHECK-NEXT: %{{[0-9]+}} = call i8* @malloc(i64 %{{[0-9]+}})
|
||||
// CHECK-NEXT: %{{[0-9]+}} = bitcast i8* %{{[0-9]+}} to float*
|
||||
// CHECK-NEXT: %{{[0-9]+}} = insertvalue { float*, i64 } undef, float* %{{[0-9]+}}, 0
|
||||
// CHECK-NEXT: %{{[0-9]+}} = insertvalue { float*, i64 } %{{[0-9]+}}, i64 %{{[0-9]+}}, 1
|
||||
%15 = "llvm.constant"() {value: 10 : index} : () -> !llvm<"i64">
|
||||
%16 = "llvm.mul"(%15, %1) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%17 = "llvm.undef"() : () -> !llvm<"{ float*, i64 }">
|
||||
%18 = "llvm.constant"() {value: 4 : index} : () -> !llvm<"i64">
|
||||
%19 = "llvm.mul"(%16, %18) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%20 = "llvm.call"(%19) {callee: @malloc : (!llvm<"i64">) -> !llvm<"i8*">} : (!llvm<"i64">) -> !llvm<"i8*">
|
||||
%21 = "llvm.bitcast"(%20) : (!llvm<"i8*">) -> !llvm<"float*">
|
||||
%22 = "llvm.insertvalue"(%17, %21) {position: [0]} : (!llvm<"{ float*, i64 }">, !llvm<"float*">) -> !llvm<"{ float*, i64 }">
|
||||
%23 = "llvm.insertvalue"(%22, %1) {position: [1]} : (!llvm<"{ float*, i64 }">, !llvm<"i64">) -> !llvm<"{ float*, i64 }">
|
||||
%15 = llvm.constant(10 : index) : !llvm<"i64">
|
||||
%16 = llvm.mul %15, %1 : !llvm<"i64">
|
||||
%17 = llvm.undef : !llvm<"{ float*, i64 }">
|
||||
%18 = llvm.constant(4 : index) : !llvm<"i64">
|
||||
%19 = llvm.mul %16, %18 : !llvm<"i64">
|
||||
%20 = llvm.call @malloc(%19) : (!llvm<"i64">) -> !llvm<"i8*">
|
||||
%21 = llvm.bitcast %20 : !llvm<"i8*"> to !llvm<"float*">
|
||||
%22 = llvm.insertvalue %21, %17[0] : !llvm<"{ float*, i64 }">
|
||||
%23 = llvm.insertvalue %1, %22[1] : !llvm<"{ float*, i64 }">
|
||||
// CHECK-NEXT: ret { float*, i64 } %{{[0-9]+}}
|
||||
"llvm.return"(%23) : (!llvm<"{ float*, i64 }">) -> ()
|
||||
llvm.return %23 : !llvm<"{ float*, i64 }">
|
||||
}
|
||||
|
||||
|
||||
// CHECK-LABEL: define i64 @memref_dim({ float*, i64, i64 })
|
||||
func @memref_dim(%arg0: !llvm<"{ float*, i64, i64 }">) -> !llvm<"i64"> {
|
||||
// Expecting this to create an LLVM constant.
|
||||
%0 = "llvm.constant"() {value: 42 : index} : () -> !llvm<"i64">
|
||||
%0 = llvm.constant(42 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: %2 = extractvalue { float*, i64, i64 } %0, 1
|
||||
%1 = "llvm.extractvalue"(%arg0) {position: [1]} : (!llvm<"{ float*, i64, i64 }">) -> !llvm<"i64">
|
||||
%1 = llvm.extractvalue %arg0[1] : !llvm<"{ float*, i64, i64 }">
|
||||
// Expecting this to create an LLVM constant.
|
||||
%2 = "llvm.constant"() {value: 10 : index} : () -> !llvm<"i64">
|
||||
%2 = llvm.constant(10 : index) : !llvm<"i64">
|
||||
// CHECK-NEXT: %3 = extractvalue { float*, i64, i64 } %0, 2
|
||||
%3 = "llvm.extractvalue"(%arg0) {position: [2]} : (!llvm<"{ float*, i64, i64 }">) -> !llvm<"i64">
|
||||
%3 = llvm.extractvalue %arg0[2] : !llvm<"{ float*, i64, i64 }">
|
||||
// Checking that the constant for d0 has been created.
|
||||
// CHECK-NEXT: %4 = add i64 42, %2
|
||||
%4 = "llvm.add"(%0, %1) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%4 = llvm.add %0, %1 : !llvm<"i64">
|
||||
// Checking that the constant for d2 has been created.
|
||||
// CHECK-NEXT: %5 = add i64 10, %3
|
||||
%5 = "llvm.add"(%2, %3) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%5 = llvm.add %2, %3 : !llvm<"i64">
|
||||
// CHECK-NEXT: %6 = add i64 %4, %5
|
||||
%6 = "llvm.add"(%4, %5) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%6 = llvm.add %4, %5 : !llvm<"i64">
|
||||
// CHECK-NEXT: ret i64 %6
|
||||
"llvm.return"(%6) : (!llvm<"i64">) -> ()
|
||||
llvm.return %6 : !llvm<"i64">
|
||||
}
|
||||
|
||||
func @get_i64() -> !llvm<"i64">
|
||||
|
@ -643,18 +643,18 @@ func @get_memref() -> !llvm<"{ float*, i64, i64 }">
|
|||
|
||||
// CHECK-LABEL: define { i64, float, { float*, i64, i64 } } @multireturn() {
|
||||
func @multireturn() -> !llvm<"{ i64, float, { float*, i64, i64 } }"> {
|
||||
%0 = "llvm.call"() {callee: @get_i64 : () -> !llvm<"i64">} : () -> !llvm<"i64">
|
||||
%1 = "llvm.call"() {callee: @get_f32 : () -> !llvm<"float">} : () -> !llvm<"float">
|
||||
%2 = "llvm.call"() {callee: @get_memref : () -> !llvm<"{ float*, i64, i64 }">} : () -> !llvm<"{ float*, i64, i64 }">
|
||||
%0 = llvm.call @get_i64() : () -> !llvm<"i64">
|
||||
%1 = llvm.call @get_f32() : () -> !llvm<"float">
|
||||
%2 = llvm.call @get_memref() : () -> !llvm<"{ float*, i64, i64 }">
|
||||
// CHECK: %{{[0-9]+}} = insertvalue { i64, float, { float*, i64, i64 } } undef, i64 %{{[0-9]+}}, 0
|
||||
// CHECK-NEXT: %{{[0-9]+}} = insertvalue { i64, float, { float*, i64, i64 } } %{{[0-9]+}}, float %{{[0-9]+}}, 1
|
||||
// CHECK-NEXT: %{{[0-9]+}} = insertvalue { i64, float, { float*, i64, i64 } } %{{[0-9]+}}, { float*, i64, i64 } %{{[0-9]+}}, 2
|
||||
// CHECK-NEXT: ret { i64, float, { float*, i64, i64 } } %{{[0-9]+}}
|
||||
%3 = "llvm.undef"() : () -> !llvm<"{ i64, float, { float*, i64, i64 } }">
|
||||
%4 = "llvm.insertvalue"(%3, %0) {position: [0]} : (!llvm<"{ i64, float, { float*, i64, i64 } }">, !llvm<"i64">) -> !llvm<"{ i64, float, { float*, i64, i64 } }">
|
||||
%5 = "llvm.insertvalue"(%4, %1) {position: [1]} : (!llvm<"{ i64, float, { float*, i64, i64 } }">, !llvm<"float">) -> !llvm<"{ i64, float, { float*, i64, i64 } }">
|
||||
%6 = "llvm.insertvalue"(%5, %2) {position: [2]} : (!llvm<"{ i64, float, { float*, i64, i64 } }">, !llvm<"{ float*, i64, i64 }">) -> !llvm<"{ i64, float, { float*, i64, i64 } }">
|
||||
"llvm.return"(%6) : (!llvm<"{ i64, float, { float*, i64, i64 } }">) -> ()
|
||||
%3 = llvm.undef : !llvm<"{ i64, float, { float*, i64, i64 } }">
|
||||
%4 = llvm.insertvalue %0, %3[0] : !llvm<"{ i64, float, { float*, i64, i64 } }">
|
||||
%5 = llvm.insertvalue %1, %4[1] : !llvm<"{ i64, float, { float*, i64, i64 } }">
|
||||
%6 = llvm.insertvalue %2, %5[2] : !llvm<"{ i64, float, { float*, i64, i64 } }">
|
||||
llvm.return %6 : !llvm<"{ i64, float, { float*, i64, i64 } }">
|
||||
}
|
||||
|
||||
|
||||
|
@ -664,86 +664,86 @@ func @multireturn_caller() {
|
|||
// CHECK-NEXT: [[ret0:%[0-9]+]] = extractvalue { i64, float, { float*, i64, i64 } } %1, 0
|
||||
// CHECK-NEXT: [[ret1:%[0-9]+]] = extractvalue { i64, float, { float*, i64, i64 } } %1, 1
|
||||
// CHECK-NEXT: [[ret2:%[0-9]+]] = extractvalue { i64, float, { float*, i64, i64 } } %1, 2
|
||||
%0 = "llvm.call"() {callee: @multireturn : () -> !llvm<"{ i64, float, { float*, i64, i64 } }">} : () -> !llvm<"{ i64, float, { float*, i64, i64 } }">
|
||||
%1 = "llvm.extractvalue"(%0) {position: [0]} : (!llvm<"{ i64, float, { float*, i64, i64 } }">) -> !llvm<"i64">
|
||||
%2 = "llvm.extractvalue"(%0) {position: [1]} : (!llvm<"{ i64, float, { float*, i64, i64 } }">) -> !llvm<"float">
|
||||
%3 = "llvm.extractvalue"(%0) {position: [2]} : (!llvm<"{ i64, float, { float*, i64, i64 } }">) -> !llvm<"{ float*, i64, i64 }">
|
||||
%4 = "llvm.constant"() {value: 42} : () -> !llvm<"i64">
|
||||
%0 = llvm.call @multireturn() : () -> !llvm<"{ i64, float, { float*, i64, i64 } }">
|
||||
%1 = llvm.extractvalue %0[0] : !llvm<"{ i64, float, { float*, i64, i64 } }">
|
||||
%2 = llvm.extractvalue %0[1] : !llvm<"{ i64, float, { float*, i64, i64 } }">
|
||||
%3 = llvm.extractvalue %0[2] : !llvm<"{ i64, float, { float*, i64, i64 } }">
|
||||
%4 = llvm.constant(42) : !llvm<"i64">
|
||||
// CHECK: add i64 [[ret0]], 42
|
||||
%5 = "llvm.add"(%1, %4) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%6 = "llvm.constant"() {value: 4.200000e+01 : f32} : () -> !llvm<"float">
|
||||
%5 = llvm.add %1, %4 : !llvm<"i64">
|
||||
%6 = llvm.constant(4.200000e+01 : f32) : !llvm<"float">
|
||||
// CHECK: fadd float [[ret1]], 4.200000e+01
|
||||
%7 = "llvm.fadd"(%2, %6) : (!llvm<"float">, !llvm<"float">) -> !llvm<"float">
|
||||
%8 = "llvm.constant"() {value: 0 : index} : () -> !llvm<"i64">
|
||||
%9 = "llvm.constant"() {value: 42 : index} : () -> !llvm<"i64">
|
||||
%7 = llvm.fadd %2, %6 : !llvm<"float">
|
||||
%8 = llvm.constant(0 : index) : !llvm<"i64">
|
||||
%9 = llvm.constant(42 : index) : !llvm<"i64">
|
||||
// CHECK: extractvalue { float*, i64, i64 } [[ret2]], 0
|
||||
%10 = "llvm.extractvalue"(%3) {position: [1]} : (!llvm<"{ float*, i64, i64 }">) -> !llvm<"i64">
|
||||
%11 = "llvm.constant"() {value: 10 : index} : () -> !llvm<"i64">
|
||||
%12 = "llvm.extractvalue"(%3) {position: [2]} : (!llvm<"{ float*, i64, i64 }">) -> !llvm<"i64">
|
||||
%13 = "llvm.mul"(%8, %10) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%14 = "llvm.add"(%13, %8) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%15 = "llvm.mul"(%14, %11) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%16 = "llvm.add"(%15, %8) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%17 = "llvm.mul"(%16, %12) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%18 = "llvm.add"(%17, %8) : (!llvm<"i64">, !llvm<"i64">) -> !llvm<"i64">
|
||||
%19 = "llvm.extractvalue"(%3) {position: [0]} : (!llvm<"{ float*, i64, i64 }">) -> !llvm<"float*">
|
||||
%20 = "llvm.getelementptr"(%19, %18) : (!llvm<"float*">, !llvm<"i64">) -> !llvm<"float*">
|
||||
%21 = "llvm.load"(%20) : (!llvm<"float*">) -> !llvm<"float">
|
||||
"llvm.return"() : () -> ()
|
||||
%10 = llvm.extractvalue %3[1] : !llvm<"{ float*, i64, i64 }">
|
||||
%11 = llvm.constant(10 : index) : !llvm<"i64">
|
||||
%12 = llvm.extractvalue %3[2] : !llvm<"{ float*, i64, i64 }">
|
||||
%13 = llvm.mul %8, %10 : !llvm<"i64">
|
||||
%14 = llvm.add %13, %8 : !llvm<"i64">
|
||||
%15 = llvm.mul %14, %11 : !llvm<"i64">
|
||||
%16 = llvm.add %15, %8 : !llvm<"i64">
|
||||
%17 = llvm.mul %16, %12 : !llvm<"i64">
|
||||
%18 = llvm.add %17, %8 : !llvm<"i64">
|
||||
%19 = llvm.extractvalue %3[0] : !llvm<"{ float*, i64, i64 }">
|
||||
%20 = llvm.getelementptr %19[%18] : (!llvm<"float*">, !llvm<"i64">) -> !llvm<"float*">
|
||||
%21 = llvm.load %20 : !llvm<"float*">
|
||||
llvm.return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define <4 x float> @vector_ops(<4 x float>, <4 x i1>, <4 x i64>) {
|
||||
func @vector_ops(%arg0: !llvm<"<4 x float>">, %arg1: !llvm<"<4 x i1>">, %arg2: !llvm<"<4 x i64>">) -> !llvm<"<4 x float>"> {
|
||||
%0 = "llvm.constant"() {value: splat<vector<4xf32>, 4.200000e+01>} : () -> !llvm<"<4 x float>">
|
||||
%0 = llvm.constant(splat<vector<4xf32>, 4.200000e+01>) : !llvm<"<4 x float>">
|
||||
// CHECK-NEXT: %4 = fadd <4 x float> %0, <float 4.200000e+01, float 4.200000e+01, float 4.200000e+01, float 4.200000e+01>
|
||||
%1 = "llvm.fadd"(%arg0, %0) : (!llvm<"<4 x float>">, !llvm<"<4 x float>">) -> !llvm<"<4 x float>">
|
||||
%1 = llvm.fadd %arg0, %0 : !llvm<"<4 x float>">
|
||||
// CHECK-NEXT: %5 = select <4 x i1> %1, <4 x float> %4, <4 x float> %0
|
||||
%2 = "llvm.select"(%arg1, %1, %arg0) : (!llvm<"<4 x i1>">, !llvm<"<4 x float>">, !llvm<"<4 x float>">) -> !llvm<"<4 x float>">
|
||||
%2 = llvm.select %arg1, %1, %arg0 : !llvm<"<4 x i1>">, !llvm<"<4 x float>">
|
||||
// CHECK-NEXT: %6 = sdiv <4 x i64> %2, %2
|
||||
%3 = "llvm.sdiv"(%arg2, %arg2) : (!llvm<"<4 x i64>">, !llvm<"<4 x i64>">) -> !llvm<"<4 x i64>">
|
||||
%3 = llvm.sdiv %arg2, %arg2 : !llvm<"<4 x i64>">
|
||||
// CHECK-NEXT: %7 = udiv <4 x i64> %2, %2
|
||||
%4 = "llvm.udiv"(%arg2, %arg2) : (!llvm<"<4 x i64>">, !llvm<"<4 x i64>">) -> !llvm<"<4 x i64>">
|
||||
%4 = llvm.udiv %arg2, %arg2 : !llvm<"<4 x i64>">
|
||||
// CHECK-NEXT: %8 = srem <4 x i64> %2, %2
|
||||
%5 = "llvm.srem"(%arg2, %arg2) : (!llvm<"<4 x i64>">, !llvm<"<4 x i64>">) -> !llvm<"<4 x i64>">
|
||||
%5 = llvm.srem %arg2, %arg2 : !llvm<"<4 x i64>">
|
||||
// CHECK-NEXT: %9 = urem <4 x i64> %2, %2
|
||||
%6 = "llvm.urem"(%arg2, %arg2) : (!llvm<"<4 x i64>">, !llvm<"<4 x i64>">) -> !llvm<"<4 x i64>">
|
||||
%6 = llvm.urem %arg2, %arg2 : !llvm<"<4 x i64>">
|
||||
// CHECK-NEXT: %10 = fdiv <4 x float> %0, <float 4.200000e+01, float 4.200000e+01, float 4.200000e+01, float 4.200000e+01>
|
||||
%7 = "llvm.fdiv"(%arg0, %0) : (!llvm<"<4 x float>">, !llvm<"<4 x float>">) -> !llvm<"<4 x float>">
|
||||
%7 = llvm.fdiv %arg0, %0 : !llvm<"<4 x float>">
|
||||
// CHECK-NEXT: %11 = frem <4 x float> %0, <float 4.200000e+01, float 4.200000e+01, float 4.200000e+01, float 4.200000e+01>
|
||||
%8 = "llvm.frem"(%arg0, %0) : (!llvm<"<4 x float>">, !llvm<"<4 x float>">) -> !llvm<"<4 x float>">
|
||||
%8 = llvm.frem %arg0, %0 : !llvm<"<4 x float>">
|
||||
// CHECK-NEXT: ret <4 x float> %4
|
||||
"llvm.return"(%1) : (!llvm<"<4 x float>">) -> ()
|
||||
llvm.return %1 : !llvm<"<4 x float>">
|
||||
}
|
||||
|
||||
// CHECK-LABEL: @ops
|
||||
func @ops(%arg0: !llvm<"float">, %arg1: !llvm<"float">, %arg2: !llvm<"i32">, %arg3: !llvm<"i32">) -> !llvm<"{ float, i32 }"> {
|
||||
// CHECK-NEXT: fsub float %0, %1
|
||||
%0 = "llvm.fsub"(%arg0, %arg1) : (!llvm<"float">, !llvm<"float">) -> !llvm<"float">
|
||||
%0 = llvm.fsub %arg0, %arg1 : !llvm<"float">
|
||||
// CHECK-NEXT: %6 = sub i32 %2, %3
|
||||
%1 = "llvm.sub"(%arg2, %arg3) : (!llvm<"i32">, !llvm<"i32">) -> !llvm<"i32">
|
||||
%1 = llvm.sub %arg2, %arg3 : !llvm<"i32">
|
||||
// CHECK-NEXT: %7 = icmp slt i32 %2, %6
|
||||
%2 = "llvm.icmp"(%arg2, %1) {predicate: 2} : (!llvm<"i32">, !llvm<"i32">) -> !llvm<"i1">
|
||||
%2 = llvm.icmp "slt" %arg2, %1 : !llvm<"i32">
|
||||
// CHECK-NEXT: %8 = select i1 %7, i32 %2, i32 %6
|
||||
%3 = "llvm.select"(%2, %arg2, %1) : (!llvm<"i1">, !llvm<"i32">, !llvm<"i32">) -> !llvm<"i32">
|
||||
%3 = llvm.select %2, %arg2, %1 : !llvm<"i1">, !llvm<"i32">
|
||||
// CHECK-NEXT: %9 = sdiv i32 %2, %3
|
||||
%4 = "llvm.sdiv"(%arg2, %arg3) : (!llvm<"i32">, !llvm<"i32">) -> !llvm<"i32">
|
||||
%4 = llvm.sdiv %arg2, %arg3 : !llvm<"i32">
|
||||
// CHECK-NEXT: %10 = udiv i32 %2, %3
|
||||
%5 = "llvm.udiv"(%arg2, %arg3) : (!llvm<"i32">, !llvm<"i32">) -> !llvm<"i32">
|
||||
%5 = llvm.udiv %arg2, %arg3 : !llvm<"i32">
|
||||
// CHECK-NEXT: %11 = srem i32 %2, %3
|
||||
%6 = "llvm.srem"(%arg2, %arg3) : (!llvm<"i32">, !llvm<"i32">) -> !llvm<"i32">
|
||||
%6 = llvm.srem %arg2, %arg3 : !llvm<"i32">
|
||||
// CHECK-NEXT: %12 = urem i32 %2, %3
|
||||
%7 = "llvm.urem"(%arg2, %arg3) : (!llvm<"i32">, !llvm<"i32">) -> !llvm<"i32">
|
||||
%7 = llvm.urem %arg2, %arg3 : !llvm<"i32">
|
||||
|
||||
%8 = "llvm.undef"() : () -> !llvm<"{ float, i32 }">
|
||||
%9 = "llvm.insertvalue"(%8, %0) {position: [0]} : (!llvm<"{ float, i32 }">, !llvm<"float">) -> !llvm<"{ float, i32 }">
|
||||
%10 = "llvm.insertvalue"(%9, %3) {position: [1]} : (!llvm<"{ float, i32 }">, !llvm<"i32">) -> !llvm<"{ float, i32 }">
|
||||
%8 = llvm.undef : !llvm<"{ float, i32 }">
|
||||
%9 = llvm.insertvalue %0, %8[0] : !llvm<"{ float, i32 }">
|
||||
%10 = llvm.insertvalue %3, %9[1] : !llvm<"{ float, i32 }">
|
||||
|
||||
// CHECK: %15 = fdiv float %0, %1
|
||||
%11 = "llvm.fdiv"(%arg0, %arg1) : (!llvm<"float">, !llvm<"float">) -> !llvm<"float">
|
||||
%11 = llvm.fdiv %arg0, %arg1 : !llvm<"float">
|
||||
// CHECK-NEXT: %16 = frem float %0, %1
|
||||
%12 = "llvm.frem"(%arg0, %arg1) : (!llvm<"float">, !llvm<"float">) -> !llvm<"float">
|
||||
%12 = llvm.frem %arg0, %arg1 : !llvm<"float">
|
||||
|
||||
"llvm.return"(%10) : (!llvm<"{ float, i32 }">) -> ()
|
||||
llvm.return %10 : !llvm<"{ float, i32 }">
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -753,18 +753,18 @@ func @ops(%arg0: !llvm<"float">, %arg1: !llvm<"float">, %arg2: !llvm<"i32">, %ar
|
|||
// CHECK-LABEL: define void @indirect_const_call(i64) {
|
||||
func @indirect_const_call(%arg0: !llvm<"i64">) {
|
||||
// CHECK-NEXT: call void @body(i64 %0)
|
||||
%0 = "llvm.constant"() {value: @body : (!llvm<"i64">) -> ()} : () -> !llvm<"void (i64)*">
|
||||
"llvm.call"(%0, %arg0) : (!llvm<"void (i64)*">, !llvm<"i64">) -> ()
|
||||
%0 = llvm.constant(@body : (!llvm<"i64">) -> ()) : !llvm<"void (i64)*">
|
||||
llvm.call %0(%arg0) : (!llvm<"i64">) -> ()
|
||||
// CHECK-NEXT: ret void
|
||||
"llvm.return"() : () -> ()
|
||||
llvm.return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define i32 @indirect_call(i32 (float)*, float) {
|
||||
func @indirect_call(%arg0: !llvm<"i32 (float)*">, %arg1: !llvm<"float">) -> !llvm<"i32"> {
|
||||
// CHECK-NEXT: %3 = call i32 %0(float %1)
|
||||
%0 = "llvm.call"(%arg0, %arg1) : (!llvm<"i32 (float)*">, !llvm<"float">) -> !llvm<"i32">
|
||||
%0 = llvm.call %arg0(%arg1) : (!llvm<"float">) -> !llvm<"i32">
|
||||
// CHECK-NEXT: ret i32 %3
|
||||
"llvm.return"(%0) : (!llvm<"i32">) -> ()
|
||||
llvm.return %0 : !llvm<"i32">
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -775,21 +775,21 @@ func @indirect_call(%arg0: !llvm<"i32 (float)*">, %arg1: !llvm<"float">) -> !llv
|
|||
// CHECK-LABEL: define void @cond_br_arguments(i1, i1) {
|
||||
func @cond_br_arguments(%arg0: !llvm<"i1">, %arg1: !llvm<"i1">) {
|
||||
// CHECK-NEXT: br i1 %0, label %3, label %5
|
||||
"llvm.cond_br"(%arg0)[^bb2(%arg0 : !llvm<"i1">), ^bb3] : (!llvm<"i1">) -> ()
|
||||
llvm.cond_br %arg0, ^bb1(%arg0 : !llvm<"i1">), ^bb2
|
||||
|
||||
// CHECK: 3:
|
||||
// CHECK-NEXT: %4 = phi i1 [ %1, %5 ], [ %0, %2 ]
|
||||
^bb2(%0 : !llvm<"i1">):
|
||||
^bb1(%0 : !llvm<"i1">):
|
||||
// CHECK-NEXT: ret void
|
||||
"llvm.return"() : () -> ()
|
||||
llvm.return
|
||||
|
||||
// CHECK: 5:
|
||||
^bb3:
|
||||
^bb2:
|
||||
// CHECK-NEXT: br label %3
|
||||
"llvm.br"()[^bb2(%arg1 : !llvm<"i1">)] : () -> ()
|
||||
llvm.br ^bb1(%arg1 : !llvm<"i1">)
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define void @llvm_noalias(float* noalias) {
|
||||
func @llvm_noalias(%arg0: !llvm<"float*"> {llvm.noalias: true}) {
|
||||
"llvm.return"() : () -> ()
|
||||
llvm.return
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue