forked from OSchip/llvm-project
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. llvm-svn: 122663
This commit is contained in:
parent
a3514441e0
commit
62acecd7e1
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue