15
15
16
16
#include " llvm/CodeGen/MachineFunctionPass.h"
17
17
#include " llvm/CodeGen/MachineInstrBuilder.h"
18
+ #include " llvm/CodeGen/MachineRegisterInfo.h"
18
19
#include " llvm/Target/TargetRegisterInfo.h"
19
20
20
21
#include " AVR.h"
@@ -30,8 +31,15 @@ namespace llvm {
30
31
class AVRExpandPseudo : public MachineFunctionPass {
31
32
public:
32
33
static char ID;
34
+
33
35
const AVRRegisterInfo *TRI;
34
36
const TargetInstrInfo *TII;
37
+
38
+ // / The register to be used for temporary storage.
39
+ const unsigned SCRATCH_REGISTER = AVR::R0;
40
+ // / The IO address of the status register.
41
+ const unsigned SREG_ADDR = 0x3f ;
42
+
35
43
AVRExpandPseudo () : MachineFunctionPass(ID) {}
36
44
37
45
bool runOnMachineFunction (MachineFunction &MF) override ;
@@ -57,6 +65,21 @@ class AVRExpandPseudo : public MachineFunctionPass {
57
65
unsigned DstReg) {
58
66
return BuildMI (MBB, MBBI, MBBI->getDebugLoc (), TII->get (Opcode), DstReg);
59
67
}
68
+
69
+ MachineRegisterInfo &getRegInfo (Block &MBB) { return MBB.getParent ()->getRegInfo (); }
70
+
71
+ template <typename Func>
72
+ bool expandAtomic (Block &MBB, BlockIt MBBI, Func f);
73
+
74
+ template <typename Func>
75
+ bool expandAtomicBinaryOp (unsigned Opcode, Block &MBB, BlockIt MBBI, Func f);
76
+
77
+ bool expandAtomicBinaryOp (unsigned Opcode, Block &MBB, BlockIt MBBI);
78
+
79
+ bool expandAtomicArithmeticOp (unsigned MemOpcode,
80
+ unsigned ArithOpcode,
81
+ Block &MBB,
82
+ BlockIt MBBI);
60
83
};
61
84
62
85
char AVRExpandPseudo::ID = 0 ;
@@ -80,9 +103,20 @@ bool AVRExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
80
103
TRI = static_cast <const AVRRegisterInfo*>(TM.getSubtargetImpl ()->getRegisterInfo ());
81
104
TII = TM.getSubtargetImpl ()->getInstrInfo ();
82
105
83
- typedef MachineFunction::iterator FuncIt;
84
- for (FuncIt MFI = MF.begin (), E = MF.end (); MFI != E; ++MFI) {
85
- Modified |= expandMBB (*MFI);
106
+ for (Block &MBB : MF) {
107
+ bool ContinueExpanding = true ;
108
+ unsigned ExpandCount = 0 ;
109
+
110
+ // Continue expanding the block until all pseudos are expanded.
111
+ do {
112
+ assert (ExpandCount < 10 && " pseudo expand limit reached" );
113
+
114
+ bool BlockModified = expandMBB (MBB);
115
+ Modified |= BlockModified;
116
+ ExpandCount++;
117
+
118
+ ContinueExpanding = BlockModified;
119
+ } while (ContinueExpanding);
86
120
}
87
121
88
122
return Modified;
@@ -799,6 +833,146 @@ bool AVRExpandPseudo::expand<AVR::LDDWRdPtrQ>(Block &MBB, BlockIt MBBI) {
799
833
return true ;
800
834
}
801
835
836
+ template <typename Func>
837
+ bool AVRExpandPseudo::expandAtomic (Block &MBB, BlockIt MBBI, Func f) {
838
+ // Remove the pseudo instruction.
839
+ MachineInstr &MI = *MBBI;
840
+
841
+ // Store the SREG.
842
+ buildMI (MBB, MBBI, AVR::INRdA)
843
+ .addReg (SCRATCH_REGISTER, RegState::Define)
844
+ .addImm (SREG_ADDR);
845
+
846
+ // Disable exceptions.
847
+ buildMI (MBB, MBBI, AVR::BCLRs).addImm (7 ); // CLI
848
+
849
+ f (MI);
850
+
851
+ // Restore the status reg.
852
+ buildMI (MBB, MBBI, AVR::OUTARr)
853
+ .addImm (SREG_ADDR)
854
+ .addReg (SCRATCH_REGISTER);
855
+
856
+ MI.eraseFromParent ();
857
+ return true ;
858
+ }
859
+
860
+ template <typename Func>
861
+ bool AVRExpandPseudo::expandAtomicBinaryOp (unsigned Opcode, Block &MBB, BlockIt MBBI, Func f) {
862
+ return expandAtomic (MBB, MBBI, [&](MachineInstr &MI) {
863
+ auto Op1 = MI.getOperand (0 );
864
+ auto Op2 = MI.getOperand (1 );
865
+
866
+ MachineInstr &NewInst = *buildMI (MBB, MBBI, Opcode).addOperand (Op1).addOperand (Op2).getInstr ();
867
+
868
+ f (NewInst);
869
+ });
870
+ }
871
+
872
+ bool AVRExpandPseudo::expandAtomicBinaryOp (unsigned Opcode, Block &MBB, BlockIt MBBI) {
873
+ return expandAtomicBinaryOp (Opcode, MBB, MBBI, [](MachineInstr &MI) {});
874
+ }
875
+
876
+ bool AVRExpandPseudo::expandAtomicArithmeticOp (unsigned Width,
877
+ unsigned ArithOpcode,
878
+ Block &MBB,
879
+ BlockIt MBBI) {
880
+
881
+ return expandAtomic (MBB, MBBI, [&](MachineInstr &MI) {
882
+ auto Op1 = MI.getOperand (0 );
883
+ auto Op2 = MI.getOperand (1 );
884
+
885
+ unsigned LoadOpcode = (Width == 8 ) ? AVR::LDRdPtr : AVR::LDWRdPtr;
886
+ unsigned StoreOpcode = (Width == 8 ) ? AVR::STPtrRr : AVR::STWPtrRr;
887
+
888
+ // Create the load
889
+ buildMI (MBB, MBBI, LoadOpcode).addOperand (Op1).addOperand (Op2);
890
+
891
+ // Create the arithmetic op
892
+ buildMI (MBB, MBBI, ArithOpcode).addOperand (Op1).addOperand (Op1).addOperand (Op2);
893
+
894
+ // Create the store
895
+ buildMI (MBB, MBBI, StoreOpcode).addOperand (Op2).addOperand (Op1);
896
+ });
897
+ }
898
+
899
+ template <>
900
+ bool AVRExpandPseudo::expand<AVR::AtomicLoad8>(Block &MBB, BlockIt MBBI) {
901
+ return expandAtomicBinaryOp (AVR::LDRdPtr, MBB, MBBI);
902
+ }
903
+
904
+ template <>
905
+ bool AVRExpandPseudo::expand<AVR::AtomicLoad16>(Block &MBB, BlockIt MBBI) {
906
+ return expandAtomicBinaryOp (AVR::LDWRdPtr, MBB, MBBI);
907
+ }
908
+
909
+ template <>
910
+ bool AVRExpandPseudo::expand<AVR::AtomicStore8>(Block &MBB, BlockIt MBBI) {
911
+ return expandAtomicBinaryOp (AVR::STPtrRr, MBB, MBBI);
912
+ }
913
+
914
+ template <>
915
+ bool AVRExpandPseudo::expand<AVR::AtomicStore16>(Block &MBB, BlockIt MBBI) {
916
+ return expandAtomicBinaryOp (AVR::STWPtrRr, MBB, MBBI);
917
+ }
918
+
919
+ template <>
920
+ bool AVRExpandPseudo::expand<AVR::AtomicLoadAdd8>(Block &MBB, BlockIt MBBI) {
921
+ return expandAtomicArithmeticOp (8 , AVR::ADDRdRr, MBB, MBBI);
922
+ }
923
+
924
+ template <>
925
+ bool AVRExpandPseudo::expand<AVR::AtomicLoadAdd16>(Block &MBB, BlockIt MBBI) {
926
+ return expandAtomicArithmeticOp (16 , AVR::ADDWRdRr, MBB, MBBI);
927
+ }
928
+
929
+ template <>
930
+ bool AVRExpandPseudo::expand<AVR::AtomicLoadSub8>(Block &MBB, BlockIt MBBI) {
931
+ return expandAtomicArithmeticOp (8 , AVR::SUBRdRr, MBB, MBBI);
932
+ }
933
+
934
+ template <>
935
+ bool AVRExpandPseudo::expand<AVR::AtomicLoadSub16>(Block &MBB, BlockIt MBBI) {
936
+ return expandAtomicArithmeticOp (16 , AVR::SUBWRdRr, MBB, MBBI);
937
+ }
938
+
939
+ template <>
940
+ bool AVRExpandPseudo::expand<AVR::AtomicLoadAnd8>(Block &MBB, BlockIt MBBI) {
941
+ return expandAtomicArithmeticOp (8 , AVR::ANDRdRr, MBB, MBBI);
942
+ }
943
+
944
+ template <>
945
+ bool AVRExpandPseudo::expand<AVR::AtomicLoadAnd16>(Block &MBB, BlockIt MBBI) {
946
+ return expandAtomicArithmeticOp (16 , AVR::ANDWRdRr, MBB, MBBI);
947
+ }
948
+
949
+ template <>
950
+ bool AVRExpandPseudo::expand<AVR::AtomicLoadOr8>(Block &MBB, BlockIt MBBI) {
951
+ return expandAtomicArithmeticOp (8 , AVR::ORRdRr, MBB, MBBI);
952
+ }
953
+
954
+ template <>
955
+ bool AVRExpandPseudo::expand<AVR::AtomicLoadOr16>(Block &MBB, BlockIt MBBI) {
956
+ return expandAtomicArithmeticOp (16 , AVR::ORWRdRr, MBB, MBBI);
957
+ }
958
+
959
+ template <>
960
+ bool AVRExpandPseudo::expand<AVR::AtomicLoadXor8>(Block &MBB, BlockIt MBBI) {
961
+ return expandAtomicArithmeticOp (8 , AVR::EORRdRr, MBB, MBBI);
962
+ }
963
+
964
+ template <>
965
+ bool AVRExpandPseudo::expand<AVR::AtomicLoadXor16>(Block &MBB, BlockIt MBBI) {
966
+ return expandAtomicArithmeticOp (16 , AVR::EORWRdRr, MBB, MBBI);
967
+ }
968
+
969
+ template <>
970
+ bool AVRExpandPseudo::expand<AVR::AtomicFence>(Block &MBB, BlockIt MBBI) {
971
+ // On AVR, there is only one core and so atomic fences do nothing.
972
+ MBBI->eraseFromParent ();
973
+ return true ;
974
+ }
975
+
802
976
template <>
803
977
bool AVRExpandPseudo::expand<AVR::STSWKRr>(Block &MBB, BlockIt MBBI) {
804
978
MachineInstr &MI = *MBBI;
@@ -1305,7 +1479,7 @@ bool AVRExpandPseudo::expand<AVR::SPWRITE>(Block &MBB, BlockIt MBBI) {
1305
1479
1306
1480
buildMI (MBB, MBBI, AVR::INRdA)
1307
1481
.addReg (AVR::R0, RegState::Define)
1308
- .addImm (0x3f )
1482
+ .addImm (SREG_ADDR )
1309
1483
.setMIFlags (Flags);
1310
1484
1311
1485
buildMI (MBB, MBBI, AVR::BCLRs).addImm (0x07 ).setMIFlags (Flags);
@@ -1316,7 +1490,7 @@ bool AVRExpandPseudo::expand<AVR::SPWRITE>(Block &MBB, BlockIt MBBI) {
1316
1490
.setMIFlags (Flags);
1317
1491
1318
1492
buildMI (MBB, MBBI, AVR::OUTARr)
1319
- .addImm (0x3f )
1493
+ .addImm (SREG_ADDR )
1320
1494
.addReg (AVR::R0, RegState::Kill)
1321
1495
.setMIFlags (Flags);
1322
1496
@@ -1359,6 +1533,21 @@ bool AVRExpandPseudo::expandMI(Block &MBB, BlockIt MBBI) {
1359
1533
EXPAND (AVR::LDWRdPtrPd);
1360
1534
case AVR::LDDWRdYQ: // :FIXME: remove this once PR13375 gets fixed
1361
1535
EXPAND (AVR::LDDWRdPtrQ);
1536
+ EXPAND (AVR::AtomicLoad8);
1537
+ EXPAND (AVR::AtomicLoad16);
1538
+ EXPAND (AVR::AtomicStore8);
1539
+ EXPAND (AVR::AtomicStore16);
1540
+ EXPAND (AVR::AtomicLoadAdd8);
1541
+ EXPAND (AVR::AtomicLoadAdd16);
1542
+ EXPAND (AVR::AtomicLoadSub8);
1543
+ EXPAND (AVR::AtomicLoadSub16);
1544
+ EXPAND (AVR::AtomicLoadAnd8);
1545
+ EXPAND (AVR::AtomicLoadAnd16);
1546
+ EXPAND (AVR::AtomicLoadOr8);
1547
+ EXPAND (AVR::AtomicLoadOr16);
1548
+ EXPAND (AVR::AtomicLoadXor8);
1549
+ EXPAND (AVR::AtomicLoadXor16);
1550
+ EXPAND (AVR::AtomicFence);
1362
1551
EXPAND (AVR::STSWKRr);
1363
1552
EXPAND (AVR::STWPtrRr);
1364
1553
EXPAND (AVR::STWPtrPiRr);
0 commit comments