diff --git a/docs/GlobalISel/GenericOpcode.rst b/docs/GlobalISel/GenericOpcode.rst index e37ec24f02b..331efd242ca 100644 --- a/docs/GlobalISel/GenericOpcode.rst +++ b/docs/GlobalISel/GenericOpcode.rst @@ -301,6 +301,11 @@ G_SHL, G_LSHR, G_ASHR Shift the bits of a scalar left or right inserting zeros (sign-bit for G_ASHR). +G_ROTR, G_ROTL +^^^^^^^^^^^^^^ + +Rotate the bits right (G_ROTR) or left (G_ROTL). + G_ICMP ^^^^^^ diff --git a/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h index 3868211c029..ccc44b46a37 100644 --- a/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h +++ b/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h @@ -1856,6 +1856,18 @@ public: return buildInstr(TargetOpcode::G_UBFX, {Dst}, {Src, LSB, Width}); } + /// Build and insert \p Dst = G_ROTR \p Src, \p Amt + MachineInstrBuilder buildRotateRight(const DstOp &Dst, const SrcOp &Src, + const SrcOp &Amt) { + return buildInstr(TargetOpcode::G_ROTR, {Dst}, {Src, Amt}); + } + + /// Build and insert \p Dst = G_ROTL \p Src, \p Amt + MachineInstrBuilder buildRotateLeft(const DstOp &Dst, const SrcOp &Src, + const SrcOp &Amt) { + return buildInstr(TargetOpcode::G_ROTL, {Dst}, {Src, Amt}); + } + virtual MachineInstrBuilder buildInstr(unsigned Opc, ArrayRef DstOps, ArrayRef SrcOps, Optional Flags = None); diff --git a/include/llvm/Support/TargetOpcodes.def b/include/llvm/Support/TargetOpcodes.def index 4228b67f525..09f182c46b3 100644 --- a/include/llvm/Support/TargetOpcodes.def +++ b/include/llvm/Support/TargetOpcodes.def @@ -432,6 +432,12 @@ HANDLE_TARGET_OPCODE(G_FSHL) // Generic funnel right shift HANDLE_TARGET_OPCODE(G_FSHR) +// Generic right rotate +HANDLE_TARGET_OPCODE(G_ROTR) + +// Generic left rotate +HANDLE_TARGET_OPCODE(G_ROTL) + /// Generic integer-base comparison, also applicable to vectors of integers. HANDLE_TARGET_OPCODE(G_ICMP) diff --git a/include/llvm/Target/GenericOpcodes.td b/include/llvm/Target/GenericOpcodes.td index 72c602d3069..7eb9ffa2a93 100644 --- a/include/llvm/Target/GenericOpcodes.td +++ b/include/llvm/Target/GenericOpcodes.td @@ -362,6 +362,20 @@ def G_FSHR : GenericInstruction { let hasSideEffects = false; } +/// Rotate bits right. +def G_ROTR : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type1:$src2); + let hasSideEffects = false; +} + +/// Rotate bits left. +def G_ROTL : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type1:$src2); + let hasSideEffects = false; +} + // Generic integer comparison. def G_ICMP : GenericInstruction { let OutOperandList = (outs type0:$dst); diff --git a/include/llvm/Target/GlobalISel/SelectionDAGCompat.td b/include/llvm/Target/GlobalISel/SelectionDAGCompat.td index 6fb8a6b15dd..4c947b5c669 100644 --- a/include/llvm/Target/GlobalISel/SelectionDAGCompat.td +++ b/include/llvm/Target/GlobalISel/SelectionDAGCompat.td @@ -141,6 +141,8 @@ def : GINodeEquiv; def : GINodeEquiv; def : GINodeEquiv; def : GINodeEquiv; +def : GINodeEquiv; +def : GINodeEquiv; def : GINodeEquiv; def : GINodeEquiv; diff --git a/lib/CodeGen/MachineVerifier.cpp b/lib/CodeGen/MachineVerifier.cpp index 9966600e1e6..503cd5250e5 100644 --- a/lib/CodeGen/MachineVerifier.cpp +++ b/lib/CodeGen/MachineVerifier.cpp @@ -1578,6 +1578,17 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) { } break; } + case TargetOpcode::G_ROTR: + case TargetOpcode::G_ROTL: { + LLT Src1Ty = MRI->getType(MI->getOperand(1).getReg()); + LLT Src2Ty = MRI->getType(MI->getOperand(2).getReg()); + if (Src1Ty.isVector() != Src2Ty.isVector()) { + report("Rotate requires operands to be either all scalars or all vectors", + MI); + break; + } + break; + } default: break; diff --git a/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir b/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir index eb4efb95fa7..36fd8475746 100644 --- a/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir +++ b/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir @@ -291,6 +291,12 @@ # DEBUG-NEXT: .. opcode {{[0-9]+}} is aliased to {{[0-9]+}} # DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected # DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected +# DEBUG-NEXT: G_ROTR (opcode {{[0-9]+}}): 2 type indices, 0 imm indices +# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined +# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined +# DEBUG-NEXT: G_ROTL (opcode {{[0-9]+}}): 2 type indices, 0 imm indices +# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined +# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined # DEBUG-NEXT: G_ICMP (opcode {{[0-9]+}}): 2 type indices, 0 imm indices # DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected # DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected diff --git a/test/MachineVerifier/test_g_rotr_rotl.mir b/test/MachineVerifier/test_g_rotr_rotl.mir new file mode 100644 index 00000000000..0d545662765 --- /dev/null +++ b/test/MachineVerifier/test_g_rotr_rotl.mir @@ -0,0 +1,13 @@ +# RUN: not --crash llc -march=arm64 -verify-machineinstrs -run-pass none -o /dev/null %s 2>&1 | FileCheck %s +# REQUIRES: aarch64-registered-target +--- +name: test_uniform +body: | + bb.0: + %src:_(<2 x s64>) = G_IMPLICIT_DEF + %amt:_(s64) = G_IMPLICIT_DEF + + ; CHECK: Rotate requires operands to be either all scalars or all vectors + %rotr:_(<2 x s64>) = G_ROTR %src, %amt + +...