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
^^^^^^
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<DstOp> DstOps,
ArrayRef<SrcOp> SrcOps,
Optional<unsigned> Flags = None);
// 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)
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);
def : GINodeEquiv<G_FMINNUM_IEEE, fminnum_ieee>;
def : GINodeEquiv<G_FMAXNUM_IEEE, fmaxnum_ieee>;
def : GINodeEquiv<G_READCYCLECOUNTER, readcyclecounter>;
+def : GINodeEquiv<G_ROTR, rotr>;
+def : GINodeEquiv<G_ROTL, rotl>;
def : GINodeEquiv<G_STRICT_FADD, strict_fadd>;
def : GINodeEquiv<G_STRICT_FSUB, strict_fsub>;
}
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;
# 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
--- /dev/null
+# 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
+
+...