[llvm] r272403 - Interprocedural Register Allocation (IPRA) Analysis

Mehdi Amini via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 10 09:19:47 PDT 2016


Author: mehdi_amini
Date: Fri Jun 10 11:19:46 2016
New Revision: 272403

URL: http://llvm.org/viewvc/llvm-project?rev=272403&view=rev
Log:
Interprocedural Register Allocation (IPRA) Analysis

Add an option to enable the analysis of MachineFunction register
usage to extract the list of clobbered registers.

When enabled, the CodeGen order is changed to be bottom up on the Call
Graph.

The analysis is split in two parts, RegUsageInfoCollector is the
MachineFunction Pass that runs post-RA and collect the list of
clobbered registers to produce a register mask.

An immutable pass, RegisterUsageInfo, stores the RegMask produced by
RegUsageInfoCollector, and keep them available. A future tranformation
pass will use this information to update every call-sites after
instruction selection.

Patch by Vivek Pandya <vivekvpandya at gmail.com>

Differential Revision: http://reviews.llvm.org/D20769

Added:
    llvm/trunk/include/llvm/CodeGen/RegisterUsageInfo.h
    llvm/trunk/lib/CodeGen/RegUsageInfoCollector.cpp
    llvm/trunk/lib/CodeGen/RegisterUsageInfo.cpp
    llvm/trunk/test/CodeGen/X86/ipra-inline-asm.ll
    llvm/trunk/test/CodeGen/X86/ipra-reg-usage.ll
Modified:
    llvm/trunk/include/llvm/Analysis/CallGraphSCCPass.h
    llvm/trunk/include/llvm/CodeGen/MachineOperand.h
    llvm/trunk/include/llvm/CodeGen/Passes.h
    llvm/trunk/include/llvm/InitializePasses.h
    llvm/trunk/lib/Analysis/CallGraphSCCPass.cpp
    llvm/trunk/lib/CodeGen/CMakeLists.txt
    llvm/trunk/lib/CodeGen/TargetPassConfig.cpp

Modified: llvm/trunk/include/llvm/Analysis/CallGraphSCCPass.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/CallGraphSCCPass.h?rev=272403&r1=272402&r2=272403&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/CallGraphSCCPass.h (original)
+++ llvm/trunk/include/llvm/Analysis/CallGraphSCCPass.h Fri Jun 10 11:19:46 2016
@@ -23,6 +23,7 @@
 
 #include "llvm/Analysis/CallGraph.h"
 #include "llvm/Pass.h"
+#include "llvm/PassSupport.h"
 
 namespace llvm {
 
@@ -111,6 +112,23 @@ public:
   const CallGraph &getCallGraph() { return CG; }
 };
 
+void initializeDummyCGSCCPassPass(PassRegistry &);
+
+/// This pass is required by interprocedural register allocation. It forces
+/// codegen to follow bottom up order on call graph.
+class DummyCGSCCPass : public CallGraphSCCPass {
+public:
+  static char ID;
+  DummyCGSCCPass() : CallGraphSCCPass(ID) {
+    PassRegistry &Registry = *PassRegistry::getPassRegistry();
+    initializeDummyCGSCCPassPass(Registry);
+  };
+  bool runOnSCC(CallGraphSCC &SCC) override { return false; }
+  void getAnalysisUsage(AnalysisUsage &AU) const override {
+    AU.setPreservesAll();
+  }
+};
+
 } // End llvm namespace
 
 #endif

Modified: llvm/trunk/include/llvm/CodeGen/MachineOperand.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineOperand.h?rev=272403&r1=272402&r2=272403&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/MachineOperand.h (original)
+++ llvm/trunk/include/llvm/CodeGen/MachineOperand.h Fri Jun 10 11:19:46 2016
@@ -534,6 +534,15 @@ public:
     Contents.MBB = MBB;
   }
 
