Skip to content

Commit 634f5a7

Browse files
authored
Merge pull request #1 from gergoerdi/avr-rust-experiments
Experimental AVR target improvements
2 parents 110c682 + f3dcdf8 commit 634f5a7

8 files changed

+253
-36
lines changed

lib/Target/AVR/AVRExpandPseudoInsts.cpp

+108-5
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ class AVRExpandPseudo : public MachineFunctionPass {
7171

7272
MachineRegisterInfo &getRegInfo(Block &MBB) { return MBB.getParent()->getRegInfo(); }
7373

74+
bool expandBR(Block &MBB, BlockIt MBBI, int OppositeOpcode);
7475
bool expandArith(unsigned OpLo, unsigned OpHi, Block &MBB, BlockIt MBBI);
7576
bool expandLogic(unsigned Op, Block &MBB, BlockIt MBBI);
7677
bool expandLogicImm(unsigned Op, Block &MBB, BlockIt MBBI);
@@ -583,8 +584,8 @@ bool AVRExpandPseudo::expand<AVR::LDWRdPtr>(Block &MBB, BlockIt MBBI) {
583584
unsigned TmpReg = 0; // 0 for no temporary register
584585
unsigned SrcReg = MI.getOperand(1).getReg();
585586
bool SrcIsKill = MI.getOperand(1).isKill();
586-
OpLo = AVR::LDRdPtr;
587-
OpHi = AVR::LDDRdPtrQ;
587+
OpLo = AVR::LDRdPtrPi;
588+
OpHi = AVR::LDRdPtr;
588589
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
589590

590591
// Use a temporary register if src and dst registers are the same.
@@ -597,6 +598,7 @@ bool AVRExpandPseudo::expand<AVR::LDWRdPtr>(Block &MBB, BlockIt MBBI) {
597598
// Load low byte.
598599
auto MIBLO = buildMI(MBB, MBBI, OpLo)
599600
.addReg(CurDstLoReg, RegState::Define)
601+
.addReg(SrcReg, RegState::Define)
600602
.addReg(SrcReg);
601603

602604
// Push low byte onto stack if necessary.
@@ -606,8 +608,7 @@ bool AVRExpandPseudo::expand<AVR::LDWRdPtr>(Block &MBB, BlockIt MBBI) {
606608
// Load high byte.
607609
auto MIBHI = buildMI(MBB, MBBI, OpHi)
608610
.addReg(CurDstHiReg, RegState::Define)
609-
.addReg(SrcReg, getKillRegState(SrcIsKill))
610-
.addImm(1);
611+
.addReg(SrcReg, getKillRegState(SrcIsKill));
611612

612613
if (TmpReg) {
613614
// Move the high byte into the final destination.
@@ -741,7 +742,50 @@ bool AVRExpandPseudo::expand<AVR::LDDWRdPtrQ>(Block &MBB, BlockIt MBBI) {
741742

742743
template <>
743744
bool AVRExpandPseudo::expand<AVR::LPMWRdZ>(Block &MBB, BlockIt MBBI) {
744-
llvm_unreachable("wide LPM is unimplemented");
745+
MachineInstr &MI = *MBBI;
746+
unsigned OpLo, OpHi, DstLoReg, DstHiReg;
747+
unsigned DstReg = MI.getOperand(0).getReg();
748+
unsigned TmpReg = 0; // 0 for no temporary register
749+
unsigned SrcReg = MI.getOperand(1).getReg();
750+
bool SrcIsKill = MI.getOperand(1).isKill();
751+
OpLo = AVR::LPMRdZPi;
752+
OpHi = AVR::LPMRdZ;
753+
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
754+
755+
// Use a temporary register if src and dst registers are the same.
756+
if (DstReg == SrcReg)
757+
TmpReg = scavengeGPR8(MI);
758+
759+
unsigned CurDstLoReg = (DstReg == SrcReg) ? TmpReg : DstLoReg;
760+
unsigned CurDstHiReg = (DstReg == SrcReg) ? TmpReg : DstHiReg;
761+
762+
// Load low byte.
763+
auto MIBLO = buildMI(MBB, MBBI, OpLo)
764+
.addReg(CurDstLoReg, RegState::Define)
765+
.addReg(SrcReg);
766+
767+
// Push low byte onto stack if necessary.
768+
if (TmpReg)
769+
buildMI(MBB, MBBI, AVR::PUSHRr).addReg(TmpReg);
770+
771+
// Load high byte.
772+
auto MIBHI = buildMI(MBB, MBBI, OpHi)
773+
.addReg(CurDstHiReg, RegState::Define)
774+
.addReg(SrcReg, getKillRegState(SrcIsKill));
775+
776+
if (TmpReg) {
777+
// Move the high byte into the final destination.
778+
buildMI(MBB, MBBI, AVR::MOVRdRr).addReg(DstHiReg).addReg(TmpReg);
779+
780+
// Move the low byte from the scratch space into the final destination.
781+
buildMI(MBB, MBBI, AVR::POPRd).addReg(DstLoReg);
782+
}
783+
784+
MIBLO->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
785+
MIBHI->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
786+
787+
MI.eraseFromParent();
788+
return true;
745789
}
746790

747791
template <>
@@ -1457,6 +1501,57 @@ bool AVRExpandPseudo::expand<AVR::SPWRITE>(Block &MBB, BlockIt MBBI) {
14571501
return true;
14581502
}
14591503

1504+
bool AVRExpandPseudo::expandBR(Block &MBB, BlockIt MBBI, int OppositeOpcode) {
1505+
MachineInstr &MI = *MBBI;
1506+
MachineBasicBlock *targetMBB = MI.getOperand(0).getMBB();
1507+
1508+
buildMI(MBB, MBBI, OppositeOpcode).addImm(2);
1509+
buildMI(MBB, MBBI, AVR::RJMPk).addMBB(targetMBB);
1510+
1511+
MI.eraseFromParent();
1512+
return true;
1513+
}
1514+
1515+
template <>
1516+
bool AVRExpandPseudo::expand<AVR::RBRGEk>(Block &MBB, BlockIt MBBI) {
1517+
return expandBR(MBB, MBBI, AVR::BRLTk);
1518+
}
1519+
1520+
template <>
1521+
bool AVRExpandPseudo::expand<AVR::RBRLTk>(Block &MBB, BlockIt MBBI) {
1522+
return expandBR(MBB, MBBI, AVR::BRGEk);
1523+
}
1524+
1525+
template <>
1526+
bool AVRExpandPseudo::expand<AVR::RBREQk>(Block &MBB, BlockIt MBBI) {
1527+
return expandBR(MBB, MBBI, AVR::BRNEk);
1528+
}
1529+
1530+
template <>
1531+
bool AVRExpandPseudo::expand<AVR::RBRNEk>(Block &MBB, BlockIt MBBI) {
1532+
return expandBR(MBB, MBBI, AVR::BREQk);
1533+
}
1534+
1535+
template <>
1536+
bool AVRExpandPseudo::expand<AVR::RBRSHk>(Block &MBB, BlockIt MBBI) {
1537+
return expandBR(MBB, MBBI, AVR::BRLOk);
1538+
}
1539+
1540+
template <>
1541+
bool AVRExpandPseudo::expand<AVR::RBRLOk>(Block &MBB, BlockIt MBBI) {
1542+
return expandBR(MBB, MBBI, AVR::BRSHk);
1543+
}
1544+
1545+
template <>
1546+
bool AVRExpandPseudo::expand<AVR::RBRPLk>(Block &MBB, BlockIt MBBI) {
1547+
return expandBR(MBB, MBBI, AVR::BRMIk);
1548+
}
1549+
1550+
template <>
1551+
bool AVRExpandPseudo::expand<AVR::RBRMIk>(Block &MBB, BlockIt MBBI) {
1552+
return expandBR(MBB, MBBI, AVR::BRPLk);
1553+
}
1554+
14601555
bool AVRExpandPseudo::expandMI(Block &MBB, BlockIt MBBI) {
14611556
MachineInstr &MI = *MBBI;
14621557
int Opcode = MBBI->getOpcode();
@@ -1522,6 +1617,14 @@ bool AVRExpandPseudo::expandMI(Block &MBB, BlockIt MBBI) {
15221617
EXPAND(AVR::ZEXT);
15231618
EXPAND(AVR::SPREAD);
15241619
EXPAND(AVR::SPWRITE);
1620+
EXPAND(AVR::RBRGEk);
1621+
EXPAND(AVR::RBRLTk);
1622+
EXPAND(AVR::RBREQk);
1623+
EXPAND(AVR::RBRNEk);
1624+
EXPAND(AVR::RBRSHk);
1625+
EXPAND(AVR::RBRLOk);
1626+
EXPAND(AVR::RBRMIk);
1627+
EXPAND(AVR::RBRPLk);
15251628
}
15261629
#undef EXPAND
15271630
return false;

lib/Target/AVR/AVRISelLowering.cpp

+21-10
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ const char *AVRTargetLowering::getTargetNodeName(unsigned Opcode) const {
236236
NODE(RETI_FLAG);
237237
NODE(CALL);
238238
NODE(WRAPPER);
239+
NODE(PROGMEM_WRAPPER);
239240
NODE(LSL);
240241
NODE(LSR);
241242
NODE(ROL);
@@ -245,6 +246,7 @@ const char *AVRTargetLowering::getTargetNodeName(unsigned Opcode) const {
245246
NODE(LSRLOOP);
246247
NODE(ASRLOOP);
247248
NODE(BRCOND);
249+
NODE(RBRCOND);
248250
NODE(CMP);
249251
NODE(CMPC);
250252
NODE(TST);
@@ -380,13 +382,20 @@ SDValue AVRTargetLowering::LowerGlobalAddress(SDValue Op,
380382
SelectionDAG &DAG) const {
381383
auto DL = DAG.getDataLayout();
382384

383-
const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
385+
const auto *GA = cast<GlobalAddressSDNode>(Op);
386+
const GlobalValue *GV = GA->getGlobal();
387+
388+
unsigned Wrapper = AVRISD::WRAPPER;
389+
if (const auto *GVar = dyn_cast<GlobalVariable>(GV))
390+
if (GVar->isConstant())
391+
Wrapper = AVRISD::PROGMEM_WRAPPER;
392+
384393
int64_t Offset = cast<GlobalAddressSDNode>(Op)->getOffset();
385394

386395
// Create the TargetGlobalAddress node, folding in the constant offset.
387396
SDValue Result =
388397
DAG.getTargetGlobalAddress(GV, SDLoc(Op), getPointerTy(DL), Offset);
389-
return DAG.getNode(AVRISD::WRAPPER, SDLoc(Op), getPointerTy(DL), Result);
398+
return DAG.getNode(Wrapper, SDLoc(Op), getPointerTy(DL), Result);
390399
}
391400

392401
SDValue AVRTargetLowering::LowerBlockAddress(SDValue Op,
@@ -608,7 +617,7 @@ SDValue AVRTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const {
608617
SDValue TargetCC;
609618
SDValue Cmp = getAVRCmp(LHS, RHS, CC, TargetCC, DAG, dl);
610619

611-
return DAG.getNode(AVRISD::BRCOND, dl, MVT::Other, Chain, Dest, TargetCC,
620+
return DAG.getNode(AVRISD::RBRCOND, dl, MVT::Other, Chain, Dest, TargetCC,
612621
Cmp);
613622
}
614623

@@ -1470,8 +1479,10 @@ MachineBasicBlock *AVRTargetLowering::insertShift(MachineInstr &MI,
14701479
}
14711480

14721481
const BasicBlock *LLVM_BB = BB->getBasicBlock();
1473-
MachineFunction::iterator I = BB->getParent()->begin();
1474-
++I;
1482+
1483+
MachineFunction::iterator I;
1484+
for (I = F->begin(); I != F->end() && &(*I) != BB; ++I);
1485+
if (I != F->end()) ++I;
14751486

14761487
// Create loop block.
14771488
MachineBasicBlock *LoopBB = F->CreateMachineBasicBlock(LLVM_BB);
@@ -1501,9 +1512,9 @@ MachineBasicBlock *AVRTargetLowering::insertShift(MachineInstr &MI,
15011512
unsigned DstReg = MI.getOperand(0).getReg();
15021513

15031514
// BB:
1504-
// cp 0, N
1515+
// cpi N, 0
15051516
// breq RemBB
1506-
BuildMI(BB, dl, TII.get(AVR::CPRdRr)).addReg(ShiftAmtSrcReg).addReg(AVR::R0);
1517+
BuildMI(BB, dl, TII.get(AVR::CPIRdK)).addReg(ShiftAmtSrcReg).addImm(0);
15071518
BuildMI(BB, dl, TII.get(AVR::BREQk)).addMBB(RemBB);
15081519

15091520
// LoopBB:
@@ -1611,8 +1622,9 @@ AVRTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
16111622
MachineBasicBlock *trueMBB = MF->CreateMachineBasicBlock(LLVM_BB);
16121623
MachineBasicBlock *falseMBB = MF->CreateMachineBasicBlock(LLVM_BB);
16131624

1614-
MachineFunction::iterator I = MBB->getParent()->begin();
1615-
++I;
1625+
MachineFunction::iterator I;
1626+
for (I = MF->begin(); I != MF->end() && &(*I) != MBB; ++I);
1627+
if (I != MF->end()) ++I;
16161628
MF->insert(I, trueMBB);
16171629
MF->insert(I, falseMBB);
16181630

@@ -2014,4 +2026,3 @@ unsigned AVRTargetLowering::getRegisterByName(const char *RegName,
20142026
}
20152027

20162028
} // end of namespace llvm
2017-

lib/Target/AVR/AVRISelLowering.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ enum NodeType {
3636
/// A wrapper node for TargetConstantPool,
3737
/// TargetExternalSymbol, and TargetGlobalAddress.
3838
WRAPPER,
39+
PROGMEM_WRAPPER,
3940
LSL, ///< Logical shift left.
4041
LSR, ///< Logical shift right.
4142
ASR, ///< Arithmetic shift right.
@@ -50,7 +51,7 @@ enum NodeType {
5051
/// is the block to branch if condition is true, operand 2 is the
5152
/// condition code, and operand 3 is the flag operand produced by a CMP
5253
/// or TEST instruction.
53-
BRCOND,
54+
BRCOND, RBRCOND,
5455
/// Compare instruction.
5556
CMP,
5657
/// Compare with carry instruction.

lib/Target/AVR/AVRInstrInfo.cpp

+16-8
Original file line numberDiff line numberDiff line change
@@ -197,21 +197,21 @@ const MCInstrDesc &AVRInstrInfo::getBrCond(AVRCC::CondCodes CC) const {
197197
default:
198198
llvm_unreachable("Unknown condition code!");
199199
case AVRCC::COND_EQ:
200-
return get(AVR::BREQk);
200+
return get(AVR::RBREQk);
201201
case AVRCC::COND_NE:
202-
return get(AVR::BRNEk);
202+
return get(AVR::RBRNEk);
203203
case AVRCC::COND_GE:
204-
return get(AVR::BRGEk);
204+
return get(AVR::RBRGEk);
205205
case AVRCC::COND_LT:
206-
return get(AVR::BRLTk);
206+
return get(AVR::RBRLTk);
207207
case AVRCC::COND_SH:
208-
return get(AVR::BRSHk);
208+
return get(AVR::RBRSHk);
209209
case AVRCC::COND_LO:
210-
return get(AVR::BRLOk);
210+
return get(AVR::RBRLOk);
211211
case AVRCC::COND_MI:
212-
return get(AVR::BRMIk);
212+
return get(AVR::RBRMIk);
213213
case AVRCC::COND_PL:
214-
return get(AVR::BRPLk);
214+
return get(AVR::RBRPLk);
215215
}
216216
}
217217

@@ -220,20 +220,28 @@ AVRCC::CondCodes AVRInstrInfo::getCondFromBranchOpc(unsigned Opc) const {
220220
default:
221221
return AVRCC::COND_INVALID;
222222
case AVR::BREQk:
223+
case AVR::RBREQk:
223224
return AVRCC::COND_EQ;
224225
case AVR::BRNEk:
226+
case AVR::RBRNEk:
225227
return AVRCC::COND_NE;
226228
case AVR::BRSHk:
229+
case AVR::RBRSHk:
227230
return AVRCC::COND_SH;
228231
case AVR::BRLOk:
232+
case AVR::RBRLOk:
229233
return AVRCC::COND_LO;
230234
case AVR::BRMIk:
235+
case AVR::RBRMIk:
231236
return AVRCC::COND_MI;
232237
case AVR::BRPLk:
238+
case AVR::RBRPLk:
233239
return AVRCC::COND_PL;
234240
case AVR::BRGEk:
241+
case AVR::RBRGEk:
235242
return AVRCC::COND_GE;
236243
case AVR::BRLTk:
244+
case AVR::RBRLTk:
237245
return AVRCC::COND_LT;
238246
}
239247
}

0 commit comments

Comments
 (0)