Model operand restrictions of mul-like instructions on ARMv5 via

earlyclobber stuff. This should fix PRs 2313 and 8157.

Unfortunately, no testcase, since it'd be dependent on register
assignments.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@122663 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Anton Korobeynikov 2011-01-01 20:38:38 +00:00
parent bafa117e8f
commit 4d72860835
4 changed files with 100 additions and 10 deletions

View File

@ -725,6 +725,16 @@ static void populateADROperands(MCInst &Inst, unsigned Dest,
Inst.addOperand(MCOperand::CreateReg(ccreg));
}
void ARMAsmPrinter::EmitPatchedInstruction(const MachineInstr *MI,
unsigned Opcode) {
MCInst TmpInst;
// Emit the instruction as usual, just patch the opcode.
LowerARMMachineInstrToMCInst(MI, TmpInst, *this);
TmpInst.setOpcode(Opcode);
OutStreamer.EmitInstruction(TmpInst);
}
void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
switch (MI->getOpcode()) {
default: break;
@ -1376,6 +1386,30 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
}
return;
}
// These are the pseudos created to comply with stricter operand restrictions
// on ARMv5. Lower them now to "normal" instructions, since all the
// restrictions are already satisfied.
case ARM::MULv5:
EmitPatchedInstruction(MI, ARM::MUL);
return;
case ARM::MLAv5:
EmitPatchedInstruction(MI, ARM::MLA);
return;
case ARM::SMULLv5:
EmitPatchedInstruction(MI, ARM::SMULL);
return;
case ARM::UMULLv5:
EmitPatchedInstruction(MI, ARM::UMULL);
return;
case ARM::SMLALv5:
EmitPatchedInstruction(MI, ARM::SMLAL);
return;
case ARM::UMLALv5:
EmitPatchedInstruction(MI, ARM::UMLAL);
return;
case ARM::UMAALv5:
EmitPatchedInstruction(MI, ARM::UMAAL);
return;
}
MCInst TmpInst;

View File

@ -79,6 +79,9 @@ private:
// Helper for ELF .o only
void emitARMAttributeSection();
// Generic helper used to emit e.g. ARMv5 mul pseudos
void EmitPatchedInstruction(const MachineInstr *MI, unsigned TargetOpc);
public:
void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS);

View File

