X > C1 && X < C2 is canonicalized to X + C3 < C4, so look through
X + C to try and find compares.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp | ||
---|---|---|
2833 | What is the motivating test case for this? And what information are we losing? This looks very dubious. |
Rebase
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp | ||
---|---|---|
2833 |
check_ucmp_range_from0_assumed and check_ucmp_range_from0_and_abs both rely on it. Diff w.o is roughly: define i1 @check_ucmp_range_from0_assumed(i8 %x, i8 %y) { ; CHECK-LABEL: @check_ucmp_range_from0_assumed( -; CHECK-NEXT: [[UB:%.*]] = add i8 [[X:%.*]], -1 -; CHECK-NEXT: [[NE:%.*]] = icmp ult i8 [[UB]], 14 +; CHECK-NEXT: [[NE:%.*]] = icmp ult i8 [[X:%.*]], 15 ; CHECK-NEXT: call void @llvm.assume(i1 [[NE]]) ; CHECK-NEXT: [[CMP0:%.*]] = icmp ugt i8 [[X]], [[Y:%.*]] -; CHECK-NEXT: ret i1 [[CMP0]] +; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[Y]], 0 +; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP0]], [[CMP1]] +; CHECK-NEXT: ret i1 [[R]] and define i1 @check_ucmp_range_from0_and_abs(i8 %x, i8 %y) { ; CHECK-LABEL: @check_ucmp_range_from0_and_abs( ; CHECK-NEXT: [[X1:%.*]] = and i8 [[X:%.*]], 123 -; CHECK-NEXT: [[TMP1:%.*]] = add nsw i8 [[X1]], -1 -; CHECK-NEXT: [[NE:%.*]] = icmp ult i8 [[TMP1]], 14 +; CHECK-NEXT: [[NE:%.*]] = icmp ult i8 [[X1]], 15 ; CHECK-NEXT: call void @llvm.assume(i1 [[NE]]) ; CHECK-NEXT: [[CMP0:%.*]] = icmp ugt i8 [[X]], [[Y:%.*]] -; CHECK-NEXT: ret i1 [[CMP0]] +; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[Y]], 0 +; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP0]], [[CMP1]] +; CHECK-NEXT: ret i1 [[R]] ; The expression X - 1 u< C cannot be true for X == 0, the expression X u< C can be true for X == 0 so when doing the dom analysis if we make the transform we end up unable to prove about X != 0. Its a but circular, i.e we use isKnownNonZero(X) which is true, make the change, then at a later use of X are unable to reprove isKnownNonZero(X) |
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp | ||
---|---|---|
2833 | Why isn't this covered by ephemeral value handling? That is supposed to prevent an assume from simplifying its own condition. |
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp | ||
---|---|---|
2833 |
I don't know, what file should I look at? My preference would be to keep as is and add TODO to see if this can be handled by ephemeral value handling. But can also do the inverse (remove this and add TODO to fix by handling in ephemeral value handling). |
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp | ||
---|---|---|
2833 | See isEphemeralValueOf() used by isValidAssumeForContext() in ValueTracking. |
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp | ||
---|---|---|
2833 |
So I'm not sure what you're getting at with re:"Why isn't this covered by ephemeral value handling?", the issue isn't that the assume doesn't check the expression, the issue is that after we visit the X0 + 1 u< C0 the new expression X1 u<= C1 no longer exclude zero. Do isEphemeralValueOf` exclude the instruction from going the instcombine? If not I don't see how it could help avoid this case. |
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp | ||
---|---|---|
2833 |
| |
2833 |
Sorry ignore, accidentally resubmitted. |
What is the motivating test case for this? And what information are we losing? This looks very dubious.