From 43e7d9af1d319693b3302560b447366ba359f1a2 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 1 Sep 2022 10:48:49 +0200 Subject: [PATCH] [InstCombine] Fold extractvalue of phi Just as we do for most other operations, we should push extractvalue instructions through phis, if this does not increase unfolded instruction count. --- .../InstCombine/InstructionCombining.cpp | 9 ++++++++ .../InstCombine/phi-extractvalue.ll | 22 +++++++++---------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp index 458f28decf7cdb..e6735930286807 100644 --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -1280,6 +1280,11 @@ Instruction *InstCombinerImpl::foldOpIntoPhi(Instruction &I, PHINode *PN) { InV = PN->getIncomingValue(i); NewPN->addIncoming(InV, PN->getIncomingBlock(i)); } + } else if (auto *EV = dyn_cast(&I)) { + for (unsigned i = 0; i != NumPHIValues; ++i) + NewPN->addIncoming(Builder.CreateExtractValue(PN->getIncomingValue(i), + EV->getIndices(), "phi.ev"), + PN->getIncomingBlock(i)); } else { CastInst *CI = cast(&I); Type *RetTy = CI->getType(); @@ -3399,6 +3404,10 @@ Instruction *InstCombinerImpl::visitExtractValueInst(ExtractValueInst &EV) { } } + if (auto *PN = dyn_cast(Agg)) + if (Instruction *Res = foldOpIntoPhi(EV, PN)) + return Res; + // We could simplify extracts from other values. Note that nested extracts may // already be simplified implicitly by the above: extract (extract (insert) ) // will be translated into extract ( insert ( extract ) ) first and then just diff --git a/llvm/test/Transforms/InstCombine/phi-extractvalue.ll b/llvm/test/Transforms/InstCombine/phi-extractvalue.ll index 89667c21c188d4..06ae31cfebef80 100644 --- a/llvm/test/Transforms/InstCombine/phi-extractvalue.ll +++ b/llvm/test/Transforms/InstCombine/phi-extractvalue.ll @@ -393,9 +393,8 @@ define i32 @extractvalue_of_constant_phi(i1 %c) { ; CHECK: else: ; CHECK-NEXT: br label [[JOIN]] ; CHECK: join: -; CHECK-NEXT: [[PHI:%.*]] = phi { i32, i32 } [ { i32 1, i32 2 }, [[IF]] ], [ { i32 3, i32 4 }, [[ELSE]] ] -; CHECK-NEXT: [[EV:%.*]] = extractvalue { i32, i32 } [[PHI]], 0 -; CHECK-NEXT: ret i32 [[EV]] +; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ 1, [[IF]] ], [ 3, [[ELSE]] ] +; CHECK-NEXT: ret i32 [[PHI]] ; br i1 %c, label %if, label %else @@ -415,13 +414,13 @@ define i32 @extractvalue_of_one_constant_phi(i1 %c, { i32, i32 } %arg) { ; CHECK-LABEL: @extractvalue_of_one_constant_phi( ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]] ; CHECK: if: +; CHECK-NEXT: [[PHI_EV:%.*]] = extractvalue { i32, i32 } [[ARG:%.*]], 0 ; CHECK-NEXT: br label [[JOIN:%.*]] ; CHECK: else: ; CHECK-NEXT: br label [[JOIN]] ; CHECK: join: -; CHECK-NEXT: [[PHI:%.*]] = phi { i32, i32 } [ [[ARG:%.*]], [[IF]] ], [ { i32 3, i32 4 }, [[ELSE]] ] -; CHECK-NEXT: [[EV:%.*]] = extractvalue { i32, i32 } [[PHI]], 0 -; CHECK-NEXT: ret i32 [[EV]] +; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[PHI_EV]], [[IF]] ], [ 3, [[ELSE]] ] +; CHECK-NEXT: ret i32 [[PHI]] ; br i1 %c, label %if, label %else @@ -445,9 +444,8 @@ define i32 @extractvalue_of_constant_phi_multi_index(i1 %c) { ; CHECK: else: ; CHECK-NEXT: br label [[JOIN]] ; CHECK: join: -; CHECK-NEXT: [[PHI:%.*]] = phi { i32, { i32, i32 } } [ { i32 1, { i32, i32 } { i32 2, i32 3 } }, [[IF]] ], [ { i32 4, { i32, i32 } { i32 5, i32 6 } }, [[ELSE]] ] -; CHECK-NEXT: [[EV:%.*]] = extractvalue { i32, { i32, i32 } } [[PHI]], 1, 1 -; CHECK-NEXT: ret i32 [[EV]] +; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ 3, [[IF]] ], [ 6, [[ELSE]] ] +; CHECK-NEXT: ret i32 [[PHI]] ; br i1 %c, label %if, label %else @@ -467,13 +465,13 @@ define i32 @extractvalue_of_one_constant_phi_multi_index(i1 %c, { i32, { i32, i3 ; CHECK-LABEL: @extractvalue_of_one_constant_phi_multi_index( ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]] ; CHECK: if: +; CHECK-NEXT: [[PHI_EV:%.*]] = extractvalue { i32, { i32, i32 } } [[ARG:%.*]], 1, 1 ; CHECK-NEXT: br label [[JOIN:%.*]] ; CHECK: else: ; CHECK-NEXT: br label [[JOIN]] ; CHECK: join: -; CHECK-NEXT: [[PHI:%.*]] = phi { i32, { i32, i32 } } [ [[ARG:%.*]], [[IF]] ], [ { i32 4, { i32, i32 } { i32 5, i32 6 } }, [[ELSE]] ] -; CHECK-NEXT: [[EV:%.*]] = extractvalue { i32, { i32, i32 } } [[PHI]], 1, 1 -; CHECK-NEXT: ret i32 [[EV]] +; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[PHI_EV]], [[IF]] ], [ 6, [[ELSE]] ] +; CHECK-NEXT: ret i32 [[PHI]] ; br i1 %c, label %if, label %else