thomasjohns created this revision.
thomasjohns added a reviewer: marksl.
Herald added a subscriber: hiraditya.
thomasjohns requested review of this revision.
Herald added projects: clang, LLVM.
Herald added a subscriber: cfe-commits.

Add a CTLZ pseudo instruction to tablegen and the ability to expand this pseudo 
instruction instruction to ARC assembly code.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D107611

Files:
  clang/lib/Basic/Targets/ARC.h
  llvm/lib/Target/ARC/ARCExpandPseudos.cpp
  llvm/lib/Target/ARC/ARCISelLowering.cpp
  llvm/lib/Target/ARC/ARCInstrInfo.td
  llvm/test/CodeGen/ARC/ctlz.ll

Index: llvm/test/CodeGen/ARC/ctlz.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/ARC/ctlz.ll
@@ -0,0 +1,14 @@
+; RUN: llc -march=arc < %s | FileCheck %s
+
+target triple = "arc"
+
+declare i32 @llvm.ctlz.i32(i32, i1)
+
+; CHECK-LABEL: clz32:
+; CHECK: fls.f   %r0, %r0
+; CHECK: mov.eq  [[R:%r[01]]], 32
+; CHECK: rsub.ne [[R]], [[R]], 31
+define i32 @clz32(i32 %x) {
+  %a = call i32 @llvm.ctlz.i32(i32 %x, i1 false)
+  ret i32 %a
+}
Index: llvm/lib/Target/ARC/ARCInstrInfo.td
===================================================================
--- llvm/lib/Target/ARC/ARCInstrInfo.td
+++ llvm/lib/Target/ARC/ARCInstrInfo.td
@@ -311,6 +311,13 @@
 let Predicates=[HasNorm] in {
   defm NORM  : ArcUnaryEXT5Inst<0b000001,"norm">;
   defm NORMH : ArcUnaryEXT5Inst<0b001000,"normh">;
+
+// TODO: Add `Requires<[HasBitScan]>` predicate when available.
+def CTLZ : PseudoInstARC<(outs GPR32:$A),
+                         (ins GPR32:$B),
+                         "error.fls $A, $B",
+                         [(set GPR32:$A, (ctlz i32:$B))]> {
+  let Defs = [STATUS32];
 }
 
 // General Unary Instruction fragments.
Index: llvm/lib/Target/ARC/ARCISelLowering.cpp
===================================================================
--- llvm/lib/Target/ARC/ARCISelLowering.cpp
+++ llvm/lib/Target/ARC/ARCISelLowering.cpp
@@ -135,6 +135,10 @@
 
   // Sign extend inreg
   setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Custom);
+
+  // TODO: Predicate with `options.hasBitScan() ? Legal : Expand` when
+  //       the HasBitScan predicate is available.
+  setOperationAction(ISD::CTLZ, MVT::i32, Legal);
 }
 
 const char *ARCTargetLowering::getTargetNodeName(unsigned Opcode) const {
Index: llvm/lib/Target/ARC/ARCExpandPseudos.cpp
===================================================================
--- llvm/lib/Target/ARC/ARCExpandPseudos.cpp
+++ llvm/lib/Target/ARC/ARCExpandPseudos.cpp
@@ -13,6 +13,7 @@
 #include "ARCInstrInfo.h"
 #include "ARCRegisterInfo.h"
 #include "ARCSubtarget.h"
+#include "MCTargetDesc/ARCInfo.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/CodeGen/MachineFunctionPass.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
@@ -35,6 +36,7 @@
 
 private:
   void ExpandStore(MachineFunction &, MachineBasicBlock::iterator);
+  void ExpandCTLZ(MachineFunction &, MachineBasicBlock::iterator);
 
   const ARCInstrInfo *TII;
 };
@@ -73,10 +75,45 @@
   SI.eraseFromParent();
 }
 
+void ARCExpandPseudos::ExpandCTLZ(MachineFunction &MF,
+                                  MachineBasicBlock::iterator SII) {
+  // Expand:
+  //	%R2<def> = CTLZ %R0, %STATUS<imp-def>
+  // To:
+  //	%R2<def> = FLS_f_rr %R0, %STATUS<imp-def>
+  //	%R2<def,tied1> = MOV_cc_ru6 %R2<tied0>, 32, pred:1, %STATUS<imp-use>
+  //	%R2<def,tied1> = RSUB_cc_rru6 %R2<tied0>, 31, pred:2, %STATUS<imp-use>
+  MachineInstr &SI = *SII;
+  const MachineOperand &Dest = SI.getOperand(0);
+  assert(Dest.isReg());
+  const MachineOperand &Src = SI.getOperand(1);
+  assert(Src.isReg());
+  unsigned DestReg = Dest.getReg();
+
+  BuildMI(*SI.getParent(), SI, SI.getDebugLoc(), TII->get(ARC::FLS_f_rr),
+          DestReg)
+      .add(Src)
+      .addReg(ARC::STATUS32, RegState::ImplicitDefine);
+
+  unsigned Ra = MF.getRegInfo().createVirtualRegister(&ARC::GPR32RegClass);
+  unsigned Rb = MF.getRegInfo().createVirtualRegister(&ARC::GPR32RegClass);
+  BuildMI(*SI.getParent(), SI, SI.getDebugLoc(), TII->get(ARC::MOV_cc_ru6), Ra)
+      .addImm(32)
+      .addImm(ARCCC::EQ)
+      .addReg(DestReg);
+  BuildMI(*SI.getParent(), SI, SI.getDebugLoc(), TII->get(ARC::RSUB_cc_rru6),
+          Rb)
+      .addImm(31)
+      .addImm(ARCCC::NE)
+      .addReg(Ra);
+
+  SI.eraseFromParent();
+}
+
 bool ARCExpandPseudos::runOnMachineFunction(MachineFunction &MF) {
   const ARCSubtarget *STI = &MF.getSubtarget<ARCSubtarget>();
   TII = STI->getInstrInfo();
-  bool ExpandedStore = false;
+  bool Expanded = false;
   for (auto &MBB : MF) {
     MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
     while (MBBI != E) {
@@ -86,7 +123,11 @@
       case ARC::STH_FAR:
       case ARC::STB_FAR:
         ExpandStore(MF, MBBI);
-        ExpandedStore = true;
+        Expanded = true;
+        break;
+      case ARC::CTLZ:
+        ExpandCTLZ(MF, MBBI);
+        Expanded = true;
         break;
       default:
         break;
@@ -94,7 +135,7 @@
       MBBI = NMBBI;
     }
   }
-  return ExpandedStore;
+  return Expanded;
 }
 
 FunctionPass *llvm::createARCExpandPseudosPass() {
Index: clang/lib/Basic/Targets/ARC.h
===================================================================
--- clang/lib/Basic/Targets/ARC.h
+++ clang/lib/Basic/Targets/ARC.h
@@ -67,6 +67,8 @@
   }
 
   bool hasExtIntType() const override { return true; }
+
+  bool isCLZForZeroUndef() const override { return false; }
 };
 
 } // namespace targets
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to