-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[LVI] Support no constant range of cast value in getEdgeValueLocal. #157614
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…geValueLocal. (NFC)
@llvm/pr-subscribers-llvm-transforms @llvm/pr-subscribers-llvm-analysis Author: Andreas Jonson (andjo403) Changesproof: https://alive2.llvm.org/ce/z/8emkHY Full diff: https://github.com/llvm/llvm-project/pull/157614.diff 2 Files Affected:
diff --git a/llvm/lib/Analysis/LazyValueInfo.cpp b/llvm/lib/Analysis/LazyValueInfo.cpp
index c7b0ca97a8e43..cbb9ed3b12934 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<CastInst>(Usr) || isa<FreezeInst>(Usr)) {
+ ValueLatticeElement OpLatticeVal =
+ *getValueFromCondition(Usr->getOperand(0), Condition,
+ isTrueDest, /*UseBlockValue*/ false);
+
+ if (isa<FreezeInst>(Usr) || !OpLatticeVal.isConstantRange())
+ return OpLatticeVal;
+
+ const unsigned ResultBitWidth =
+ Usr->getType()->getScalarSizeInBits();
+ if (auto *Trunc = dyn_cast<TruncInst>(Usr))
+ return ValueLatticeElement::getRange(
+ OpLatticeVal.getConstantRange().truncate(
+ ResultBitWidth, Trunc->getNoWrapKind()));
+
+ return ValueLatticeElement::getRange(
+ OpLatticeVal.getConstantRange().castOp(
+ cast<CastInst>(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..fd6722cfc1671 100644
--- a/llvm/test/Transforms/CorrelatedValuePropagation/range.ll
+++ b/llvm/test/Transforms/CorrelatedValuePropagation/range.ll
@@ -1235,6 +1235,150 @@ 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 0, 98) 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 ult i8 [[A]], 98
+; 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 ult i8 %a, 98
+ 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
+}
+
+define i8 @return_range_for_edge_value_freeze(i8 %a) {
+; CHECK-LABEL: define range(i8 0, 98) i8 @return_range_for_edge_value_freeze(
+; CHECK-SAME: i8 [[A:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[B:%.*]] = freeze i8 [[A]]
+; 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 i8 [[B]]
+;
+entry:
+ %b = freeze i8 %a
+ br label %dispatch
+
+dispatch:
+ %cmp = icmp ult i8 %a, 98
+ 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)
|
I needs to look in to why there is failures in dtcxzyw/llvm-opt-benchmark#2768 |
98aa2b2
to
3c4ac99
Compare
3c4ac99
to
7cce3e7
Compare
limited the cast to trunc, zext and sext as that is what I have tested |
br label %dispatch | ||
|
||
dispatch: | ||
%cmp = icmp ult i8 %a, 98 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
InstCombine canonicalizes all uses of %a
to %b
. Can you put freeze-related changes into a separate PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good catch there was no changes for freeze when I did a benchmark run I only added it as it was listed in isOperationFoldable. but is dropped now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes w/o freeze look good.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
…e in getEdgeValueLocal.
Closes #161367. In #157614, we ignored cases where OpLatticeVal might be a constant or notconstant. Directly returning the result causes a type mismatch. I apologize for the oversight in the previous code review. This patch applies the cast op to constants. For notconstant value lattices, I'd leave it as a todo (it is similar to the constant case, except for trunc without nsw/nuw).
… (#161410) Closes llvm/llvm-project#161367. In llvm/llvm-project#157614, we ignored cases where OpLatticeVal might be a constant or notconstant. Directly returning the result causes a type mismatch. I apologize for the oversight in the previous code review. This patch applies the cast op to constants. For notconstant value lattices, I'd leave it as a todo (it is similar to the constant case, except for trunc without nsw/nuw).
Closes llvm#161367. In llvm#157614, we ignored cases where OpLatticeVal might be a constant or notconstant. Directly returning the result causes a type mismatch. I apologize for the oversight in the previous code review. This patch applies the cast op to constants. For notconstant value lattices, I'd leave it as a todo (it is similar to the constant case, except for trunc without nsw/nuw).
proof: https://alive2.llvm.org/ce/z/8emkHY