Index: lib/Target/Mips/MipsInstructionSelector.cpp =================================================================== --- lib/Target/Mips/MipsInstructionSelector.cpp +++ lib/Target/Mips/MipsInstructionSelector.cpp @@ -338,6 +338,11 @@ I.eraseFromParent(); return true; } + case G_BRINDIRECT: { + MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::PseudoIndirectBranch)) + .add(I.getOperand(0)); + break; + } case G_PHI: { const Register DestReg = I.getOperand(0).getReg(); const unsigned OpSize = MRI.getType(DestReg).getSizeInBits(); Index: lib/Target/Mips/MipsLegalizerInfo.cpp =================================================================== --- lib/Target/Mips/MipsLegalizerInfo.cpp +++ lib/Target/Mips/MipsLegalizerInfo.cpp @@ -77,6 +77,9 @@ getActionDefinitionsBuilder(G_BRJT) .legalFor({{p0, s32}}); + getActionDefinitionsBuilder(G_BRINDIRECT) + .legalFor({p0}); + getActionDefinitionsBuilder(G_PHI) .legalFor({p0, s32, s64}) .minScalar(0, s32); Index: lib/Target/Mips/MipsRegisterBankInfo.cpp =================================================================== --- lib/Target/Mips/MipsRegisterBankInfo.cpp +++ lib/Target/Mips/MipsRegisterBankInfo.cpp @@ -402,6 +402,7 @@ case G_UDIV: case G_SREM: case G_UREM: + case G_BRINDIRECT: OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx]; break; case G_LOAD: { Index: test/CodeGen/Mips/GlobalISel/instruction-select/brindirect.mir =================================================================== --- /dev/null +++ test/CodeGen/Mips/GlobalISel/instruction-select/brindirect.mir @@ -0,0 +1,56 @@ +# 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 +--- | + + define i32 @indirectbr(i8* %addr) { + entry: + indirectbr i8* %addr, [label %L1, label %L2] + + L1: + ret i32 0 + + L2: + ret i32 1 + } + +... +--- +name: indirectbr +alignment: 4 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + ; MIPS32-LABEL: name: indirectbr + ; MIPS32: bb.0.entry: + ; MIPS32: successors: %bb.1(0x40000000), %bb.2(0x40000000) + ; MIPS32: liveins: $a0 + ; MIPS32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0 + ; MIPS32: [[ORi:%[0-9]+]]:gpr32 = ORi $zero, 1 + ; MIPS32: [[ORi1:%[0-9]+]]:gpr32 = ORi $zero, 0 + ; MIPS32: PseudoIndirectBranch [[COPY]] + ; MIPS32: bb.1.L1: + ; MIPS32: $v0 = COPY [[ORi1]] + ; MIPS32: RetRA implicit $v0 + ; MIPS32: bb.2.L2: + ; MIPS32: $v0 = COPY [[ORi]] + ; MIPS32: RetRA implicit $v0 + bb.1.entry: + successors: %bb.2, %bb.3 + liveins: $a0 + + %0:gprb(p0) = COPY $a0 + %1:gprb(s32) = G_CONSTANT i32 1 + %2:gprb(s32) = G_CONSTANT i32 0 + G_BRINDIRECT %0(p0) + + bb.2.L1: + $v0 = COPY %2(s32) + RetRA implicit $v0 + + bb.3.L2: + $v0 = COPY %1(s32) + RetRA implicit $v0 + +... + Index: test/CodeGen/Mips/GlobalISel/legalizer/brindirect.mir =================================================================== --- /dev/null +++ test/CodeGen/Mips/GlobalISel/legalizer/brindirect.mir @@ -0,0 +1,53 @@ +# 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 +--- | + + define i32 @indirectbr(i8* %addr) { + entry: + indirectbr i8* %addr, [label %L1, label %L2] + + L1: + ret i32 0 + + L2: + ret i32 1 + } + +... +--- +name: indirectbr +alignment: 4 +tracksRegLiveness: true +body: | + ; MIPS32-LABEL: name: indirectbr + ; MIPS32: bb.0.entry: + ; MIPS32: successors: %bb.1(0x40000000), %bb.2(0x40000000) + ; MIPS32: liveins: $a0 + ; MIPS32: [[COPY:%[0-9]+]]:_(p0) = COPY $a0 + ; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 + ; MIPS32: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; MIPS32: G_BRINDIRECT [[COPY]](p0) + ; MIPS32: bb.1.L1: + ; MIPS32: $v0 = COPY [[C1]](s32) + ; MIPS32: RetRA implicit $v0 + ; MIPS32: bb.2.L2: + ; MIPS32: $v0 = COPY [[C]](s32) + ; MIPS32: RetRA implicit $v0 + bb.1.entry: + successors: %bb.2, %bb.3 + liveins: $a0 + + %0:_(p0) = COPY $a0 + %1:_(s32) = G_CONSTANT i32 1 + %2:_(s32) = G_CONSTANT i32 0 + G_BRINDIRECT %0(p0) + + bb.2.L1: + $v0 = COPY %2(s32) + RetRA implicit $v0 + + bb.3.L2: + $v0 = COPY %1(s32) + RetRA implicit $v0 + +... Index: test/CodeGen/Mips/GlobalISel/llvm-ir/brindirect.ll =================================================================== --- /dev/null +++ test/CodeGen/Mips/GlobalISel/llvm-ir/brindirect.ll @@ -0,0 +1,33 @@ +; 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 + +define i32 @indirectbr(i8 *%addr) { +; MIPS32-LABEL: indirectbr: +; MIPS32: # %bb.0: # %entry +; MIPS32-NEXT: addiu $sp, $sp, -8 +; MIPS32-NEXT: .cfi_def_cfa_offset 8 +; MIPS32-NEXT: ori $2, $zero, 1 +; MIPS32-NEXT: ori $1, $zero, 0 +; MIPS32-NEXT: sw $2, 4($sp) # 4-byte Folded Spill +; MIPS32-NEXT: sw $1, 0($sp) # 4-byte Folded Spill +; MIPS32-NEXT: jr $4 +; MIPS32-NEXT: nop +; MIPS32-NEXT: $BB0_1: # %L1 +; MIPS32-NEXT: lw $2, 0($sp) # 4-byte Folded Reload +; MIPS32-NEXT: addiu $sp, $sp, 8 +; MIPS32-NEXT: jr $ra +; MIPS32-NEXT: nop +; MIPS32-NEXT: $BB0_2: # %L2 +; MIPS32-NEXT: lw $2, 4($sp) # 4-byte Folded Reload +; MIPS32-NEXT: addiu $sp, $sp, 8 +; MIPS32-NEXT: jr $ra +; MIPS32-NEXT: nop +entry: + indirectbr i8* %addr, [label %L1, label %L2] + +L1: + ret i32 0 + +L2: + ret i32 1 +} Index: test/CodeGen/Mips/GlobalISel/regbankselect/brindirect.mir =================================================================== --- /dev/null +++ test/CodeGen/Mips/GlobalISel/regbankselect/brindirect.mir @@ -0,0 +1,54 @@ +# 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 +--- | + + define i32 @indirectbr(i8* %addr) { + entry: + indirectbr i8* %addr, [label %L1, label %L2] + + L1: + ret i32 0 + + L2: + ret i32 1 + } + +... +--- +name: indirectbr +alignment: 4 +legalized: true +tracksRegLiveness: true +body: | + ; MIPS32-LABEL: name: indirectbr + ; MIPS32: bb.0.entry: + ; MIPS32: successors: %bb.1(0x40000000), %bb.2(0x40000000) + ; MIPS32: liveins: $a0 + ; MIPS32: [[COPY:%[0-9]+]]:gprb(p0) = COPY $a0 + ; MIPS32: [[C:%[0-9]+]]:gprb(s32) = G_CONSTANT i32 1 + ; MIPS32: [[C1:%[0-9]+]]:gprb(s32) = G_CONSTANT i32 0 + ; MIPS32: G_BRINDIRECT [[COPY]](p0) + ; MIPS32: bb.1.L1: + ; MIPS32: $v0 = COPY [[C1]](s32) + ; MIPS32: RetRA implicit $v0 + ; MIPS32: bb.2.L2: + ; MIPS32: $v0 = COPY [[C]](s32) + ; MIPS32: RetRA implicit $v0 + bb.1.entry: + successors: %bb.2, %bb.3 + liveins: $a0 + + %0:_(p0) = COPY $a0 + %1:_(s32) = G_CONSTANT i32 1 + %2:_(s32) = G_CONSTANT i32 0 + G_BRINDIRECT %0(p0) + + bb.2.L1: + $v0 = COPY %2(s32) + RetRA implicit $v0 + + bb.3.L2: + $v0 = COPY %1(s32) + RetRA implicit $v0 + +...