15 changes: 15 additions & 0 deletions llvm/lib/CodeGen/TargetPassConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -112,6 +114,10 @@ static cl::opt<bool> UseCFLAA("use-cfl-aa-in-codegen",
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.
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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);
Expand Down
20 changes: 20 additions & 0 deletions llvm/test/CodeGen/X86/ipra-inline-asm.ll
Original file line number Diff line number Diff line change
@@ -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 }
12 changes: 12 additions & 0 deletions llvm/test/CodeGen/X86/ipra-reg-usage.ll
Original file line number Diff line number Diff line change
@@ -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}