From d88fc03602947b5baa35c8b09fe8bcfa2b4a03c1 Mon Sep 17 00:00:00 2001 From: Nate Begeman Date: Sat, 14 Jan 2006 03:14:10 +0000 Subject: [PATCH] bswap implementation git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@25312 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 68 +++++++++++++++++++ lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 15 ++++ lib/Target/Alpha/AlphaISelLowering.cpp | 1 + lib/Target/IA64/IA64ISelLowering.cpp | 1 + lib/Target/IA64/IA64ISelPattern.cpp | 1 + lib/Target/PowerPC/PPCISelLowering.cpp | 3 +- lib/Target/Sparc/SparcISelDAGToDAG.cpp | 1 + lib/Target/SparcV8/SparcV8ISelDAGToDAG.cpp | 1 + lib/Target/TargetSelectionDAG.td | 1 + lib/Target/X86/X86ISelLowering.cpp | 2 + lib/Target/X86/X86InstrInfo.td | 4 +- test/CodeGen/X86/bswap.ll | 23 +++++++ 12 files changed, 119 insertions(+), 2 deletions(-) create mode 100644 test/CodeGen/X86/bswap.ll diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index af7fce423f3..9dae31d6d77 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -2217,6 +2217,58 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { } break; + case ISD::BSWAP: + Tmp1 = LegalizeOp(Node->getOperand(0)); // Op + switch (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0))) { + case TargetLowering::Legal: + if (Tmp1 != Node->getOperand(0)) + Result = DAG.getNode(Node->getOpcode(), Node->getValueType(0), Tmp1); + break; + case TargetLowering::Promote: { + MVT::ValueType OVT = Tmp1.getValueType(); + MVT::ValueType NVT = TLI.getTypeToPromoteTo(Node->getOpcode(), OVT); + unsigned DiffBits = getSizeInBits(NVT) - getSizeInBits(OVT); + + Tmp1 = DAG.getNode(ISD::ZERO_EXTEND, NVT, Tmp1); + Tmp1 = DAG.getNode(ISD::BSWAP, NVT, Tmp1); + Result = DAG.getNode(ISD::SRL, NVT, Tmp1, + DAG.getConstant(DiffBits, TLI.getShiftAmountTy())); + break; + } + case TargetLowering::Custom: + assert(0 && "Cannot custom legalize this yet!"); + case TargetLowering::Expand: { + MVT::ValueType VT = Tmp1.getValueType(); + switch (VT) { + default: assert(0 && "Unhandled Expand type in BSWAP!"); abort(); + case MVT::i16: + Tmp2 = DAG.getNode(ISD::SHL, VT, Tmp1, + DAG.getConstant(8, TLI.getShiftAmountTy())); + Tmp1 = DAG.getNode(ISD::SRL, VT, Tmp1, + DAG.getConstant(8, TLI.getShiftAmountTy())); + Result = DAG.getNode(ISD::OR, VT, Tmp1, Tmp2); + break; + case MVT::i32: + Tmp4 = DAG.getNode(ISD::SHL, VT, Tmp1, + DAG.getConstant(24, TLI.getShiftAmountTy())); + Tmp3 = DAG.getNode(ISD::SHL, VT, Tmp1, + DAG.getConstant(8, TLI.getShiftAmountTy())); + Tmp2 = DAG.getNode(ISD::SRL, VT, Tmp1, + DAG.getConstant(8, TLI.getShiftAmountTy())); + Tmp1 = DAG.getNode(ISD::SRL, VT, Tmp1, + DAG.getConstant(24, TLI.getShiftAmountTy())); + Tmp3 = DAG.getNode(ISD::AND, VT, Tmp3, DAG.getConstant(0xFF0000, VT)); + Tmp2 = DAG.getNode(ISD::AND, VT, Tmp2, DAG.getConstant(0xFF00, VT)); + Tmp4 = DAG.getNode(ISD::OR, VT, Tmp4, Tmp3); + Tmp2 = DAG.getNode(ISD::OR, VT, Tmp2, Tmp1); + Result = DAG.getNode(ISD::OR, VT, Tmp4, Tmp2); + break; + } + break; + } + } + break; + case ISD::CTPOP: case ISD::CTTZ: case ISD::CTLZ: @@ -3027,6 +3079,14 @@ SDOperand SelectionDAGLegalize::PromoteOp(SDOperand Op) { AddLegalizedOperand(Op.getValue(1), Result.getValue(1)); break; } + case ISD::BSWAP: + Tmp1 = Node->getOperand(0); + Tmp1 = DAG.getNode(ISD::ZERO_EXTEND, NVT, Tmp1); + Tmp1 = DAG.getNode(ISD::BSWAP, NVT, Tmp1); + Result = DAG.getNode(ISD::SRL, NVT, Tmp1, + DAG.getConstant(getSizeInBits(NVT) - getSizeInBits(VT), + TLI.getShiftAmountTy())); + break; case ISD::CTPOP: case ISD::CTTZ: case ISD::CTLZ: @@ -3636,6 +3696,14 @@ void SelectionDAGLegalize::ExpandOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi){ Lo = DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Lo, Node->getOperand(1)); break; + case ISD::BSWAP: { + ExpandOp(Node->getOperand(0), Lo, Hi); + SDOperand TempLo = DAG.getNode(ISD::BSWAP, NVT, Hi); + Hi = DAG.getNode(ISD::BSWAP, NVT, Lo); + Lo = TempLo; + break; + } + case ISD::CTPOP: ExpandOp(Node->getOperand(0), Lo, Hi); Lo = DAG.getNode(ISD::ADD, NVT, // ctpop(HL) -> ctpop(H)+ctpop(L) diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 061a3ef8a3e..c3029308412 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -989,6 +989,21 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { DAG.setRoot(Tmp.getValue(1)); return 0; } + case Intrinsic::bswap_i16: + setValue(&I, DAG.getNode(ISD::BSWAP, + getValue(I.getOperand(1)).getValueType(), + getValue(I.getOperand(1)))); + return 0; + case Intrinsic::bswap_i32: + setValue(&I, DAG.getNode(ISD::BSWAP, + getValue(I.getOperand(1)).getValueType(), + getValue(I.getOperand(1)))); + return 0; + case Intrinsic::bswap_i64: + setValue(&I, DAG.getNode(ISD::BSWAP, + getValue(I.getOperand(1)).getValueType(), + getValue(I.getOperand(1)))); + return 0; case Intrinsic::cttz: setValue(&I, DAG.getNode(ISD::CTTZ, getValue(I.getOperand(1)).getValueType(), diff --git a/lib/Target/Alpha/AlphaISelLowering.cpp b/lib/Target/Alpha/AlphaISelLowering.cpp index f6d8f36605c..b9332890d6c 100644 --- a/lib/Target/Alpha/AlphaISelLowering.cpp +++ b/lib/Target/Alpha/AlphaISelLowering.cpp @@ -81,6 +81,7 @@ AlphaTargetLowering::AlphaTargetLowering(TargetMachine &TM) : TargetLowering(TM) setOperationAction(ISD::CTTZ , MVT::i64 , Expand); setOperationAction(ISD::CTLZ , MVT::i64 , Expand); } + setOperationAction(ISD::BSWAP , MVT::i64, Expand); setOperationAction(ISD::ROTL , MVT::i64, Expand); setOperationAction(ISD::ROTR , MVT::i64, Expand); diff --git a/lib/Target/IA64/IA64ISelLowering.cpp b/lib/Target/IA64/IA64ISelLowering.cpp index 91d3f359b5f..f56a02b1bcc 100644 --- a/lib/Target/IA64/IA64ISelLowering.cpp +++ b/lib/Target/IA64/IA64ISelLowering.cpp @@ -82,6 +82,7 @@ IA64TargetLowering::IA64TargetLowering(TargetMachine &TM) setOperationAction(ISD::CTLZ , MVT::i64 , Expand); setOperationAction(ISD::ROTL , MVT::i64 , Expand); setOperationAction(ISD::ROTR , MVT::i64 , Expand); + setOperationAction(ISD::BSWAP, MVT::i64 , Expand); // mux @rev // Not implemented yet. setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); diff --git a/lib/Target/IA64/IA64ISelPattern.cpp b/lib/Target/IA64/IA64ISelPattern.cpp index 3aeb1598b60..3a1a413caf0 100644 --- a/lib/Target/IA64/IA64ISelPattern.cpp +++ b/lib/Target/IA64/IA64ISelPattern.cpp @@ -98,6 +98,7 @@ namespace { setOperationAction(ISD::CTLZ , MVT::i64 , Expand); setOperationAction(ISD::ROTL , MVT::i64 , Expand); setOperationAction(ISD::ROTR , MVT::i64 , Expand); + setOperationAction(ISD::BSWAP, MVT::i64 , Expand); // mux @rev // FIXME: implement mulhs (xma.h) and mulhu (xma.hu) setOperationAction(ISD::MULHS , MVT::i64 , Expand); setOperationAction(ISD::MULHU , MVT::i64 , Expand); diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index d8c00dcb1aa..7991821133f 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -64,7 +64,8 @@ PPCTargetLowering::PPCTargetLowering(TargetMachine &TM) setOperationAction(ISD::FSQRT, MVT::f32, Expand); } - // PowerPC does not have CTPOP or CTTZ + // PowerPC does not have BSWAP, CTPOP or CTTZ + setOperationAction(ISD::BSWAP, MVT::i32 , Expand); setOperationAction(ISD::CTPOP, MVT::i32 , Expand); setOperationAction(ISD::CTTZ , MVT::i32 , Expand); diff --git a/lib/Target/Sparc/SparcISelDAGToDAG.cpp b/lib/Target/Sparc/SparcISelDAGToDAG.cpp index 7cfc68006b6..85c69c6c098 100644 --- a/lib/Target/Sparc/SparcISelDAGToDAG.cpp +++ b/lib/Target/Sparc/SparcISelDAGToDAG.cpp @@ -150,6 +150,7 @@ SparcV8TargetLowering::SparcV8TargetLowering(TargetMachine &TM) setOperationAction(ISD::CTLZ , MVT::i32, Expand); setOperationAction(ISD::ROTL , MVT::i32, Expand); setOperationAction(ISD::ROTR , MVT::i32, Expand); + setOperationAction(ISD::BSWAP, MVT::i32, Expand); setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand); setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand); diff --git a/lib/Target/SparcV8/SparcV8ISelDAGToDAG.cpp b/lib/Target/SparcV8/SparcV8ISelDAGToDAG.cpp index 7cfc68006b6..85c69c6c098 100644 --- a/lib/Target/SparcV8/SparcV8ISelDAGToDAG.cpp +++ b/lib/Target/SparcV8/SparcV8ISelDAGToDAG.cpp @@ -150,6 +150,7 @@ SparcV8TargetLowering::SparcV8TargetLowering(TargetMachine &TM) setOperationAction(ISD::CTLZ , MVT::i32, Expand); setOperationAction(ISD::ROTL , MVT::i32, Expand); setOperationAction(ISD::ROTR , MVT::i32, Expand); + setOperationAction(ISD::BSWAP, MVT::i32, Expand); setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand); setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand); diff --git a/lib/Target/TargetSelectionDAG.td b/lib/Target/TargetSelectionDAG.td index 23abb104479..9537819aad6 100644 --- a/lib/Target/TargetSelectionDAG.td +++ b/lib/Target/TargetSelectionDAG.td @@ -240,6 +240,7 @@ def xor : SDNode<"ISD::XOR" , SDTIntBinOp, [SDNPCommutative, SDNPAssociative]>; def sext_inreg : SDNode<"ISD::SIGN_EXTEND_INREG", SDTExtInreg>; +def bswap : SDNode<"ISD::BSWAP" , SDTIntUnaryOp>; def ctlz : SDNode<"ISD::CTLZ" , SDTIntUnaryOp>; def cttz : SDNode<"ISD::CTTZ" , SDTIntUnaryOp>; def ctpop : SDNode<"ISD::CTPOP" , SDTIntUnaryOp>; diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index d93ec3a5375..a749380b864 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -109,6 +109,7 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM) setOperationAction(ISD::READCYCLECOUNTER , MVT::i64 , Custom); if (!X86DAGIsel) { + setOperationAction(ISD::BSWAP , MVT::i32 , Expand); setOperationAction(ISD::ROTL , MVT::i8 , Expand); setOperationAction(ISD::ROTR , MVT::i8 , Expand); setOperationAction(ISD::ROTL , MVT::i16 , Expand); @@ -116,6 +117,7 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM) setOperationAction(ISD::ROTL , MVT::i32 , Expand); setOperationAction(ISD::ROTR , MVT::i32 , Expand); } + setOperationAction(ISD::BSWAP , MVT::i16 , Expand); setOperationAction(ISD::READIO , MVT::i1 , Expand); setOperationAction(ISD::READIO , MVT::i8 , Expand); diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index 291abd48e35..5427e249d0f 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -518,7 +518,9 @@ def POP32r : I<0x58, AddRegFrm, let isTwoAddress = 1 in // R32 = bswap R32 def BSWAP32r : I<0xC8, AddRegFrm, - (ops R32:$dst, R32:$src), "bswap{l} $dst", []>, TB; + (ops R32:$dst, R32:$src), + "bswap{l} $dst", + [(set R32:$dst, (bswap R32:$src))]>, TB; def XCHG8rr : I<0x86, MRMDestReg, // xchg R8, R8 (ops R8:$src1, R8:$src2), diff --git a/test/CodeGen/X86/bswap.ll b/test/CodeGen/X86/bswap.ll new file mode 100644 index 00000000000..d48d26568cd --- /dev/null +++ b/test/CodeGen/X86/bswap.ll @@ -0,0 +1,23 @@ +; bswap should be constant folded when it is passed a constant argument + +; RUN: llvm-as < %s | llc -march=x86 -enable-x86-dag-isel | grep bswapl | wc -l | grep 3 && +; RUN: llvm-as < %s | llc -march=x86 -enable-x86-dag-isel | grep rolw | wc -l | grep 1 + +declare ushort %llvm.bswap.i16(ushort) +declare uint %llvm.bswap.i32(uint) +declare ulong %llvm.bswap.i64(ulong) + +ushort %W(ushort %A) { + %Z = call ushort %llvm.bswap.i16(ushort %A) + ret ushort %Z +} + +uint %X(uint %A) { + %Z = call uint %llvm.bswap.i32(uint %A) + ret uint %Z +} + +ulong %Y(ulong %A) { + %Z = call ulong %llvm.bswap.i64(ulong %A) + ret ulong %Z +} -- 2.34.1