-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[InstCombine] Fold trunc nuw i1 to false when dominated by icmp. #151961
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
|
@llvm/pr-subscribers-llvm-transforms Author: Andreas Jonson (andjo403) ChangesProof: https://alive2.llvm.org/ce/z/4BOiFF Full diff: https://github.com/llvm/llvm-project/pull/151961.diff 2 Files Affected:
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
index a43a6ee1f58b0..8529d7b30b56d 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
@@ -951,6 +951,38 @@ Instruction *InstCombinerImpl::visitTrunc(TruncInst &Trunc) {
}
}
+ // Fold Trunc nuw i1 With Dominating ICmp
+ if (DestWidth == 1 && Trunc.hasNoUnsignedWrap()) {
+ auto HandleDomCond = [&](ICmpInst::Predicate DomPred,
+ const APInt *DomC) -> Instruction * {
+ ConstantRange DominatingCR =
+ ConstantRange::makeExactICmpRegion(DomPred, *DomC);
+ if (!DominatingCR.contains(APInt(SrcWidth, 1)))
+ return replaceInstUsesWith(Trunc, Builder.getFalse());
+ return nullptr;
+ };
+
+ for (BranchInst *BI : DC.conditionsFor(Src)) {
+ CmpPredicate DomPred;
+ const APInt *DomC;
+ if (!match(BI->getCondition(),
+ m_ICmp(DomPred, m_Specific(Src), m_APInt(DomC))))
+ continue;
+
+ BasicBlockEdge Edge0(BI->getParent(), BI->getSuccessor(0));
+ if (DT.dominates(Edge0, Trunc.getParent())) {
+ if (auto *V = HandleDomCond(DomPred, DomC))
+ return V;
+ } else {
+ BasicBlockEdge Edge1(BI->getParent(), BI->getSuccessor(1));
+ if (DT.dominates(Edge1, Trunc.getParent()))
+ if (auto *V =
+ HandleDomCond(CmpInst::getInversePredicate(DomPred), DomC))
+ return V;
+ }
+ }
+ }
+
if (DestWidth == 1 &&
(Trunc.hasNoUnsignedWrap() || Trunc.hasNoSignedWrap()) &&
isKnownNonZero(Src, SQ.getWithInstruction(&Trunc)))
diff --git a/llvm/test/Transforms/InstCombine/trunc.ll b/llvm/test/Transforms/InstCombine/trunc.ll
index dfe9d941f840c..a03aa88063247 100644
--- a/llvm/test/Transforms/InstCombine/trunc.ll
+++ b/llvm/test/Transforms/InstCombine/trunc.ll
@@ -1218,3 +1218,143 @@ define i2 @neg_trunc_nsw_i2_non_zero(i8 %1) {
%ret = trunc nsw i8 %1 to i2
ret i2 %ret
}
+
+define i1 @trunc_nuw_i1_dominating_icmp_ne_1(i8 %x) {
+; CHECK-LABEL: @trunc_nuw_i1_dominating_icmp_ne_1(
+; CHECK-NEXT: [[ICMP_NOT:%.*]] = icmp eq i8 [[X:%.*]], 1
+; CHECK-NEXT: br i1 [[ICMP_NOT]], label [[BB2:%.*]], label [[BB1:%.*]]
+; CHECK: bb1:
+; CHECK-NEXT: ret i1 false
+; CHECK: bb2:
+; CHECK-NEXT: ret i1 true
+;
+ %icmp = icmp ne i8 %x, 1
+ br i1 %icmp, label %bb1, label %bb2
+bb1:
+ %ret1 = trunc nuw i8 %x to i1
+ ret i1 %ret1
+bb2:
+ %ret2 = trunc nuw i8 %x to i1
+ ret i1 %ret2
+}
+
+define i1 @trunc_nuw_i1_dominating_icmp_eq_1(i8 %x) {
+; CHECK-LABEL: @trunc_nuw_i1_dominating_icmp_eq_1(
+; CHECK-NEXT: [[ICMP:%.*]] = icmp eq i8 [[X:%.*]], 1
+; CHECK-NEXT: br i1 [[ICMP]], label [[BB1:%.*]], label [[BB2:%.*]]
+; CHECK: bb1:
+; CHECK-NEXT: ret i1 true
+; CHECK: bb2:
+; CHECK-NEXT: ret i1 false
+;
+ %icmp = icmp eq i8 %x, 1
+ br i1 %icmp, label %bb1, label %bb2
+bb1:
+ %ret1 = trunc nuw i8 %x to i1
+ ret i1 %ret1
+bb2:
+ %ret2 = trunc nuw i8 %x to i1
+ ret i1 %ret2
+}
+
+define i1 @trunc_nuw_i1_dominating_icmp_ne_0(i8 %x) {
+; CHECK-LABEL: @trunc_nuw_i1_dominating_icmp_ne_0(
+; CHECK-NEXT: [[ICMP_NOT:%.*]] = icmp eq i8 [[X:%.*]], 0
+; CHECK-NEXT: br i1 [[ICMP_NOT]], label [[BB2:%.*]], label [[BB1:%.*]]
+; CHECK: bb1:
+; CHECK-NEXT: ret i1 true
+; CHECK: bb2:
+; CHECK-NEXT: ret i1 false
+;
+ %icmp = icmp ne i8 %x, 0
+ br i1 %icmp, label %bb1, label %bb2
+bb1:
+ %ret1 = trunc nuw i8 %x to i1
+ ret i1 %ret1
+bb2:
+ %ret2 = trunc nuw i8 %x to i1
+ ret i1 %ret2
+}
+
+define i1 @trunc_nuw_i1_dominating_icmp_eq_0(i8 %x) {
+; CHECK-LABEL: @trunc_nuw_i1_dominating_icmp_eq_0(
+; CHECK-NEXT: [[ICMP:%.*]] = icmp eq i8 [[X:%.*]], 0
+; CHECK-NEXT: br i1 [[ICMP]], label [[BB1:%.*]], label [[BB2:%.*]]
+; CHECK: bb1:
+; CHECK-NEXT: ret i1 false
+; CHECK: bb2:
+; CHECK-NEXT: ret i1 true
+;
+ %icmp = icmp eq i8 %x, 0
+ br i1 %icmp, label %bb1, label %bb2
+bb1:
+ %ret1 = trunc nuw i8 %x to i1
+ ret i1 %ret1
+bb2:
+ %ret2 = trunc nuw i8 %x to i1
+ ret i1 %ret2
+}
+
+define i1 @neg_trunc_i1_dominating_icmp_ne_1(i8 %x) {
+; CHECK-LABEL: @neg_trunc_i1_dominating_icmp_ne_1(
+; CHECK-NEXT: [[ICMP_NOT:%.*]] = icmp eq i8 [[X:%.*]], 1
+; CHECK-NEXT: br i1 [[ICMP_NOT]], label [[BB2:%.*]], label [[BB1:%.*]]
+; CHECK: bb1:
+; CHECK-NEXT: [[RET1:%.*]] = trunc i8 [[X]] to i1
+; CHECK-NEXT: ret i1 [[RET1]]
+; CHECK: bb2:
+; CHECK-NEXT: ret i1 true
+;
+ %icmp = icmp ne i8 %x, 1
+ br i1 %icmp, label %bb1, label %bb2
+bb1:
+ %ret1 = trunc i8 %x to i1
+ ret i1 %ret1
+bb2:
+ %ret2 = trunc i8 %x to i1
+ ret i1 %ret2
+}
+
+define i2 @neg_trunc_nuw_i2_dominating_icmp_ne_1(i8 %x) {
+; CHECK-LABEL: @neg_trunc_nuw_i2_dominating_icmp_ne_1(
+; CHECK-NEXT: [[ICMP_NOT:%.*]] = icmp eq i8 [[X:%.*]], 1
+; CHECK-NEXT: br i1 [[ICMP_NOT]], label [[BB2:%.*]], label [[BB1:%.*]]
+; CHECK: bb1:
+; CHECK-NEXT: [[RET1:%.*]] = trunc nuw i8 [[X]] to i2
+; CHECK-NEXT: ret i2 [[RET1]]
+; CHECK: bb2:
+; CHECK-NEXT: ret i2 1
+;
+ %icmp = icmp ne i8 %x, 1
+ br i1 %icmp, label %bb1, label %bb2
+bb1:
+ %ret1 = trunc nuw i8 %x to i2
+ ret i2 %ret1
+bb2:
+ %ret2 = trunc nuw i8 %x to i2
+ ret i2 %ret2
+}
+
+define i1 @neg_trunc_nuw_i1_not_dominating_icmp_ne_1(i8 %x, i1 %y) {
+; CHECK-LABEL: @neg_trunc_nuw_i1_not_dominating_icmp_ne_1(
+; CHECK-NEXT: br i1 [[Y:%.*]], label [[BB1:%.*]], label [[BB0:%.*]]
+; CHECK: bb0:
+; CHECK-NEXT: [[ICMP_NOT:%.*]] = icmp eq i8 [[X:%.*]], 1
+; CHECK-NEXT: br i1 [[ICMP_NOT]], label [[BB2:%.*]], label [[BB1]]
+; CHECK: bb1:
+; CHECK-NEXT: [[RET1:%.*]] = trunc nuw i8 [[X]] to i1
+; CHECK-NEXT: ret i1 [[RET1]]
+; CHECK: bb2:
+; CHECK-NEXT: ret i1 true
+;
+ br i1 %y, label %bb1, label %bb0
+bb0:
+ %icmp = icmp ne i8 %x, 1
+ br i1 %icmp, label %bb1, label %bb2
+bb1:
+ %ret1 = trunc nuw i8 %x to i1
+ ret i1 %ret1
+bb2:
+ %ret2 = trunc nuw i8 %x to i1
+ ret i1 %ret2
+}
|
|
|
||
| if (DestWidth == 1 && | ||
| (Trunc.hasNoUnsignedWrap() || Trunc.hasNoSignedWrap()) && | ||
| isKnownNonZero(Src, SQ.getWithInstruction(&Trunc))) |
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.
only added fold to false as the fold to true is handled here
dtcxzyw
left a comment
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.
LG.
| } | ||
| } | ||
|
|
||
| // Fold Trunc nuw i1 With Dominating ICmp |
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.
| // Fold Trunc nuw i1 With Dominating ICmp | |
| // Fold trunc nuw i1 with dominating icmp. |
nikic
left a comment
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.
This does not look like a great fit for InstCombine. Would (IP)SCCP be able to handle this if we teach ConstantRange::truncate() to make use of the nuw flag?
It is also required by #110511 (comment). |
|
Can this be closed now that the SCCP support has landed? |
|
this PR still gives changes in the llvm-opt-benchmark when I run it locally after the SCCP PR was merged. I can try to look at why SCCP is not enough. background for why I added this here was that I fund this fold for icmp and was thinking of adding trunc nuw support there and was not able to find something similar for trunc. llvm-project/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp Lines 1407 to 1480 in 0561ff6
|
|
forgot to mention that I tried to run with #153003 applied also but there still was 15 files changed have not looked if it was the same changes |
|
hmm maybe it was git that tricked me, it was not happy with more then 10k changed files, when I checked bench/ruff-rs/optimized/8dg5gv1ul0w7vccunqd3ii3jp.ll with this PR vs #153003 there was only changes of names on variables so that PR helps a least. |
|
seems like most was solved by #153003 |
Proof: https://alive2.llvm.org/ce/z/4BOiFF