mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 03:33:20 +01:00
9a22014a44
The indirect call sequence on PPC requires that the TOC base register be saved prior to the indirect call and restored after the call since the indirect call may branch to a global entry point in another DSO which will update the TOC base. Over the last couple of years, we have improved this to: - be able to hoist TOC saves from loops (with changes to MachineLICM) - avoid multiple saves when one dominates the other[s] However, it is still possible to have multiple TOC saves dynamically in the execution path if there is no dominance relationship between them. This patch moves the TOC save to the prologue when one of the TOC saves is in a block that post-dominates entry (i.e. it cannot be avoided) or if it is in a block that is hotter than entry. Differential revision: https://reviews.llvm.org/D63803 llvm-svn: 365232
122 lines
4.2 KiB
LLVM
122 lines
4.2 KiB
LLVM
; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu < %s | FileCheck %s
|
|
define signext i32 @test1(i32 signext %i, i32 (i32)* nocapture %Func, i32 (i32)* nocapture %Func2) {
|
|
entry:
|
|
; CHECK-LABEL: test1:
|
|
; CHECK: std 2, 24(1)
|
|
; CHECK-NOT: std 2, 24(1)
|
|
%call = tail call signext i32 %Func(i32 signext %i)
|
|
%call1 = tail call signext i32 %Func2(i32 signext %i)
|
|
%add2 = add nsw i32 %call1, %call
|
|
ret i32 %add2
|
|
}
|
|
|
|
define signext i32 @test2(i32 signext %i, i32 signext %j, i32 (i32)* nocapture %Func, i32 (i32)* nocapture %Func2) {
|
|
entry:
|
|
; CHECK-LABEL: test2:
|
|
; CHECK: std 2, 24(1)
|
|
; CHECK-NOT: std 2, 24(1)
|
|
%call = tail call signext i32 %Func(i32 signext %i)
|
|
%tobool = icmp eq i32 %j, 0
|
|
br i1 %tobool, label %if.end, label %if.then
|
|
|
|
if.then: ; preds = %entry
|
|
%call1 = tail call signext i32 %Func(i32 signext %i)
|
|
%add2 = add nsw i32 %call1, %call
|
|
%call3 = tail call signext i32 %Func2(i32 signext %i)
|
|
%add4 = add nsw i32 %add2, %call3
|
|
br label %if.end
|
|
|
|
if.end: ; preds = %entry, %if.then
|
|
%Sum.0 = phi i32 [ %add4, %if.then ], [ %call, %entry ]
|
|
%call5 = tail call signext i32 %Func(i32 signext %i)
|
|
%add6 = add nsw i32 %call5, %Sum.0
|
|
ret i32 %add6
|
|
}
|
|
|
|
; Check for multiple TOC saves with if then else where neither dominates the other.
|
|
define signext i32 @test3(i32 signext %i, i32 (i32)* nocapture %Func, i32 (i32)* nocapture %Func2) {
|
|
; CHECK-LABEL: test3:
|
|
; CHECK: std 2, 24(1)
|
|
; CHECK-NOT: std 2, 24(1)
|
|
entry:
|
|
%tobool = icmp eq i32 %i, 0
|
|
br i1 %tobool, label %if.else, label %if.then
|
|
|
|
if.then: ; preds = %entry
|
|
%call = tail call signext i32 %Func(i32 signext %i)
|
|
br label %if.end
|
|
|
|
if.else: ; preds = %entry
|
|
%call1 = tail call signext i32 %Func2(i32 signext 0)
|
|
br label %if.end
|
|
|
|
if.end: ; preds = %if.else, %if.then
|
|
%Sum.0 = phi i32 [ %call, %if.then ], [ %call1, %if.else ]
|
|
%call3 = tail call signext i32 %Func(i32 signext %i)
|
|
%add4 = add nsw i32 %call3, %Sum.0
|
|
ret i32 %add4
|
|
}
|
|
|
|
define signext i32 @test4(i32 signext %i, i32 (i32)* nocapture %Func, i32 (i32)* nocapture %Func2) {
|
|
; CHECK-LABEL: test4:
|
|
; CHECK: std 2, 24(1)
|
|
; CHECK-NOT: std 2, 24(1)
|
|
|
|
entry:
|
|
%call = tail call signext i32 %Func(i32 signext %i)
|
|
%tobool = icmp eq i32 %i, 0
|
|
br i1 %tobool, label %if.else, label %if.then
|
|
|
|
if.then: ; preds = %entry
|
|
%call1 = tail call signext i32 %Func(i32 signext %i)
|
|
br label %if.end
|
|
|
|
if.else: ; preds = %entry
|
|
%call3 = tail call signext i32 %Func2(i32 signext 0)
|
|
br label %if.end
|
|
|
|
if.end: ; preds = %if.else, %if.then
|
|
%call1.pn = phi i32 [ %call1, %if.then ], [ %call3, %if.else ]
|
|
%Sum.0 = add nsw i32 %call1.pn, %call
|
|
ret i32 %Sum.0
|
|
}
|
|
|
|
; Check for multiple TOC saves with if then where neither is redundant.
|
|
define signext i32 @test5(i32 signext %i, i32 (i32)* nocapture %Func, i32 (i32)* nocapture readnone %Func2) {
|
|
entry:
|
|
; CHECK-LABEL: test5:
|
|
; CHECK: std 2, 24(1)
|
|
|
|
%tobool = icmp eq i32 %i, 0
|
|
br i1 %tobool, label %if.end, label %if.then
|
|
|
|
if.then: ; preds = %entry
|
|
%call = tail call signext i32 %Func(i32 signext %i)
|
|
br label %if.end
|
|
|
|
if.end: ; preds = %entry, %if.then
|
|
%Sum.0 = phi i32 [ %call, %if.then ], [ 0, %entry ]
|
|
%call1 = tail call signext i32 %Func(i32 signext %i)
|
|
%add2 = add nsw i32 %call1, %Sum.0
|
|
ret i32 %add2
|
|
}
|
|
|
|
; Check for multiple TOC saves if there are dynamic allocations on the stack.
|
|
define signext i32 @test6(i32 signext %i, i32 (i32)* nocapture %Func, i32 (i32)* nocapture %Func2) {
|
|
entry:
|
|
; CHECK-LABEL: test6:
|
|
; CHECK: std 2, 24(1)
|
|
; CHECK: std 2, 24(1)
|
|
|
|
%conv = sext i32 %i to i64
|
|
%0 = alloca i8, i64 %conv, align 16
|
|
%1 = bitcast i8* %0 to i32*
|
|
%call = tail call signext i32 %Func(i32 signext %i)
|
|
call void @useAlloca(i32* nonnull %1, i32 signext %call)
|
|
%call1 = call signext i32 %Func2(i32 signext %i)
|
|
%add2 = add nsw i32 %call1, %call
|
|
ret i32 %add2
|
|
}
|
|
|
|
declare void @useAlloca(i32*, i32 signext)
|