From 77f452d1a83054f0451ef8421297ffc8294f45dd Mon Sep 17 00:00:00 2001 From: Scott Michel Date: Tue, 25 Aug 2009 22:37:34 +0000 Subject: [PATCH] Updated i128 sext support for CellSPU backend, contributed by Ken Werner (IBM) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@80042 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/CellSPU/SPUISelLowering.cpp | 48 +++++++++++++++++--------- test/CodeGen/CellSPU/sext128.ll | 35 +++++++++++++++++-- 2 files changed, 64 insertions(+), 19 deletions(-) diff --git a/lib/Target/CellSPU/SPUISelLowering.cpp b/lib/Target/CellSPU/SPUISelLowering.cpp index edbceddaeda..324b9ddf835 100644 --- a/lib/Target/CellSPU/SPUISelLowering.cpp +++ b/lib/Target/CellSPU/SPUISelLowering.cpp @@ -350,7 +350,7 @@ SPUTargetLowering::SPUTargetLowering(SPUTargetMachine &TM) // Custom lower i128 -> i64 truncates setOperationAction(ISD::TRUNCATE, MVT::i64, Custom); - // Custom lower i64 -> i128 sign extend + // Custom lower i32/i64 -> i128 sign extend setOperationAction(ISD::SIGN_EXTEND, MVT::i128, Custom); setOperationAction(ISD::FP_TO_SINT, MVT::i8, Promote); @@ -2610,41 +2610,57 @@ static SDValue LowerTRUNCATE(SDValue Op, SelectionDAG &DAG) return SDValue(); // Leave the truncate unmolested } -//! Custom lower ISD::SIGN_EXTEND +/*! + * Emit the instruction sequence for i64/i32 -> i128 sign extend. The basic + * algorithm is to duplicate the sign bit using rotmai to generate at + * least one byte full of sign bits. Then propagate the "sign-byte" into + * the leftmost words and the i64/i32 into the rightmost words using shufb. + * + * @param Op The sext operand + * @param DAG The current DAG + * @return The SDValue with the entire instruction sequence + */ static SDValue LowerSIGN_EXTEND(SDValue Op, SelectionDAG &DAG) { - // Type to extend to - EVT VT = Op.getValueType(); DebugLoc dl = Op.getDebugLoc(); + // Type to extend to + MVT OpVT = Op.getValueType().getSimpleVT(); + EVT VecVT = EVT::getVectorVT(*DAG.getContext(), + OpVT, (128 / OpVT.getSizeInBits())); + // Type to extend from SDValue Op0 = Op.getOperand(0); - EVT Op0VT = Op0.getValueType(); + MVT Op0VT = Op0.getValueType().getSimpleVT(); - assert((VT == MVT::i128 && Op0VT == MVT::i64) && + // The type to extend to needs to be a i128 and + // the type to extend from needs to be i64 or i32. + assert((OpVT == MVT::i128 && (Op0VT == MVT::i64 || Op0VT == MVT::i32)) && "LowerSIGN_EXTEND: input and/or output operand have wrong size"); // Create shuffle mask - unsigned mask1 = 0x10101010; // byte 0 - 3 and 4 - 7 - unsigned mask2 = 0x01020304; // byte 8 - 11 - unsigned mask3 = 0x05060708; // byte 12 - 15 + unsigned mask1 = 0x10101010; // byte 0 - 3 and 4 - 7 + unsigned mask2 = Op0VT == MVT::i64 ? 0x00010203 : 0x10101010; // byte 8 - 11 + unsigned mask3 = Op0VT == MVT::i64 ? 0x04050607 : 0x00010203; // byte 12 - 15 SDValue shufMask = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32, DAG.getConstant(mask1, MVT::i32), DAG.getConstant(mask1, MVT::i32), DAG.getConstant(mask2, MVT::i32), DAG.getConstant(mask3, MVT::i32)); - // Word wise arithmetic right shift to generate a byte that contains sign bits + // Word wise arithmetic right shift to generate at least one byte + // that contains sign bits. + MVT mvt = Op0VT == MVT::i64 ? MVT::v2i64 : MVT::v4i32; SDValue sraVal = DAG.getNode(ISD::SRA, dl, - MVT::v2i64, - DAG.getNode(SPUISD::PREFSLOT2VEC, dl, MVT::v2i64, Op0, Op0), + mvt, + DAG.getNode(SPUISD::PREFSLOT2VEC, dl, mvt, Op0, Op0), DAG.getConstant(31, MVT::i32)); - // shuffle bytes - copies the sign bits into the upper 64 bits - // and the input value into the lower 64 bits - SDValue extShuffle = DAG.getNode(SPUISD::SHUFB, dl, MVT::v2i64, - Op0, sraVal, shufMask); + // Shuffle bytes - Copy the sign bits into the upper 64 bits + // and the input value into the lower 64 bits. + SDValue extShuffle = DAG.getNode(SPUISD::SHUFB, dl, mvt, + DAG.getNode(ISD::ANY_EXTEND, dl, MVT::i128, Op0), sraVal, shufMask); return DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i128, extShuffle); } diff --git a/test/CodeGen/CellSPU/sext128.ll b/test/CodeGen/CellSPU/sext128.ll index 0cff87937bb..71962a94258 100644 --- a/test/CodeGen/CellSPU/sext128.ll +++ b/test/CodeGen/CellSPU/sext128.ll @@ -6,13 +6,42 @@ target triple = "spu" define i128 @sext_i64_i128(i64 %a) { entry: + %0 = sext i64 %a to i128 + ret i128 %0 ; CHECK: long 269488144 ; CHECK: long 269488144 -; CHECK: long 16909060 -; CHECK: long 84281096 +; CHECK: long 66051 +; CHECK: long 67438087 ; CHECK: rotmai ; CHECK: lqa ; CHECK: shufb - %0 = sext i64 %a to i128 +} + +define i128 @sext_i32_i128(i32 %a) { +entry: + %0 = sext i32 %a to i128 ret i128 %0 +; CHECK: long 269488144 +; CHECK: long 269488144 +; CHECK: long 269488144 +; CHECK: long 66051 +; CHECK: rotmai +; CHECK: lqa +; CHECK: shufb } + +define i128 @sext_i32_i128a(float %a) { +entry: + %0 = call i32 @myfunc(float %a) + %1 = sext i32 %0 to i128 + ret i128 %1 +; CHECK: long 269488144 +; CHECK: long 269488144 +; CHECK: long 269488144 +; CHECK: long 66051 +; CHECK: rotmai +; CHECK: lqa +; CHECK: shufb +} + +declare i32 @myfunc(float) -- 2.34.1