1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-26 04:32:44 +01:00

[MachineSink] Don't break ImplicitNulls

Summary:
This teaches MachineSink to not sink instructions that might break the
implicit null check optimization that runs later.  This should not
affect frontends that do not use implicit null checks.

Reviewers: aadg, reames, hfinkel, atrick

Subscribers: majnemer, llvm-commits

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

llvm-svn: 258254
This commit is contained in:
Sanjoy Das 2016-01-20 00:06:14 +00:00
parent 85e195fefe
commit d2d9b2b709
2 changed files with 98 additions and 0 deletions

View File

@ -27,6 +27,7 @@
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachinePostDominators.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
@ -673,6 +674,49 @@ MachineBasicBlock *MachineSinking::FindSuccToSinkTo(MachineInstr *MI,
return SuccToSinkTo;
}
/// \brief Return true if MI is likely to be usable as a memory operation by the
/// implicit null check optimization.
///
/// This is a "best effort" heuristic, and should not be relied upon for
/// correctness. This returning true does not guarantee that the implicit null
/// check optimization is legal over MI, and this returning false does not
/// guarantee MI cannot possibly be used to do a null check.
static bool SinkingPreventsImplicitNullCheck(MachineInstr *MI,
const TargetInstrInfo *TII,
const TargetRegisterInfo *TRI) {
typedef TargetInstrInfo::MachineBranchPredicate MachineBranchPredicate;
auto *MBB = MI->getParent();
if (MBB->pred_size() != 1)
return false;
auto *PredMBB = *MBB->pred_begin();
auto *PredBB = PredMBB->getBasicBlock();
// Frontends that don't use implicit null checks have no reason to emit
// branches with make.implicit metadata, and this function should always
// return false for them.
if (!PredBB ||
!PredBB->getTerminator()->getMetadata(LLVMContext::MD_make_implicit))
return false;
unsigned BaseReg, Offset;
if (!TII->getMemOpBaseRegImmOfs(MI, BaseReg, Offset, TRI))
return false;
if (!(MI->mayLoad() && !MI->isPredicable()))
return false;
MachineBranchPredicate MBP;
if (TII->AnalyzeBranchPredicate(*PredMBB, MBP, false))
return false;
return MBP.LHS.isReg() && MBP.RHS.isImm() && MBP.RHS.getImm() == 0 &&
(MBP.Predicate == MachineBranchPredicate::PRED_NE ||
MBP.Predicate == MachineBranchPredicate::PRED_EQ) &&
MBP.LHS.getReg() == BaseReg;
}
/// SinkInstruction - Determine whether it is safe to sink the specified machine
/// instruction out of its current block into a successor.
bool MachineSinking::SinkInstruction(MachineInstr *MI, bool &SawStore,
@ -691,6 +735,11 @@ bool MachineSinking::SinkInstruction(MachineInstr *MI, bool &SawStore,
if (MI->isConvergent())
return false;
// Don't break implicit null checks. This is a performance heuristic, and not
// required for correctness.
if (SinkingPreventsImplicitNullCheck(MI, TII, TRI))
return false;
// FIXME: This should include support for sinking instructions within the
// block they are currently in to shorten the live ranges. We often get
// instructions sunk into the top of a large block, but it would be better to

View File

@ -0,0 +1,49 @@
; RUN: llc -mtriple=x86_64-apple-macosx -O3 -enable-implicit-null-checks -o - < %s 2>&1 | FileCheck %s
declare void @throw0()
declare void @throw1()
define i1 @f(i8* %p0, i8* %p1) {
entry:
%c0 = icmp eq i8* %p0, null
br i1 %c0, label %throw0, label %continue0, !make.implicit !0
continue0:
%v0 = load i8, i8* %p0
%c1 = icmp eq i8* %p1, null
br i1 %c1, label %throw1, label %continue1, !make.implicit !0
continue1:
%v1 = load i8, i8* %p1
%v = icmp eq i8 %v0, %v1
ret i1 %v
throw0:
call void @throw0()
unreachable
throw1:
call void @throw1()
unreachable
}
; Check that we have two implicit null checks in @f
; CHECK: __LLVM_FaultMaps:
; CHECK-NEXT: .byte 1
; CHECK-NEXT: .byte 0
; CHECK-NEXT: .short 0
; CHECK-NEXT: .long 1
; FunctionInfo[0] =
; FunctionAddress =
; CHECK-NEXT: .quad _f
; NumFaultingPCs =
; CHECK-NEXT: .long 2
; Reserved =
; CHECK-NEXT: .long 0
!0 = !{}