mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-11-02 07:17:36 +00:00
[mips][microMIPS] Implement CodeGen support for SW16 and LW16 instructions
Differential Revision: http://reviews.llvm.org/D6581 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@228149 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
def addrimm12 : ComplexPattern<iPTR, 2, "selectIntAddrMM", [frameindex]>;
|
def addrimm12 : ComplexPattern<iPTR, 2, "selectIntAddrMM", [frameindex]>;
|
||||||
|
def addrimm4lsl2 : ComplexPattern<iPTR, 2, "selectIntAddrLSL2MM", [frameindex]>;
|
||||||
|
|
||||||
def simm4 : Operand<i32> {
|
def simm4 : Operand<i32> {
|
||||||
let DecoderMethod = "DecodeSimm4";
|
let DecoderMethod = "DecodeSimm4";
|
||||||
@@ -65,7 +66,7 @@ def MicroMipsMemGPRMM16AsmOperand : AsmOperandClass {
|
|||||||
|
|
||||||
class mem_mm_4_generic : Operand<i32> {
|
class mem_mm_4_generic : Operand<i32> {
|
||||||
let PrintMethod = "printMemOperand";
|
let PrintMethod = "printMemOperand";
|
||||||
let MIOperandInfo = (ops ptr_rc, simm4);
|
let MIOperandInfo = (ops GPRMM16, simm4);
|
||||||
let OperandType = "OPERAND_MEMORY";
|
let OperandType = "OPERAND_MEMORY";
|
||||||
let ParserMatchClass = MicroMipsMemGPRMM16AsmOperand;
|
let ParserMatchClass = MicroMipsMemGPRMM16AsmOperand;
|
||||||
}
|
}
|
||||||
@@ -879,6 +880,16 @@ def : MipsPat<(srl GPRMM16:$src, immZExt2Shift:$imm),
|
|||||||
def : MipsPat<(srl GPR32:$src, immZExt5:$imm),
|
def : MipsPat<(srl GPR32:$src, immZExt5:$imm),
|
||||||
(SRL_MM GPR32:$src, immZExt5:$imm)>;
|
(SRL_MM GPR32:$src, immZExt5:$imm)>;
|
||||||
|
|
||||||
|
def : MipsPat<(store GPRMM16:$src, addrimm4lsl2:$addr),
|
||||||
|
(SW16_MM GPRMM16:$src, addrimm4lsl2:$addr)>;
|
||||||
|
def : MipsPat<(store GPR32:$src, addr:$addr),
|
||||||
|
(SW_MM GPR32:$src, addr:$addr)>;
|
||||||
|
|
||||||
|
def : MipsPat<(load addrimm4lsl2:$addr),
|
||||||
|
(LW16_MM addrimm4lsl2:$addr)>;
|
||||||
|
def : MipsPat<(load addr:$addr),
|
||||||
|
(LW_MM addr:$addr)>;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// MicroMips instruction aliases
|
// MicroMips instruction aliases
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|||||||
@@ -95,6 +95,12 @@ bool MipsDAGToDAGISel::selectIntAddrMM(SDValue Addr, SDValue &Base,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MipsDAGToDAGISel::selectIntAddrLSL2MM(SDValue Addr, SDValue &Base,
|
||||||
|
SDValue &Offset) const {
|
||||||
|
llvm_unreachable("Unimplemented function.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool MipsDAGToDAGISel::selectIntAddrMSA(SDValue Addr, SDValue &Base,
|
bool MipsDAGToDAGISel::selectIntAddrMSA(SDValue Addr, SDValue &Base,
|
||||||
SDValue &Offset) const {
|
SDValue &Offset) const {
|
||||||
llvm_unreachable("Unimplemented function.");
|
llvm_unreachable("Unimplemented function.");
|
||||||
|
|||||||
@@ -73,6 +73,9 @@ private:
|
|||||||
virtual bool selectIntAddrMM(SDValue Addr, SDValue &Base,
|
virtual bool selectIntAddrMM(SDValue Addr, SDValue &Base,
|
||||||
SDValue &Offset) const;
|
SDValue &Offset) const;
|
||||||
|
|
||||||
|
virtual bool selectIntAddrLSL2MM(SDValue Addr, SDValue &Base,
|
||||||
|
SDValue &Offset) const;
|
||||||
|
|
||||||
/// Match addr+simm10 and addr
|
/// Match addr+simm10 and addr
|
||||||
virtual bool selectIntAddrMSA(SDValue Addr, SDValue &Base,
|
virtual bool selectIntAddrMSA(SDValue Addr, SDValue &Base,
|
||||||
SDValue &Offset) const;
|
SDValue &Offset) const;
|
||||||
|
|||||||
@@ -1192,11 +1192,15 @@ def LBu : Load<"lbu", GPR32Opnd, zextloadi8, II_LBU, addrDefault>, MMRel,
|
|||||||
def LH : Load<"lh", GPR32Opnd, sextloadi16, II_LH, addrDefault>, MMRel,
|
def LH : Load<"lh", GPR32Opnd, sextloadi16, II_LH, addrDefault>, MMRel,
|
||||||
LW_FM<0x21>;
|
LW_FM<0x21>;
|
||||||
def LHu : Load<"lhu", GPR32Opnd, zextloadi16, II_LHU>, MMRel, LW_FM<0x25>;
|
def LHu : Load<"lhu", GPR32Opnd, zextloadi16, II_LHU>, MMRel, LW_FM<0x25>;
|
||||||
|
let AdditionalPredicates = [NotInMicroMips] in {
|
||||||
def LW : Load<"lw", GPR32Opnd, load, II_LW, addrDefault>, MMRel,
|
def LW : Load<"lw", GPR32Opnd, load, II_LW, addrDefault>, MMRel,
|
||||||
LW_FM<0x23>;
|
LW_FM<0x23>;
|
||||||
|
}
|
||||||
def SB : Store<"sb", GPR32Opnd, truncstorei8, II_SB>, MMRel, LW_FM<0x28>;
|
def SB : Store<"sb", GPR32Opnd, truncstorei8, II_SB>, MMRel, LW_FM<0x28>;
|
||||||
def SH : Store<"sh", GPR32Opnd, truncstorei16, II_SH>, MMRel, LW_FM<0x29>;
|
def SH : Store<"sh", GPR32Opnd, truncstorei16, II_SH>, MMRel, LW_FM<0x29>;
|
||||||
|
let AdditionalPredicates = [NotInMicroMips] in {
|
||||||
def SW : Store<"sw", GPR32Opnd, store, II_SW>, MMRel, LW_FM<0x2b>;
|
def SW : Store<"sw", GPR32Opnd, store, II_SW>, MMRel, LW_FM<0x2b>;
|
||||||
|
}
|
||||||
|
|
||||||
/// load/store left/right
|
/// load/store left/right
|
||||||
let EncodingPredicates = []<Predicate>, // FIXME: Lack of HasStdEnc is probably a bug
|
let EncodingPredicates = []<Predicate>, // FIXME: Lack of HasStdEnc is probably a bug
|
||||||
@@ -1211,6 +1215,7 @@ def SWR : StoreLeftRight<"swr", MipsSWR, GPR32Opnd, II_SWR>, LW_FM<0x2e>,
|
|||||||
ISA_MIPS1_NOT_32R6_64R6;
|
ISA_MIPS1_NOT_32R6_64R6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let AdditionalPredicates = [NotInMicroMips] in {
|
||||||
// COP2 Memory Instructions
|
// COP2 Memory Instructions
|
||||||
def LWC2 : LW_FT2<"lwc2", COP2Opnd, NoItinerary, load>, LW_FM<0x32>,
|
def LWC2 : LW_FT2<"lwc2", COP2Opnd, NoItinerary, load>, LW_FM<0x32>,
|
||||||
ISA_MIPS1_NOT_32R6_64R6;
|
ISA_MIPS1_NOT_32R6_64R6;
|
||||||
@@ -1230,6 +1235,7 @@ let DecoderNamespace = "COP3_" in {
|
|||||||
def SDC3 : SW_FT3<"sdc3", COP3Opnd, NoItinerary, store>, LW_FM<0x3f>,
|
def SDC3 : SW_FT3<"sdc3", COP3Opnd, NoItinerary, store>, LW_FM<0x3f>,
|
||||||
ISA_MIPS2;
|
ISA_MIPS2;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def SYNC : MMRel, SYNC_FT<"sync">, SYNC_FM, ISA_MIPS32;
|
def SYNC : MMRel, SYNC_FT<"sync">, SYNC_FM, ISA_MIPS32;
|
||||||
def SYNCI : MMRel, SYNCI_FT<"synci">, SYNCI_FM, ISA_MIPS32R2;
|
def SYNCI : MMRel, SYNCI_FT<"synci">, SYNCI_FM, ISA_MIPS32R2;
|
||||||
@@ -1858,7 +1864,9 @@ def : MipsPat<(bswap GPR32:$rt), (ROTR (WSBH GPR32:$rt), 16)>;
|
|||||||
let AddedComplexity = 40 in {
|
let AddedComplexity = 40 in {
|
||||||
def : LoadRegImmPat<LBu, i32, zextloadi8>;
|
def : LoadRegImmPat<LBu, i32, zextloadi8>;
|
||||||
def : LoadRegImmPat<LH, i32, sextloadi16>;
|
def : LoadRegImmPat<LH, i32, sextloadi16>;
|
||||||
|
let AdditionalPredicates = [NotInMicroMips] in {
|
||||||
def : LoadRegImmPat<LW, i32, load>;
|
def : LoadRegImmPat<LW, i32, load>;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|||||||
@@ -407,6 +407,31 @@ bool MipsSEDAGToDAGISel::selectIntAddrMM(SDValue Addr, SDValue &Base,
|
|||||||
selectAddrDefault(Addr, Base, Offset);
|
selectAddrDefault(Addr, Base, Offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MipsSEDAGToDAGISel::selectIntAddrLSL2MM(SDValue Addr, SDValue &Base,
|
||||||
|
SDValue &Offset) const {
|
||||||
|
if (selectAddrFrameIndexOffset(Addr, Base, Offset, 7)) {
|
||||||
|
if (dyn_cast<FrameIndexSDNode>(Base))
|
||||||
|
return false;
|
||||||
|
else {
|
||||||
|
ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Offset);
|
||||||
|
if (CN) {
|
||||||
|
unsigned CnstOff = CN->getZExtValue();
|
||||||
|
if (CnstOff == (CnstOff & 0x3c))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// For all other cases where "lw" would be selected, don't select "lw16"
|
||||||
|
// because it would result in additional instructions to prepare operands.
|
||||||
|
if (selectAddrRegImm(Addr, Base, Offset))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return selectAddrDefault(Addr, Base, Offset);
|
||||||
|
}
|
||||||
|
|
||||||
bool MipsSEDAGToDAGISel::selectIntAddrMSA(SDValue Addr, SDValue &Base,
|
bool MipsSEDAGToDAGISel::selectIntAddrMSA(SDValue Addr, SDValue &Base,
|
||||||
SDValue &Offset) const {
|
SDValue &Offset) const {
|
||||||
if (selectAddrRegImm10(Addr, Base, Offset))
|
if (selectAddrRegImm10(Addr, Base, Offset))
|
||||||
|
|||||||
@@ -65,6 +65,9 @@ private:
|
|||||||
bool selectIntAddrMM(SDValue Addr, SDValue &Base,
|
bool selectIntAddrMM(SDValue Addr, SDValue &Base,
|
||||||
SDValue &Offset) const override;
|
SDValue &Offset) const override;
|
||||||
|
|
||||||
|
bool selectIntAddrLSL2MM(SDValue Addr, SDValue &Base,
|
||||||
|
SDValue &Offset) const override;
|
||||||
|
|
||||||
bool selectIntAddrMSA(SDValue Addr, SDValue &Base,
|
bool selectIntAddrMSA(SDValue Addr, SDValue &Base,
|
||||||
SDValue &Offset) const override;
|
SDValue &Offset) const override;
|
||||||
|
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ end:
|
|||||||
; MICROMIPS: $[[BB0]]:
|
; MICROMIPS: $[[BB0]]:
|
||||||
; MICROMIPS: lw $[[R1:[0-9]+]], %got(x)($[[GP]])
|
; MICROMIPS: lw $[[R1:[0-9]+]], %got(x)($[[GP]])
|
||||||
; MICROMIPS: li16 $[[R2:[0-9]+]], 1
|
; MICROMIPS: li16 $[[R2:[0-9]+]], 1
|
||||||
; MICROMIPS: sw $[[R2]], 0($[[R1]])
|
; MICROMIPS: sw16 $[[R2]], 0($[[R1]])
|
||||||
; MICROMIPS: $[[BB2]]:
|
; MICROMIPS: $[[BB2]]:
|
||||||
; MICROMIPS: jr $ra
|
; MICROMIPS: jr $ra
|
||||||
; MICROMIPS: nop
|
; MICROMIPS: nop
|
||||||
|
|||||||
27
test/CodeGen/Mips/micromips-sw-lw-16.ll
Normal file
27
test/CodeGen/Mips/micromips-sw-lw-16.ll
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
; RUN: llc %s -march=mipsel -mattr=micromips -filetype=asm \
|
||||||
|
; RUN: -relocation-model=pic -O3 -o - | FileCheck %s
|
||||||
|
|
||||||
|
; Function Attrs: noinline nounwind
|
||||||
|
define void @bar(i32* %p) #0 {
|
||||||
|
entry:
|
||||||
|
%p.addr = alloca i32*, align 4
|
||||||
|
store i32* %p, i32** %p.addr, align 4
|
||||||
|
%0 = load i32** %p.addr, align 4
|
||||||
|
%1 = load i32* %0, align 4
|
||||||
|
%add = add nsw i32 7, %1
|
||||||
|
%2 = load i32** %p.addr, align 4
|
||||||
|
store i32 %add, i32* %2, align 4
|
||||||
|
%3 = load i32** %p.addr, align 4
|
||||||
|
%add.ptr = getelementptr inbounds i32* %3, i32 1
|
||||||
|
%4 = load i32* %add.ptr, align 4
|
||||||
|
%add1 = add nsw i32 7, %4
|
||||||
|
%5 = load i32** %p.addr, align 4
|
||||||
|
%add.ptr2 = getelementptr inbounds i32* %5, i32 1
|
||||||
|
store i32 %add1, i32* %add.ptr2, align 4
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK: lw16 ${{[0-9]+}}, 0($4)
|
||||||
|
; CHECK: sw16 ${{[0-9]+}}, 0($4)
|
||||||
|
; CHECK: lw16 ${{[0-9]+}}, 4(${{[0-9]+}})
|
||||||
|
; CHECK: sw16 ${{[0-9]+}}, 4(${{[0-9]+}})
|
||||||
Reference in New Issue
Block a user