From 6bab5151faec55af6f360ea575338fd82aa89547 Mon Sep 17 00:00:00 2001 From: Andreas Jonson Date: Wed, 9 Apr 2025 21:33:24 +0200 Subject: [PATCH] [InstCombine] Simplify phi using KnownBits of condition Simplify the arms of a phi based on the KnownBits implied by the condition for the predecessor basic block. --- .../Transforms/InstCombine/InstCombinePHI.cpp | 38 +++++++++++++++++++ .../fold-aggregate-reconstruction.ll | 2 +- .../Transforms/InstCombine/known-phi-br.ll | 9 ++--- .../Transforms/LoopVectorize/induction.ll | 2 +- llvm/test/Transforms/PGOProfile/chr.ll | 2 +- 5 files changed, 44 insertions(+), 9 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp b/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp index 80308bf92dbbc..cd6e189c2a906 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp @@ -1625,6 +1625,44 @@ Instruction *InstCombinerImpl::visitPHINode(PHINode &PN) { return replaceInstUsesWith(PN, &IdenticalPN); } + if (PN.getType()->isIntegerTy()) { + BasicBlock *PNBB = PN.getParent(); + KnownBits Known(PN.getType()->getScalarSizeInBits()); + bool MadeChange = false; + for (unsigned I = 0, E = PN.getNumIncomingValues(); I != E; ++I) { + Value *V = PN.getIncomingValue(I); + if (isa(V)) + continue; + + ArrayRef BRs = SQ.DC->conditionsFor(V); + if (BRs.empty()) + continue; + + Known.resetAll(); + Instruction *CtxI = PN.getIncomingBlock(I)->getTerminator(); + SimplifyQuery Q = SQ.getWithInstruction(CtxI); + BranchInst *BI = dyn_cast(CtxI); + if (BI && BI->isConditional() && llvm::is_contained(BRs, BI)) { + CondContext CC(BI->getCondition()); + CC.AffectedValues.insert(V); + if (BI->getSuccessor(1) == PNBB) + CC.Invert = true; + llvm::computeKnownBits(V, Known, /* Depth */ 0, + Q.getWithCondContext(CC)); + } else { + llvm::computeKnownBits(V, Known, /* Depth */ 0, Q); + } + + if (Known.isConstant()) { + replaceOperand(PN, I, + ConstantInt::get(V->getType(), Known.getConstant())); + MadeChange = true; + } + } + if (MadeChange) + return &PN; + } + // If this is an integer PHI and we know that it has an illegal type, see if // it is only used by trunc or trunc(lshr) operations. If so, we split the // PHI into the various pieces being extracted. This sort of thing is diff --git a/llvm/test/Transforms/InstCombine/fold-aggregate-reconstruction.ll b/llvm/test/Transforms/InstCombine/fold-aggregate-reconstruction.ll index eb5f96d8f942d..ed1247d9aec5b 100644 --- a/llvm/test/Transforms/InstCombine/fold-aggregate-reconstruction.ll +++ b/llvm/test/Transforms/InstCombine/fold-aggregate-reconstruction.ll @@ -178,7 +178,7 @@ define {ptr, i64} @test4(i1 %cond1, i1 %cond2, ptr %p1, ptr %p2) { ; CHECK-NEXT: br i1 [[COND3_NOT]], label %[[EXIT]], label %[[BBB4]] ; CHECK: [[EXIT]]: ; CHECK-NEXT: [[VAL1:%.*]] = phi ptr [ [[VAL11]], %[[BBB2]] ], [ [[VAL21]], %[[BBB3]] ], [ [[VAL31]], %[[BBB4]] ] -; CHECK-NEXT: [[VAL2:%.*]] = phi i64 [ [[VAL12]], %[[BBB2]] ], [ [[VAL22]], %[[BBB3]] ], [ [[VAL32]], %[[BBB4]] ] +; CHECK-NEXT: [[VAL2:%.*]] = phi i64 [ [[VAL12]], %[[BBB2]] ], [ [[VAL22]], %[[BBB3]] ], [ 0, %[[BBB4]] ] ; CHECK-NEXT: [[TMP:%.*]] = insertvalue { ptr, i64 } poison, ptr [[VAL1]], 0 ; CHECK-NEXT: [[RES:%.*]] = insertvalue { ptr, i64 } [[TMP]], i64 [[VAL2]], 1 ; CHECK-NEXT: ret { ptr, i64 } [[RES]] diff --git a/llvm/test/Transforms/InstCombine/known-phi-br.ll b/llvm/test/Transforms/InstCombine/known-phi-br.ll index e9463b2fc65cc..2c8cfa30298be 100644 --- a/llvm/test/Transforms/InstCombine/known-phi-br.ll +++ b/llvm/test/Transforms/InstCombine/known-phi-br.ll @@ -15,8 +15,7 @@ define i64 @limit_i64_eq_7(i64 %x) { ; CHECK: body: ; CHECK-NEXT: br label [[END]] ; CHECK: end: -; CHECK-NEXT: [[RES:%.*]] = phi i64 [ [[X]], [[ENTRY:%.*]] ], [ 7, [[BODY]] ] -; CHECK-NEXT: ret i64 [[RES]] +; CHECK-NEXT: ret i64 7 ; entry: %cmp = icmp eq i64 %x, 7 @@ -36,8 +35,7 @@ define i64 @limit_i64_eq_7_commuted(i64 %x) { ; CHECK: body: ; CHECK-NEXT: br label [[BODY]] ; CHECK: end: -; CHECK-NEXT: [[RES:%.*]] = phi i64 [ [[X]], [[END]] ], [ 7, [[ENTRY:%.*]] ] -; CHECK-NEXT: ret i64 [[RES]] +; CHECK-NEXT: ret i64 7 ; entry: %cmp = icmp eq i64 %x, 7 @@ -80,8 +78,7 @@ define i64 @limit_i64_ne_255(i64 %x) { ; CHECK: body: ; CHECK-NEXT: br label [[END]] ; CHECK: end: -; CHECK-NEXT: [[RES:%.*]] = phi i64 [ [[X]], [[ENTRY:%.*]] ], [ 255, [[BODY]] ] -; CHECK-NEXT: ret i64 [[RES]] +; CHECK-NEXT: ret i64 255 ; entry: %cmp = icmp ne i64 %x, 255 diff --git a/llvm/test/Transforms/LoopVectorize/induction.ll b/llvm/test/Transforms/LoopVectorize/induction.ll index 2cb740e17553e..e276b9e2893dc 100644 --- a/llvm/test/Transforms/LoopVectorize/induction.ll +++ b/llvm/test/Transforms/LoopVectorize/induction.ll @@ -3176,7 +3176,7 @@ define i32 @testoverflowcheck() { ; IND-NEXT: [[CMP_N:%.*]] = icmp eq i32 [[TMP3]], [[N_VEC]] ; IND-NEXT: br i1 [[CMP_N]], label [[LOOPEXIT:%.*]], label [[SCALAR_PH]] ; IND: scalar.ph: -; IND-NEXT: [[BC_RESUME_VAL:%.*]] = phi i8 [ [[IND_END]], [[MIDDLE_BLOCK]] ], [ [[DOTPR_I]], [[ENTRY:%.*]] ] +; IND-NEXT: [[BC_RESUME_VAL:%.*]] = phi i8 [ [[IND_END]], [[MIDDLE_BLOCK]] ], [ -1, [[ENTRY:%.*]] ] ; IND-NEXT: [[BC_MERGE_RDX:%.*]] = phi i32 [ [[TMP7]], [[MIDDLE_BLOCK]] ], [ [[C_PROMOTED_I]], [[ENTRY]] ] ; IND-NEXT: br label [[COND_END_I:%.*]] ; IND: cond.end.i: diff --git a/llvm/test/Transforms/PGOProfile/chr.ll b/llvm/test/Transforms/PGOProfile/chr.ll index 46f9a2bde7a23..dac0ca2b6f90c 100644 --- a/llvm/test/Transforms/PGOProfile/chr.ll +++ b/llvm/test/Transforms/PGOProfile/chr.ll @@ -1584,7 +1584,7 @@ define i32 @test_chr_17(i32 %i, i1 %j) !prof !14 { ; CHECK-NEXT: [[S:%.*]] = add nuw nsw i32 [[TMP0]], [[I]] ; CHECK-NEXT: br label [[BB1]] ; CHECK: bb1: -; CHECK-NEXT: [[P:%.*]] = phi i32 [ [[I]], [[BBQ]] ], [ [[TMP0]], [[BBE]] ], [ [[S]], [[BB0]] ] +; CHECK-NEXT: [[P:%.*]] = phi i32 [ [[I]], [[BBQ]] ], [ 0, [[BBE]] ], [ [[S]], [[BB0]] ] ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[I]], 2 ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 0 ; CHECK-NEXT: br i1 [[TMP3]], label [[BB3]], label [[BB2:%.*]], !prof [[PROF16]]