[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:
Aditya Nandakumar 2018-08-04 01:22:12 +00:00
parent 2655b0383c
commit e07b3b737b
8 changed files with 127 additions and 17 deletions

View File

@ -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)

View File

@ -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);

View File

@ -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;
}

View File

@ -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() {

View File

@ -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

View File

@ -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; }

View File

@ -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; }

View File

@ -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; }