Change how so_imm and t2_so_imm are handled. At instruction selection time, the immediates are no longer encoded in the imm8 + rot format, that are left as it is. The encoding is now done in ams printing and code emission time instead.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@75048 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evan Cheng 2009-07-08 21:03:57 +00:00
parent c3d505c3c2
commit e7cbe4118b
9 changed files with 48 additions and 111 deletions

View File

@ -273,29 +273,6 @@ namespace ARM_AM {
return V >> getThumbImmValShift(V);
}
/// getT2SOImmValDecode - Given a 12-bit encoded Thumb-2 modified immediate,
/// return the corresponding 32-bit immediate value.
/// See ARM Reference Manual A6.3.2.
static inline unsigned getT2SOImmValDecode(unsigned Imm) {
unsigned Base = Imm & 0xff;
switch ((Imm >> 8) & 0xf) {
case 0:
return Base;
case 1:
return Base | (Base << 16);
case 2:
return (Base << 8) | (Base << 24);
case 3:
return Base | (Base << 8) | (Base << 16) | (Base << 24);
default:
break;
}
// shifted immediate
unsigned RotAmount = ((Imm >> 7) & 0x1f) - 8;
return (Base | 0x80) << (24 - RotAmount);
}
/// getT2SOImmValSplat - Return the 12-bit encoded representation
/// if the specified value can be obtained by splatting the low 8 bits
/// into every other byte or every byte of a 32-bit value. i.e.,

View File

