bswap implementation
authorNate Begeman <natebegeman@mac.com>
Sat, 14 Jan 2006 03:14:10 +0000 (03:14 +0000)
committerNate Begeman <natebegeman@mac.com>
Sat, 14 Jan 2006 03:14:10 +0000 (03:14 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@25312 91177308-0d34-0410-b5e6-96231b3b80d8

12 files changed:
lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
lib/Target/Alpha/AlphaISelLowering.cpp
lib/Target/IA64/IA64ISelLowering.cpp
lib/Target/IA64/IA64ISelPattern.cpp
lib/Target/PowerPC/PPCISelLowering.cpp
lib/Target/Sparc/SparcISelDAGToDAG.cpp
lib/Target/SparcV8/SparcV8ISelDAGToDAG.cpp
lib/Target/TargetSelectionDAG.td
lib/Target/X86/X86ISelLowering.cpp
lib/Target/X86/X86InstrInfo.td
test/CodeGen/X86/bswap.ll [new file with mode: 0644]

index af7fce423f367bc1eaaca894ddef142228605bd3..9dae31d6d77e01ff1211ae2916f8624fca706359 100644 (file)
@@ -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)
index 061a3ef8a3e41f8c5076a59e007335e852f62fdb..c30293084129327d6d442bcc9321a571b07d2217 100644 (file)
@@ -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(),
index f6d8f36605c8823df97a432f7cdf2cc1d3891a40..b9332890d6c11f7a9685e6736d8d6a05a2019df7 100644 (file)
@@ -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);
   
index 91d3f359b5fbaf5525e7d406ca44586484cec9f8..f56a02b1bcc6b3c0ea09fe46feb715f216808b0e 100644 (file)
@@ -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);
index 3aeb1598b6013ea171f12a662f52df43eee6b65b..3a1a413caf08b3b95cf270ecea6632ee9257a914 100644 (file)
@@ -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);
index d8c00dcb1aa71179850bbcc2bcc616b4121d9b9b..7991821133f1690bd81312a1bc54183c93405ec0 100644 (file)
@@ -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);
   
index 7cfc68006b61a204b741332fc30557e0360ae750..85c69c6c098c10e36fe46e89b8199a817cec782a 100644 (file)
@@ -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);
index 7cfc68006b61a204b741332fc30557e0360ae750..85c69c6c098c10e36fe46e89b8199a817cec782a 100644 (file)
@@ -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);
index 23abb1044791da7a01e005334d6fee9bad0efe32..9537819aad6727ebb7f56737294a4657f42dc8bd 100644 (file)
@@ -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>;
index d93ec3a537574dffcecce13a1caaf4e3a8587788..a749380b864bae141598a520449160381f469000 100644 (file)
@@ -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);
index 291abd48e3528b74e581bb41f3586a41ec649422..5427e249d0f510c62bc4f246cf35a5076875fa4c 100644 (file)
@@ -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 (file)
index 0000000..d48d265
--- /dev/null
@@ -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
+}