2014-07-26 05:45:17 +08:00
|
|
|
; RUN: opt < %s -instcombine -S | FileCheck %s
|
|
|
|
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
|
|
|
target triple = "x86_64-unknown-linux-gnu"
|
|
|
|
|
Make use of @llvm.assume in ValueTracking (computeKnownBits, etc.)
This change, which allows @llvm.assume to be used from within computeKnownBits
(and other associated functions in ValueTracking), adds some (optional)
parameters to computeKnownBits and friends. These functions now (optionally)
take a "context" instruction pointer, an AssumptionTracker pointer, and also a
DomTree pointer, and most of the changes are just to pass this new information
when it is easily available from InstSimplify, InstCombine, etc.
As explained below, the significant conceptual change is that known properties
of a value might depend on the control-flow location of the use (because we
care that the @llvm.assume dominates the use because assumptions have
control-flow dependencies). This means that, when we ask if bits are known in a
value, we might get different answers for different uses.
The significant changes are all in ValueTracking. Two main changes: First, as
with the rest of the code, new parameters need to be passed around. To make
this easier, I grouped them into a structure, and I made internal static
versions of the relevant functions that take this structure as a parameter. The
new code does as you might expect, it looks for @llvm.assume calls that make
use of the value we're trying to learn something about (often indirectly),
attempts to pattern match that expression, and uses the result if successful.
By making use of the AssumptionTracker, the process of finding @llvm.assume
calls is not expensive.
Part of the structure being passed around inside ValueTracking is a set of
already-considered @llvm.assume calls. This is to prevent a query using, for
example, the assume(a == b), to recurse on itself. The context and DT params
are used to find applicable assumptions. An assumption needs to dominate the
context instruction, or come after it deterministically. In this latter case we
only handle the specific case where both the assumption and the context
instruction are in the same block, and we need to exclude assumptions from
being used to simplify their own ephemeral values (those which contribute only
to the assumption) because otherwise the assumption would prove its feeding
comparison trivial and would be removed.
This commit adds the plumbing and the logic for a simple masked-bit propagation
(just enough to write a regression test). Future commits add more patterns
(and, correspondingly, more regression tests).
llvm-svn: 217342
2014-09-08 02:57:58 +08:00
|
|
|
; Function Attrs: nounwind uwtable
|
|
|
|
define i32 @foo1(i32* %a) #0 {
|
|
|
|
entry:
|
|
|
|
%0 = load i32* %a, align 4
|
|
|
|
|
|
|
|
; Check that the alignment has been upgraded and that the assume has not
|
|
|
|
; been removed:
|
|
|
|
; CHECK-LABEL: @foo1
|
|
|
|
; CHECK-DAG: load i32* %a, align 32
|
|
|
|
; CHECK-DAG: call void @llvm.assume
|
|
|
|
; CHECK: ret i32
|
|
|
|
|
|
|
|
%ptrint = ptrtoint i32* %a to i64
|
|
|
|
%maskedptr = and i64 %ptrint, 31
|
|
|
|
%maskcond = icmp eq i64 %maskedptr, 0
|
|
|
|
tail call void @llvm.assume(i1 %maskcond)
|
|
|
|
|
|
|
|
ret i32 %0
|
|
|
|
}
|
|
|
|
|
|
|
|
; Function Attrs: nounwind uwtable
|
|
|
|
define i32 @foo2(i32* %a) #0 {
|
|
|
|
entry:
|
|
|
|
; Same check as in @foo1, but make sure it works if the assume is first too.
|
|
|
|
; CHECK-LABEL: @foo2
|
|
|
|
; CHECK-DAG: load i32* %a, align 32
|
|
|
|
; CHECK-DAG: call void @llvm.assume
|
|
|
|
; CHECK: ret i32
|
|
|
|
|
|
|
|
%ptrint = ptrtoint i32* %a to i64
|
|
|
|
%maskedptr = and i64 %ptrint, 31
|
|
|
|
%maskcond = icmp eq i64 %maskedptr, 0
|
|
|
|
tail call void @llvm.assume(i1 %maskcond)
|
|
|
|
|
|
|
|
%0 = load i32* %a, align 4
|
|
|
|
ret i32 %0
|
|
|
|
}
|
|
|
|
|
2014-07-26 05:45:17 +08:00
|
|
|
; Function Attrs: nounwind
|
|
|
|
declare void @llvm.assume(i1) #1
|
|
|
|
|
2014-09-08 05:28:34 +08:00
|
|
|
define i32 @simple(i32 %a) #1 {
|
|
|
|
entry:
|
|
|
|
|
|
|
|
; CHECK-LABEL: @simple
|
|
|
|
; CHECK: call void @llvm.assume
|
|
|
|
; CHECK: ret i32 4
|
|
|
|
|
|
|
|
%cmp = icmp eq i32 %a, 4
|
|
|
|
tail call void @llvm.assume(i1 %cmp)
|
|
|
|
ret i32 %a
|
|
|
|
}
|
|
|
|
|
2014-07-26 05:45:17 +08:00
|
|
|
; Function Attrs: nounwind uwtable
|
|
|
|
define i32 @can1(i1 %a, i1 %b, i1 %c) {
|
|
|
|
entry:
|
|
|
|
%and1 = and i1 %a, %b
|
|
|
|
%and = and i1 %and1, %c
|
|
|
|
tail call void @llvm.assume(i1 %and)
|
|
|
|
|
|
|
|
; CHECK-LABEL: @can1
|
|
|
|
; CHECK: call void @llvm.assume(i1 %a)
|
|
|
|
; CHECK: call void @llvm.assume(i1 %b)
|
|
|
|
; CHECK: call void @llvm.assume(i1 %c)
|
|
|
|
; CHECK: ret i32
|
|
|
|
|
|
|
|
ret i32 5
|
|
|
|
}
|
|
|
|
|
|
|
|
; Function Attrs: nounwind uwtable
|
|
|
|
define i32 @can2(i1 %a, i1 %b, i1 %c) {
|
|
|
|
entry:
|
|
|
|
%v = or i1 %a, %b
|
|
|
|
%w = xor i1 %v, 1
|
|
|
|
tail call void @llvm.assume(i1 %w)
|
|
|
|
|
|
|
|
; CHECK-LABEL: @can2
|
|
|
|
; CHECK: %[[V1:[^ ]+]] = xor i1 %a, true
|
|
|
|
; CHECK: call void @llvm.assume(i1 %[[V1]])
|
|
|
|
; CHECK: %[[V2:[^ ]+]] = xor i1 %b, true
|
|
|
|
; CHECK: call void @llvm.assume(i1 %[[V2]])
|
|
|
|
; CHECK: ret i32
|
|
|
|
|
|
|
|
ret i32 5
|
|
|
|
}
|
|
|
|
|
Make use of @llvm.assume in ValueTracking (computeKnownBits, etc.)
This change, which allows @llvm.assume to be used from within computeKnownBits
(and other associated functions in ValueTracking), adds some (optional)
parameters to computeKnownBits and friends. These functions now (optionally)
take a "context" instruction pointer, an AssumptionTracker pointer, and also a
DomTree pointer, and most of the changes are just to pass this new information
when it is easily available from InstSimplify, InstCombine, etc.
As explained below, the significant conceptual change is that known properties
of a value might depend on the control-flow location of the use (because we
care that the @llvm.assume dominates the use because assumptions have
control-flow dependencies). This means that, when we ask if bits are known in a
value, we might get different answers for different uses.
The significant changes are all in ValueTracking. Two main changes: First, as
with the rest of the code, new parameters need to be passed around. To make
this easier, I grouped them into a structure, and I made internal static
versions of the relevant functions that take this structure as a parameter. The
new code does as you might expect, it looks for @llvm.assume calls that make
use of the value we're trying to learn something about (often indirectly),
attempts to pattern match that expression, and uses the result if successful.
By making use of the AssumptionTracker, the process of finding @llvm.assume
calls is not expensive.
Part of the structure being passed around inside ValueTracking is a set of
already-considered @llvm.assume calls. This is to prevent a query using, for
example, the assume(a == b), to recurse on itself. The context and DT params
are used to find applicable assumptions. An assumption needs to dominate the
context instruction, or come after it deterministically. In this latter case we
only handle the specific case where both the assumption and the context
instruction are in the same block, and we need to exclude assumptions from
being used to simplify their own ephemeral values (those which contribute only
to the assumption) because otherwise the assumption would prove its feeding
comparison trivial and would be removed.
This commit adds the plumbing and the logic for a simple masked-bit propagation
(just enough to write a regression test). Future commits add more patterns
(and, correspondingly, more regression tests).
llvm-svn: 217342
2014-09-08 02:57:58 +08:00
|
|
|
define i32 @bar1(i32 %a) #0 {
|
|
|
|
entry:
|
|
|
|
%and1 = and i32 %a, 3
|
|
|
|
|
|
|
|
; CHECK-LABEL: @bar1
|
|
|
|
; CHECK: call void @llvm.assume
|
|
|
|
; CHECK: ret i32 1
|
|
|
|
|
|
|
|
%and = and i32 %a, 7
|
|
|
|
%cmp = icmp eq i32 %and, 1
|
|
|
|
tail call void @llvm.assume(i1 %cmp)
|
|
|
|
|
|
|
|
ret i32 %and1
|
|
|
|
}
|
|
|
|
|
|
|
|
; Function Attrs: nounwind uwtable
|
|
|
|
define i32 @bar2(i32 %a) #0 {
|
|
|
|
entry:
|
|
|
|
; CHECK-LABEL: @bar2
|
|
|
|
; CHECK: call void @llvm.assume
|
|
|
|
; CHECK: ret i32 1
|
|
|
|
|
|
|
|
%and = and i32 %a, 7
|
|
|
|
%cmp = icmp eq i32 %and, 1
|
|
|
|
tail call void @llvm.assume(i1 %cmp)
|
|
|
|
|
|
|
|
%and1 = and i32 %a, 3
|
|
|
|
ret i32 %and1
|
|
|
|
}
|
|
|
|
|
|
|
|
; Function Attrs: nounwind uwtable
|
|
|
|
define i32 @bar3(i32 %a, i1 %x, i1 %y) #0 {
|
|
|
|
entry:
|
|
|
|
%and1 = and i32 %a, 3
|
|
|
|
|
|
|
|
; Don't be fooled by other assumes around.
|
|
|
|
; CHECK-LABEL: @bar3
|
|
|
|
; CHECK: call void @llvm.assume
|
|
|
|
; CHECK: ret i32 1
|
|
|
|
|
|
|
|
tail call void @llvm.assume(i1 %x)
|
|
|
|
|
|
|
|
%and = and i32 %a, 7
|
|
|
|
%cmp = icmp eq i32 %and, 1
|
|
|
|
tail call void @llvm.assume(i1 %cmp)
|
|
|
|
|
|
|
|
tail call void @llvm.assume(i1 %y)
|
|
|
|
|
|
|
|
ret i32 %and1
|
|
|
|
}
|
|
|
|
|
|
|
|
; Function Attrs: nounwind uwtable
|
|
|
|
define i32 @bar4(i32 %a, i32 %b) {
|
|
|
|
entry:
|
|
|
|
%and1 = and i32 %b, 3
|
|
|
|
|
|
|
|
; CHECK-LABEL: @bar4
|
|
|
|
; CHECK: call void @llvm.assume
|
|
|
|
; CHECK: call void @llvm.assume
|
|
|
|
; CHECK: ret i32 1
|
|
|
|
|
|
|
|
%and = and i32 %a, 7
|
|
|
|
%cmp = icmp eq i32 %and, 1
|
|
|
|
tail call void @llvm.assume(i1 %cmp)
|
|
|
|
|
|
|
|
%cmp2 = icmp eq i32 %a, %b
|
|
|
|
tail call void @llvm.assume(i1 %cmp2)
|
|
|
|
|
|
|
|
ret i32 %and1
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @icmp1(i32 %a) #0 {
|
|
|
|
entry:
|
|
|
|
%cmp = icmp sgt i32 %a, 5
|
|
|
|
tail call void @llvm.assume(i1 %cmp)
|
|
|
|
%conv = zext i1 %cmp to i32
|
|
|
|
ret i32 %conv
|
|
|
|
|
|
|
|
; CHECK-LABEL: @icmp1
|
|
|
|
; CHECK: call void @llvm.assume
|
|
|
|
; CHECK: ret i32 1
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
; Function Attrs: nounwind uwtable
|
|
|
|
define i32 @icmp2(i32 %a) #0 {
|
|
|
|
entry:
|
|
|
|
%cmp = icmp sgt i32 %a, 5
|
|
|
|
tail call void @llvm.assume(i1 %cmp)
|
|
|
|
%0 = zext i1 %cmp to i32
|
|
|
|
%lnot.ext = xor i32 %0, 1
|
|
|
|
ret i32 %lnot.ext
|
|
|
|
|
|
|
|
; CHECK-LABEL: @icmp2
|
|
|
|
; CHECK: call void @llvm.assume
|
|
|
|
; CHECK: ret i32 0
|
|
|
|
}
|
|
|
|
|
2014-11-12 07:33:19 +08:00
|
|
|
declare void @escape(i32* %a)
|
|
|
|
|
|
|
|
; Do we canonicalize a nonnull assumption on a load into
|
|
|
|
; metadata form?
|
|
|
|
define i1 @nonnull1(i32** %a) {
|
|
|
|
entry:
|
|
|
|
%load = load i32** %a
|
|
|
|
%cmp = icmp ne i32* %load, null
|
|
|
|
tail call void @llvm.assume(i1 %cmp)
|
|
|
|
tail call void @escape(i32* %load)
|
|
|
|
%rval = icmp eq i32* %load, null
|
|
|
|
ret i1 %rval
|
|
|
|
|
|
|
|
; CHECK-LABEL: @nonnull1
|
|
|
|
; CHECK: !nonnull
|
|
|
|
; CHECK-NOT: call void @llvm.assume
|
|
|
|
; CHECK: ret i1 false
|
|
|
|
}
|
|
|
|
|
|
|
|
; Make sure the above canonicalization applies only
|
|
|
|
; to pointer types. Doing otherwise would be illegal.
|
|
|
|
define i1 @nonnull2(i32* %a) {
|
|
|
|
entry:
|
|
|
|
%load = load i32* %a
|
|
|
|
%cmp = icmp ne i32 %load, 0
|
|
|
|
tail call void @llvm.assume(i1 %cmp)
|
|
|
|
%rval = icmp eq i32 %load, 0
|
|
|
|
ret i1 %rval
|
|
|
|
|
|
|
|
; CHECK-LABEL: @nonnull2
|
|
|
|
; CHECK-NOT: !nonnull
|
|
|
|
; CHECK: call void @llvm.assume
|
|
|
|
}
|
|
|
|
|
|
|
|
; Make sure the above canonicalization does not trigger
|
|
|
|
; if the assume is control dependent on something else
|
|
|
|
define i1 @nonnull3(i32** %a, i1 %control) {
|
|
|
|
entry:
|
|
|
|
%load = load i32** %a
|
|
|
|
%cmp = icmp ne i32* %load, null
|
|
|
|
br i1 %control, label %taken, label %not_taken
|
|
|
|
taken:
|
|
|
|
tail call void @llvm.assume(i1 %cmp)
|
|
|
|
%rval = icmp eq i32* %load, null
|
|
|
|
ret i1 %rval
|
|
|
|
not_taken:
|
|
|
|
ret i1 true
|
|
|
|
|
|
|
|
; CHECK-LABEL: @nonnull3
|
|
|
|
; CHECK-NOT: !nonnull
|
|
|
|
; CHECK: call void @llvm.assume
|
|
|
|
}
|
|
|
|
|
|
|
|
; Make sure the above canonicalization does not trigger
|
|
|
|
; if the path from the load to the assume is potentially
|
|
|
|
; interrupted by an exception being thrown
|
|
|
|
define i1 @nonnull4(i32** %a) {
|
|
|
|
entry:
|
|
|
|
%load = load i32** %a
|
|
|
|
;; This call may throw!
|
|
|
|
tail call void @escape(i32* %load)
|
|
|
|
%cmp = icmp ne i32* %load, null
|
|
|
|
tail call void @llvm.assume(i1 %cmp)
|
|
|
|
%rval = icmp eq i32* %load, null
|
|
|
|
ret i1 %rval
|
|
|
|
|
|
|
|
; CHECK-LABEL: @nonnull4
|
|
|
|
; CHECK-NOT: !nonnull
|
|
|
|
; CHECK: call void @llvm.assume
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-07-26 05:45:17 +08:00
|
|
|
attributes #0 = { nounwind uwtable }
|
|
|
|
attributes #1 = { nounwind }
|
|
|
|
|