Index: lib/CodeGen/SelectionDAG/LegalizeDAG.cpp =================================================================== --- lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -3689,6 +3689,9 @@ unsigned EntrySize = DAG.getMachineFunction().getJumpTableInfo()->getEntrySize(TD); + // TODO: Should we turn this into a shift if entry size is a power of 2 + // This would stop MIPS from emitting a dmult+dmlfo for this but could + // it possibly break other targets? Index = DAG.getNode(ISD::MUL, dl, Index.getValueType(), Index, DAG.getConstant(EntrySize, dl, Index.getValueType())); SDValue Addr = DAG.getNode(ISD::ADD, dl, Index.getValueType(), Index: lib/Target/Mips/MipsSEISelLowering.cpp =================================================================== --- lib/Target/Mips/MipsSEISelLowering.cpp +++ lib/Target/Mips/MipsSEISelLowering.cpp @@ -1226,6 +1226,21 @@ EVT Ty = Op.getOperand(0).getValueType(); SDLoc DL(Op); + + // Turn constant power-of-two multiplications that only need lo into a shift: + // FIXME: this is probably the wrong place to do this transformation but it is + // needed to avoid emitting a li/dmult/dmflo instead of a single shift with an + // immediate operand during the lowering of jump tables + if ((NewOpc == MipsISD::Mult || NewOpc == MipsISD::Multu) && HasLo && + !HasHi) { + if (ConstantSDNode *CImm = dyn_cast(Op.getOperand(1))) { + const APInt &Val = CImm->getAPIntValue(); + if (Val.isStrictlyPositive() && Val.isPowerOf2()) + return DAG.getNode(ISD::SHL, DL, Ty, Op->getOperand(0), + DAG.getConstant(Val.logBase2(), DL, Ty)); + } + } + SDValue Mult = DAG.getNode(NewOpc, DL, MVT::Untyped, Op.getOperand(0), Op.getOperand(1)); SDValue Lo, Hi; Index: test/CodeGen/Mips/2010-07-20-Switch.ll =================================================================== --- test/CodeGen/Mips/2010-07-20-Switch.ll +++ test/CodeGen/Mips/2010-07-20-Switch.ll @@ -28,7 +28,8 @@ ; PIC-O32: addu $[[R5:[0-9]+]], $[[R4:[0-9]+]] ; PIC-O32: jr $[[R5]] -; STATIC-N64: mflo $[[R0:[0-9]]] +; STATIC-N64: dsrl $[[I32:[0-9]]], ${{[0-9]+}}, 32 +; STATIC-N64: dsll $[[R0:[0-9]]], $[[I32]], 3 ; STATIC-N64: lui $[[R1:[0-9]]], %highest(.LJTI0_0) ; STATIC-N64: daddiu $[[R2:[0-9]]], $[[R1]], %higher(.LJTI0_0) ; STATIC-N64: dsll $[[R3:[0-9]]], $[[R2]], 16 Index: test/CodeGen/Mips/indirect-jump-hazard/jumptables.ll =================================================================== --- test/CodeGen/Mips/indirect-jump-hazard/jumptables.ll +++ test/CodeGen/Mips/indirect-jump-hazard/jumptables.ll @@ -161,9 +161,7 @@ ; MIPS64R2-NEXT: beqz $1, .LBB0_3 ; MIPS64R2-NEXT: nop ; MIPS64R2-NEXT: .LBB0_1: # %entry -; MIPS64R2-NEXT: daddiu $1, $zero, 8 -; MIPS64R2-NEXT: dmult $2, $1 -; MIPS64R2-NEXT: mflo $1 +; MIPS64R2-NEXT: dsll $1, $2, 3 ; MIPS64R2-NEXT: lui $2, %highest(.LJTI0_0) ; MIPS64R2-NEXT: daddiu $2, $2, %higher(.LJTI0_0) ; MIPS64R2-NEXT: dsll $2, $2, 16 @@ -481,9 +479,7 @@ ; PIC-MIPS64R2-NEXT: beqz $1, .LBB0_3 ; PIC-MIPS64R2-NEXT: nop ; PIC-MIPS64R2-NEXT: .LBB0_1: # %entry -; PIC-MIPS64R2-NEXT: daddiu $1, $zero, 8 -; PIC-MIPS64R2-NEXT: dmult $3, $1 -; PIC-MIPS64R2-NEXT: mflo $1 +; PIC-MIPS64R2-NEXT: dsll $1, $3, 3 ; PIC-MIPS64R2-NEXT: ld $3, %got_page(.LJTI0_0)($2) ; PIC-MIPS64R2-NEXT: daddu $1, $1, $3 ; PIC-MIPS64R2-NEXT: ld $1, %got_ofst(.LJTI0_0)($1) Index: test/CodeGen/Mips/jump-table-mul.ll =================================================================== --- /dev/null +++ test/CodeGen/Mips/jump-table-mul.ll @@ -0,0 +1,72 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; We used to generate a mul+mflo sequence instead of shifting by 2/3 to get the jump table address +; RUN: llc %s -O2 -mtriple=mips64-unknown-freebsd -target-abi n64 -relocation-model=pic -o /dev/null -debug +; RUN: llc %s -O2 -mtriple=mips64-unknown-freebsd -target-abi n64 -relocation-model=pic -o - | FileCheck %s + +; Function Attrs: noreturn nounwind +define i64 @test(i64 %arg) local_unnamed_addr #0 { +; CHECK-LABEL: test: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: lui $1, %hi(%neg(%gp_rel(test))) +; CHECK-NEXT: daddu $2, $1, $25 +; CHECK-NEXT: sltiu $1, $4, 11 +; CHECK-NEXT: beqz $1, .LBB0_3 +; CHECK-NEXT: nop +; CHECK-NEXT: .LBB0_1: # %entry +; CHECK-NEXT: daddiu $1, $2, %lo(%neg(%gp_rel(test))) +; CHECK-NEXT: dsll $2, $4, 3 +; Previously this dsll was the following sequence: +; daddiu $2, $zero, 8 +; dmult $4, $2 +; mflo $2 +; CHECK-NEXT: ld $3, %got_page(.LJTI0_0)($1) +; CHECK-NEXT: daddu $2, $2, $3 +; CHECK-NEXT: ld $2, %got_ofst(.LJTI0_0)($2) +; CHECK-NEXT: daddu $1, $2, $1 +; CHECK-NEXT: jr $1 +; CHECK-NEXT: nop +; CHECK-NEXT: .LBB0_2: # %sw.bb +; CHECK-NEXT: jr $ra +; CHECK-NEXT: daddiu $2, $zero, 1 +; CHECK-NEXT: .LBB0_3: # %default +; CHECK-NEXT: jr $ra +; CHECK-NEXT: daddiu $2, $zero, 1234 +; CHECK-NEXT: .LBB0_4: # %sw.bb1 +; CHECK-NEXT: jr $ra +; CHECK-NEXT: daddiu $2, $zero, 0 +entry: + switch i64 %arg, label %default [ + i64 0, label %sw.bb + i64 3, label %sw.bb + i64 5, label %sw.bb + i64 10, label %sw.bb1 + ] + +default: + ret i64 1234 + +sw.bb: + ret i64 1 + +sw.bb1: + ret i64 0 +} + +; CHECK-LABEL: .section .rodata,"a",@progbits +; CHECK-NEXT: .p2align 3 +; CHECK-LABEL: .LJTI0_0: +; CHECK-NEXT: .gpdword .LBB0_2 +; CHECK-NEXT: .gpdword .LBB0_3 +; CHECK-NEXT: .gpdword .LBB0_3 +; CHECK-NEXT: .gpdword .LBB0_2 +; CHECK-NEXT: .gpdword .LBB0_3 +; CHECK-NEXT: .gpdword .LBB0_2 +; CHECK-NEXT: .gpdword .LBB0_3 +; CHECK-NEXT: .gpdword .LBB0_3 +; CHECK-NEXT: .gpdword .LBB0_3 +; CHECK-NEXT: .gpdword .LBB0_3 +; CHECK-NEXT: .gpdword .LBB0_4 + + + +attributes #0 = { noreturn nounwind }