mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-02 07:11:49 +00:00
FastISel: avoid function calls between the materialization of the constant and its use.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@137993 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
93b3eff623
commit
74af88a666
@ -54,8 +54,18 @@ protected:
|
|||||||
const TargetInstrInfo &TII;
|
const TargetInstrInfo &TII;
|
||||||
const TargetLowering &TLI;
|
const TargetLowering &TLI;
|
||||||
const TargetRegisterInfo &TRI;
|
const TargetRegisterInfo &TRI;
|
||||||
|
|
||||||
|
/// The position of the last instruction for materializing constants
|
||||||
|
/// for use in the current block. It resets to EmitStartPt when it
|
||||||
|
/// makes sense (for example, it's usually profitable to avoid function
|
||||||
|
/// calls between the definition and the use)
|
||||||
MachineInstr *LastLocalValue;
|
MachineInstr *LastLocalValue;
|
||||||
|
|
||||||
|
/// The top most instruction in the current block that is allowed for
|
||||||
|
/// emitting local variables. LastLocalValue resets to EmitStartPt when
|
||||||
|
/// it makes sense (for example, on function calls)
|
||||||
|
MachineInstr *EmitStartPt;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// getLastLocalValue - Return the position of the last instruction
|
/// getLastLocalValue - Return the position of the last instruction
|
||||||
/// emitted for materializing constants for use in the current block.
|
/// emitted for materializing constants for use in the current block.
|
||||||
@ -63,7 +73,10 @@ public:
|
|||||||
|
|
||||||
/// setLastLocalValue - Update the position of the last instruction
|
/// setLastLocalValue - Update the position of the last instruction
|
||||||
/// emitted for materializing constants for use in the current block.
|
/// emitted for materializing constants for use in the current block.
|
||||||
void setLastLocalValue(MachineInstr *I) { LastLocalValue = I; }
|
void setLastLocalValue(MachineInstr *I) {
|
||||||
|
EmitStartPt = I;
|
||||||
|
LastLocalValue = I;
|
||||||
|
}
|
||||||
|
|
||||||
/// startNewBlock - Set the current block to which generated machine
|
/// startNewBlock - Set the current block to which generated machine
|
||||||
/// instructions will be appended, and clear the local CSE map.
|
/// instructions will be appended, and clear the local CSE map.
|
||||||
@ -358,6 +371,11 @@ private:
|
|||||||
/// be materialized with new instructions.
|
/// be materialized with new instructions.
|
||||||
unsigned materializeRegForValue(const Value *V, MVT VT);
|
unsigned materializeRegForValue(const Value *V, MVT VT);
|
||||||
|
|
||||||
|
/// flushLocalValueMap - clears LocalValueMap and moves the area for the
|
||||||
|
/// new local variables to the beginning of the block. It helps to avoid
|
||||||
|
/// spilling cached variables across heavy instructions like calls.
|
||||||
|
void flushLocalValueMap();
|
||||||
|
|
||||||
/// hasTrivialKill - Test whether the given value has exactly one use.
|
/// hasTrivialKill - Test whether the given value has exactly one use.
|
||||||
bool hasTrivialKill(const Value *V) const;
|
bool hasTrivialKill(const Value *V) const;
|
||||||
};
|
};
|
||||||
|
@ -66,17 +66,22 @@ using namespace llvm;
|
|||||||
void FastISel::startNewBlock() {
|
void FastISel::startNewBlock() {
|
||||||
LocalValueMap.clear();
|
LocalValueMap.clear();
|
||||||
|
|
||||||
// Start out as null, meaining no local-value instructions have
|
EmitStartPt = 0;
|
||||||
// been emitted.
|
|
||||||
LastLocalValue = 0;
|
|
||||||
|
|
||||||
// Advance the last local value past any EH_LABEL instructions.
|
// Advance the emit start point past any EH_LABEL instructions.
|
||||||
MachineBasicBlock::iterator
|
MachineBasicBlock::iterator
|
||||||
I = FuncInfo.MBB->begin(), E = FuncInfo.MBB->end();
|
I = FuncInfo.MBB->begin(), E = FuncInfo.MBB->end();
|
||||||
while (I != E && I->getOpcode() == TargetOpcode::EH_LABEL) {
|
while (I != E && I->getOpcode() == TargetOpcode::EH_LABEL) {
|
||||||
LastLocalValue = I;
|
EmitStartPt = I;
|
||||||
++I;
|
++I;
|
||||||
}
|
}
|
||||||
|
LastLocalValue = EmitStartPt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FastISel::flushLocalValueMap() {
|
||||||
|
LocalValueMap.clear();
|
||||||
|
LastLocalValue = EmitStartPt;
|
||||||
|
recomputeInsertPt();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FastISel::hasTrivialKill(const Value *V) const {
|
bool FastISel::hasTrivialKill(const Value *V) const {
|
||||||
@ -645,6 +650,16 @@ bool FastISel::SelectCall(const User *I) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Usually, it does not make sense to initialize a value,
|
||||||
|
// make an unrelated function call and use the value, because
|
||||||
|
// it tends to be spilled on the stack. So, we move the pointer
|
||||||
|
// to the last local value to the beginning of the block, so that
|
||||||
|
// all the values which have already been materialized,
|
||||||
|
// appear after the call. It also makes sense to skip intrinsics
|
||||||
|
// since they tend to be inlined.
|
||||||
|
if (!isa<IntrinsicInst>(F))
|
||||||
|
flushLocalValueMap();
|
||||||
|
|
||||||
// An arbitrary call. Bail.
|
// An arbitrary call. Bail.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
; RUN: llc -O0 < %s | FileCheck %s
|
; RUN: llc -O0 < %s | FileCheck %s
|
||||||
; CHECK: @DEBUG_VALUE: mydata <- [sp+#8]+#0
|
; CHECK: @DEBUG_VALUE: mydata <- [sp+#4]+#0
|
||||||
; Radar 9331779
|
; Radar 9331779
|
||||||
target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:64-v128:32:128-a0:0:32-n32"
|
target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:64-v128:32:128-a0:0:32-n32"
|
||||||
target triple = "thumbv7-apple-macosx10.7.0"
|
target triple = "thumbv7-apple-macosx10.7.0"
|
||||||
|
@ -259,4 +259,27 @@ define void @test21(double* %p1) {
|
|||||||
; CHECK: test21:
|
; CHECK: test21:
|
||||||
; CHECK-NOT: pxor
|
; CHECK-NOT: pxor
|
||||||
; CHECK: movsd LCPI
|
; CHECK: movsd LCPI
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; Check that immediate arguments to a function
|
||||||
|
; do not cause massive spilling and are used
|
||||||
|
; as immediates just before the call.
|
||||||
|
define void @test22() nounwind {
|
||||||
|
entry:
|
||||||
|
call void @foo22(i32 0)
|
||||||
|
call void @foo22(i32 1)
|
||||||
|
call void @foo22(i32 2)
|
||||||
|
call void @foo22(i32 3)
|
||||||
|
ret void
|
||||||
|
; CHECK: test22:
|
||||||
|
; CHECK: movl $0, %edi
|
||||||
|
; CHECK: callq _foo22
|
||||||
|
; CHECK: movl $1, %edi
|
||||||
|
; CHECK: callq _foo22
|
||||||
|
; CHECK: movl $2, %edi
|
||||||
|
; CHECK: callq _foo22
|
||||||
|
; CHECK: movl $3, %edi
|
||||||
|
; CHECK: callq _foo22
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @foo22(i32)
|
||||||
|
Loading…
Reference in New Issue
Block a user