diff --git a/llvm/lib/Analysis/LazyValueInfo.cpp b/llvm/lib/Analysis/LazyValueInfo.cpp index 789c2902369b9..7a40259492abf 100644 --- a/llvm/lib/Analysis/LazyValueInfo.cpp +++ b/llvm/lib/Analysis/LazyValueInfo.cpp @@ -876,10 +876,14 @@ LazyValueInfoImpl::solveBlockValueSelect(SelectInst *SI, BasicBlock *BB) { // condition itself? This shows up with idioms like e.g. select(a > 5, a, 5). // TODO: We could potentially refine an overdefined true value above. Value *Cond = SI->getCondition(); - TrueVal = intersect(TrueVal, - getValueFromCondition(SI->getTrueValue(), Cond, true)); - FalseVal = intersect(FalseVal, - getValueFromCondition(SI->getFalseValue(), Cond, false)); + // If the value is undef, a different value may be chosen in + // the select condition. + if (isGuaranteedNotToBeUndefOrPoison(Cond, AC)) { + TrueVal = intersect(TrueVal, + getValueFromCondition(SI->getTrueValue(), Cond, true)); + FalseVal = intersect( + FalseVal, getValueFromCondition(SI->getFalseValue(), Cond, false)); + } ValueLatticeElement Result = TrueVal; Result.mergeIn(FalseVal); diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/basic.ll b/llvm/test/Transforms/CorrelatedValuePropagation/basic.ll index c3c753375f1b4..39285df56ae3c 100644 --- a/llvm/test/Transforms/CorrelatedValuePropagation/basic.ll +++ b/llvm/test/Transforms/CorrelatedValuePropagation/basic.ll @@ -735,7 +735,7 @@ define i1 @umin_rhs_overdefined_lhs_range(i32 %a, i32 %b) { ret i1 %cmp2 } -define i1 @clamp_low1(i32 %a) { +define i1 @clamp_low1(i32 noundef %a) { ; CHECK-LABEL: @clamp_low1( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[A:%.*]], 5 @@ -762,7 +762,7 @@ out: ret i1 false } -define i1 @clamp_low2(i32 %a) { +define i1 @clamp_low2(i32 noundef %a) { ; CHECK-LABEL: @clamp_low2( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[A:%.*]], 5 @@ -789,7 +789,7 @@ out: ret i1 false } -define i1 @clamp_low3(i32 %a) { +define i1 @clamp_low3(i32 noundef %a) { ; CHECK-LABEL: @clamp_low3( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[A:%.*]], 5 @@ -816,7 +816,7 @@ out: ret i1 false } -define i1 @clamp_low4(i32 %a) { +define i1 @clamp_low4(i32 noundef %a) { ; CHECK-LABEL: @clamp_low4( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[A:%.*]], 5 @@ -843,7 +843,7 @@ out: ret i1 false } -define i1 @clamp_high1(i32 %a) { +define i1 @clamp_high1(i32 noundef %a) { ; CHECK-LABEL: @clamp_high1( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A:%.*]], 5 @@ -870,7 +870,7 @@ out: ret i1 false } -define i1 @clamp_high2(i32 %a) { +define i1 @clamp_high2(i32 noundef %a) { ; CHECK-LABEL: @clamp_high2( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A:%.*]], 5 @@ -897,7 +897,7 @@ out: ret i1 false } -define i1 @clamp_high3(i32 %a) { +define i1 @clamp_high3(i32 noundef %a) { ; CHECK-LABEL: @clamp_high3( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A:%.*]], 5 @@ -924,7 +924,7 @@ out: ret i1 false } -define i1 @clamp_high4(i32 %a) { +define i1 @clamp_high4(i32 noundef %a) { ; CHECK-LABEL: @clamp_high4( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A:%.*]], 5 @@ -952,7 +952,7 @@ out: } ; Just showing arbitrary constants work, not really a clamp -define i1 @not_clamp_high(i32 %a) { +define i1 @not_clamp_high(i32 noundef %a) { ; CHECK-LABEL: @not_clamp_high( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A:%.*]], 5 diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/select.ll b/llvm/test/Transforms/CorrelatedValuePropagation/select.ll index 923b6ac427578..8ffd9536d7970 100644 --- a/llvm/test/Transforms/CorrelatedValuePropagation/select.ll +++ b/llvm/test/Transforms/CorrelatedValuePropagation/select.ll @@ -222,7 +222,7 @@ define i1 @test5(ptr %p, i1 %unknown) { ; CHECK: exit: ; CHECK-NEXT: ret i1 true ; - %pval = load i32, i32* %p + %pval = load i32, i32* %p, !noundef !0 %cmp1 = icmp slt i32 %pval, 255 br i1 %cmp1, label %next, label %exit @@ -248,7 +248,7 @@ define i1 @test6(ptr %p, i1 %unknown) { ; CHECK: exit: ; CHECK-NEXT: ret i1 true ; - %pval = load i32, i32* %p + %pval = load i32, i32* %p, !noundef !0 %cmp1 = icmp ult i32 %pval, 255 br i1 %cmp1, label %next, label %exit @@ -261,3 +261,18 @@ next: exit: ret i1 true } + +define i64 @select_cond_may_undef(i32 %a) { +; CHECK-LABEL: @select_cond_may_undef( +; CHECK-NEXT: [[IS_A_NONNEGATIVE:%.*]] = icmp sgt i32 [[A:%.*]], 1 +; CHECK-NEXT: [[NARROW:%.*]] = select i1 [[IS_A_NONNEGATIVE]], i32 [[A]], i32 0 +; CHECK-NEXT: [[MAX:%.*]] = sext i32 [[NARROW]] to i64 +; CHECK-NEXT: ret i64 [[MAX]] +; + %is_a_nonnegative = icmp sgt i32 %a, 1 + %narrow = select i1 %is_a_nonnegative, i32 %a, i32 0 + %max = sext i32 %narrow to i64 + ret i64 %max +} + +!0 = !{}