mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 11:42:57 +01:00
Add ARMv6T2 SBFX/UBFX instructions. Approved by Anton Korobeynikov.
llvm-svn: 84009
This commit is contained in:
parent
1f746d5df3
commit
1584038783
@ -126,6 +126,9 @@ private:
|
|||||||
/// SelectDYN_ALLOC - Select dynamic alloc for Thumb.
|
/// SelectDYN_ALLOC - Select dynamic alloc for Thumb.
|
||||||
SDNode *SelectDYN_ALLOC(SDValue Op);
|
SDNode *SelectDYN_ALLOC(SDValue Op);
|
||||||
|
|
||||||
|
/// SelectV6T2BitfielsOp - Select SBFX/UBFX instructions for ARM.
|
||||||
|
SDNode *SelectV6T2BitfieldExtractOp(SDValue Op, unsigned Opc);
|
||||||
|
|
||||||
/// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
|
/// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
|
||||||
/// inline asm expressions.
|
/// inline asm expressions.
|
||||||
virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op,
|
virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op,
|
||||||
@ -138,6 +141,31 @@ private:
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// isInt32Immediate - This method tests to see if the node is a 32-bit constant
|
||||||
|
/// operand. If so Imm will receive the 32-bit value.
|
||||||
|
static bool isInt32Immediate(SDNode *N, unsigned &Imm) {
|
||||||
|
if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i32) {
|
||||||
|
Imm = cast<ConstantSDNode>(N)->getZExtValue();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// isInt32Immediate - This method tests to see if a constant operand.
|
||||||
|
// If so Imm will receive the 32 bit value.
|
||||||
|
static bool isInt32Immediate(SDValue N, unsigned &Imm) {
|
||||||
|
return isInt32Immediate(N.getNode(), Imm);
|
||||||
|
}
|
||||||
|
|
||||||
|
// isOpcWithIntImmediate - This method tests to see if the node is a specific
|
||||||
|
// opcode and that it has a immediate integer right operand.
|
||||||
|
// If so Imm will receive the 32 bit value.
|
||||||
|
static bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) {
|
||||||
|
return N->getOpcode() == Opc &&
|
||||||
|
isInt32Immediate(N->getOperand(1).getNode(), Imm);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void ARMDAGToDAGISel::InstructionSelect() {
|
void ARMDAGToDAGISel::InstructionSelect() {
|
||||||
DEBUG(BB->dump());
|
DEBUG(BB->dump());
|
||||||
|
|
||||||
@ -942,6 +970,32 @@ SDNode *ARMDAGToDAGISel::PairDRegs(EVT VT, SDValue V0, SDValue V1) {
|
|||||||
VT, SDValue(Pair, 0), V1, SubReg1);
|
VT, SDValue(Pair, 0), V1, SubReg1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDNode *ARMDAGToDAGISel::SelectV6T2BitfieldExtractOp(SDValue Op,
|
||||||
|
unsigned Opc) {
|
||||||
|
if (!Subtarget->hasV6T2Ops())
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
unsigned Shl_imm = 0;
|
||||||
|
if (isOpcWithIntImmediate(Op.getOperand(0).getNode(), ISD::SHL, Shl_imm)){
|
||||||
|
assert(Shl_imm > 0 && Shl_imm < 32 && "bad amount in shift node!");
|
||||||
|
unsigned Srl_imm = 0;
|
||||||
|
if (isInt32Immediate(Op.getOperand(1), Srl_imm)) {
|
||||||
|
assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!");
|
||||||
|
unsigned Width = 32 - Srl_imm;
|
||||||
|
int LSB = Srl_imm - Shl_imm;
|
||||||
|
if ((LSB + Width) > 32)
|
||||||
|
return NULL;
|
||||||
|
SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
|
||||||
|
SDValue Ops[] = { Op.getOperand(0).getOperand(0),
|
||||||
|
CurDAG->getTargetConstant(LSB, MVT::i32),
|
||||||
|
CurDAG->getTargetConstant(Width, MVT::i32),
|
||||||
|
getAL(CurDAG), Reg0 };
|
||||||
|
return CurDAG->SelectNodeTo(Op.getNode(), Opc, MVT::i32, Ops, 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
SDNode *ARMDAGToDAGISel::Select(SDValue Op) {
|
SDNode *ARMDAGToDAGISel::Select(SDValue Op) {
|
||||||
SDNode *N = Op.getNode();
|
SDNode *N = Op.getNode();
|
||||||
DebugLoc dl = N->getDebugLoc();
|
DebugLoc dl = N->getDebugLoc();
|
||||||
@ -1019,6 +1073,16 @@ SDNode *ARMDAGToDAGISel::Select(SDValue Op) {
|
|||||||
}
|
}
|
||||||
case ARMISD::DYN_ALLOC:
|
case ARMISD::DYN_ALLOC:
|
||||||
return SelectDYN_ALLOC(Op);
|
return SelectDYN_ALLOC(Op);
|
||||||
|
case ISD::SRL:
|
||||||
|
if (SDNode *I = SelectV6T2BitfieldExtractOp(Op,
|
||||||
|
Subtarget->isThumb() ? ARM::t2UBFX : ARM::UBFX))
|
||||||
|
return I;
|
||||||
|
break;
|
||||||
|
case ISD::SRA:
|
||||||
|
if (SDNode *I = SelectV6T2BitfieldExtractOp(Op,
|
||||||
|
Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX))
|
||||||
|
return I;
|
||||||
|
break;
|
||||||
case ISD::MUL:
|
case ISD::MUL:
|
||||||
if (Subtarget->isThumb1Only())
|
if (Subtarget->isThumb1Only())
|
||||||
break;
|
break;
|
||||||
|
@ -284,6 +284,10 @@ def so_imm2part_2 : SDNodeXForm<imm, [{
|
|||||||
return CurDAG->getTargetConstant(V, MVT::i32);
|
return CurDAG->getTargetConstant(V, MVT::i32);
|
||||||
}]>;
|
}]>;
|
||||||
|
|
||||||
|
/// imm0_31 predicate - True if the 32-bit immediate is in the range [0,31].
|
||||||
|
def imm0_31 : Operand<i32>, PatLeaf<(imm), [{
|
||||||
|
return (int32_t)N->getZExtValue() < 32;
|
||||||
|
}]>;
|
||||||
|
|
||||||
// Define ARM specific addressing modes.
|
// Define ARM specific addressing modes.
|
||||||
|
|
||||||
@ -1014,6 +1018,24 @@ defm UXTAH : AI_bin_rrot<0b01101111, "uxtah",
|
|||||||
|
|
||||||
// TODO: UXT(A){B|H}16
|
// TODO: UXT(A){B|H}16
|
||||||
|
|
||||||
|
def SBFX : I<(outs GPR:$dst),
|
||||||
|
(ins GPR:$src, imm0_31:$lsb, imm0_31:$width),
|
||||||
|
AddrMode1, Size4Bytes, IndexModeNone, DPFrm, IIC_iALUi,
|
||||||
|
"sbfx", " $dst, $src, $lsb, $width", "", []>,
|
||||||
|
Requires<[IsARM, HasV6T2]> {
|
||||||
|
let Inst{27-21} = 0b0111101;
|
||||||
|
let Inst{6-4} = 0b101;
|
||||||
|
}
|
||||||
|
|
||||||
|
def UBFX : I<(outs GPR:$dst),
|
||||||
|
(ins GPR:$src, imm0_31:$lsb, imm0_31:$width),
|
||||||
|
AddrMode1, Size4Bytes, IndexModeNone, DPFrm, IIC_iALUi,
|
||||||
|
"ubfx", " $dst, $src, $lsb, $width", "", []>,
|
||||||
|
Requires<[IsARM, HasV6T2]> {
|
||||||
|
let Inst{27-21} = 0b0111111;
|
||||||
|
let Inst{6-4} = 0b101;
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Arithmetic Instructions.
|
// Arithmetic Instructions.
|
||||||
//
|
//
|
||||||
|
@ -767,6 +767,12 @@ def t2BFC : T2I<(outs GPR:$dst), (ins GPR:$src, bf_inv_mask_imm:$imm),
|
|||||||
IIC_iALUi, "bfc", " $dst, $imm",
|
IIC_iALUi, "bfc", " $dst, $imm",
|
||||||
[(set GPR:$dst, (and GPR:$src, bf_inv_mask_imm:$imm))]>;
|
[(set GPR:$dst, (and GPR:$src, bf_inv_mask_imm:$imm))]>;
|
||||||
|
|
||||||
|
def t2SBFX : T2I<(outs GPR:$dst), (ins GPR:$src, imm0_31:$lsb, imm0_31:$width),
|
||||||
|
IIC_iALUi, "sbfx", " $dst, $src, $lsb, $width", []>;
|
||||||
|
|
||||||
|
def t2UBFX : T2I<(outs GPR:$dst), (ins GPR:$src, imm0_31:$lsb, imm0_31:$width),
|
||||||
|
IIC_iALUi, "ubfx", " $dst, $src, $lsb, $width", []>;
|
||||||
|
|
||||||
// FIXME: A8.6.18 BFI - Bitfield insert (Encoding T1)
|
// FIXME: A8.6.18 BFI - Bitfield insert (Encoding T1)
|
||||||
|
|
||||||
defm t2ORN : T2I_bin_irs<"orn", BinOpFrag<(or node:$LHS, (not node:$RHS))>>;
|
defm t2ORN : T2I_bin_irs<"orn", BinOpFrag<(or node:$LHS, (not node:$RHS))>>;
|
||||||
|
37
test/CodeGen/ARM/sbfx.ll
Normal file
37
test/CodeGen/ARM/sbfx.ll
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
; RUN: llc < %s -march=arm -mattr=+v6t2 | FileCheck %s
|
||||||
|
|
||||||
|
define i32 @f1(i32 %a) {
|
||||||
|
entry:
|
||||||
|
; CHECK: f1:
|
||||||
|
; CHECK: sbfx r0, r0, #0, #20
|
||||||
|
%tmp = shl i32 %a, 12
|
||||||
|
%tmp2 = ashr i32 %tmp, 12
|
||||||
|
ret i32 %tmp2
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @f2(i32 %a) {
|
||||||
|
entry:
|
||||||
|
; CHECK: f2:
|
||||||
|
; CHECK: ubfx r0, r0, #0, #20
|
||||||
|
%tmp = shl i32 %a, 12
|
||||||
|
%tmp2 = lshr i32 %tmp, 12
|
||||||
|
ret i32 %tmp2
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @f3(i32 %a) {
|
||||||
|
entry:
|
||||||
|
; CHECK: f3:
|
||||||
|
; CHECK: sbfx r0, r0, #5, #3
|
||||||
|
%tmp = shl i32 %a, 24
|
||||||
|
%tmp2 = ashr i32 %tmp, 29
|
||||||
|
ret i32 %tmp2
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @f4(i32 %a) {
|
||||||
|
entry:
|
||||||
|
; CHECK: f4:
|
||||||
|
; CHECK: ubfx r0, r0, #5, #3
|
||||||
|
%tmp = shl i32 %a, 24
|
||||||
|
%tmp2 = lshr i32 %tmp, 29
|
||||||
|
ret i32 %tmp2
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user