[llvm] r288541 - [lanai] Custom lowering of SHL_PARTS

Jacques Pienaar via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 2 14:01:28 PST 2016


Author: jpienaar
Date: Fri Dec  2 16:01:28 2016
New Revision: 288541

URL: http://llvm.org/viewvc/llvm-project?rev=288541&view=rev
Log:
[lanai] Custom lowering of SHL_PARTS

Summary: Implement custom lowering of SHL_PARTS to enable lowering of left shift with larger than 32-bit shifts.

Reviewers: eliben, majnemer

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D27232

Added:
    llvm/trunk/test/CodeGen/Lanai/lshift64.ll
Modified:
    llvm/trunk/lib/Target/Lanai/LanaiISelLowering.cpp
    llvm/trunk/lib/Target/Lanai/LanaiISelLowering.h

Modified: llvm/trunk/lib/Target/Lanai/LanaiISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Lanai/LanaiISelLowering.cpp?rev=288541&r1=288540&r2=288541&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Lanai/LanaiISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/Lanai/LanaiISelLowering.cpp Fri Dec  2 16:01:28 2016
@@ -104,7 +104,7 @@ LanaiTargetLowering::LanaiTargetLowering
 
   setOperationAction(ISD::ROTR, MVT::i32, Expand);
   setOperationAction(ISD::ROTL, MVT::i32, Expand);
-  setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);
+  setOperationAction(ISD::SHL_PARTS, MVT::i32, Custom);
   setOperationAction(ISD::SRL_PARTS, MVT::i32, Custom);
   setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand);
 
@@ -179,6 +179,8 @@ SDValue LanaiTargetLowering::LowerOperat
     return LowerSETCC(Op, DAG);
   case ISD::SETCCE:
     return LowerSETCCE(Op, DAG);
+  case ISD::SHL_PARTS:
+    return LowerSHL_PARTS(Op, DAG);
   case ISD::SRL_PARTS:
     return LowerSRL_PARTS(Op, DAG);
   case ISD::VASTART:
@@ -1233,6 +1235,55 @@ SDValue LanaiTargetLowering::LowerJumpTa
   }
 }
 
