[ValueTracking] Handle icmp pred (trunc X), C in computeKnownBitsFromCmp#82803
Conversation
|
@llvm/pr-subscribers-llvm-transforms Author: Yingwei Zheng (dtcxzyw) ChangesThis patch handles the pattern Full diff: https://github.com/llvm/llvm-project/pull/82803.diff 3 Files Affected:
diff --git a/llvm/lib/Analysis/DomConditionCache.cpp b/llvm/lib/Analysis/DomConditionCache.cpp
index 274f3ff44b2a6f..b1d9cdff943b80 100644
--- a/llvm/lib/Analysis/DomConditionCache.cpp
+++ b/llvm/lib/Analysis/DomConditionCache.cpp
@@ -27,7 +27,8 @@ static void findAffectedValues(Value *Cond,
// Peek through unary operators to find the source of the condition.
Value *Op;
- if (match(I, m_PtrToInt(m_Value(Op)))) {
+ if (match(I,
+ m_CombineOr(m_PtrToInt(m_Value(Op)), m_Trunc(m_Value(Op))))) {
if (isa<Instruction>(Op) || isa<Argument>(Op))
Affected.push_back(Op);
}
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 04f317228b3ea7..dbac5bc8aa7626 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -717,10 +717,22 @@ static void computeKnownBitsFromCond(const Value *V, Value *Cond,
computeKnownBitsFromCond(V, B, Known, Depth + 1, SQ, Invert);
}
- if (auto *Cmp = dyn_cast<ICmpInst>(Cond))
- computeKnownBitsFromCmp(
- V, Invert ? Cmp->getInversePredicate() : Cmp->getPredicate(),
- Cmp->getOperand(0), Cmp->getOperand(1), Known, SQ);
+ if (auto *Cmp = dyn_cast<ICmpInst>(Cond)) {
+ ICmpInst::Predicate Pred =
+ Invert ? Cmp->getInversePredicate() : Cmp->getPredicate();
+ Value *LHS = Cmp->getOperand(0);
+ Value *RHS = Cmp->getOperand(1);
+
+ // Handle icmp pred (trunc V), C
+ if (match(LHS, m_Trunc(m_Specific(V)))) {
+ KnownBits DstKnown(LHS->getType()->getScalarSizeInBits());
+ computeKnownBitsFromCmp(LHS, Pred, LHS, RHS, DstKnown, SQ);
+ Known = Known.unionWith(DstKnown.anyext(Known.getBitWidth()));
+ return;
+ }
+
+ computeKnownBitsFromCmp(V, Pred, LHS, RHS, Known, SQ);
+ }
}
void llvm::computeKnownBitsFromContext(const Value *V, KnownBits &Known,
diff --git a/llvm/test/Transforms/InstCombine/known-bits.ll b/llvm/test/Transforms/InstCombine/known-bits.ll
index 246579cc4cd0c0..3581256131a270 100644
--- a/llvm/test/Transforms/InstCombine/known-bits.ll
+++ b/llvm/test/Transforms/InstCombine/known-bits.ll
@@ -284,5 +284,129 @@ exit:
ret i8 %or2
}
+define i32 @test_icmp_trunc1(i32 %x){
+; CHECK-LABEL: @test_icmp_trunc1(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[Y:%.*]] = trunc i32 [[X:%.*]] to i16
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[Y]], 7
+; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
+; CHECK: then:
+; CHECK-NEXT: ret i32 7
+; CHECK: else:
+; CHECK-NEXT: ret i32 0
+;
+entry:
+ %y = trunc i32 %x to i16
+ %cmp = icmp eq i16 %y, 7
+ br i1 %cmp, label %then, label %else
+then:
+ %z = and i32 %x, 15
+ ret i32 %z
+else:
+ ret i32 0
+}
+
+define i64 @test_icmp_trunc2(i64 %x) {
+; CHECK-LABEL: @test_icmp_trunc2(
+; CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[X:%.*]] to i32
+; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[CONV]], 12
+; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK: if.then:
+; CHECK-NEXT: [[SEXT:%.*]] = and i64 [[X]], 2147483647
+; CHECK-NEXT: ret i64 [[SEXT]]
+; CHECK: if.else:
+; CHECK-NEXT: ret i64 0
+;
+ %conv = trunc i64 %x to i32
+ %cmp = icmp sgt i32 %conv, 12
+ br i1 %cmp, label %if.then, label %if.else
+
+if.then:
+ %sext = shl i64 %x, 32
+ %ret = ashr exact i64 %sext, 32
+ ret i64 %ret
+if.else:
+ ret i64 0
+}
+
+define i64 @test_icmp_trunc3(i64 %n) {
+; CHECK-LABEL: @test_icmp_trunc3(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[N:%.*]] to i32
+; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[CONV]], 96
+; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK: if.then:
+; CHECK-NEXT: [[RET:%.*]] = and i64 [[N]], 127
+; CHECK-NEXT: ret i64 [[RET]]
+; CHECK: if.else:
+; CHECK-NEXT: ret i64 0
+;
+entry:
+ %conv = trunc i64 %n to i32
+ %cmp = icmp ult i32 %conv, 96
+ br i1 %cmp, label %if.then, label %if.else
+
+if.then:
+ %ret = and i64 %n, 4294967295
+ ret i64 %ret
+
+if.else:
+ ret i64 0
+}
+
+define i8 @test_icmp_trunc4(i64 %n) {
+; CHECK-LABEL: @test_icmp_trunc4(
+; CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[N:%.*]] to i32
+; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[CONV]], 10
+; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK: if.then:
+; CHECK-NEXT: [[CONV2:%.*]] = trunc i64 [[N]] to i8
+; CHECK-NEXT: [[ADD:%.*]] = or disjoint i8 [[CONV2]], 48
+; CHECK-NEXT: ret i8 [[ADD]]
+; CHECK: if.else:
+; CHECK-NEXT: ret i8 0
+;
+ %conv = trunc i64 %n to i32
+ %cmp = icmp ult i32 %conv, 10
+ br i1 %cmp, label %if.then, label %if.else
+
+if.then:
+ %conv2 = trunc i64 %n to i8
+ %add = add i8 %conv2, 48
+ ret i8 %add
+
+if.else:
+ ret i8 0
+}
+
+define i64 @test_icmp_trunc5(i64 %n) {
+; CHECK-LABEL: @test_icmp_trunc5(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[SHR:%.*]] = ashr i64 [[N:%.*]], 47
+; CHECK-NEXT: [[CONV1:%.*]] = trunc i64 [[SHR]] to i32
+; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[CONV1]], -13
+; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK: if.then:
+; CHECK-NEXT: [[TMP0:%.*]] = and i64 [[SHR]], 15
+; CHECK-NEXT: [[NOT:%.*]] = xor i64 [[TMP0]], 15
+; CHECK-NEXT: ret i64 [[NOT]]
+; CHECK: if.else:
+; CHECK-NEXT: ret i64 13
+;
+entry:
+ %shr = ashr i64 %n, 47
+ %conv1 = trunc i64 %shr to i32
+ %cmp = icmp ugt i32 %conv1, -13
+ br i1 %cmp, label %if.then, label %if.else
+
+if.then:
+ %and = and i64 %shr, 4294967295
+ %not = xor i64 %and, 4294967295
+ ret i64 %not
+
+if.else:
+ ret i64 13
+}
+
declare void @use(i1)
declare void @sink(i8)
|
|
@llvm/pr-subscribers-llvm-analysis Author: Yingwei Zheng (dtcxzyw) ChangesThis patch handles the pattern Full diff: https://github.com/llvm/llvm-project/pull/82803.diff 3 Files Affected:
diff --git a/llvm/lib/Analysis/DomConditionCache.cpp b/llvm/lib/Analysis/DomConditionCache.cpp
index 274f3ff44b2a6f..b1d9cdff943b80 100644
--- a/llvm/lib/Analysis/DomConditionCache.cpp
+++ b/llvm/lib/Analysis/DomConditionCache.cpp
@@ -27,7 +27,8 @@ static void findAffectedValues(Value *Cond,
// Peek through unary operators to find the source of the condition.
Value *Op;
- if (match(I, m_PtrToInt(m_Value(Op)))) {
+ if (match(I,
+ m_CombineOr(m_PtrToInt(m_Value(Op)), m_Trunc(m_Value(Op))))) {
if (isa<Instruction>(Op) || isa<Argument>(Op))
Affected.push_back(Op);
}
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 04f317228b3ea7..dbac5bc8aa7626 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -717,10 +717,22 @@ static void computeKnownBitsFromCond(const Value *V, Value *Cond,
computeKnownBitsFromCond(V, B, Known, Depth + 1, SQ, Invert);
}
- if (auto *Cmp = dyn_cast<ICmpInst>(Cond))
- computeKnownBitsFromCmp(
- V, Invert ? Cmp->getInversePredicate() : Cmp->getPredicate(),
- Cmp->getOperand(0), Cmp->getOperand(1), Known, SQ);
+ if (auto *Cmp = dyn_cast<ICmpInst>(Cond)) {
+ ICmpInst::Predicate Pred =
+ Invert ? Cmp->getInversePredicate() : Cmp->getPredicate();
+ Value *LHS = Cmp->getOperand(0);
+ Value *RHS = Cmp->getOperand(1);
+
+ // Handle icmp pred (trunc V), C
+ if (match(LHS, m_Trunc(m_Specific(V)))) {
+ KnownBits DstKnown(LHS->getType()->getScalarSizeInBits());
+ computeKnownBitsFromCmp(LHS, Pred, LHS, RHS, DstKnown, SQ);
+ Known = Known.unionWith(DstKnown.anyext(Known.getBitWidth()));
+ return;
+ }
+
+ computeKnownBitsFromCmp(V, Pred, LHS, RHS, Known, SQ);
+ }
}
void llvm::computeKnownBitsFromContext(const Value *V, KnownBits &Known,
diff --git a/llvm/test/Transforms/InstCombine/known-bits.ll b/llvm/test/Transforms/InstCombine/known-bits.ll
index 246579cc4cd0c0..3581256131a270 100644
--- a/llvm/test/Transforms/InstCombine/known-bits.ll
+++ b/llvm/test/Transforms/InstCombine/known-bits.ll
@@ -284,5 +284,129 @@ exit:
ret i8 %or2
}
+define i32 @test_icmp_trunc1(i32 %x){
+; CHECK-LABEL: @test_icmp_trunc1(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[Y:%.*]] = trunc i32 [[X:%.*]] to i16
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[Y]], 7
+; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
+; CHECK: then:
+; CHECK-NEXT: ret i32 7
+; CHECK: else:
+; CHECK-NEXT: ret i32 0
+;
+entry:
+ %y = trunc i32 %x to i16
+ %cmp = icmp eq i16 %y, 7
+ br i1 %cmp, label %then, label %else
+then:
+ %z = and i32 %x, 15
+ ret i32 %z
+else:
+ ret i32 0
+}
+
+define i64 @test_icmp_trunc2(i64 %x) {
+; CHECK-LABEL: @test_icmp_trunc2(
+; CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[X:%.*]] to i32
+; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[CONV]], 12
+; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK: if.then:
+; CHECK-NEXT: [[SEXT:%.*]] = and i64 [[X]], 2147483647
+; CHECK-NEXT: ret i64 [[SEXT]]
+; CHECK: if.else:
+; CHECK-NEXT: ret i64 0
+;
+ %conv = trunc i64 %x to i32
+ %cmp = icmp sgt i32 %conv, 12
+ br i1 %cmp, label %if.then, label %if.else
+
+if.then:
+ %sext = shl i64 %x, 32
+ %ret = ashr exact i64 %sext, 32
+ ret i64 %ret
+if.else:
+ ret i64 0
+}
+
+define i64 @test_icmp_trunc3(i64 %n) {
+; CHECK-LABEL: @test_icmp_trunc3(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[N:%.*]] to i32
+; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[CONV]], 96
+; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK: if.then:
+; CHECK-NEXT: [[RET:%.*]] = and i64 [[N]], 127
+; CHECK-NEXT: ret i64 [[RET]]
+; CHECK: if.else:
+; CHECK-NEXT: ret i64 0
+;
+entry:
+ %conv = trunc i64 %n to i32
+ %cmp = icmp ult i32 %conv, 96
+ br i1 %cmp, label %if.then, label %if.else
+
+if.then:
+ %ret = and i64 %n, 4294967295
+ ret i64 %ret
+
+if.else:
+ ret i64 0
+}
+
+define i8 @test_icmp_trunc4(i64 %n) {
+; CHECK-LABEL: @test_icmp_trunc4(
+; CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[N:%.*]] to i32
+; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[CONV]], 10
+; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK: if.then:
+; CHECK-NEXT: [[CONV2:%.*]] = trunc i64 [[N]] to i8
+; CHECK-NEXT: [[ADD:%.*]] = or disjoint i8 [[CONV2]], 48
+; CHECK-NEXT: ret i8 [[ADD]]
+; CHECK: if.else:
+; CHECK-NEXT: ret i8 0
+;
+ %conv = trunc i64 %n to i32
+ %cmp = icmp ult i32 %conv, 10
+ br i1 %cmp, label %if.then, label %if.else
+
+if.then:
+ %conv2 = trunc i64 %n to i8
+ %add = add i8 %conv2, 48
+ ret i8 %add
+
+if.else:
+ ret i8 0
+}
+
+define i64 @test_icmp_trunc5(i64 %n) {
+; CHECK-LABEL: @test_icmp_trunc5(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[SHR:%.*]] = ashr i64 [[N:%.*]], 47
+; CHECK-NEXT: [[CONV1:%.*]] = trunc i64 [[SHR]] to i32
+; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[CONV1]], -13
+; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK: if.then:
+; CHECK-NEXT: [[TMP0:%.*]] = and i64 [[SHR]], 15
+; CHECK-NEXT: [[NOT:%.*]] = xor i64 [[TMP0]], 15
+; CHECK-NEXT: ret i64 [[NOT]]
+; CHECK: if.else:
+; CHECK-NEXT: ret i64 13
+;
+entry:
+ %shr = ashr i64 %n, 47
+ %conv1 = trunc i64 %shr to i32
+ %cmp = icmp ugt i32 %conv1, -13
+ br i1 %cmp, label %if.then, label %if.else
+
+if.then:
+ %and = and i64 %shr, 4294967295
+ %not = xor i64 %and, 4294967295
+ ret i64 %not
+
+if.else:
+ ret i64 13
+}
+
declare void @use(i1)
declare void @sink(i8)
|
| Known = Known.unionWith(DstKnown.anyext(Known.getBitWidth())); | ||
| return; | ||
| } | ||
|
|
There was a problem hiding this comment.
Code all looks correct, i'm wondering, however, if this may become bugprone given the code "distance" between adding affected ops and actually supporting them.
Think there is any convenient way to fix that?
db1fc57 to
359c40a
Compare
359c40a to
114a7df
Compare
|
Hm, I wonder why this causes code size regressions, especially on mafft (https://llvm-compile-time-tracker.com/compare.php?from=0cbbcf1ef006ce13a1fa94960067723982ae955a&to=3589cacfa8da89b9b5051e4dba659caa575e6b3f&stat=size-text). |
I will add CTMark to my benchmark. |
…ownBitsFromCmp` (llvm#82803)" This reverts commit 3589cac.
Reverting this patch cannot improve the code size. |
…125414) This patch extends #82803 to further infer high bits when `nuw` is set. It will save some and instructions on induction variables. No real-world benefit is observed for `trunc nsw`. Alive2: https://alive2.llvm.org/ce/z/j-YFvt
…mICmpCond` (#125414) This patch extends llvm/llvm-project#82803 to further infer high bits when `nuw` is set. It will save some and instructions on induction variables. No real-world benefit is observed for `trunc nsw`. Alive2: https://alive2.llvm.org/ce/z/j-YFvt
…(#125414) This patch extends llvm/llvm-project#82803 to further infer high bits when `nuw` is set. It will save some and instructions on induction variables. No real-world benefit is observed for `trunc nsw`. Alive2: https://alive2.llvm.org/ce/z/j-YFvt
…(#125414) This patch extends llvm/llvm-project#82803 to further infer high bits when `nuw` is set. It will save some and instructions on induction variables. No real-world benefit is observed for `trunc nsw`. Alive2: https://alive2.llvm.org/ce/z/j-YFvt
This patch handles the pattern
icmp pred (trunc X), CincomputeKnownBitsFromCmpto infer low bits ofXfrom dominating conditions.