Skip to content

Commit

Permalink
[GlobalISel] LegalizationArtifactCombiner: Elide redundant G_AND
Browse files Browse the repository at this point in the history
The legalizer currently generates lots of G_AND artifacts.
For example between boolean uses and defs there is always a G_AND with a mask of 1, but when the target uses ZeroOrOneBooleanContents, this is unnecessary.
Currently these artifacts have to be removed using post-legalize combines.
Omitting these artifacts at their source in the artifact combiner has a few advantages:
- We know that the emitted G_AND is very likely to be useless, so our KnownBits call is likely worth it.
- The G_AND and G_CONSTANT can interrupt e.g. G_UADDE/... sequences generated during legalization of wide adds which makes it harder to detect these sequences in the instruction selector (e.g. useful to prevent unnecessary reloading of AArch64 NZCV register).
- This cleans up a lot of legalizer output and even improves compilation-times.
AArch64 CTMark geomean: `O0` -5.6% size..text; `O0` and `O3` ~-0.9% compilation-time (instruction count).

Since this introduces KnownBits into code-paths used by `O0`, I reduced the default recursion depth.
This doesn't seem to make a difference in CTMark, but should prevent excessive recursive calls in the worst case.

Reviewed By: aemerson

Differential Revision: https://reviews.llvm.org/D159140
  • Loading branch information
tobias-stadler committed Sep 29, 2023
1 parent 78c4974 commit 3686a0b
Show file tree
Hide file tree
Showing 185 changed files with 11,686 additions and 12,287 deletions.
6 changes: 1 addition & 5 deletions llvm/include/llvm/CodeGen/GlobalISel/GISelKnownBits.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,7 @@ class GISelKnownBitsAnalysis : public MachineFunctionPass {
GISelKnownBitsAnalysis() : MachineFunctionPass(ID) {
initializeGISelKnownBitsAnalysisPass(*PassRegistry::getPassRegistry());
}
GISelKnownBits &get(MachineFunction &MF) {
if (!Info)
Info = std::make_unique<GISelKnownBits>(MF);
return *Info.get();
}
GISelKnownBits &get(MachineFunction &MF);
void getAnalysisUsage(AnalysisUsage &AU) const override;
bool runOnMachineFunction(MachineFunction &MF) override;
void releaseMemory() override { Info.reset(); }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class LegalizationArtifactCombiner {
MachineIRBuilder &Builder;
MachineRegisterInfo &MRI;
const LegalizerInfo &LI;
GISelKnownBits *KB;

static bool isArtifactCast(unsigned Opc) {
switch (Opc) {
Expand All @@ -50,8 +51,9 @@ class LegalizationArtifactCombiner {

public:
LegalizationArtifactCombiner(MachineIRBuilder &B, MachineRegisterInfo &MRI,
const LegalizerInfo &LI)
: Builder(B), MRI(MRI), LI(LI) {}
const LegalizerInfo &LI,
GISelKnownBits *KB = nullptr)
: Builder(B), MRI(MRI), LI(LI), KB(KB) {}

bool tryCombineAnyExt(MachineInstr &MI,
SmallVectorImpl<MachineInstr *> &DeadInsts,
Expand Down Expand Up @@ -131,13 +133,26 @@ class LegalizationArtifactCombiner {
LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;);
LLT SrcTy = MRI.getType(SrcReg);
APInt MaskVal = APInt::getAllOnes(SrcTy.getScalarSizeInBits());
auto Mask = Builder.buildConstant(
DstTy, MaskVal.zext(DstTy.getScalarSizeInBits()));
if (SextSrc && (DstTy != MRI.getType(SextSrc)))
SextSrc = Builder.buildSExtOrTrunc(DstTy, SextSrc).getReg(0);
if (TruncSrc && (DstTy != MRI.getType(TruncSrc)))
TruncSrc = Builder.buildAnyExtOrTrunc(DstTy, TruncSrc).getReg(0);
Builder.buildAnd(DstReg, SextSrc ? SextSrc : TruncSrc, Mask);
APInt ExtMaskVal = MaskVal.zext(DstTy.getScalarSizeInBits());
Register AndSrc = SextSrc ? SextSrc : TruncSrc;
// Elide G_AND and mask constant if possible.
// The G_AND would also be removed by the post-legalize redundant_and
// combine, but in this very common case, eliding early and regardless of
// OptLevel results in significant compile-time and O0 code-size
// improvements. Inserting unnecessary instructions between a boolean def
// and use can also hinder ISel to detect e.g. that reloading a flags
// register is unnecessary.
if (KB && (KB->getKnownZeroes(AndSrc) | ExtMaskVal).isAllOnes()) {
replaceRegOrBuildCopy(DstReg, AndSrc, MRI, Builder, UpdatedDefs,
Observer);
} else {
auto Mask = Builder.buildConstant(DstTy, ExtMaskVal);
Builder.buildAnd(DstReg, AndSrc, Mask);
}
markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);
return true;
}
Expand Down
10 changes: 10 additions & 0 deletions llvm/lib/CodeGen/GlobalISel/GISelKnownBits.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetOpcodes.h"
#include "llvm/IR/Module.h"
#include "llvm/Target/TargetMachine.h"

#define DEBUG_TYPE "gisel-known-bits"

Expand Down Expand Up @@ -773,3 +774,12 @@ void GISelKnownBitsAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
bool GISelKnownBitsAnalysis::runOnMachineFunction(MachineFunction &MF) {
return false;
}

GISelKnownBits &GISelKnownBitsAnalysis::get(MachineFunction &MF) {
if (!Info) {
unsigned MaxDepth =
MF.getTarget().getOptLevel() == CodeGenOptLevel::None ? 2 : 6;
Info = std::make_unique<GISelKnownBits>(MF, MaxDepth);
}
return *Info.get();
}
2 changes: 1 addition & 1 deletion llvm/lib/CodeGen/GlobalISel/Legalizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ Legalizer::legalizeMachineFunction(MachineFunction &MF, const LegalizerInfo &LI,
// This will keep all the observers notified about new insertions/deletions.
RAIIMFObsDelInstaller Installer(MF, WrapperObserver);
LegalizerHelper Helper(MF, LI, WrapperObserver, MIRBuilder, KB);
LegalizationArtifactCombiner ArtCombiner(MIRBuilder, MRI, LI);
LegalizationArtifactCombiner ArtCombiner(MIRBuilder, MRI, LI, KB);
bool Changed = false;
SmallVector<MachineInstr *, 128> RetryList;
do {
Expand Down
Loading

0 comments on commit 3686a0b

Please sign in to comment.