diff options
| author | Daniel Sanders <daniel.sanders@imgtec.com> | 2016-05-12 14:01:50 +0000 |
|---|---|---|
| committer | Daniel Sanders <daniel.sanders@imgtec.com> | 2016-05-12 14:01:50 +0000 |
| commit | 241c67989b24acccd5ff230cab6291a5e19bd32d (patch) | |
| tree | d15c0a6713e1468655503792d95d46425a0850ae | |
| parent | 5fb391c893073547f546a88f461a0de15924c55b (diff) | |
| download | bcm5719-llvm-241c67989b24acccd5ff230cab6291a5e19bd32d.tar.gz bcm5719-llvm-241c67989b24acccd5ff230cab6291a5e19bd32d.zip | |
[mips][ias] Fix O32 .cprestore directive when inside .set noat region and offset is in range.
Summary:
This expands on r269179 to fix an additional case that was not covered by our
tests. The assembler temporary is not needed when the .cprestore offset fits
inside a simm16 and it is not an error to use it inside a '.set noat' in this
case.
Reviewers: emaste, seanbruno, sdardis
Subscribers: dsanders, sdardis, llvm-commits
Differential Revision: http://reviews.llvm.org/D20199
llvm-svn: 269295
| -rw-r--r-- | llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 19 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp | 13 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MipsTargetStreamer.h | 21 | ||||
| -rw-r--r-- | llvm/test/MC/Mips/cprestore-noreorder-noat.s | 21 |
4 files changed, 54 insertions, 20 deletions
diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index f7fd72fd27f..128cef7bc8d 100644 --- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -2633,16 +2633,17 @@ void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, unsigned SrcReg = Inst.getOperand(0).getReg(); unsigned BaseReg = Inst.getOperand(1).getReg(); - unsigned ATReg = getATReg(IDLoc); - if (!ATReg) - return; - if (IsImmOpnd) { TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg, - Inst.getOperand(2).getImm(), ATReg, IDLoc, STI); + Inst.getOperand(2).getImm(), + [&]() { return getATReg(IDLoc); }, IDLoc, STI); return; } + unsigned ATReg = getATReg(IDLoc); + if (!ATReg) + return; + const MCExpr *ExprOffset = Inst.getOperand(2).getExpr(); MCOperand LoOperand = MCOperand::createExpr( MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext())); @@ -3626,12 +3627,8 @@ void MipsAsmParser::createCpRestoreMemOp(bool IsLoad, int StackOffset, return; } - unsigned ATReg = getATReg(IDLoc); - if (!ATReg) - return; - - TOut.emitStoreWithImmOffset(Mips::SW, Mips::GP, Mips::SP, StackOffset, ATReg, - IDLoc, STI); + TOut.emitStoreWithImmOffset(Mips::SW, Mips::GP, Mips::SP, StackOffset, + [&]() { return getATReg(IDLoc); }, IDLoc, STI); } unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) { diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp index c9e240c7fb3..c6bb84d3b02 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp @@ -228,7 +228,8 @@ void MipsTargetStreamer::emitGPRestore(int Offset, SMLoc IDLoc, /// Emit a store instruction with an immediate offset. void MipsTargetStreamer::emitStoreWithImmOffset( unsigned Opcode, unsigned SrcReg, unsigned BaseReg, int64_t Offset, - unsigned ATReg, SMLoc IDLoc, const MCSubtargetInfo *STI) { + std::function<unsigned()> GetATReg, SMLoc IDLoc, + const MCSubtargetInfo *STI) { if (isInt<16>(Offset)) { emitRRI(Opcode, SrcReg, BaseReg, Offset, IDLoc, STI); return; @@ -238,6 +239,10 @@ void MipsTargetStreamer::emitStoreWithImmOffset( // add $at, $at, $8 // sw $8, %lo(offset)($at) + unsigned ATReg = GetATReg(); + if (!ATReg) + return; + unsigned LoOffset = Offset & 0x0000ffff; unsigned HiOffset = (Offset & 0xffff0000) >> 16; @@ -1055,12 +1060,8 @@ bool MipsTargetELFStreamer::emitDirectiveCpRestore( if (!Pic || (getABI().IsN32() || getABI().IsN64())) return true; - unsigned ATReg = GetATReg(); - if (!ATReg) - return false; - // Store the $gp on the stack. - emitStoreWithImmOffset(Mips::SW, Mips::GP, Mips::SP, Offset, ATReg, IDLoc, + emitStoreWithImmOffset(Mips::SW, Mips::GP, Mips::SP, Offset, GetATReg, IDLoc, STI); return true; } diff --git a/llvm/lib/Target/Mips/MipsTargetStreamer.h b/llvm/lib/Target/Mips/MipsTargetStreamer.h index c0b3c443f97..d418f80916b 100644 --- a/llvm/lib/Target/Mips/MipsTargetStreamer.h +++ b/llvm/lib/Target/Mips/MipsTargetStreamer.h @@ -122,9 +122,18 @@ public: void emitEmptyDelaySlot(bool hasShortDelaySlot, SMLoc IDLoc, const MCSubtargetInfo *STI); void emitNop(SMLoc IDLoc, const MCSubtargetInfo *STI); + + /// Emit a store instruction with an offset. If the offset is out of range + /// then it will be synthesized using the assembler temporary. + /// + /// GetATReg() is a callback that can be used to obtain the current assembler + /// temporary and is only called when the assembler temporary is required. It + /// must handle the case where no assembler temporary is available (typically + /// by reporting an error). void emitStoreWithImmOffset(unsigned Opcode, unsigned SrcReg, - unsigned BaseReg, int64_t Offset, unsigned ATReg, - SMLoc IDLoc, const MCSubtargetInfo *STI); + unsigned BaseReg, int64_t Offset, + std::function<unsigned()> GetATReg, SMLoc IDLoc, + const MCSubtargetInfo *STI); void emitStoreWithSymOffset(unsigned Opcode, unsigned SrcReg, unsigned BaseReg, MCOperand &HiOperand, MCOperand &LoOperand, unsigned ATReg, SMLoc IDLoc, @@ -237,6 +246,14 @@ public: // PIC support void emitDirectiveCpLoad(unsigned RegNo) override; + + /// Emit a .cprestore directive. If the offset is out of range then it will + /// be synthesized using the assembler temporary. + /// + /// GetATReg() is a callback that can be used to obtain the current assembler + /// temporary and is only called when the assembler temporary is required. It + /// must handle the case where no assembler temporary is available (typically + /// by reporting an error). bool emitDirectiveCpRestore(int Offset, std::function<unsigned()> GetATReg, SMLoc IDLoc, const MCSubtargetInfo *STI) override; void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, diff --git a/llvm/test/MC/Mips/cprestore-noreorder-noat.s b/llvm/test/MC/Mips/cprestore-noreorder-noat.s index d71d8fb91ed..0716145effa 100644 --- a/llvm/test/MC/Mips/cprestore-noreorder-noat.s +++ b/llvm/test/MC/Mips/cprestore-noreorder-noat.s @@ -24,7 +24,7 @@ foo: .cpload $25 .cprestore 8 -# O32: :[[@LINE-1]]:3: error: pseudo-instruction requires $at, which is not available +# O32-NOT: error: pseudo-instruction requires $at, which is not available # N32-NOT: error: pseudo-instruction requires $at, which is not available # N64-NOT: error: pseudo-instruction requires $at, which is not available # NO-STORE-NOT: sw $gp, 8($sp) @@ -34,3 +34,22 @@ foo: jal foo .end foo + + .ent bar +bar: + .frame $sp, 0, $ra + .set noreorder + .set noat + + .cpload $25 + .cprestore 65536 +# O32: :[[@LINE-1]]:3: error: pseudo-instruction requires $at, which is not available +# N32-NOT: error: pseudo-instruction requires $at, which is not available +# N64-NOT: error: pseudo-instruction requires $at, which is not available +# NO-STORE-NOT: sw $gp, + + jal $25 + jal $4, $25 + jal bar + + .end bar |

