diff options
| author | Jim Grosbach <grosbach@apple.com> | 2009-10-31 21:00:56 +0000 | 
|---|---|---|
| committer | Jim Grosbach <grosbach@apple.com> | 2009-10-31 21:00:56 +0000 | 
| commit | 624fcb286ea7e3184fe34e414e5288465e33883c (patch) | |
| tree | 92d25e9ecd78b7c494e1a51f86fcfc3fea725a56 /llvm | |
| parent | ae6bb6159461e2ead080e548abe9ab00ed561f91 (diff) | |
| download | bcm5719-llvm-624fcb286ea7e3184fe34e414e5288465e33883c.tar.gz bcm5719-llvm-624fcb286ea7e3184fe34e414e5288465e33883c.zip  | |
Expand 64-bit arithmetic shift right inline
llvm-svn: 85685
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/lib/Target/ARM/ARMISelLowering.cpp | 37 | ||||
| -rw-r--r-- | llvm/test/CodeGen/ARM/long_shift.ll | 2 | 
2 files changed, 37 insertions, 2 deletions
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp index 6263fbb825f..25fc86fd0f6 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -331,7 +331,7 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)        setOperationAction(ISD::MULHS, MVT::i32, Expand);    }    setOperationAction(ISD::SHL_PARTS, MVT::i32, Custom); -  setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand); +  setOperationAction(ISD::SRA_PARTS, MVT::i32, Custom);    setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand);    setOperationAction(ISD::SRL,       MVT::i64, Custom);    setOperationAction(ISD::SRA,       MVT::i64, Custom); @@ -2096,6 +2096,40 @@ static SDValue getOnesVector(EVT VT, SelectionDAG &DAG, DebugLoc dl) {    return DAG.getNode(ISD::BIT_CONVERT, dl, VT, Vec);  } +/// LowerShiftRightParts - Lower SRA_PARTS, which returns two +/// i32 values and take a 2 x i32 value to shift plus a shift amount. +static SDValue LowerShiftRightParts(SDValue Op, SelectionDAG &DAG, +                                   const ARMSubtarget *ST) { +  assert(Op.getNumOperands() == 3 && "Not a double-shift!"); +  EVT VT = Op.getValueType(); +  unsigned VTBits = VT.getSizeInBits(); +  DebugLoc dl = Op.getDebugLoc(); +  SDValue ShOpLo = Op.getOperand(0); +  SDValue ShOpHi = Op.getOperand(1); +  SDValue ShAmt  = Op.getOperand(2); +  SDValue ARMCC; + +  assert(Op.getOpcode() == ISD::SRA_PARTS); +  SDValue RevShAmt = DAG.getNode(ISD::SUB, dl, MVT::i32, +                                 DAG.getConstant(VTBits, MVT::i32), ShAmt); +  SDValue Tmp1 = DAG.getNode(ISD::SRL, dl, VT, ShOpLo, ShAmt); +  SDValue ExtraShAmt = DAG.getNode(ISD::SUB, dl, MVT::i32, ShAmt, +                                   DAG.getConstant(VTBits, MVT::i32)); +  SDValue Tmp2 = DAG.getNode(ISD::SHL, dl, VT, ShOpHi, RevShAmt); +  SDValue FalseVal = DAG.getNode(ISD::OR, dl, VT, Tmp1, Tmp2); +  SDValue TrueVal = DAG.getNode(ISD::SRA, dl, VT, ShOpHi, ExtraShAmt); + +  SDValue CCR = DAG.getRegister(ARM::CPSR, MVT::i32); +  SDValue Cmp = getARMCmp(ExtraShAmt, DAG.getConstant(0, MVT::i32), ISD::SETGE, +                          ARMCC, DAG, ST->isThumb1Only(), dl); +  SDValue Hi = DAG.getNode(ISD::SRA, dl, VT, ShOpHi, ShAmt); +  SDValue Lo = DAG.getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal, ARMCC, +                           CCR, Cmp); + +  SDValue Ops[2] = { Lo, Hi }; +  return DAG.getMergeValues(Ops, 2, dl); +} +  /// LowerShiftLeftParts - Lower SHL_PARTS, which returns two  /// i32 values and take a 2 x i32 value to shift plus a shift amount.  static SDValue LowerShiftLeftParts(SDValue Op, SelectionDAG &DAG, @@ -2823,6 +2857,7 @@ SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {    case ISD::SRL:    case ISD::SRA:           return LowerShift(Op.getNode(), DAG, Subtarget);    case ISD::SHL_PARTS:     return LowerShiftLeftParts(Op, DAG, Subtarget); +  case ISD::SRA_PARTS:     return LowerShiftRightParts(Op, DAG, Subtarget);    case ISD::VSETCC:        return LowerVSETCC(Op, DAG);    case ISD::BUILD_VECTOR:  return LowerBUILD_VECTOR(Op, DAG);    case ISD::VECTOR_SHUFFLE: return LowerVECTOR_SHUFFLE(Op, DAG); diff --git a/llvm/test/CodeGen/ARM/long_shift.ll b/llvm/test/CodeGen/ARM/long_shift.ll index e72ae785124..0de66542fcf 100644 --- a/llvm/test/CodeGen/ARM/long_shift.ll +++ b/llvm/test/CodeGen/ARM/long_shift.ll @@ -19,7 +19,7 @@ define i32 @f1(i64 %x, i64 %y) {  define i32 @f2(i64 %x, i64 %y) {  ; CHECK: f2 -; CHECK: __ashrdi3 +; CHECK: movge r0, r1, asr r2  	%a = ashr i64 %x, %y  	%b = trunc i64 %a to i32  	ret i32 %b  | 

