diff --git a/llvm/lib/Analysis/LazyValueInfo.cpp b/llvm/lib/Analysis/LazyValueInfo.cpp index c7b0ca97a8e43..90bae77bcf703 100644 --- a/llvm/lib/Analysis/LazyValueInfo.cpp +++ b/llvm/lib/Analysis/LazyValueInfo.cpp @@ -1493,6 +1493,24 @@ LazyValueInfoImpl::getEdgeValueLocal(Value *Val, BasicBlock *BBFrom, // br %Condition, label %then, label %else APInt ConditionVal(1, isTrueDest ? 1 : 0); Result = constantFoldUser(Usr, Condition, ConditionVal, DL); + } else if (isa(Usr)) { + ValueLatticeElement OpLatticeVal = + *getValueFromCondition(Usr->getOperand(0), Condition, + isTrueDest, /*UseBlockValue*/ false); + + if (!OpLatticeVal.isConstantRange()) + return OpLatticeVal; + + const unsigned ResultBitWidth = + Usr->getType()->getScalarSizeInBits(); + if (auto *Trunc = dyn_cast(Usr)) + return ValueLatticeElement::getRange( + OpLatticeVal.getConstantRange().truncate( + ResultBitWidth, Trunc->getNoWrapKind())); + + return ValueLatticeElement::getRange( + OpLatticeVal.getConstantRange().castOp( + cast(Usr)->getOpcode(), ResultBitWidth)); } else { // If one of Val's operand has an inferred value, we may be able to // infer the value of Val. diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/range.ll b/llvm/test/Transforms/CorrelatedValuePropagation/range.ll index 8d787fd5586ef..860caf2624d42 100644 --- a/llvm/test/Transforms/CorrelatedValuePropagation/range.ll +++ b/llvm/test/Transforms/CorrelatedValuePropagation/range.ll @@ -1235,6 +1235,126 @@ define i1 @neg_icmp_eq_range_call() { ret i1 %cmp } +define i16 @return_range_for_edge_value_zext(i8 %a) { +; CHECK-LABEL: define range(i16 0, 98) i16 @return_range_for_edge_value_zext( +; CHECK-SAME: i8 [[A:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[B:%.*]] = zext i8 [[A]] to i16 +; CHECK-NEXT: br label %[[DISPATCH:.*]] +; CHECK: [[DISPATCH]]: +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[A]], 98 +; CHECK-NEXT: br i1 [[CMP]], label %[[TARGET:.*]], label %[[DISPATCH]] +; CHECK: [[TARGET]]: +; CHECK-NEXT: ret i16 [[B]] +; +entry: + %b = zext i8 %a to i16 + br label %dispatch + +dispatch: + %cmp = icmp ult i8 %a, 98 + br i1 %cmp, label %target, label %dispatch + +target: + ret i16 %b +} + +define i16 @return_range_for_edge_value_sext(i8 %a) { +; CHECK-LABEL: define range(i16 -55, 0) i16 @return_range_for_edge_value_sext( +; CHECK-SAME: i8 [[A:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[B:%.*]] = sext i8 [[A]] to i16 +; CHECK-NEXT: br label %[[DISPATCH:.*]] +; CHECK: [[DISPATCH]]: +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[A]], -56 +; CHECK-NEXT: br i1 [[CMP]], label %[[TARGET:.*]], label %[[DISPATCH]] +; CHECK: [[TARGET]]: +; CHECK-NEXT: ret i16 [[B]] +; +entry: + %b = sext i8 %a to i16 + br label %dispatch + +dispatch: + %cmp = icmp ugt i8 %a, -56 + br i1 %cmp, label %target, label %dispatch + +target: + ret i16 %b +} + +define i8 @return_range_for_edge_value_trunc(i16 %a) { +; CHECK-LABEL: define range(i8 0, 98) i8 @return_range_for_edge_value_trunc( +; CHECK-SAME: i16 [[A:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[B:%.*]] = trunc i16 [[A]] to i8 +; CHECK-NEXT: br label %[[DISPATCH:.*]] +; CHECK: [[DISPATCH]]: +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[A]], 98 +; CHECK-NEXT: br i1 [[CMP]], label %[[TARGET:.*]], label %[[DISPATCH]] +; CHECK: [[TARGET]]: +; CHECK-NEXT: ret i8 [[B]] +; +entry: + %b = trunc i16 %a to i8 + br label %dispatch + +dispatch: + %cmp = icmp ult i16 %a, 98 + br i1 %cmp, label %target, label %dispatch + +target: + ret i8 %b +} + +define i8 @neg_return_range_for_edge_value_trunc(i16 %a) { +; CHECK-LABEL: define i8 @neg_return_range_for_edge_value_trunc( +; CHECK-SAME: i16 [[A:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[B:%.*]] = trunc i16 [[A]] to i8 +; CHECK-NEXT: br label %[[DISPATCH:.*]] +; CHECK: [[DISPATCH]]: +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i16 [[A]], 200 +; CHECK-NEXT: br i1 [[CMP]], label %[[TARGET:.*]], label %[[DISPATCH]] +; CHECK: [[TARGET]]: +; CHECK-NEXT: ret i8 [[B]] +; +entry: + %b = trunc i16 %a to i8 + br label %dispatch + +dispatch: + %cmp = icmp ugt i16 %a, 200 + br i1 %cmp, label %target, label %dispatch + +target: + ret i8 %b +} + +define i8 @return_range_for_edge_value_trunc_nuw(i16 %a) { +; CHECK-LABEL: define range(i8 -55, 0) i8 @return_range_for_edge_value_trunc_nuw( +; CHECK-SAME: i16 [[A:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[B:%.*]] = trunc nuw i16 [[A]] to i8 +; CHECK-NEXT: br label %[[DISPATCH:.*]] +; CHECK: [[DISPATCH]]: +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i16 [[A]], 200 +; CHECK-NEXT: br i1 [[CMP]], label %[[TARGET:.*]], label %[[DISPATCH]] +; CHECK: [[TARGET]]: +; CHECK-NEXT: ret i8 [[B]] +; +entry: + %b = trunc nuw i16 %a to i8 + br label %dispatch + +dispatch: + %cmp = icmp ugt i16 %a, 200 + br i1 %cmp, label %target, label %dispatch + +target: + ret i8 %b +} + declare i16 @llvm.ctlz.i16(i16, i1) declare i16 @llvm.cttz.i16(i16, i1) declare i16 @llvm.ctpop.i16(i16) diff --git a/llvm/test/Transforms/JumpThreading/branch-debug-info2.ll b/llvm/test/Transforms/JumpThreading/branch-debug-info2.ll index 2bfa492832def..59b6ef51d670f 100644 --- a/llvm/test/Transforms/JumpThreading/branch-debug-info2.ll +++ b/llvm/test/Transforms/JumpThreading/branch-debug-info2.ll @@ -18,8 +18,8 @@ if.end.i60: ; preds = %shadow_to_ptr.exit %spec.select.i = select i1 %cmp3.i, i32 -1, i32 %conv7.i, !dbg !17 ; Jump threading is going to fold the select in to the branch. Ensure debug ; info is not lost, and is merged from the select and the branch. -; CHECK-NOT: br i1 %cmp3.i, label %for.inc, label %ptr_to_shadow.exit -; CHECK: br i1 %cmp3.i, label %for.inc, label %ptr_to_shadow.exit, !dbg [[DBG:![0-9]+]] +; CHECK-NOT: br i1 %cmp3.i, label %for.inc, label %if.end22 +; CHECK: br i1 %cmp3.i, label %for.inc, label %if.end22, !dbg [[DBG:![0-9]+]] ; CHECK: [[DBG]] = !DILocation(line: 9, column: 1, scope: !{{.*}}) br label %ptr_to_shadow.exit, !dbg !17