+  /// Sets value of register mask operand referencing Mask.  The
+  /// operand does not take ownership of the memory referenced by Mask, it must
+  /// remain valid for the lifetime of the operand. See CreateRegMask().
+  /// Any physreg with a 0 bit in the mask is clobbered by the instruction.
+  void setRegMask(const uint32_t *RegMaskPtr) {
+    assert(isRegMask() && "Wrong MachineOperand mutator");
+    Contents.RegMask = RegMaskPtr;
+  }
+
   //===--------------------------------------------------------------------===//
   // Other methods.
   //===--------------------------------------------------------------------===//

Modified: llvm/trunk/include/llvm/CodeGen/Passes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/Passes.h?rev=272403&r1=272402&r2=272403&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/Passes.h (original)
+++ llvm/trunk/include/llvm/CodeGen/Passes.h Fri Jun 10 11:19:46 2016
@@ -361,6 +361,10 @@ namespace llvm {
   /// independently of other lanes and splits them into separate virtual
   /// registers.
   extern char &RenameIndependentSubregsID;
+
+  /// This pass is executed POST-RA to collect which physical registers are
+  /// preserved by given machine function.
+  FunctionPass *createRegUsageInfoCollector();
 } // End llvm namespace
 
 /// Target machine pass initializer for passes with dependencies. Use with

Added: llvm/trunk/include/llvm/CodeGen/RegisterUsageInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/RegisterUsageInfo.h?rev=272403&view=auto
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/RegisterUsageInfo.h (added)
+++ llvm/trunk/include/llvm/CodeGen/RegisterUsageInfo.h Fri Jun 10 11:19:46 2016
@@ -0,0 +1,75 @@
+//==- RegisterUsageInfo.h - Register Usage Informartion Storage -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This pass is required to take advantage of the interprocedural register
+/// allocation infrastructure.
+///
+/// This pass is simple immutable pass which keeps RegMasks (calculated based on
+/// actual register allocation) for functions in a module and provides simple
+/// API to query this information.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_PHYSICALREGISTERUSAGEINFO_H
+#define LLVM_CODEGEN_PHYSICALREGISTERUSAGEINFO_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+
+class PhysicalRegisterUsageInfo : public ImmutablePass {
+  virtual void anchor();
+
+public:
+  static char ID;
+
+  PhysicalRegisterUsageInfo() : ImmutablePass(ID) {
+    PassRegistry &Registry = *PassRegistry::getPassRegistry();
+    initializePhysicalRegisterUsageInfoPass(Registry);
+  }
+
+  void getAnalysisUsage(AnalysisUsage &AU) const override {
+    AU.setPreservesAll();
+  }
+
+  /// To set TargetMachine *, which is used to print
+  /// analysis when command line option -print-regusage is used.
+  void setTargetMachine(const TargetMachine *TM_) { TM = TM_; }
+
+  bool doInitialization(Module &M) override;
+
+  bool doFinalization(Module &M) override;
+
+  /// To store RegMask for given Function *.
+  void storeUpdateRegUsageInfo(const Function *FP,
+                               std::vector<uint32_t> RegMask);
+
+  /// To query stored RegMask for given Function *, it will return nullptr if
+  /// function is not known.
+  const std::vector<uint32_t> *getRegUsageInfo(const Function *FP);
+
+  void print(raw_ostream &OS, const Module *M = nullptr) const override;
+
+private:
+  /// A Dense map from Function * to RegMask.
+  /// In RegMask 0 means register used (clobbered) by function.
+  /// and 1 means content of register will be preserved around function call.
+  DenseMap<const Function *, std::vector<uint32_t>> RegMasks;
+
+  const TargetMachine *TM;
+};
+}
+
+#endif

Modified: llvm/trunk/include/llvm/InitializePasses.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=272403&r1=272402&r2=272403&view=diff
==============================================================================
--- llvm/trunk/include/llvm/InitializePasses.h (original)
+++ llvm/trunk/include/llvm/InitializePasses.h Fri Jun 10 11:19:46 2016
@@ -245,6 +245,7 @@ void initializePGOIndirectCallPromotionL
 void initializePGOInstrumentationGenLegacyPassPass(PassRegistry&);
 void initializePGOInstrumentationUseLegacyPassPass(PassRegistry&);
 void initializePHIEliminationPass(PassRegistry&);
