From 26f23b1dfa9ce68fa455eb18f8cdd221efe13210 Mon Sep 17 00:00:00 2001 From: Jacques Pienaar Date: Thu, 14 Apr 2016 17:59:22 +0000 Subject: [PATCH] [lanai] Add custom lowering for SRL_PARTS i32. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@266349 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Lanai/LanaiISelLowering.cpp | 44 +++++++++++++++++++++++++- lib/Target/Lanai/LanaiISelLowering.h | 1 + test/CodeGen/Lanai/rshift64.ll | 12 +++++++ 3 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 test/CodeGen/Lanai/rshift64.ll diff --git a/lib/Target/Lanai/LanaiISelLowering.cpp b/lib/Target/Lanai/LanaiISelLowering.cpp index b18e04dc6a0..b2c47429bad 100644 --- a/lib/Target/Lanai/LanaiISelLowering.cpp +++ b/lib/Target/Lanai/LanaiISelLowering.cpp @@ -104,7 +104,7 @@ LanaiTargetLowering::LanaiTargetLowering(const TargetMachine &TM, setOperationAction(ISD::ROTR, MVT::i32, Expand); setOperationAction(ISD::ROTL, MVT::i32, Expand); setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand); - setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand); + setOperationAction(ISD::SRL_PARTS, MVT::i32, Custom); setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand); setOperationAction(ISD::BSWAP, MVT::i32, Expand); @@ -169,6 +169,8 @@ SDValue LanaiTargetLowering::LowerOperation(SDValue Op, return LowerSELECT_CC(Op, DAG); case ISD::SETCC: return LowerSETCC(Op, DAG); + case ISD::SRL_PARTS: + return LowerSRL_PARTS(Op, DAG); case ISD::VASTART: return LowerVASTART(Op, DAG); case ISD::DYNAMIC_STACKALLOC: @@ -1205,3 +1207,43 @@ SDValue LanaiTargetLowering::LowerJumpTable(SDValue Op, return Result; } } + +SDValue LanaiTargetLowering::LowerSRL_PARTS(SDValue Op, + SelectionDAG &DAG) const { + MVT VT = Op.getSimpleValueType(); + unsigned VTBits = VT.getSizeInBits(); + SDLoc dl(Op); + SDValue ShOpLo = Op.getOperand(0); + SDValue ShOpHi = Op.getOperand(1); + SDValue ShAmt = Op.getOperand(2); + + // Performs the following for a >> b: + // unsigned r_high = a_high >> b; + // r_high = (32 - b <= 0) ? 0 : r_high; + // + // unsigned r_low = a_low >> b; + // r_low = (32 - b <= 0) ? r_high : r_low; + // r_low = (b == 0) ? r_low : r_low | (a_high << (32 - b)); + // return (unsigned long long)r_high << 32 | r_low; + // Note: This takes advantage of Lanai's shift behavior to avoid needing to + // mask the shift amount. + + SDValue Zero = DAG.getConstant(0, dl, MVT::i32); + SDValue NegatedPlus32 = DAG.getNode( + ISD::SUB, dl, MVT::i32, DAG.getConstant(VTBits, dl, MVT::i32), ShAmt); + SDValue SetCC = DAG.getSetCC(dl, MVT::i32, NegatedPlus32, Zero, ISD::SETLE); + + SDValue Hi = DAG.getNode(ISD::SRL, dl, MVT::i32, ShOpHi, ShAmt); + Hi = DAG.getSelect(dl, MVT::i32, SetCC, Zero, Hi); + + SDValue Lo = DAG.getNode(ISD::SRL, dl, MVT::i32, ShOpLo, ShAmt); + Lo = DAG.getSelect(dl, MVT::i32, SetCC, Hi, Lo); + SDValue CarryBits = + DAG.getNode(ISD::SHL, dl, MVT::i32, ShOpHi, NegatedPlus32); + SDValue ShiftIsZero = DAG.getSetCC(dl, MVT::i32, ShAmt, Zero, ISD::SETEQ); + Lo = DAG.getSelect(dl, MVT::i32, ShiftIsZero, Lo, + DAG.getNode(ISD::OR, dl, MVT::i32, Lo, CarryBits)); + + SDValue Ops[2] = {Lo, Hi}; + return DAG.getMergeValues(Ops, dl); +} diff --git a/lib/Target/Lanai/LanaiISelLowering.h b/lib/Target/Lanai/LanaiISelLowering.h index 57623d05ae2..8cd1e36e2a7 100644 --- a/lib/Target/Lanai/LanaiISelLowering.h +++ b/lib/Target/Lanai/LanaiISelLowering.h @@ -87,6 +87,7 @@ public: SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const; SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const; SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerSRL_PARTS(SDValue Op, SelectionDAG &DAG) const; SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const; unsigned getRegisterByName(const char *RegName, EVT VT, diff --git a/test/CodeGen/Lanai/rshift64.ll b/test/CodeGen/Lanai/rshift64.ll new file mode 100644 index 00000000000..2009edd001c --- /dev/null +++ b/test/CodeGen/Lanai/rshift64.ll @@ -0,0 +1,12 @@ +; RUN: llc < %s -mtriple=lanai-unknown-unknown | FileCheck %s + +; Test right-shift i64 lowering does not result in call being inserted. + +; CHECK-LABEL: shift +; CHECK-NOT: bt __lshrdi3 +; CHECK: %rv +define i64 @shift(i64 inreg, i32 inreg) { + %3 = zext i32 %1 to i64 + %4 = lshr i64 %0, %3 + ret i64 %4 +}