[llvm] r348430 - [GlobalISel] Introduce G_BUILD_VECTOR, G_BUILD_VECTOR_TRUNC and G_CONCAT_VECTOR opcodes.
Amara Emerson via llvm-commits
llvm-commits at lists.llvm.org
Wed Dec 5 15:53:30 PST 2018
Author: aemerson
Date: Wed Dec 5 15:53:30 2018
New Revision: 348430
URL: http://llvm.org/viewvc/llvm-project?rev=348430&view=rev
Log:
[GlobalISel] Introduce G_BUILD_VECTOR, G_BUILD_VECTOR_TRUNC and G_CONCAT_VECTOR opcodes.
These opcodes are intended to subsume some of the capability of G_MERGE_VALUES,
as it was too powerful and thus complex to add deal with throughout the GISel
pipeline.
G_BUILD_VECTOR creates a vector value from a sequence of uniformly typed
scalar values. G_BUILD_VECTOR_TRUNC is a special opcode for handling scalar
operands which are larger than the destination vector element type, and
therefore does an implicit truncate.
G_CONCAT_VECTOR creates a vector by concatenating smaller, uniformly typed,
vectors together.
These will be used in a subsequent commit. This commit just adds the initial
infrastructure.
Differential Revision: https://reviews.llvm.org/D53594
Added:
llvm/trunk/test/Verifier/gisel-g_build_vector.mir
llvm/trunk/test/Verifier/gisel-g_build_vector_trunc.mir
llvm/trunk/test/Verifier/gisel-g_concat_vector.mir
Modified:
llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
llvm/trunk/include/llvm/Support/TargetOpcodes.def
llvm/trunk/include/llvm/Target/GenericOpcodes.td
llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
llvm/trunk/lib/CodeGen/MachineVerifier.cpp
llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
Modified: llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h?rev=348430&r1=348429&r2=348430&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h (original)
+++ llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h Wed Dec 5 15:53:30 2018
@@ -603,6 +603,46 @@ public:
/// \return a MachineInstrBuilder for the newly created instruction.
MachineInstrBuilder buildUnmerge(ArrayRef<unsigned> Res, unsigned Op);
+ /// Build and insert \p Res = G_BUILD_VECTOR \p Op0, ...
+ ///
+ /// G_BUILD_VECTOR creates a vector value from multiple scalar registers.
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre The entire register \p Res (and no more) must be covered by the
+ /// input scalar registers.
+ /// \pre The type of all \p Ops registers must be identical.
+ ///
+ /// \return a MachineInstrBuilder for the newly created instruction.
+ MachineInstrBuilder buildBuildVector(unsigned Res, ArrayRef<unsigned> Ops);
+
+ /// Build and insert \p Res = G_BUILD_VECTOR_TRUNC \p Op0, ...
+ ///
+ /// G_BUILD_VECTOR_TRUNC creates a vector value from multiple scalar registers
+ /// which have types larger than the destination vector element type, and
+ /// truncates the values to fit.
+ ///
+ /// If the operands given are already the same size as the vector elt type,
+ /// then this method will instead create a G_BUILD_VECTOR instruction.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre The type of all \p Ops registers must be identical.
+ ///
+ /// \return a MachineInstrBuilder for the newly created instruction.
+ MachineInstrBuilder buildBuildVectorTrunc(unsigned Res,
+ ArrayRef<unsigned> Ops);
+
+ /// Build and insert \p Res = G_CONCAT_VECTORS \p Op0, ...
+ ///
+ /// G_CONCAT_VECTORS creates a vector from the concatenation of 2 or more
+ /// vectors.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre The entire register \p Res (and no more) must be covered by the input
+ /// registers.
+ /// \pre The type of all source operands must be identical.
+ ///
+ /// \return a MachineInstrBuilder for the newly created instruction.
+ MachineInstrBuilder buildConcatVectors(unsigned Res, ArrayRef<unsigned> Ops);
+
MachineInstrBuilder buildInsert(unsigned Res, unsigned Src,
unsigned Op, unsigned Index);
Modified: llvm/trunk/include/llvm/Support/TargetOpcodes.def
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/TargetOpcodes.def?rev=348430&r1=348429&r2=348430&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/TargetOpcodes.def (original)
+++ llvm/trunk/include/llvm/Support/TargetOpcodes.def Wed Dec 5 15:53:30 2018
@@ -258,6 +258,17 @@ HANDLE_TARGET_OPCODE(G_INSERT)
/// larger register.
HANDLE_TARGET_OPCODE(G_MERGE_VALUES)
+/// Generic instruction to create a vector value from a number of scalar
+/// components.
+HANDLE_TARGET_OPCODE(G_BUILD_VECTOR)
+
+/// Generic instruction to create a vector value from a number of scalar
+/// components, which have types larger than the result vector elt type.
+HANDLE_TARGET_OPCODE(G_BUILD_VECTOR_TRUNC)
+
+/// Generic instruction to create a vector by concatenating multiple vectors.
+HANDLE_TARGET_OPCODE(G_CONCAT_VECTORS)
+
/// Generic pointer to int conversion.
HANDLE_TARGET_OPCODE(G_PTRTOINT)
Modified: llvm/trunk/include/llvm/Target/GenericOpcodes.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/GenericOpcodes.td?rev=348430&r1=348429&r2=348430&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Target/GenericOpcodes.td (original)
+++ llvm/trunk/include/llvm/Target/GenericOpcodes.td Wed Dec 5 15:53:30 2018
@@ -675,6 +675,28 @@ def G_MERGE_VALUES : GenericInstruction
let hasSideEffects = 0;
}
+/// Create a vector from multiple scalar registers.
+def G_BUILD_VECTOR : GenericInstruction {
+ let OutOperandList = (outs type0:$dst);
+ let InOperandList = (ins type1:$src0, variable_ops);
+ let hasSideEffects = 0;
+}
+
+/// Like G_BUILD_VECTOR, but truncates the larger operand types to fit the
+/// destination vector elt type.
+def G_BUILD_VECTOR_TRUNC : GenericInstruction {
+ let OutOperandList = (outs type0:$dst);
+ let InOperandList = (ins type1:$src0, variable_ops);
+ let hasSideEffects = 0;
+}
+
+/// Create a vector by concatenating vectors together.
+def G_CONCAT_VECTORS : GenericInstruction {
+ let OutOperandList = (outs type0:$dst);
+ let InOperandList = (ins type1:$src0, variable_ops);
+ let hasSideEffects = 0;
+}
+
// Intrinsic without side effects.
def G_INTRINSIC : GenericInstruction {
let OutOperandList = (outs);
Modified: llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp?rev=348430&r1=348429&r2=348430&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp (original)
+++ llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp Wed Dec 5 15:53:30 2018
@@ -519,6 +519,64 @@ MachineInstrBuilder MachineIRBuilderBase
return MIB;
}
+MachineInstrBuilder
+MachineIRBuilderBase::buildBuildVector(unsigned Res, ArrayRef<unsigned> Ops) {
+#ifndef NDEBUG
+ assert((!Ops.empty() || Ops.size() < 2) && "Must have at least 2 operands");
+ assert(getMRI()->getType(Res).isVector() && "Res type must be a vector");
+ LLT Ty = getMRI()->getType(Ops[0]);
+ for (auto Reg : Ops)
+ assert(getMRI()->getType(Reg) == Ty && "type mismatch in input list");
+ assert(Ops.size() * Ty.getSizeInBits() ==
+ getMRI()->getType(Res).getSizeInBits() &&
+ "input scalars do not exactly cover the outpur vector register");
+#endif
+ MachineInstrBuilder MIB = buildInstr(TargetOpcode::G_BUILD_VECTOR);
+ MIB.addDef(Res);
+ for (auto Op : Ops)
+ MIB.addUse(Op);
+ return MIB;
+}
+
+MachineInstrBuilder
+MachineIRBuilderBase::buildBuildVectorTrunc(unsigned Res,
+ ArrayRef<unsigned> Ops) {
+#ifndef NDEBUG
+ assert((!Ops.empty() || Ops.size() < 2) && "Must have at least 2 operands");
+ LLT Ty = getMRI()->getType(Ops[0]);
+ for (auto Reg : Ops)
+ assert(getMRI()->getType(Reg) == Ty && "type mismatch in input list");
+#endif
+ if (getMRI()->getType(Ops[0]).getSizeInBits() ==
+ getMRI()->getType(Res).getElementType().getSizeInBits())
+ return buildBuildVector(Res, Ops);
+ MachineInstrBuilder MIB = buildInstr(TargetOpcode::G_BUILD_VECTOR_TRUNC);
+ MIB.addDef(Res);
+ for (auto Op : Ops)
+ MIB.addUse(Op);
+ return MIB;
+}
+
+MachineInstrBuilder
+MachineIRBuilderBase::buildConcatVectors(unsigned Res, ArrayRef<unsigned> Ops) {
+ #ifndef NDEBUG
+ assert((!Ops.empty() || Ops.size() < 2) && "Must have at least 2 operands");
+ LLT Ty = getMRI()->getType(Ops[0]);
+ for (auto Reg : Ops) {
+ assert(getMRI()->getType(Reg).isVector() && "expected vector operand");
+ assert(getMRI()->getType(Reg) == Ty && "type mismatch in input list");
+ }
+ assert(Ops.size() * Ty.getSizeInBits() ==
+ getMRI()->getType(Res).getSizeInBits() &&
+ "input vectors do not exactly cover the outpur vector register");
+ #endif
+ MachineInstrBuilder MIB = buildInstr(TargetOpcode::G_CONCAT_VECTORS);
+ MIB.addDef(Res);
+ for (auto Op : Ops)
+ MIB.addUse(Op);
+ return MIB;
+}
+
MachineInstrBuilder MachineIRBuilderBase::buildInsert(unsigned Res,
unsigned Src, unsigned Op,
unsigned Index) {
Modified: llvm/trunk/lib/CodeGen/MachineVerifier.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MachineVerifier.cpp?rev=348430&r1=348429&r2=348430&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/MachineVerifier.cpp (original)
+++ llvm/trunk/lib/CodeGen/MachineVerifier.cpp Wed Dec 5 15:53:30 2018
@@ -1055,6 +1055,63 @@ void MachineVerifier::visitMachineInstrB
}
break;
}
+ case TargetOpcode::G_BUILD_VECTOR: {
+ // Source types must be scalars, dest type a vector. Total size of scalars
+ // must match the dest vector size.
+ LLT DstTy = MRI->getType(MI->getOperand(0).getReg());
+ LLT SrcEltTy = MRI->getType(MI->getOperand(1).getReg());
+ if (!DstTy.isVector() || SrcEltTy.isVector())
+ report("G_BUILD_VECTOR must produce a vector from scalar operands", MI);
+ for (unsigned i = 2; i < MI->getNumOperands(); ++i) {
+ if (MRI->getType(MI->getOperand(1).getReg()) !=
+ MRI->getType(MI->getOperand(i).getReg()))
+ report("G_BUILD_VECTOR source operand types are not homogeneous", MI);
+ }
+ if (DstTy.getSizeInBits() !=
+ SrcEltTy.getSizeInBits() * (MI->getNumOperands() - 1))
+ report("G_BUILD_VECTOR src operands total size don't match dest "
+ "size.",
+ MI);
+ break;
+ }
+ case TargetOpcode::G_BUILD_VECTOR_TRUNC: {
+ // Source types must be scalars, dest type a vector. Scalar types must be
+ // larger than the dest vector elt type, as this is a truncating operation.
+ LLT DstTy = MRI->getType(MI->getOperand(0).getReg());
+ LLT SrcEltTy = MRI->getType(MI->getOperand(1).getReg());
+ if (!DstTy.isVector() || SrcEltTy.isVector())
+ report("G_BUILD_VECTOR_TRUNC must produce a vector from scalar operands",
+ MI);
+ for (unsigned i = 2; i < MI->getNumOperands(); ++i) {
+ if (MRI->getType(MI->getOperand(1).getReg()) !=
+ MRI->getType(MI->getOperand(i).getReg()))
+ report("G_BUILD_VECTOR_TRUNC source operand types are not homogeneous",
+ MI);
+ }
+ if (SrcEltTy.getSizeInBits() <= DstTy.getElementType().getSizeInBits())
+ report("G_BUILD_VECTOR_TRUNC source operand types are not larger than "
+ "dest elt type",
+ MI);
+ break;
+ }
+ case TargetOpcode::G_CONCAT_VECTORS: {
+ // Source types should be vectors, and total size should match the dest
+ // vector size.
+ LLT DstTy = MRI->getType(MI->getOperand(0).getReg());
+ LLT SrcTy = MRI->getType(MI->getOperand(1).getReg());
+ if (!DstTy.isVector() || !SrcTy.isVector())
+ report("G_CONCAT_VECTOR requires vector source and destination operands",
+ MI);
+ for (unsigned i = 2; i < MI->getNumOperands(); ++i) {
+ if (MRI->getType(MI->getOperand(1).getReg()) !=
+ MRI->getType(MI->getOperand(i).getReg()))
+ report("G_CONCAT_VECTOR source operand types are not homogeneous", MI);
+ }
+ if (DstTy.getNumElements() !=
+ SrcTy.getNumElements() * (MI->getNumOperands() - 1))
+ report("G_CONCAT_VECTOR num dest and source elements should match", MI);
+ break;
+ }
case TargetOpcode::COPY: {
if (foundErrors)
break;
Modified: llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir?rev=348430&r1=348429&r2=348430&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir (original)
+++ llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir Wed Dec 5 15:53:30 2018
@@ -69,6 +69,15 @@
# DEBUG-NEXT: G_MERGE_VALUES (opcode {{[0-9]+}}): 2 type indices
# DEBUG: .. type index coverage check SKIPPED: user-defined predicate detected
#
+# DEBUG-NEXT: G_BUILD_VECTOR (opcode {{[0-9]+}}): 2 type indices
+# DEBUG: .. type index coverage check SKIPPED: no rules defined
+#
+# DEBUG-NEXT: G_BUILD_VECTOR_TRUNC (opcode {{[0-9]+}}): 2 type indices
+# DEBUG: .. type index coverage check SKIPPED: no rules defined
+#
+# DEBUG-NEXT: G_CONCAT_VECTORS (opcode {{[0-9]+}}): 2 type indices
+# DEBUG: .. type index coverage check SKIPPED: no rules defined
+#
# DEBUG-NEXT: G_PTRTOINT (opcode {{[0-9]+}}): 2 type indices
# DEBUG: .. the first uncovered type index: 2, OK
#
Added: llvm/trunk/test/Verifier/gisel-g_build_vector.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/gisel-g_build_vector.mir?rev=348430&view=auto
==============================================================================
--- llvm/trunk/test/Verifier/gisel-g_build_vector.mir (added)
+++ llvm/trunk/test/Verifier/gisel-g_build_vector.mir Wed Dec 5 15:53:30 2018
@@ -0,0 +1,27 @@
+#RUN: not llc -o - -global-isel -run-pass=none -verify-machineinstrs %s 2>&1 | FileCheck %s
+# REQUIRES: global-isel, aarch64-registered-target
+--- |
+ target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+ target triple = "aarch64-unknown-unknown"
+
+ define i32 @g_build_vector() {
+ ret i32 0
+ }
+
+...
+---
+name: g_build_vector
+legalized: true
+regBankSelected: false
+selected: false
+tracksRegLiveness: true
+registers:
+ - { id: 0, class: _, preferred-register: '' }
+liveins:
+body: |
+ bb.0:
+ ; CHECK: Bad machine code: G_BUILD_VECTOR src operands total size don't match dest size
+
+ %0(s32) = IMPLICIT_DEF
+ %1:_(<2 x s32>) = G_BUILD_VECTOR %0, %0, %0, %0
+...
Added: llvm/trunk/test/Verifier/gisel-g_build_vector_trunc.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/gisel-g_build_vector_trunc.mir?rev=348430&view=auto
==============================================================================
--- llvm/trunk/test/Verifier/gisel-g_build_vector_trunc.mir (added)
+++ llvm/trunk/test/Verifier/gisel-g_build_vector_trunc.mir Wed Dec 5 15:53:30 2018
@@ -0,0 +1,27 @@
+#RUN: not llc -o - -global-isel -run-pass=none -verify-machineinstrs %s 2>&1 | FileCheck %s
+# REQUIRES: global-isel, aarch64-registered-target
+--- |
+ target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+ target triple = "aarch64-unknown-unknown"
+
+ define i32 @g_build_vector_trunc() {
+ ret i32 0
+ }
+
+...
+---
+name: g_build_vector_trunc
+legalized: true
+regBankSelected: false
+selected: false
+tracksRegLiveness: true
+registers:
+ - { id: 0, class: _, preferred-register: '' }
+liveins:
+body: |
+ bb.0:
+ ; CHECK: Bad machine code: G_BUILD_VECTOR_TRUNC source operand types are not larger than dest elt type
+
+ %0(s32) = IMPLICIT_DEF
+ %1:_(<2 x s32>) = G_BUILD_VECTOR_TRUNC %0, %0
+...
Added: llvm/trunk/test/Verifier/gisel-g_concat_vector.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/gisel-g_concat_vector.mir?rev=348430&view=auto
==============================================================================
--- llvm/trunk/test/Verifier/gisel-g_concat_vector.mir (added)
+++ llvm/trunk/test/Verifier/gisel-g_concat_vector.mir Wed Dec 5 15:53:30 2018
@@ -0,0 +1,29 @@
+#RUN: not llc -o - -global-isel -run-pass=none -verify-machineinstrs %s 2>&1 | FileCheck %s
+# REQUIRES: global-isel, aarch64-registered-target
+--- |
+ target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+ target triple = "aarch64-unknown-unknown"
+
+ define i32 @g_concat_vectors() {
+ ret i32 0
+ }
+
+...
+---
+name: g_concat_vectors
+legalized: true
+regBankSelected: false
+selected: false
+tracksRegLiveness: true
+registers:
+ - { id: 0, class: _, preferred-register: '' }
+ - { id: 1, class: _, preferred-register: '' }
+liveins:
+body: |
+ bb.0:
+ ; CHECK: Bad machine code: G_CONCAT_VECTOR num dest and source elements should match
+
+ %0(<2 x s32>) = IMPLICIT_DEF
+ %1(<2 x s32>) = IMPLICIT_DEF
+ %2:_(<2 x s32>) = G_CONCAT_VECTORS %0, %1
+...
More information about the llvm-commits
mailing list