@ -2322,7 +2322,9 @@ SDNode *ARMDAGToDAGISel::Select(SDNode *N) {
SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
CurDAG->getRegister(0, MVT::i32) };
return CurDAG->getMachineNode(ARM::UMULL, dl, MVT::i32, MVT::i32, Ops, 5);
return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
ARM::UMULL : ARM::UMULLv5,
dl, MVT::i32, MVT::i32, Ops, 5);
}
}
case ISD::SMUL_LOHI: {
@ -2336,7 +2338,9 @@ SDNode *ARMDAGToDAGISel::Select(SDNode *N) {
SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
getAL(CurDAG), CurDAG->getRegister(0, MVT::i32),
CurDAG->getRegister(0, MVT::i32) };
return CurDAG->getMachineNode(ARM::SMULL, dl, MVT::i32, MVT::i32, Ops, 5);
return CurDAG->getMachineNode(Subtarget->hasV6Ops() ?
ARM::SMULL : ARM::SMULLv5,
dl, MVT::i32, MVT::i32, Ops, 5);
}
}
case ISD::LOAD: {

View File

@ -149,6 +149,7 @@ def NoV4T : Predicate<"!Subtarget->hasV4TOps()">;
def HasV5T : Predicate<"Subtarget->hasV5TOps()">;
def HasV5TE : Predicate<"Subtarget->hasV5TEOps()">, AssemblerPredicate;
def HasV6 : Predicate<"Subtarget->hasV6Ops()">, AssemblerPredicate;
def NoV6 : Predicate<"!Subtarget->hasV6Ops()">;
def HasV6T2 : Predicate<"Subtarget->hasV6T2Ops()">, AssemblerPredicate;
def NoV6T2 : Predicate<"!Subtarget->hasV6T2Ops()">;
def HasV7 : Predicate<"Subtarget->hasV7Ops()">, AssemblerPredicate;
@ -2504,14 +2505,31 @@ class AsMul1I64<bits<7> opcod, dag oops, dag iops, InstrItinClass itin,
let Inst{3-0} = Rn;
}
let isCommutable = 1 in
let isCommutable = 1 in {
let Constraints = "@earlyclobber $Rd" in
def MULv5: PseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s),
IIC_iMUL32, [(set GPR:$Rd, (mul GPR:$Rn, GPR:$Rm))]>,
Requires<[IsARM, NoV6]>;
def MUL : AsMul1I32<0b0000000, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
IIC_iMUL32, "mul", "\t$Rd, $Rn, $Rm",
[(set GPR:$Rd, (mul GPR:$Rn, GPR:$Rm))]>;
[(set GPR:$Rd, (mul GPR:$Rn, GPR:$Rm))]>,
Requires<[IsARM, HasV6]>;
}
let Constraints = "@earlyclobber $Rd" in
def MLAv5: PseudoInst<(outs GPR:$Rd),
(ins GPR:$Rn, GPR:$Rm, GPR:$Ra, pred:$p, cc_out:$s),
IIC_iMAC32, [(set GPR:$Rd, (add (mul GPR:$Rn, GPR:$Rm),
GPR:$Ra))]>,
Requires<[IsARM, NoV6]> {
bits<4> Ra;
let Inst{15-12} = Ra;
}
def MLA : AsMul1I32<0b0000001, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
IIC_iMAC32, "mla", "\t$Rd, $Rn, $Rm, $Ra",
[(set GPR:$Rd, (add (mul GPR:$Rn, GPR:$Rm), GPR:$Ra))]> {
[(set GPR:$Rd, (add (mul GPR:$Rn, GPR:$Rm), GPR:$Ra))]>,
Requires<[IsARM, HasV6]> {
bits<4> Ra;
let Inst{15-12} = Ra;
}
@ -2534,23 +2552,54 @@ def MLS : AMul1I<0b0000011, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
let neverHasSideEffects = 1 in {
let isCommutable = 1 in {
let Constraints = "@earlyclobber $RdLo,@earlyclobber $RdHi" in {
def SMULLv5 : PseudoInst<(outs GPR:$RdLo, GPR:$RdHi),
(ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s),
IIC_iMUL64, []>,
Requires<[IsARM, NoV6]>;
def UMULLv5 : PseudoInst<(outs GPR:$RdLo, GPR:$RdHi),
(ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s),
IIC_iMUL64, []>,
Requires<[IsARM, NoV6]>;
}
def SMULL : AsMul1I64<0b0000110, (outs GPR:$RdLo, GPR:$RdHi),
(ins GPR:$Rn, GPR:$Rm), IIC_iMUL64,
"smull", "\t$RdLo, $RdHi, $Rn, $Rm", []>;
"smull", "\t$RdLo, $RdHi, $Rn, $Rm", []>,
Requires<[IsARM, HasV6]>;
def UMULL : AsMul1I64<0b0000100, (outs GPR:$RdLo, GPR:$RdHi),
(ins GPR:$Rn, GPR:$Rm), IIC_iMUL64,
"umull", "\t$RdLo, $RdHi, $Rn, $Rm", []>;
"umull", "\t$RdLo, $RdHi, $Rn, $Rm", []>,
Requires<[IsARM, HasV6]>;
}
// Multiply + accumulate
let Constraints = "@earlyclobber $RdLo,@earlyclobber $RdHi" in {
def SMLALv5 : PseudoInst<(outs GPR:$RdLo, GPR:$RdHi),
(ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s),
IIC_iMAC64, []>,
Requires<[IsARM, NoV6]>;
def UMLALv5 : PseudoInst<(outs GPR:$RdLo, GPR:$RdHi),
(ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s),
IIC_iMAC64, []>,
Requires<[IsARM, NoV6]>;
def UMAALv5 : PseudoInst<(outs GPR:$RdLo, GPR:$RdHi),
(ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s),
IIC_iMAC64, []>,
Requires<[IsARM, NoV6]>;
}
def SMLAL : AsMul1I64<0b0000111, (outs GPR:$RdLo, GPR:$RdHi),
(ins GPR:$Rn, GPR:$Rm), IIC_iMAC64,
"smlal", "\t$RdLo, $RdHi, $Rn, $Rm", []>;
"smlal", "\t$RdLo, $RdHi, $Rn, $Rm", []>,
Requires<[IsARM, HasV6]>;
def UMLAL : AsMul1I64<0b0000101, (outs GPR:$RdLo, GPR:$RdHi),
(ins GPR:$Rn, GPR:$Rm), IIC_iMAC64,
"umlal", "\t$RdLo, $RdHi, $Rn, $Rm", []>;
"umlal", "\t$RdLo, $RdHi, $Rn, $Rm", []>,
Requires<[IsARM, HasV6]>;
def UMAAL : AMul1I <0b0000010, (outs GPR:$RdLo, GPR:$RdHi),
(ins GPR:$Rn, GPR:$Rm), IIC_iMAC64,