mirror of
https://github.com/RPCS3/llvm.git
synced 2024-11-25 12:49:50 +00:00
Use movt/movw pair to materialize 32 bit constants on ARMv6T2+.
This should be better than single load from constpool. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@82948 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
1edaef62a4
commit
6a2fa325c1
@ -934,19 +934,21 @@ SDNode *ARMDAGToDAGISel::Select(SDValue Op) {
|
||||
case ISD::Constant: {
|
||||
unsigned Val = cast<ConstantSDNode>(N)->getZExtValue();
|
||||
bool UseCP = true;
|
||||
if (Subtarget->isThumb()) {
|
||||
if (Subtarget->hasThumb2())
|
||||
// Thumb2 has the MOVT instruction, so all immediates can
|
||||
// be done with MOV + MOVT, at worst.
|
||||
UseCP = 0;
|
||||
else
|
||||
if (Subtarget->hasThumb2())
|
||||
// Thumb2-aware targets have the MOVT instruction, so all immediates can
|
||||
// be done with MOV + MOVT, at worst.
|
||||
UseCP = 0;
|
||||
else {
|
||||
if (Subtarget->isThumb()) {
|
||||
UseCP = (Val > 255 && // MOV
|
||||
~Val > 255 && // MOV + MVN
|
||||
!ARM_AM::isThumbImmShiftedVal(Val)); // MOV + LSL
|
||||
} else
|
||||
UseCP = (ARM_AM::getSOImmVal(Val) == -1 && // MOV
|
||||
ARM_AM::getSOImmVal(~Val) == -1 && // MVN
|
||||
!ARM_AM::isSOImmTwoPartVal(Val)); // two instrs.
|
||||
} else
|
||||
UseCP = (ARM_AM::getSOImmVal(Val) == -1 && // MOV
|
||||
ARM_AM::getSOImmVal(~Val) == -1 && // MVN
|
||||
!ARM_AM::isSOImmTwoPartVal(Val)); // two instrs.
|
||||
}
|
||||
|
||||
if (UseCP) {
|
||||
SDValue CPIdx =
|
||||
CurDAG->getTargetConstantPool(ConstantInt::get(
|
||||
|
@ -96,6 +96,9 @@ reMaterialize(MachineBasicBlock &MBB,
|
||||
|
||||
MachineInstr *MI = MBB.getParent()->CloneMachineInstr(Orig);
|
||||
MI->getOperand(0).setReg(DestReg);
|
||||
if (Orig->getOpcode() == ARM::MOVTi16)
|
||||
MI->getOperand(1).setReg(DestReg);
|
||||
|
||||
MBB.insert(I, MI);
|
||||
}
|
||||
|
||||
|
@ -190,6 +190,27 @@ def bf_inv_mask_imm : Operand<i32>,
|
||||
let PrintMethod = "printBitfieldInvMaskImmOperand";
|
||||
}
|
||||
|
||||
/// Split a 32-bit immediate into two 16 bit parts.
|
||||
def lo16 : SDNodeXForm<imm, [{
|
||||
return CurDAG->getTargetConstant((uint32_t)N->getZExtValue() & 0xffff,
|
||||
MVT::i32);
|
||||
}]>;
|
||||
|
||||
def hi16 : SDNodeXForm<imm, [{
|
||||
return CurDAG->getTargetConstant((uint32_t)N->getZExtValue() >> 16, MVT::i32);
|
||||
}]>;
|
||||
|
||||
def lo16AllZero : PatLeaf<(i32 imm), [{
|
||||
// Returns true if all low 16-bits are 0.
|
||||
return (((uint32_t)N->getZExtValue()) & 0xFFFFUL) == 0;
|
||||
}], hi16>;
|
||||
|
||||
/// imm0_65535 predicate - True if the 32-bit immediate is in the range
|
||||
/// [0.65535].
|
||||
def imm0_65535 : PatLeaf<(i32 imm), [{
|
||||
return (uint32_t)N->getZExtValue() < 65536;
|
||||
}]>;
|
||||
|
||||
class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
|
||||
class UnOpFrag <dag res> : PatFrag<(ops node:$Src), res>;
|
||||
|
||||
@ -897,15 +918,36 @@ def STM : AXI4st<(outs),
|
||||
|
||||
let neverHasSideEffects = 1 in
|
||||
def MOVr : AsI1<0b1101, (outs GPR:$dst), (ins GPR:$src), DPFrm, IIC_iMOVr,
|
||||
"mov", " $dst, $src", []>, UnaryDP;
|
||||
"mov", " $dst, $src", []>, UnaryDP;
|
||||
def MOVs : AsI1<0b1101, (outs GPR:$dst), (ins so_reg:$src),
|
||||
DPSoRegFrm, IIC_iMOVsr,
|
||||
"mov", " $dst, $src", [(set GPR:$dst, so_reg:$src)]>, UnaryDP;
|
||||
DPSoRegFrm, IIC_iMOVsr,
|
||||
"mov", " $dst, $src", [(set GPR:$dst, so_reg:$src)]>, UnaryDP;
|
||||
|
||||
let isReMaterializable = 1, isAsCheapAsAMove = 1 in
|
||||
def MOVi : AsI1<0b1101, (outs GPR:$dst), (ins so_imm:$src), DPFrm, IIC_iMOVi,
|
||||
"mov", " $dst, $src", [(set GPR:$dst, so_imm:$src)]>, UnaryDP {
|
||||
let Inst{25} = 1;
|
||||
"mov", " $dst, $src", [(set GPR:$dst, so_imm:$src)]>, UnaryDP {
|
||||
let Inst{25} = 1;
|
||||
}
|
||||
|
||||
let isReMaterializable = 1, isAsCheapAsAMove = 1 in
|
||||
def MOVi16 : AI1<0b1000, (outs GPR:$dst), (ins i32imm:$src),
|
||||
DPFrm, IIC_iMOVi,
|
||||
"movw", " $dst, $src",
|
||||
[(set GPR:$dst, imm0_65535:$src)]>,
|
||||
Requires<[IsARM, HasV6T2]> {
|
||||
let Inst{25} = 1;
|
||||
}
|
||||
|
||||
let isReMaterializable = 1, isAsCheapAsAMove = 1,
|
||||
Constraints = "$src = $dst" in
|
||||
def MOVTi16 : AI1<0b1010, (outs GPR:$dst), (ins GPR:$src, i32imm:$imm),
|
||||
DPFrm, IIC_iMOVi,
|
||||
"movt", " $dst, $imm",
|
||||
[(set GPR:$dst,
|
||||
(or (and GPR:$src, 0xffff),
|
||||
lo16AllZero:$imm))]>, UnaryDP,
|
||||
Requires<[IsARM, HasV6T2]> {
|
||||
let Inst{25} = 1;
|
||||
}
|
||||
|
||||
let Uses = [CPSR] in
|
||||
@ -1478,6 +1520,10 @@ def : ARMPat<(xor GPR:$LHS, so_imm2part:$RHS),
|
||||
(EORri (EORri GPR:$LHS, (so_imm2part_1 imm:$RHS)),
|
||||
(so_imm2part_2 imm:$RHS))>;
|
||||
|
||||
def : ARMPat<(i32 imm:$src),
|
||||
(MOVTi16 (MOVi16 (lo16 imm:$src)), (hi16 imm:$src))>,
|
||||
Requires<[IsARM, HasV6T2]>;
|
||||
|
||||
// TODO: add,sub,and, 3-instr forms?
|
||||
|
||||
|
||||
|
@ -88,28 +88,6 @@ def imm0_255_neg : PatLeaf<(i32 imm), [{
|
||||
return (uint32_t)(-N->getZExtValue()) < 255;
|
||||
}], imm_neg_XFORM>;
|
||||
|
||||
/// imm0_65535 predicate - True if the 32-bit immediate is in the range
|
||||
/// [0.65535].
|
||||
def imm0_65535 : PatLeaf<(i32 imm), [{
|
||||
return (uint32_t)N->getZExtValue() < 65536;
|
||||
}]>;
|
||||
|
||||
/// Split a 32-bit immediate into two 16 bit parts.
|
||||
def t2_lo16 : SDNodeXForm<imm, [{
|
||||
return CurDAG->getTargetConstant((uint32_t)N->getZExtValue() & 0xffff,
|
||||
MVT::i32);
|
||||
}]>;
|
||||
|
||||
def t2_hi16 : SDNodeXForm<imm, [{
|
||||
return CurDAG->getTargetConstant((uint32_t)N->getZExtValue() >> 16, MVT::i32);
|
||||
}]>;
|
||||
|
||||
def t2_lo16AllZero : PatLeaf<(i32 imm), [{
|
||||
// Returns true if all low 16-bits are 0.
|
||||
return (((uint32_t)N->getZExtValue()) & 0xFFFFUL) == 0;
|
||||
}], t2_hi16>;
|
||||
|
||||
|
||||
// Define Thumb2 specific addressing modes.
|
||||
|
||||
// t2addrmode_imm12 := reg + imm12
|
||||
@ -681,12 +659,11 @@ def t2MOVi16 : T2I<(outs GPR:$dst), (ins i32imm:$src), IIC_iMOVi,
|
||||
"movw", " $dst, $src",
|
||||
[(set GPR:$dst, imm0_65535:$src)]>;
|
||||
|
||||
// FIXME: Also available in ARM mode.
|
||||
let Constraints = "$src = $dst" in
|
||||
def t2MOVTi16 : T2sI<(outs GPR:$dst), (ins GPR:$src, i32imm:$imm), IIC_iMOVi,
|
||||
"movt", " $dst, $imm",
|
||||
[(set GPR:$dst,
|
||||
(or (and GPR:$src, 0xffff), t2_lo16AllZero:$imm))]>;
|
||||
(or (and GPR:$src, 0xffff), lo16AllZero:$imm))]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Extend Instructions.
|
||||
@ -1153,4 +1130,4 @@ def : T2Pat<(ARMWrapperJT tjumptable:$dst, imm:$id),
|
||||
// Large immediate handling.
|
||||
|
||||
def : T2Pat<(i32 imm:$src),
|
||||
(t2MOVTi16 (t2MOVi16 (t2_lo16 imm:$src)), (t2_hi16 imm:$src))>;
|
||||
(t2MOVTi16 (t2MOVi16 (lo16 imm:$src)), (hi16 imm:$src))>;
|
||||
|
9
test/CodeGen/ARM/t2-imm.ll
Normal file
9
test/CodeGen/ARM/t2-imm.ll
Normal file
@ -0,0 +1,9 @@
|
||||
; RUN: llc < %s -march=arm -mattr=+thumb2 | FileCheck %s
|
||||
|
||||
define i32 @f6(i32 %a) {
|
||||
; CHECK:f6
|
||||
; CHECK: movw r0, #1123
|
||||
; CHECK: movt r0, #1000
|
||||
%tmp = add i32 0, 65537123
|
||||
ret i32 %tmp
|
||||
}
|
Loading…
Reference in New Issue
Block a user