Skip to content

Commit 3686a0b

Browse files
[GlobalISel] LegalizationArtifactCombiner: Elide redundant G_AND
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
1 parent 78c4974 commit 3686a0b

File tree

185 files changed

+11686
-12287
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

185 files changed

+11686
-12287
lines changed

llvm/include/llvm/CodeGen/GlobalISel/GISelKnownBits.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -118,11 +118,7 @@ class GISelKnownBitsAnalysis : public MachineFunctionPass {
118118
GISelKnownBitsAnalysis() : MachineFunctionPass(ID) {
119119
initializeGISelKnownBitsAnalysisPass(*PassRegistry::getPassRegistry());
120120
}
121-
GISelKnownBits &get(MachineFunction &MF) {
122-
if (!Info)
123-
Info = std::make_unique<GISelKnownBits>(MF);
124-
return *Info.get();
125-
}
121+
GISelKnownBits &get(MachineFunction &MF);
126122
void getAnalysisUsage(AnalysisUsage &AU) const override;
127123
bool runOnMachineFunction(MachineFunction &MF) override;
128124
void releaseMemory() override { Info.reset(); }

llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class LegalizationArtifactCombiner {
3535
MachineIRBuilder &Builder;
3636
MachineRegisterInfo &MRI;
3737
const LegalizerInfo &LI;
38+
GISelKnownBits *KB;
3839

3940
static bool isArtifactCast(unsigned Opc) {
4041
switch (Opc) {
@@ -50,8 +51,9 @@ class LegalizationArtifactCombiner {
5051

5152
public:
5253
LegalizationArtifactCombiner(MachineIRBuilder &B, MachineRegisterInfo &MRI,
53-
const LegalizerInfo &LI)
54-
: Builder(B), MRI(MRI), LI(LI) {}
54+
const LegalizerInfo &LI,
55+
GISelKnownBits *KB = nullptr)
56+
: Builder(B), MRI(MRI), LI(LI), KB(KB) {}
5557

5658
bool tryCombineAnyExt(MachineInstr &MI,
5759
SmallVectorImpl<MachineInstr *> &DeadInsts,
@@ -131,13 +133,26 @@ class LegalizationArtifactCombiner {
131133
LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;);
132134
LLT SrcTy = MRI.getType(SrcReg);
133135
APInt MaskVal = APInt::getAllOnes(SrcTy.getScalarSizeInBits());
134-
auto Mask = Builder.buildConstant(
135-
DstTy, MaskVal.zext(DstTy.getScalarSizeInBits()));
136136
if (SextSrc && (DstTy != MRI.getType(SextSrc)))
137137
SextSrc = Builder.buildSExtOrTrunc(DstTy, SextSrc).getReg(0);
138138
if (TruncSrc && (DstTy != MRI.getType(TruncSrc)))
139139
TruncSrc = Builder.buildAnyExtOrTrunc(DstTy, TruncSrc).getReg(0);
140-
Builder.buildAnd(DstReg, SextSrc ? SextSrc : TruncSrc, Mask);
140+
APInt ExtMaskVal = MaskVal.zext(DstTy.getScalarSizeInBits());
141+
Register AndSrc = SextSrc ? SextSrc : TruncSrc;
142+
// Elide G_AND and mask constant if possible.
143+
// The G_AND would also be removed by the post-legalize redundant_and
144+
// combine, but in this very common case, eliding early and regardless of
145+
// OptLevel results in significant compile-time and O0 code-size
146+
// improvements. Inserting unnecessary instructions between a boolean def
147+
// and use can also hinder ISel to detect e.g. that reloading a flags
148+
// register is unnecessary.
149+
if (KB && (KB->getKnownZeroes(AndSrc) | ExtMaskVal).isAllOnes()) {
150+
replaceRegOrBuildCopy(DstReg, AndSrc, MRI, Builder, UpdatedDefs,
151+
Observer);
152+
} else {
153+
auto Mask = Builder.buildConstant(DstTy, ExtMaskVal);
154+
Builder.buildAnd(DstReg, AndSrc, Mask);
155+
}
141156
markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts);
142157
return true;
143158
}

llvm/lib/CodeGen/GlobalISel/GISelKnownBits.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "llvm/CodeGen/TargetLowering.h"
2020
#include "llvm/CodeGen/TargetOpcodes.h"
2121
#include "llvm/IR/Module.h"
22+
#include "llvm/Target/TargetMachine.h"
2223

2324
#define DEBUG_TYPE "gisel-known-bits"
2425

@@ -773,3 +774,12 @@ void GISelKnownBitsAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
773774
bool GISelKnownBitsAnalysis::runOnMachineFunction(MachineFunction &MF) {
774775
return false;
775776
}
777+
778+
GISelKnownBits &GISelKnownBitsAnalysis::get(MachineFunction &MF) {
779+
if (!Info) {
780+
unsigned MaxDepth =
781+
MF.getTarget().getOptLevel() == CodeGenOptLevel::None ? 2 : 6;
782+
Info = std::make_unique<GISelKnownBits>(MF, MaxDepth);
783+
}
784+
return *Info.get();
785+
}

llvm/lib/CodeGen/GlobalISel/Legalizer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ Legalizer::legalizeMachineFunction(MachineFunction &MF, const LegalizerInfo &LI,
218218
// This will keep all the observers notified about new insertions/deletions.
219219
RAIIMFObsDelInstaller Installer(MF, WrapperObserver);
220220
LegalizerHelper Helper(MF, LI, WrapperObserver, MIRBuilder, KB);
221-
LegalizationArtifactCombiner ArtCombiner(MIRBuilder, MRI, LI);
221+
LegalizationArtifactCombiner ArtCombiner(MIRBuilder, MRI, LI, KB);
222222
bool Changed = false;
223223
SmallVector<MachineInstr *, 128> RetryList;
224224
do {

0 commit comments

Comments
 (0)