mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-02 22:04:55 +00:00
ARM refactor indexed store instructions.
Refactor STR[B] pre and post indexed instructions to use addressing modes for memory operands, which is necessary for assembly parsing and is more consistent with the rest of the memory instruction definitions. Make some incremental progress on refactoring away the mega-operand addrmode2 along the way, which is nice. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@136978 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
6fc1c08635
commit
19dec207fc
@ -588,14 +588,8 @@ void ARMFrameLowering::emitPushInst(MachineBasicBlock &MBB,
|
|||||||
MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, TII.get(StrOpc),
|
MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, TII.get(StrOpc),
|
||||||
ARM::SP)
|
ARM::SP)
|
||||||
.addReg(Regs[0].first, getKillRegState(Regs[0].second))
|
.addReg(Regs[0].first, getKillRegState(Regs[0].second))
|
||||||
.addReg(ARM::SP).setMIFlags(MIFlags);
|
.addReg(ARM::SP).setMIFlags(MIFlags)
|
||||||
// ARM mode needs an extra reg0 here due to addrmode2. Will go away once
|
.addImm(-4);
|
||||||
// that refactoring is complete (eventually).
|
|
||||||
if (StrOpc == ARM::STR_PRE_REG || StrOpc == ARM::STR_PRE_IMM) {
|
|
||||||
MIB.addReg(0);
|
|
||||||
MIB.addImm(ARM_AM::getAM2Opc(ARM_AM::sub, 4, ARM_AM::no_shift));
|
|
||||||
} else
|
|
||||||
MIB.addImm(-4);
|
|
||||||
AddDefaultPred(MIB);
|
AddDefaultPred(MIB);
|
||||||
}
|
}
|
||||||
Regs.clear();
|
Regs.clear();
|
||||||
|
@ -133,6 +133,7 @@ public:
|
|||||||
SDValue &Offset, SDValue &Opc);
|
SDValue &Offset, SDValue &Opc);
|
||||||
bool SelectAddrMode2OffsetImm(SDNode *Op, SDValue N,
|
bool SelectAddrMode2OffsetImm(SDNode *Op, SDValue N,
|
||||||
SDValue &Offset, SDValue &Opc);
|
SDValue &Offset, SDValue &Opc);
|
||||||
|
bool SelectAddrOffsetNone(SDValue N, SDValue &Base);
|
||||||
bool SelectAddrMode3(SDValue N, SDValue &Base,
|
bool SelectAddrMode3(SDValue N, SDValue &Base,
|
||||||
SDValue &Offset, SDValue &Opc);
|
SDValue &Offset, SDValue &Opc);
|
||||||
bool SelectAddrMode3Offset(SDNode *Op, SDValue N,
|
bool SelectAddrMode3Offset(SDNode *Op, SDValue N,
|
||||||
@ -772,8 +773,10 @@ bool ARMDAGToDAGISel::SelectAddrMode2OffsetImm(SDNode *Op, SDValue N,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ARMDAGToDAGISel::SelectAddrOffsetNone(SDValue N, SDValue &Base) {
|
||||||
|
Base = N;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ARMDAGToDAGISel::SelectAddrMode3(SDValue N,
|
bool ARMDAGToDAGISel::SelectAddrMode3(SDValue N,
|
||||||
SDValue &Base, SDValue &Offset,
|
SDValue &Base, SDValue &Offset,
|
||||||
|
@ -5289,6 +5289,37 @@ ARMTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
|
|||||||
MI->dump();
|
MI->dump();
|
||||||
llvm_unreachable("Unexpected instr type to insert");
|
llvm_unreachable("Unexpected instr type to insert");
|
||||||
}
|
}
|
||||||
|
case ARM::STRi_preidx:
|
||||||
|
case ARM::STRBi_preidx: {
|
||||||
|
unsigned NewOpc = MI->getOpcode() == ARM::STRr_preidx ?
|
||||||
|
ARM::STR_PRE_IMM : ARM::STRB_PRE_IMM;
|
||||||
|
// Decode the offset.
|
||||||
|
unsigned Offset = MI->getOperand(4).getImm();
|
||||||
|
bool isSub = ARM_AM::getAM2Op(Offset) == ARM_AM::sub;
|
||||||
|
Offset = ARM_AM::getAM2Offset(Offset);
|
||||||
|
if (isSub)
|
||||||
|
Offset = -Offset;
|
||||||
|
|
||||||
|
MachineInstrBuilder MIB = BuildMI(*BB, MI, dl, TII->get(NewOpc))
|
||||||
|
.addOperand(MI->getOperand(0)) // Rn_wb
|
||||||
|
.addOperand(MI->getOperand(1)) // Rt
|
||||||
|
.addOperand(MI->getOperand(2)) // Rn
|
||||||
|
.addImm(Offset) // offset (skip GPR==zero_reg)
|
||||||
|
.addOperand(MI->getOperand(5)) // pred
|
||||||
|
.addOperand(MI->getOperand(6));
|
||||||
|
MI->eraseFromParent();
|
||||||
|
return BB;
|
||||||
|
}
|
||||||
|
case ARM::STRr_preidx:
|
||||||
|
case ARM::STRBr_preidx: {
|
||||||
|
unsigned NewOpc = MI->getOpcode() == ARM::STRr_preidx ?
|
||||||
|
ARM::STR_PRE_REG : ARM::STRB_PRE_REG;
|
||||||
|
MachineInstrBuilder MIB = BuildMI(*BB, MI, dl, TII->get(NewOpc));
|
||||||
|
for (unsigned i = 0; i < MI->getNumOperands(); ++i)
|
||||||
|
MIB.addOperand(MI->getOperand(i));
|
||||||
|
MI->eraseFromParent();
|
||||||
|
return BB;
|
||||||
|
}
|
||||||
case ARM::ATOMIC_LOAD_ADD_I8:
|
case ARM::ATOMIC_LOAD_ADD_I8:
|
||||||
return EmitAtomicBinary(MI, BB, 1, isThumb2 ? ARM::t2ADDrr : ARM::ADDrr);
|
return EmitAtomicBinary(MI, BB, 1, isThumb2 ? ARM::t2ADDrr : ARM::ADDrr);
|
||||||
case ARM::ATOMIC_LOAD_ADD_I16:
|
case ARM::ATOMIC_LOAD_ADD_I16:
|
||||||
|
@ -769,7 +769,8 @@ def addrmodepc : Operand<i32>,
|
|||||||
// addr_offset_none := reg
|
// addr_offset_none := reg
|
||||||
//
|
//
|
||||||
def MemNoOffsetAsmOperand : AsmOperandClass { let Name = "MemNoOffset"; }
|
def MemNoOffsetAsmOperand : AsmOperandClass { let Name = "MemNoOffset"; }
|
||||||
def addr_offset_none : Operand<i32> {
|
def addr_offset_none : Operand<i32>,
|
||||||
|
ComplexPattern<i32, 1, "SelectAddrOffsetNone", []> {
|
||||||
let PrintMethod = "printAddrMode7Operand";
|
let PrintMethod = "printAddrMode7Operand";
|
||||||
let ParserMatchClass = MemNoOffsetAsmOperand;
|
let ParserMatchClass = MemNoOffsetAsmOperand;
|
||||||
let MIOperandInfo = (ops GPR:$base);
|
let MIOperandInfo = (ops GPR:$base);
|
||||||
@ -1926,7 +1927,6 @@ multiclass AI2_ldridx<bit isByte, string opc, InstrItinClass itin> {
|
|||||||
let Inst{23} = offset{12};
|
let Inst{23} = offset{12};
|
||||||
let Inst{19-16} = addr;
|
let Inst{19-16} = addr;
|
||||||
let Inst{11-0} = offset{11-0};
|
let Inst{11-0} = offset{11-0};
|
||||||
let DecoderMethod = "DecodeAddrMode2IdxInstruction";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def _POST_IMM : AI2ldstidx<1, isByte, 0, (outs GPR:$Rt, GPR:$Rn_wb),
|
def _POST_IMM : AI2ldstidx<1, isByte, 0, (outs GPR:$Rt, GPR:$Rn_wb),
|
||||||
@ -1942,7 +1942,6 @@ multiclass AI2_ldridx<bit isByte, string opc, InstrItinClass itin> {
|
|||||||
let Inst{23} = offset{12};
|
let Inst{23} = offset{12};
|
||||||
let Inst{19-16} = addr;
|
let Inst{19-16} = addr;
|
||||||
let Inst{11-0} = offset{11-0};
|
let Inst{11-0} = offset{11-0};
|
||||||
let DecoderMethod = "DecodeAddrMode2IdxInstruction";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2092,69 +2091,111 @@ def STRD : AI3str<0b1111, (outs), (ins GPR:$Rt, GPR:$src2, addrmode3:$addr),
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Indexed stores
|
// Indexed stores
|
||||||
def STR_PRE_REG : AI2stridx_reg<0, 1, (outs GPR:$Rn_wb),
|
multiclass AI2_stridx<bit isByte, string opc, InstrItinClass itin> {
|
||||||
(ins GPR:$Rt, GPR:$Rn, am2offset_reg:$offset),
|
def _PRE_IMM : AI2ldstidx<0, isByte, 1, (outs GPR:$Rn_wb),
|
||||||
IndexModePre, StFrm, IIC_iStore_ru,
|
(ins GPR:$Rt, addrmode_imm12:$addr), IndexModePre,
|
||||||
"str", "\t$Rt, [$Rn, $offset]!",
|
StFrm, itin,
|
||||||
"$Rn = $Rn_wb,@earlyclobber $Rn_wb",
|
opc, "\t$Rt, $addr!", "$addr.base = $Rn_wb", []> {
|
||||||
[(set GPR:$Rn_wb,
|
bits<17> addr;
|
||||||
(pre_store GPR:$Rt, GPR:$Rn, am2offset_reg:$offset))]>;
|
let Inst{25} = 0;
|
||||||
def STR_PRE_IMM : AI2stridx_imm<0, 1, (outs GPR:$Rn_wb),
|
let Inst{23} = addr{12}; // U (add = ('U' == 1))
|
||||||
(ins GPR:$Rt, GPR:$Rn, am2offset_imm:$offset),
|
let Inst{19-16} = addr{16-13}; // Rn
|
||||||
IndexModePre, StFrm, IIC_iStore_ru,
|
let Inst{11-0} = addr{11-0}; // imm12
|
||||||
"str", "\t$Rt, [$Rn, $offset]!",
|
let AsmMatchConverter = "cvtStWriteBackRegAddrMode2";
|
||||||
"$Rn = $Rn_wb,@earlyclobber $Rn_wb",
|
}
|
||||||
[(set GPR:$Rn_wb,
|
|
||||||
(pre_store GPR:$Rt, GPR:$Rn, am2offset_imm:$offset))]>;
|
|
||||||
|
|
||||||
|
def _PRE_REG : AI2ldstidx<0, isByte, 1, (outs GPR:$Rn_wb),
|
||||||
|
(ins GPR:$Rt, addrmode2:$addr), IndexModePre, StFrm, itin,
|
||||||
|
opc, "\t$Rt, $addr!", "$addr.base = $Rn_wb", []> {
|
||||||
|
bits<17> addr;
|
||||||
|
let Inst{25} = 1;
|
||||||
|
let Inst{23} = addr{12}; // U (add = ('U' == 1))
|
||||||
|
let Inst{19-16} = addr{16-13}; // Rn
|
||||||
|
let Inst{11-0} = addr{11-0};
|
||||||
|
let Inst{4} = 0; // Inst{4} = 0
|
||||||
|
let AsmMatchConverter = "cvtStWriteBackRegAddrMode2";
|
||||||
|
}
|
||||||
|
def _POST_REG : AI2ldstidx<0, isByte, 0, (outs GPR:$Rn_wb),
|
||||||
|
(ins GPR:$Rt, addr_offset_none:$addr, am2offset_reg:$offset),
|
||||||
|
IndexModePost, StFrm, itin,
|
||||||
|
opc, "\t$Rt, $addr, $offset",
|
||||||
|
"$addr.base = $Rn_wb", []> {
|
||||||
|
// {12} isAdd
|
||||||
|
// {11-0} imm12/Rm
|
||||||
|
bits<14> offset;
|
||||||
|
bits<4> addr;
|
||||||
|
let Inst{25} = 1;
|
||||||
|
let Inst{23} = offset{12};
|
||||||
|
let Inst{19-16} = addr;
|
||||||
|
let Inst{11-0} = offset{11-0};
|
||||||
|
}
|
||||||
|
|
||||||
|
def _POST_IMM : AI2ldstidx<0, isByte, 0, (outs GPR:$Rn_wb),
|
||||||
|
(ins GPR:$Rt, addr_offset_none:$addr, am2offset_imm:$offset),
|
||||||
|
IndexModePost, StFrm, itin,
|
||||||
|
opc, "\t$Rt, $addr, $offset",
|
||||||
|
"$addr.base = $Rn_wb", []> {
|
||||||
|
// {12} isAdd
|
||||||
|
// {11-0} imm12/Rm
|
||||||
|
bits<14> offset;
|
||||||
|
bits<4> addr;
|
||||||
|
let Inst{25} = 0;
|
||||||
|
let Inst{23} = offset{12};
|
||||||
|
let Inst{19-16} = addr;
|
||||||
|
let Inst{11-0} = offset{11-0};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def STR_POST_REG : AI2stridx_reg<0, 0, (outs GPR:$Rn_wb),
|
let mayStore = 1, neverHasSideEffects = 1 in {
|
||||||
(ins GPR:$Rt, GPR:$Rn, am2offset_reg:$offset),
|
defm STR : AI2_stridx<0, "str", IIC_iStore_ru>;
|
||||||
IndexModePost, StFrm, IIC_iStore_ru,
|
defm STRB : AI2_stridx<1, "strb", IIC_iStore_bh_ru>;
|
||||||
"str", "\t$Rt, [$Rn], $offset",
|
}
|
||||||
"$Rn = $Rn_wb,@earlyclobber $Rn_wb",
|
|
||||||
[(set GPR:$Rn_wb,
|
|
||||||
(post_store GPR:$Rt, GPR:$Rn, am2offset_reg:$offset))]>;
|
|
||||||
def STR_POST_IMM : AI2stridx_imm<0, 0, (outs GPR:$Rn_wb),
|
|
||||||
(ins GPR:$Rt, GPR:$Rn, am2offset_imm:$offset),
|
|
||||||
IndexModePost, StFrm, IIC_iStore_ru,
|
|
||||||
"str", "\t$Rt, [$Rn], $offset",
|
|
||||||
"$Rn = $Rn_wb,@earlyclobber $Rn_wb",
|
|
||||||
[(set GPR:$Rn_wb,
|
|
||||||
(post_store GPR:$Rt, GPR:$Rn, am2offset_imm:$offset))]>;
|
|
||||||
|
|
||||||
|
def : ARMPat<(post_store GPR:$Rt, addr_offset_none:$addr,
|
||||||
|
am2offset_reg:$offset),
|
||||||
|
(STR_POST_REG GPR:$Rt, addr_offset_none:$addr,
|
||||||
|
am2offset_reg:$offset)>;
|
||||||
|
def : ARMPat<(post_store GPR:$Rt, addr_offset_none:$addr,
|
||||||
|
am2offset_imm:$offset),
|
||||||
|
(STR_POST_IMM GPR:$Rt, addr_offset_none:$addr,
|
||||||
|
am2offset_imm:$offset)>;
|
||||||
|
def : ARMPat<(post_truncsti8 GPR:$Rt, addr_offset_none:$addr,
|
||||||
|
am2offset_reg:$offset),
|
||||||
|
(STRB_POST_REG GPR:$Rt, addr_offset_none:$addr,
|
||||||
|
am2offset_reg:$offset)>;
|
||||||
|
def : ARMPat<(post_truncsti8 GPR:$Rt, addr_offset_none:$addr,
|
||||||
|
am2offset_imm:$offset),
|
||||||
|
(STRB_POST_IMM GPR:$Rt, addr_offset_none:$addr,
|
||||||
|
am2offset_imm:$offset)>;
|
||||||
|
|
||||||
def STRB_PRE_REG : AI2stridx_reg<1, 1, (outs GPR:$Rn_wb),
|
// Pseudo-instructions for pattern matching the pre-indexed stores. We can't
|
||||||
(ins GPR:$Rt, GPR:$Rn, am2offset_reg:$offset),
|
// put the patterns on the instruction definitions directly as ISel wants
|
||||||
IndexModePre, StFrm, IIC_iStore_bh_ru,
|
// the address base and offset to be separate operands, not a single
|
||||||
"strb", "\t$Rt, [$Rn, $offset]!",
|
// complex operand like we represent the instructions themselves. The
|
||||||
"$Rn = $Rn_wb,@earlyclobber $Rn_wb",
|
// pseudos map between the two.
|
||||||
[(set GPR:$Rn_wb, (pre_truncsti8 GPR:$Rt,
|
let usesCustomInserter = 1,
|
||||||
GPR:$Rn, am2offset_reg:$offset))]>;
|
Constraints = "$Rn = $Rn_wb,@earlyclobber $Rn_wb" in {
|
||||||
def STRB_PRE_IMM : AI2stridx_imm<1, 1, (outs GPR:$Rn_wb),
|
def STRi_preidx: ARMPseudoInst<(outs GPR:$Rn_wb),
|
||||||
(ins GPR:$Rt, GPR:$Rn, am2offset_imm:$offset),
|
(ins GPR:$Rt, GPR:$Rn, am2offset_imm:$offset, pred:$p),
|
||||||
IndexModePre, StFrm, IIC_iStore_bh_ru,
|
4, IIC_iStore_ru,
|
||||||
"strb", "\t$Rt, [$Rn, $offset]!",
|
[(set GPR:$Rn_wb,
|
||||||
"$Rn = $Rn_wb,@earlyclobber $Rn_wb",
|
(pre_store GPR:$Rt, GPR:$Rn, am2offset_imm:$offset))]>;
|
||||||
[(set GPR:$Rn_wb, (pre_truncsti8 GPR:$Rt,
|
def STRr_preidx: ARMPseudoInst<(outs GPR:$Rn_wb),
|
||||||
GPR:$Rn, am2offset_imm:$offset))]>;
|
(ins GPR:$Rt, GPR:$Rn, am2offset_reg:$offset, pred:$p),
|
||||||
|
4, IIC_iStore_ru,
|
||||||
def STRB_POST_REG: AI2stridx_reg<1, 0, (outs GPR:$Rn_wb),
|
[(set GPR:$Rn_wb,
|
||||||
(ins GPR:$Rt, GPR:$Rn, am2offset_reg:$offset),
|
(pre_store GPR:$Rt, GPR:$Rn, am2offset_reg:$offset))]>;
|
||||||
IndexModePost, StFrm, IIC_iStore_bh_ru,
|
def STRBi_preidx: ARMPseudoInst<(outs GPR:$Rn_wb),
|
||||||
"strb", "\t$Rt, [$Rn], $offset",
|
(ins GPR:$Rt, GPR:$Rn, am2offset_imm:$offset, pred:$p),
|
||||||
"$Rn = $Rn_wb,@earlyclobber $Rn_wb",
|
4, IIC_iStore_ru,
|
||||||
[(set GPR:$Rn_wb, (post_truncsti8 GPR:$Rt,
|
[(set GPR:$Rn_wb,
|
||||||
GPR:$Rn, am2offset_reg:$offset))]>;
|
(pre_truncsti8 GPR:$Rt, GPR:$Rn, am2offset_imm:$offset))]>;
|
||||||
def STRB_POST_IMM: AI2stridx_imm<1, 0, (outs GPR:$Rn_wb),
|
def STRBr_preidx: ARMPseudoInst<(outs GPR:$Rn_wb),
|
||||||
(ins GPR:$Rt, GPR:$Rn, am2offset_imm:$offset),
|
(ins GPR:$Rt, GPR:$Rn, am2offset_reg:$offset, pred:$p),
|
||||||
IndexModePost, StFrm, IIC_iStore_bh_ru,
|
4, IIC_iStore_ru,
|
||||||
"strb", "\t$Rt, [$Rn], $offset",
|
[(set GPR:$Rn_wb,
|
||||||
"$Rn = $Rn_wb,@earlyclobber $Rn_wb",
|
(pre_truncsti8 GPR:$Rt, GPR:$Rn, am2offset_reg:$offset))]>;
|
||||||
[(set GPR:$Rn_wb, (post_truncsti8 GPR:$Rt,
|
}
|
||||||
GPR:$Rn, am2offset_imm:$offset))]>;
|
|
||||||
|
|
||||||
|
|
||||||
def STRH_PRE : AI3stridx<0b1011, 0, 1, (outs GPR:$Rn_wb),
|
def STRH_PRE : AI3stridx<0b1011, 0, 1, (outs GPR:$Rn_wb),
|
||||||
(ins GPR:$Rt, GPR:$Rn, am3offset:$offset),
|
(ins GPR:$Rt, GPR:$Rn, am3offset:$offset),
|
||||||
|
@ -894,7 +894,10 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineBasicBlock &MBB,
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
unsigned Offset = 0;
|
unsigned Offset = 0;
|
||||||
if (isAM2)
|
// FIXME: Loads still use a combined reg/imm offset operand. When
|
||||||
|
// AM2 refactoring is complete, this can go away and just always use
|
||||||
|
// the raw Offset value.
|
||||||
|
if (isAM2 && isLd)
|
||||||
Offset = ARM_AM::getAM2Opc(AddSub, Bytes, ARM_AM::no_shift);
|
Offset = ARM_AM::getAM2Opc(AddSub, Bytes, ARM_AM::no_shift);
|
||||||
else if (!isAM5)
|
else if (!isAM5)
|
||||||
Offset = AddSub == ARM_AM::sub ? -Bytes : Bytes;
|
Offset = AddSub == ARM_AM::sub ? -Bytes : Bytes;
|
||||||
@ -924,7 +927,10 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineBasicBlock &MBB,
|
|||||||
.addReg(Base).addImm(Offset).addImm(Pred).addReg(PredReg);
|
.addReg(Base).addImm(Offset).addImm(Pred).addReg(PredReg);
|
||||||
} else {
|
} else {
|
||||||
MachineOperand &MO = MI->getOperand(0);
|
MachineOperand &MO = MI->getOperand(0);
|
||||||
if (isAM2)
|
// FIXME: post-indexed stores use am2offset_imm, which still encodes
|
||||||
|
// the vestigal zero-reg offset register. When that's fixed, this clause
|
||||||
|
// can be removed entirely.
|
||||||
|
if (isAM2 && NewOpc == ARM::STR_POST_IMM)
|
||||||
// STR_PRE, STR_POST
|
// STR_PRE, STR_POST
|
||||||
BuildMI(MBB, MBBI, dl, TII->get(NewOpc), Base)
|
BuildMI(MBB, MBBI, dl, TII->get(NewOpc), Base)
|
||||||
.addReg(MO.getReg(), getKillRegState(MO.isKill()))
|
.addReg(MO.getReg(), getKillRegState(MO.isKill()))
|
||||||
|
Loading…
Reference in New Issue
Block a user