Complex proposal v2

All,

Here is the second revision of the proposal for a complex type in LLVM.
It clarifies a few things that came up during discussion and adds
additional operations for complex types.

                         -David

Proposal to Support Complex Operations in LLVM

I think that "cunzip" returning a pair of vectors would be better. If both results are needed, they could usually be generated by a single instruction corresponding to some kind of a shuffle, but in order to generate that instruction, the backend would have to see both of the "extract*" intrinsics. With cunzip, if one only wants a single part, they can ignore the other element of the pair.

-Krzysztof

Krzysztof Parzyszek via llvm-dev <llvm-dev@lists.llvm.org> writes:

From: llvm-dev <llvm-dev-bounces@lists.llvm.org> On Behalf Of David Greene
via llvm-dev
Sent: Thursday, August 29, 2019 10:05 AM
To: llvm-dev <llvm-dev@lists.llvm.org>
Subject: [EXT] [llvm-dev] Complex proposal v2

[...]

llvm.extractreal.* - Overloaded intrinsic to create a vector of
                     floating-point type from the real portions of a
                     vector of complex (not all variants shown)

declare v4f32 @llvm.extractreal.v4c32(v4c32 %val) declare v4f64
@llvm.extractreal.v4c64(v4c64 %val)

llvm.extractimag.* - Overloaded intrinsic to create a vector of
                     floating-point type from the imaginary portions
                     of a vector of complex (not all variants shown)

declare v4f32 @llvm.extractimag.v4c32(v4c32 %val) declare v4f64
@llvm.extractimag.v4c64(v4c64 %val)

I think that "cunzip" returning a pair of vectors would be better. If
both results are needed, they could usually be generated by a single
instruction corresponding to some kind of a shuffle, but in order to
generate that instruction, the backend would have to see both of the
"extract*" intrinsics. With cunzip, if one only wants a single part,
they can ignore the other element of the pair.

Do you mean return a struct containing two vectors or something else?
If a struct, we'd have to define a new built-in struct type then, right?
Are there other examples of intrinsics (or instructions) that return
pairs?

I agree that a single intrinsic would be better. I couldn't think of a
good way to do it though.

                         -David

Yes, that's what I meant.

Hexagon has a few intrinsics that return multiple values:

multiclass Hexagon_custom_circ_ld_Intrinsic<LLVMType ElTy> {
  def NAME#_pci : Hexagon_NonGCC_Intrinsic<
    [ElTy, llvm_ptr_ty],
    [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty],
    [IntrArgMemOnly, NoCapture<3>]>;
  def NAME#_pcr : Hexagon_NonGCC_Intrinsic<
    [ElTy, llvm_ptr_ty], [llvm_ptr_ty, llvm_i32_ty, llvm_ptr_ty],
    [IntrArgMemOnly, NoCapture<2>]>;
}

(see include/llvm/IR/IntrinsicsHexagon.td)

In C/C++ they are expressed as taking extra parameters (Tools/clang/test/CodeGen/builtins-hexagon-circ.c). I think it could work for vectors as well (if they can't be declared as returning a struct outright).

-Krzysztof

Krzysztof Parzyszek via llvm-dev <llvm-dev@lists.llvm.org> writes:

Yes, that's what I meant.

Hexagon has a few intrinsics that return multiple values:

Thanks for the pointers! I'll take a look and change this in the next
revision.

                    -David