From a284acb8a79468f378452826b2426b4bcdc27e94 Mon Sep 17 00:00:00 2001 From: Akira Hatanaka Date: Wed, 9 May 2012 00:55:21 +0000 Subject: [PATCH] Expand 64-bit shifts if target ABI is O32. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@156457 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Mips/MipsISelLowering.cpp | 84 ++++++++++++++++++++++++++++++++++-- lib/Target/Mips/MipsISelLowering.h | 2 + test/CodeGen/Mips/shift-parts.ll | 29 +++++++++++++ 3 files changed, 112 insertions(+), 3 deletions(-) create mode 100644 test/CodeGen/Mips/shift-parts.ll diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index 337a5e30f4c..d5cc7478081 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -164,6 +164,12 @@ MipsTargetLowering(MipsTargetMachine &TM) setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Custom); } + if (!HasMips64) { + setOperationAction(ISD::SHL_PARTS, MVT::i32, Custom); + setOperationAction(ISD::SRA_PARTS, MVT::i32, Custom); + setOperationAction(ISD::SRL_PARTS, MVT::i32, Custom); + } + setOperationAction(ISD::SDIV, MVT::i32, Expand); setOperationAction(ISD::SREM, MVT::i32, Expand); setOperationAction(ISD::UDIV, MVT::i32, Expand); @@ -199,9 +205,6 @@ MipsTargetLowering(MipsTargetMachine &TM) if (!Subtarget->hasMips64r2()) setOperationAction(ISD::ROTR, MVT::i64, Expand); - setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand); - setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand); - setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand); setOperationAction(ISD::FSIN, MVT::f32, Expand); setOperationAction(ISD::FSIN, MVT::f64, Expand); setOperationAction(ISD::FCOS, MVT::f32, Expand); @@ -750,6 +753,9 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG); case ISD::MEMBARRIER: return LowerMEMBARRIER(Op, DAG); case ISD::ATOMIC_FENCE: return LowerATOMIC_FENCE(Op, DAG); + case ISD::SHL_PARTS: return LowerShiftLeftParts(Op, DAG); + case ISD::SRA_PARTS: return LowerShiftRightParts(Op, DAG, true); + case ISD::SRL_PARTS: return LowerShiftRightParts(Op, DAG, false); } return SDValue(); } @@ -1964,6 +1970,78 @@ SDValue MipsTargetLowering::LowerATOMIC_FENCE(SDValue Op, DAG.getConstant(SType, MVT::i32)); } +SDValue MipsTargetLowering::LowerShiftLeftParts(SDValue Op, + SelectionDAG& DAG) const { + DebugLoc DL = Op.getDebugLoc(); + SDValue Lo = Op.getOperand(0), Hi = Op.getOperand(1); + SDValue Shamt = Op.getOperand(2); + + // if shamt < 32: + // lo = (shl lo, shamt) + // hi = (or (shl hi, shamt) (srl (srl lo, 1), ~shamt)) + // else: + // lo = 0 + // hi = (shl lo, shamt[4:0]) + SDValue Not = DAG.getNode(ISD::XOR, DL, MVT::i32, Shamt, + DAG.getConstant(-1, MVT::i32)); + SDValue ShiftRight1Lo = DAG.getNode(ISD::SRL, DL, MVT::i32, Lo, + DAG.getConstant(1, MVT::i32)); + SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, MVT::i32, ShiftRight1Lo, + Not); + SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, MVT::i32, Hi, Shamt); + SDValue Or = DAG.getNode(ISD::OR, DL, MVT::i32, ShiftLeftHi, ShiftRightLo); + SDValue ShiftLeftLo = DAG.getNode(ISD::SHL, DL, MVT::i32, Lo, Shamt); + SDValue Cond = DAG.getNode(ISD::AND, DL, MVT::i32, Shamt, + DAG.getConstant(0x20, MVT::i32)); + Lo = DAG.getNode(ISD::SELECT, DL, MVT::i32, Cond, DAG.getConstant(0, MVT::i32), + ShiftLeftLo); + Hi = DAG.getNode(ISD::SELECT, DL, MVT::i32, Cond, ShiftLeftLo, Or); + + SDValue Ops[2] = {Lo, Hi}; + return DAG.getMergeValues(Ops, 2, DL); +} + +SDValue MipsTargetLowering::LowerShiftRightParts(SDValue Op, SelectionDAG& DAG, + bool IsSRA) const { + DebugLoc DL = Op.getDebugLoc(); + SDValue Lo = Op.getOperand(0), Hi = Op.getOperand(1); + SDValue Shamt = Op.getOperand(2); + + // if shamt < 32: + // lo = (or (shl (shl hi, 1), ~shamt) (srl lo, shamt)) + // if isSRA: + // hi = (sra hi, shamt) + // else: + // hi = (srl hi, shamt) + // else: + // if isSRA: + // lo = (sra hi, shamt[4:0]) + // hi = (sra hi, 31) + // else: + // lo = (srl hi, shamt[4:0]) + // hi = 0 + SDValue Not = DAG.getNode(ISD::XOR, DL, MVT::i32, Shamt, + DAG.getConstant(-1, MVT::i32)); + SDValue ShiftLeft1Hi = DAG.getNode(ISD::SHL, DL, MVT::i32, Hi, + DAG.getConstant(1, MVT::i32)); + SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, MVT::i32, ShiftLeft1Hi, Not); + SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, MVT::i32, Lo, Shamt); + SDValue Or = DAG.getNode(ISD::OR, DL, MVT::i32, ShiftLeftHi, ShiftRightLo); + SDValue ShiftRightHi = DAG.getNode(IsSRA ? ISD::SRA : ISD::SRL, DL, MVT::i32, + Hi, Shamt); + SDValue Cond = DAG.getNode(ISD::AND, DL, MVT::i32, Shamt, + DAG.getConstant(0x20, MVT::i32)); + SDValue Shift31 = DAG.getNode(ISD::SRA, DL, MVT::i32, Hi, + DAG.getConstant(31, MVT::i32)); + Lo = DAG.getNode(ISD::SELECT, DL, MVT::i32, Cond, ShiftRightHi, Or); + Hi = DAG.getNode(ISD::SELECT, DL, MVT::i32, Cond, + IsSRA ? Shift31 : DAG.getConstant(0, MVT::i32), + ShiftRightHi); + + SDValue Ops[2] = {Lo, Hi}; + return DAG.getMergeValues(Ops, 2, DL); +} + //===----------------------------------------------------------------------===// // Calling Convention Implementation //===----------------------------------------------------------------------===// diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h index f95e0dc47ee..a38bb2f5ee6 100644 --- a/lib/Target/Mips/MipsISelLowering.h +++ b/lib/Target/Mips/MipsISelLowering.h @@ -135,6 +135,8 @@ namespace llvm { SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const; SDValue LowerMEMBARRIER(SDValue Op, SelectionDAG& DAG) const; SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG& DAG) const; + SDValue LowerShiftLeftParts(SDValue Op, SelectionDAG& DAG) const; + SDValue LowerShiftRightParts(SDValue Op, SelectionDAG& DAG, bool IsSRA) const; virtual SDValue LowerFormalArguments(SDValue Chain, diff --git a/test/CodeGen/Mips/shift-parts.ll b/test/CodeGen/Mips/shift-parts.ll new file mode 100644 index 00000000000..38cbf28108c --- /dev/null +++ b/test/CodeGen/Mips/shift-parts.ll @@ -0,0 +1,29 @@ +; RUN: llc -march=mipsel < %s | FileCheck %s + +define i64 @shl0(i64 %a, i32 %b) nounwind readnone { +entry: +; CHECK: shl0 +; CHECK-NOT: lw $25, %call16(__ + %sh_prom = zext i32 %b to i64 + %shl = shl i64 %a, %sh_prom + ret i64 %shl +} + +define i64 @shr1(i64 %a, i32 %b) nounwind readnone { +entry: +; CHECK: shr1 +; CHECK-NOT: lw $25, %call16(__ + %sh_prom = zext i32 %b to i64 + %shr = lshr i64 %a, %sh_prom + ret i64 %shr +} + +define i64 @sra2(i64 %a, i32 %b) nounwind readnone { +entry: +; CHECK: sra2 +; CHECK-NOT: lw $25, %call16(__ + %sh_prom = zext i32 %b to i64 + %shr = ashr i64 %a, %sh_prom + ret i64 %shr +} + -- 2.11.0