270 lines
6.8 KiB
LLVM
270 lines
6.8 KiB
LLVM
|
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||
|
; RUN: opt < %s -ipsccp -S | FileCheck %s
|
||
|
|
||
|
declare void @use(i1)
|
||
|
|
||
|
; We can simplify the conditions in the true block, because the condition
|
||
|
; allows us to replace all uses of %a in the block with a constant.
|
||
|
define void @val_undef_eq() {
|
||
|
; CHECK-LABEL: @val_undef_eq(
|
||
|
; CHECK-NEXT: entry:
|
||
|
; CHECK-NEXT: [[A:%.*]] = add i32 undef, 0
|
||
|
; CHECK-NEXT: [[BC_1:%.*]] = icmp eq i32 [[A]], 10
|
||
|
; CHECK-NEXT: br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]]
|
||
|
; CHECK: true:
|
||
|
; CHECK-NEXT: call void @use(i1 false)
|
||
|
; CHECK-NEXT: call void @use(i1 true)
|
||
|
; CHECK-NEXT: ret void
|
||
|
; CHECK: false:
|
||
|
; CHECK-NEXT: ret void
|
||
|
;
|
||
|
entry:
|
||
|
%a = add i32 undef, 0
|
||
|
%bc.1 = icmp eq i32 %a, 10
|
||
|
br i1 %bc.1, label %true, label %false
|
||
|
|
||
|
true:
|
||
|
%f.1 = icmp ne i32 %a, 10
|
||
|
call void @use(i1 %f.1)
|
||
|
%f.2 = icmp eq i32 %a, 10
|
||
|
call void @use(i1 %f.2)
|
||
|
ret void
|
||
|
|
||
|
false:
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
declare void @use.i32(i32)
|
||
|
|
||
|
; It is not allowed to use the range information from the condition to remove
|
||
|
; %a.127 = and ... in the true block, as %a could be undef.
|
||
|
define void @val_undef_range() {
|
||
|
; CHECK-LABEL: @val_undef_range(
|
||
|
; CHECK-NEXT: entry:
|
||
|
; CHECK-NEXT: [[A:%.*]] = add i32 undef, 0
|
||
|
; CHECK-NEXT: [[BC_1:%.*]] = icmp ult i32 [[A]], 127
|
||
|
; CHECK-NEXT: br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]]
|
||
|
; CHECK: true:
|
||
|
; CHECK-NEXT: call void @use(i1 false)
|
||
|
; CHECK-NEXT: [[A_127:%.*]] = and i32 [[A]], 127
|
||
|
; CHECK-NEXT: call void @use.i32(i32 [[A_127]])
|
||
|
; CHECK-NEXT: ret void
|
||
|
; CHECK: false:
|
||
|
; CHECK-NEXT: ret void
|
||
|
;
|
||
|
entry:
|
||
|
%a = add i32 undef, 0
|
||
|
%bc.1 = icmp ult i32 %a, 127
|
||
|
br i1 %bc.1, label %true, label %false
|
||
|
|
||
|
true:
|
||
|
%f.1 = icmp eq i32 %a, 128
|
||
|
call void @use(i1 %f.1)
|
||
|
|
||
|
%a.127 = and i32 %a, 127
|
||
|
call void @use.i32(i32 %a.127)
|
||
|
ret void
|
||
|
|
||
|
false:
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
; All uses of %p can be replaced by a constant (10).
|
||
|
define void @val_singlecrfromundef_range(i1 %cond) {
|
||
|
; CHECK-LABEL: @val_singlecrfromundef_range(
|
||
|
; CHECK-NEXT: entry:
|
||
|
; CHECK-NEXT: br i1 [[COND:%.*]], label [[INC1:%.*]], label [[INC2:%.*]]
|
||
|
; CHECK: inc1:
|
||
|
; CHECK-NEXT: br label [[IF:%.*]]
|
||
|
; CHECK: inc2:
|
||
|
; CHECK-NEXT: br label [[IF]]
|
||
|
; CHECK: if:
|
||
|
; CHECK-NEXT: br label [[TRUE:%.*]]
|
||
|
; CHECK: true:
|
||
|
; CHECK-NEXT: call void @use(i1 false)
|
||
|
; CHECK-NEXT: [[P_127:%.*]] = and i32 10, 127
|
||
|
; CHECK-NEXT: call void @use.i32(i32 [[P_127]])
|
||
|
; CHECK-NEXT: ret void
|
||
|
;
|
||
|
entry:
|
||
|
|
||
|
br i1 %cond, label %inc1, label %inc2
|
||
|
|
||
|
inc1:
|
||
|
br label %if
|
||
|
|
||
|
inc2:
|
||
|
br label %if
|
||
|
|
||
|
if:
|
||
|
%p = phi i32 [ 10, %inc1 ], [ undef, %inc2 ]
|
||
|
%bc.1 = icmp ult i32 %p, 127
|
||
|
br i1 %bc.1, label %true, label %false
|
||
|
|
||
|
true:
|
||
|
%f.1 = icmp eq i32 %p, 128
|
||
|
call void @use(i1 %f.1)
|
||
|
|
||
|
%p.127 = and i32 %p, 127
|
||
|
call void @use.i32(i32 %p.127)
|
||
|
ret void
|
||
|
|
||
|
false:
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
|
||
|
; It is not allowed to use the information from the condition ([0, 128))
|
||
|
; to remove a.127.2 = and i32 %p, 127, as %p might be undef.
|
||
|
define void @val_undef_to_cr_to_overdef_range(i32 %a, i1 %cond) {
|
||
|
; CHECK-LABEL: @val_undef_to_cr_to_overdef_range(
|
||
|
; CHECK-NEXT: entry:
|
||
|
; CHECK-NEXT: [[A_127:%.*]] = and i32 [[A:%.*]], 127
|
||
|
; CHECK-NEXT: br i1 [[COND:%.*]], label [[INC1:%.*]], label [[INC2:%.*]]
|
||
|
; CHECK: inc1:
|
||
|
; CHECK-NEXT: br label [[IF:%.*]]
|
||
|
; CHECK: inc2:
|
||
|
; CHECK-NEXT: br label [[IF]]
|
||
|
; CHECK: if:
|
||
|
; CHECK-NEXT: [[P:%.*]] = phi i32 [ [[A_127]], [[INC1]] ], [ undef, [[INC2]] ]
|
||
|
; CHECK-NEXT: [[BC_1:%.*]] = icmp ult i32 [[P]], 100
|
||
|
; CHECK-NEXT: br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]]
|
||
|
; CHECK: true:
|
||
|
; CHECK-NEXT: call void @use(i1 false)
|
||
|
; CHECK-NEXT: [[P_127:%.*]] = and i32 [[P]], 127
|
||
|
; CHECK-NEXT: call void @use.i32(i32 [[P_127]])
|
||
|
; CHECK-NEXT: ret void
|
||
|
; CHECK: false:
|
||
|
; CHECK-NEXT: ret void
|
||
|
;
|
||
|
entry:
|
||
|
%a.127 = and i32 %a, 127
|
||
|
br i1 %cond, label %inc1, label %inc2
|
||
|
|
||
|
inc1:
|
||
|
br label %if
|
||
|
|
||
|
inc2:
|
||
|
br label %if
|
||
|
|
||
|
if:
|
||
|
%p = phi i32 [ %a.127, %inc1 ], [ undef, %inc2 ]
|
||
|
%bc.1 = icmp ult i32 %p, 100
|
||
|
br i1 %bc.1, label %true, label %false
|
||
|
|
||
|
true:
|
||
|
%f.1 = icmp eq i32 %p, 128
|
||
|
call void @use(i1 %f.1)
|
||
|
|
||
|
%p.127 = and i32 %p, 127
|
||
|
call void @use.i32(i32 %p.127)
|
||
|
ret void
|
||
|
|
||
|
false:
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
; All uses of %p can be replaced by a constant (10), we are allowed to use it
|
||
|
; as a bound too.
|
||
|
define void @bound_singlecrfromundef(i32 %a, i1 %cond) {
|
||
|
; CHECK-LABEL: @bound_singlecrfromundef(
|
||
|
; CHECK-NEXT: entry:
|
||
|
; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
|
||
|
; CHECK: bb1:
|
||
|
; CHECK-NEXT: br label [[PRED:%.*]]
|
||
|
; CHECK: bb2:
|
||
|
; CHECK-NEXT: br label [[PRED]]
|
||
|
; CHECK: pred:
|
||
|
; CHECK-NEXT: [[BC_1:%.*]] = icmp ugt i32 [[A:%.*]], 10
|
||
|
; CHECK-NEXT: br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]]
|
||
|
; CHECK: true:
|
||
|
; CHECK-NEXT: call void @use(i1 false)
|
||
|
; CHECK-NEXT: call void @use(i1 true)
|
||
|
; CHECK-NEXT: [[A_127:%.*]] = and i32 [[A]], 127
|
||
|
; CHECK-NEXT: call void @use.i32(i32 [[A_127]])
|
||
|
; CHECK-NEXT: ret void
|
||
|
; CHECK: false:
|
||
|
; CHECK-NEXT: ret void
|
||
|
;
|
||
|
entry:
|
||
|
br i1 %cond, label %bb1, label %bb2
|
||
|
|
||
|
bb1:
|
||
|
br label %pred
|
||
|
|
||
|
bb2:
|
||
|
br label %pred
|
||
|
|
||
|
pred:
|
||
|
%p = phi i32 [ undef, %bb1 ], [ 10, %bb2 ]
|
||
|
%bc.1 = icmp ugt i32 %a, %p
|
||
|
br i1 %bc.1, label %true, label %false
|
||
|
|
||
|
true:
|
||
|
%f.1 = icmp eq i32 %a, 5
|
||
|
call void @use(i1 %f.1)
|
||
|
|
||
|
%t.1 = icmp ne i32 %a, 5
|
||
|
call void @use(i1 %t.1)
|
||
|
|
||
|
%a.127 = and i32 %a, 127
|
||
|
call void @use.i32(i32 %a.127)
|
||
|
|
||
|
ret void
|
||
|
|
||
|
false:
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
; It is not allowed to use the information from %p as a bound, because an
|
||
|
; incoming value is undef.
|
||
|
define void @bound_range_and_undef(i32 %a, i1 %cond) {
|
||
|
; CHECK-LABEL: @bound_range_and_undef(
|
||
|
; CHECK-NEXT: entry:
|
||
|
; CHECK-NEXT: [[A_10:%.*]] = and i32 [[A:%.*]], 127
|
||
|
; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
|
||
|
; CHECK: bb1:
|
||
|
; CHECK-NEXT: br label [[PRED:%.*]]
|
||
|
; CHECK: bb2:
|
||
|
; CHECK-NEXT: br label [[PRED]]
|
||
|
; CHECK: pred:
|
||
|
; CHECK-NEXT: [[P:%.*]] = phi i32 [ [[A_10]], [[BB1]] ], [ undef, [[BB2]] ]
|
||
|
; CHECK-NEXT: [[BC_1:%.*]] = icmp ugt i32 [[A]], [[P]]
|
||
|
; CHECK-NEXT: br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]]
|
||
|
; CHECK: true:
|
||
|
; CHECK-NEXT: [[F_1:%.*]] = icmp eq i32 [[A]], 300
|
||
|
; CHECK-NEXT: call void @use(i1 [[F_1]])
|
||
|
; CHECK-NEXT: [[A_127_2:%.*]] = and i32 [[P]], 127
|
||
|
; CHECK-NEXT: call void @use.i32(i32 [[A_127_2]])
|
||
|
; CHECK-NEXT: ret void
|
||
|
; CHECK: false:
|
||
|
; CHECK-NEXT: ret void
|
||
|
;
|
||
|
entry:
|
||
|
%a.10 = and i32 %a, 127
|
||
|
br i1 %cond, label %bb1, label %bb2
|
||
|
|
||
|
bb1:
|
||
|
br label %pred
|
||
|
|
||
|
bb2:
|
||
|
br label %pred
|
||
|
|
||
|
pred:
|
||
|
%p = phi i32 [ %a.10, %bb1 ], [ undef, %bb2 ]
|
||
|
%bc.1 = icmp ugt i32 %a, %p
|
||
|
br i1 %bc.1, label %true, label %false
|
||
|
|
||
|
true:
|
||
|
%f.1 = icmp eq i32 %a, 300
|
||
|
call void @use(i1 %f.1)
|
||
|
|
||
|
%a.127.2 = and i32 %p, 127
|
||
|
call void @use.i32(i32 %a.127.2)
|
||
|
|
||
|
ret void
|
||
|
|
||
|
false:
|
||
|
ret void
|
||
|
}
|