llvm.org GIT mirror llvm / 469bbdb
Add basic support to code-gen the ARM/Thumb2 bit-field insert (BFI) instruction and a combine pattern to use it for setting a bit-field to a constant value. More to come for non-constant stores. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@108570 91177308-0d34-0410-b5e6-96231b3b80d8 Jim Grosbach 10 years ago
8 changed file(s) with 138 addition(s) and 36 deletion(s). Raw diff Collapse all Expand all
529529 setTargetDAGCombine(ISD::SUB);
530530 setTargetDAGCombine(ISD::MUL);
531531
532 if (Subtarget->hasV6T2Ops())
533 setTargetDAGCombine(ISD::OR);
534
532535 setStackPointerRegisterToSaveRestore(ARM::SP);
533536
534537 if (UseSoftFloat || Subtarget->isThumb1Only() || !Subtarget->hasVFP2())
42314234 return SDValue();
42324235 }
42334236
4237 /// PerformORCombine - Target-specific dag combine xforms for ISD::OR
4238 static SDValue PerformORCombine(SDNode *N,
4239 TargetLowering::DAGCombinerInfo &DCI,
4240 const ARMSubtarget *Subtarget) {
4241 // BFI is only available on V6T2+
4242 if (Subtarget->isThumb1Only() || !Subtarget->hasV6T2Ops())
4243 return SDValue();
4244
4245 SelectionDAG &DAG = DCI.DAG;
4246 SDValue N0 = N->getOperand(0), N1 = N->getOperand(1);
4247 // or (and A, mask), val => ARMbfi A, val, mask
4248 // iff (val & mask) == val
4249 if (N0->getOpcode() != ISD::AND)
4250 return SDValue();
4251
4252 EVT VT = N->getValueType(0);
4253 if (VT != MVT::i32)
4254 return SDValue();
4255
4256 // The value and the mask need to be constants so we can verify this is
4257 // actually a bitfield set. If the mask is 0xffff, we can do better
4258 // via a movt instruction, so don't use BFI in that case.
4259 ConstantSDNode *C = dyn_cast(N0.getOperand(1));
4260 if (!C)
4261 return SDValue();
4262 unsigned Mask = C->getZExtValue();
4263 if (Mask == 0xffff)
4264 return SDValue();
4265 C = dyn_cast(N1);
4266 if (!C)
4267 return SDValue();
4268 unsigned Val = C->getZExtValue();
4269 if (ARM::isBitFieldInvertedMask(Mask) && (Val & ~Mask) != Val)
4270 return SDValue();
4271 Val >>= CountTrailingZeros_32(~Mask);
4272
4273 DebugLoc DL = N->getDebugLoc();
4274 SDValue Res = DAG.getNode(ARMISD::BFI, DL, VT, N0.getOperand(0),
4275 DAG.getConstant(Val, MVT::i32),
4276 DAG.getConstant(Mask, MVT::i32));
4277
4278 // Do not add new nodes to DAG combiner worklist.
4279 DCI.CombineTo(N, Res, false);
4280
4281 return SDValue();
4282 }
4283
42344284 /// PerformVMOVRRDCombine - Target-specific dag combine xforms for
42354285 /// ARMISD::VMOVRRD.
42364286 static SDValue PerformVMOVRRDCombine(SDNode *N,
46484698 case ISD::ADD: return PerformADDCombine(N, DCI);
46494699 case ISD::SUB: return PerformSUBCombine(N, DCI);
46504700 case ISD::MUL: return PerformMULCombine(N, DCI, Subtarget);
4701 case ISD::OR: return PerformORCombine(N, DCI, Subtarget);
46514702 case ARMISD::VMOVRRD: return PerformVMOVRRDCombine(N, DCI);
46524703 case ARMISD::VDUPLANE: return PerformVDUPLANECombine(N, DCI);
46534704 case ISD::INTRINSIC_WO_CHAIN: return PerformIntrinsicCombine(N, DCI.DAG);
53795430 return ((int)Sign << 7) | (Exp << 4) | Mantissa;
53805431 }
53815432
5433 bool ARM::isBitFieldInvertedMask(unsigned v) {
5434 if (v == 0xffffffff)
5435 return 0;
5436 // there can be 1's on either or both "outsides", all the "inside"
5437 // bits must be 0's
5438 unsigned int lsb = 0, msb = 31;
5439 while (v & (1 << msb)) --msb;
5440 while (v & (1 << lsb)) ++lsb;
5441 for (unsigned int i = lsb; i <= msb; ++i) {
5442 if (v & (1 << i))
5443 return 0;
5444 }
5445 return 1;
5446 }
5447
53825448 /// isFPImmLegal - Returns true if the target can instruction select the
53835449 /// specified FP immediate natively. If false, the legalizer will
53845450 /// materialize the FP immediate as a load from a constant pool.
149149
150150 // Floating-point max and min:
151151 FMAX,
152 FMIN
152 FMIN,
153
154 // Bit-field insert
155 BFI
153156 };
154157 }
155158
161164 /// returns -1.
162165 int getVFPf32Imm(const APFloat &FPImm);
163166 int getVFPf64Imm(const APFloat &FPImm);
167 bool isBitFieldInvertedMask(unsigned v);
164168 }
165169
166170 //===--------------------------------------------------------------------===//
5959 def SDT_ARMSYNCBARRIERV6 : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
6060
6161 def SDT_ARMTCRET : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>;
62
63 def SDT_ARMBFI : SDTypeProfile<1, 3, [SDTCisVT<0, i32>, SDTCisVT<1, i32>,
64 SDTCisVT<2, i32>, SDTCisVT<3, i32>]>;
6265
6366 // Node definitions.
6467 def ARMWrapper : SDNode<"ARMISD::Wrapper", SDTIntUnaryOp>;
129132
130133 def ARMtcret : SDNode<"ARMISD::TC_RETURN", SDT_ARMTCRET,
131134 [SDNPHasChain, SDNPOptInFlag, SDNPVariadic]>;
135
136
137 def ARMbfi : SDNode<"ARMISD::BFI", SDT_ARMBFI>;
132138
133139 //===----------------------------------------------------------------------===//
134140 // ARM Instruction Predicate Definitions.
220226 /// e.g., 0xf000ffff
221227 def bf_inv_mask_imm : Operand,
222228 PatLeaf<(imm), [{
223 uint32_t v = (uint32_t)N->getZExtValue();
224 if (v == 0xffffffff)
225 return 0;
226 // there can be 1's on either or both "outsides", all the "inside"
227 // bits must be 0's
228 unsigned int lsb = 0, msb = 31;
229 while (v & (1 << msb)) --msb;
230 while (v & (1 << lsb)) ++lsb;
231 for (unsigned int i = lsb; i <= msb; ++i) {
232 if (v & (1 << i))
233 return 0;
234 }
235 return 1;
229 return ARM::isBitFieldInvertedMask(N->getZExtValue());
236230 }] > {
237231 let PrintMethod = "printBitfieldInvMaskImmOperand";
238232 }
18571851 }
18581852
18591853 // A8.6.18 BFI - Bitfield insert (Encoding A1)
1860 // Added for disassembler with the pattern field purposely left blank.
1861 def BFI : I<(outs GPR:$dst), (ins GPR:$src, bf_inv_mask_imm:$imm),
1854 def BFI : I<(outs GPR:$dst), (ins GPR:$src, GPR:$val, bf_inv_mask_imm:$imm),
18621855 AddrMode1, Size4Bytes, IndexModeNone, DPFrm, IIC_iUNAsi,
1863 "bfi", "\t$dst, $src, $imm", "",
1864 [/* For disassembly only; pattern left blank */]>,
1856 "bfi", "\t$dst, $val, $imm", "$src = $dst",
1857 [(set GPR:$dst, (ARMbfi GPR:$src, GPR:$val,
1858 bf_inv_mask_imm:$imm))]>,
18651859 Requires<[IsARM, HasV6T2]> {
18661860 let Inst{27-21} = 0b0111110;
18671861 let Inst{6-4} = 0b001; // Rn: Inst{3-0} != 15
16651665 }
16661666
16671667 // A8.6.18 BFI - Bitfield insert (Encoding T1)
1668 // Added for disassembler with the pattern field purposely left blank.
1669 // FIXME: Utilize this instruction in codgen.
1670 def t2BFI : T2I<(outs GPR:$dst), (ins GPR:$src, imm0_31:$lsb, imm0_31:$width),
1671 IIC_iALUi, "bfi", "\t$dst, $src, $lsb, $width", []> {
1668 let Constraints = "$src = $dst" in
1669 def t2BFI : T2I<(outs GPR:$dst),
1670 (ins GPR:$src, GPR:$val, bf_inv_mask_imm:$imm),
1671 IIC_iALUi, "bfi", "\t$dst, $val, $imm",
1672 [(set GPR:$dst, (ARMbfi GPR:$src, GPR:$val,
1673 bf_inv_mask_imm:$imm))]> {
16721674 let Inst{31-27} = 0b11110;
16731675 let Inst{25} = 1;
16741676 let Inst{24-20} = 0b10110;
988988
989989 // Special-case handling of BFC/BFI/SBFX/UBFX.
990990 if (Opcode == ARM::BFC || Opcode == ARM::BFI) {
991 // TIED_TO operand skipped for BFC and Inst{3-0} (Reg) for BFI.
992 MI.addOperand(MCOperand::CreateReg(Opcode == ARM::BFC ? 0
993 : getRegisterEnum(B, ARM::GPRRegClassID,
991 MI.addOperand(MCOperand::CreateReg(0));
992 if (Opcode == ARM::BFI) {
993 MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
994994 decodeRm(insn))));
995 ++OpIdx;
996 }
995997 uint32_t mask = 0;
996998 if (!getBFCInvMask(insn, mask))
997999 return false;
15541554 ++OpIdx;
15551555 }
15561556
1557 if (Opcode == ARM::t2BFI) {
1558 // Add val reg operand.
1559 MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
1560 decodeRn(insn))));
1561 ++OpIdx;
1562 }
1563
15571564 assert(OpInfo[OpIdx].RegClass < 0 && !OpInfo[OpIdx].isPredicate()
15581565 && !OpInfo[OpIdx].isOptionalDef()
15591566 && "Pure imm operand expected");
15661573 MI.addOperand(MCOperand::CreateImm(getIImm3Imm8(insn)));
15671574 else if (Opcode == ARM::t2MOVi16 || Opcode == ARM::t2MOVTi16)
15681575 MI.addOperand(MCOperand::CreateImm(getImm16(insn)));
1569 else if (Opcode == ARM::t2BFC) {
1576 else if (Opcode == ARM::t2BFC || Opcode == ARM::t2BFI) {
15701577 uint32_t mask = 0;
15711578 if (getBitfieldInvMask(insn, mask))
15721579 MI.addOperand(MCOperand::CreateImm(mask));
15741581 return false;
15751582 } else {
15761583 // Handle the case of: lsb width
1577 assert((Opcode == ARM::t2SBFX || Opcode == ARM::t2UBFX ||
1578 Opcode == ARM::t2BFI) && "Unexpected opcode");
1584 assert((Opcode == ARM::t2SBFX || Opcode == ARM::t2UBFX)
1585 && "Unexpected opcode");
15791586 MI.addOperand(MCOperand::CreateImm(getLsb(insn)));
1580 if (Opcode == ARM::t2BFI) {
1581 if (getMsb(insn) < getLsb(insn)) {
1582 DEBUG(errs() << "Encoding error: msb < lsb\n");
1583 return false;
1584 }
1585 MI.addOperand(MCOperand::CreateImm(getMsb(insn) - getLsb(insn) + 1));
1586 } else
1587 MI.addOperand(MCOperand::CreateImm(getWidthMinus1(insn) + 1));
1587 MI.addOperand(MCOperand::CreateImm(getWidthMinus1(insn) + 1));
15881588
15891589 ++OpIdx;
15901590 }
0 ; RUN: llc -march=arm -mattr=+v6t2 < %s | FileCheck %s
1
2 %struct.F = type { [3 x i8], i8 }
3
4 @X = common global %struct.F zeroinitializer, align 4 ; <%struct.F*> [#uses=1]
5
6 define void @f1([1 x i32] %f.coerce0) nounwind {
7 entry:
8 ; CHECK: f1
9 ; CHECK: mov r2, #10
10 ; CHECK: bfi r1, r2, #22, #4
11 %0 = load i32* bitcast (%struct.F* @X to i32*), align 4 ; [#uses=1]
12 %1 = and i32 %0, -62914561 ; [#uses=1]
13 %2 = or i32 %1, 41943040 ; [#uses=1]
14 store i32 %2, i32* bitcast (%struct.F* @X to i32*), align 4
15 ret void
16 }
0 ; RUN: llc -march=thumb -mattr=+v6t2 < %s | FileCheck %s
1
2 %struct.F = type { [3 x i8], i8 }
3
4 @X = common global %struct.F zeroinitializer, align 4 ; <%struct.F*> [#uses=1]
5
6 define void @f1([1 x i32] %f.coerce0) nounwind {
7 entry:
8 ; CHECK: f1
9 ; CHECK: movs r2, #10
10 ; CHECK: bfi r1, r2, #22, #4
11 %0 = load i32* bitcast (%struct.F* @X to i32*), align 4 ; [#uses=1]
12 %1 = and i32 %0, -62914561 ; [#uses=1]
13 %2 = or i32 %1, 41943040 ; [#uses=1]
14 store i32 %2, i32* bitcast (%struct.F* @X to i32*), align 4
15 ret void
16 }