109467b48Spatrick //===-- llvm/CodeGen/GlobalISel/Legalizer.cpp -----------------------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick /// \file This file implements the LegalizerHelper class to legalize individual
1009467b48Spatrick /// instructions and the LegalizePass wrapper pass for the primary
1109467b48Spatrick /// legalization.
1209467b48Spatrick //
1309467b48Spatrick //===----------------------------------------------------------------------===//
1409467b48Spatrick
1509467b48Spatrick #include "llvm/CodeGen/GlobalISel/Legalizer.h"
1609467b48Spatrick #include "llvm/ADT/PostOrderIterator.h"
17*d415bd75Srobert #include "llvm/Analysis/OptimizationRemarkEmitter.h"
1809467b48Spatrick #include "llvm/CodeGen/GlobalISel/CSEInfo.h"
1909467b48Spatrick #include "llvm/CodeGen/GlobalISel/CSEMIRBuilder.h"
2009467b48Spatrick #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
2109467b48Spatrick #include "llvm/CodeGen/GlobalISel/GISelWorkList.h"
2209467b48Spatrick #include "llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h"
2309467b48Spatrick #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
24097a140dSpatrick #include "llvm/CodeGen/GlobalISel/LostDebugLocObserver.h"
2509467b48Spatrick #include "llvm/CodeGen/GlobalISel/Utils.h"
2609467b48Spatrick #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
2709467b48Spatrick #include "llvm/CodeGen/TargetPassConfig.h"
2809467b48Spatrick #include "llvm/CodeGen/TargetSubtargetInfo.h"
2909467b48Spatrick #include "llvm/InitializePasses.h"
3009467b48Spatrick #include "llvm/Support/Debug.h"
31097a140dSpatrick #include "llvm/Support/Error.h"
3209467b48Spatrick
3309467b48Spatrick #define DEBUG_TYPE "legalizer"
3409467b48Spatrick
3509467b48Spatrick using namespace llvm;
3609467b48Spatrick
3709467b48Spatrick static cl::opt<bool>
3809467b48Spatrick EnableCSEInLegalizer("enable-cse-in-legalizer",
3909467b48Spatrick cl::desc("Should enable CSE in Legalizer"),
4009467b48Spatrick cl::Optional, cl::init(false));
4109467b48Spatrick
4273471bf0Spatrick // This is a temporary hack, should be removed soon.
4373471bf0Spatrick static cl::opt<bool> AllowGInsertAsArtifact(
4473471bf0Spatrick "allow-ginsert-as-artifact",
4573471bf0Spatrick cl::desc("Allow G_INSERT to be considered an artifact. Hack around AMDGPU "
4673471bf0Spatrick "test infinite loops."),
4773471bf0Spatrick cl::Optional, cl::init(true));
4873471bf0Spatrick
49097a140dSpatrick enum class DebugLocVerifyLevel {
50097a140dSpatrick None,
51097a140dSpatrick Legalizations,
52097a140dSpatrick LegalizationsAndArtifactCombiners,
53097a140dSpatrick };
54097a140dSpatrick #ifndef NDEBUG
55097a140dSpatrick static cl::opt<DebugLocVerifyLevel> VerifyDebugLocs(
56097a140dSpatrick "verify-legalizer-debug-locs",
57097a140dSpatrick cl::desc("Verify that debug locations are handled"),
58097a140dSpatrick cl::values(
59097a140dSpatrick clEnumValN(DebugLocVerifyLevel::None, "none", "No verification"),
60097a140dSpatrick clEnumValN(DebugLocVerifyLevel::Legalizations, "legalizations",
61097a140dSpatrick "Verify legalizations"),
62097a140dSpatrick clEnumValN(DebugLocVerifyLevel::LegalizationsAndArtifactCombiners,
63097a140dSpatrick "legalizations+artifactcombiners",
64097a140dSpatrick "Verify legalizations and artifact combines")),
65097a140dSpatrick cl::init(DebugLocVerifyLevel::Legalizations));
66097a140dSpatrick #else
67097a140dSpatrick // Always disable it for release builds by preventing the observer from being
68097a140dSpatrick // installed.
69097a140dSpatrick static const DebugLocVerifyLevel VerifyDebugLocs = DebugLocVerifyLevel::None;
70097a140dSpatrick #endif
71097a140dSpatrick
7209467b48Spatrick char Legalizer::ID = 0;
7309467b48Spatrick INITIALIZE_PASS_BEGIN(Legalizer, DEBUG_TYPE,
7409467b48Spatrick "Legalize the Machine IR a function's Machine IR", false,
7509467b48Spatrick false)
INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)7609467b48Spatrick INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
7709467b48Spatrick INITIALIZE_PASS_DEPENDENCY(GISelCSEAnalysisWrapperPass)
7809467b48Spatrick INITIALIZE_PASS_END(Legalizer, DEBUG_TYPE,
7909467b48Spatrick "Legalize the Machine IR a function's Machine IR", false,
8009467b48Spatrick false)
8109467b48Spatrick
8209467b48Spatrick Legalizer::Legalizer() : MachineFunctionPass(ID) { }
8309467b48Spatrick
getAnalysisUsage(AnalysisUsage & AU) const8409467b48Spatrick void Legalizer::getAnalysisUsage(AnalysisUsage &AU) const {
8509467b48Spatrick AU.addRequired<TargetPassConfig>();
8609467b48Spatrick AU.addRequired<GISelCSEAnalysisWrapperPass>();
8709467b48Spatrick AU.addPreserved<GISelCSEAnalysisWrapperPass>();
8809467b48Spatrick getSelectionDAGFallbackAnalysisUsage(AU);
8909467b48Spatrick MachineFunctionPass::getAnalysisUsage(AU);
9009467b48Spatrick }
9109467b48Spatrick
init(MachineFunction & MF)9209467b48Spatrick void Legalizer::init(MachineFunction &MF) {
9309467b48Spatrick }
9409467b48Spatrick
isArtifact(const MachineInstr & MI)9509467b48Spatrick static bool isArtifact(const MachineInstr &MI) {
9609467b48Spatrick switch (MI.getOpcode()) {
9709467b48Spatrick default:
9809467b48Spatrick return false;
9909467b48Spatrick case TargetOpcode::G_TRUNC:
10009467b48Spatrick case TargetOpcode::G_ZEXT:
10109467b48Spatrick case TargetOpcode::G_ANYEXT:
10209467b48Spatrick case TargetOpcode::G_SEXT:
10309467b48Spatrick case TargetOpcode::G_MERGE_VALUES:
10409467b48Spatrick case TargetOpcode::G_UNMERGE_VALUES:
10509467b48Spatrick case TargetOpcode::G_CONCAT_VECTORS:
10609467b48Spatrick case TargetOpcode::G_BUILD_VECTOR:
10709467b48Spatrick case TargetOpcode::G_EXTRACT:
10809467b48Spatrick return true;
10973471bf0Spatrick case TargetOpcode::G_INSERT:
11073471bf0Spatrick return AllowGInsertAsArtifact;
11109467b48Spatrick }
11209467b48Spatrick }
11309467b48Spatrick using InstListTy = GISelWorkList<256>;
11409467b48Spatrick using ArtifactListTy = GISelWorkList<128>;
11509467b48Spatrick
11609467b48Spatrick namespace {
11709467b48Spatrick class LegalizerWorkListManager : public GISelChangeObserver {
11809467b48Spatrick InstListTy &InstList;
11909467b48Spatrick ArtifactListTy &ArtifactList;
12009467b48Spatrick #ifndef NDEBUG
12109467b48Spatrick SmallVector<MachineInstr *, 4> NewMIs;
12209467b48Spatrick #endif
12309467b48Spatrick
12409467b48Spatrick public:
LegalizerWorkListManager(InstListTy & Insts,ArtifactListTy & Arts)12509467b48Spatrick LegalizerWorkListManager(InstListTy &Insts, ArtifactListTy &Arts)
12609467b48Spatrick : InstList(Insts), ArtifactList(Arts) {}
12709467b48Spatrick
createdOrChangedInstr(MachineInstr & MI)12809467b48Spatrick void createdOrChangedInstr(MachineInstr &MI) {
12909467b48Spatrick // Only legalize pre-isel generic instructions.
13009467b48Spatrick // Legalization process could generate Target specific pseudo
13109467b48Spatrick // instructions with generic types. Don't record them
13209467b48Spatrick if (isPreISelGenericOpcode(MI.getOpcode())) {
13309467b48Spatrick if (isArtifact(MI))
13409467b48Spatrick ArtifactList.insert(&MI);
13509467b48Spatrick else
13609467b48Spatrick InstList.insert(&MI);
13709467b48Spatrick }
13809467b48Spatrick }
13909467b48Spatrick
createdInstr(MachineInstr & MI)14009467b48Spatrick void createdInstr(MachineInstr &MI) override {
14109467b48Spatrick LLVM_DEBUG(NewMIs.push_back(&MI));
14209467b48Spatrick createdOrChangedInstr(MI);
14309467b48Spatrick }
14409467b48Spatrick
printNewInstrs()14509467b48Spatrick void printNewInstrs() {
14609467b48Spatrick LLVM_DEBUG({
14709467b48Spatrick for (const auto *MI : NewMIs)
14809467b48Spatrick dbgs() << ".. .. New MI: " << *MI;
14909467b48Spatrick NewMIs.clear();
15009467b48Spatrick });
15109467b48Spatrick }
15209467b48Spatrick
erasingInstr(MachineInstr & MI)15309467b48Spatrick void erasingInstr(MachineInstr &MI) override {
15409467b48Spatrick LLVM_DEBUG(dbgs() << ".. .. Erasing: " << MI);
15509467b48Spatrick InstList.remove(&MI);
15609467b48Spatrick ArtifactList.remove(&MI);
15709467b48Spatrick }
15809467b48Spatrick
changingInstr(MachineInstr & MI)15909467b48Spatrick void changingInstr(MachineInstr &MI) override {
16009467b48Spatrick LLVM_DEBUG(dbgs() << ".. .. Changing MI: " << MI);
16109467b48Spatrick }
16209467b48Spatrick
changedInstr(MachineInstr & MI)16309467b48Spatrick void changedInstr(MachineInstr &MI) override {
16409467b48Spatrick // When insts change, we want to revisit them to legalize them again.
16509467b48Spatrick // We'll consider them the same as created.
16609467b48Spatrick LLVM_DEBUG(dbgs() << ".. .. Changed MI: " << MI);
16709467b48Spatrick createdOrChangedInstr(MI);
16809467b48Spatrick }
16909467b48Spatrick };
17009467b48Spatrick } // namespace
17109467b48Spatrick
17209467b48Spatrick Legalizer::MFResult
legalizeMachineFunction(MachineFunction & MF,const LegalizerInfo & LI,ArrayRef<GISelChangeObserver * > AuxObservers,LostDebugLocObserver & LocObserver,MachineIRBuilder & MIRBuilder)17309467b48Spatrick Legalizer::legalizeMachineFunction(MachineFunction &MF, const LegalizerInfo &LI,
17409467b48Spatrick ArrayRef<GISelChangeObserver *> AuxObservers,
175097a140dSpatrick LostDebugLocObserver &LocObserver,
17609467b48Spatrick MachineIRBuilder &MIRBuilder) {
177097a140dSpatrick MIRBuilder.setMF(MF);
17809467b48Spatrick MachineRegisterInfo &MRI = MF.getRegInfo();
17909467b48Spatrick
18009467b48Spatrick // Populate worklists.
18109467b48Spatrick InstListTy InstList;
18209467b48Spatrick ArtifactListTy ArtifactList;
18309467b48Spatrick ReversePostOrderTraversal<MachineFunction *> RPOT(&MF);
18409467b48Spatrick // Perform legalization bottom up so we can DCE as we legalize.
18509467b48Spatrick // Traverse BB in RPOT and within each basic block, add insts top down,
18609467b48Spatrick // so when we pop_back_val in the legalization process, we traverse bottom-up.
18709467b48Spatrick for (auto *MBB : RPOT) {
18809467b48Spatrick if (MBB->empty())
18909467b48Spatrick continue;
19009467b48Spatrick for (MachineInstr &MI : *MBB) {
19109467b48Spatrick // Only legalize pre-isel generic instructions: others don't have types
19209467b48Spatrick // and are assumed to be legal.
19309467b48Spatrick if (!isPreISelGenericOpcode(MI.getOpcode()))
19409467b48Spatrick continue;
19509467b48Spatrick if (isArtifact(MI))
19609467b48Spatrick ArtifactList.deferred_insert(&MI);
19709467b48Spatrick else
19809467b48Spatrick InstList.deferred_insert(&MI);
19909467b48Spatrick }
20009467b48Spatrick }
20109467b48Spatrick ArtifactList.finalize();
20209467b48Spatrick InstList.finalize();
20309467b48Spatrick
20409467b48Spatrick // This observer keeps the worklists updated.
20509467b48Spatrick LegalizerWorkListManager WorkListObserver(InstList, ArtifactList);
20609467b48Spatrick // We want both WorkListObserver as well as all the auxiliary observers (e.g.
20709467b48Spatrick // CSEInfo) to observe all changes. Use the wrapper observer.
20809467b48Spatrick GISelObserverWrapper WrapperObserver(&WorkListObserver);
20909467b48Spatrick for (GISelChangeObserver *Observer : AuxObservers)
21009467b48Spatrick WrapperObserver.addObserver(Observer);
21109467b48Spatrick
21209467b48Spatrick // Now install the observer as the delegate to MF.
21309467b48Spatrick // This will keep all the observers notified about new insertions/deletions.
214097a140dSpatrick RAIIMFObsDelInstaller Installer(MF, WrapperObserver);
21509467b48Spatrick LegalizerHelper Helper(MF, LI, WrapperObserver, MIRBuilder);
21609467b48Spatrick LegalizationArtifactCombiner ArtCombiner(MIRBuilder, MRI, LI);
21709467b48Spatrick bool Changed = false;
21809467b48Spatrick SmallVector<MachineInstr *, 128> RetryList;
21909467b48Spatrick do {
22009467b48Spatrick LLVM_DEBUG(dbgs() << "=== New Iteration ===\n");
22109467b48Spatrick assert(RetryList.empty() && "Expected no instructions in RetryList");
22209467b48Spatrick unsigned NumArtifacts = ArtifactList.size();
22309467b48Spatrick while (!InstList.empty()) {
22409467b48Spatrick MachineInstr &MI = *InstList.pop_back_val();
22509467b48Spatrick assert(isPreISelGenericOpcode(MI.getOpcode()) &&
22609467b48Spatrick "Expecting generic opcode");
22709467b48Spatrick if (isTriviallyDead(MI, MRI)) {
228*d415bd75Srobert salvageDebugInfo(MRI, MI);
229*d415bd75Srobert eraseInstr(MI, MRI, &LocObserver);
23009467b48Spatrick continue;
23109467b48Spatrick }
23209467b48Spatrick
23309467b48Spatrick // Do the legalization for this instruction.
23473471bf0Spatrick auto Res = Helper.legalizeInstrStep(MI, LocObserver);
23509467b48Spatrick // Error out if we couldn't legalize this instruction. We may want to
23609467b48Spatrick // fall back to DAG ISel instead in the future.
23709467b48Spatrick if (Res == LegalizerHelper::UnableToLegalize) {
23809467b48Spatrick // Move illegal artifacts to RetryList instead of aborting because
23909467b48Spatrick // legalizing InstList may generate artifacts that allow
24009467b48Spatrick // ArtifactCombiner to combine away them.
24109467b48Spatrick if (isArtifact(MI)) {
24209467b48Spatrick LLVM_DEBUG(dbgs() << ".. Not legalized, moving to artifacts retry\n");
24309467b48Spatrick assert(NumArtifacts == 0 &&
24409467b48Spatrick "Artifacts are only expected in instruction list starting the "
24509467b48Spatrick "second iteration, but each iteration starting second must "
24609467b48Spatrick "start with an empty artifacts list");
24709467b48Spatrick (void)NumArtifacts;
24809467b48Spatrick RetryList.push_back(&MI);
24909467b48Spatrick continue;
25009467b48Spatrick }
25109467b48Spatrick Helper.MIRBuilder.stopObservingChanges();
25209467b48Spatrick return {Changed, &MI};
25309467b48Spatrick }
25409467b48Spatrick WorkListObserver.printNewInstrs();
255097a140dSpatrick LocObserver.checkpoint();
25609467b48Spatrick Changed |= Res == LegalizerHelper::Legalized;
25709467b48Spatrick }
25809467b48Spatrick // Try to combine the instructions in RetryList again if there
25909467b48Spatrick // are new artifacts. If not, stop legalizing.
26009467b48Spatrick if (!RetryList.empty()) {
26109467b48Spatrick if (!ArtifactList.empty()) {
26209467b48Spatrick while (!RetryList.empty())
26309467b48Spatrick ArtifactList.insert(RetryList.pop_back_val());
26409467b48Spatrick } else {
26509467b48Spatrick LLVM_DEBUG(dbgs() << "No new artifacts created, not retrying!\n");
26609467b48Spatrick Helper.MIRBuilder.stopObservingChanges();
26709467b48Spatrick return {Changed, RetryList.front()};
26809467b48Spatrick }
26909467b48Spatrick }
270097a140dSpatrick LocObserver.checkpoint();
27109467b48Spatrick while (!ArtifactList.empty()) {
27209467b48Spatrick MachineInstr &MI = *ArtifactList.pop_back_val();
27309467b48Spatrick assert(isPreISelGenericOpcode(MI.getOpcode()) &&
27409467b48Spatrick "Expecting generic opcode");
27509467b48Spatrick if (isTriviallyDead(MI, MRI)) {
276*d415bd75Srobert salvageDebugInfo(MRI, MI);
277*d415bd75Srobert eraseInstr(MI, MRI, &LocObserver);
27809467b48Spatrick continue;
27909467b48Spatrick }
28009467b48Spatrick SmallVector<MachineInstr *, 4> DeadInstructions;
28109467b48Spatrick LLVM_DEBUG(dbgs() << "Trying to combine: " << MI);
28209467b48Spatrick if (ArtCombiner.tryCombineInstruction(MI, DeadInstructions,
28309467b48Spatrick WrapperObserver)) {
28409467b48Spatrick WorkListObserver.printNewInstrs();
285*d415bd75Srobert eraseInstrs(DeadInstructions, MRI, &LocObserver);
286097a140dSpatrick LocObserver.checkpoint(
287097a140dSpatrick VerifyDebugLocs ==
288097a140dSpatrick DebugLocVerifyLevel::LegalizationsAndArtifactCombiners);
28909467b48Spatrick Changed = true;
29009467b48Spatrick continue;
29109467b48Spatrick }
29209467b48Spatrick // If this was not an artifact (that could be combined away), this might
29309467b48Spatrick // need special handling. Add it to InstList, so when it's processed
29409467b48Spatrick // there, it has to be legal or specially handled.
29509467b48Spatrick else {
29609467b48Spatrick LLVM_DEBUG(dbgs() << ".. Not combined, moving to instructions list\n");
29709467b48Spatrick InstList.insert(&MI);
29809467b48Spatrick }
29909467b48Spatrick }
30009467b48Spatrick } while (!InstList.empty());
30109467b48Spatrick
30209467b48Spatrick return {Changed, /*FailedOn*/ nullptr};
30309467b48Spatrick }
30409467b48Spatrick
runOnMachineFunction(MachineFunction & MF)30509467b48Spatrick bool Legalizer::runOnMachineFunction(MachineFunction &MF) {
30609467b48Spatrick // If the ISel pipeline failed, do not bother running that pass.
30709467b48Spatrick if (MF.getProperties().hasProperty(
30809467b48Spatrick MachineFunctionProperties::Property::FailedISel))
30909467b48Spatrick return false;
31009467b48Spatrick LLVM_DEBUG(dbgs() << "Legalize Machine IR for: " << MF.getName() << '\n');
31109467b48Spatrick init(MF);
31209467b48Spatrick const TargetPassConfig &TPC = getAnalysis<TargetPassConfig>();
31309467b48Spatrick GISelCSEAnalysisWrapper &Wrapper =
31409467b48Spatrick getAnalysis<GISelCSEAnalysisWrapperPass>().getCSEWrapper();
31509467b48Spatrick MachineOptimizationRemarkEmitter MORE(MF, /*MBFI=*/nullptr);
31609467b48Spatrick
31709467b48Spatrick const size_t NumBlocks = MF.size();
31809467b48Spatrick
31909467b48Spatrick std::unique_ptr<MachineIRBuilder> MIRBuilder;
32009467b48Spatrick GISelCSEInfo *CSEInfo = nullptr;
32109467b48Spatrick bool EnableCSE = EnableCSEInLegalizer.getNumOccurrences()
32209467b48Spatrick ? EnableCSEInLegalizer
32309467b48Spatrick : TPC.isGISelCSEEnabled();
32409467b48Spatrick if (EnableCSE) {
32509467b48Spatrick MIRBuilder = std::make_unique<CSEMIRBuilder>();
32609467b48Spatrick CSEInfo = &Wrapper.get(TPC.getCSEConfig());
32709467b48Spatrick MIRBuilder->setCSEInfo(CSEInfo);
32809467b48Spatrick } else
32909467b48Spatrick MIRBuilder = std::make_unique<MachineIRBuilder>();
33009467b48Spatrick
33109467b48Spatrick SmallVector<GISelChangeObserver *, 1> AuxObservers;
33209467b48Spatrick if (EnableCSE && CSEInfo) {
33309467b48Spatrick // We want CSEInfo in addition to WorkListObserver to observe all changes.
33409467b48Spatrick AuxObservers.push_back(CSEInfo);
33509467b48Spatrick }
336097a140dSpatrick assert(!CSEInfo || !errorToBool(CSEInfo->verify()));
337097a140dSpatrick LostDebugLocObserver LocObserver(DEBUG_TYPE);
338097a140dSpatrick if (VerifyDebugLocs > DebugLocVerifyLevel::None)
339097a140dSpatrick AuxObservers.push_back(&LocObserver);
34009467b48Spatrick
34109467b48Spatrick const LegalizerInfo &LI = *MF.getSubtarget().getLegalizerInfo();
342097a140dSpatrick MFResult Result =
343097a140dSpatrick legalizeMachineFunction(MF, LI, AuxObservers, LocObserver, *MIRBuilder);
34409467b48Spatrick
34509467b48Spatrick if (Result.FailedOn) {
34609467b48Spatrick reportGISelFailure(MF, TPC, MORE, "gisel-legalize",
34709467b48Spatrick "unable to legalize instruction", *Result.FailedOn);
34809467b48Spatrick return false;
34909467b48Spatrick }
35009467b48Spatrick // For now don't support if new blocks are inserted - we would need to fix the
35109467b48Spatrick // outer loop for that.
35209467b48Spatrick if (MF.size() != NumBlocks) {
35309467b48Spatrick MachineOptimizationRemarkMissed R("gisel-legalize", "GISelFailure",
35409467b48Spatrick MF.getFunction().getSubprogram(),
35509467b48Spatrick /*MBB=*/nullptr);
35609467b48Spatrick R << "inserting blocks is not supported yet";
35709467b48Spatrick reportGISelFailure(MF, TPC, MORE, R);
35809467b48Spatrick return false;
35909467b48Spatrick }
360097a140dSpatrick
361097a140dSpatrick if (LocObserver.getNumLostDebugLocs()) {
362097a140dSpatrick MachineOptimizationRemarkMissed R("gisel-legalize", "LostDebugLoc",
363097a140dSpatrick MF.getFunction().getSubprogram(),
364097a140dSpatrick /*MBB=*/&*MF.begin());
365097a140dSpatrick R << "lost "
366097a140dSpatrick << ore::NV("NumLostDebugLocs", LocObserver.getNumLostDebugLocs())
367097a140dSpatrick << " debug locations during pass";
368097a140dSpatrick reportGISelWarning(MF, TPC, MORE, R);
369097a140dSpatrick // Example remark:
370097a140dSpatrick // --- !Missed
371097a140dSpatrick // Pass: gisel-legalize
372097a140dSpatrick // Name: GISelFailure
373097a140dSpatrick // DebugLoc: { File: '.../legalize-urem.mir', Line: 1, Column: 0 }
374097a140dSpatrick // Function: test_urem_s32
375097a140dSpatrick // Args:
376097a140dSpatrick // - String: 'lost '
377097a140dSpatrick // - NumLostDebugLocs: '1'
378097a140dSpatrick // - String: ' debug locations during pass'
379097a140dSpatrick // ...
380097a140dSpatrick }
381097a140dSpatrick
382097a140dSpatrick // If for some reason CSE was not enabled, make sure that we invalidate the
383097a140dSpatrick // CSEInfo object (as we currently declare that the analysis is preserved).
384097a140dSpatrick // The next time get on the wrapper is called, it will force it to recompute
385097a140dSpatrick // the analysis.
386097a140dSpatrick if (!EnableCSE)
387097a140dSpatrick Wrapper.setComputed(false);
38809467b48Spatrick return Result.Changed;
38909467b48Spatrick }
390