Skip to content

Commit

Permalink
[mips][mips64r6] ll, sc, lld, and scd are re-encoded on MIPS32r6/MIPS…
Browse files Browse the repository at this point in the history
…64r6.

Summary:
The linked-load, store-conditional operations have been re-encoded such
that have a 9-bit offset instead of the 16-bit offset they have prior to
MIPS32r6/MIPS64r6.

While implementing this, I noticed that the atomic load/store pseudos always
emit a sign extension using sll and sra. I have improved this to use seb/seh
when they are available (MIPS32r2/MIPS64r2 and above).

Depends on D4118

Reviewers: jkolek, zoran.jovanovic, vmedic

Reviewed By: vmedic

Differential Revision: http://reviews.llvm.org/D4119

llvm-svn: 211018
  • Loading branch information
dsandersllvm committed Jun 16, 2014
1 parent 0469dbd commit 6a803f6
Show file tree
Hide file tree
Showing 23 changed files with 306 additions and 82 deletions.
26 changes: 26 additions & 0 deletions llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
Expand Up @@ -272,6 +272,11 @@ static DecodeStatus DecodeFMem(MCInst &Inst, unsigned Insn,
uint64_t Address,
const void *Decoder);

static DecodeStatus DecodeSpecial3LlSc(MCInst &Inst,
unsigned Insn,
uint64_t Address,
const void *Decoder);

