Skip to content
This repository was archived by the owner on Sep 2, 2018. It is now read-only.

Commit a2b5eb0

Browse files
author
Dylan McKay
committed
[AVR] Support 8 and 16-bit atomic loads and stores
1 parent e81447f commit a2b5eb0

File tree

3 files changed

+153
-5
lines changed

3 files changed

+153
-5
lines changed

lib/Target/AVR/AVRExpandPseudoInsts.cpp

+85-5
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "llvm/CodeGen/MachineFunctionPass.h"
1717
#include "llvm/CodeGen/MachineInstrBuilder.h"
18+
#include "llvm/CodeGen/MachineRegisterInfo.h"
1819
#include "llvm/Target/TargetRegisterInfo.h"
1920

2021
#include "AVR.h"
@@ -30,8 +31,15 @@ namespace llvm {
3031
class AVRExpandPseudo : public MachineFunctionPass {
3132
public:
3233
static char ID;
34+
3335
const AVRRegisterInfo *TRI;
3436
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+
3543
AVRExpandPseudo() : MachineFunctionPass(ID) {}
3644

3745
bool runOnMachineFunction(MachineFunction &MF) override;
@@ -57,6 +65,13 @@ class AVRExpandPseudo : public MachineFunctionPass {
5765
unsigned DstReg) {
5866
return BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(Opcode), DstReg);
5967
}
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+
bool expandAtomicBinaryOp(unsigned Opcode, Block &MBB, BlockIt MBBI);
6075
};
6176

6277
char AVRExpandPseudo::ID = 0;
@@ -80,9 +95,16 @@ bool AVRExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
8095
TRI = static_cast<const AVRRegisterInfo*>(TM.getSubtargetImpl()->getRegisterInfo());
8196
TII = TM.getSubtargetImpl()->getInstrInfo();
8297

