diff options
| author | Akira Hatanaka <ahatanaka@mips.com> | 2012-05-09 00:55:21 +0000 | 
|---|---|---|
| committer | Akira Hatanaka <ahatanaka@mips.com> | 2012-05-09 00:55:21 +0000 | 
| commit | 0a8ab718cb2e415acd0c0d14152a81893cd28573 (patch) | |
| tree | a7f5e3c769c16fefbdc02de47347445fe8886f05 | |
| parent | edf46e6b6e3d96c8b189a3aa03d6e2c84f212fed (diff) | |
| download | bcm5719-llvm-0a8ab718cb2e415acd0c0d14152a81893cd28573.tar.gz bcm5719-llvm-0a8ab718cb2e415acd0c0d14152a81893cd28573.zip  | |
Expand 64-bit shifts if target ABI is O32.
llvm-svn: 156457
| -rw-r--r-- | llvm/lib/Target/Mips/MipsISelLowering.cpp | 84 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MipsISelLowering.h | 2 | ||||
| -rw-r--r-- | llvm/test/CodeGen/Mips/shift-parts.ll | 29 | 
3 files changed, 112 insertions, 3 deletions
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp index 337a5e30f4c..d5cc7478081 100644 --- a/llvm/lib/Target/Mips/MipsISelLowering.cpp +++ b/llvm/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/llvm/lib/Target/Mips/MipsISelLowering.h b/llvm/lib/Target/Mips/MipsISelLowering.h index f95e0dc47ee..a38bb2f5ee6 100644 --- a/llvm/lib/Target/Mips/MipsISelLowering.h +++ b/llvm/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/llvm/test/CodeGen/Mips/shift-parts.ll b/llvm/test/CodeGen/Mips/shift-parts.ll new file mode 100644 index 00000000000..38cbf28108c --- /dev/null +++ b/llvm/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 +} +  | 