static DecodeStatus DecodeSimm16(MCInst &Inst,
unsigned Insn,
uint64_t Address,
Expand Down Expand Up @@ -1068,6 +1073,27 @@ static DecodeStatus DecodeFMem(MCInst &Inst,
return MCDisassembler::Success;
}

static DecodeStatus DecodeSpecial3LlSc(MCInst &Inst,
unsigned Insn,
uint64_t Address,
const void *Decoder) {
int64_t Offset = SignExtend64<9>((Insn >> 7) & 0x1ff);
unsigned Rt = fieldFromInstruction(Insn, 16, 5);
unsigned Base = fieldFromInstruction(Insn, 21, 5);

Rt = getReg(Decoder, Mips::GPR32RegClassID, Rt);
Base = getReg(Decoder, Mips::GPR32RegClassID, Base);

if(Inst.getOpcode() == Mips::SC_R6 || Inst.getOpcode() == Mips::SCD_R6){
Inst.addOperand(MCOperand::CreateReg(Rt));
}

Inst.addOperand(MCOperand::CreateReg(Rt));
Inst.addOperand(MCOperand::CreateReg(Base));
Inst.addOperand(MCOperand::CreateImm(Offset));

return MCDisassembler::Success;
}

static DecodeStatus DecodeHWRegsRegisterClass(MCInst &Inst,
unsigned RegNo,
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp
Expand Up @@ -203,6 +203,7 @@ bool isBasePlusOffsetMemoryAccess(unsigned Opcode, unsigned *AddrIdx,
case Mips::LWC1:
case Mips::LDC1:
case Mips::LL:
case Mips::LL_R6:
case Mips::LWL:
case Mips::LWR:
*AddrIdx = 1;
Expand All @@ -223,6 +224,7 @@ bool isBasePlusOffsetMemoryAccess(unsigned Opcode, unsigned *AddrIdx,

// Store instructions with base address register in position 2.
case Mips::SC:
case Mips::SC_R6:
*AddrIdx = 2;
if (IsStore)
*IsStore = true;
Expand Down
24 changes: 24 additions & 0 deletions llvm/lib/Target/Mips/Mips32r6InstrFormats.td
Expand Up @@ -39,6 +39,7 @@ def OPGROUP_DAUI : OPGROUP<0b011101>;
def OPGROUP_PCREL : OPGROUP<0b111011>;
def OPGROUP_REGIMM : OPGROUP<0b000001>;
def OPGROUP_SPECIAL : OPGROUP<0b000000>;
// The spec occasionally names this value LL, LLD, SC, or SCD.
def OPGROUP_SPECIAL3 : OPGROUP<0b011111>;
// The spec names this constant LWC2, LDC2, SWC2, and SDC2 in different places.
def OPGROUP_COP2LDST : OPGROUP<0b010010>;
Expand Down Expand Up @@ -84,6 +85,12 @@ def OPCODE6_DBITSWAP : OPCODE6<0b100100>;
def OPCODE6_JALR : OPCODE6<0b001001>;
def OPCODE6_CACHE : OPCODE6<0b100101>;
def OPCODE6_PREF : OPCODE6<0b110101>;
// The next four constants are unnamed in the spec. These names are taken from
// the OPGROUP names they are used with.
def OPCODE6_LL : OPCODE6<0b110110>;
def OPCODE6_LLD : OPCODE6<0b110111>;
def OPCODE6_SC : OPCODE6<0b100110>;
def OPCODE6_SCD : OPCODE6<0b100111>;

class FIELD_FMT<bits<5> Val> {
bits<5> Value = Val;
Expand Down Expand Up @@ -411,6 +418,23 @@ class SPECIAL3_DALIGN_FM<OPCODE6 Operation> : MipsR6Inst {
let Inst{5-0} = Operation.Value;
}

class SPECIAL3_LL_SC_FM<OPCODE6 Operation> : MipsR6Inst {
bits<5> rt;
bits<21> addr;
bits<5> base = addr{20-16};
bits<9> offset = addr{8-0};

bits<32> Inst;

let Inst{31-26} = OPGROUP_SPECIAL3.Value;
let Inst{25-21} = base;
let Inst{20-16} = rt;
let Inst{15-7} = offset;
let Inst{5-0} = Operation.Value;

string DecoderMethod = "DecodeSpecial3LlSc";
}

class REGIMM_FM<OPCODE5 Operation> : MipsR6Inst {
bits<5> rs;
bits<16> imm;
Expand Down
27 changes: 26 additions & 1 deletion llvm/lib/Target/Mips/Mips32r6InstrInfo.td
Expand Up @@ -18,7 +18,6 @@ include "Mips32r6InstrFormats.td"
// Reencoded: clo, clz
// Reencoded: jr -> jalr
// Reencoded: jr.hb -> jalr.hb
// Reencoded: ll, sc
// Reencoded: sdbbp

def brtarget21 : Operand<OtherVT> {
Expand Down Expand Up @@ -158,6 +157,9 @@ class LWC2_R6_ENC : COP2LDST_FM<OPCODE5_LWC2>;
class SDC2_R6_ENC : COP2LDST_FM<OPCODE5_SDC2>;
class SWC2_R6_ENC : COP2LDST_FM<OPCODE5_SWC2>;

class LL_R6_ENC : SPECIAL3_LL_SC_FM<OPCODE6_LL>;
class SC_R6_ENC : SPECIAL3_LL_SC_FM<OPCODE6_SC>;

class CMP_CONDN_DESC_BASE<string CondStr, string Typestr,
RegisterOperand FGROpnd,
SDPatternOperator Op = null_frag> {
Expand Down Expand Up @@ -563,6 +565,27 @@ class COP2ST_DESC_BASE<string instr_asm, RegisterOperand COPOpnd> {
class SDC2_R6_DESC : COP2ST_DESC_BASE<"sdc2", COP2Opnd>;
class SWC2_R6_DESC : COP2ST_DESC_BASE<"swc2", COP2Opnd>;

class LL_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> {
dag OutOperandList = (outs GPROpnd:$rt);
dag InOperandList = (ins mem_simm9:$addr);
string AsmString = !strconcat(instr_asm, "\t$rt, $addr");
list<dag> Pattern = [];
bit mayLoad = 1;
}

class LL_R6_DESC : LL_R6_DESC_BASE<"ll", GPR32Opnd>;

class SC_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> {
dag OutOperandList = (outs GPROpnd:$dst);
dag InOperandList = (ins GPROpnd:$rt, mem_simm9:$addr);
string AsmString = !strconcat(instr_asm, "\t$rt, $addr");
list<dag> Pattern = [];
bit mayStore = 1;
string Constraints = "$rt = $dst";
}

class SC_R6_DESC : SC_R6_DESC_BASE<"sc", GPR32Opnd>;

//===----------------------------------------------------------------------===//
//
// Instruction Definitions
Expand Down Expand Up @@ -613,6 +636,7 @@ def JIALC : JIALC_ENC, JIALC_DESC, ISA_MIPS32R6;
def JIC : JIC_ENC, JIC_DESC, ISA_MIPS32R6;
def JR_HB_R6 : JR_HB_R6_ENC, JR_HB_R6_DESC, ISA_MIPS32R6;
def LDC2_R6 : LDC2_R6_ENC, LDC2_R6_DESC, ISA_MIPS32R6;
def LL_R6 : LL_R6_ENC, LL_R6_DESC, ISA_MIPS32R6;
// def LSA; // See MSA
def LWC2_R6 : LWC2_R6_ENC, LWC2_R6_DESC, ISA_MIPS32R6;
def LWPC : LWPC_ENC, LWPC_DESC, ISA_MIPS32R6;
Expand All @@ -639,6 +663,7 @@ def NAL; // BAL with rd=0
def PREF_R6 : PREF_ENC, PREF_DESC, ISA_MIPS32R6;
def RINT_D : RINT_D_ENC, RINT_D_DESC, ISA_MIPS32R6;
def RINT_S : RINT_S_ENC, RINT_S_DESC, ISA_MIPS32R6;
def SC_R6 : SC_R6_ENC, SC_R6_DESC, ISA_MIPS32R6;
def SDC2_R6 : SDC2_R6_ENC, SDC2_R6_DESC, ISA_MIPS32R6;
def SELEQZ : SELEQZ_ENC, SELEQZ_DESC, ISA_MIPS32R6, GPR_32;
def SELEQZ_D : SELEQZ_D_ENC, SELEQZ_D_DESC, ISA_MIPS32R6;
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Target/Mips/Mips64InstrInfo.td
Expand Up @@ -167,8 +167,8 @@ def SDR : StoreLeftRight<"sdr", MipsSDR, GPR64Opnd, II_SDR>, LW_FM<0x2d>,
ISA_MIPS3_NOT_32R6_64R6;

/// Load-linked, Store-conditional
def LLD : LLBase<"lld", GPR64Opnd>, LW_FM<0x34>, ISA_MIPS3;
def SCD : SCBase<"scd", GPR64Opnd>, LW_FM<0x3c>, ISA_MIPS3;
def LLD : LLBase<"lld", GPR64Opnd>, LW_FM<0x34>, ISA_MIPS3_NOT_32R6_64R6;
def SCD : SCBase<"scd", GPR64Opnd>, LW_FM<0x3c>, ISA_MIPS3_NOT_32R6_64R6;

/// Jump and Branch Instructions
let isCodeGenOnly = 1 in {
Expand Down
8 changes: 6 additions & 2 deletions llvm/lib/Target/Mips/Mips64r6InstrInfo.td
Expand Up @@ -13,7 +13,6 @@

// Notes about removals/changes from MIPS32r6:
// Reencoded: dclo, dclz
// Reencoded: lld, scd

//===----------------------------------------------------------------------===//
//
Expand All @@ -35,6 +34,8 @@ class DMUHU_ENC : SPECIAL_3R_FM<0b00011, 0b111001>;
class DMUL_R6_ENC : SPECIAL_3R_FM<0b00010, 0b111000>;
class DMULU_ENC : SPECIAL_3R_FM<0b00010, 0b111001>;
class LDPC_ENC : PCREL18_FM<OPCODE3_LDPC>;
class LLD_R6_ENC : SPECIAL3_LL_SC_FM<OPCODE6_LLD>;
class SCD_R6_ENC : SPECIAL3_LL_SC_FM<OPCODE6_SCD>;

//===----------------------------------------------------------------------===//
//
Expand Down Expand Up @@ -63,7 +64,8 @@ class DMUHU_DESC : MUL_R6_DESC_BASE<"dmuhu", GPR64Opnd, mulhu>;
class DMUL_R6_DESC : MUL_R6_DESC_BASE<"dmul", GPR64Opnd, mul>;
class DMULU_DESC : MUL_R6_DESC_BASE<"dmulu", GPR64Opnd>;
class LDPC_DESC : PCREL_DESC_BASE<"ldpc", GPR64Opnd, simm18_lsl3>;

class LLD_R6_DESC : LL_R6_DESC_BASE<"lld", GPR64Opnd>;
class SCD_R6_DESC : SC_R6_DESC_BASE<"scd", GPR64Opnd>;
class SELEQZ64_DESC : SELEQNE_Z_DESC_BASE<"seleqz", GPR64Opnd>;
class SELNEZ64_DESC : SELEQNE_Z_DESC_BASE<"selnez", GPR64Opnd>;

Expand All @@ -88,6 +90,8 @@ def DMUHU: DMUHU_ENC, DMUHU_DESC, ISA_MIPS64R6;
def DMUL_R6: DMUL_R6_ENC, DMUL_R6_DESC, ISA_MIPS64R6;
def DMULU: DMULU_ENC, DMULU_DESC, ISA_MIPS64R6;
def LDPC: LDPC_ENC, LDPC_DESC, ISA_MIPS64R6;
def LLD_R6 : LLD_R6_ENC, LLD_R6_DESC, ISA_MIPS32R6;
def SCD_R6 : SCD_R6_ENC, SCD_R6_DESC, ISA_MIPS32R6;
let DecoderNamespace = "Mips32r6_64r6_GP64" in {
def SELEQZ64 : SELEQZ_ENC, SELEQZ64_DESC, ISA_MIPS32R6, GPR_64;
def SELNEZ64 : SELNEZ_ENC, SELNEZ64_DESC, ISA_MIPS32R6, GPR_64;
Expand Down
74 changes: 47 additions & 27 deletions llvm/lib/Target/Mips/MipsISelLowering.cpp
Expand Up @@ -958,16 +958,20 @@ MipsTargetLowering::emitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB,
unsigned LL, SC, AND, NOR, ZERO, BEQ;

if (Size == 4) {
LL = isMicroMips ? Mips::LL_MM : Mips::LL;
SC = isMicroMips ? Mips::SC_MM : Mips::SC;
if (isMicroMips) {
LL = Mips::LL_MM;
SC = Mips::SC_MM;
} else {
LL = Subtarget->hasMips32r6() ? Mips::LL : Mips::LL_R6;
SC = Subtarget->hasMips32r6() ? Mips::SC : Mips::SC_R6;
}
AND = Mips::AND;
NOR = Mips::NOR;
ZERO = Mips::ZERO;
BEQ = Mips::BEQ;
}
else {
LL = Mips::LLD;
SC = Mips::SCD;
} else {
LL = Subtarget->hasMips64r6() ? Mips::LLD : Mips::LLD_R6;
SC = Subtarget->hasMips64r6() ? Mips::SCD : Mips::SCD_R6;
AND = Mips::AND64;
NOR = Mips::NOR64;
ZERO = Mips::ZERO_64;
Expand Down Expand Up @@ -1029,11 +1033,39 @@ MipsTargetLowering::emitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB,
return exitMBB;
}

MachineBasicBlock *
MipsTargetLowering::emitAtomicBinaryPartword(MachineInstr *MI,
MachineBasicBlock *BB,
unsigned Size, unsigned BinOpcode,
bool Nand) const {
MachineBasicBlock *MipsTargetLowering::emitSignExtendToI32InReg(
MachineInstr *MI, MachineBasicBlock *BB, unsigned Size, unsigned DstReg,
unsigned SrcReg) const {
const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
DebugLoc DL = MI->getDebugLoc();

if (Subtarget->hasMips32r2() && Size == 1) {
BuildMI(BB, DL, TII->get(Mips::SEB), DstReg).addReg(SrcReg);
return BB;
}

if (Subtarget->hasMips32r2() && Size == 2) {
BuildMI(BB, DL, TII->get(Mips::SEH), DstReg).addReg(SrcReg);
return BB;
}

MachineFunction *MF = BB->getParent();
MachineRegisterInfo &RegInfo = MF->getRegInfo();
const TargetRegisterClass *RC = getRegClassFor(MVT::i32);
unsigned ScrReg = RegInfo.createVirtualRegister(RC);

assert(Size < 32);
int64_t ShiftImm = 32 - (Size * 8);

BuildMI(BB, DL, TII->get(Mips::SLL), ScrReg).addReg(SrcReg).addImm(ShiftImm);
BuildMI(BB, DL, TII->get(Mips::SRA), DstReg).addReg(ScrReg).addImm(ShiftImm);

return BB;
}

MachineBasicBlock *MipsTargetLowering::emitAtomicBinaryPartword(
MachineInstr *MI, MachineBasicBlock *BB, unsigned Size, unsigned BinOpcode,
bool Nand) const {
assert((Size == 1 || Size == 2) &&
"Unsupported size for EmitAtomicBinaryPartial.");

Expand Down Expand Up @@ -1063,7 +1095,6 @@ MipsTargetLowering::emitAtomicBinaryPartword(MachineInstr *MI,
unsigned StoreVal = RegInfo.createVirtualRegister(RC);
unsigned MaskedOldVal1 = RegInfo.createVirtualRegister(RC);
unsigned SrlRes = RegInfo.createVirtualRegister(RC);
unsigned SllRes = RegInfo.createVirtualRegister(RC);
unsigned Success = RegInfo.createVirtualRegister(RC);

// insert new blocks after the current block
Expand Down Expand Up @@ -1169,19 +1200,14 @@ MipsTargetLowering::emitAtomicBinaryPartword(MachineInstr *MI,
// sinkMBB:
// and maskedoldval1,oldval,mask
// srl srlres,maskedoldval1,shiftamt
// sll sllres,srlres,24
// sra dest,sllres,24
// sign_extend dest,srlres
BB = sinkMBB;
int64_t ShiftImm = (Size == 1) ? 24 : 16;

BuildMI(BB, DL, TII->get(Mips::AND), MaskedOldVal1)
.addReg(OldVal).addReg(Mask);
BuildMI(BB, DL, TII->get(Mips::SRLV), SrlRes)
.addReg(MaskedOldVal1).addReg(ShiftAmt);
BuildMI(BB, DL, TII->get(Mips::SLL), SllRes)
.addReg(SrlRes).addImm(ShiftImm);
BuildMI(BB, DL, TII->get(Mips::SRA), Dest)
.addReg(SllRes).addImm(ShiftImm);
BB = emitSignExtendToI32InReg(MI, BB, Size, Dest, SrlRes);

MI->eraseFromParent(); // The instruction is gone now.

Expand Down Expand Up @@ -1302,7 +1328,6 @@ MipsTargetLowering::emitAtomicCmpSwapPartword(MachineInstr *MI,
unsigned MaskedOldVal1 = RegInfo.createVirtualRegister(RC);
unsigned StoreVal = RegInfo.createVirtualRegister(RC);
unsigned SrlRes = RegInfo.createVirtualRegister(RC);
unsigned SllRes = RegInfo.createVirtualRegister(RC);
unsigned Success = RegInfo.createVirtualRegister(RC);

// insert new blocks after the current block
Expand Down Expand Up @@ -1399,17 +1424,12 @@ MipsTargetLowering::emitAtomicCmpSwapPartword(MachineInstr *MI,

// sinkMBB:
// srl srlres,maskedoldval0,shiftamt
// sll sllres,srlres,24
// sra dest,sllres,24
// sign_extend dest,srlres
BB = sinkMBB;
int64_t ShiftImm = (Size == 1) ? 24 : 16;

BuildMI(BB, DL, TII->get(Mips::SRLV), SrlRes)
.addReg(MaskedOldVal0).addReg(ShiftAmt);
BuildMI(BB, DL, TII->get(Mips::SLL), SllRes)
.addReg(SrlRes).addImm(ShiftImm);
BuildMI(BB, DL, TII->get(Mips::SRA), Dest)
.addReg(SllRes).addImm(ShiftImm);
BB = emitSignExtendToI32InReg(MI, BB, Size, Dest, SrlRes);

MI->eraseFromParent(); // The instruction is gone now.

Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/Target/Mips/MipsISelLowering.h
Expand Up @@ -598,6 +598,12 @@ namespace llvm {

unsigned getJumpTableEncoding() const override;

/// Emit a sign-extension using sll/sra, seb, or seh appropriately.
MachineBasicBlock *emitSignExtendToI32InReg(MachineInstr *MI,
MachineBasicBlock *BB,
unsigned Size, unsigned DstReg,
unsigned SrcRec) const;

MachineBasicBlock *emitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB,
unsigned Size, unsigned BinOpcode, bool Nand = false) const;
MachineBasicBlock *emitAtomicBinaryPartword(MachineInstr *MI,
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Target/Mips/MipsInstrInfo.td
Expand Up @@ -1189,8 +1189,8 @@ let EncodingPredicates = []<Predicate>, // FIXME: Lack of HasStdEnc is probably
def WAIT : WAIT_FT<"wait">, WAIT_FM;

/// Load-linked, Store-conditional
def LL : LLBase<"ll", GPR32Opnd>, LW_FM<0x30>, ISA_MIPS2;
def SC : SCBase<"sc", GPR32Opnd>, LW_FM<0x38>, ISA_MIPS2;
def LL : LLBase<"ll", GPR32Opnd>, LW_FM<0x30>, ISA_MIPS2_NOT_32R6_64R6;
def SC : SCBase<"sc", GPR32Opnd>, LW_FM<0x38>, ISA_MIPS2_NOT_32R6_64R6;
}

/// Jump and Branch Instructions
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/Mips/MipsSubtarget.h
Expand Up @@ -161,7 +161,7 @@ class MipsSubtarget : public MipsGenSubtargetInfo {
bool hasMips32() const { return MipsArchVersion >= Mips32; }
bool hasMips32r2() const {
return MipsArchVersion == Mips32r2 || MipsArchVersion == Mips32r6 ||
MipsArchVersion == Mips64r2;
MipsArchVersion == Mips64r2 || MipsArchVersion == Mips64r6;
}
bool hasMips32r6() const {
return MipsArchVersion == Mips32r6 || MipsArchVersion == Mips64r6;
Expand Down

0 comments on commit 6a803f6

Please sign in to comment.