83-
typedef MachineFunction::iterator FuncIt;
84-
for (FuncIt MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
85-
Modified |= expandMBB(*MFI);
98+
for(Block &MBB : MF) {
99+
bool ContinueExpanding = true;
100+
101+
// Continue expanding the block until all pseudos are expanded.
102+
do {
103+
bool BlockModified = expandMBB(MBB);
104+
Modified |= BlockModified;
105+
106+
ContinueExpanding = BlockModified;
107+
} while(ContinueExpanding);
86108
}
87109

88110
return Modified;
@@ -799,6 +821,60 @@ bool AVRExpandPseudo::expand<AVR::LDDWRdPtrQ>(Block &MBB, BlockIt MBBI) {
799821
return true;
800822
}
801823

824+
template<typename Func>
825+
bool AVRExpandPseudo::expandAtomic(Block &MBB, BlockIt MBBI, Func f) {
826+
// Remove the pseudo instruction.
827+
MachineInstr &MI = *MBBI;
828+
829+
// Store the SREG.
830+
buildMI(MBB, MBBI, AVR::INRdA)
831+
.addReg(SCRATCH_REGISTER, RegState::Define)
832+
.addImm(SREG_ADDR);
833+
834+
// Disable exceptions.
835+
buildMI(MBB, MBBI, AVR::BCLRs).addImm(7); // CLI
836+
837+
f(MI);
838+
839+
// Restore the status reg.
840+
buildMI(MBB, MBBI, AVR::OUTARr)
841+
.addImm(SREG_ADDR)
842+
.addReg(SCRATCH_REGISTER);
843+
844+
MI.eraseFromParent();
845+
return true;
846+
}
847+
848+
bool AVRExpandPseudo::expandAtomicBinaryOp(unsigned Opcode, Block &MBB, BlockIt MBBI) {
849+
return expandAtomic(MBB, MBBI, [&](MachineInstr &MI) {
850+
auto Op1 = MI.getOperand(0);
851+
auto Op2 = MI.getOperand(1);
852+
853+
buildMI(MBB, MBBI, Opcode).addOperand(Op1).addOperand(Op2);
854+
});
855+
}
856+
857+
template<>
858+
bool AVRExpandPseudo::expand<AVR::AtomicLoad8>(Block &MBB, BlockIt MBBI) {
859+
return expandAtomicBinaryOp(AVR::LDRdPtr, MBB, MBBI);
860+
}
861+
862+
863+
template<>
864+
bool AVRExpandPseudo::expand<AVR::AtomicLoad16>(Block &MBB, BlockIt MBBI) {
865+
return expandAtomicBinaryOp(AVR::LDWRdPtr, MBB, MBBI);
866+
}
867+
868+
template<>
869+
bool AVRExpandPseudo::expand<AVR::AtomicStore8>(Block &MBB, BlockIt MBBI) {
870+
return expandAtomicBinaryOp(AVR::STPtrRr, MBB, MBBI);
871+
}
872+
873+
template<>
874+
bool AVRExpandPseudo::expand<AVR::AtomicStore16>(Block &MBB, BlockIt MBBI) {
875+
return expandAtomicBinaryOp(AVR::STWPtrRr, MBB, MBBI);
876+
}
877+
802878
template <>
803879
bool AVRExpandPseudo::expand<AVR::STSWKRr>(Block &MBB, BlockIt MBBI) {
804880
MachineInstr &MI = *MBBI;
@@ -1305,7 +1381,7 @@ bool AVRExpandPseudo::expand<AVR::SPWRITE>(Block &MBB, BlockIt MBBI) {
13051381

13061382
buildMI(MBB, MBBI, AVR::INRdA)
13071383
.addReg(AVR::R0, RegState::Define)
1308-
.addImm(0x3f)
1384+
.addImm(SREG_ADDR)
13091385
.setMIFlags(Flags);
13101386

13111387
buildMI(MBB, MBBI, AVR::BCLRs).addImm(0x07).setMIFlags(Flags);
@@ -1316,7 +1392,7 @@ bool AVRExpandPseudo::expand<AVR::SPWRITE>(Block &MBB, BlockIt MBBI) {
13161392
.setMIFlags(Flags);
13171393

13181394
buildMI(MBB, MBBI, AVR::OUTARr)
1319-
.addImm(0x3f)
1395+
.addImm(SREG_ADDR)
13201396
.addReg(AVR::R0, RegState::Kill)
13211397
.setMIFlags(Flags);
13221398

@@ -1359,6 +1435,10 @@ bool AVRExpandPseudo::expandMI(Block &MBB, BlockIt MBBI) {
13591435
EXPAND(AVR::LDWRdPtrPd);
13601436
case AVR::LDDWRdYQ: //:FIXME: remove this once PR13375 gets fixed
13611437
EXPAND(AVR::LDDWRdPtrQ);
1438+
EXPAND(AVR::AtomicLoad8);
1439+
EXPAND(AVR::AtomicLoad16);
1440+
EXPAND(AVR::AtomicStore8);
1441+
EXPAND(AVR::AtomicStore16);
13621442
EXPAND(AVR::STSWKRr);
13631443
EXPAND(AVR::STWPtrRr);
13641444
EXPAND(AVR::STWPtrPiRr);

lib/Target/AVR/AVRInstrInfo.td

+22
Original file line numberDiff line numberDiff line change
@@ -1237,6 +1237,28 @@ isReMaterializable = 1 in
12371237
Requires<[HasSRAM]>;
12381238
}
12391239

1240+
def AtomicLoad8 : Pseudo<(outs GPR8:$rd),
1241+
(ins PTRREGS:$rr),
1242+
"atomic_load $rd, $rr",
1243+
[(set GPR8:$rd, (atomic_load i16:$rr))]>;
1244+
1245+
def AtomicLoad16 : Pseudo<(outs DREGS:$rd),
1246+
(ins PTRREGS:$rr),
1247+
"atomic_load $rd, $rr",
1248+
[(set DREGS:$rd, (atomic_load i16:$rr))]>;
1249+
1250+
def AtomicStore8 : Pseudo<(outs),
1251+
(ins LDSTPtrReg:$rd, GPR8:$rr),
1252+
"atomic_store $rd, $rr",
1253+
[(atomic_store i16:$rd, GPR8:$rr)]>,
1254+
Requires<[HasSRAM]>;
1255+
1256+
def AtomicStore16 : Pseudo<(outs),
1257+
(ins LDSTPtrReg:$rd, DREGS:$rr),
1258+
"atomic_store $rd, $rr",
1259+
[(atomic_store i16:$rd, DREGS:$rr)]>,
1260+
Requires<[HasSRAM]>;
1261+
12401262
// Indirect store from register to data space.
12411263
def STSKRr : F32DM<0b1,
12421264
(outs),

test/CodeGen/AVR/atomics.ll

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
; RUN: llc -mattr=avr6 < %s -march=avr | FileCheck %s
2+
3+
; Tests atomic operations on AVR
4+
5+
; CHECK-LABEL: atomic_load8
6+
; CHECK: in r0, 63
7+
; CHECK-NEXT: cli
8+
; CHECK-NEXT: ld [[RR:r[0-9]+]], [[RD:(X|Y|Z)]]
9+
; CHECK-NEXT: out 63, r0
10+
define i8 @atomic_load8(i8* %foo) {
11+
%val = load atomic i8, i8* %foo unordered, align 1
12+
ret i8 %val
13+
}
14+
15+
; CHECK-LABEL: atomic_load16
16+
; CHECK: in r0, 63
17+
; CHECK-NEXT: cli
18+
; CHECK-NEXT: ld [[RR:r[0-9]+]], [[RD:(X|Y|Z)]]
19+
; CHECK-NEXT: ldd [[RR:r[0-9]+]], [[RD:(X|Y|Z)]]+
20+
; CHECK-NEXT: out 63, r0
21+
define i16 @atomic_load16(i16* %foo) {
22+
%val = load atomic i16, i16* %foo unordered, align 2
23+
ret i16 %val
24+
}
25+
26+
; CHECK-LABEL: atomic_store8
27+
; CHECK: in r0, 63
28+
; CHECK-NEXT: cli
29+
; CHECK-NEXT: st [[RD:(X|Y|Z)]], [[RR:r[0-9]+]]
30+
; CHECK-NEXT: out 63, r0
31+
define void @atomic_store8(i8* %foo) {
32+
store atomic i8 1, i8* %foo unordered, align 1
33+
ret void
34+
}
35+
36+
; CHECK-LABEL: atomic_store16
37+
; CHECK: in r0, 63
38+
; CHECK-NEXT: cli
39+
; CHECK-NEXT: st [[RD:(X|Y|Z)]], [[RR:r[0-9]+]]
40+
; CHECK-NEXT: std [[RD:(X|Y|Z)]]+1, [[RR:r[0-9]+]]
41+
; CHECK-NEXT: out 63, r0
42+
define void @atomic_store16(i16* %foo) {
43+
store atomic i16 1, i16* %foo unordered, align 2
44+
ret void
45+
}
46+

0 commit comments

Comments
 (0)