mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
3e63efac67
This recommit r317351 after fixing a buildbot failure. Original commit message: Summary: This change add a pass which tries to split a call-site to pass more constrained arguments if its argument is predicated in the control flow so that we can expose better context to the later passes (e.g, inliner, jump threading, or IPA-CP based function cloning, etc.). As of now we support two cases : 1) If a call site is dominated by an OR condition and if any of its arguments are predicated on this OR condition, try to split the condition with more constrained arguments. For example, in the code below, we try to split the call site since we can predicate the argument (ptr) based on the OR condition. Split from : if (!ptr || c) callee(ptr); to : if (!ptr) callee(null ptr) // set the known constant value else if (c) callee(nonnull ptr) // set non-null attribute in the argument 2) We can also split a call-site based on constant incoming values of a PHI For example, from : BB0: %c = icmp eq i32 %i1, %i2 br i1 %c, label %BB2, label %BB1 BB1: br label %BB2 BB2: %p = phi i32 [ 0, %BB0 ], [ 1, %BB1 ] call void @bar(i32 %p) to BB0: %c = icmp eq i32 %i1, %i2 br i1 %c, label %BB2-split0, label %BB1 BB1: br label %BB2-split1 BB2-split0: call void @bar(i32 0) br label %BB2 BB2-split1: call void @bar(i32 1) br label %BB2 BB2: %p = phi i32 [ 0, %BB2-split0 ], [ 1, %BB2-split1 ] llvm-svn: 317362
120 lines
4.0 KiB
LLVM
120 lines
4.0 KiB
LLVM
; RUN: opt < %s -callsite-splitting -inline -instcombine -jump-threading -S | FileCheck %s
|
|
; RUN: opt < %s -passes='function(callsite-splitting),cgscc(inline),function(instcombine,jump-threading)' -S | FileCheck %s
|
|
|
|
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
|
|
target triple = "aarch64-linaro-linux-gnueabi"
|
|
|
|
%struct.bitmap = type { i32, %struct.bitmap* }
|
|
|
|
;CHECK-LABEL: @caller
|
|
;CHECK-LABEL: NextCond:
|
|
;CHECK: br {{.*}} label %callee.exit
|
|
;CHECK-LABEL: CallSiteBB.predBB1.split:
|
|
;CHECK: call void @callee(%struct.bitmap* null, %struct.bitmap* null, %struct.bitmap* %b_elt, i1 false)
|
|
;CHECK-LABEL: callee.exit:
|
|
;CHECK: call void @dummy2(%struct.bitmap* %a_elt)
|
|
|
|
define void @caller(i1 %c, %struct.bitmap* %a_elt, %struct.bitmap* %b_elt) {
|
|
entry:
|
|
br label %Top
|
|
|
|
Top:
|
|
%tobool1 = icmp eq %struct.bitmap* %a_elt, null
|
|
br i1 %tobool1, label %CallSiteBB, label %NextCond
|
|
|
|
NextCond:
|
|
%cmp = icmp ne %struct.bitmap* %b_elt, null
|
|
br i1 %cmp, label %CallSiteBB, label %End
|
|
|
|
CallSiteBB:
|
|
%p = phi i1 [0, %Top], [%c, %NextCond]
|
|
call void @callee(%struct.bitmap* %a_elt, %struct.bitmap* %a_elt, %struct.bitmap* %b_elt, i1 %p)
|
|
br label %End
|
|
|
|
End:
|
|
ret void
|
|
}
|
|
|
|
define void @callee(%struct.bitmap* %dst_elt, %struct.bitmap* %a_elt, %struct.bitmap* %b_elt, i1 %c) {
|
|
entry:
|
|
%tobool = icmp ne %struct.bitmap* %a_elt, null
|
|
%tobool1 = icmp ne %struct.bitmap* %b_elt, null
|
|
%or.cond = and i1 %tobool, %tobool1
|
|
br i1 %or.cond, label %Cond, label %Big
|
|
|
|
Cond:
|
|
%cmp = icmp eq %struct.bitmap* %dst_elt, %a_elt
|
|
br i1 %cmp, label %Small, label %Big
|
|
|
|
Small:
|
|
call void @dummy2(%struct.bitmap* %a_elt)
|
|
br label %End
|
|
|
|
Big:
|
|
call void @dummy1(%struct.bitmap* %a_elt, %struct.bitmap* %a_elt, %struct.bitmap* %a_elt, %struct.bitmap* %a_elt, %struct.bitmap* %a_elt, %struct.bitmap* %a_elt)
|
|
call void @dummy1(%struct.bitmap* %a_elt, %struct.bitmap* %a_elt, %struct.bitmap* %a_elt, %struct.bitmap* %a_elt, %struct.bitmap* %a_elt, %struct.bitmap* %a_elt)
|
|
call void @dummy1(%struct.bitmap* %a_elt, %struct.bitmap* %a_elt, %struct.bitmap* %a_elt, %struct.bitmap* %a_elt, %struct.bitmap* %a_elt, %struct.bitmap* %a_elt)
|
|
call void @dummy1(%struct.bitmap* %a_elt, %struct.bitmap* %a_elt, %struct.bitmap* %a_elt, %struct.bitmap* %a_elt, %struct.bitmap* %a_elt, %struct.bitmap* %a_elt)
|
|
call void @dummy1(%struct.bitmap* %a_elt, %struct.bitmap* %a_elt, %struct.bitmap* %a_elt, %struct.bitmap* %a_elt, %struct.bitmap* %a_elt, %struct.bitmap* %a_elt)
|
|
call void @dummy1(%struct.bitmap* %a_elt, %struct.bitmap* %a_elt, %struct.bitmap* %a_elt, %struct.bitmap* %a_elt, %struct.bitmap* %a_elt, %struct.bitmap* %a_elt)
|
|
call void @dummy1(%struct.bitmap* %a_elt, %struct.bitmap* %a_elt, %struct.bitmap* %a_elt, %struct.bitmap* %a_elt, %struct.bitmap* %a_elt, %struct.bitmap* %a_elt)
|
|
br label %End
|
|
|
|
End:
|
|
ret void
|
|
}
|
|
|
|
declare void @dummy2(%struct.bitmap*)
|
|
declare void @dummy1(%struct.bitmap*, %struct.bitmap*, %struct.bitmap*, %struct.bitmap*, %struct.bitmap*, %struct.bitmap*)
|
|
|
|
|
|
;CHECK-LABEL: @caller2
|
|
;CHECK-LABEL: CallSiteBB.predBB1.split:
|
|
;CHECK: call void @dummy4()
|
|
;CHECK-LABEL: CallSiteBB.predBB2.split:
|
|
;CHECK: call void @dummy3()
|
|
;CheCK-LABEL: CallSiteBB:
|
|
;CHECK: %phi.call = phi i1 [ false, %CallSiteBB.predBB1.split ], [ true, %CallSiteBB.predBB2.split ]
|
|
;CHECK: call void @foo(i1 %phi.call)
|
|
define void @caller2(i1 %c, %struct.bitmap* %a_elt, %struct.bitmap* %b_elt, %struct.bitmap* %c_elt) {
|
|
entry:
|
|
br label %Top
|
|
|
|
Top:
|
|
%tobool1 = icmp eq %struct.bitmap* %a_elt, %b_elt
|
|
br i1 %tobool1, label %CallSiteBB, label %NextCond
|
|
|
|
NextCond:
|
|
%cmp = icmp ne %struct.bitmap* %b_elt, %c_elt
|
|
br i1 %cmp, label %CallSiteBB, label %End
|
|
|
|
CallSiteBB:
|
|
%phi = phi i1 [0, %Top],[1, %NextCond]
|
|
%u = call i1 @callee2(i1 %phi)
|
|
call void @foo(i1 %u)
|
|
br label %End
|
|
|
|
End:
|
|
ret void
|
|
}
|
|
|
|
define i1 @callee2(i1 %b) {
|
|
entry:
|
|
br i1 %b, label %BB1, label %BB2
|
|
|
|
BB1:
|
|
call void @dummy3()
|
|
br label %End
|
|
|
|
BB2:
|
|
call void @dummy4()
|
|
br label %End
|
|
|
|
End:
|
|
ret i1 %b
|
|
}
|
|
|
|
declare void @dummy3()
|
|
declare void @dummy4()
|
|
declare void @foo(i1)
|