+SDValue LanaiTargetLowering::LowerSHL_PARTS(SDValue Op,
+                                            SelectionDAG &DAG) const {
+  EVT VT = Op.getValueType();
+  unsigned VTBits = VT.getSizeInBits();
+  SDLoc dl(Op);
+  assert(Op.getNumOperands() == 3 && "Unexpected SHL!");
+  SDValue ShOpLo = Op.getOperand(0);
+  SDValue ShOpHi = Op.getOperand(1);
+  SDValue ShAmt = Op.getOperand(2);
+
+  // Performs the following for (ShOpLo + (ShOpHi << 32)) << ShAmt:
+  //   LoBitsForHi = (ShAmt == 0) ? 0 : (ShOpLo >> (32-ShAmt))
+  //   HiBitsForHi = ShOpHi << ShAmt
+  //   Hi = (ShAmt >= 32) ? (ShOpLo << (ShAmt-32)) : (LoBitsForHi | HiBitsForHi)
+  //   Lo = (ShAmt >= 32) ? 0 : (ShOpLo << ShAmt)
+  //   return (Hi << 32) | Lo;
+
+  SDValue RevShAmt = DAG.getNode(ISD::SUB, dl, MVT::i32,
+                                 DAG.getConstant(VTBits, dl, MVT::i32), ShAmt);
+  SDValue LoBitsForHi = DAG.getNode(ISD::SRL, dl, VT, ShOpLo, RevShAmt);
+
+  // If ShAmt == 0, we just calculated "(SRL ShOpLo, 32)" which is "undef". We
+  // wanted 0, so CSEL it directly.
+  SDValue Zero = DAG.getConstant(0, dl, MVT::i32);
+  SDValue SetCC = DAG.getSetCC(dl, MVT::i32, ShAmt, Zero, ISD::SETEQ);
+  LoBitsForHi = DAG.getSelect(dl, MVT::i32, SetCC, Zero, LoBitsForHi);
+
+  SDValue ExtraShAmt = DAG.getNode(ISD::SUB, dl, MVT::i32, ShAmt,
+                                   DAG.getConstant(VTBits, dl, MVT::i32));
+  SDValue HiBitsForHi = DAG.getNode(ISD::SHL, dl, VT, ShOpHi, ShAmt);
+  SDValue HiForNormalShift =
+      DAG.getNode(ISD::OR, dl, VT, LoBitsForHi, HiBitsForHi);
+
+  SDValue HiForBigShift = DAG.getNode(ISD::SHL, dl, VT, ShOpLo, ExtraShAmt);
+
+  SetCC = DAG.getSetCC(dl, MVT::i32, ExtraShAmt, Zero, ISD::SETGE);
+  SDValue Hi =
+      DAG.getSelect(dl, MVT::i32, SetCC, HiForBigShift, HiForNormalShift);
+
+  // Lanai shifts of larger than register sizes are wrapped rather than
+  // clamped, so we can't just emit "lo << b" if b is too big.
+  SDValue LoForNormalShift = DAG.getNode(ISD::SHL, dl, VT, ShOpLo, ShAmt);
+  SDValue Lo = DAG.getSelect(
+      dl, MVT::i32, SetCC, DAG.getConstant(0, dl, MVT::i32), LoForNormalShift);
+
+  SDValue Ops[2] = {Lo, Hi};
+  return DAG.getMergeValues(Ops, dl);
+}
+
 SDValue LanaiTargetLowering::LowerSRL_PARTS(SDValue Op,
                                             SelectionDAG &DAG) const {
   MVT VT = Op.getSimpleValueType();

Modified: llvm/trunk/lib/Target/Lanai/LanaiISelLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Lanai/LanaiISelLowering.h?rev=288541&r1=288540&r2=288541&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Lanai/LanaiISelLowering.h (original)
+++ llvm/trunk/lib/Target/Lanai/LanaiISelLowering.h Fri Dec  2 16:01:28 2016
@@ -88,6 +88,7 @@ public:
   SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerSETCCE(SDValue Op, SelectionDAG &DAG) const;
+  SDValue LowerSHL_PARTS(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerSRL_PARTS(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const;
 

Added: llvm/trunk/test/CodeGen/Lanai/lshift64.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Lanai/lshift64.ll?rev=288541&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/Lanai/lshift64.ll (added)
+++ llvm/trunk/test/CodeGen/Lanai/lshift64.ll Fri Dec  2 16:01:28 2016
@@ -0,0 +1,24 @@
+; RUN: llc < %s -mtriple=lanai-unknown-unknown | FileCheck %s
+
+; Test left-shift i64 lowering does not result in call being inserted.
+
+; CHECK-LABEL: shift
+; CHECKT: bt __ashldi3
+; CHECK: or	%r0, 0x0, %r[[T0:[0-9]+]]
+; CHECK: mov	0x20, %r[[T1:[0-9]+]]
+; CHECK: sub	%r[[T1]], %r[[ShAmt:[0-9]+]], %r[[T1]]
+; CHECK: sub	%r0, %r[[T1]], %r[[T1]]
+; CHECK: sh	%r[[ShOpB:[0-9]+]], %r[[T1]], %r[[T1]]
+; CHECK: sub.f	%r[[ShAmt]], 0x0, %r0
+; CHECK: sel.eq %r0, %r[[T1]], %r[[T1]]
+; CHECK: sh	%r[[ShOpA:[0-9]+]], %r[[ShAmt]], %r[[T2:[0-9]+]]
+; CHECK: or	%r[[T1]], %r[[T2]], %rv
+; CHECK: sub.f	%r[[ShAmt]], 0x20, %r[[T1]]
+; CHECK: sh.pl	%r[[ShOpB]], %r[[T1]], %rv
+; CHECK: sh.mi	%r[[ShOpB]], %r[[ShAmt]], %r[[T0]]
+
+define i64 @shift(i64 inreg, i32 inreg) {
+  %3 = zext i32 %1 to i64
+  %4 = shl i64 %0, %3
+  ret i64 %4
+}




More information about the llvm-commits mailing list