+void initializePhysicalRegisterUsageInfoPass(PassRegistry &);
 void initializePartialInlinerPass(PassRegistry&);
 void initializePartiallyInlineLibCallsLegacyPassPass(PassRegistry &);
 void initializePatchableFunctionPass(PassRegistry &);

Modified: llvm/trunk/lib/Analysis/CallGraphSCCPass.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/CallGraphSCCPass.cpp?rev=272403&r1=272402&r2=272403&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/CallGraphSCCPass.cpp (original)
+++ llvm/trunk/lib/Analysis/CallGraphSCCPass.cpp Fri Jun 10 11:19:46 2016
@@ -638,3 +638,7 @@ bool CallGraphSCCPass::skipSCC(CallGraph
               .getOptBisect()
               .shouldRunPass(this, SCC);
 }
+
+char DummyCGSCCPass::ID = 0;
+INITIALIZE_PASS(DummyCGSCCPass, "DummyCGSCCPass", "DummyCGSCCPass", false,
+                false)

Modified: llvm/trunk/lib/CodeGen/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CMakeLists.txt?rev=272403&r1=272402&r2=272403&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/CMakeLists.txt (original)
+++ llvm/trunk/lib/CodeGen/CMakeLists.txt Fri Jun 10 11:19:46 2016
@@ -101,6 +101,8 @@ add_llvm_library(LLVMCodeGen
   RegisterPressure.cpp
   RegisterScavenging.cpp
   RenameIndependentSubregs.cpp
+  RegisterUsageInfo.cpp
+  RegUsageInfoCollector.cpp
   SafeStack.cpp
   ScheduleDAG.cpp
   ScheduleDAGInstrs.cpp

Added: llvm/trunk/lib/CodeGen/RegUsageInfoCollector.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegUsageInfoCollector.cpp?rev=272403&view=auto
==============================================================================
--- llvm/trunk/lib/CodeGen/RegUsageInfoCollector.cpp (added)
+++ llvm/trunk/lib/CodeGen/RegUsageInfoCollector.cpp Fri Jun 10 11:19:46 2016
@@ -0,0 +1,131 @@
+//===- RegUsageInfoCollector.cpp - Register Usage Informartion Collector --===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// This pass is required to take advantage of the interprocedural register
+/// allocation infrastructure.
+///
+/// This pass is simple MachineFunction pass which collects register usage
+/// details by iterating through each physical registers and checking
+/// MRI::isPhysRegUsed() then creates a RegMask based on this details.
+/// The pass then stores this RegMask in PhysicalRegisterUsageInfo.cpp
+///
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineOperand.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/CodeGen/RegisterUsageInfo.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "ip-regalloc"
+
+namespace llvm {
+void initializeRegUsageInfoCollectorPass(PassRegistry &);
+}
+
+namespace {
+class RegUsageInfoCollector : public MachineFunctionPass {
+public:
+  RegUsageInfoCollector() : MachineFunctionPass(ID) {
+    PassRegistry &Registry = *PassRegistry::getPassRegistry();
+    initializeRegUsageInfoCollectorPass(Registry);
+  }
+
+  const char *getPassName() const override {
+    return "Register Usage Information Collector Pass";
+  }
+
+  void getAnalysisUsage(AnalysisUsage &AU) const override;
+
+  bool runOnMachineFunction(MachineFunction &MF) override;
+
+  static char ID;
+
+private:
+  void markRegClobbered(const TargetRegisterInfo *TRI, uint32_t *RegMask,
+                        unsigned PReg);
+};
+} // end of anonymous namespace
+
+char RegUsageInfoCollector::ID = 0;
+
+INITIALIZE_PASS_BEGIN(RegUsageInfoCollector, "RegUsageInfoCollector",
+                      "Register Usage Information Collector", false, false)
+INITIALIZE_PASS_DEPENDENCY(PhysicalRegisterUsageInfo)
+INITIALIZE_PASS_END(RegUsageInfoCollector, "RegUsageInfoCollector",
+                    "Register Usage Information Collector", false, false)
+
+FunctionPass *llvm::createRegUsageInfoCollector() {
+  return new RegUsageInfoCollector();
+}
+
+void RegUsageInfoCollector::markRegClobbered(const TargetRegisterInfo *TRI,
+                                             uint32_t *RegMask, unsigned PReg) {
+  // If PReg is clobbered then all of its alias are also clobbered.
+  for (MCRegAliasIterator AI(PReg, TRI, true); AI.isValid(); ++AI)
+    RegMask[*AI / 32] &= ~(1u << *AI % 32);
+}
+
+void RegUsageInfoCollector::getAnalysisUsage(AnalysisUsage &AU) const {
+  AU.addRequired<PhysicalRegisterUsageInfo>();
+  AU.setPreservesAll();
+  MachineFunctionPass::getAnalysisUsage(AU);
+}
+
+bool RegUsageInfoCollector::runOnMachineFunction(MachineFunction &MF) {
+  MachineRegisterInfo *MRI = &MF.getRegInfo();
+  TargetRegisterInfo *TRI =
+      (TargetRegisterInfo *)MF.getSubtarget().getRegisterInfo();
+  const TargetMachine &TM = MF.getTarget();
+
+  DEBUG(dbgs() << " -------------------- " << getPassName()
+               << " -------------------- \n");
+  DEBUG(dbgs() << "Function Name : " << MF.getName() << "\n");
+
+  std::vector<uint32_t> RegMask;
+
+  // Compute the size of the bit vector to represent all the registers.
+  // The bit vector is broken into 32-bit chunks, thus takes the ceil of
+  // the number of registers divided by 32 for the size.
+  unsigned regMaskSize = (TRI->getNumRegs() + 31) / 32;
+  RegMask.resize(regMaskSize, 0xFFFFFFFF);
+
+  PhysicalRegisterUsageInfo *PRUI = &getAnalysis<PhysicalRegisterUsageInfo>();
+
+  PRUI->setTargetMachine(&TM);
+
+  DEBUG(dbgs() << "Clobbered Registers: ");
+  for (unsigned PReg = 1, PRegE = TRI->getNumRegs(); PReg < PRegE; ++PReg) {
+    if (!MRI->reg_nodbg_empty(PReg) && MRI->isPhysRegUsed(PReg))
+      markRegClobbered(TRI, &RegMask[0], PReg);
+  }
+
+  const uint32_t *CallPreservedMask =
+      TRI->getCallPreservedMask(MF, MF.getFunction()->getCallingConv());
+  // Set callee saved register as preserved.
+  for (unsigned index = 0; index < regMaskSize; index++) {
+    RegMask[index] = RegMask[index] | CallPreservedMask[index];
+  }
+  for (unsigned PReg = 1, PRegE = TRI->getNumRegs(); PReg < PRegE; ++PReg) {
+    if (MachineOperand::clobbersPhysReg(&(RegMask[0]), PReg))
+      DEBUG(dbgs() << TRI->getName(PReg) << " ");
+  }
+
+  DEBUG(dbgs() << " \n----------------------------------------\n");
+
+  PRUI->storeUpdateRegUsageInfo(MF.getFunction(), std::move(RegMask));
+
+  return false;
+}

Added: llvm/trunk/lib/CodeGen/RegisterUsageInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegisterUsageInfo.cpp?rev=272403&view=auto
==============================================================================
--- llvm/trunk/lib/CodeGen/RegisterUsageInfo.cpp (added)
+++ llvm/trunk/lib/CodeGen/RegisterUsageInfo.cpp Fri Jun 10 11:19:46 2016
@@ -0,0 +1,92 @@
+//===- RegisterUsageInfo.cpp - Register Usage Informartion Storage --------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// This pass is required to take advantage of the interprocedural register
+/// allocation infrastructure.
+///
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CodeGen/RegisterUsageInfo.h"
+#include "llvm/CodeGen/MachineOperand.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "ip-regalloc"
+
+cl::opt<bool> DumpRegUsage(
+    "print-regusage", cl::init(false), cl::Hidden,
+    cl::desc("print register usage details collected for analysis."));
+
+INITIALIZE_PASS(PhysicalRegisterUsageInfo, "reg-usage-info",
+                "Register Usage Informartion Stroage", false, true)
+
+char PhysicalRegisterUsageInfo::ID = 0;
+
+void PhysicalRegisterUsageInfo::anchor() {}
+
+bool PhysicalRegisterUsageInfo::doInitialization(Module &M) {
+  RegMasks.grow(M.size());
+  return false;
+}
+
+bool PhysicalRegisterUsageInfo::doFinalization(Module &M) {
+  if (DumpRegUsage)
+    print(errs());
+
+  RegMasks.shrink_and_clear();
+  return false;
+}
+
+void PhysicalRegisterUsageInfo::storeUpdateRegUsageInfo(
+    const Function *FP, std::vector<uint32_t> RegMask) {
+  assert(FP != nullptr && "Function * can't be nullptr.");
+  RegMasks[FP] = std::move(RegMask);
+}
+
+const std::vector<uint32_t> *
+PhysicalRegisterUsageInfo::getRegUsageInfo(const Function *FP) {
+  if (RegMasks.find(FP) != RegMasks.end())
+    return &(RegMasks.find(FP)->second);
+  return nullptr;
+}
+
+void PhysicalRegisterUsageInfo::print(raw_ostream &OS, const Module *M) const {
+  const TargetRegisterInfo *TRI;
+
+  typedef std::pair<const Function *, std::vector<uint32_t>> FuncPtrRegMaskPair;
+
+  SmallVector<const FuncPtrRegMaskPair *, 64> FPRMPairVector;
+
+  // Create a vector of pointer to RegMasks entries
+  for (const auto &RegMask : RegMasks)
+    FPRMPairVector.push_back(&RegMask);
+
+  // sort the vector to print analysis in alphabatic order of function name.
+  std::sort(
+      FPRMPairVector.begin(), FPRMPairVector.end(),
+      [](const FuncPtrRegMaskPair *A, const FuncPtrRegMaskPair *B) -> bool {
+        return A->first->getName() < B->first->getName();
+      });
+
+  for (const FuncPtrRegMaskPair *FPRMPair : FPRMPairVector) {
+    OS << FPRMPair->first->getName() << " "
+       << "Clobbered Registers: ";
+    TRI = TM->getSubtarget<TargetSubtargetInfo>(*(FPRMPair->first))
+              .getRegisterInfo();
+
+    for (unsigned PReg = 1, PRegE = TRI->getNumRegs(); PReg < PRegE; ++PReg) {
+      if (MachineOperand::clobbersPhysReg(&(FPRMPair->second[0]), PReg))
+        OS << TRI->getName(PReg) << " ";
+    }
+    OS << "\n";
+  }
+}

Modified: llvm/trunk/lib/CodeGen/TargetPassConfig.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/TargetPassConfig.cpp?rev=272403&r1=272402&r2=272403&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/TargetPassConfig.cpp (original)
+++ llvm/trunk/lib/CodeGen/TargetPassConfig.cpp Fri Jun 10 11:19:46 2016
@@ -16,11 +16,13 @@
 
 #include "llvm/Analysis/BasicAliasAnalysis.h"
 #include "llvm/Analysis/CFLAliasAnalysis.h"
+#include "llvm/Analysis/CallGraphSCCPass.h"
 #include "llvm/Analysis/Passes.h"
 #include "llvm/Analysis/ScopedNoAliasAA.h"
 #include "llvm/Analysis/TypeBasedAliasAnalysis.h"
 #include "llvm/CodeGen/MachineFunctionPass.h"
 #include "llvm/CodeGen/RegAllocRegistry.h"
+#include "llvm/CodeGen/RegisterUsageInfo.h"
 #include "llvm/IR/IRPrintingPasses.h"
 #include "llvm/IR/LegacyPassManager.h"
 #include "llvm/IR/Verifier.h"
@@ -112,6 +114,10 @@ static cl::opt<bool> UseCFLAA("use-cfl-a
   cl::init(false), cl::Hidden,
   cl::desc("Enable the new, experimental CFL alias analysis in CodeGen"));
 
+cl::opt<bool> UseIPRA("enable-ipra", cl::init(false), cl::Hidden,
+                      cl::desc("Enable interprocedural register allocation "
+                               "to reduce load/store at procedure calls."));
+
 /// Allow standard passes to be disabled by command line options. This supports
 /// simple binary flags that either suppress the pass or do nothing.
 /// i.e. -disable-mypass=false has no effect.
@@ -492,6 +498,10 @@ void TargetPassConfig::addCodeGenPrepare
 void TargetPassConfig::addISelPrepare() {
   addPreISel();
 
+  // Force codegen to run according to the callgraph.
+  if (UseIPRA)
+    addPass(new DummyCGSCCPass);
+
   // Add both the safe stack and the stack protection passes: each of them will
   // only protect functions that have corresponding attributes.
   addPass(createSafeStackPass(TM));
@@ -613,6 +623,11 @@ void TargetPassConfig::addMachinePasses(
 
   addPreEmitPass();
 
+  if (UseIPRA)
+    // Collect register usage information and produce a register mask of
+    // clobbered registers, to be used to optimize call sites.
+    addPass(createRegUsageInfoCollector());
+
   addPass(&FuncletLayoutID, false);
 
   addPass(&StackMapLivenessID, false);

Added: llvm/trunk/test/CodeGen/X86/ipra-inline-asm.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/ipra-inline-asm.ll?rev=272403&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/ipra-inline-asm.ll (added)
+++ llvm/trunk/test/CodeGen/X86/ipra-inline-asm.ll Fri Jun 10 11:19:46 2016
@@ -0,0 +1,20 @@
+; RUN: llc -enable-ipra -print-regusage -o /dev/null 2>&1 < %s | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.12.0"
+
+; Verify that bar does not clobber anything
+; CHECK-NOT: bar Clobbered Registers:{{.+}}
+; CHECK: bar Clobbered Registers:
+define void @bar() #0 {
+  ret void
+}
+
+; Verifies that inline assembly is correctly handled by giving a list of clobbered registers
+; CHECK: foo Clobbered Registers: AH AL AX CH CL CX DI DIL EAX ECX EDI RAX RCX RDI
+define void @foo() #0 {
+  call void asm sideeffect "", "~{eax},~{ecx},~{edi}"() #0
+  ret void
+}
+
+attributes #0 = { nounwind }

Added: llvm/trunk/test/CodeGen/X86/ipra-reg-usage.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/ipra-reg-usage.ll?rev=272403&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/ipra-reg-usage.ll (added)
+++ llvm/trunk/test/CodeGen/X86/ipra-reg-usage.ll Fri Jun 10 11:19:46 2016
@@ -0,0 +1,12 @@
+; RUN: llc -enable-ipra -print-regusage -o /dev/null 2>&1 < %s | FileCheck %s
+
+target triple = "x86_64-unknown-unknown"
+declare void @bar1()
+define preserve_allcc void @foo()#0 {
+; CHECK: foo Clobbered Registers: EFLAGS YMM0 YMM1 YMM2 YMM3 YMM4 YMM5 YMM6 YMM7 YMM8 YMM9 YMM10 YMM11 YMM12 YMM13 YMM14 YMM15 ZMM0 ZMM1 ZMM2 ZMM3 ZMM4 ZMM5 ZMM6 ZMM7 ZMM8 ZMM9 ZMM10 ZMM11 ZMM12 ZMM13 ZMM14 ZMM15
+  call void @bar1()
+  call void @bar2()
+  ret void
+}
+declare void @bar2()
+attributes #0 = {nounwind}




More information about the llvm-commits mailing list