mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 10:42:39 +01:00
[GISel]: Add Opcodes for CTLZ/CTTZ/CTPOP
https://reviews.llvm.org/D48600 Added IRTranslator support to translate these known intrinsics into GISel opcodes. llvm-svn: 338944
This commit is contained in:
parent
9838cc2887
commit
6188b99859
@ -464,6 +464,21 @@ HANDLE_TARGET_OPCODE(G_EXTRACT_VECTOR_ELT)
|
||||
/// Generic shufflevector.
|
||||
HANDLE_TARGET_OPCODE(G_SHUFFLE_VECTOR)
|
||||
|
||||
/// Generic count trailing zeroes.
|
||||
HANDLE_TARGET_OPCODE(G_CTTZ)
|
||||
|
||||
/// Same as above, undefined for zero inputs.
|
||||
HANDLE_TARGET_OPCODE(G_CTTZ_ZERO_UNDEF)
|
||||
|
||||
/// Generic count leading zeroes.
|
||||
HANDLE_TARGET_OPCODE(G_CTLZ)
|
||||
|
||||
/// Same as above, undefined for zero inputs.
|
||||
HANDLE_TARGET_OPCODE(G_CTLZ_ZERO_UNDEF)
|
||||
|
||||
/// Generic count bits.
|
||||
HANDLE_TARGET_OPCODE(G_CTPOP)
|
||||
|
||||
/// Generic byte swap.
|
||||
HANDLE_TARGET_OPCODE(G_BSWAP)
|
||||
|
||||
|
@ -120,6 +120,36 @@ def G_VAARG : GenericInstruction {
|
||||
let mayStore = 1;
|
||||
}
|
||||
|
||||
def G_CTLZ : GenericInstruction {
|
||||
let OutOperandList = (outs type0:$dst);
|
||||
let InOperandList = (ins type0:$src);
|
||||
let hasSideEffects = 0;
|
||||
}
|
||||
|
||||
def G_CTLZ_ZERO_UNDEF : GenericInstruction {
|
||||
let OutOperandList = (outs type0:$dst);
|
||||
let InOperandList = (ins type0:$src);
|
||||
let hasSideEffects = 0;
|
||||
}
|
||||
|
||||
def G_CTTZ : GenericInstruction {
|
||||
let OutOperandList = (outs type0:$dst);
|
||||
let InOperandList = (ins type0:$src);
|
||||
let hasSideEffects = 0;
|
||||
}
|
||||
|
||||
def G_CTTZ_ZERO_UNDEF : GenericInstruction {
|
||||
let OutOperandList = (outs type0:$dst);
|
||||
let InOperandList = (ins type0:$src);
|
||||
let hasSideEffects = 0;
|
||||
}
|
||||
|
||||
def G_CTPOP : GenericInstruction {
|
||||
let OutOperandList = (outs type0:$dst);
|
||||
let InOperandList = (ins type0:$src);
|
||||
let hasSideEffects = 0;
|
||||
}
|
||||
|
||||
def G_BSWAP : GenericInstruction {
|
||||
let OutOperandList = (outs type0:$dst);
|
||||
let InOperandList = (ins type0:$src);
|
||||
|
@ -913,6 +913,26 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
|
||||
PtrTy.getSizeInBits() / 8, 8));
|
||||
return true;
|
||||
}
|
||||
case Intrinsic::cttz:
|
||||
case Intrinsic::ctlz: {
|
||||
ConstantInt *Cst = cast<ConstantInt>(CI.getArgOperand(1));
|
||||
bool isTrailing = ID == Intrinsic::cttz;
|
||||
unsigned Opcode = isTrailing
|
||||
? Cst->isZero() ? TargetOpcode::G_CTTZ
|
||||
: TargetOpcode::G_CTTZ_ZERO_UNDEF
|
||||
: Cst->isZero() ? TargetOpcode::G_CTLZ
|
||||
: TargetOpcode::G_CTLZ_ZERO_UNDEF;
|
||||
MIRBuilder.buildInstr(Opcode)
|
||||
.addDef(getOrCreateVReg(CI))
|
||||
.addUse(getOrCreateVReg(*CI.getArgOperand(0)));
|
||||
return true;
|
||||
}
|
||||
case Intrinsic::ctpop: {
|
||||
MIRBuilder.buildInstr(TargetOpcode::G_CTPOP)
|
||||
.addDef(getOrCreateVReg(CI))
|
||||
.addUse(getOrCreateVReg(*CI.getArgOperand(0)));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -1408,6 +1408,36 @@ define float @test_fabs_intrin(float %a) {
|
||||
ret float %res
|
||||
}
|
||||
|
||||
declare i32 @llvm.ctlz.i32(i32, i1)
|
||||
define i32 @test_ctlz_intrinsic_zero_not_undef(i32 %a) {
|
||||
; CHECK-LABEL: name: test_ctlz_intrinsic_zero_not_undef
|
||||
; CHECK: [[A:%[0-9]+]]:_(s32) = COPY $w0
|
||||
; CHECK: [[RES:%[0-9]+]]:_(s32) = G_CTLZ [[A]]
|
||||
; CHECK: $w0 = COPY [[RES]]
|
||||
%res = call i32 @llvm.ctlz.i32(i32 %a, i1 0)
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
declare i32 @llvm.cttz.i32(i32, i1)
|
||||
define i32 @test_cttz_intrinsic_zero_undef(i32 %a) {
|
||||
; CHECK-LABEL: name: test_cttz_intrinsic_zero_undef
|
||||
; CHECK: [[A:%[0-9]+]]:_(s32) = COPY $w0
|
||||
; CHECK: [[RES:%[0-9]+]]:_(s32) = G_CTTZ_ZERO_UNDEF [[A]]
|
||||
; CHECK: $w0 = COPY [[RES]]
|
||||
%res = call i32 @llvm.cttz.i32(i32 %a, i1 1)
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
declare i32 @llvm.ctpop.i32(i32)
|
||||
define i32 @test_ctpop_intrinsic(i32 %a) {
|
||||
; CHECK-LABEL: name: test_ctpop
|
||||
; CHECK: [[A:%[0-9]+]]:_(s32) = COPY $w0
|
||||
; CHECK: [[RES:%[0-9]+]]:_(s32) = G_CTPOP [[A]]
|
||||
; CHECK: $w0 = COPY [[RES]]
|
||||
%res = call i32 @llvm.ctpop.i32(i32 %a)
|
||||
ret i32 %res
|
||||
}
|
||||
|
||||
declare void @llvm.lifetime.start.p0i8(i64, i8*)
|
||||
declare void @llvm.lifetime.end.p0i8(i64, i8*)
|
||||
define void @test_lifetime_intrin() {
|
||||
|
@ -282,6 +282,21 @@
|
||||
# DEBUG-NEXT: G_SHUFFLE_VECTOR (opcode {{[0-9]+}}): 3 type indices
|
||||
# DEBUG: .. type index coverage check SKIPPED: no rules defined
|
||||
#
|
||||
# DEBUG-NEXT: G_CTTZ (opcode {{[0-9]+}}): 1 type index
|
||||
# DEBUG: .. type index coverage check SKIPPED: no rules defined
|
||||
#
|
||||
# DEBUG-NEXT: G_CTTZ_ZERO_UNDEF (opcode {{[0-9]+}}): 1 type index
|
||||
# DEBUG: .. type index coverage check SKIPPED: no rules defined
|
||||
#
|
||||
# DEBUG-NEXT: G_CTLZ (opcode {{[0-9]+}}): 1 type index
|
||||
# DEBUG: .. type index coverage check SKIPPED: no rules defined
|
||||
#
|
||||
# DEBUG-NEXT: G_CTLZ_ZERO_UNDEF (opcode {{[0-9]+}}): 1 type index
|
||||
# DEBUG: .. type index coverage check SKIPPED: no rules defined
|
||||
#
|
||||
# DEBUG-NEXT: G_CTPOP (opcode {{[0-9]+}}): 1 type index
|
||||
# DEBUG: .. type index coverage check SKIPPED: no rules defined
|
||||
#
|
||||
# DEBUG-NEXT: G_BSWAP (opcode {{[0-9]+}}): 1 type index
|
||||
# DEBUG: .. the first uncovered type index: 1, OK
|
||||
|
||||
|
@ -34,10 +34,10 @@ def InstB : TestInstruction {
|
||||
}
|
||||
|
||||
// CHECK: /* 0 */ MCD::OPC_ExtractField, 4, 4, // Inst{7-4} ...
|
||||
// CHECK-NEXT: /* 3 */ MCD::OPC_FilterValue, 0, 16, 0, 0, // Skip to: 24
|
||||
// CHECK-NEXT: /* 8 */ MCD::OPC_CheckField, 2, 2, 0, 6, 0, 0, // Skip to: 21
|
||||
// CHECK-NEXT: /* 15 */ MCD::OPC_TryDecode, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, skip to: 21
|
||||
// CHECK-NEXT: /* 21 */ MCD::OPC_Decode, {{[0-9]+}}, 1, // Opcode: InstA
|
||||
// CHECK-NEXT: /* 24 */ MCD::OPC_Fail,
|
||||
// CHECK-NEXT: /* 3 */ MCD::OPC_FilterValue, 0, 18, 0, 0, // Skip to: 26
|
||||
// CHECK-NEXT: /* 8 */ MCD::OPC_CheckField, 2, 2, 0, 7, 0, 0, // Skip to: 22
|
||||
// CHECK-NEXT: /* 15 */ MCD::OPC_TryDecode, {{[0-9]+}}, 1, 0, 0, 0, 0, // Opcode: InstB, skip to: 22
|
||||
// CHECK-NEXT: /* 22 */ MCD::OPC_Decode, {{[0-9]+}}, 1, 1, // Opcode: InstA
|
||||
// CHECK-NEXT: /* 26 */ MCD::OPC_Fail,
|
||||
|
||||
// CHECK: if (DecodeInstB(MI, insn, Address, Decoder) == MCDisassembler::Fail) { DecodeComplete = false; return MCDisassembler::Fail; }
|
||||
|
@ -31,14 +31,14 @@ def InstB : TestInstruction {
|
||||
}
|
||||
|
||||
// CHECK: /* 0 */ MCD::OPC_ExtractField, 2, 1, // Inst{2} ...
|
||||
// CHECK-NEXT: /* 3 */ MCD::OPC_FilterValue, 0, 34, 0, 0, // Skip to: 42
|
||||
// CHECK-NEXT: /* 3 */ MCD::OPC_FilterValue, 0, 36, 0, 0, // Skip to: 44
|
||||
// CHECK-NEXT: /* 8 */ MCD::OPC_ExtractField, 5, 3, // Inst{7-5} ...
|
||||
// CHECK-NEXT: /* 11 */ MCD::OPC_FilterValue, 0, 26, 0, 0, // Skip to: 42
|
||||
// CHECK-NEXT: /* 16 */ MCD::OPC_CheckField, 0, 2, 3, 6, 0, 0, // Skip to: 29
|
||||
// CHECK-NEXT: /* 23 */ MCD::OPC_TryDecode, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, skip to: 29
|
||||
// CHECK-NEXT: /* 29 */ MCD::OPC_CheckField, 3, 2, 0, 6, 0, 0, // Skip to: 42
|
||||
// CHECK-NEXT: /* 36 */ MCD::OPC_TryDecode, {{[0-9]+}}, 1, 0, 0, 0, // Opcode: InstA, skip to: 42
|
||||
// CHECK-NEXT: /* 42 */ MCD::OPC_Fail,
|
||||
// CHECK-NEXT: /* 11 */ MCD::OPC_FilterValue, 0, 28, 0, 0, // Skip to: 44
|
||||
// CHECK-NEXT: /* 16 */ MCD::OPC_CheckField, 0, 2, 3, 7, 0, 0, // Skip to: 30
|
||||
// CHECK-NEXT: /* 23 */ MCD::OPC_TryDecode, {{[0-9]+}}, 1, 0, 0, 0, 0, // Opcode: InstB, skip to: 30
|
||||
// CHECK-NEXT: /* 30 */ MCD::OPC_CheckField, 3, 2, 0, 7, 0, 0, // Skip to: 44
|
||||
// CHECK-NEXT: /* 37 */ MCD::OPC_TryDecode, {{[0-9]+}}, 1, 1, 0, 0, 0, // Opcode: InstA, skip to: 44
|
||||
// CHECK-NEXT: /* 44 */ MCD::OPC_Fail,
|
||||
|
||||
// CHECK: if (DecodeInstB(MI, insn, Address, Decoder) == MCDisassembler::Fail) { DecodeComplete = false; return MCDisassembler::Fail; }
|
||||
// CHECK: if (DecodeInstA(MI, insn, Address, Decoder) == MCDisassembler::Fail) { DecodeComplete = false; return MCDisassembler::Fail; }
|
||||
|
@ -35,10 +35,10 @@ def InstB : TestInstruction {
|
||||
}
|
||||
|
||||
// CHECK: /* 0 */ MCD::OPC_ExtractField, 4, 4, // Inst{7-4} ...
|
||||
// CHECK-NEXT: /* 3 */ MCD::OPC_FilterValue, 0, 16, 0, 0, // Skip to: 24
|
||||
// CHECK-NEXT: /* 8 */ MCD::OPC_CheckField, 2, 2, 0, 6, 0, 0, // Skip to: 21
|
||||
// CHECK-NEXT: /* 15 */ MCD::OPC_TryDecode, {{[0-9]+}}, 0, 0, 0, 0, // Opcode: InstB, skip to: 21
|
||||
// CHECK-NEXT: /* 21 */ MCD::OPC_Decode, {{[0-9]+}}, 1, // Opcode: InstA
|
||||
// CHECK-NEXT: /* 24 */ MCD::OPC_Fail,
|
||||
// CHECK-NEXT: /* 3 */ MCD::OPC_FilterValue, 0, 18, 0, 0, // Skip to: 26
|
||||
// CHECK-NEXT: /* 8 */ MCD::OPC_CheckField, 2, 2, 0, 7, 0, 0, // Skip to: 22
|
||||
// CHECK-NEXT: /* 15 */ MCD::OPC_TryDecode, {{[0-9]+}}, 1, 0, 0, 0, 0, // Opcode: InstB, skip to: 22
|
||||
// CHECK-NEXT: /* 22 */ MCD::OPC_Decode, {{[0-9]+}}, 1, 1, // Opcode: InstA
|
||||
// CHECK-NEXT: /* 26 */ MCD::OPC_Fail,
|
||||
|
||||
// CHECK: if (DecodeInstBOp(MI, tmp, Address, Decoder) == MCDisassembler::Fail) { DecodeComplete = false; return MCDisassembler::Fail; }
|
||||
|
Loading…
Reference in New Issue
Block a user