Files
clang-p2996/llvm/test/Transforms/CorrelatedValuePropagation/cond-using-block-value.ll
Nikita Popov 734ee0e01f [LVI] Support using block values when handling conditions (#75311)
Currently, LVI will only use conditions like "X < C" to constrain the
value of X on the relevant edge. This patch extends it to handle
conditions like "X < Y" by querying the known range of Y.

This means that getValueFromCondition() and various related APIs can now
return nullopt to indicate that they have pushed to the worklist, and
need to be called again later. This behavior is currently controlled by
a UseBlockValue option, and only enabled for actual edge value handling.
All other places deriving constraints from conditions keep using the
previous logic for now.

This change was originally motivated as a fix for the regression
reported in
https://github.com/llvm/llvm-project/pull/73662#issuecomment-1849281758.
Unfortunately, it doesn't actually fix it, because we run into another
issue there (LVI currently is really bad at handling values used in
loops).

This change has some compile-time impact, but it's fairly small,
in the 0.05% range.
2024-01-02 10:49:45 +01:00

97 lines
2.7 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
; RUN: opt -S -passes=correlated-propagation < %s | FileCheck %s
declare void @use(i1)
define void @test_icmp_from_implied_cond(i32 %a, i32 %b) {
; CHECK-LABEL: define void @test_icmp_from_implied_cond(
; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
; CHECK-NEXT: [[A_CMP:%.*]] = icmp ugt i32 [[A]], 32
; CHECK-NEXT: br i1 [[A_CMP]], label [[END:%.*]], label [[L1:%.*]]
; CHECK: l1:
; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[B]], [[A]]
; CHECK-NEXT: br i1 [[COND]], label [[L2:%.*]], label [[END]]
; CHECK: l2:
; CHECK-NEXT: call void @use(i1 true)
; CHECK-NEXT: [[B_CMP2:%.*]] = icmp ult i32 [[B]], 31
; CHECK-NEXT: call void @use(i1 [[B_CMP2]])
; CHECK-NEXT: ret void
; CHECK: end:
; CHECK-NEXT: ret void
;
%a.cmp = icmp ugt i32 %a, 32
br i1 %a.cmp, label %end, label %l1
l1:
%cond = icmp ult i32 %b, %a
br i1 %cond, label %l2, label %end
l2:
%b.cmp1 = icmp ult i32 %b, 32
call void @use(i1 %b.cmp1)
%b.cmp2 = icmp ult i32 %b, 31
call void @use(i1 %b.cmp2)
ret void
end:
ret void
}
define i64 @test_sext_from_implied_cond(i32 %a, i32 %b) {
; CHECK-LABEL: define i64 @test_sext_from_implied_cond(
; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
; CHECK-NEXT: [[A_CMP:%.*]] = icmp slt i32 [[A]], 0
; CHECK-NEXT: br i1 [[A_CMP]], label [[END:%.*]], label [[L1:%.*]]
; CHECK: l1:
; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[B]], [[A]]
; CHECK-NEXT: br i1 [[COND]], label [[L2:%.*]], label [[END]]
; CHECK: l2:
; CHECK-NEXT: [[SEXT:%.*]] = zext nneg i32 [[B]] to i64
; CHECK-NEXT: ret i64 [[SEXT]]
; CHECK: end:
; CHECK-NEXT: ret i64 0
;
%a.cmp = icmp slt i32 %a, 0
br i1 %a.cmp, label %end, label %l1
l1:
%cond = icmp ult i32 %b, %a
br i1 %cond, label %l2, label %end
l2:
%sext = sext i32 %b to i64
ret i64 %sext
end:
ret i64 0
}
define void @test_icmp_from_implied_range(i16 %x, i32 %b) {
; CHECK-LABEL: define void @test_icmp_from_implied_range(
; CHECK-SAME: i16 [[X:%.*]], i32 [[B:%.*]]) {
; CHECK-NEXT: [[A:%.*]] = zext i16 [[X]] to i32
; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[B]], [[A]]
; CHECK-NEXT: br i1 [[COND]], label [[L1:%.*]], label [[END:%.*]]
; CHECK: l1:
; CHECK-NEXT: call void @use(i1 true)
; CHECK-NEXT: [[B_CMP2:%.*]] = icmp ult i32 [[B]], 65534
; CHECK-NEXT: call void @use(i1 [[B_CMP2]])
; CHECK-NEXT: ret void
; CHECK: end:
; CHECK-NEXT: ret void
;
%a = zext i16 %x to i32
%cond = icmp ult i32 %b, %a
br i1 %cond, label %l1, label %end
l1:
%b.cmp1 = icmp ult i32 %b, 65535
call void @use(i1 %b.cmp1)
%b.cmp2 = icmp ult i32 %b, 65534
call void @use(i1 %b.cmp2)
ret void
end:
ret void
}