Index: llvm/trunk/lib/Target/Mips/MipsInstructionSelector.cpp =================================================================== --- llvm/trunk/lib/Target/Mips/MipsInstructionSelector.cpp +++ llvm/trunk/lib/Target/Mips/MipsInstructionSelector.cpp @@ -107,8 +107,72 @@ if (selectImpl(I, CoverageInfo)) { return true; } - // We didn't select anything. - return false; + + MachineInstr *MI = nullptr; + using namespace TargetOpcode; + + switch (I.getOpcode()) { + case G_GEP: { + MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDu)) + .add(I.getOperand(0)) + .add(I.getOperand(1)) + .add(I.getOperand(2)); + break; + } + case G_FRAME_INDEX: { + MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu)) + .add(I.getOperand(0)) + .add(I.getOperand(1)) + .addImm(0); + break; + } + case G_STORE: + case G_LOAD: { + const unsigned DestReg = I.getOperand(0).getReg(); + const unsigned DestRegBank = RBI.getRegBank(DestReg, MRI, TRI)->getID(); + const unsigned OpSize = MRI.getType(DestReg).getSizeInBits(); + + if (DestRegBank != Mips::GPRBRegBankID || OpSize != 32) + return false; + + const unsigned NewOpc = I.getOpcode() == G_STORE ? Mips::SW : Mips::LW; + + MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(NewOpc)) + .add(I.getOperand(0)) + .add(I.getOperand(1)) + .addImm(0) + .addMemOperand(*I.memoperands_begin()); + break; + } + case G_CONSTANT: { + int Imm = I.getOperand(1).getCImm()->getValue().getLimitedValue(); + unsigned LUiReg = MRI.createVirtualRegister(&Mips::GPR32RegClass); + MachineInstr *LUi, *ORi; + + LUi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LUi)) + .addDef(LUiReg) + .addImm(Imm >> 16); + + ORi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ORi)) + .addDef(I.getOperand(0).getReg()) + .addUse(LUiReg) + .addImm(Imm & 0xFFFF); + + if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI)) + return false; + if (!constrainSelectedInstRegOperands(*ORi, TII, TRI, RBI)) + return false; + + I.eraseFromParent(); + return true; + } + + default: + return false; + } + + I.eraseFromParent(); + return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI); } namespace llvm { Index: llvm/trunk/lib/Target/Mips/MipsLegalizerInfo.cpp =================================================================== --- llvm/trunk/lib/Target/Mips/MipsLegalizerInfo.cpp +++ llvm/trunk/lib/Target/Mips/MipsLegalizerInfo.cpp @@ -20,9 +20,22 @@ using namespace TargetOpcode; const LLT s32 = LLT::scalar(32); + const LLT p0 = LLT::pointer(0, 32); getActionDefinitionsBuilder(G_ADD).legalFor({s32}); + getActionDefinitionsBuilder({G_LOAD, G_STORE}) + .legalFor({{s32, p0}}); + + getActionDefinitionsBuilder(G_CONSTANT) + .legalFor({s32}); + + getActionDefinitionsBuilder(G_GEP) + .legalFor({{p0, s32}}); + + getActionDefinitionsBuilder(G_FRAME_INDEX) + .legalFor({p0}); + computeTables(); verify(*ST.getInstrInfo()); } Index: llvm/trunk/lib/Target/Mips/MipsRegisterBankInfo.cpp =================================================================== --- llvm/trunk/lib/Target/Mips/MipsRegisterBankInfo.cpp +++ llvm/trunk/lib/Target/Mips/MipsRegisterBankInfo.cpp @@ -58,6 +58,7 @@ case Mips::GPR32RegClassID: case Mips::CPU16Regs_and_GPRMM16ZeroRegClassID: case Mips::GPRMM16MoveP_and_CPU16Regs_and_GPRMM16ZeroRegClassID: + case Mips::SP32RegClassID: return getRegBank(Mips::GPRBRegBankID); default: llvm_unreachable("Register class not supported"); @@ -80,8 +81,16 @@ switch (Opc) { case G_ADD: + case G_LOAD: + case G_STORE: + case G_GEP: OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx]; break; + case G_CONSTANT: + case G_FRAME_INDEX: + OperandsMapping = + getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr}); + break; default: return getInvalidInstructionMapping(); } Index: llvm/trunk/test/CodeGen/Mips/GlobalISel/instruction-select/stack_args.mir =================================================================== --- llvm/trunk/test/CodeGen/Mips/GlobalISel/instruction-select/stack_args.mir +++ llvm/trunk/test/CodeGen/Mips/GlobalISel/instruction-select/stack_args.mir @@ -0,0 +1,65 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32 +--- | + + declare i32 @f(i32, i32, i32, i32, i32) + define void @g(i32, i32, i32, i32, i32) {entry: ret void} + +... +--- +name: g +alignment: 2 +legalized: true +regBankSelected: true +tracksRegLiveness: true +fixedStack: + - { id: 0, offset: 16, size: 4, alignment: 8, stack-id: 0, isImmutable: true } +body: | + bb.1.entry: + liveins: $a0, $a1, $a2, $a3 + + ; MIPS32-LABEL: name: g + ; MIPS32: liveins: $a0, $a1, $a2, $a3 + ; MIPS32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:gpr32 = COPY $a1 + ; MIPS32: [[COPY2:%[0-9]+]]:gpr32 = COPY $a2 + ; MIPS32: [[COPY3:%[0-9]+]]:gpr32 = COPY $a3 + ; MIPS32: [[ADDiu:%[0-9]+]]:gpr32 = ADDiu %fixed-stack.0, 0 + ; MIPS32: [[LW:%[0-9]+]]:gpr32 = LW [[ADDiu]], 0 :: (load 4 from %fixed-stack.0, align 0) + ; MIPS32: ADJCALLSTACKDOWN 24, 0, implicit-def $sp, implicit $sp + ; MIPS32: $a0 = COPY [[COPY]] + ; MIPS32: $a1 = COPY [[COPY1]] + ; MIPS32: $a2 = COPY [[COPY2]] + ; MIPS32: $a3 = COPY [[COPY3]] + ; MIPS32: [[COPY4:%[0-9]+]]:gpr32 = COPY $sp + ; MIPS32: [[LUi:%[0-9]+]]:gpr32 = LUi 0 + ; MIPS32: [[ORi:%[0-9]+]]:gpr32 = ORi [[LUi]], 16 + ; MIPS32: [[ADDu:%[0-9]+]]:gpr32 = ADDu [[COPY4]], [[ORi]] + ; MIPS32: SW [[LW]], [[ADDu]], 0 :: (store 4 into stack + 16, align 0) + ; MIPS32: JAL @f, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit $a2, implicit $a3, implicit-def $v0 + ; MIPS32: [[COPY5:%[0-9]+]]:gpr32 = COPY $v0 + ; MIPS32: ADJCALLSTACKUP 24, 0, implicit-def $sp, implicit $sp + ; MIPS32: $v0 = COPY [[COPY5]] + ; MIPS32: RetRA implicit $v0 + %0:gprb(s32) = COPY $a0 + %1:gprb(s32) = COPY $a1 + %2:gprb(s32) = COPY $a2 + %3:gprb(s32) = COPY $a3 + %5:gprb(p0) = G_FRAME_INDEX %fixed-stack.0 + %4:gprb(s32) = G_LOAD %5(p0) :: (load 4 from %fixed-stack.0, align 0) + ADJCALLSTACKDOWN 24, 0, implicit-def $sp, implicit $sp + $a0 = COPY %0(s32) + $a1 = COPY %1(s32) + $a2 = COPY %2(s32) + $a3 = COPY %3(s32) + %7:gprb(p0) = COPY $sp + %8:gprb(s32) = G_CONSTANT i32 16 + %9:gprb(p0) = G_GEP %7, %8(s32) + G_STORE %4(s32), %9(p0) :: (store 4 into stack + 16, align 0) + JAL @f, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit $a2, implicit $a3, implicit-def $v0 + %6:gprb(s32) = COPY $v0 + ADJCALLSTACKUP 24, 0, implicit-def $sp, implicit $sp + $v0 = COPY %6(s32) + RetRA implicit $v0 + +... Index: llvm/trunk/test/CodeGen/Mips/GlobalISel/legalizer/stack_args.mir =================================================================== --- llvm/trunk/test/CodeGen/Mips/GlobalISel/legalizer/stack_args.mir +++ llvm/trunk/test/CodeGen/Mips/GlobalISel/legalizer/stack_args.mir @@ -0,0 +1,62 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32 +--- | + + declare i32 @f(i32, i32, i32, i32, i32) + define void @g(i32, i32, i32, i32, i32) {entry: ret void} + +... +--- +name: g +alignment: 2 +tracksRegLiveness: true +fixedStack: + - { id: 0, offset: 16, size: 4, alignment: 8, stack-id: 0, isImmutable: true } +body: | + bb.1.entry: + liveins: $a0, $a1, $a2, $a3 + + ; MIPS32-LABEL: name: g + ; MIPS32: liveins: $a0, $a1, $a2, $a3 + ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1 + ; MIPS32: [[COPY2:%[0-9]+]]:_(s32) = COPY $a2 + ; MIPS32: [[COPY3:%[0-9]+]]:_(s32) = COPY $a3 + ; MIPS32: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0 + ; MIPS32: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX]](p0) :: (load 4 from %fixed-stack.0, align 0) + ; MIPS32: ADJCALLSTACKDOWN 24, 0, implicit-def $sp, implicit $sp + ; MIPS32: $a0 = COPY [[COPY]](s32) + ; MIPS32: $a1 = COPY [[COPY1]](s32) + ; MIPS32: $a2 = COPY [[COPY2]](s32) + ; MIPS32: $a3 = COPY [[COPY3]](s32) + ; MIPS32: [[COPY4:%[0-9]+]]:_(p0) = COPY $sp + ; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 + ; MIPS32: [[GEP:%[0-9]+]]:_(p0) = G_GEP [[COPY4]], [[C]](s32) + ; MIPS32: G_STORE [[LOAD]](s32), [[GEP]](p0) :: (store 4 into stack + 16, align 0) + ; MIPS32: JAL @f, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit $a2, implicit $a3, implicit-def $v0 + ; MIPS32: [[COPY5:%[0-9]+]]:_(s32) = COPY $v0 + ; MIPS32: ADJCALLSTACKUP 24, 0, implicit-def $sp, implicit $sp + ; MIPS32: $v0 = COPY [[COPY5]](s32) + ; MIPS32: RetRA implicit $v0 + %0:_(s32) = COPY $a0 + %1:_(s32) = COPY $a1 + %2:_(s32) = COPY $a2 + %3:_(s32) = COPY $a3 + %5:_(p0) = G_FRAME_INDEX %fixed-stack.0 + %4:_(s32) = G_LOAD %5(p0) :: (load 4 from %fixed-stack.0, align 0) + ADJCALLSTACKDOWN 24, 0, implicit-def $sp, implicit $sp + $a0 = COPY %0(s32) + $a1 = COPY %1(s32) + $a2 = COPY %2(s32) + $a3 = COPY %3(s32) + %7:_(p0) = COPY $sp + %8:_(s32) = G_CONSTANT i32 16 + %9:_(p0) = G_GEP %7, %8(s32) + G_STORE %4(s32), %9(p0) :: (store 4 into stack + 16, align 0) + JAL @f, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit $a2, implicit $a3, implicit-def $v0 + %6:_(s32) = COPY $v0 + ADJCALLSTACKUP 24, 0, implicit-def $sp, implicit $sp + $v0 = COPY %6(s32) + RetRA implicit $v0 + +... Index: llvm/trunk/test/CodeGen/Mips/GlobalISel/llvm-ir/stack_args.ll =================================================================== --- llvm/trunk/test/CodeGen/Mips/GlobalISel/llvm-ir/stack_args.ll +++ llvm/trunk/test/CodeGen/Mips/GlobalISel/llvm-ir/stack_args.ll @@ -0,0 +1,29 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -O0 -mtriple=mipsel-linux-gnu -global-isel -verify-machineinstrs %s -o -| FileCheck %s -check-prefixes=MIPS32 + +declare i32 @f(i32, i32, i32, i32, i32) + +define i32 @g(i32 %x1, i32 %x2, i32 %x3, i32 %x4, i32 %x5){ +; MIPS32-LABEL: g: +; MIPS32: # %bb.0: # %entry +; MIPS32-NEXT: addiu $sp, $sp, -32 +; MIPS32-NEXT: .cfi_def_cfa_offset 32 +; MIPS32-NEXT: sw $ra, 28($sp) # 4-byte Folded Spill +; MIPS32-NEXT: .cfi_offset 31, -4 +; MIPS32-NEXT: addiu $1, $sp, 48 +; MIPS32-NEXT: lw $1, 0($1) +; MIPS32-NEXT: move $2, $sp +; MIPS32-NEXT: lui $3, 0 +; MIPS32-NEXT: ori $3, $3, 16 +; MIPS32-NEXT: addu $2, $2, $3 +; MIPS32-NEXT: sw $1, 0($2) +; MIPS32-NEXT: jal f +; MIPS32-NEXT: nop +; MIPS32-NEXT: lw $ra, 28($sp) # 4-byte Folded Reload +; MIPS32-NEXT: addiu $sp, $sp, 32 +; MIPS32-NEXT: jr $ra +; MIPS32-NEXT: nop +entry: + %call = call i32 @f(i32 %x1, i32 %x2, i32 %x3, i32 %x4, i32 %x5) + ret i32 %call +} Index: llvm/trunk/test/CodeGen/Mips/GlobalISel/regbankselect/stack_args.mir =================================================================== --- llvm/trunk/test/CodeGen/Mips/GlobalISel/regbankselect/stack_args.mir +++ llvm/trunk/test/CodeGen/Mips/GlobalISel/regbankselect/stack_args.mir @@ -0,0 +1,63 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=regbankselect -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32 +--- | + + declare i32 @f(i32, i32, i32, i32, i32) + define void @g(i32, i32, i32, i32, i32) {entry: ret void} + +... +--- +name: g +alignment: 2 +legalized: true +tracksRegLiveness: true +fixedStack: + - { id: 0, offset: 16, size: 4, alignment: 8, stack-id: 0, isImmutable: true } +body: | + bb.1.entry: + liveins: $a0, $a1, $a2, $a3 + + ; MIPS32-LABEL: name: g + ; MIPS32: liveins: $a0, $a1, $a2, $a3 + ; MIPS32: [[COPY:%[0-9]+]]:gprb(s32) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:gprb(s32) = COPY $a1 + ; MIPS32: [[COPY2:%[0-9]+]]:gprb(s32) = COPY $a2 + ; MIPS32: [[COPY3:%[0-9]+]]:gprb(s32) = COPY $a3 + ; MIPS32: [[FRAME_INDEX:%[0-9]+]]:gprb(p0) = G_FRAME_INDEX %fixed-stack.0 + ; MIPS32: [[LOAD:%[0-9]+]]:gprb(s32) = G_LOAD [[FRAME_INDEX]](p0) :: (load 4 from %fixed-stack.0, align 0) + ; MIPS32: ADJCALLSTACKDOWN 24, 0, implicit-def $sp, implicit $sp + ; MIPS32: $a0 = COPY [[COPY]](s32) + ; MIPS32: $a1 = COPY [[COPY1]](s32) + ; MIPS32: $a2 = COPY [[COPY2]](s32) + ; MIPS32: $a3 = COPY [[COPY3]](s32) + ; MIPS32: [[COPY4:%[0-9]+]]:gprb(p0) = COPY $sp + ; MIPS32: [[C:%[0-9]+]]:gprb(s32) = G_CONSTANT i32 16 + ; MIPS32: [[GEP:%[0-9]+]]:gprb(p0) = G_GEP [[COPY4]], [[C]](s32) + ; MIPS32: G_STORE [[LOAD]](s32), [[GEP]](p0) :: (store 4 into stack + 16, align 0) + ; MIPS32: JAL @f, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit $a2, implicit $a3, implicit-def $v0 + ; MIPS32: [[COPY5:%[0-9]+]]:gprb(s32) = COPY $v0 + ; MIPS32: ADJCALLSTACKUP 24, 0, implicit-def $sp, implicit $sp + ; MIPS32: $v0 = COPY [[COPY5]](s32) + ; MIPS32: RetRA implicit $v0 + %0:_(s32) = COPY $a0 + %1:_(s32) = COPY $a1 + %2:_(s32) = COPY $a2 + %3:_(s32) = COPY $a3 + %5:_(p0) = G_FRAME_INDEX %fixed-stack.0 + %4:_(s32) = G_LOAD %5(p0) :: (load 4 from %fixed-stack.0, align 0) + ADJCALLSTACKDOWN 24, 0, implicit-def $sp, implicit $sp + $a0 = COPY %0(s32) + $a1 = COPY %1(s32) + $a2 = COPY %2(s32) + $a3 = COPY %3(s32) + %7:_(p0) = COPY $sp + %8:_(s32) = G_CONSTANT i32 16 + %9:_(p0) = G_GEP %7, %8(s32) + G_STORE %4(s32), %9(p0) :: (store 4 into stack + 16, align 0) + JAL @f, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit $a2, implicit $a3, implicit-def $v0 + %6:_(s32) = COPY $v0 + ADJCALLSTACKUP 24, 0, implicit-def $sp, implicit $sp + $v0 = COPY %6(s32) + RetRA implicit $v0 + +...