[llvm-commits] [llvm] r84009 - in /llvm/trunk: lib/Target/ARM/ARMISelDAGToDAG.cpp lib/Target/ARM/ARMInstrInfo.td lib/Target/ARM/ARMInstrThumb2.td test/CodeGen/ARM/sbfx.ll
Sandeep Patel
deeppatel1987 at gmail.com
Tue Oct 13 11:59:49 PDT 2009
Author: sandeep
Date: Tue Oct 13 13:59:48 2009
New Revision: 84009
URL: http://llvm.org/viewvc/llvm-project?rev=84009&view=rev
Log:
Add ARMv6T2 SBFX/UBFX instructions. Approved by Anton Korobeynikov.
Added:
llvm/trunk/test/CodeGen/ARM/sbfx.ll
Modified:
llvm/trunk/lib/Target/ARM/ARMISelDAGToDAG.cpp
llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td
Modified: llvm/trunk/lib/Target/ARM/ARMISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelDAGToDAG.cpp?rev=84009&r1=84008&r2=84009&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMISelDAGToDAG.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMISelDAGToDAG.cpp Tue Oct 13 13:59:48 2009
@@ -126,6 +126,9 @@
/// SelectDYN_ALLOC - Select dynamic alloc for Thumb.
SDNode *SelectDYN_ALLOC(SDValue Op);
+ /// SelectV6T2BitfielsOp - Select SBFX/UBFX instructions for ARM.
+ SDNode *SelectV6T2BitfieldExtractOp(SDValue Op, unsigned Opc);
+
/// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
/// inline asm expressions.
virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op,
@@ -138,6 +141,31 @@
};
}
+/// 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() {
DEBUG(BB->dump());
@@ -942,6 +970,32 @@
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 *N = Op.getNode();
DebugLoc dl = N->getDebugLoc();
@@ -1019,6 +1073,16 @@
}
case ARMISD::DYN_ALLOC:
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:
if (Subtarget->isThumb1Only())
break;
Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=84009&r1=84008&r2=84009&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Tue Oct 13 13:59:48 2009
@@ -284,6 +284,10 @@
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.
@@ -1014,6 +1018,24 @@
// 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.
//
Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td?rev=84009&r1=84008&r2=84009&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Tue Oct 13 13:59:48 2009
@@ -767,6 +767,12 @@
IIC_iALUi, "bfc", " $dst, $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)
defm t2ORN : T2I_bin_irs<"orn", BinOpFrag<(or node:$LHS, (not node:$RHS))>>;
Added: llvm/trunk/test/CodeGen/ARM/sbfx.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/sbfx.ll?rev=84009&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/sbfx.ll (added)
+++ llvm/trunk/test/CodeGen/ARM/sbfx.ll Tue Oct 13 13:59:48 2009
@@ -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
+}
More information about the llvm-commits
mailing list