Index: include/llvm/Analysis/AliasAnalysis.h =================================================================== --- include/llvm/Analysis/AliasAnalysis.h +++ include/llvm/Analysis/AliasAnalysis.h @@ -970,6 +970,26 @@ FunctionPass *createAAResultsWrapperPass(); +/// A wrapper pass to provide the legacy pass manager access to the empty +/// AAResults object, that always provides conservative results. +class NoAAResultsWrapperPass : public FunctionPass { + std::unique_ptr AAR; + +public: + static char ID; + + NoAAResultsWrapperPass(); + + AAResults &getAAResults() { return *AAR; } + const AAResults &getAAResults() const { return *AAR; } + + bool runOnFunction(Function &F) override; + + void getAnalysisUsage(AnalysisUsage &AU) const override; +}; + +FunctionPass *createNoAAResultsWrapperPass(); + /// A wrapper pass around a callback which can be used to populate the /// AAResults in the AAResultsWrapperPass from an external AA. /// Index: include/llvm/CodeGen/Passes.h =================================================================== --- include/llvm/CodeGen/Passes.h +++ include/llvm/CodeGen/Passes.h @@ -101,10 +101,9 @@ /// LiveStacks pass. An analysis keeping track of the liveness of stack slots. extern char &LiveStacksID; - /// TwoAddressInstruction - This pass reduces two-address instructions to - /// use two operands. This destroys SSA information but it is desired by - /// register allocators. - extern char &TwoAddressInstructionPassID; + /// This pass reduces two-address instructions to use two operands. This + /// destroys SSA information but it is desired by register allocators. + FunctionPass *createTwoAddressInstructionPass(bool UseAA); /// ProcessImpicitDefs pass - This pass removes IMPLICIT_DEFs. extern char &ProcessImplicitDefsID; Index: include/llvm/InitializePasses.h =================================================================== --- include/llvm/InitializePasses.h +++ include/llvm/InitializePasses.h @@ -261,6 +261,7 @@ void initializeNameAnonGlobalLegacyPassPass(PassRegistry&); void initializeNaryReassociateLegacyPassPass(PassRegistry&); void initializeNewGVNLegacyPassPass(PassRegistry&); +void initializeNoAAResultsWrapperPassPass(PassRegistry&); void initializeObjCARCAAWrapperPassPass(PassRegistry&); void initializeObjCARCAPElimPass(PassRegistry&); void initializeObjCARCContractPass(PassRegistry&); Index: lib/Analysis/AliasAnalysis.cpp =================================================================== --- lib/Analysis/AliasAnalysis.cpp +++ lib/Analysis/AliasAnalysis.cpp @@ -668,6 +668,40 @@ AU.addUsedIfAvailable(); } +NoAAResultsWrapperPass::NoAAResultsWrapperPass() : FunctionPass(ID) { + initializeNoAAResultsWrapperPassPass(*PassRegistry::getPassRegistry()); +} + +char NoAAResultsWrapperPass::ID = 0; + +INITIALIZE_PASS_BEGIN(NoAAResultsWrapperPass, "noaa", + "No (conservative) Function Alias Analysis Results", false, true) +INITIALIZE_PASS_END(NoAAResultsWrapperPass, "noaa", + "No (conservative) Function Alias Analysis Results", false, true) + +FunctionPass *llvm::createNoAAResultsWrapperPass() { + return new NoAAResultsWrapperPass(); +} + +bool NoAAResultsWrapperPass::runOnFunction(Function &F) { + // NB! This *must* be reset before adding new AA results to the new + // AAResults object because in the legacy pass manager, each instance + // of these will refer to the *same* immutable analyses, registering and + // unregistering themselves with them. We need to carefully tear down the + // previous object first, in this case replacing it with an empty one, before + // registering new results. + AAR.reset( + new AAResults(getAnalysis().getTLI())); + + // Analyses don't mutate the IR, so return false. + return false; +} + +void NoAAResultsWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired(); +} + AAResults llvm::createLegacyPMAAResults(Pass &P, Function &F, BasicAAResult &BAR) { AAResults AAR(P.getAnalysis().getTLI()); Index: lib/Analysis/Analysis.cpp =================================================================== --- lib/Analysis/Analysis.cpp +++ lib/Analysis/Analysis.cpp @@ -65,6 +65,7 @@ initializeMemoryDependenceWrapperPassPass(Registry); initializeModuleDebugInfoPrinterPass(Registry); initializeModuleSummaryIndexWrapperPassPass(Registry); + initializeNoAAResultsWrapperPassPass(Registry); initializeObjCARCAAWrapperPassPass(Registry); initializeOptimizationRemarkEmitterWrapperPassPass(Registry); initializePostDominatorTreeWrapperPassPass(Registry); Index: lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -305,6 +305,7 @@ initializeBranchProbabilityInfoWrapperPassPass( *PassRegistry::getPassRegistry()); initializeAAResultsWrapperPassPass(*PassRegistry::getPassRegistry()); + initializeNoAAResultsWrapperPassPass(*PassRegistry::getPassRegistry()); initializeTargetLibraryInfoWrapperPassPass( *PassRegistry::getPassRegistry()); } @@ -316,7 +317,11 @@ } void SelectionDAGISel::getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired(); + // Always require NoAAResultsWrapper, as we might end up using it for an + // optnone function. + AU.addRequired(); + if (OptLevel != CodeGenOpt::None) + AU.addRequired(); AU.addRequired(); AU.addRequired(); AU.addPreserved(); @@ -393,11 +398,15 @@ TII = MF->getSubtarget().getInstrInfo(); TLI = MF->getSubtarget().getTargetLowering(); RegInfo = &MF->getRegInfo(); - AA = &getAnalysis().getAAResults(); LibInfo = &getAnalysis().getTLI(); GFI = Fn.hasGC() ? &getAnalysis().getFunctionInfo(Fn) : nullptr; ORE = make_unique(&Fn); + if (OptLevel == CodeGenOpt::None) + AA = &getAnalysis().getAAResults(); + else + AA = &getAnalysis().getAAResults(); + DEBUG(dbgs() << "\n\n\n=== " << Fn.getName() << "\n"); SplitCriticalSideEffectEdges(const_cast(Fn)); Index: lib/CodeGen/TargetPassConfig.cpp =================================================================== --- lib/CodeGen/TargetPassConfig.cpp +++ lib/CodeGen/TargetPassConfig.cpp @@ -819,7 +819,7 @@ /// register allocation. No coalescing or scheduling. void TargetPassConfig::addFastRegAlloc(FunctionPass *RegAllocPass) { addPass(&PHIEliminationID, false); - addPass(&TwoAddressInstructionPassID, false); + addPass(createTwoAddressInstructionPass(getOptLevel()), false); if (RegAllocPass) addPass(RegAllocPass); @@ -849,7 +849,7 @@ if (EarlyLiveIntervals) addPass(&LiveIntervalsID, false); - addPass(&TwoAddressInstructionPassID, false); + addPass(createTwoAddressInstructionPass(getOptLevel()), false); addPass(&RegisterCoalescerID); // The machine scheduler may accidentally create disconnected components Index: lib/CodeGen/TwoAddressInstructionPass.cpp =================================================================== --- lib/CodeGen/TwoAddressInstructionPass.cpp +++ lib/CodeGen/TwoAddressInstructionPass.cpp @@ -80,6 +80,9 @@ AliasAnalysis *AA; CodeGenOpt::Level OptLevel; + // Whether we're permitted to use AliasAnalysis, via AAResultsWrapperPass. + bool UseAA; + // The current basic block being processed. MachineBasicBlock *MBB; @@ -149,13 +152,17 @@ public: static char ID; // Pass identification, replacement for typeid - TwoAddressInstructionPass() : MachineFunctionPass(ID) { + TwoAddressInstructionPass(bool UseAA = false) + : MachineFunctionPass(ID), UseAA(UseAA) { initializeTwoAddressInstructionPassPass(*PassRegistry::getPassRegistry()); } void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesCFG(); - AU.addRequired(); + if (UseAA) + AU.addRequired(); + else + AU.addRequired(); AU.addUsedIfAvailable(); AU.addPreserved(); AU.addPreserved(); @@ -173,11 +180,16 @@ char TwoAddressInstructionPass::ID = 0; INITIALIZE_PASS_BEGIN(TwoAddressInstructionPass, "twoaddressinstruction", "Two-Address instruction pass", false, false) +INITIALIZE_PASS_DEPENDENCY(NoAAResultsWrapperPass) INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass) INITIALIZE_PASS_END(TwoAddressInstructionPass, "twoaddressinstruction", "Two-Address instruction pass", false, false) -char &llvm::TwoAddressInstructionPassID = TwoAddressInstructionPass::ID; +//char &llvm::TwoAddressInstructionPassID = TwoAddressInstructionPass::ID; + +FunctionPass *llvm::createTwoAddressInstructionPass(bool UseAA) { + return new TwoAddressInstructionPass(UseAA); +} static bool isPlainlyKilled(MachineInstr *MI, unsigned Reg, LiveIntervals *LIS); @@ -1627,7 +1639,10 @@ InstrItins = MF->getSubtarget().getInstrItineraryData(); LV = getAnalysisIfAvailable(); LIS = getAnalysisIfAvailable(); - AA = &getAnalysis().getAAResults(); + if (UseAA) + AA = &getAnalysis().getAAResults(); + else + AA = &getAnalysis().getAAResults(); OptLevel = TM.getOptLevel(); bool MadeChange = false; Index: lib/Target/NVPTX/NVPTXTargetMachine.cpp =================================================================== --- lib/Target/NVPTX/NVPTXTargetMachine.cpp +++ lib/Target/NVPTX/NVPTXTargetMachine.cpp @@ -297,7 +297,7 @@ void NVPTXPassConfig::addFastRegAlloc(FunctionPass *RegAllocPass) { assert(!RegAllocPass && "NVPTX uses no regalloc!"); addPass(&PHIEliminationID); - addPass(&TwoAddressInstructionPassID); + addPass(createTwoAddressInstructionPass(getOptLevel())); } void NVPTXPassConfig::addOptimizedRegAlloc(FunctionPass *RegAllocPass) { @@ -308,7 +308,7 @@ addPass(&MachineLoopInfoID); addPass(&PHIEliminationID); - addPass(&TwoAddressInstructionPassID); + addPass(createTwoAddressInstructionPass(getOptLevel())); addPass(&RegisterCoalescerID); // PreRA instruction scheduling. Index: test/CodeGen/X86/O0-pipeline.ll =================================================================== --- test/CodeGen/X86/O0-pipeline.ll +++ test/CodeGen/X86/O0-pipeline.ll @@ -29,15 +29,14 @@ ; CHECK-NEXT: Safe Stack instrumentation pass ; CHECK-NEXT: Insert stack protectors ; CHECK-NEXT: Module Verifier -; CHECK-NEXT: Dominator Tree Construction -; CHECK-NEXT: Basic Alias Analysis (stateless AA impl) -; CHECK-NEXT: Function Alias Analysis Results +; CHECK-NEXT: No (conservative) Function Alias Analysis Results ; CHECK-NEXT: X86 DAG->DAG Instruction Selection ; CHECK-NEXT: X86 PIC Global Base Reg Initialization ; CHECK-NEXT: Expand ISel Pseudo-instructions ; CHECK-NEXT: Local Stack Slot Allocation ; CHECK-NEXT: X86 WinAlloca Expander ; CHECK-NEXT: Eliminate PHI nodes for register allocation +; CHECK-NEXT: No (conservative) Function Alias Analysis Results ; CHECK-NEXT: Two-Address instruction pass ; CHECK-NEXT: Fast Register Allocator ; CHECK-NEXT: Bundle Machine CFG Edges Index: test/CodeGen/X86/pr32284.ll =================================================================== --- test/CodeGen/X86/pr32284.ll +++ test/CodeGen/X86/pr32284.ll @@ -30,25 +30,24 @@ ; X86-O0-NEXT: subl $12, %esp ; X86-O0-NEXT: .Lcfi0: ; X86-O0-NEXT: .cfi_def_cfa_offset 16 -; X86-O0-NEXT: movzbl c, %eax -; X86-O0-NEXT: testl %eax, %eax -; X86-O0-NEXT: setne %cl -; X86-O0-NEXT: movl %eax, %edx -; X86-O0-NEXT: movb %dl, %ch -; X86-O0-NEXT: testb %ch, %ch +; X86-O0-NEXT: movb c, %al +; X86-O0-NEXT: testb %al, %al ; X86-O0-NEXT: setne {{[0-9]+}}(%esp) -; X86-O0-NEXT: movzbl %cl, %edx -; X86-O0-NEXT: subl %eax, %edx -; X86-O0-NEXT: setle %cl -; X86-O0-NEXT: # implicit-def: %EAX -; X86-O0-NEXT: movb %cl, %al -; X86-O0-NEXT: andl $1, %eax -; X86-O0-NEXT: kmovd %eax, %k0 -; X86-O0-NEXT: kmovd %k0, %eax +; X86-O0-NEXT: movzbl c, %ecx +; X86-O0-NEXT: testl %ecx, %ecx +; X86-O0-NEXT: setne %al +; X86-O0-NEXT: movzbl %al, %edx +; X86-O0-NEXT: subl %ecx, %edx +; X86-O0-NEXT: setle %al +; X86-O0-NEXT: # implicit-def: %ECX ; X86-O0-NEXT: movb %al, %cl -; X86-O0-NEXT: andb $1, %cl -; X86-O0-NEXT: movzbl %cl, %eax -; X86-O0-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-O0-NEXT: andl $1, %ecx +; X86-O0-NEXT: kmovd %ecx, %k0 +; X86-O0-NEXT: kmovd %k0, %ecx +; X86-O0-NEXT: movb %cl, %al +; X86-O0-NEXT: andb $1, %al +; X86-O0-NEXT: movzbl %al, %ecx +; X86-O0-NEXT: movl %ecx, {{[0-9]+}}(%esp) ; X86-O0-NEXT: movl %edx, (%esp) # 4-byte Spill ; X86-O0-NEXT: addl $12, %esp ; X86-O0-NEXT: retl @@ -69,27 +68,25 @@ ; ; X64-O0-LABEL: foo: ; X64-O0: # BB#0: # %entry -; X64-O0-NEXT: movzbl {{.*}}(%rip), %eax -; X64-O0-NEXT: movl %eax, %ecx -; X64-O0-NEXT: movb %cl, %dl -; X64-O0-NEXT: movl %ecx, %eax -; X64-O0-NEXT: testq %rcx, %rcx -; X64-O0-NEXT: setne %sil -; X64-O0-NEXT: testb %dl, %dl +; X64-O0-NEXT: movb {{.*}}(%rip), %al +; X64-O0-NEXT: testb %al, %al ; X64-O0-NEXT: setne -{{[0-9]+}}(%rsp) -; X64-O0-NEXT: movzbl %sil, %edi -; X64-O0-NEXT: subl %eax, %edi -; X64-O0-NEXT: setle %dl -; X64-O0-NEXT: # implicit-def: %EAX -; X64-O0-NEXT: movb %dl, %al -; X64-O0-NEXT: andl $1, %eax -; X64-O0-NEXT: kmovd %eax, %k0 -; X64-O0-NEXT: kmovd %k0, %eax -; X64-O0-NEXT: movb %al, %dl -; X64-O0-NEXT: andb $1, %dl -; X64-O0-NEXT: movzbl %dl, %eax -; X64-O0-NEXT: movl %eax, -{{[0-9]+}}(%rsp) -; X64-O0-NEXT: movl %edi, -{{[0-9]+}}(%rsp) # 4-byte Spill +; X64-O0-NEXT: movzbl {{.*}}(%rip), %ecx +; X64-O0-NEXT: testl %ecx, %ecx +; X64-O0-NEXT: setne %al +; X64-O0-NEXT: movzbl %al, %edx +; X64-O0-NEXT: subl %ecx, %edx +; X64-O0-NEXT: setle %al +; X64-O0-NEXT: # implicit-def: %ECX +; X64-O0-NEXT: movb %al, %cl +; X64-O0-NEXT: andl $1, %ecx +; X64-O0-NEXT: kmovd %ecx, %k0 +; X64-O0-NEXT: kmovd %k0, %ecx +; X64-O0-NEXT: movb %cl, %al +; X64-O0-NEXT: andb $1, %al +; X64-O0-NEXT: movzbl %al, %ecx +; X64-O0-NEXT: movl %ecx, -{{[0-9]+}}(%rsp) +; X64-O0-NEXT: movl %edx, -{{[0-9]+}}(%rsp) # 4-byte Spill ; X64-O0-NEXT: retq entry: %a = alloca i8, align 1