@ -91,15 +91,14 @@ ARMBaseInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
bool isSub = ARM_AM::getAM2Op(OffImm) == ARM_AM::sub;
unsigned Amt = ARM_AM::getAM2Offset(OffImm);
if (OffReg == 0) {
int SOImmVal = ARM_AM::getSOImmVal(Amt);
if (SOImmVal == -1)
if (ARM_AM::getSOImmVal(Amt) == -1)
// Can't encode it in a so_imm operand. This transformation will
// add more than 1 instruction. Abandon!
return NULL;
UpdateMI = BuildMI(MF, MI->getDebugLoc(),
get(isSub ? getOpcode(ARMII::SUBri) :
getOpcode(ARMII::ADDri)), WBReg)
.addReg(BaseReg).addImm(SOImmVal)
.addReg(BaseReg).addImm(Amt)
.addImm(Pred).addReg(0).addReg(0);
} else if (Amt != 0) {
ARM_AM::ShiftOpc ShOpc = ARM_AM::getAM2ShiftOpc(OffImm);

View File

@ -942,13 +942,11 @@ void emitARMRegPlusImmediate(MachineBasicBlock &MBB,
// We will handle these bits from offset, clear them.
NumBytes &= ~ThisVal;
// Get the properly encoded SOImmVal field.
int SOImmVal = ARM_AM::getSOImmVal(ThisVal);
assert(SOImmVal != -1 && "Bit extraction didn't work?");
assert(ARM_AM::getSOImmVal(ThisVal) != -1 && "Bit extraction didn't work?");
// Build the new ADD / SUB.
BuildMI(MBB, MBBI, dl, TII.get(TII.getOpcode(isSub ? ARMII::SUBri : ARMII::ADDri)), DestReg)
.addReg(BaseReg, RegState::Kill).addImm(SOImmVal)
.addReg(BaseReg, RegState::Kill).addImm(ThisVal)
.addImm((unsigned)Pred).addReg(PredReg).addReg(0);
BaseReg = DestReg;
}
@ -1071,11 +1069,10 @@ eliminateFrameIndex(MachineBasicBlock::iterator II,
}
// Common case: small offset, fits into instruction.
int ImmedOffset = ARM_AM::getSOImmVal(Offset);
if (ImmedOffset != -1) {
if (ARM_AM::getSOImmVal(Offset) != -1) {
// Replace the FrameIndex with sp / fp
MI.getOperand(i).ChangeToRegister(FrameReg, false);
MI.getOperand(i+1).ChangeToImmediate(ImmedOffset);
MI.getOperand(i+1).ChangeToImmediate(Offset);
return;
}
@ -1089,9 +1086,9 @@ eliminateFrameIndex(MachineBasicBlock::iterator II,
Offset &= ~ThisImmVal;
// Get the properly encoded SOImmVal field.
int ThisSOImmVal = ARM_AM::getSOImmVal(ThisImmVal);
assert(ThisSOImmVal != -1 && "Bit extraction didn't work?");
MI.getOperand(i+1).ChangeToImmediate(ThisSOImmVal);
assert(ARM_AM::getSOImmVal(ThisImmVal) != -1 &&
"Bit extraction didn't work?");
MI.getOperand(i+1).ChangeToImmediate(ThisImmVal);
} else {
unsigned ImmIdx = 0;
int InstrOffs = 0;

View File

@ -470,7 +470,8 @@ template<class CodeEmitter>
void Emitter<CodeEmitter>::emitMOVi2piecesInstruction(const MachineInstr &MI) {
const MachineOperand &MO0 = MI.getOperand(0);
const MachineOperand &MO1 = MI.getOperand(1);
assert(MO1.isImm() && "Not a valid so_imm value!");
assert(MO1.isImm() && ARM_AM::getSOImmVal(MO1.isImm()) != -1 &&
"Not a valid so_imm value!");
unsigned V1 = ARM_AM::getSOImmTwoPartFirst(MO1.getImm());
unsigned V2 = ARM_AM::getSOImmTwoPartSecond(MO1.getImm());
@ -486,7 +487,7 @@ void Emitter<CodeEmitter>::emitMOVi2piecesInstruction(const MachineInstr &MI) {
// Encode so_imm.
// Set bit I(25) to identify this is the immediate form of <shifter_op>
Binary |= 1 << ARMII::I_BitShift;
Binary |= getMachineSoImmOpValue(ARM_AM::getSOImmVal(V1));
Binary |= getMachineSoImmOpValue(V1);
emitWordLE(Binary);
// Now the 'orr' instruction.
@ -504,7 +505,7 @@ void Emitter<CodeEmitter>::emitMOVi2piecesInstruction(const MachineInstr &MI) {
// Encode so_imm.
// Set bit I(25) to identify this is the immediate form of <shifter_op>
Binary |= 1 << ARMII::I_BitShift;
Binary |= getMachineSoImmOpValue(ARM_AM::getSOImmVal(V2));
Binary |= getMachineSoImmOpValue(V2);
emitWordLE(Binary);
}
@ -714,12 +715,15 @@ unsigned Emitter<CodeEmitter>::getMachineSoRegOpValue(
template<class CodeEmitter>
unsigned Emitter<CodeEmitter>::getMachineSoImmOpValue(unsigned SoImm) {
int SoImmVal = ARM_AM::getSOImmVal(SoImm);
assert(SoImmVal != -1 && "Not a valid so_imm value!");
// Encode rotate_imm.
unsigned Binary = (ARM_AM::getSOImmValRot(SoImm) >> 1)
unsigned Binary = (ARM_AM::getSOImmValRot((unsigned)SoImmVal) >> 1)
<< ARMII::SoRotImmShift;
// Encode immed_8.
Binary |= ARM_AM::getSOImmValImm(SoImm);
Binary |= ARM_AM::getSOImmValImm((unsigned)SoImmVal);
return Binary;
}
@ -796,8 +800,7 @@ void Emitter<CodeEmitter>::emitDataProcessingInstruction(
}
// Encode so_imm.
Binary |= 1 << ARMII::I_BitShift;
Binary |= getMachineSoImmOpValue(MO.getImm());
Binary |= getMachineSoImmOpValue((unsigned)MO.getImm());
emitWordLE(Binary);
}

View File

@ -1071,10 +1071,10 @@ SDNode *ARMDAGToDAGISel::Select(SDValue Op) {
}
// Pattern: (ARMcmov:i32 GPR:i32:$false,
// (imm:i32)<<P:Predicate_so_imm>><<X:so_imm_XFORM>>:$true,
// (imm:i32)<<P:Predicate_so_imm>>:$true,
// (imm:i32):$cc)
// Emits: (MOVCCi:i32 GPR:i32:$false,
// (so_imm_XFORM:i32 (imm:i32):$true), (imm:i32):$cc)
// (so_imm:i32 (imm:i32):$true), (imm:i32):$cc)
// Pattern complexity = 10 cost = 1 size = 0
if (N3.getOpcode() == ISD::Constant) {
if (Subtarget->isThumb()) {
@ -1082,7 +1082,6 @@ SDNode *ARMDAGToDAGISel::Select(SDValue Op) {
SDValue Tmp1 = CurDAG->getTargetConstant(((unsigned)
cast<ConstantSDNode>(N1)->getZExtValue()),
MVT::i32);
Tmp1 = Transform_t2_so_imm_XFORM(Tmp1.getNode());
SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned)
cast<ConstantSDNode>(N2)->getZExtValue()),
MVT::i32);
@ -1095,7 +1094,6 @@ SDNode *ARMDAGToDAGISel::Select(SDValue Op) {
SDValue Tmp1 = CurDAG->getTargetConstant(((unsigned)
cast<ConstantSDNode>(N1)->getZExtValue()),
MVT::i32);
Tmp1 = Transform_so_imm_XFORM(Tmp1.getNode());
SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned)
cast<ConstantSDNode>(N2)->getZExtValue()),
MVT::i32);

View File

@ -118,25 +118,16 @@ class RegConstraint<string C> {
// ARM specific transformation functions and pattern fragments.
//
// so_imm_XFORM - Return a so_imm value packed into the format described for
// so_imm def below.
def so_imm_XFORM : SDNodeXForm<imm, [{
return CurDAG->getTargetConstant(ARM_AM::getSOImmVal(N->getZExtValue()),
MVT::i32);
}]>;
// so_imm_neg_XFORM - Return a so_imm value packed into the format described for
// so_imm_neg def below.
def so_imm_neg_XFORM : SDNodeXForm<imm, [{
return CurDAG->getTargetConstant(ARM_AM::getSOImmVal(-(int)N->getZExtValue()),
MVT::i32);
return CurDAG->getTargetConstant(-(int)N->getZExtValue(), MVT::i32);
}]>;
// so_imm_not_XFORM - Return a so_imm value packed into the format described for
// so_imm_not def below.
def so_imm_not_XFORM : SDNodeXForm<imm, [{
return CurDAG->getTargetConstant(ARM_AM::getSOImmVal(~(int)N->getZExtValue()),
MVT::i32);
return CurDAG->getTargetConstant(~(int)N->getZExtValue(), MVT::i32);
}]>;
// rot_imm predicate - True if the 32-bit immediate is equal to 8, 16, or 24.
@ -234,9 +225,9 @@ def so_reg : Operand<i32>, // reg reg imm
// into so_imm instructions: the 8-bit immediate is the least significant bits
// [bits 0-7], the 4-bit shift amount is the next 4 bits [bits 8-11].
def so_imm : Operand<i32>,
PatLeaf<(imm),
[{ return ARM_AM::getSOImmVal(N->getZExtValue()) != -1; }],
so_imm_XFORM> {
PatLeaf<(imm), [{
return ARM_AM::getSOImmVal(N->getZExtValue()) != -1;
}]> {
let PrintMethod = "printSOImmOperand";
}
@ -252,12 +243,12 @@ def so_imm2part : Operand<i32>,
def so_imm2part_1 : SDNodeXForm<imm, [{
unsigned V = ARM_AM::getSOImmTwoPartFirst((unsigned)N->getZExtValue());
return CurDAG->getTargetConstant(ARM_AM::getSOImmVal(V), MVT::i32);
return CurDAG->getTargetConstant(V, MVT::i32);
}]>;
def so_imm2part_2 : SDNodeXForm<imm, [{
unsigned V = ARM_AM::getSOImmTwoPartSecond((unsigned)N->getZExtValue());
return CurDAG->getTargetConstant(ARM_AM::getSOImmVal(V), MVT::i32);
return CurDAG->getTargetConstant(V, MVT::i32);
}]>;
@ -1440,11 +1431,11 @@ def MOVi2pieces : AI1x2<(outs GPR:$dst), (ins so_imm2part:$src), Pseudo,
[(set GPR:$dst, so_imm2part:$src)]>;
def : ARMPat<(or GPR:$LHS, so_imm2part:$RHS),
(ORRri (ORRri GPR:$LHS, (so_imm2part_1 imm:$RHS)),
(so_imm2part_2 imm:$RHS))>;
(ORRri (ORRri GPR:$LHS, (so_imm2part_1 imm:$RHS)),
(so_imm2part_2 imm:$RHS))>;
def : ARMPat<(xor GPR:$LHS, so_imm2part:$RHS),
(EORri (EORri GPR:$LHS, (so_imm2part_1 imm:$RHS)),
(so_imm2part_2 imm:$RHS))>;
(EORri (EORri GPR:$LHS, (so_imm2part_1 imm:$RHS)),
(so_imm2part_2 imm:$RHS))>;
// TODO: add,sub,and, 3-instr forms?

View File

@ -20,23 +20,14 @@ def t2_so_reg : Operand<i32>, // reg imm
let MIOperandInfo = (ops GPR, i32imm);
}
// t2_so_imm_XFORM - Return a t2_so_imm value packed into the format
// described for t2_so_imm def below.
def t2_so_imm_XFORM : SDNodeXForm<imm, [{
return CurDAG->getTargetConstant(
ARM_AM::getT2SOImmVal(N->getZExtValue()), MVT::i32);
}]>;
// t2_so_imm_not_XFORM - Return the complement of a t2_so_imm value
def t2_so_imm_not_XFORM : SDNodeXForm<imm, [{
return CurDAG->getTargetConstant(
ARM_AM::getT2SOImmVal(~((uint32_t)N->getZExtValue())), MVT::i32);
return CurDAG->getTargetConstant(~((uint32_t)N->getZExtValue()), MVT::i32);
}]>;
// t2_so_imm_neg_XFORM - Return the negation of a t2_so_imm value
def t2_so_imm_neg_XFORM : SDNodeXForm<imm, [{
return CurDAG->getTargetConstant(
ARM_AM::getT2SOImmVal(-((int)N->getZExtValue())), MVT::i32);
return CurDAG->getTargetConstant(-((int)N->getZExtValue()), MVT::i32);
}]>;
// t2_so_imm - Match a 32-bit immediate operand, which is an
@ -47,27 +38,21 @@ def t2_so_imm_neg_XFORM : SDNodeXForm<imm, [{
// [bits 0-7], the 4-bit shift/splat amount is the next 4 bits [bits 8-11].
def t2_so_imm : Operand<i32>,
PatLeaf<(imm), [{
return ARM_AM::getT2SOImmVal((uint32_t)N->getZExtValue()) != -1;
}], t2_so_imm_XFORM> {
let PrintMethod = "printT2SOImmOperand";
}
return ARM_AM::getT2SOImmVal((uint32_t)N->getZExtValue()) != -1;
}]>;
// t2_so_imm_not - Match an immediate that is a complement
// of a t2_so_imm.
def t2_so_imm_not : Operand<i32>,
PatLeaf<(imm), [{
return ARM_AM::getT2SOImmVal(~((uint32_t)N->getZExtValue())) != -1;
}], t2_so_imm_not_XFORM> {
let PrintMethod = "printT2SOImmOperand";
}
return ARM_AM::getT2SOImmVal(~((uint32_t)N->getZExtValue())) != -1;
}], t2_so_imm_not_XFORM>;
// t2_so_imm_neg - Match an immediate that is a negation of a t2_so_imm.
def t2_so_imm_neg : Operand<i32>,
PatLeaf<(imm), [{
return ARM_AM::getT2SOImmVal(-((int)N->getZExtValue())) != -1;
}], t2_so_imm_neg_XFORM> {
let PrintMethod = "printT2SOImmOperand";
}
return ARM_AM::getT2SOImmVal(-((int)N->getZExtValue())) != -1;
}], t2_so_imm_neg_XFORM>;
/// imm1_31 predicate - True if the 32-bit immediate is in the range [1,31].
def imm1_31 : PatLeaf<(i32 imm), [{

View File

@ -171,12 +171,11 @@ ARMLoadStoreOpt::MergeOps(MachineBasicBlock &MBB,
BaseOpc = ARM::SUBri;
Offset = - Offset;
}
int ImmedOffset = ARM_AM::getSOImmVal(Offset);
if (ImmedOffset == -1)
if (ARM_AM::getSOImmVal(Offset) == -1)
return false; // Probably not worth it then.
BuildMI(MBB, MBBI, dl, TII->get(BaseOpc), NewBase)
.addReg(Base, getKillRegState(BaseKill)).addImm(ImmedOffset)
.addReg(Base, getKillRegState(BaseKill)).addImm(Offset)
.addImm(Pred).addReg(PredReg).addReg(0);
Base = NewBase;
BaseKill = true; // New base is always killed right its use.

View File

@ -119,7 +119,6 @@ namespace {
void printThumbAddrModeS4Operand(const MachineInstr *MI, int OpNum);
void printThumbAddrModeSPOperand(const MachineInstr *MI, int OpNum);
void printT2SOImmOperand(const MachineInstr *MI, int OpNum);
void printT2SOOperand(const MachineInstr *MI, int OpNum);
void printT2AddrModeImm12Operand(const MachineInstr *MI, int OpNum);
void printT2AddrModeImm8Operand(const MachineInstr *MI, int OpNum);
@ -370,7 +369,10 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
static void printSOImm(raw_ostream &O, int64_t V, bool VerboseAsm,
const TargetAsmInfo *TAI) {
assert(V < (1 << 12) && "Not a valid so_imm value!");
// Break it up into two parts that make up a shifter immediate.
V = ARM_AM::getSOImmVal(V);
assert(V != -1 && "Not a valid so_imm value!");
unsigned Imm = ARM_AM::getSOImmValImm(V);
unsigned Rot = ARM_AM::getSOImmValRot(V);
@ -402,7 +404,7 @@ void ARMAsmPrinter::printSOImm2PartOperand(const MachineInstr *MI, int OpNum) {
assert(MO.isImm() && "Not a valid so_imm value!");
unsigned V1 = ARM_AM::getSOImmTwoPartFirst(MO.getImm());
unsigned V2 = ARM_AM::getSOImmTwoPartSecond(MO.getImm());
printSOImm(O, ARM_AM::getSOImmVal(V1), VerboseAsm, TAI);
printSOImm(O, V1, VerboseAsm, TAI);
O << "\n\torr";
printPredicateOperand(MI, 2);
O << " ";
@ -410,7 +412,7 @@ void ARMAsmPrinter::printSOImm2PartOperand(const MachineInstr *MI, int OpNum) {
O << ", ";
printOperand(MI, 0);
O << ", ";
printSOImm(O, ARM_AM::getSOImmVal(V2), VerboseAsm, TAI);
printSOImm(O, V2, VerboseAsm, TAI);
}
// so_reg is a 4-operand unit corresponding to register forms of the A5.1
@ -687,20 +689,6 @@ void ARMAsmPrinter::printThumbAddrModeSPOperand(const MachineInstr *MI,int Op) {
//===--------------------------------------------------------------------===//
/// printT2SOImmOperand - T2SOImm is:
/// 1. a 4-bit splat control value and 8 bit immediate value
/// 2. a 5-bit rotate amount and a non-zero 8-bit immediate value
/// represented by a normalizedin 7-bit value (msb is always 1)
void ARMAsmPrinter::printT2SOImmOperand(const MachineInstr *MI, int OpNum) {
const MachineOperand &MO = MI->getOperand(OpNum);
assert(MO.isImm() && "Not a valid so_imm value!");
unsigned Imm = ARM_AM::getT2SOImmValDecode(MO.getImm());
// Always print the immediate directly, as the "rotate" form
// is deprecated in some contexts.
O << "#" << Imm;
}
// Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
// register with shift forms.
// REG 0 0 - e.g. R5