2020-01-12 15:09:22 +08:00
|
|
|
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
|
2020-02-10 15:31:20 +08:00
|
|
|
; RUN: opt -attributor -attributor-disable=false -S < %s | FileCheck %s --check-prefixes=CHECK,OLD_PM,MODULE_OLD_PM
|
|
|
|
; RUN: opt -passes=attributor -attributor-disable=false -S < %s | FileCheck %s --check-prefixes=CHECK,NEW_PM,MODULE_NEW_PM
|
|
|
|
; RUN: opt -attributor-cgscc -attributor-disable=false -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC_OLD_PM
|
|
|
|
; RUN: opt -passes=attributor-cgscc -attributor-disable=false -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC_NEW_PM
|
2020-02-10 09:08:19 +08:00
|
|
|
|
|
|
|
; FIXME: CGSCC is not looking at callees and calleers even though it could be allowed.
|
[Attributor] AAValueConstantRange: Value range analysis using constant range
Summary:
This patch introduces `AAValueConstantRange`, which answers a possible range for integer value in a specific program point.
One of the motivations is propagating existing `range` metadata. (I think we need to change the situation that `range` metadata cannot be put to Argument).
The state is a tuple of `ConstantRange` and it is initialized to (known, assumed) = ([-∞, +∞], empty).
Currently, AAValueConstantRange is created in `getAssumedConstant` method when `AAValueSimplify` returns `nullptr`(worst state).
Supported
- BinaryOperator(add, sub, ...)
- CmpInst(icmp eq, ...)
- !range metadata
`AAValueConstantRange` is not intended to extend to polyhedral range value analysis.
Reviewers: jdoerfert, sstefan1
Reviewed By: jdoerfert
Subscribers: phosek, davezarzycki, baziotis, hiraditya, javed.absar, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D71620
2020-01-15 14:25:52 +08:00
|
|
|
|
|
|
|
define i32 @test0(i32* %p) {
|
|
|
|
; CHECK-LABEL: define {{[^@]+}}@test0
|
|
|
|
; CHECK-SAME: (i32* nocapture nofree nonnull readonly dereferenceable(4) [[P:%.*]])
|
|
|
|
; CHECK-NEXT: [[A:%.*]] = load i32, i32* [[P]], !range !0
|
|
|
|
; CHECK-NEXT: ret i32 [[A]]
|
|
|
|
;
|
|
|
|
%a = load i32, i32* %p, !range !0
|
|
|
|
ret i32 %a
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @test0-range-check(i32* %p) {
|
2020-02-10 09:08:19 +08:00
|
|
|
;
|
2020-02-10 15:31:20 +08:00
|
|
|
; OLD_PM-LABEL: define {{[^@]+}}@test0-range-check
|
|
|
|
; OLD_PM-SAME: (i32* nocapture nofree readonly [[P:%.*]])
|
|
|
|
; OLD_PM-NEXT: [[A:%.*]] = tail call i32 @test0(i32* nocapture nofree readonly [[P]]) #0, !range !0
|
|
|
|
; OLD_PM-NEXT: ret i32 [[A]]
|
|
|
|
;
|
|
|
|
; NEW_PM-LABEL: define {{[^@]+}}@test0-range-check
|
|
|
|
; NEW_PM-SAME: (i32* nocapture nofree readonly [[P:%.*]])
|
|
|
|
; NEW_PM-NEXT: [[A:%.*]] = tail call i32 @test0(i32* nocapture nofree readonly [[P]]) #0, !range !0
|
|
|
|
; NEW_PM-NEXT: ret i32 [[A]]
|
|
|
|
;
|
|
|
|
; CGSCC_OLD_PM-LABEL: define {{[^@]+}}@test0-range-check
|
|
|
|
; CGSCC_OLD_PM-SAME: (i32* nocapture nofree nonnull readonly dereferenceable(4) [[P:%.*]])
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[A:%.*]] = tail call i32 @test0(i32* nocapture nofree nonnull readonly dereferenceable(4) [[P]])
|
|
|
|
; CGSCC_OLD_PM-NEXT: ret i32 [[A]]
|
|
|
|
;
|
|
|
|
; CGSCC_NEW_PM-LABEL: define {{[^@]+}}@test0-range-check
|
|
|
|
; CGSCC_NEW_PM-SAME: (i32* nocapture nofree nonnull readonly dereferenceable(4) [[P:%.*]])
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[A:%.*]] = tail call i32 @test0(i32* nocapture nofree nonnull readonly dereferenceable(4) [[P]])
|
|
|
|
; CGSCC_NEW_PM-NEXT: ret i32 [[A]]
|
|
|
|
;
|
2020-02-10 09:08:19 +08:00
|
|
|
; MODULE-LABEL: define {{[^@]+}}@test0-range-check
|
|
|
|
; MODULE-SAME: (i32* nocapture nofree readonly [[P:%.*]])
|
|
|
|
; MODULE-NEXT: [[A:%.*]] = tail call i32 @test0(i32* nocapture nofree readonly [[P]]) #0, !range !0
|
|
|
|
; MODULE-NEXT: ret i32 [[A]]
|
|
|
|
; CGSCC-LABEL: define {{[^@]+}}@test0-range-check
|
|
|
|
; CGSCC-SAME: (i32* nocapture nofree nonnull readonly dereferenceable(4) [[P:%.*]])
|
|
|
|
; CGSCC-NEXT: [[A:%.*]] = tail call i32 @test0(i32* nocapture nofree nonnull readonly dereferenceable(4) [[P]])
|
|
|
|
; CGSCC-NEXT: ret i32 [[A]]
|
[Attributor] AAValueConstantRange: Value range analysis using constant range
Summary:
This patch introduces `AAValueConstantRange`, which answers a possible range for integer value in a specific program point.
One of the motivations is propagating existing `range` metadata. (I think we need to change the situation that `range` metadata cannot be put to Argument).
The state is a tuple of `ConstantRange` and it is initialized to (known, assumed) = ([-∞, +∞], empty).
Currently, AAValueConstantRange is created in `getAssumedConstant` method when `AAValueSimplify` returns `nullptr`(worst state).
Supported
- BinaryOperator(add, sub, ...)
- CmpInst(icmp eq, ...)
- !range metadata
`AAValueConstantRange` is not intended to extend to polyhedral range value analysis.
Reviewers: jdoerfert, sstefan1
Reviewed By: jdoerfert
Subscribers: phosek, davezarzycki, baziotis, hiraditya, javed.absar, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D71620
2020-01-15 14:25:52 +08:00
|
|
|
%a = tail call i32 @test0(i32* %p)
|
|
|
|
ret i32 %a
|
|
|
|
}
|
|
|
|
|
|
|
|
declare void @use3-dummy(i1, i1, i1)
|
|
|
|
define void @use3(i1, i1, i1) {
|
|
|
|
; CHECK-LABEL: define {{[^@]+}}@use3
|
|
|
|
; CHECK-SAME: (i1 [[TMP0:%.*]], i1 [[TMP1:%.*]], i1 [[TMP2:%.*]])
|
|
|
|
; CHECK-NEXT: tail call void @use3-dummy(i1 [[TMP0]], i1 [[TMP1]], i1 [[TMP2]])
|
|
|
|
; CHECK-NEXT: ret void
|
|
|
|
;
|
|
|
|
tail call void @use3-dummy(i1 %0, i1 %1, i1 %2)
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
; TEST0 icmp test
|
|
|
|
define void @test0-icmp-check(i32* %p){
|
2020-02-10 15:31:20 +08:00
|
|
|
; OLD_PM-LABEL: define {{[^@]+}}@test0-icmp-check
|
|
|
|
; OLD_PM-SAME: (i32* nocapture nofree readonly [[P:%.*]])
|
|
|
|
; OLD_PM-NEXT: [[RET:%.*]] = tail call i32 @test0(i32* nocapture nofree readonly [[P]]) #0, !range !0
|
|
|
|
; OLD_PM-NEXT: [[CMP_EQ_2:%.*]] = icmp eq i32 [[RET]], 9
|
|
|
|
; OLD_PM-NEXT: [[CMP_EQ_3:%.*]] = icmp eq i32 [[RET]], 8
|
|
|
|
; OLD_PM-NEXT: [[CMP_EQ_4:%.*]] = icmp eq i32 [[RET]], 1
|
|
|
|
; OLD_PM-NEXT: [[CMP_EQ_5:%.*]] = icmp eq i32 [[RET]], 0
|
|
|
|
; OLD_PM-NEXT: tail call void @use3(i1 false, i1 [[CMP_EQ_2]], i1 [[CMP_EQ_3]])
|
|
|
|
; OLD_PM-NEXT: tail call void @use3(i1 [[CMP_EQ_4]], i1 [[CMP_EQ_5]], i1 false)
|
|
|
|
; OLD_PM-NEXT: [[CMP_NE_2:%.*]] = icmp ne i32 [[RET]], 9
|
|
|
|
; OLD_PM-NEXT: [[CMP_NE_3:%.*]] = icmp ne i32 [[RET]], 8
|
|
|
|
; OLD_PM-NEXT: [[CMP_NE_4:%.*]] = icmp ne i32 [[RET]], 1
|
|
|
|
; OLD_PM-NEXT: [[CMP_NE_5:%.*]] = icmp ne i32 [[RET]], 0
|
|
|
|
; OLD_PM-NEXT: tail call void @use3(i1 true, i1 [[CMP_NE_2]], i1 [[CMP_NE_3]])
|
|
|
|
; OLD_PM-NEXT: tail call void @use3(i1 [[CMP_NE_4]], i1 [[CMP_NE_5]], i1 true)
|
|
|
|
; OLD_PM-NEXT: [[CMP_UGT_3:%.*]] = icmp ugt i32 [[RET]], 8
|
|
|
|
; OLD_PM-NEXT: [[CMP_UGT_4:%.*]] = icmp ugt i32 [[RET]], 1
|
|
|
|
; OLD_PM-NEXT: [[CMP_UGT_5:%.*]] = icmp ugt i32 [[RET]], 0
|
|
|
|
; OLD_PM-NEXT: tail call void @use3(i1 false, i1 false, i1 [[CMP_UGT_3]])
|
|
|
|
; OLD_PM-NEXT: tail call void @use3(i1 [[CMP_UGT_4]], i1 [[CMP_UGT_5]], i1 false)
|
|
|
|
; OLD_PM-NEXT: [[CMP_UGE_2:%.*]] = icmp uge i32 [[RET]], 9
|
|
|
|
; OLD_PM-NEXT: [[CMP_UGE_3:%.*]] = icmp uge i32 [[RET]], 8
|
|
|
|
; OLD_PM-NEXT: [[CMP_UGE_4:%.*]] = icmp uge i32 [[RET]], 1
|
|
|
|
; OLD_PM-NEXT: tail call void @use3(i1 false, i1 [[CMP_UGE_2]], i1 [[CMP_UGE_3]])
|
|
|
|
; OLD_PM-NEXT: tail call void @use3(i1 [[CMP_UGE_4]], i1 true, i1 false)
|
|
|
|
; OLD_PM-NEXT: [[CMP_SGT_3:%.*]] = icmp sgt i32 [[RET]], 8
|
|
|
|
; OLD_PM-NEXT: [[CMP_SGT_4:%.*]] = icmp sgt i32 [[RET]], 1
|
|
|
|
; OLD_PM-NEXT: [[CMP_SGT_5:%.*]] = icmp sgt i32 [[RET]], 0
|
|
|
|
; OLD_PM-NEXT: tail call void @use3(i1 false, i1 false, i1 [[CMP_SGT_3]])
|
|
|
|
; OLD_PM-NEXT: tail call void @use3(i1 [[CMP_SGT_4]], i1 [[CMP_SGT_5]], i1 true)
|
|
|
|
; OLD_PM-NEXT: [[CMP_GTE_2:%.*]] = icmp sge i32 [[RET]], 9
|
|
|
|
; OLD_PM-NEXT: [[CMP_GTE_3:%.*]] = icmp sge i32 [[RET]], 8
|
|
|
|
; OLD_PM-NEXT: [[CMP_GTE_4:%.*]] = icmp sge i32 [[RET]], 1
|
|
|
|
; OLD_PM-NEXT: tail call void @use3(i1 false, i1 [[CMP_GTE_2]], i1 [[CMP_GTE_3]])
|
|
|
|
; OLD_PM-NEXT: tail call void @use3(i1 [[CMP_GTE_4]], i1 true, i1 true)
|
|
|
|
; OLD_PM-NEXT: [[CMP_SLT_2:%.*]] = icmp slt i32 [[RET]], 9
|
|
|
|
; OLD_PM-NEXT: [[CMP_SLT_3:%.*]] = icmp slt i32 [[RET]], 8
|
|
|
|
; OLD_PM-NEXT: [[CMP_SLT_4:%.*]] = icmp slt i32 [[RET]], 1
|
|
|
|
; OLD_PM-NEXT: tail call void @use3(i1 true, i1 [[CMP_SLT_2]], i1 [[CMP_SLT_3]])
|
|
|
|
; OLD_PM-NEXT: tail call void @use3(i1 [[CMP_SLT_4]], i1 false, i1 false)
|
|
|
|
; OLD_PM-NEXT: [[CMP_LTE_3:%.*]] = icmp sle i32 [[RET]], 8
|
|
|
|
; OLD_PM-NEXT: [[CMP_LTE_4:%.*]] = icmp sle i32 [[RET]], 1
|
|
|
|
; OLD_PM-NEXT: [[CMP_LTE_5:%.*]] = icmp sle i32 [[RET]], 0
|
|
|
|
; OLD_PM-NEXT: tail call void @use3(i1 true, i1 true, i1 [[CMP_LTE_3]])
|
|
|
|
; OLD_PM-NEXT: tail call void @use3(i1 [[CMP_LTE_4]], i1 [[CMP_LTE_5]], i1 false)
|
|
|
|
; OLD_PM-NEXT: ret void
|
|
|
|
;
|
|
|
|
; NEW_PM-LABEL: define {{[^@]+}}@test0-icmp-check
|
|
|
|
; NEW_PM-SAME: (i32* nocapture nofree readonly [[P:%.*]])
|
|
|
|
; NEW_PM-NEXT: [[RET:%.*]] = tail call i32 @test0(i32* nocapture nofree readonly [[P]]) #0, !range !0
|
|
|
|
; NEW_PM-NEXT: [[CMP_EQ_2:%.*]] = icmp eq i32 [[RET]], 9
|
|
|
|
; NEW_PM-NEXT: [[CMP_EQ_3:%.*]] = icmp eq i32 [[RET]], 8
|
|
|
|
; NEW_PM-NEXT: [[CMP_EQ_4:%.*]] = icmp eq i32 [[RET]], 1
|
|
|
|
; NEW_PM-NEXT: [[CMP_EQ_5:%.*]] = icmp eq i32 [[RET]], 0
|
|
|
|
; NEW_PM-NEXT: tail call void @use3(i1 false, i1 [[CMP_EQ_2]], i1 [[CMP_EQ_3]])
|
|
|
|
; NEW_PM-NEXT: tail call void @use3(i1 [[CMP_EQ_4]], i1 [[CMP_EQ_5]], i1 false)
|
|
|
|
; NEW_PM-NEXT: [[CMP_NE_2:%.*]] = icmp ne i32 [[RET]], 9
|
|
|
|
; NEW_PM-NEXT: [[CMP_NE_3:%.*]] = icmp ne i32 [[RET]], 8
|
|
|
|
; NEW_PM-NEXT: [[CMP_NE_4:%.*]] = icmp ne i32 [[RET]], 1
|
|
|
|
; NEW_PM-NEXT: [[CMP_NE_5:%.*]] = icmp ne i32 [[RET]], 0
|
|
|
|
; NEW_PM-NEXT: tail call void @use3(i1 true, i1 [[CMP_NE_2]], i1 [[CMP_NE_3]])
|
|
|
|
; NEW_PM-NEXT: tail call void @use3(i1 [[CMP_NE_4]], i1 [[CMP_NE_5]], i1 true)
|
|
|
|
; NEW_PM-NEXT: [[CMP_UGT_3:%.*]] = icmp ugt i32 [[RET]], 8
|
|
|
|
; NEW_PM-NEXT: [[CMP_UGT_4:%.*]] = icmp ugt i32 [[RET]], 1
|
|
|
|
; NEW_PM-NEXT: [[CMP_UGT_5:%.*]] = icmp ugt i32 [[RET]], 0
|
|
|
|
; NEW_PM-NEXT: tail call void @use3(i1 false, i1 false, i1 [[CMP_UGT_3]])
|
|
|
|
; NEW_PM-NEXT: tail call void @use3(i1 [[CMP_UGT_4]], i1 [[CMP_UGT_5]], i1 false)
|
|
|
|
; NEW_PM-NEXT: [[CMP_UGE_2:%.*]] = icmp uge i32 [[RET]], 9
|
|
|
|
; NEW_PM-NEXT: [[CMP_UGE_3:%.*]] = icmp uge i32 [[RET]], 8
|
|
|
|
; NEW_PM-NEXT: [[CMP_UGE_4:%.*]] = icmp uge i32 [[RET]], 1
|
|
|
|
; NEW_PM-NEXT: tail call void @use3(i1 false, i1 [[CMP_UGE_2]], i1 [[CMP_UGE_3]])
|
|
|
|
; NEW_PM-NEXT: tail call void @use3(i1 [[CMP_UGE_4]], i1 true, i1 false)
|
|
|
|
; NEW_PM-NEXT: [[CMP_SGT_3:%.*]] = icmp sgt i32 [[RET]], 8
|
|
|
|
; NEW_PM-NEXT: [[CMP_SGT_4:%.*]] = icmp sgt i32 [[RET]], 1
|
|
|
|
; NEW_PM-NEXT: [[CMP_SGT_5:%.*]] = icmp sgt i32 [[RET]], 0
|
|
|
|
; NEW_PM-NEXT: tail call void @use3(i1 false, i1 false, i1 [[CMP_SGT_3]])
|
|
|
|
; NEW_PM-NEXT: tail call void @use3(i1 [[CMP_SGT_4]], i1 [[CMP_SGT_5]], i1 true)
|
|
|
|
; NEW_PM-NEXT: [[CMP_GTE_2:%.*]] = icmp sge i32 [[RET]], 9
|
|
|
|
; NEW_PM-NEXT: [[CMP_GTE_3:%.*]] = icmp sge i32 [[RET]], 8
|
|
|
|
; NEW_PM-NEXT: [[CMP_GTE_4:%.*]] = icmp sge i32 [[RET]], 1
|
|
|
|
; NEW_PM-NEXT: tail call void @use3(i1 false, i1 [[CMP_GTE_2]], i1 [[CMP_GTE_3]])
|
|
|
|
; NEW_PM-NEXT: tail call void @use3(i1 [[CMP_GTE_4]], i1 true, i1 true)
|
|
|
|
; NEW_PM-NEXT: [[CMP_SLT_2:%.*]] = icmp slt i32 [[RET]], 9
|
|
|
|
; NEW_PM-NEXT: [[CMP_SLT_3:%.*]] = icmp slt i32 [[RET]], 8
|
|
|
|
; NEW_PM-NEXT: [[CMP_SLT_4:%.*]] = icmp slt i32 [[RET]], 1
|
|
|
|
; NEW_PM-NEXT: tail call void @use3(i1 true, i1 [[CMP_SLT_2]], i1 [[CMP_SLT_3]])
|
|
|
|
; NEW_PM-NEXT: tail call void @use3(i1 [[CMP_SLT_4]], i1 false, i1 false)
|
|
|
|
; NEW_PM-NEXT: [[CMP_LTE_3:%.*]] = icmp sle i32 [[RET]], 8
|
|
|
|
; NEW_PM-NEXT: [[CMP_LTE_4:%.*]] = icmp sle i32 [[RET]], 1
|
|
|
|
; NEW_PM-NEXT: [[CMP_LTE_5:%.*]] = icmp sle i32 [[RET]], 0
|
|
|
|
; NEW_PM-NEXT: tail call void @use3(i1 true, i1 true, i1 [[CMP_LTE_3]])
|
|
|
|
; NEW_PM-NEXT: tail call void @use3(i1 [[CMP_LTE_4]], i1 [[CMP_LTE_5]], i1 false)
|
|
|
|
; NEW_PM-NEXT: ret void
|
|
|
|
;
|
|
|
|
; CGSCC_OLD_PM-LABEL: define {{[^@]+}}@test0-icmp-check
|
|
|
|
; CGSCC_OLD_PM-SAME: (i32* nocapture nofree nonnull readonly dereferenceable(4) [[P:%.*]])
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[RET:%.*]] = tail call i32 @test0(i32* nocapture nofree nonnull readonly dereferenceable(4) [[P]])
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_EQ_1:%.*]] = icmp eq i32 [[RET]], 10
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_EQ_2:%.*]] = icmp eq i32 [[RET]], 9
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_EQ_3:%.*]] = icmp eq i32 [[RET]], 8
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_EQ_4:%.*]] = icmp eq i32 [[RET]], 1
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_EQ_5:%.*]] = icmp eq i32 [[RET]], 0
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_EQ_6:%.*]] = icmp eq i32 [[RET]], -1
|
|
|
|
; CGSCC_OLD_PM-NEXT: tail call void @use3(i1 [[CMP_EQ_1]], i1 [[CMP_EQ_2]], i1 [[CMP_EQ_3]])
|
|
|
|
; CGSCC_OLD_PM-NEXT: tail call void @use3(i1 [[CMP_EQ_4]], i1 [[CMP_EQ_5]], i1 [[CMP_EQ_6]])
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_NE_1:%.*]] = icmp ne i32 [[RET]], 10
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_NE_2:%.*]] = icmp ne i32 [[RET]], 9
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_NE_3:%.*]] = icmp ne i32 [[RET]], 8
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_NE_4:%.*]] = icmp ne i32 [[RET]], 1
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_NE_5:%.*]] = icmp ne i32 [[RET]], 0
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_NE_6:%.*]] = icmp ne i32 [[RET]], -1
|
|
|
|
; CGSCC_OLD_PM-NEXT: tail call void @use3(i1 [[CMP_NE_1]], i1 [[CMP_NE_2]], i1 [[CMP_NE_3]])
|
|
|
|
; CGSCC_OLD_PM-NEXT: tail call void @use3(i1 [[CMP_NE_4]], i1 [[CMP_NE_5]], i1 [[CMP_NE_6]])
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_UGT_1:%.*]] = icmp ugt i32 [[RET]], 10
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_UGT_2:%.*]] = icmp ugt i32 [[RET]], 9
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_UGT_3:%.*]] = icmp ugt i32 [[RET]], 8
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_UGT_4:%.*]] = icmp ugt i32 [[RET]], 1
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_UGT_5:%.*]] = icmp ugt i32 [[RET]], 0
|
|
|
|
; CGSCC_OLD_PM-NEXT: tail call void @use3(i1 [[CMP_UGT_1]], i1 [[CMP_UGT_2]], i1 [[CMP_UGT_3]])
|
|
|
|
; CGSCC_OLD_PM-NEXT: tail call void @use3(i1 [[CMP_UGT_4]], i1 [[CMP_UGT_5]], i1 false)
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_UGE_1:%.*]] = icmp uge i32 [[RET]], 10
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_UGE_2:%.*]] = icmp uge i32 [[RET]], 9
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_UGE_3:%.*]] = icmp uge i32 [[RET]], 8
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_UGE_4:%.*]] = icmp uge i32 [[RET]], 1
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_UGE_6:%.*]] = icmp uge i32 [[RET]], -1
|
|
|
|
; CGSCC_OLD_PM-NEXT: tail call void @use3(i1 [[CMP_UGE_1]], i1 [[CMP_UGE_2]], i1 [[CMP_UGE_3]])
|
|
|
|
; CGSCC_OLD_PM-NEXT: tail call void @use3(i1 [[CMP_UGE_4]], i1 true, i1 [[CMP_UGE_6]])
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_SGT_1:%.*]] = icmp sgt i32 [[RET]], 10
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_SGT_2:%.*]] = icmp sgt i32 [[RET]], 9
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_SGT_3:%.*]] = icmp sgt i32 [[RET]], 8
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_SGT_4:%.*]] = icmp sgt i32 [[RET]], 1
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_SGT_5:%.*]] = icmp sgt i32 [[RET]], 0
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_SGT_6:%.*]] = icmp sgt i32 [[RET]], -1
|
|
|
|
; CGSCC_OLD_PM-NEXT: tail call void @use3(i1 [[CMP_SGT_1]], i1 [[CMP_SGT_2]], i1 [[CMP_SGT_3]])
|
|
|
|
; CGSCC_OLD_PM-NEXT: tail call void @use3(i1 [[CMP_SGT_4]], i1 [[CMP_SGT_5]], i1 [[CMP_SGT_6]])
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_GTE_1:%.*]] = icmp sge i32 [[RET]], 10
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_GTE_2:%.*]] = icmp sge i32 [[RET]], 9
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_GTE_3:%.*]] = icmp sge i32 [[RET]], 8
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_GTE_4:%.*]] = icmp sge i32 [[RET]], 1
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_GTE_5:%.*]] = icmp sge i32 [[RET]], 0
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_GTE_6:%.*]] = icmp sge i32 [[RET]], -1
|
|
|
|
; CGSCC_OLD_PM-NEXT: tail call void @use3(i1 [[CMP_GTE_1]], i1 [[CMP_GTE_2]], i1 [[CMP_GTE_3]])
|
|
|
|
; CGSCC_OLD_PM-NEXT: tail call void @use3(i1 [[CMP_GTE_4]], i1 [[CMP_GTE_5]], i1 [[CMP_GTE_6]])
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_SLT_1:%.*]] = icmp slt i32 [[RET]], 10
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_SLT_2:%.*]] = icmp slt i32 [[RET]], 9
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_SLT_3:%.*]] = icmp slt i32 [[RET]], 8
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_SLT_4:%.*]] = icmp slt i32 [[RET]], 1
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_SLT_5:%.*]] = icmp slt i32 [[RET]], 0
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_SLT_6:%.*]] = icmp slt i32 [[RET]], -1
|
|
|
|
; CGSCC_OLD_PM-NEXT: tail call void @use3(i1 [[CMP_SLT_1]], i1 [[CMP_SLT_2]], i1 [[CMP_SLT_3]])
|
|
|
|
; CGSCC_OLD_PM-NEXT: tail call void @use3(i1 [[CMP_SLT_4]], i1 [[CMP_SLT_5]], i1 [[CMP_SLT_6]])
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_LTE_1:%.*]] = icmp sle i32 [[RET]], 10
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_LTE_2:%.*]] = icmp sle i32 [[RET]], 9
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_LTE_3:%.*]] = icmp sle i32 [[RET]], 8
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_LTE_4:%.*]] = icmp sle i32 [[RET]], 1
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_LTE_5:%.*]] = icmp sle i32 [[RET]], 0
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP_LTE_6:%.*]] = icmp sle i32 [[RET]], -1
|
|
|
|
; CGSCC_OLD_PM-NEXT: tail call void @use3(i1 [[CMP_LTE_1]], i1 [[CMP_LTE_2]], i1 [[CMP_LTE_3]])
|
|
|
|
; CGSCC_OLD_PM-NEXT: tail call void @use3(i1 [[CMP_LTE_4]], i1 [[CMP_LTE_5]], i1 [[CMP_LTE_6]])
|
|
|
|
; CGSCC_OLD_PM-NEXT: ret void
|
|
|
|
;
|
|
|
|
; CGSCC_NEW_PM-LABEL: define {{[^@]+}}@test0-icmp-check
|
|
|
|
; CGSCC_NEW_PM-SAME: (i32* nocapture nofree nonnull readonly dereferenceable(4) [[P:%.*]])
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[RET:%.*]] = tail call i32 @test0(i32* nocapture nofree nonnull readonly dereferenceable(4) [[P]])
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_EQ_1:%.*]] = icmp eq i32 [[RET]], 10
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_EQ_2:%.*]] = icmp eq i32 [[RET]], 9
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_EQ_3:%.*]] = icmp eq i32 [[RET]], 8
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_EQ_4:%.*]] = icmp eq i32 [[RET]], 1
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_EQ_5:%.*]] = icmp eq i32 [[RET]], 0
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_EQ_6:%.*]] = icmp eq i32 [[RET]], -1
|
|
|
|
; CGSCC_NEW_PM-NEXT: tail call void @use3(i1 [[CMP_EQ_1]], i1 [[CMP_EQ_2]], i1 [[CMP_EQ_3]])
|
|
|
|
; CGSCC_NEW_PM-NEXT: tail call void @use3(i1 [[CMP_EQ_4]], i1 [[CMP_EQ_5]], i1 [[CMP_EQ_6]])
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_NE_1:%.*]] = icmp ne i32 [[RET]], 10
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_NE_2:%.*]] = icmp ne i32 [[RET]], 9
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_NE_3:%.*]] = icmp ne i32 [[RET]], 8
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_NE_4:%.*]] = icmp ne i32 [[RET]], 1
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_NE_5:%.*]] = icmp ne i32 [[RET]], 0
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_NE_6:%.*]] = icmp ne i32 [[RET]], -1
|
|
|
|
; CGSCC_NEW_PM-NEXT: tail call void @use3(i1 [[CMP_NE_1]], i1 [[CMP_NE_2]], i1 [[CMP_NE_3]])
|
|
|
|
; CGSCC_NEW_PM-NEXT: tail call void @use3(i1 [[CMP_NE_4]], i1 [[CMP_NE_5]], i1 [[CMP_NE_6]])
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_UGT_1:%.*]] = icmp ugt i32 [[RET]], 10
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_UGT_2:%.*]] = icmp ugt i32 [[RET]], 9
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_UGT_3:%.*]] = icmp ugt i32 [[RET]], 8
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_UGT_4:%.*]] = icmp ugt i32 [[RET]], 1
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_UGT_5:%.*]] = icmp ugt i32 [[RET]], 0
|
|
|
|
; CGSCC_NEW_PM-NEXT: tail call void @use3(i1 [[CMP_UGT_1]], i1 [[CMP_UGT_2]], i1 [[CMP_UGT_3]])
|
|
|
|
; CGSCC_NEW_PM-NEXT: tail call void @use3(i1 [[CMP_UGT_4]], i1 [[CMP_UGT_5]], i1 false)
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_UGE_1:%.*]] = icmp uge i32 [[RET]], 10
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_UGE_2:%.*]] = icmp uge i32 [[RET]], 9
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_UGE_3:%.*]] = icmp uge i32 [[RET]], 8
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_UGE_4:%.*]] = icmp uge i32 [[RET]], 1
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_UGE_6:%.*]] = icmp uge i32 [[RET]], -1
|
|
|
|
; CGSCC_NEW_PM-NEXT: tail call void @use3(i1 [[CMP_UGE_1]], i1 [[CMP_UGE_2]], i1 [[CMP_UGE_3]])
|
|
|
|
; CGSCC_NEW_PM-NEXT: tail call void @use3(i1 [[CMP_UGE_4]], i1 true, i1 [[CMP_UGE_6]])
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_SGT_1:%.*]] = icmp sgt i32 [[RET]], 10
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_SGT_2:%.*]] = icmp sgt i32 [[RET]], 9
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_SGT_3:%.*]] = icmp sgt i32 [[RET]], 8
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_SGT_4:%.*]] = icmp sgt i32 [[RET]], 1
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_SGT_5:%.*]] = icmp sgt i32 [[RET]], 0
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_SGT_6:%.*]] = icmp sgt i32 [[RET]], -1
|
|
|
|
; CGSCC_NEW_PM-NEXT: tail call void @use3(i1 [[CMP_SGT_1]], i1 [[CMP_SGT_2]], i1 [[CMP_SGT_3]])
|
|
|
|
; CGSCC_NEW_PM-NEXT: tail call void @use3(i1 [[CMP_SGT_4]], i1 [[CMP_SGT_5]], i1 [[CMP_SGT_6]])
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_GTE_1:%.*]] = icmp sge i32 [[RET]], 10
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_GTE_2:%.*]] = icmp sge i32 [[RET]], 9
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_GTE_3:%.*]] = icmp sge i32 [[RET]], 8
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_GTE_4:%.*]] = icmp sge i32 [[RET]], 1
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_GTE_5:%.*]] = icmp sge i32 [[RET]], 0
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_GTE_6:%.*]] = icmp sge i32 [[RET]], -1
|
|
|
|
; CGSCC_NEW_PM-NEXT: tail call void @use3(i1 [[CMP_GTE_1]], i1 [[CMP_GTE_2]], i1 [[CMP_GTE_3]])
|
|
|
|
; CGSCC_NEW_PM-NEXT: tail call void @use3(i1 [[CMP_GTE_4]], i1 [[CMP_GTE_5]], i1 [[CMP_GTE_6]])
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_SLT_1:%.*]] = icmp slt i32 [[RET]], 10
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_SLT_2:%.*]] = icmp slt i32 [[RET]], 9
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_SLT_3:%.*]] = icmp slt i32 [[RET]], 8
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_SLT_4:%.*]] = icmp slt i32 [[RET]], 1
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_SLT_5:%.*]] = icmp slt i32 [[RET]], 0
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_SLT_6:%.*]] = icmp slt i32 [[RET]], -1
|
|
|
|
; CGSCC_NEW_PM-NEXT: tail call void @use3(i1 [[CMP_SLT_1]], i1 [[CMP_SLT_2]], i1 [[CMP_SLT_3]])
|
|
|
|
; CGSCC_NEW_PM-NEXT: tail call void @use3(i1 [[CMP_SLT_4]], i1 [[CMP_SLT_5]], i1 [[CMP_SLT_6]])
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_LTE_1:%.*]] = icmp sle i32 [[RET]], 10
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_LTE_2:%.*]] = icmp sle i32 [[RET]], 9
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_LTE_3:%.*]] = icmp sle i32 [[RET]], 8
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_LTE_4:%.*]] = icmp sle i32 [[RET]], 1
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_LTE_5:%.*]] = icmp sle i32 [[RET]], 0
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP_LTE_6:%.*]] = icmp sle i32 [[RET]], -1
|
|
|
|
; CGSCC_NEW_PM-NEXT: tail call void @use3(i1 [[CMP_LTE_1]], i1 [[CMP_LTE_2]], i1 [[CMP_LTE_3]])
|
|
|
|
; CGSCC_NEW_PM-NEXT: tail call void @use3(i1 [[CMP_LTE_4]], i1 [[CMP_LTE_5]], i1 [[CMP_LTE_6]])
|
|
|
|
; CGSCC_NEW_PM-NEXT: ret void
|
|
|
|
;
|
2020-02-10 09:08:19 +08:00
|
|
|
; MODULE-LABEL: define {{[^@]+}}@test0-icmp-check
|
|
|
|
; MODULE-SAME: (i32* nocapture nofree readonly [[P:%.*]])
|
|
|
|
; MODULE-NEXT: [[RET:%.*]] = tail call i32 @test0(i32* nocapture nofree readonly [[P]]) #0, !range !0
|
|
|
|
; MODULE-NEXT: [[CMP_EQ_2:%.*]] = icmp eq i32 [[RET]], 9
|
|
|
|
; MODULE-NEXT: [[CMP_EQ_3:%.*]] = icmp eq i32 [[RET]], 8
|
|
|
|
; MODULE-NEXT: [[CMP_EQ_4:%.*]] = icmp eq i32 [[RET]], 1
|
|
|
|
; MODULE-NEXT: [[CMP_EQ_5:%.*]] = icmp eq i32 [[RET]], 0
|
|
|
|
; MODULE-NEXT: tail call void @use3(i1 false, i1 [[CMP_EQ_2]], i1 [[CMP_EQ_3]])
|
|
|
|
; MODULE-NEXT: tail call void @use3(i1 [[CMP_EQ_4]], i1 [[CMP_EQ_5]], i1 false)
|
|
|
|
; MODULE-NEXT: [[CMP_NE_2:%.*]] = icmp ne i32 [[RET]], 9
|
|
|
|
; MODULE-NEXT: [[CMP_NE_3:%.*]] = icmp ne i32 [[RET]], 8
|
|
|
|
; MODULE-NEXT: [[CMP_NE_4:%.*]] = icmp ne i32 [[RET]], 1
|
|
|
|
; MODULE-NEXT: [[CMP_NE_5:%.*]] = icmp ne i32 [[RET]], 0
|
|
|
|
; MODULE-NEXT: tail call void @use3(i1 true, i1 [[CMP_NE_2]], i1 [[CMP_NE_3]])
|
|
|
|
; MODULE-NEXT: tail call void @use3(i1 [[CMP_NE_4]], i1 [[CMP_NE_5]], i1 true)
|
|
|
|
; MODULE-NEXT: [[CMP_UGT_3:%.*]] = icmp ugt i32 [[RET]], 8
|
|
|
|
; MODULE-NEXT: [[CMP_UGT_4:%.*]] = icmp ugt i32 [[RET]], 1
|
|
|
|
; MODULE-NEXT: [[CMP_UGT_5:%.*]] = icmp ugt i32 [[RET]], 0
|
|
|
|
; MODULE-NEXT: tail call void @use3(i1 false, i1 false, i1 [[CMP_UGT_3]])
|
|
|
|
; MODULE-NEXT: tail call void @use3(i1 [[CMP_UGT_4]], i1 [[CMP_UGT_5]], i1 false)
|
|
|
|
; MODULE-NEXT: [[CMP_UGE_2:%.*]] = icmp uge i32 [[RET]], 9
|
|
|
|
; MODULE-NEXT: [[CMP_UGE_3:%.*]] = icmp uge i32 [[RET]], 8
|
|
|
|
; MODULE-NEXT: [[CMP_UGE_4:%.*]] = icmp uge i32 [[RET]], 1
|
|
|
|
; MODULE-NEXT: tail call void @use3(i1 false, i1 [[CMP_UGE_2]], i1 [[CMP_UGE_3]])
|
|
|
|
; MODULE-NEXT: tail call void @use3(i1 [[CMP_UGE_4]], i1 true, i1 false)
|
|
|
|
; MODULE-NEXT: [[CMP_SGT_3:%.*]] = icmp sgt i32 [[RET]], 8
|
|
|
|
; MODULE-NEXT: [[CMP_SGT_4:%.*]] = icmp sgt i32 [[RET]], 1
|
|
|
|
; MODULE-NEXT: [[CMP_SGT_5:%.*]] = icmp sgt i32 [[RET]], 0
|
|
|
|
; MODULE-NEXT: tail call void @use3(i1 false, i1 false, i1 [[CMP_SGT_3]])
|
|
|
|
; MODULE-NEXT: tail call void @use3(i1 [[CMP_SGT_4]], i1 [[CMP_SGT_5]], i1 true)
|
|
|
|
; MODULE-NEXT: [[CMP_GTE_2:%.*]] = icmp sge i32 [[RET]], 9
|
|
|
|
; MODULE-NEXT: [[CMP_GTE_3:%.*]] = icmp sge i32 [[RET]], 8
|
|
|
|
; MODULE-NEXT: [[CMP_GTE_4:%.*]] = icmp sge i32 [[RET]], 1
|
|
|
|
; MODULE-NEXT: tail call void @use3(i1 false, i1 [[CMP_GTE_2]], i1 [[CMP_GTE_3]])
|
|
|
|
; MODULE-NEXT: tail call void @use3(i1 [[CMP_GTE_4]], i1 true, i1 true)
|
|
|
|
; MODULE-NEXT: [[CMP_SLT_2:%.*]] = icmp slt i32 [[RET]], 9
|
|
|
|
; MODULE-NEXT: [[CMP_SLT_3:%.*]] = icmp slt i32 [[RET]], 8
|
|
|
|
; MODULE-NEXT: [[CMP_SLT_4:%.*]] = icmp slt i32 [[RET]], 1
|
|
|
|
; MODULE-NEXT: tail call void @use3(i1 true, i1 [[CMP_SLT_2]], i1 [[CMP_SLT_3]])
|
|
|
|
; MODULE-NEXT: tail call void @use3(i1 [[CMP_SLT_4]], i1 false, i1 false)
|
|
|
|
; MODULE-NEXT: [[CMP_LTE_3:%.*]] = icmp sle i32 [[RET]], 8
|
|
|
|
; MODULE-NEXT: [[CMP_LTE_4:%.*]] = icmp sle i32 [[RET]], 1
|
|
|
|
; MODULE-NEXT: [[CMP_LTE_5:%.*]] = icmp sle i32 [[RET]], 0
|
|
|
|
; MODULE-NEXT: tail call void @use3(i1 true, i1 true, i1 [[CMP_LTE_3]])
|
|
|
|
; MODULE-NEXT: tail call void @use3(i1 [[CMP_LTE_4]], i1 [[CMP_LTE_5]], i1 false)
|
|
|
|
; MODULE-NEXT: ret void
|
|
|
|
; CGSCC-LABEL: define {{[^@]+}}@test0-icmp-check
|
|
|
|
; CGSCC-SAME: (i32* nocapture nofree nonnull readonly dereferenceable(4) [[P:%.*]])
|
|
|
|
; CGSCC-NEXT: [[RET:%.*]] = tail call i32 @test0(i32* nocapture nofree nonnull readonly dereferenceable(4) [[P]])
|
|
|
|
; CGSCC-NEXT: [[CMP_EQ_1:%.*]] = icmp eq i32 [[RET]], 10
|
|
|
|
; CGSCC-NEXT: [[CMP_EQ_2:%.*]] = icmp eq i32 [[RET]], 9
|
|
|
|
; CGSCC-NEXT: [[CMP_EQ_3:%.*]] = icmp eq i32 [[RET]], 8
|
|
|
|
; CGSCC-NEXT: [[CMP_EQ_4:%.*]] = icmp eq i32 [[RET]], 1
|
|
|
|
; CGSCC-NEXT: [[CMP_EQ_5:%.*]] = icmp eq i32 [[RET]], 0
|
|
|
|
; CGSCC-NEXT: [[CMP_EQ_6:%.*]] = icmp eq i32 [[RET]], -1
|
|
|
|
; CGSCC-NEXT: tail call void @use3(i1 [[CMP_EQ_1]], i1 [[CMP_EQ_2]], i1 [[CMP_EQ_3]])
|
|
|
|
; CGSCC-NEXT: tail call void @use3(i1 [[CMP_EQ_4]], i1 [[CMP_EQ_5]], i1 [[CMP_EQ_6]])
|
|
|
|
; CGSCC-NEXT: [[CMP_NE_1:%.*]] = icmp ne i32 [[RET]], 10
|
|
|
|
; CGSCC-NEXT: [[CMP_NE_2:%.*]] = icmp ne i32 [[RET]], 9
|
|
|
|
; CGSCC-NEXT: [[CMP_NE_3:%.*]] = icmp ne i32 [[RET]], 8
|
|
|
|
; CGSCC-NEXT: [[CMP_NE_4:%.*]] = icmp ne i32 [[RET]], 1
|
|
|
|
; CGSCC-NEXT: [[CMP_NE_5:%.*]] = icmp ne i32 [[RET]], 0
|
|
|
|
; CGSCC-NEXT: [[CMP_NE_6:%.*]] = icmp ne i32 [[RET]], -1
|
|
|
|
; CGSCC-NEXT: tail call void @use3(i1 [[CMP_NE_1]], i1 [[CMP_NE_2]], i1 [[CMP_NE_3]])
|
|
|
|
; CGSCC-NEXT: tail call void @use3(i1 [[CMP_NE_4]], i1 [[CMP_NE_5]], i1 [[CMP_NE_6]])
|
|
|
|
; CGSCC-NEXT: [[CMP_UGT_1:%.*]] = icmp ugt i32 [[RET]], 10
|
|
|
|
; CGSCC-NEXT: [[CMP_UGT_2:%.*]] = icmp ugt i32 [[RET]], 9
|
|
|
|
; CGSCC-NEXT: [[CMP_UGT_3:%.*]] = icmp ugt i32 [[RET]], 8
|
|
|
|
; CGSCC-NEXT: [[CMP_UGT_4:%.*]] = icmp ugt i32 [[RET]], 1
|
|
|
|
; CGSCC-NEXT: [[CMP_UGT_5:%.*]] = icmp ugt i32 [[RET]], 0
|
|
|
|
; CGSCC-NEXT: tail call void @use3(i1 [[CMP_UGT_1]], i1 [[CMP_UGT_2]], i1 [[CMP_UGT_3]])
|
|
|
|
; CGSCC-NEXT: tail call void @use3(i1 [[CMP_UGT_4]], i1 [[CMP_UGT_5]], i1 false)
|
|
|
|
; CGSCC-NEXT: [[CMP_UGE_1:%.*]] = icmp uge i32 [[RET]], 10
|
|
|
|
; CGSCC-NEXT: [[CMP_UGE_2:%.*]] = icmp uge i32 [[RET]], 9
|
|
|
|
; CGSCC-NEXT: [[CMP_UGE_3:%.*]] = icmp uge i32 [[RET]], 8
|
|
|
|
; CGSCC-NEXT: [[CMP_UGE_4:%.*]] = icmp uge i32 [[RET]], 1
|
|
|
|
; CGSCC-NEXT: [[CMP_UGE_6:%.*]] = icmp uge i32 [[RET]], -1
|
|
|
|
; CGSCC-NEXT: tail call void @use3(i1 [[CMP_UGE_1]], i1 [[CMP_UGE_2]], i1 [[CMP_UGE_3]])
|
|
|
|
; CGSCC-NEXT: tail call void @use3(i1 [[CMP_UGE_4]], i1 true, i1 [[CMP_UGE_6]])
|
|
|
|
; CGSCC-NEXT: [[CMP_SGT_1:%.*]] = icmp sgt i32 [[RET]], 10
|
|
|
|
; CGSCC-NEXT: [[CMP_SGT_2:%.*]] = icmp sgt i32 [[RET]], 9
|
|
|
|
; CGSCC-NEXT: [[CMP_SGT_3:%.*]] = icmp sgt i32 [[RET]], 8
|
|
|
|
; CGSCC-NEXT: [[CMP_SGT_4:%.*]] = icmp sgt i32 [[RET]], 1
|
|
|
|
; CGSCC-NEXT: [[CMP_SGT_5:%.*]] = icmp sgt i32 [[RET]], 0
|
|
|
|
; CGSCC-NEXT: [[CMP_SGT_6:%.*]] = icmp sgt i32 [[RET]], -1
|
|
|
|
; CGSCC-NEXT: tail call void @use3(i1 [[CMP_SGT_1]], i1 [[CMP_SGT_2]], i1 [[CMP_SGT_3]])
|
|
|
|
; CGSCC-NEXT: tail call void @use3(i1 [[CMP_SGT_4]], i1 [[CMP_SGT_5]], i1 [[CMP_SGT_6]])
|
|
|
|
; CGSCC-NEXT: [[CMP_GTE_1:%.*]] = icmp sge i32 [[RET]], 10
|
|
|
|
; CGSCC-NEXT: [[CMP_GTE_2:%.*]] = icmp sge i32 [[RET]], 9
|
|
|
|
; CGSCC-NEXT: [[CMP_GTE_3:%.*]] = icmp sge i32 [[RET]], 8
|
|
|
|
; CGSCC-NEXT: [[CMP_GTE_4:%.*]] = icmp sge i32 [[RET]], 1
|
|
|
|
; CGSCC-NEXT: [[CMP_GTE_5:%.*]] = icmp sge i32 [[RET]], 0
|
|
|
|
; CGSCC-NEXT: [[CMP_GTE_6:%.*]] = icmp sge i32 [[RET]], -1
|
|
|
|
; CGSCC-NEXT: tail call void @use3(i1 [[CMP_GTE_1]], i1 [[CMP_GTE_2]], i1 [[CMP_GTE_3]])
|
|
|
|
; CGSCC-NEXT: tail call void @use3(i1 [[CMP_GTE_4]], i1 [[CMP_GTE_5]], i1 [[CMP_GTE_6]])
|
|
|
|
; CGSCC-NEXT: [[CMP_SLT_1:%.*]] = icmp slt i32 [[RET]], 10
|
|
|
|
; CGSCC-NEXT: [[CMP_SLT_2:%.*]] = icmp slt i32 [[RET]], 9
|
|
|
|
; CGSCC-NEXT: [[CMP_SLT_3:%.*]] = icmp slt i32 [[RET]], 8
|
|
|
|
; CGSCC-NEXT: [[CMP_SLT_4:%.*]] = icmp slt i32 [[RET]], 1
|
|
|
|
; CGSCC-NEXT: [[CMP_SLT_5:%.*]] = icmp slt i32 [[RET]], 0
|
|
|
|
; CGSCC-NEXT: [[CMP_SLT_6:%.*]] = icmp slt i32 [[RET]], -1
|
|
|
|
; CGSCC-NEXT: tail call void @use3(i1 [[CMP_SLT_1]], i1 [[CMP_SLT_2]], i1 [[CMP_SLT_3]])
|
|
|
|
; CGSCC-NEXT: tail call void @use3(i1 [[CMP_SLT_4]], i1 [[CMP_SLT_5]], i1 [[CMP_SLT_6]])
|
|
|
|
; CGSCC-NEXT: [[CMP_LTE_1:%.*]] = icmp sle i32 [[RET]], 10
|
|
|
|
; CGSCC-NEXT: [[CMP_LTE_2:%.*]] = icmp sle i32 [[RET]], 9
|
|
|
|
; CGSCC-NEXT: [[CMP_LTE_3:%.*]] = icmp sle i32 [[RET]], 8
|
|
|
|
; CGSCC-NEXT: [[CMP_LTE_4:%.*]] = icmp sle i32 [[RET]], 1
|
|
|
|
; CGSCC-NEXT: [[CMP_LTE_5:%.*]] = icmp sle i32 [[RET]], 0
|
|
|
|
; CGSCC-NEXT: [[CMP_LTE_6:%.*]] = icmp sle i32 [[RET]], -1
|
|
|
|
; CGSCC-NEXT: tail call void @use3(i1 [[CMP_LTE_1]], i1 [[CMP_LTE_2]], i1 [[CMP_LTE_3]])
|
|
|
|
; CGSCC-NEXT: tail call void @use3(i1 [[CMP_LTE_4]], i1 [[CMP_LTE_5]], i1 [[CMP_LTE_6]])
|
|
|
|
; CGSCC-NEXT: ret void
|
[Attributor] AAValueConstantRange: Value range analysis using constant range
Summary:
This patch introduces `AAValueConstantRange`, which answers a possible range for integer value in a specific program point.
One of the motivations is propagating existing `range` metadata. (I think we need to change the situation that `range` metadata cannot be put to Argument).
The state is a tuple of `ConstantRange` and it is initialized to (known, assumed) = ([-∞, +∞], empty).
Currently, AAValueConstantRange is created in `getAssumedConstant` method when `AAValueSimplify` returns `nullptr`(worst state).
Supported
- BinaryOperator(add, sub, ...)
- CmpInst(icmp eq, ...)
- !range metadata
`AAValueConstantRange` is not intended to extend to polyhedral range value analysis.
Reviewers: jdoerfert, sstefan1
Reviewed By: jdoerfert
Subscribers: phosek, davezarzycki, baziotis, hiraditya, javed.absar, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D71620
2020-01-15 14:25:52 +08:00
|
|
|
; ret = [0, 10)
|
|
|
|
%ret = tail call i32 @test0(i32 *%p)
|
|
|
|
|
|
|
|
; ret = [0, 10), eq
|
|
|
|
%cmp-eq-1 = icmp eq i32 %ret, 10
|
|
|
|
%cmp-eq-2 = icmp eq i32 %ret, 9
|
|
|
|
%cmp-eq-3 = icmp eq i32 %ret, 8
|
|
|
|
%cmp-eq-4 = icmp eq i32 %ret, 1
|
|
|
|
%cmp-eq-5 = icmp eq i32 %ret, 0
|
|
|
|
%cmp-eq-6 = icmp eq i32 %ret, -1
|
|
|
|
tail call void @use3(i1 %cmp-eq-1, i1 %cmp-eq-2, i1 %cmp-eq-3)
|
|
|
|
tail call void @use3(i1 %cmp-eq-4, i1 %cmp-eq-5, i1 %cmp-eq-6)
|
|
|
|
|
|
|
|
; ret = [0, 10), ne
|
|
|
|
%cmp-ne-1 = icmp ne i32 %ret, 10
|
|
|
|
%cmp-ne-2 = icmp ne i32 %ret, 9
|
|
|
|
%cmp-ne-3 = icmp ne i32 %ret, 8
|
|
|
|
%cmp-ne-4 = icmp ne i32 %ret, 1
|
|
|
|
%cmp-ne-5 = icmp ne i32 %ret, 0
|
|
|
|
%cmp-ne-6 = icmp ne i32 %ret, -1
|
|
|
|
tail call void @use3(i1 %cmp-ne-1, i1 %cmp-ne-2, i1 %cmp-ne-3)
|
|
|
|
tail call void @use3(i1 %cmp-ne-4, i1 %cmp-ne-5, i1 %cmp-ne-6)
|
|
|
|
|
|
|
|
; ret = [0, 10), ugt
|
|
|
|
%cmp-ugt-1 = icmp ugt i32 %ret, 10
|
|
|
|
%cmp-ugt-2 = icmp ugt i32 %ret, 9
|
|
|
|
%cmp-ugt-3 = icmp ugt i32 %ret, 8
|
|
|
|
%cmp-ugt-4 = icmp ugt i32 %ret, 1
|
|
|
|
%cmp-ugt-5 = icmp ugt i32 %ret, 0
|
|
|
|
%cmp-ugt-6 = icmp ugt i32 %ret, -1
|
|
|
|
tail call void @use3(i1 %cmp-ugt-1, i1 %cmp-ugt-2, i1 %cmp-ugt-3)
|
|
|
|
tail call void @use3(i1 %cmp-ugt-4, i1 %cmp-ugt-5, i1 %cmp-ugt-6)
|
|
|
|
|
|
|
|
; ret = [0, 10), uge
|
|
|
|
%cmp-uge-1 = icmp uge i32 %ret, 10
|
|
|
|
%cmp-uge-2 = icmp uge i32 %ret, 9
|
|
|
|
%cmp-uge-3 = icmp uge i32 %ret, 8
|
|
|
|
%cmp-uge-4 = icmp uge i32 %ret, 1
|
|
|
|
%cmp-uge-5 = icmp uge i32 %ret, 0
|
|
|
|
%cmp-uge-6 = icmp uge i32 %ret, -1
|
|
|
|
tail call void @use3(i1 %cmp-uge-1, i1 %cmp-uge-2, i1 %cmp-uge-3)
|
|
|
|
tail call void @use3(i1 %cmp-uge-4, i1 %cmp-uge-5, i1 %cmp-uge-6)
|
|
|
|
|
|
|
|
; ret = [0, 10), sgt
|
|
|
|
%cmp-sgt-1 = icmp sgt i32 %ret, 10
|
|
|
|
%cmp-sgt-2 = icmp sgt i32 %ret, 9
|
|
|
|
%cmp-sgt-3 = icmp sgt i32 %ret, 8
|
|
|
|
%cmp-sgt-4 = icmp sgt i32 %ret, 1
|
|
|
|
%cmp-sgt-5 = icmp sgt i32 %ret, 0
|
|
|
|
%cmp-sgt-6 = icmp sgt i32 %ret, -1
|
|
|
|
tail call void @use3(i1 %cmp-sgt-1, i1 %cmp-sgt-2, i1 %cmp-sgt-3)
|
|
|
|
tail call void @use3(i1 %cmp-sgt-4, i1 %cmp-sgt-5, i1 %cmp-sgt-6)
|
|
|
|
|
|
|
|
; ret = [0, 10), sge
|
|
|
|
%cmp-gte-1 = icmp sge i32 %ret, 10
|
|
|
|
%cmp-gte-2 = icmp sge i32 %ret, 9
|
|
|
|
%cmp-gte-3 = icmp sge i32 %ret, 8
|
|
|
|
%cmp-gte-4 = icmp sge i32 %ret, 1
|
|
|
|
%cmp-gte-5 = icmp sge i32 %ret, 0
|
|
|
|
%cmp-gte-6 = icmp sge i32 %ret, -1
|
|
|
|
tail call void @use3(i1 %cmp-gte-1, i1 %cmp-gte-2, i1 %cmp-gte-3)
|
|
|
|
tail call void @use3(i1 %cmp-gte-4, i1 %cmp-gte-5, i1 %cmp-gte-6)
|
|
|
|
|
|
|
|
; ret = [0, 10), slt
|
|
|
|
%cmp-slt-1 = icmp slt i32 %ret, 10
|
|
|
|
%cmp-slt-2 = icmp slt i32 %ret, 9
|
|
|
|
%cmp-slt-3 = icmp slt i32 %ret, 8
|
|
|
|
%cmp-slt-4 = icmp slt i32 %ret, 1
|
|
|
|
%cmp-slt-5 = icmp slt i32 %ret, 0
|
|
|
|
%cmp-slt-6 = icmp slt i32 %ret, -1
|
|
|
|
tail call void @use3(i1 %cmp-slt-1, i1 %cmp-slt-2, i1 %cmp-slt-3)
|
|
|
|
tail call void @use3(i1 %cmp-slt-4, i1 %cmp-slt-5, i1 %cmp-slt-6)
|
|
|
|
|
|
|
|
; ret = [0, 10), sle
|
|
|
|
%cmp-lte-1 = icmp sle i32 %ret, 10
|
|
|
|
%cmp-lte-2 = icmp sle i32 %ret, 9
|
|
|
|
%cmp-lte-3 = icmp sle i32 %ret, 8
|
|
|
|
%cmp-lte-4 = icmp sle i32 %ret, 1
|
|
|
|
%cmp-lte-5 = icmp sle i32 %ret, 0
|
|
|
|
%cmp-lte-6 = icmp sle i32 %ret, -1
|
|
|
|
tail call void @use3(i1 %cmp-lte-1, i1 %cmp-lte-2, i1 %cmp-lte-3)
|
|
|
|
tail call void @use3(i1 %cmp-lte-4, i1 %cmp-lte-5, i1 %cmp-lte-6)
|
|
|
|
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
define i32 @test1(i32* %p) {
|
|
|
|
; CHECK-LABEL: define {{[^@]+}}@test1
|
|
|
|
; CHECK-SAME: (i32* nocapture nofree nonnull readonly dereferenceable(4) [[P:%.*]])
|
|
|
|
; CHECK-NEXT: [[LOAD_10_100:%.*]] = load i32, i32* [[P]], !range !1
|
|
|
|
; CHECK-NEXT: [[ADD_10_THEN_20_110:%.*]] = add i32 [[LOAD_10_100]], 10
|
|
|
|
; CHECK-NEXT: [[MUL_10_THEN_200_1091:%.*]] = mul i32 [[ADD_10_THEN_20_110]], 10
|
|
|
|
; CHECK-NEXT: ret i32 [[MUL_10_THEN_200_1091]]
|
|
|
|
;
|
|
|
|
%load-10-100 = load i32, i32* %p, !range !1
|
|
|
|
%add-10-then-20-110 = add i32 %load-10-100, 10
|
|
|
|
%mul-10-then-200-1091 = mul i32 %add-10-then-20-110, 10
|
|
|
|
ret i32 %mul-10-then-200-1091
|
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test1-check(i32* %p) {
|
2020-02-10 15:31:20 +08:00
|
|
|
; OLD_PM-LABEL: define {{[^@]+}}@test1-check
|
|
|
|
; OLD_PM-SAME: (i32* nocapture nofree readonly [[P:%.*]])
|
|
|
|
; OLD_PM-NEXT: [[RES:%.*]] = tail call i32 @test1(i32* nocapture nofree readonly [[P]]) #0, !range !2
|
|
|
|
; OLD_PM-NEXT: [[CMP:%.*]] = icmp eq i32 [[RES]], 500
|
|
|
|
; OLD_PM-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
; NEW_PM-LABEL: define {{[^@]+}}@test1-check
|
|
|
|
; NEW_PM-SAME: (i32* nocapture nofree readonly [[P:%.*]])
|
|
|
|
; NEW_PM-NEXT: [[RES:%.*]] = tail call i32 @test1(i32* nocapture nofree readonly [[P]]) #0, !range !2
|
|
|
|
; NEW_PM-NEXT: [[CMP:%.*]] = icmp eq i32 [[RES]], 500
|
|
|
|
; NEW_PM-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
; CGSCC_OLD_PM-LABEL: define {{[^@]+}}@test1-check
|
|
|
|
; CGSCC_OLD_PM-SAME: (i32* nocapture nofree nonnull readonly dereferenceable(4) [[P:%.*]])
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[RES:%.*]] = tail call i32 @test1(i32* nocapture nofree nonnull readonly dereferenceable(4) [[P]])
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP:%.*]] = icmp eq i32 [[RES]], 500
|
|
|
|
; CGSCC_OLD_PM-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
; CGSCC_NEW_PM-LABEL: define {{[^@]+}}@test1-check
|
|
|
|
; CGSCC_NEW_PM-SAME: (i32* nocapture nofree nonnull readonly dereferenceable(4) [[P:%.*]])
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[RES:%.*]] = tail call i32 @test1(i32* nocapture nofree nonnull readonly dereferenceable(4) [[P]])
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP:%.*]] = icmp eq i32 [[RES]], 500
|
|
|
|
; CGSCC_NEW_PM-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
2020-02-10 09:08:19 +08:00
|
|
|
; MODULE-LABEL: define {{[^@]+}}@test1-check
|
|
|
|
; MODULE-SAME: (i32* nocapture nofree readonly [[P:%.*]])
|
|
|
|
; MODULE-NEXT: [[RES:%.*]] = tail call i32 @test1(i32* nocapture nofree readonly [[P]]) #0, !range !2
|
|
|
|
; MODULE-NEXT: [[CMP:%.*]] = icmp eq i32 [[RES]], 500
|
|
|
|
; MODULE-NEXT: ret i1 [[CMP]]
|
|
|
|
; CGSCC-LABEL: define {{[^@]+}}@test1-check
|
|
|
|
; CGSCC-SAME: (i32* nocapture nofree nonnull readonly dereferenceable(4) [[P:%.*]])
|
|
|
|
; CGSCC-NEXT: [[RES:%.*]] = tail call i32 @test1(i32* nocapture nofree nonnull readonly dereferenceable(4) [[P]])
|
|
|
|
; CGSCC-NEXT: [[CMP:%.*]] = icmp eq i32 [[RES]], 500
|
|
|
|
; CGSCC-NEXT: ret i1 [[CMP]]
|
[Attributor] AAValueConstantRange: Value range analysis using constant range
Summary:
This patch introduces `AAValueConstantRange`, which answers a possible range for integer value in a specific program point.
One of the motivations is propagating existing `range` metadata. (I think we need to change the situation that `range` metadata cannot be put to Argument).
The state is a tuple of `ConstantRange` and it is initialized to (known, assumed) = ([-∞, +∞], empty).
Currently, AAValueConstantRange is created in `getAssumedConstant` method when `AAValueSimplify` returns `nullptr`(worst state).
Supported
- BinaryOperator(add, sub, ...)
- CmpInst(icmp eq, ...)
- !range metadata
`AAValueConstantRange` is not intended to extend to polyhedral range value analysis.
Reviewers: jdoerfert, sstefan1
Reviewed By: jdoerfert
Subscribers: phosek, davezarzycki, baziotis, hiraditya, javed.absar, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D71620
2020-01-15 14:25:52 +08:00
|
|
|
%res = tail call i32 @test1(i32* %p)
|
|
|
|
%cmp = icmp eq i32 %res, 500
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
; TEST2
|
|
|
|
; int test2(int *p) { return *p == 0 ? 4 : 3; }
|
|
|
|
; int test2_check(int *p) {
|
|
|
|
; int call = test2(p);
|
|
|
|
; if (call == 5) {
|
|
|
|
; // dead block
|
|
|
|
; return 2;
|
|
|
|
; } else {
|
|
|
|
; return 3;
|
|
|
|
; }
|
|
|
|
; }
|
|
|
|
|
|
|
|
define i32 @test2(i32* %p) {
|
|
|
|
; CHECK-LABEL: define {{[^@]+}}@test2
|
|
|
|
; CHECK-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[P:%.*]])
|
|
|
|
; CHECK-NEXT: entry:
|
|
|
|
; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[P]], align 4
|
|
|
|
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[TMP0]], 0
|
|
|
|
; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 4, i32 3
|
|
|
|
; CHECK-NEXT: ret i32 [[COND]]
|
|
|
|
;
|
|
|
|
entry:
|
|
|
|
%0 = load i32, i32* %p, align 4
|
|
|
|
%tobool = icmp eq i32 %0, 0
|
|
|
|
%cond = select i1 %tobool, i32 4, i32 3
|
|
|
|
ret i32 %cond
|
|
|
|
}
|
|
|
|
|
|
|
|
define i32 @test2_check(i32* %p) {
|
2020-02-10 15:31:20 +08:00
|
|
|
; OLD_PM-LABEL: define {{[^@]+}}@test2_check
|
2020-01-12 15:09:22 +08:00
|
|
|
; OLD_PM-SAME: (i32* nocapture nofree readnone align 4 [[P:%.*]])
|
2020-02-10 15:31:20 +08:00
|
|
|
; OLD_PM-NEXT: entry:
|
|
|
|
; OLD_PM-NEXT: br label [[IF_THEN:%.*]]
|
|
|
|
; OLD_PM: if.then:
|
|
|
|
; OLD_PM-NEXT: br label [[RETURN:%.*]]
|
|
|
|
; OLD_PM: if.end:
|
|
|
|
; OLD_PM-NEXT: unreachable
|
|
|
|
; OLD_PM: return:
|
|
|
|
; OLD_PM-NEXT: ret i32 2
|
|
|
|
;
|
|
|
|
; NEW_PM-LABEL: define {{[^@]+}}@test2_check
|
2020-01-12 15:09:22 +08:00
|
|
|
; NEW_PM-SAME: (i32* nocapture nofree readnone align 4 [[P:%.*]])
|
2020-02-10 15:31:20 +08:00
|
|
|
; NEW_PM-NEXT: entry:
|
|
|
|
; NEW_PM-NEXT: br label [[IF_THEN:%.*]]
|
|
|
|
; NEW_PM: if.then:
|
|
|
|
; NEW_PM-NEXT: br label [[RETURN:%.*]]
|
|
|
|
; NEW_PM: if.end:
|
|
|
|
; NEW_PM-NEXT: unreachable
|
|
|
|
; NEW_PM: return:
|
|
|
|
; NEW_PM-NEXT: ret i32 2
|
|
|
|
;
|
|
|
|
; CGSCC_OLD_PM-LABEL: define {{[^@]+}}@test2_check
|
|
|
|
; CGSCC_OLD_PM-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[P:%.*]])
|
|
|
|
; CGSCC_OLD_PM-NEXT: entry:
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CALL:%.*]] = tail call i32 @test2(i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[P]])
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CMP:%.*]] = icmp slt i32 [[CALL]], 5
|
|
|
|
; CGSCC_OLD_PM-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
|
|
|
|
; CGSCC_OLD_PM: if.then:
|
|
|
|
; CGSCC_OLD_PM-NEXT: br label [[RETURN:%.*]]
|
|
|
|
; CGSCC_OLD_PM: if.end:
|
|
|
|
; CGSCC_OLD_PM-NEXT: br label [[RETURN]]
|
|
|
|
; CGSCC_OLD_PM: return:
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[RETVAL_0:%.*]] = phi i32 [ 2, [[IF_THEN]] ], [ 3, [[IF_END]] ]
|
|
|
|
; CGSCC_OLD_PM-NEXT: ret i32 [[RETVAL_0]]
|
|
|
|
;
|
|
|
|
; CGSCC_NEW_PM-LABEL: define {{[^@]+}}@test2_check
|
|
|
|
; CGSCC_NEW_PM-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[P:%.*]])
|
|
|
|
; CGSCC_NEW_PM-NEXT: entry:
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CALL:%.*]] = tail call i32 @test2(i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[P]])
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CMP:%.*]] = icmp slt i32 [[CALL]], 5
|
|
|
|
; CGSCC_NEW_PM-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
|
|
|
|
; CGSCC_NEW_PM: if.then:
|
|
|
|
; CGSCC_NEW_PM-NEXT: br label [[RETURN:%.*]]
|
|
|
|
; CGSCC_NEW_PM: if.end:
|
|
|
|
; CGSCC_NEW_PM-NEXT: br label [[RETURN]]
|
|
|
|
; CGSCC_NEW_PM: return:
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[RETVAL_0:%.*]] = phi i32 [ 2, [[IF_THEN]] ], [ 3, [[IF_END]] ]
|
|
|
|
; CGSCC_NEW_PM-NEXT: ret i32 [[RETVAL_0]]
|
|
|
|
;
|
2020-02-10 09:08:19 +08:00
|
|
|
; MODULE-LABEL: define {{[^@]+}}@test2_check
|
|
|
|
; MODULE-SAME: (i32* nocapture nofree readonly align 4 [[P:%.*]])
|
|
|
|
; MODULE-NEXT: entry:
|
|
|
|
; MODULE-NEXT: br label [[IF_THEN:%.*]]
|
|
|
|
; MODULE: if.then:
|
|
|
|
; MODULE-NEXT: br label [[RETURN:%.*]]
|
|
|
|
; MODULE: if.end:
|
|
|
|
; MODULE-NEXT: unreachable
|
|
|
|
; MODULE: return:
|
|
|
|
; MODULE-NEXT: ret i32 2
|
|
|
|
; CGSCC-LABEL: define {{[^@]+}}@test2_check
|
|
|
|
; CGSCC-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[P:%.*]])
|
|
|
|
; CGSCC-NEXT: entry:
|
|
|
|
; CGSCC-NEXT: [[CALL:%.*]] = tail call i32 @test2(i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[P]])
|
|
|
|
; CGSCC-NEXT: [[CMP:%.*]] = icmp slt i32 [[CALL]], 5
|
|
|
|
; CGSCC-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
|
|
|
|
; CGSCC: if.then:
|
|
|
|
; CGSCC-NEXT: br label [[RETURN:%.*]]
|
|
|
|
; CGSCC: if.end:
|
|
|
|
; CGSCC-NEXT: br label [[RETURN]]
|
|
|
|
; CGSCC: return:
|
|
|
|
; CGSCC-NEXT: [[RETVAL_0:%.*]] = phi i32 [ 2, [[IF_THEN]] ], [ 3, [[IF_END]] ]
|
|
|
|
; CGSCC-NEXT: ret i32 [[RETVAL_0]]
|
[Attributor] AAValueConstantRange: Value range analysis using constant range
Summary:
This patch introduces `AAValueConstantRange`, which answers a possible range for integer value in a specific program point.
One of the motivations is propagating existing `range` metadata. (I think we need to change the situation that `range` metadata cannot be put to Argument).
The state is a tuple of `ConstantRange` and it is initialized to (known, assumed) = ([-∞, +∞], empty).
Currently, AAValueConstantRange is created in `getAssumedConstant` method when `AAValueSimplify` returns `nullptr`(worst state).
Supported
- BinaryOperator(add, sub, ...)
- CmpInst(icmp eq, ...)
- !range metadata
`AAValueConstantRange` is not intended to extend to polyhedral range value analysis.
Reviewers: jdoerfert, sstefan1
Reviewed By: jdoerfert
Subscribers: phosek, davezarzycki, baziotis, hiraditya, javed.absar, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D71620
2020-01-15 14:25:52 +08:00
|
|
|
entry:
|
|
|
|
%call = tail call i32 @test2(i32* %p)
|
|
|
|
%cmp = icmp slt i32 %call, 5
|
|
|
|
br i1 %cmp, label %if.then, label %if.end
|
|
|
|
|
|
|
|
if.then: ; preds = %entry
|
|
|
|
br label %return
|
|
|
|
|
|
|
|
if.end: ; preds = %entry
|
|
|
|
br label %return
|
|
|
|
|
|
|
|
return: ; preds = %if.end, %if.then
|
|
|
|
%retval.0 = phi i32 [ 2, %if.then ], [ 3, %if.end ]
|
|
|
|
ret i32 %retval.0
|
|
|
|
}
|
|
|
|
|
|
|
|
; TEST 3 SECV test
|
|
|
|
|
|
|
|
; void unkown();
|
|
|
|
; int r1(unsigned int u){
|
|
|
|
; int sum = 0;
|
|
|
|
; for(int i = 0; i<100;i++){
|
|
|
|
; sum += i;
|
|
|
|
; }
|
|
|
|
; // sum = 50 * 49 / 2
|
|
|
|
; if(sum > 10000){
|
|
|
|
; // dead block
|
|
|
|
; return 20;
|
|
|
|
; }else {
|
|
|
|
; return 10;
|
|
|
|
; }
|
|
|
|
; }
|
|
|
|
; void f1(int u){
|
|
|
|
; if(r1(u) > 15){
|
|
|
|
; // deadblock
|
|
|
|
; unkown();
|
|
|
|
; }else {
|
|
|
|
; return;
|
|
|
|
; }
|
|
|
|
; }
|
|
|
|
|
|
|
|
declare dso_local void @unkown()
|
|
|
|
|
|
|
|
define internal i32 @r1(i32) local_unnamed_addr {
|
2020-02-10 15:31:20 +08:00
|
|
|
; OLD_PM-LABEL: define {{[^@]+}}@r1() local_unnamed_addr
|
|
|
|
; OLD_PM-NEXT: br label [[TMP4:%.*]]
|
|
|
|
; OLD_PM: 1:
|
|
|
|
; OLD_PM-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[TMP7:%.*]], 10000
|
|
|
|
; OLD_PM-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[F:%.*]]
|
|
|
|
; OLD_PM: 3:
|
|
|
|
; OLD_PM-NEXT: ret i32 20
|
|
|
|
; OLD_PM: f:
|
|
|
|
; OLD_PM-NEXT: ret i32 10
|
|
|
|
; OLD_PM: 4:
|
|
|
|
; OLD_PM-NEXT: [[TMP5:%.*]] = phi i32 [ 0, [[TMP0:%.*]] ], [ [[TMP8:%.*]], [[TMP4]] ]
|
|
|
|
; OLD_PM-NEXT: [[TMP6:%.*]] = phi i32 [ 0, [[TMP0]] ], [ [[TMP7]], [[TMP4]] ]
|
|
|
|
; OLD_PM-NEXT: [[TMP7]] = add nuw nsw i32 [[TMP5]], [[TMP6]]
|
|
|
|
; OLD_PM-NEXT: [[TMP8]] = add nuw nsw i32 [[TMP5]], 1
|
|
|
|
; OLD_PM-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 100
|
|
|
|
; OLD_PM-NEXT: br i1 [[TMP9]], label [[TMP1:%.*]], label [[TMP4]]
|
|
|
|
;
|
2020-02-10 09:08:19 +08:00
|
|
|
; CGSCC_OLD_PM-LABEL: define {{[^@]+}}@r1
|
|
|
|
; CGSCC_OLD_PM-SAME: (i32 [[TMP0:%.*]]) local_unnamed_addr
|
|
|
|
; CGSCC_OLD_PM-NEXT: br label [[TMP5:%.*]]
|
|
|
|
; CGSCC_OLD_PM: 2:
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP8:%.*]], 10000
|
|
|
|
; CGSCC_OLD_PM-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[F:%.*]]
|
|
|
|
; CGSCC_OLD_PM: 4:
|
|
|
|
; CGSCC_OLD_PM-NEXT: ret i32 20
|
|
|
|
; CGSCC_OLD_PM: f:
|
|
|
|
; CGSCC_OLD_PM-NEXT: ret i32 10
|
|
|
|
; CGSCC_OLD_PM: 5:
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[TMP6:%.*]] = phi i32 [ 0, [[TMP1:%.*]] ], [ [[TMP9:%.*]], [[TMP5]] ]
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[TMP7:%.*]] = phi i32 [ 0, [[TMP1]] ], [ [[TMP8]], [[TMP5]] ]
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[TMP8]] = add nuw nsw i32 [[TMP6]], [[TMP7]]
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[TMP9]] = add nuw nsw i32 [[TMP6]], 1
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[TMP10:%.*]] = icmp eq i32 [[TMP9]], 100
|
|
|
|
; CGSCC_OLD_PM-NEXT: br i1 [[TMP10]], label [[TMP2:%.*]], label [[TMP5]]
|
[Attributor] AAValueConstantRange: Value range analysis using constant range
Summary:
This patch introduces `AAValueConstantRange`, which answers a possible range for integer value in a specific program point.
One of the motivations is propagating existing `range` metadata. (I think we need to change the situation that `range` metadata cannot be put to Argument).
The state is a tuple of `ConstantRange` and it is initialized to (known, assumed) = ([-∞, +∞], empty).
Currently, AAValueConstantRange is created in `getAssumedConstant` method when `AAValueSimplify` returns `nullptr`(worst state).
Supported
- BinaryOperator(add, sub, ...)
- CmpInst(icmp eq, ...)
- !range metadata
`AAValueConstantRange` is not intended to extend to polyhedral range value analysis.
Reviewers: jdoerfert, sstefan1
Reviewed By: jdoerfert
Subscribers: phosek, davezarzycki, baziotis, hiraditya, javed.absar, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D71620
2020-01-15 14:25:52 +08:00
|
|
|
;
|
|
|
|
br label %5
|
|
|
|
|
|
|
|
2: ; preds = %5
|
|
|
|
%3 = icmp sgt i32 %8, 10000
|
|
|
|
br i1 %3, label %4, label %f
|
|
|
|
4:
|
|
|
|
ret i32 20
|
|
|
|
f:
|
|
|
|
ret i32 10
|
|
|
|
5: ; preds = %5, %1
|
|
|
|
%6 = phi i32 [ 0, %1 ], [ %9, %5 ]
|
|
|
|
%7 = phi i32 [ 0, %1 ], [ %8, %5 ]
|
|
|
|
%8 = add nuw nsw i32 %6, %7
|
|
|
|
%9 = add nuw nsw i32 %6, 1
|
|
|
|
%10 = icmp eq i32 %9, 100
|
|
|
|
br i1 %10, label %2, label %5
|
|
|
|
}
|
|
|
|
|
|
|
|
define void @f1(i32){
|
2020-02-10 15:31:20 +08:00
|
|
|
; OLD_PM-LABEL: define {{[^@]+}}@f1
|
|
|
|
; OLD_PM-SAME: (i32 [[TMP0:%.*]])
|
|
|
|
; OLD_PM-NEXT: [[TMP2:%.*]] = tail call i32 @r1()
|
|
|
|
; OLD_PM-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 15
|
|
|
|
; OLD_PM-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP5:%.*]]
|
|
|
|
; OLD_PM: 4:
|
|
|
|
; OLD_PM-NEXT: tail call void @unkown()
|
|
|
|
; OLD_PM-NEXT: br label [[TMP5]]
|
|
|
|
; OLD_PM: 5:
|
|
|
|
; OLD_PM-NEXT: ret void
|
|
|
|
;
|
|
|
|
; NEW_PM-LABEL: define {{[^@]+}}@f1
|
|
|
|
; NEW_PM-SAME: (i32 [[TMP0:%.*]])
|
2020-01-12 14:17:08 +08:00
|
|
|
; NEW_PM-NEXT: br label [[TMP3:%.*]]
|
|
|
|
; NEW_PM: 2:
|
2020-02-10 15:31:20 +08:00
|
|
|
; NEW_PM-NEXT: unreachable
|
2020-01-12 14:17:08 +08:00
|
|
|
; NEW_PM: 3:
|
2020-02-10 15:31:20 +08:00
|
|
|
; NEW_PM-NEXT: ret void
|
2020-02-10 09:08:19 +08:00
|
|
|
;
|
|
|
|
; CGSCC_OLD_PM-LABEL: define {{[^@]+}}@f1
|
|
|
|
; CGSCC_OLD_PM-SAME: (i32 [[TMP0:%.*]])
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[TMP2:%.*]] = tail call i32 @r1(i32 [[TMP0]])
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 15
|
|
|
|
; CGSCC_OLD_PM-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP5:%.*]]
|
|
|
|
; CGSCC_OLD_PM: 4:
|
|
|
|
; CGSCC_OLD_PM-NEXT: tail call void @unkown()
|
|
|
|
; CGSCC_OLD_PM-NEXT: br label [[TMP5]]
|
|
|
|
; CGSCC_OLD_PM: 5:
|
|
|
|
; CGSCC_OLD_PM-NEXT: ret void
|
|
|
|
;
|
|
|
|
; CGSCC_NEW_PM-LABEL: define {{[^@]+}}@f1
|
|
|
|
; CGSCC_NEW_PM-SAME: (i32 [[TMP0:%.*]])
|
2020-01-12 14:17:08 +08:00
|
|
|
; CGSCC_NEW_PM-NEXT: br label [[TMP3:%.*]]
|
|
|
|
; CGSCC_NEW_PM: 2:
|
2020-02-10 09:08:19 +08:00
|
|
|
; CGSCC_NEW_PM-NEXT: unreachable
|
2020-01-12 14:17:08 +08:00
|
|
|
; CGSCC_NEW_PM: 3:
|
2020-02-10 09:08:19 +08:00
|
|
|
; CGSCC_NEW_PM-NEXT: ret void
|
[Attributor] AAValueConstantRange: Value range analysis using constant range
Summary:
This patch introduces `AAValueConstantRange`, which answers a possible range for integer value in a specific program point.
One of the motivations is propagating existing `range` metadata. (I think we need to change the situation that `range` metadata cannot be put to Argument).
The state is a tuple of `ConstantRange` and it is initialized to (known, assumed) = ([-∞, +∞], empty).
Currently, AAValueConstantRange is created in `getAssumedConstant` method when `AAValueSimplify` returns `nullptr`(worst state).
Supported
- BinaryOperator(add, sub, ...)
- CmpInst(icmp eq, ...)
- !range metadata
`AAValueConstantRange` is not intended to extend to polyhedral range value analysis.
Reviewers: jdoerfert, sstefan1
Reviewed By: jdoerfert
Subscribers: phosek, davezarzycki, baziotis, hiraditya, javed.absar, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D71620
2020-01-15 14:25:52 +08:00
|
|
|
;
|
|
|
|
%2 = tail call i32 @r1(i32 %0)
|
|
|
|
%3 = icmp sgt i32 %2, 15
|
|
|
|
br i1 %3, label %4, label %5
|
|
|
|
|
|
|
|
4: ; preds = %1
|
|
|
|
tail call void @unkown()
|
|
|
|
br label %5
|
|
|
|
|
|
|
|
5: ; preds = %1, %4
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
; TEST4 LVI test
|
|
|
|
|
|
|
|
; f1
|
|
|
|
; int test4-f1(int u){
|
|
|
|
; if(u>=0) {
|
|
|
|
; return u;
|
|
|
|
; }else{
|
|
|
|
; return 0;
|
|
|
|
; }
|
|
|
|
; }
|
|
|
|
define dso_local i32 @test4-f1(i32 %u) {
|
|
|
|
; CHECK-LABEL: define {{[^@]+}}@test4-f1
|
|
|
|
; CHECK-SAME: (i32 [[U:%.*]])
|
|
|
|
; CHECK-NEXT: entry:
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[U]], -1
|
|
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[RETURN:%.*]]
|
|
|
|
; CHECK: if.then:
|
|
|
|
; CHECK-NEXT: br label [[RETURN]]
|
|
|
|
; CHECK: return:
|
|
|
|
; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[U]], [[IF_THEN]] ], [ 0, [[ENTRY:%.*]] ]
|
|
|
|
; CHECK-NEXT: ret i32 [[RETVAL_0]]
|
|
|
|
;
|
|
|
|
; FIXME: RETVAL_0 >= 0
|
|
|
|
entry:
|
|
|
|
%cmp = icmp sgt i32 %u, -1
|
|
|
|
br i1 %cmp, label %if.then, label %return
|
|
|
|
|
|
|
|
if.then: ; preds = %entry
|
|
|
|
br label %return
|
|
|
|
|
|
|
|
return: ; preds = %entry, %if.then
|
|
|
|
%retval.0 = phi i32 [ %u, %if.then ], [ 0, %entry ]
|
|
|
|
ret i32 %retval.0
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
define dso_local i32 @test4-g1(i32 %u) {
|
|
|
|
; CHECK-LABEL: define {{[^@]+}}@test4-g1
|
|
|
|
; CHECK-SAME: (i32 [[U:%.*]])
|
|
|
|
; CHECK-NEXT: entry:
|
|
|
|
; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @test4-f1(i32 [[U]])
|
|
|
|
; CHECK-NEXT: ret i32 [[CALL]]
|
|
|
|
;
|
|
|
|
; FIXME: %call should have range [0, inf]
|
|
|
|
|
|
|
|
entry:
|
|
|
|
%call = tail call i32 @test4-f1(i32 %u)
|
|
|
|
ret i32 %call
|
|
|
|
}
|
|
|
|
|
|
|
|
; f2
|
|
|
|
; int test4-f1(int u){
|
|
|
|
; if(u>-1) {
|
|
|
|
; return u+1;
|
|
|
|
; }else{
|
|
|
|
; return 1;
|
|
|
|
; }
|
|
|
|
; }
|
|
|
|
define dso_local i32 @test4-f2(i32 %u) {
|
|
|
|
; CHECK-LABEL: define {{[^@]+}}@test4-f2
|
|
|
|
; CHECK-SAME: (i32 [[U:%.*]])
|
|
|
|
; CHECK-NEXT: entry:
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[U]], -1
|
|
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
|
|
|
|
; CHECK: if.then:
|
|
|
|
; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[U]], 1
|
|
|
|
; CHECK-NEXT: br label [[RETURN:%.*]]
|
|
|
|
; CHECK: if.else:
|
|
|
|
; CHECK-NEXT: br label [[RETURN]]
|
|
|
|
; CHECK: return:
|
|
|
|
; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[ADD]], [[IF_THEN]] ], [ 1, [[IF_ELSE]] ]
|
|
|
|
; CHECK-NEXT: ret i32 [[RETVAL_0]]
|
|
|
|
;
|
|
|
|
entry:
|
|
|
|
%cmp = icmp sgt i32 %u, -1
|
|
|
|
br i1 %cmp, label %if.then, label %if.else
|
|
|
|
|
|
|
|
if.then: ; preds = %entry
|
|
|
|
%add = add nuw nsw i32 %u, 1
|
|
|
|
br label %return
|
|
|
|
|
|
|
|
if.else: ; preds = %entry
|
|
|
|
br label %return
|
|
|
|
|
|
|
|
return: ; preds = %if.else, %if.then
|
|
|
|
%retval.0 = phi i32 [ %add, %if.then ], [ 1, %if.else ]
|
|
|
|
ret i32 %retval.0
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
define dso_local i32 @test4-g2(i32 %u) {
|
2020-02-10 09:05:15 +08:00
|
|
|
; OLD_PM-LABEL: define {{[^@]+}}@test4-g2
|
|
|
|
; OLD_PM-SAME: (i32 [[U:%.*]])
|
|
|
|
; OLD_PM-NEXT: entry:
|
|
|
|
; OLD_PM-NEXT: [[CALL:%.*]] = tail call i32 @test4-f2(i32 [[U]])
|
|
|
|
; OLD_PM-NEXT: ret i32 [[CALL]]
|
[Attributor] AAValueConstantRange: Value range analysis using constant range
Summary:
This patch introduces `AAValueConstantRange`, which answers a possible range for integer value in a specific program point.
One of the motivations is propagating existing `range` metadata. (I think we need to change the situation that `range` metadata cannot be put to Argument).
The state is a tuple of `ConstantRange` and it is initialized to (known, assumed) = ([-∞, +∞], empty).
Currently, AAValueConstantRange is created in `getAssumedConstant` method when `AAValueSimplify` returns `nullptr`(worst state).
Supported
- BinaryOperator(add, sub, ...)
- CmpInst(icmp eq, ...)
- !range metadata
`AAValueConstantRange` is not intended to extend to polyhedral range value analysis.
Reviewers: jdoerfert, sstefan1
Reviewed By: jdoerfert
Subscribers: phosek, davezarzycki, baziotis, hiraditya, javed.absar, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D71620
2020-01-15 14:25:52 +08:00
|
|
|
;
|
2020-02-10 15:31:20 +08:00
|
|
|
; NEW_PM-LABEL: define {{[^@]+}}@test4-g2
|
|
|
|
; NEW_PM-SAME: (i32 [[U:%.*]])
|
|
|
|
; NEW_PM-NEXT: entry:
|
|
|
|
; NEW_PM-NEXT: [[CALL:%.*]] = tail call i32 @test4-f2(i32 [[U]]) #2, !range !3
|
|
|
|
; NEW_PM-NEXT: ret i32 [[CALL]]
|
|
|
|
;
|
|
|
|
; CGSCC_OLD_PM-LABEL: define {{[^@]+}}@test4-g2
|
|
|
|
; CGSCC_OLD_PM-SAME: (i32 [[U:%.*]])
|
|
|
|
; CGSCC_OLD_PM-NEXT: entry:
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CALL:%.*]] = tail call i32 @test4-f2(i32 [[U]])
|
|
|
|
; CGSCC_OLD_PM-NEXT: ret i32 [[CALL]]
|
|
|
|
;
|
|
|
|
; CGSCC_NEW_PM-LABEL: define {{[^@]+}}@test4-g2
|
|
|
|
; CGSCC_NEW_PM-SAME: (i32 [[U:%.*]])
|
|
|
|
; CGSCC_NEW_PM-NEXT: entry:
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CALL:%.*]] = tail call i32 @test4-f2(i32 [[U]])
|
|
|
|
; CGSCC_NEW_PM-NEXT: ret i32 [[CALL]]
|
2020-02-10 09:08:19 +08:00
|
|
|
;
|
|
|
|
; CGSCC-LABEL: define {{[^@]+}}@test4-g2
|
|
|
|
; CGSCC-SAME: (i32 [[U:%.*]])
|
|
|
|
; CGSCC-NEXT: entry:
|
|
|
|
; CGSCC-NEXT: [[CALL:%.*]] = tail call i32 @test4-f2(i32 [[U]])
|
|
|
|
; CGSCC-NEXT: ret i32 [[CALL]]
|
[Attributor] AAValueConstantRange: Value range analysis using constant range
Summary:
This patch introduces `AAValueConstantRange`, which answers a possible range for integer value in a specific program point.
One of the motivations is propagating existing `range` metadata. (I think we need to change the situation that `range` metadata cannot be put to Argument).
The state is a tuple of `ConstantRange` and it is initialized to (known, assumed) = ([-∞, +∞], empty).
Currently, AAValueConstantRange is created in `getAssumedConstant` method when `AAValueSimplify` returns `nullptr`(worst state).
Supported
- BinaryOperator(add, sub, ...)
- CmpInst(icmp eq, ...)
- !range metadata
`AAValueConstantRange` is not intended to extend to polyhedral range value analysis.
Reviewers: jdoerfert, sstefan1
Reviewed By: jdoerfert
Subscribers: phosek, davezarzycki, baziotis, hiraditya, javed.absar, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D71620
2020-01-15 14:25:52 +08:00
|
|
|
entry:
|
|
|
|
%call = tail call i32 @test4-f2(i32 %u)
|
|
|
|
ret i32 %call
|
|
|
|
}
|
|
|
|
|
|
|
|
define dso_local i32 @test-5() {
|
2020-02-10 15:31:20 +08:00
|
|
|
; OLD_PM-LABEL: define {{[^@]+}}@test-5()
|
|
|
|
; OLD_PM-NEXT: entry:
|
|
|
|
; OLD_PM-NEXT: [[CALL:%.*]] = call i32 @rec(i32 0), !range !3
|
|
|
|
; OLD_PM-NEXT: ret i32 [[CALL]]
|
|
|
|
;
|
|
|
|
; NEW_PM-LABEL: define {{[^@]+}}@test-5()
|
|
|
|
; NEW_PM-NEXT: entry:
|
|
|
|
; NEW_PM-NEXT: [[CALL:%.*]] = call i32 @rec(i32 0), !range !4
|
|
|
|
; NEW_PM-NEXT: ret i32 [[CALL]]
|
2020-02-10 09:05:15 +08:00
|
|
|
;
|
2020-02-10 15:31:20 +08:00
|
|
|
; CGSCC_OLD_PM-LABEL: define {{[^@]+}}@test-5()
|
|
|
|
; CGSCC_OLD_PM-NEXT: entry:
|
|
|
|
; CGSCC_OLD_PM-NEXT: [[CALL:%.*]] = call i32 @rec(i32 0)
|
|
|
|
; CGSCC_OLD_PM-NEXT: ret i32 [[CALL]]
|
|
|
|
;
|
|
|
|
; CGSCC_NEW_PM-LABEL: define {{[^@]+}}@test-5()
|
|
|
|
; CGSCC_NEW_PM-NEXT: entry:
|
|
|
|
; CGSCC_NEW_PM-NEXT: [[CALL:%.*]] = call i32 @rec(i32 0)
|
|
|
|
; CGSCC_NEW_PM-NEXT: ret i32 [[CALL]]
|
2020-02-10 09:08:19 +08:00
|
|
|
;
|
|
|
|
; CGSCC-LABEL: define {{[^@]+}}@test-5()
|
|
|
|
; CGSCC-NEXT: entry:
|
|
|
|
; CGSCC-NEXT: [[CALL:%.*]] = call i32 @rec(i32 0)
|
|
|
|
; CGSCC-NEXT: ret i32 [[CALL]]
|
[Attributor] AAValueConstantRange: Value range analysis using constant range
Summary:
This patch introduces `AAValueConstantRange`, which answers a possible range for integer value in a specific program point.
One of the motivations is propagating existing `range` metadata. (I think we need to change the situation that `range` metadata cannot be put to Argument).
The state is a tuple of `ConstantRange` and it is initialized to (known, assumed) = ([-∞, +∞], empty).
Currently, AAValueConstantRange is created in `getAssumedConstant` method when `AAValueSimplify` returns `nullptr`(worst state).
Supported
- BinaryOperator(add, sub, ...)
- CmpInst(icmp eq, ...)
- !range metadata
`AAValueConstantRange` is not intended to extend to polyhedral range value analysis.
Reviewers: jdoerfert, sstefan1
Reviewed By: jdoerfert
Subscribers: phosek, davezarzycki, baziotis, hiraditya, javed.absar, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D71620
2020-01-15 14:25:52 +08:00
|
|
|
entry:
|
|
|
|
%call = call i32 @rec(i32 0)
|
|
|
|
ret i32 %call
|
|
|
|
}
|
|
|
|
define internal i32 @rec(i32 %depth) {
|
|
|
|
; CHECK-LABEL: define {{[^@]+}}@rec
|
|
|
|
; CHECK-SAME: (i32 [[DEPTH:%.*]])
|
|
|
|
; CHECK-NEXT: entry:
|
|
|
|
; CHECK-NEXT: [[CALL:%.*]] = call i32 @foo(i32 [[DEPTH]])
|
|
|
|
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[CALL]], 0
|
|
|
|
; CHECK-NEXT: br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
|
|
|
|
; CHECK: if.then:
|
|
|
|
; CHECK-NEXT: br label [[RETURN:%.*]]
|
|
|
|
; CHECK: if.end:
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[DEPTH]], 10
|
|
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN1:%.*]], label [[IF_END3:%.*]]
|
|
|
|
; CHECK: if.then1:
|
|
|
|
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[DEPTH]], 1
|
|
|
|
; CHECK-NEXT: [[CALL2:%.*]] = call i32 @rec(i32 [[ADD]])
|
|
|
|
; CHECK-NEXT: br label [[IF_END3]]
|
|
|
|
; CHECK: if.end3:
|
|
|
|
; CHECK-NEXT: br label [[RETURN]]
|
|
|
|
; CHECK: return:
|
|
|
|
; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ 0, [[IF_THEN]] ], [ 1, [[IF_END3]] ]
|
|
|
|
; CHECK-NEXT: ret i32 [[RETVAL_0]]
|
|
|
|
;
|
|
|
|
entry:
|
|
|
|
%call = call i32 @foo(i32 %depth)
|
|
|
|
%tobool = icmp ne i32 %call, 0
|
|
|
|
br i1 %tobool, label %if.then, label %if.end
|
|
|
|
|
|
|
|
if.then: ; preds = %entry
|
|
|
|
br label %return
|
|
|
|
|
|
|
|
if.end: ; preds = %entry
|
|
|
|
%cmp = icmp slt i32 %depth, 10
|
|
|
|
br i1 %cmp, label %if.then1, label %if.end3
|
|
|
|
|
|
|
|
if.then1: ; preds = %if.end
|
|
|
|
%add = add nsw i32 %depth, 1
|
|
|
|
%call2 = call i32 @rec(i32 %add)
|
|
|
|
br label %if.end3
|
|
|
|
|
|
|
|
if.end3: ; preds = %if.then1, %if.end
|
|
|
|
br label %return
|
|
|
|
|
|
|
|
return: ; preds = %if.end3, %if.then
|
|
|
|
%retval.0 = phi i32 [ 0, %if.then ], [ 1, %if.end3 ]
|
|
|
|
ret i32 %retval.0
|
|
|
|
}
|
|
|
|
declare dso_local i32 @foo(i32)
|
|
|
|
|
2020-02-10 09:06:09 +08:00
|
|
|
|
|
|
|
; Examples taken from https://llvm.discourse.group/t/impossible-condition-optimization/461/1
|
|
|
|
;
|
|
|
|
; The important part is that we return a constant (false)
|
|
|
|
;
|
|
|
|
; {
|
|
|
|
|
|
|
|
; FIXME: All but the return is not needed anymore
|
|
|
|
define dso_local zeroext i1 @phi(i32 %arg) {
|
2020-02-10 10:14:35 +08:00
|
|
|
; CHECK-LABEL: define {{[^@]+}}@phi
|
|
|
|
; CHECK-SAME: (i32 [[ARG:%.*]])
|
|
|
|
; CHECK-NEXT: bb:
|
|
|
|
; CHECK-NEXT: [[TMP:%.*]] = icmp sgt i32 [[ARG]], 5
|
|
|
|
; CHECK-NEXT: br i1 [[TMP]], label [[BB1:%.*]], label [[BB2:%.*]]
|
|
|
|
; CHECK: bb1:
|
|
|
|
; CHECK-NEXT: br label [[BB3:%.*]]
|
|
|
|
; CHECK: bb2:
|
|
|
|
; CHECK-NEXT: br label [[BB3]]
|
|
|
|
; CHECK: bb3:
|
|
|
|
; CHECK-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[ARG]], 10
|
|
|
|
; CHECK-NEXT: br i1 [[TMP4]], label [[BB5:%.*]], label [[BB7:%.*]]
|
|
|
|
; CHECK: bb5:
|
|
|
|
; CHECK-NEXT: br label [[BB9:%.*]]
|
|
|
|
; CHECK: bb7:
|
|
|
|
; CHECK-NEXT: br label [[BB9]]
|
|
|
|
; CHECK: bb9:
|
|
|
|
; CHECK-NEXT: br label [[BB12:%.*]]
|
|
|
|
; CHECK: bb11:
|
|
|
|
; CHECK-NEXT: unreachable
|
|
|
|
; CHECK: bb12:
|
|
|
|
; CHECK-NEXT: br label [[BB13:%.*]]
|
|
|
|
; CHECK: bb13:
|
|
|
|
; CHECK-NEXT: ret i1 false
|
2020-02-10 09:06:09 +08:00
|
|
|
;
|
|
|
|
bb:
|
|
|
|
%tmp = icmp sgt i32 %arg, 5
|
|
|
|
br i1 %tmp, label %bb1, label %bb2
|
|
|
|
|
|
|
|
bb1: ; preds = %bb
|
|
|
|
br label %bb3
|
|
|
|
|
|
|
|
bb2: ; preds = %bb
|
|
|
|
br label %bb3
|
|
|
|
|
|
|
|
bb3: ; preds = %bb2, %bb1
|
|
|
|
%.02 = phi i32 [ 1, %bb1 ], [ 2, %bb2 ]
|
|
|
|
%tmp4 = icmp sgt i32 %arg, 10
|
|
|
|
br i1 %tmp4, label %bb5, label %bb7
|
|
|
|
|
|
|
|
bb5: ; preds = %bb3
|
|
|
|
%tmp6 = add nsw i32 %.02, 1
|
|
|
|
br label %bb9
|
|
|
|
|
|
|
|
bb7: ; preds = %bb3
|
|
|
|
%tmp8 = add nsw i32 %.02, 2
|
|
|
|
br label %bb9
|
|
|
|
|
|
|
|
bb9: ; preds = %bb7, %bb5
|
|
|
|
%.01 = phi i32 [ %tmp6, %bb5 ], [ %tmp8, %bb7 ]
|
|
|
|
%tmp10 = icmp eq i32 %.01, 5
|
|
|
|
br i1 %tmp10, label %bb11, label %bb12
|
|
|
|
|
|
|
|
bb11: ; preds = %bb9
|
|
|
|
br label %bb13
|
|
|
|
|
|
|
|
bb12: ; preds = %bb9
|
|
|
|
br label %bb13
|
|
|
|
|
|
|
|
bb13: ; preds = %bb12, %bb11
|
|
|
|
%.0 = phi i1 [ true, %bb11 ], [ false, %bb12 ]
|
|
|
|
ret i1 %.0
|
|
|
|
}
|
|
|
|
|
|
|
|
define dso_local i1 @select(i32 %a) local_unnamed_addr #0 {
|
2020-02-10 09:08:04 +08:00
|
|
|
; CHECK-LABEL: define {{[^@]+}}@select
|
|
|
|
; CHECK-SAME: (i32 [[A:%.*]]) local_unnamed_addr
|
|
|
|
; CHECK-NEXT: entry:
|
|
|
|
; CHECK-NEXT: ret i1 false
|
2020-02-10 09:06:09 +08:00
|
|
|
;
|
|
|
|
entry:
|
|
|
|
%cmp = icmp sgt i32 %a, 5
|
|
|
|
%. = select i1 %cmp, i32 1, i32 2
|
|
|
|
%cmp1 = icmp sgt i32 %a, 10
|
|
|
|
%y.0.v = select i1 %cmp1, i32 1, i32 2
|
|
|
|
%y.0 = add nuw nsw i32 %., %y.0.v
|
|
|
|
%cmp6 = icmp eq i32 %y.0, 5
|
|
|
|
ret i1 %cmp6
|
|
|
|
}
|
|
|
|
|
|
|
|
define dso_local i32 @select_zext(i32 %a) local_unnamed_addr #0 {
|
2020-02-10 09:08:04 +08:00
|
|
|
; CHECK-LABEL: define {{[^@]+}}@select_zext
|
|
|
|
; CHECK-SAME: (i32 [[A:%.*]]) local_unnamed_addr
|
|
|
|
; CHECK-NEXT: entry:
|
|
|
|
; CHECK-NEXT: ret i32 0
|
2020-02-10 09:07:30 +08:00
|
|
|
;
|
|
|
|
entry:
|
|
|
|
%cmp = icmp sgt i32 %a, 5
|
|
|
|
%. = select i1 %cmp, i32 1, i32 2
|
|
|
|
%cmp1 = icmp sgt i32 %a, 10
|
|
|
|
%y.0.v = select i1 %cmp1, i32 1, i32 2
|
|
|
|
%y.0 = add nuw nsw i32 %., %y.0.v
|
|
|
|
%cmp6 = icmp eq i32 %y.0, 5
|
|
|
|
%.13 = zext i1 %cmp6 to i32
|
|
|
|
ret i32 %.13
|
|
|
|
}
|
|
|
|
|
|
|
|
; FIXME: We do not look through the ptr casts here.
|
|
|
|
define dso_local i64 @select_int2ptr_bitcast_ptr2int(i32 %a) local_unnamed_addr #0 {
|
|
|
|
; CHECK-LABEL: define {{[^@]+}}@select_int2ptr_bitcast_ptr2int
|
2020-02-10 09:06:09 +08:00
|
|
|
; CHECK-SAME: (i32 [[A:%.*]]) local_unnamed_addr
|
|
|
|
; CHECK-NEXT: entry:
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A]], 5
|
|
|
|
; CHECK-NEXT: [[DOT:%.*]] = select i1 [[CMP]], i32 1, i32 2
|
|
|
|
; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[A]], 10
|
|
|
|
; CHECK-NEXT: [[Y_0_V:%.*]] = select i1 [[CMP1]], i32 1, i32 2
|
|
|
|
; CHECK-NEXT: [[Y_0:%.*]] = add nuw nsw i32 [[DOT]], [[Y_0_V]]
|
|
|
|
; CHECK-NEXT: [[CMP6:%.*]] = icmp eq i32 [[Y_0]], 5
|
2020-02-10 09:07:30 +08:00
|
|
|
; CHECK-NEXT: [[I2P:%.*]] = inttoptr i1 [[CMP6]] to i1*
|
|
|
|
; CHECK-NEXT: [[BC:%.*]] = bitcast i1* [[I2P]] to i32*
|
|
|
|
; CHECK-NEXT: [[P2I:%.*]] = ptrtoint i32* [[BC]] to i64
|
|
|
|
; CHECK-NEXT: ret i64 [[P2I]]
|
2020-02-10 09:06:09 +08:00
|
|
|
;
|
|
|
|
entry:
|
|
|
|
%cmp = icmp sgt i32 %a, 5
|
|
|
|
%. = select i1 %cmp, i32 1, i32 2
|
|
|
|
%cmp1 = icmp sgt i32 %a, 10
|
|
|
|
%y.0.v = select i1 %cmp1, i32 1, i32 2
|
|
|
|
%y.0 = add nuw nsw i32 %., %y.0.v
|
|
|
|
%cmp6 = icmp eq i32 %y.0, 5
|
2020-02-10 09:07:30 +08:00
|
|
|
%i2p = inttoptr i1 %cmp6 to i1*
|
|
|
|
%bc = bitcast i1* %i2p to i32*
|
|
|
|
%p2i = ptrtoint i32* %bc to i64
|
|
|
|
ret i64 %p2i
|
2020-02-10 09:06:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
; }
|
|
|
|
|
2020-02-14 04:22:26 +08:00
|
|
|
define i1 @f_fcmp(float %a, float %b) {
|
|
|
|
%r = fcmp uge float %a, %b
|
|
|
|
%s = select i1 %r, i1 %r, i1 0
|
|
|
|
ret i1 %s
|
|
|
|
}
|
|
|
|
define i1 @d_fcmp(double %a, double %b) {
|
|
|
|
%r = fcmp oeq double %a, %b
|
|
|
|
%s = select i1 %r, i1 %r, i1 0
|
|
|
|
ret i1 %s
|
|
|
|
}
|
|
|
|
define i1 @dp_icmp(double* %a, double* %b) {
|
|
|
|
%r = icmp sge double* %a, %b
|
|
|
|
%s = select i1 %r, i1 %r, i1 0
|
|
|
|
ret i1 %s
|
|
|
|
}
|
|
|
|
define i1 @ip_icmp(i8* %a, i8* %b) {
|
|
|
|
%r = icmp ult i8* %a, %b
|
|
|
|
%s = select i1 %r, i1 %r, i1 0
|
|
|
|
ret i1 %s
|
|
|
|
}
|
|
|
|
define i1 @fcmp_caller(float %fa, float %fb, double %da, double %db, double* %dpa, double* %dpb, i8* %ipa, i8* %ipb) {
|
|
|
|
%r1 = call i1 @f_fcmp(float %fa, float %fb)
|
|
|
|
%r2 = call i1 @d_fcmp(double %da, double %db)
|
|
|
|
%r3 = call i1 @dp_icmp(double* %dpa, double* %dpb)
|
|
|
|
%r4 = call i1 @ip_icmp(i8* %ipa, i8* %ipb)
|
|
|
|
%o1 = or i1 %r1, %r2
|
|
|
|
%o2 = or i1 %r3, %r4
|
|
|
|
%o3 = or i1 %o1, %o2
|
|
|
|
ret i1 %o3
|
|
|
|
}
|
|
|
|
|
[Attributor] AAValueConstantRange: Value range analysis using constant range
Summary:
This patch introduces `AAValueConstantRange`, which answers a possible range for integer value in a specific program point.
One of the motivations is propagating existing `range` metadata. (I think we need to change the situation that `range` metadata cannot be put to Argument).
The state is a tuple of `ConstantRange` and it is initialized to (known, assumed) = ([-∞, +∞], empty).
Currently, AAValueConstantRange is created in `getAssumedConstant` method when `AAValueSimplify` returns `nullptr`(worst state).
Supported
- BinaryOperator(add, sub, ...)
- CmpInst(icmp eq, ...)
- !range metadata
`AAValueConstantRange` is not intended to extend to polyhedral range value analysis.
Reviewers: jdoerfert, sstefan1
Reviewed By: jdoerfert
Subscribers: phosek, davezarzycki, baziotis, hiraditya, javed.absar, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D71620
2020-01-15 14:25:52 +08:00
|
|
|
!0 = !{i32 0, i32 10}
|
|
|
|
!1 = !{i32 10, i32 100}
|
2020-02-10 09:05:15 +08:00
|
|
|
; CHECK: !0 = !{i32 0, i32 10}
|
|
|
|
; CHECK-NEXT: !1 = !{i32 10, i32 100}
|
2020-02-10 15:31:20 +08:00
|
|
|
; NEW_PM: !2 = !{i32 200, i32 1091}
|
2020-02-10 09:05:15 +08:00
|
|
|
; OLD_PM: !3 = !{i32 0, i32 2}
|
|
|
|
; NEW_PM: !3 = !{i32 1, i32 -2147483648}
|
|
|
|
; NEW_PM: !4 = !{i32 0, i32 2}
|