diff --git a/llvm/include/llvm/CodeGen/GlobalISel/Localizer.h b/llvm/include/llvm/CodeGen/GlobalISel/Localizer.h --- a/llvm/include/llvm/CodeGen/GlobalISel/Localizer.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/Localizer.h @@ -64,6 +64,11 @@ typedef SmallSetVector LocalizedSetVecT; + /// If \p Op is a phi operand and not unique in that phi, that is, + /// there are other operands in the phi with the same register, + /// return true. + bool isNonUniquePhiValue(MachineOperand &Op) const; + /// Do inter-block localization from the entry block. bool localizeInterBlock(MachineFunction &MF, LocalizedSetVecT &LocalizedInstrs); diff --git a/llvm/lib/CodeGen/GlobalISel/Localizer.cpp b/llvm/lib/CodeGen/GlobalISel/Localizer.cpp --- a/llvm/lib/CodeGen/GlobalISel/Localizer.cpp +++ b/llvm/lib/CodeGen/GlobalISel/Localizer.cpp @@ -11,6 +11,7 @@ #include "llvm/CodeGen/GlobalISel/Localizer.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/TargetLowering.h" @@ -56,6 +57,20 @@ return InsertMBB == Def.getParent(); } +bool Localizer::isNonUniquePhiValue(MachineOperand &Op) const { + MachineInstr *MI = Op.getParent(); + if (!MI->isPHI()) + return false; + + Register SrcReg = Op.getReg(); + for (unsigned Idx = 1; Idx < MI->getNumOperands(); Idx += 2) { + auto &MO = MI->getOperand(Idx); + if (&MO != &Op && MO.isReg() && MO.getReg() == SrcReg) + return true; + } + return false; +} + bool Localizer::localizeInterBlock(MachineFunction &MF, LocalizedSetVecT &LocalizedInstrs) { bool Changed = false; @@ -93,6 +108,14 @@ LocalizedInstrs.insert(&MI); continue; } + + // If the use is a phi operand that's not unique, don't try to localize. + // If we do, we can cause unnecessary instruction bloat by duplicating + // into each predecessor block, when the existing one is sufficient and + // allows for easier optimization later. + if (isNonUniquePhiValue(MOUse)) + continue; + LLVM_DEBUG(dbgs() << "Fixing non-local use\n"); Changed = true; auto MBBAndReg = std::make_pair(InsertMBB, Reg); diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/localizer.mir b/llvm/test/CodeGen/AArch64/GlobalISel/localizer.mir --- a/llvm/test/CodeGen/AArch64/GlobalISel/localizer.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/localizer.mir @@ -56,7 +56,7 @@ define void @test_inttoptr() { ret void } define void @many_local_use_intra_block() { ret void } - + define void @non_local_phi_use_nonunique() { ret void } ... --- @@ -564,3 +564,45 @@ %6:gpr(s32) = G_ADD %0, %0 %7:gpr(s32) = G_ADD %1, %1 ... + +--- +name: non_local_phi_use_nonunique +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + ; CHECK-LABEL: name: non_local_phi_use_nonunique + ; CHECK: bb.0: + ; CHECK: successors: %bb.1(0x40000000), %bb.2(0x40000000) + ; CHECK: [[C:%[0-9]+]]:gpr(s32) = G_CONSTANT i32 1 + ; CHECK: [[ADD:%[0-9]+]]:gpr(s32) = G_ADD [[C]], [[C]] + ; CHECK: %cmp:gpr(s32) = G_ICMP intpred(eq), [[ADD]](s32), [[C]] + ; CHECK: %cond:gpr(s1) = G_TRUNC %cmp(s32) + ; CHECK: G_BRCOND %cond(s1), %bb.1 + ; CHECK: G_BR %bb.2 + ; CHECK: bb.1: + ; CHECK: successors: %bb.2(0x80000000) + ; CHECK: bb.2: + ; CHECK: [[PHI:%[0-9]+]]:gpr(s32) = G_PHI [[C]](s32), %bb.1 + ; CHECK: [[ADD1:%[0-9]+]]:gpr(s32) = G_ADD [[PHI]], [[PHI]] + + ; Don't localize the 1 into bb.1, because there are multiple edges + ; using that register. + + bb.0: + successors: %bb.1, %bb.2 + + %0:gpr(s32) = G_CONSTANT i32 1 + %1:gpr(s32) = G_ADD %0, %0 + %cmp:gpr(s32) = G_ICMP intpred(eq), %1(s32), %0 + %cond:gpr(s1) = G_TRUNC %cmp(s32) + G_BRCOND %cond(s1), %bb.1 + G_BR %bb.2 + + bb.1: + successors: %bb.2 + + bb.2: + %3:gpr(s32) = G_PHI %0(s32), %bb.1, %0(s32), %bb.0 + %2:gpr(s32) = G_ADD %3, %3 +...