From c39b18b306c7681cb155127096a56afbea24a08e Mon Sep 17 00:00:00 2001 From: Matheus Almeida Date: Wed, 18 Jun 2014 14:49:56 +0000 Subject: [PATCH] [mips] Fix expansion of memory operation if destination register is not a GPR. Summary: The assembler tries to reuse the destination register for memory operations whenever it can but it's not possible to do so if the destination register is not a GPR. Example: ldc1 $f0, sym should expand to: lui $at, %hi(sym) ldc1 $f0, %lo(sym)($at) It's entirely wrong to expand to: lui $f0, %hi(sym) ldc1 $f0, %lo(sym)($f0) Reviewers: dsanders Reviewed By: dsanders Differential Revision: http://reviews.llvm.org/D4173 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@211169 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 33 ++++++++++++++++++--- test/MC/Mips/mips-expansions.s | 8 +++++ 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 4a226a9f9d8..dd2b857789c 100644 --- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -1144,10 +1144,35 @@ void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, ExprOffset = Inst.getOperand(2).getExpr(); // All instructions will have the same location. TempInst.setLoc(IDLoc); - // 1st instruction in expansion is LUi. For load instruction we can use - // the dst register as a temporary if base and dst are different, - // but for stores we must use $at. - if (isLoad && (BaseRegNum != RegOpNum)) + // These are some of the types of expansions we perform here: + // 1) lw $8, sym => lui $8, %hi(sym) + // lw $8, %lo(sym)($8) + // 2) lw $8, offset($9) => lui $8, %hi(offset) + // add $8, $8, $9 + // lw $8, %lo(offset)($9) + // 3) lw $8, offset($8) => lui $at, %hi(offset) + // add $at, $at, $8 + // lw $8, %lo(offset)($at) + // 4) sw $8, sym => lui $at, %hi(sym) + // sw $8, %lo(sym)($at) + // 5) sw $8, offset($8) => lui $at, %hi(offset) + // add $at, $at, $8 + // sw $8, %lo(offset)($at) + // 6) ldc1 $f0, sym => lui $at, %hi(sym) + // ldc1 $f0, %lo(sym)($at) + // + // For load instructions we can use the destination register as a temporary + // if base and dst are different (examples 1 and 2) and if the base register + // is general purpose otherwise we must use $at (example 6) and error if it's + // not available. For stores we must use $at (examples 4 and 5) because we + // must not clobber the source register setting up the offset. + const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode()); + int16_t RegClassOp0 = Desc.OpInfo[0].RegClass; + unsigned RegClassIDOp0 = + getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID(); + bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) || + (RegClassIDOp0 == Mips::GPR64RegClassID); + if (isLoad && IsGPR && (BaseRegNum != RegOpNum)) TmpRegNum = RegOpNum; else { int AT = getATReg(IDLoc); diff --git a/test/MC/Mips/mips-expansions.s b/test/MC/Mips/mips-expansions.s index 9925609ecd1..f0a04a5a251 100644 --- a/test/MC/Mips/mips-expansions.s +++ b/test/MC/Mips/mips-expansions.s @@ -34,6 +34,11 @@ # CHECK: addu $1, $1, $9 # encoding: [0x21,0x08,0x29,0x00] # CHECK: sw $10, 57920($1) # encoding: [0x40,0xe2,0x2a,0xac] +# CHECK: lui $1, %hi(symbol) +# CHECK: ldc1 $f0, %lo(symbol)($1) +# CHECK: lui $1, %hi(symbol) +# CHECK: sdc1 $f0, %lo(symbol)($1) + li $5,123 li $6,-2345 li $7,65538 @@ -51,3 +56,6 @@ lw $t2, 655483($a0) sw $t2, 123456($t1) + + ldc1 $f0, symbol + sdc1 $f0, symbol