[llvm] f8a4495 - [ARC] Add codegen for llvm.ctlz intrinsic for the ARC backend

Mark Schimmel via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 6 12:19:47 PDT 2021


Author: Thomas Johnson
Date: 2021-08-06T12:18:06-07:00
New Revision: f8a449514931bf2b3a0b36328e821365ed8bf5c6

URL: https://github.com/llvm/llvm-project/commit/f8a449514931bf2b3a0b36328e821365ed8bf5c6
DIFF: https://github.com/llvm/llvm-project/commit/f8a449514931bf2b3a0b36328e821365ed8bf5c6.diff

LOG: [ARC] Add codegen for llvm.ctlz intrinsic for the ARC backend

    Differential Revision: https://reviews.llvm.org/D107611

Added: 
    llvm/test/CodeGen/ARC/ctlz.ll

Modified: 
    clang/lib/Basic/Targets/ARC.h
    llvm/lib/Target/ARC/ARCExpandPseudos.cpp
    llvm/lib/Target/ARC/ARCISelLowering.cpp
    llvm/lib/Target/ARC/ARCInstrInfo.td

Removed: 
    


################################################################################
diff  --git a/clang/lib/Basic/Targets/ARC.h b/clang/lib/Basic/Targets/ARC.h
index b314c42be1e94..3c0c5f6df2f4d 100644
--- a/clang/lib/Basic/Targets/ARC.h
+++ b/clang/lib/Basic/Targets/ARC.h
@@ -67,6 +67,8 @@ class LLVM_LIBRARY_VISIBILITY ARCTargetInfo : public TargetInfo {
   }
 
   bool hasExtIntType() const override { return true; }
+
+  bool isCLZForZeroUndef() const override { return false; }
 };
 
 } // namespace targets

diff  --git a/llvm/lib/Target/ARC/ARCExpandPseudos.cpp b/llvm/lib/Target/ARC/ARCExpandPseudos.cpp
index a1646d17605fe..cef9882909b3f 100644
--- a/llvm/lib/Target/ARC/ARCExpandPseudos.cpp
+++ b/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 @@ class ARCExpandPseudos : public MachineFunctionPass {
 
 private:
   void ExpandStore(MachineFunction &, MachineBasicBlock::iterator);
+  void ExpandCTLZ(MachineFunction &, MachineBasicBlock::iterator);
 
   const ARCInstrInfo *TII;
 };
@@ -59,8 +61,8 @@ static unsigned getMappedOp(unsigned PseudoOp) {
 void ARCExpandPseudos::ExpandStore(MachineFunction &MF,
                                    MachineBasicBlock::iterator SII) {
   MachineInstr &SI = *SII;
-  unsigned AddrReg = MF.getRegInfo().createVirtualRegister(&ARC::GPR32RegClass);
-  unsigned AddOpc =
+  Register AddrReg = MF.getRegInfo().createVirtualRegister(&ARC::GPR32RegClass);
+  Register AddOpc =
       isUInt<6>(SI.getOperand(2).getImm()) ? ARC::ADD_rru6 : ARC::ADD_rrlimm;
   BuildMI(*SI.getParent(), SI, SI.getDebugLoc(), TII->get(AddOpc), AddrReg)
       .addReg(SI.getOperand(1).getReg())
@@ -73,10 +75,39 @@ void ARCExpandPseudos::ExpandStore(MachineFunction &MF,
   SI.eraseFromParent();
 }
 
+void ARCExpandPseudos::ExpandCTLZ(MachineFunction &MF,
+                                  MachineBasicBlock::iterator MII) {
+  // 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 &MI = *MII;
+  const MachineOperand &Dest = MI.getOperand(0);
+  const MachineOperand &Src = MI.getOperand(1);
+  Register Ra = MF.getRegInfo().createVirtualRegister(&ARC::GPR32RegClass);
+  Register Rb = MF.getRegInfo().createVirtualRegister(&ARC::GPR32RegClass);
+
+  BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), TII->get(ARC::FLS_f_rr), Ra)
+      .add(Src);
+  BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), TII->get(ARC::MOV_cc_ru6), Rb)
+      .addImm(32)
+      .addImm(ARCCC::EQ)
+      .addReg(Ra);
+  BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), TII->get(ARC::RSUB_cc_rru6))
+      .add(Dest)
+      .addImm(31)
+      .addImm(ARCCC::NE)
+      .addReg(Rb);
+
+  MI.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 +117,11 @@ bool ARCExpandPseudos::runOnMachineFunction(MachineFunction &MF) {
       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 +129,7 @@ bool ARCExpandPseudos::runOnMachineFunction(MachineFunction &MF) {
       MBBI = NMBBI;
     }
   }
-  return ExpandedStore;
+  return Expanded;
 }
 
 FunctionPass *llvm::createARCExpandPseudosPass() {

diff  --git a/llvm/lib/Target/ARC/ARCISelLowering.cpp b/llvm/lib/Target/ARC/ARCISelLowering.cpp
index ca33f52974711..3db132a50b93f 100644
--- a/llvm/lib/Target/ARC/ARCISelLowering.cpp
+++ b/llvm/lib/Target/ARC/ARCISelLowering.cpp
@@ -135,6 +135,10 @@ ARCTargetLowering::ARCTargetLowering(const TargetMachine &TM,
 
   // 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 {

diff  --git a/llvm/lib/Target/ARC/ARCInstrInfo.td b/llvm/lib/Target/ARC/ARCInstrInfo.td
index 16c3e50635bf8..22a583c2b587f 100644
--- a/llvm/lib/Target/ARC/ARCInstrInfo.td
+++ b/llvm/lib/Target/ARC/ARCInstrInfo.td
@@ -133,6 +133,14 @@ def STB_FAR : PseudoInstARC<(outs), (ins GPR32:$dst, MEMrlimm:$addr),
                              "STB_FAR $dst, $addr",
                              [(truncstorei8 GPR32:$dst, AddrModeFar:$addr)]>;
 
+// 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];
+}
+
 //===----------------------------------------------------------------------===//
 // Instruction Generation multiclasses.
 // Generate many variants of a single instruction with a single defining

diff  --git a/llvm/test/CodeGen/ARC/ctlz.ll b/llvm/test/CodeGen/ARC/ctlz.ll
new file mode 100644
index 0000000000000..1702a5c5b040a
--- /dev/null
+++ b/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-NEXT:  mov.eq  %r0, 32
+; CHECK-NEXT:  rsub.ne %r0, %r0, 31
+define i32 @clz32(i32 %x) {
+  %a = call i32 @llvm.ctlz.i32(i32 %x, i1 false)
+  ret i32 %a
+}


        


More information about the llvm-commits mailing list