From d984dc6c9d4f292087f5b10621094874503678f5 Mon Sep 17 00:00:00 2001 From: Anton Korobeynikov Date: Thu, 16 Jul 2009 13:56:42 +0000 Subject: [PATCH] Provide "wide" muls and divs/rems llvm-svn: 75958 --- lib/Target/SystemZ/SystemZISelLowering.cpp | 15 +-- lib/Target/SystemZ/SystemZInstrInfo.cpp | 12 ++- lib/Target/SystemZ/SystemZInstrInfo.td | 102 +++++++++++++++++++++ test/CodeGen/SystemZ/08-DivRem.ll | 55 +++++++++++ 4 files changed, 170 insertions(+), 14 deletions(-) create mode 100644 test/CodeGen/SystemZ/08-DivRem.ll diff --git a/lib/Target/SystemZ/SystemZISelLowering.cpp b/lib/Target/SystemZ/SystemZISelLowering.cpp index a5999feaa3e..62bd46b011c 100644 --- a/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -41,8 +41,9 @@ SystemZTargetLowering::SystemZTargetLowering(SystemZTargetMachine &tm) : RegInfo = TM.getRegisterInfo(); // Set up the register classes. - addRegisterClass(MVT::i32, SystemZ::GR32RegisterClass); - addRegisterClass(MVT::i64, SystemZ::GR64RegisterClass); + addRegisterClass(MVT::i32, SystemZ::GR32RegisterClass); + addRegisterClass(MVT::i64, SystemZ::GR64RegisterClass); + addRegisterClass(MVT::i128, SystemZ::GR128RegisterClass); // Compute derived properties from the register classes computeRegisterProperties(); @@ -73,16 +74,10 @@ SystemZTargetLowering::SystemZTargetLowering(SystemZTargetMachine &tm) : setOperationAction(ISD::SELECT_CC, MVT::i32, Custom); setOperationAction(ISD::SELECT_CC, MVT::i64, Custom); - // FIXME: We can lower this better - setOperationAction(ISD::MULHS, MVT::i32, Expand); + // Funny enough: we don't have 64-bit signed versions of these stuff, but have + // unsigned. setOperationAction(ISD::MULHS, MVT::i64, Expand); - setOperationAction(ISD::MULHU, MVT::i32, Expand); - setOperationAction(ISD::MULHU, MVT::i64, Expand); - - setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand); setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand); - setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand); - setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand); } SDValue SystemZTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) { diff --git a/lib/Target/SystemZ/SystemZInstrInfo.cpp b/lib/Target/SystemZ/SystemZInstrInfo.cpp index 9734709c6b3..0348e1e5ca8 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.cpp +++ b/lib/Target/SystemZ/SystemZInstrInfo.cpp @@ -83,18 +83,20 @@ bool SystemZInstrInfo::copyRegToReg(MachineBasicBlock &MBB, CommonRC = 0; if (CommonRC) { - unsigned Opc; if (CommonRC == &SystemZ::GR64RegClass || CommonRC == &SystemZ::ADDR64RegClass) { - Opc = SystemZ::MOV64rr; + BuildMI(MBB, I, DL, get(SystemZ::MOV64rr), DestReg).addReg(SrcReg); } else if (CommonRC == &SystemZ::GR32RegClass || CommonRC == &SystemZ::ADDR32RegClass) { - Opc = SystemZ::MOV32rr; + BuildMI(MBB, I, DL, get(SystemZ::MOV32rr), DestReg).addReg(SrcReg); + } else if (CommonRC == &SystemZ::GR64PRegClass) { + BuildMI(MBB, I, DL, get(SystemZ::MOV64rrP), DestReg).addReg(SrcReg); + } else if (CommonRC == &SystemZ::GR128RegClass) { + BuildMI(MBB, I, DL, get(SystemZ::MOV128rr), DestReg).addReg(SrcReg); } else { return false; } - BuildMI(MBB, I, DL, get(Opc), DestReg).addReg(SrcReg); return true; } @@ -126,6 +128,8 @@ SystemZInstrInfo::isMoveInstr(const MachineInstr& MI, return false; case SystemZ::MOV32rr: case SystemZ::MOV64rr: + case SystemZ::MOV64rrP: + case SystemZ::MOV128rr: assert(MI.getNumOperands() >= 2 && MI.getOperand(0).isReg() && MI.getOperand(1).isReg() && diff --git a/lib/Target/SystemZ/SystemZInstrInfo.td b/lib/Target/SystemZ/SystemZInstrInfo.td index 4b5a9ce3ba9..f58021cf737 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.td +++ b/lib/Target/SystemZ/SystemZInstrInfo.td @@ -330,6 +330,16 @@ def MOV32rr : Pseudo<(outs GR32:$dst), (ins GR32:$src), def MOV64rr : Pseudo<(outs GR64:$dst), (ins GR64:$src), "lgr\t{$dst, $src}", []>; +def MOV128rr : Pseudo<(outs GR128:$dst), (ins GR128:$src), + "# MOV128 PSEUDO!" + "lgr\t{$dst:subreg_odd, $src:subreg_odd}\n" + "lgr\t{$dst:subreg_even, $src:subreg_even}", + []>; +def MOV64rrP : Pseudo<(outs GR64P:$dst), (ins GR64P:$src), + "# MOV64P PSEUDO!" + "lr\t{$dst:subreg_odd, $src:subreg_odd}\n" + "lr\t{$dst:subreg_even, $src:subreg_even}", + []>; } def MOVSX64rr32 : Pseudo<(outs GR64:$dst), (ins GR32:$src), @@ -616,8 +626,19 @@ def MUL32rr : Pseudo<(outs GR32:$dst), (ins GR32:$src1, GR32:$src2), def MUL64rr : Pseudo<(outs GR64:$dst), (ins GR64:$src1, GR64:$src2), "msgr\t{$dst, $src2}", [(set GR64:$dst, (mul GR64:$src1, GR64:$src2))]>; + +def MUL64rrP : Pseudo<(outs GR64P:$dst), (ins GR64P:$src1, GR32:$src2), + "mr\t{$dst, $src2}", + []>; +def UMUL64rrP : Pseudo<(outs GR64P:$dst), (ins GR64P:$src1, GR32:$src2), + "mlr\t{$dst, $src2}", + []>; +def UMUL128rrP : Pseudo<(outs GR128:$dst), (ins GR128:$src1, GR64:$src2), + "mlgr\t{$dst, $src2}", + []>; } + def MUL32ri16 : Pseudo<(outs GR32:$dst), (ins GR32:$src1, i32i16imm:$src2), "mhi\t{$dst, $src2}", [(set GR32:$dst, (mul GR32:$src1, i32immSExt16:$src2))]>; @@ -641,6 +662,23 @@ def MUL64rm : Pseudo<(outs GR64:$dst), (ins GR64:$src1, rriaddr:$src2), def MULSX64rr32 : Pseudo<(outs GR64:$dst), (ins GR64:$src1, GR32:$src2), "msgfr\t{$dst, $src2}", [(set GR64:$dst, (mul GR64:$src1, (sext GR32:$src2)))]>; + +def SDIVREM64rrP : Pseudo<(outs GR64P:$dst), (ins GR64P:$src1, GR32:$src2), + "dr\t{$dst, $src2}", + []>; + +def SDIVREM128rrP : Pseudo<(outs GR128:$dst), (ins GR128:$src1, GR64:$src2), + "dsgr\t{$dst, $src2}", + []>; + +def UDIVREM64rrP : Pseudo<(outs GR64P:$dst), (ins GR64P:$src1, GR32:$src2), + "dlr\t{$dst, $src2}", + []>; + +def UDIVREM128rrP : Pseudo<(outs GR128:$dst), (ins GR128:$src1, GR64:$src2), + "dlgr\t{$dst, $src2}", + []>; + } // isTwoAddress = 1 //===----------------------------------------------------------------------===// @@ -794,3 +832,67 @@ def : Pat<(SystemZcall (i64 tglobaladdr:$dst)), (CALLi tglobaladdr:$dst)>; def : Pat<(SystemZcall (i64 texternalsym:$dst)), (CALLi texternalsym:$dst)>; + +// muls +def : Pat<(mulhs GR32:$src1, GR32:$src2), + (EXTRACT_SUBREG (MUL64rrP (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + GR32:$src1, subreg_odd), + GR32:$src2), + subreg_even)>; + +def : Pat<(mulhu GR32:$src1, GR32:$src2), + (EXTRACT_SUBREG (UMUL64rrP (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + GR32:$src1, subreg_odd), + GR32:$src2), + subreg_even)>; +def : Pat<(mulhu GR64:$src1, GR64:$src2), + (EXTRACT_SUBREG (UMUL128rrP (INSERT_SUBREG (i128 (IMPLICIT_DEF)), + GR64:$src1, subreg_odd), + GR64:$src2), + subreg_even)>; + +// divs +// FIXME: Add memory versions +def : Pat<(sdiv GR32:$src1, GR32:$src2), + (EXTRACT_SUBREG (SDIVREM64rrP (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + GR32:$src1, subreg_odd), + GR32:$src2), + subreg_odd)>; +def : Pat<(sdiv GR64:$src1, GR64:$src2), + (EXTRACT_SUBREG (SDIVREM128rrP (INSERT_SUBREG (i128 (IMPLICIT_DEF)), + GR64:$src1, subreg_odd), + GR64:$src2), + subreg_odd)>; +def : Pat<(udiv GR32:$src1, GR32:$src2), + (EXTRACT_SUBREG (UDIVREM64rrP (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + GR32:$src1, subreg_odd), + GR32:$src2), + subreg_odd)>; +def : Pat<(udiv GR64:$src1, GR64:$src2), + (EXTRACT_SUBREG (UDIVREM128rrP (INSERT_SUBREG (i128 (IMPLICIT_DEF)), + GR64:$src1, subreg_odd), + GR64:$src2), + subreg_odd)>; + +// rems +// FIXME: Add memory versions +def : Pat<(srem GR32:$src1, GR32:$src2), + (EXTRACT_SUBREG (SDIVREM64rrP (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + GR32:$src1, subreg_odd), + GR32:$src2), + subreg_even)>; +def : Pat<(srem GR64:$src1, GR64:$src2), + (EXTRACT_SUBREG (SDIVREM128rrP (INSERT_SUBREG (i128 (IMPLICIT_DEF)), + GR64:$src1, subreg_odd), + GR64:$src2), + subreg_even)>; +def : Pat<(urem GR32:$src1, GR32:$src2), + (EXTRACT_SUBREG (UDIVREM64rrP (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + GR32:$src1, subreg_odd), + GR32:$src2), + subreg_even)>; +def : Pat<(urem GR64:$src1, GR64:$src2), + (EXTRACT_SUBREG (UDIVREM128rrP (INSERT_SUBREG (i128 (IMPLICIT_DEF)), + GR64:$src1, subreg_odd), + GR64:$src2), + subreg_even)>; diff --git a/test/CodeGen/SystemZ/08-DivRem.ll b/test/CodeGen/SystemZ/08-DivRem.ll new file mode 100644 index 00000000000..ea9214f812f --- /dev/null +++ b/test/CodeGen/SystemZ/08-DivRem.ll @@ -0,0 +1,55 @@ +; RUN: llvm-as < %s | llc | grep dsgr | count 2 +; RUN: llvm-as < %s | llc | grep dr | count 2 +; RUN: llvm-as < %s | llc | grep dlr | count 2 +; RUN: llvm-as < %s | llc | grep dlgr | count 2 + +target datalayout = "E-p:64:64:64-i1:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f128:128:128" +target triple = "s390x-unknown-linux-gnu" + +define i64 @div(i64 %a, i64 %b) nounwind readnone { +entry: + %div = sdiv i64 %a, %b ; [#uses=1] + ret i64 %div +} + +define i32 @div1(i32 %a, i32 %b) nounwind readnone { +entry: + %div = sdiv i32 %a, %b ; [#uses=1] + ret i32 %div +} + +define i64 @div2(i64 %a, i64 %b) nounwind readnone { +entry: + %div = udiv i64 %a, %b ; [#uses=1] + ret i64 %div +} + +define i32 @div3(i32 %a, i32 %b) nounwind readnone { +entry: + %div = udiv i32 %a, %b ; [#uses=1] + ret i32 %div +} + +define i64 @rem(i64 %a, i64 %b) nounwind readnone { +entry: + %rem = srem i64 %a, %b ; [#uses=1] + ret i64 %rem +} + +define i32 @rem1(i32 %a, i32 %b) nounwind readnone { +entry: + %rem = srem i32 %a, %b ; [#uses=1] + ret i32 %rem +} + +define i64 @rem2(i64 %a, i64 %b) nounwind readnone { +entry: + %rem = urem i64 %a, %b ; [#uses=1] + ret i64 %rem +} + +define i32 @rem3(i32 %a, i32 %b) nounwind readnone { +entry: + %rem = urem i32 %a, %b ; [#uses=1] + ret i32 %rem +}