1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 20:51:52 +01:00
Jun Bum Lim 3e63efac67 Recommit r317351 : Add CallSiteSplitting pass
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
2017-11-03 20:41:16 +00:00

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)