From 7c1bd8a74b6da21a991084fefe3b24a1a1e95a67 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Tue, 11 Sep 2018 11:47:14 +0200 Subject: [PATCH 1/4] remove useless patches (already on upstream) --- debian/patches/D51108-rust-powerpc.diff | 65 - debian/patches/D51335-alignment-issue.diff | 107 -- debian/patches/D51639-optim-issue.diff | 46 - debian/patches/pr38663-pgo-lto-crash.patch | 1573 ----------------- ...-cherry-pick-really-subtle-miscompile.diff | 153 -- 5 files changed, 1944 deletions(-) delete mode 100644 debian/patches/D51108-rust-powerpc.diff delete mode 100644 debian/patches/D51335-alignment-issue.diff delete mode 100644 debian/patches/D51639-optim-issue.diff delete mode 100644 debian/patches/pr38663-pgo-lto-crash.patch delete mode 100644 debian/patches/rL338481-cherry-pick-really-subtle-miscompile.diff diff --git a/debian/patches/D51108-rust-powerpc.diff b/debian/patches/D51108-rust-powerpc.diff deleted file mode 100644 index aa7f7196..00000000 --- a/debian/patches/D51108-rust-powerpc.diff +++ /dev/null @@ -1,65 +0,0 @@ -Index: llvm-toolchain-6.0-6.0.1/lib/Target/PowerPC/PPCISelLowering.cpp -=================================================================== ---- llvm-toolchain-6.0-6.0.1.orig/lib/Target/PowerPC/PPCISelLowering.cpp -+++ llvm-toolchain-6.0-6.0.1/lib/Target/PowerPC/PPCISelLowering.cpp -@@ -3351,9 +3351,14 @@ - // Argument stored in memory. - assert(VA.isMemLoc()); - -+ // Get the extended size of the argument type in stack - unsigned ArgSize = VA.getLocVT().getStoreSize(); -- int FI = MFI.CreateFixedObject(ArgSize, VA.getLocMemOffset(), -- isImmutable); -+ // Get the actual size of the argument type -+ unsigned ObjSize = VA.getValVT().getStoreSize(); -+ unsigned ArgOffset = VA.getLocMemOffset(); -+ // Stack objects in PPC32 are right justified. -+ ArgOffset += ArgSize - ObjSize; -+ int FI = MFI.CreateFixedObject(ArgSize, ArgOffset, isImmutable); - - // Create load nodes to retrieve arguments from the stack. - SDValue FIN = DAG.getFrameIndex(FI, PtrVT); -@@ -5303,10 +5308,11 @@ - Arg = PtrOff; - } - -- if (VA.isRegLoc()) { -- if (Arg.getValueType() == MVT::i1) -- Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i32, Arg); -+ // Ensure callee will get either 0x00000001 or 0x00000000. -+ if (Arg.getValueType() == MVT::i1) -+ Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i32, Arg); - -+ if (VA.isRegLoc()) { - seenFloatArg |= VA.getLocVT().isFloatingPoint(); - // Put argument in a physical register. - RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); -Index: llvm-toolchain-6.0-6.0.1/test/CodeGen/PowerPC/ppc32-i1-stack-arguments-abi-bug.ll -=================================================================== ---- /dev/null -+++ llvm-toolchain-6.0-6.0.1/test/CodeGen/PowerPC/ppc32-i1-stack-arguments-abi-bug.ll -@@ -0,0 +1,24 @@ -+; RUN: llc -verify-machineinstrs < %s -mcpu=ppc32 -mattr=+crbits | FileCheck %s -+target triple = "powerpc-unknown-linux-gnu" -+ -+define zeroext i1 @check_callee( -+ i1 zeroext, i1 zeroext, i1 zeroext, i1 zeroext, -+ i1 zeroext, i1 zeroext, i1 zeroext, i1 zeroext, -+ i1 zeroext %s1 -+) { -+ call void @check_caller( -+ i1 zeroext true, i1 zeroext true, i1 zeroext true, i1 zeroext true, -+ i1 zeroext true, i1 zeroext true, i1 zeroext true, i1 zeroext true, -+ i1 zeroext %s1) -+ ret i1 true -+} -+ -+; CHECK-LABEL: @check_callee -+; CHECK: lbz {{[0-9]+}}, 27(1) -+; CHECK: stw {{[0-9]+}}, 8(1) -+ -+declare void @check_caller( -+ i1 zeroext, i1 zeroext, i1 zeroext, i1 zeroext, -+ i1 zeroext, i1 zeroext, i1 zeroext, i1 zeroext, -+ i1 zeroext -+) diff --git a/debian/patches/D51335-alignment-issue.diff b/debian/patches/D51335-alignment-issue.diff deleted file mode 100644 index 6c8589cd..00000000 --- a/debian/patches/D51335-alignment-issue.diff +++ /dev/null @@ -1,107 +0,0 @@ -Index: llvm-toolchain-6.0-6.0.1/lib/Transforms/Scalar/SROA.cpp -=================================================================== ---- llvm-toolchain-6.0-6.0.1.orig/lib/Transforms/Scalar/SROA.cpp -+++ llvm-toolchain-6.0-6.0.1/lib/Transforms/Scalar/SROA.cpp -@@ -2987,6 +2987,42 @@ private: - return true; - } - -+ void fixLoadStoreAlign(Instruction &Root) { -+ // This algorithm implements the same visitor loop as -+ // hasUnsafePHIOrSelectUse, and fixes the alignment of each load -+ // or store found. -+ SmallPtrSet Visited; -+ SmallVector Uses; -+ Visited.insert(&Root); -+ Uses.push_back(&Root); -+ do { -+ Instruction *I = Uses.pop_back_val(); -+ -+ if (LoadInst *LI = dyn_cast(I)) { -+ unsigned LoadAlign = LI->getAlignment(); -+ if (!LoadAlign) -+ LoadAlign = DL.getABITypeAlignment(LI->getType()); -+ LI->setAlignment(std::min(LoadAlign, getSliceAlign())); -+ continue; -+ } -+ if (StoreInst *SI = dyn_cast(I)) { -+ unsigned StoreAlign = SI->getAlignment(); -+ if (!StoreAlign) { -+ Value *Op = SI->getOperand(0); -+ StoreAlign = DL.getABITypeAlignment(Op->getType()); -+ } -+ SI->setAlignment(std::min(StoreAlign, getSliceAlign())); -+ continue; -+ } -+ -+ assert(isa(I) || isa(I) || -+ isa(I) || isa(I)); -+ for (User *U : I->users()) -+ if (Visited.insert(cast(U)).second) -+ Uses.push_back(cast(U)); -+ } while (!Uses.empty()); -+ } -+ - bool visitPHINode(PHINode &PN) { - DEBUG(dbgs() << " original: " << PN << "\n"); - assert(BeginOffset >= NewAllocaBeginOffset && "PHIs are unsplittable"); -@@ -3010,6 +3046,9 @@ private: - DEBUG(dbgs() << " to: " << PN << "\n"); - deleteIfTriviallyDead(OldPtr); - -+ // Fix the alignment of any loads or stores using this PHI node. -+ fixLoadStoreAlign(PN); -+ - // PHIs can't be promoted on their own, but often can be speculated. We - // check the speculation outside of the rewriter so that we see the - // fully-rewritten alloca. -@@ -3034,6 +3073,9 @@ private: - DEBUG(dbgs() << " to: " << SI << "\n"); - deleteIfTriviallyDead(OldPtr); - -+ // Fix the alignment of any loads or stores using this select. -+ fixLoadStoreAlign(SI); -+ - // Selects can't be promoted on their own, but often can be speculated. We - // check the speculation outside of the rewriter so that we see the - // fully-rewritten alloca. -Index: llvm-toolchain-6.0-6.0.1/test/Transforms/SROA/phi-and-select.ll -=================================================================== ---- llvm-toolchain-6.0-6.0.1.orig/test/Transforms/SROA/phi-and-select.ll -+++ llvm-toolchain-6.0-6.0.1/test/Transforms/SROA/phi-and-select.ll -@@ -600,3 +600,35 @@ if.then5: - store %struct.S undef, %struct.S* %f1, align 4 - ret void - } -+ -+define i32 @phi_align(i32* %z) { -+; CHECK-LABEL: @phi_align( -+entry: -+ %a = alloca [8 x i8], align 8 -+; CHECK: alloca [7 x i8] -+ -+ %a0x = getelementptr [8 x i8], [8 x i8]* %a, i64 0, i32 1 -+ %a0 = bitcast i8* %a0x to i32* -+ %a1x = getelementptr [8 x i8], [8 x i8]* %a, i64 0, i32 4 -+ %a1 = bitcast i8* %a1x to i32* -+; CHECK: store i32 0, {{.*}}, align 1 -+ store i32 0, i32* %a0, align 1 -+; CHECK: store i32 1, {{.*}}, align 1 -+ store i32 1, i32* %a1, align 4 -+; CHECK: load {{.*}}, align 1 -+ %v0 = load i32, i32* %a0, align 1 -+; CHECK: load {{.*}}, align 1 -+ %v1 = load i32, i32* %a1, align 4 -+ %cond = icmp sle i32 %v0, %v1 -+ br i1 %cond, label %then, label %exit -+ -+then: -+ br label %exit -+ -+exit: -+; CHECK: %phi = phi i32* [ {{.*}}, %then ], [ %z, %entry ] -+; CHECK-NEXT: %result = load i32, i32* %phi, align 1 -+ %phi = phi i32* [ %a1, %then ], [ %z, %entry ] -+ %result = load i32, i32* %phi, align 4 -+ ret i32 %result -+} diff --git a/debian/patches/D51639-optim-issue.diff b/debian/patches/D51639-optim-issue.diff deleted file mode 100644 index 791ef595..00000000 --- a/debian/patches/D51639-optim-issue.diff +++ /dev/null @@ -1,46 +0,0 @@ -Index: llvm-toolchain-6.0-6.0.1/lib/Transforms/Vectorize/LoopVectorize.cpp -=================================================================== ---- llvm-toolchain-6.0-6.0.1.orig/lib/Transforms/Vectorize/LoopVectorize.cpp -+++ llvm-toolchain-6.0-6.0.1/lib/Transforms/Vectorize/LoopVectorize.cpp -@@ -4529,6 +4529,11 @@ - // isOutOfScope operands cannot be uniform instructions. - if (isOutOfScope(OV)) - continue; -+ // First order recurrence Phi's should typically be considered -+ // non-uniform. -+ auto *OP = dyn_cast(OV); -+ if (OP && Legal->isFirstOrderRecurrence(OP)) -+ continue; - // If all the users of the operand are uniform, then add the - // operand into the uniform worklist. - auto *OI = cast(OV); -Index: llvm-toolchain-6.0-6.0.1/test/Transforms/LoopVectorize/X86/uniform-phi.ll -=================================================================== ---- llvm-toolchain-6.0-6.0.1.orig/test/Transforms/LoopVectorize/X86/uniform-phi.ll -+++ llvm-toolchain-6.0-6.0.1/test/Transforms/LoopVectorize/X86/uniform-phi.ll -@@ -75,3 +75,25 @@ - ret i64 %retval - } - -+; CHECK-LABEL: PR38786 -+; Check that first order recurrence phis (%phi32 and %phi64) are not uniform. -+; CHECK-NOT: LV: Found uniform instruction: %phi -+define void @PR38786(double* %y, double* %x, i64 %n) { -+entry: -+ br label %for.body -+ -+for.body: -+ %phi32 = phi i32 [ 0, %entry ], [ %i32next, %for.body ] -+ %phi64 = phi i64 [ 0, %entry ], [ %i64next, %for.body ] -+ %i32next = add i32 %phi32, 1 -+ %i64next = zext i32 %i32next to i64 -+ %xip = getelementptr inbounds double, double* %x, i64 %i64next -+ %yip = getelementptr inbounds double, double* %y, i64 %phi64 -+ %xi = load double, double* %xip, align 8 -+ store double %xi, double* %yip, align 8 -+ %cmp = icmp slt i64 %i64next, %n -+ br i1 %cmp, label %for.body, label %for.end -+ -+for.end: -+ ret void -+} diff --git a/debian/patches/pr38663-pgo-lto-crash.patch b/debian/patches/pr38663-pgo-lto-crash.patch deleted file mode 100644 index 16db4086..00000000 --- a/debian/patches/pr38663-pgo-lto-crash.patch +++ /dev/null @@ -1,1573 +0,0 @@ -Index: llvm-toolchain-6.0-6.0.1/lib/CodeGen/PeepholeOptimizer.cpp -=================================================================== ---- llvm-toolchain-6.0-6.0.1.orig/lib/CodeGen/PeepholeOptimizer.cpp -+++ llvm-toolchain-6.0-6.0.1/lib/CodeGen/PeepholeOptimizer.cpp -@@ -98,6 +98,8 @@ - #include - - using namespace llvm; -+using RegSubRegPair = TargetInstrInfo::RegSubRegPair; -+using RegSubRegPairAndIdx = TargetInstrInfo::RegSubRegPairAndIdx; - - #define DEBUG_TYPE "peephole-opt" - -@@ -110,6 +112,9 @@ static cl::opt - DisablePeephole("disable-peephole", cl::Hidden, cl::init(false), - cl::desc("Disable the peephole optimizer")); - -+/// Specifiy whether or not the value tracking looks through -+/// complex instructions. When this is true, the value tracker -+/// bails on everything that is not a copy or a bitcast. - static cl::opt - DisableAdvCopyOpt("disable-adv-copy-opt", cl::Hidden, cl::init(false), - cl::desc("Disable advanced copy optimization")); -@@ -132,11 +137,11 @@ static cl::opt MaxRecurrenceCh - "of commuting operands")); - - --STATISTIC(NumReuse, "Number of extension results reused"); --STATISTIC(NumCmps, "Number of compares eliminated"); --STATISTIC(NumImmFold, "Number of move immediate folded"); --STATISTIC(NumLoadFold, "Number of loads folded"); --STATISTIC(NumSelects, "Number of selects optimized"); -+STATISTIC(NumReuse, "Number of extension results reused"); -+STATISTIC(NumCmps, "Number of compares eliminated"); -+STATISTIC(NumImmFold, "Number of move immediate folded"); -+STATISTIC(NumLoadFold, "Number of loads folded"); -+STATISTIC(NumSelects, "Number of selects optimized"); - STATISTIC(NumUncoalescableCopies, "Number of uncoalescable copies optimized"); - STATISTIC(NumRewrittenCopies, "Number of copies rewritten"); - STATISTIC(NumNAPhysCopies, "Number of non-allocatable physical copies removed"); -@@ -149,9 +154,9 @@ namespace { - class PeepholeOptimizer : public MachineFunctionPass { - const TargetInstrInfo *TII; - const TargetRegisterInfo *TRI; -- MachineRegisterInfo *MRI; -- MachineDominatorTree *DT; // Machine dominator tree -- MachineLoopInfo *MLI; -+ MachineRegisterInfo *MRI; -+ MachineDominatorTree *DT; // Machine dominator tree -+ MachineLoopInfo *MLI; - - public: - static char ID; // Pass identification -@@ -173,31 +178,28 @@ namespace { - } - } - -- /// \brief Track Def -> Use info used for rewriting copies. -- using RewriteMapTy = -- SmallDenseMap; -+ /// Track Def -> Use info used for rewriting copies. -+ using RewriteMapTy = SmallDenseMap; - -- /// \brief Sequence of instructions that formulate recurrence cycle. -+ /// Sequence of instructions that formulate recurrence cycle. - using RecurrenceCycle = SmallVector; - - private: -- bool optimizeCmpInstr(MachineInstr *MI, MachineBasicBlock *MBB); -- bool optimizeExtInstr(MachineInstr *MI, MachineBasicBlock *MBB, -+ bool optimizeCmpInstr(MachineInstr &MI); -+ bool optimizeExtInstr(MachineInstr &MI, MachineBasicBlock &MBB, - SmallPtrSetImpl &LocalMIs); -- bool optimizeSelect(MachineInstr *MI, -+ bool optimizeSelect(MachineInstr &MI, - SmallPtrSetImpl &LocalMIs); -- bool optimizeCondBranch(MachineInstr *MI); -- bool optimizeCoalescableCopy(MachineInstr *MI); -- bool optimizeUncoalescableCopy(MachineInstr *MI, -+ bool optimizeCondBranch(MachineInstr &MI); -+ bool optimizeCoalescableCopy(MachineInstr &MI); -+ bool optimizeUncoalescableCopy(MachineInstr &MI, - SmallPtrSetImpl &LocalMIs); - bool optimizeRecurrence(MachineInstr &PHI); -- bool findNextSource(unsigned Reg, unsigned SubReg, -- RewriteMapTy &RewriteMap); -- bool isMoveImmediate(MachineInstr *MI, -+ bool findNextSource(RegSubRegPair RegSubReg, RewriteMapTy &RewriteMap); -+ bool isMoveImmediate(MachineInstr &MI, - SmallSet &ImmDefRegs, - DenseMap &ImmDefMIs); -- bool foldImmediate(MachineInstr *MI, MachineBasicBlock *MBB, -- SmallSet &ImmDefRegs, -+ bool foldImmediate(MachineInstr &MI, SmallSet &ImmDefRegs, - DenseMap &ImmDefMIs); - - /// \brief Finds recurrence cycles, but only ones that formulated around -@@ -212,11 +214,11 @@ namespace { - /// the set \p CopySrcRegs and \p CopyMIs. If this virtual register was - /// previously seen as a copy, replace the uses of this copy with the - /// previously seen copy's destination register. -- bool foldRedundantCopy(MachineInstr *MI, -+ bool foldRedundantCopy(MachineInstr &MI, - SmallSet &CopySrcRegs, - DenseMap &CopyMIs); - -- /// \brief Is the register \p Reg a non-allocatable physical register? -+ /// Is the register \p Reg a non-allocatable physical register? - bool isNAPhysCopy(unsigned Reg); - - /// \brief If copy instruction \p MI is a non-allocatable virtual<->physical -@@ -224,11 +226,10 @@ namespace { - /// non-allocatable physical register was previously copied to a virtual - /// registered and hasn't been clobbered, the virt->phys copy can be - /// deleted. -- bool foldRedundantNAPhysCopy( -- MachineInstr *MI, -+ bool foldRedundantNAPhysCopy(MachineInstr &MI, - DenseMap &NAPhysToVirtMIs); - -- bool isLoadFoldable(MachineInstr *MI, -+ bool isLoadFoldable(MachineInstr &MI, - SmallSet &FoldAsLoadDefCandidates); - - /// \brief Check whether \p MI is understood by the register coalescer -@@ -249,10 +250,13 @@ namespace { - (MI.isRegSequenceLike() || MI.isInsertSubregLike() || - MI.isExtractSubregLike())); - } -+ -+ MachineInstr &rewriteSource(MachineInstr &CopyLike, -+ RegSubRegPair Def, RewriteMapTy &RewriteMap); - }; - -- /// \brief Helper class to hold instructions that are inside recurrence -- /// cycles. The recurrence cycle is formulated around 1) a def operand and its -+ /// Helper class to hold instructions that are inside recurrence cycles. -+ /// The recurrence cycle is formulated around 1) a def operand and its - /// tied use operand, or 2) a def operand and a use operand that is commutable - /// with another use operand which is tied to the def operand. In the latter - /// case, index of the tied use operand and the commutable use operand are -@@ -273,13 +277,13 @@ namespace { - Optional CommutePair; - }; - -- /// \brief Helper class to hold a reply for ValueTracker queries. Contains the -- /// returned sources for a given search and the instructions where the sources -- /// were tracked from. -+ /// Helper class to hold a reply for ValueTracker queries. -+ /// Contains the returned sources for a given search and the instructions -+ /// where the sources were tracked from. - class ValueTrackerResult { - private: - /// Track all sources found by one ValueTracker query. -- SmallVector RegSrcs; -+ SmallVector RegSrcs; - - /// Instruction using the sources in 'RegSrcs'. - const MachineInstr *Inst = nullptr; -@@ -302,16 +306,20 @@ namespace { - } - - void addSource(unsigned SrcReg, unsigned SrcSubReg) { -- RegSrcs.push_back(TargetInstrInfo::RegSubRegPair(SrcReg, SrcSubReg)); -+ RegSrcs.push_back(RegSubRegPair(SrcReg, SrcSubReg)); - } - - void setSource(int Idx, unsigned SrcReg, unsigned SrcSubReg) { - assert(Idx < getNumSources() && "Reg pair source out of index"); -- RegSrcs[Idx] = TargetInstrInfo::RegSubRegPair(SrcReg, SrcSubReg); -+ RegSrcs[Idx] = RegSubRegPair(SrcReg, SrcSubReg); - } - - int getNumSources() const { return RegSrcs.size(); } - -+ RegSubRegPair getSrc(int Idx) const { -+ return RegSrcs[Idx]; -+ } -+ - unsigned getSrcReg(int Idx) const { - assert(Idx < getNumSources() && "Reg source out of index"); - return RegSrcs[Idx].Reg; -@@ -367,59 +375,41 @@ namespace { - /// The register where the value can be found. - unsigned Reg; - -- /// Specifiy whether or not the value tracking looks through -- /// complex instructions. When this is false, the value tracker -- /// bails on everything that is not a copy or a bitcast. -- /// -- /// Note: This could have been implemented as a specialized version of -- /// the ValueTracker class but that would have complicated the code of -- /// the users of this class. -- bool UseAdvancedTracking; -- - /// MachineRegisterInfo used to perform tracking. - const MachineRegisterInfo &MRI; - -- /// Optional TargetInstrInfo used to perform some complex -- /// tracking. -+ /// Optional TargetInstrInfo used to perform some complex tracking. - const TargetInstrInfo *TII; - -- /// \brief Dispatcher to the right underlying implementation of -- /// getNextSource. -+ /// Dispatcher to the right underlying implementation of getNextSource. - ValueTrackerResult getNextSourceImpl(); - -- /// \brief Specialized version of getNextSource for Copy instructions. -+ /// Specialized version of getNextSource for Copy instructions. - ValueTrackerResult getNextSourceFromCopy(); - -- /// \brief Specialized version of getNextSource for Bitcast instructions. -+ /// Specialized version of getNextSource for Bitcast instructions. - ValueTrackerResult getNextSourceFromBitcast(); - -- /// \brief Specialized version of getNextSource for RegSequence -- /// instructions. -+ /// Specialized version of getNextSource for RegSequence instructions. - ValueTrackerResult getNextSourceFromRegSequence(); - -- /// \brief Specialized version of getNextSource for InsertSubreg -- /// instructions. -+ /// Specialized version of getNextSource for InsertSubreg instructions. - ValueTrackerResult getNextSourceFromInsertSubreg(); - -- /// \brief Specialized version of getNextSource for ExtractSubreg -- /// instructions. -+ /// Specialized version of getNextSource for ExtractSubreg instructions. - ValueTrackerResult getNextSourceFromExtractSubreg(); - -- /// \brief Specialized version of getNextSource for SubregToReg -- /// instructions. -+ /// Specialized version of getNextSource for SubregToReg instructions. - ValueTrackerResult getNextSourceFromSubregToReg(); - -- /// \brief Specialized version of getNextSource for PHI instructions. -+ /// Specialized version of getNextSource for PHI instructions. - ValueTrackerResult getNextSourceFromPHI(); - - public: -- /// \brief Create a ValueTracker instance for the value defined by \p Reg. -+ /// Create a ValueTracker instance for the value defined by \p Reg. - /// \p DefSubReg represents the sub register index the value tracker will - /// track. It does not need to match the sub register index used in the - /// definition of \p Reg. -- /// \p UseAdvancedTracking specifies whether or not the value tracker looks -- /// through complex instructions. By default (false), it handles only copy -- /// and bitcast instructions. - /// If \p Reg is a physical register, a value tracker constructed with - /// this constructor will not find any alternative source. - /// Indeed, when \p Reg is a physical register that constructor does not -@@ -427,46 +417,20 @@ namespace { - /// Use the next constructor to track a physical register. - ValueTracker(unsigned Reg, unsigned DefSubReg, - const MachineRegisterInfo &MRI, -- bool UseAdvancedTracking = false, - const TargetInstrInfo *TII = nullptr) -- : DefSubReg(DefSubReg), Reg(Reg), -- UseAdvancedTracking(UseAdvancedTracking), MRI(MRI), TII(TII) { -+ : DefSubReg(DefSubReg), Reg(Reg), MRI(MRI), TII(TII) { - if (!TargetRegisterInfo::isPhysicalRegister(Reg)) { - Def = MRI.getVRegDef(Reg); - DefIdx = MRI.def_begin(Reg).getOperandNo(); - } - } - -- /// \brief Create a ValueTracker instance for the value defined by -- /// the pair \p MI, \p DefIdx. -- /// Unlike the other constructor, the value tracker produced by this one -- /// may be able to find a new source when the definition is a physical -- /// register. -- /// This could be useful to rewrite target specific instructions into -- /// generic copy instructions. -- ValueTracker(const MachineInstr &MI, unsigned DefIdx, unsigned DefSubReg, -- const MachineRegisterInfo &MRI, -- bool UseAdvancedTracking = false, -- const TargetInstrInfo *TII = nullptr) -- : Def(&MI), DefIdx(DefIdx), DefSubReg(DefSubReg), -- UseAdvancedTracking(UseAdvancedTracking), MRI(MRI), TII(TII) { -- assert(DefIdx < Def->getDesc().getNumDefs() && -- Def->getOperand(DefIdx).isReg() && "Invalid definition"); -- Reg = Def->getOperand(DefIdx).getReg(); -- } -- - /// \brief Following the use-def chain, get the next available source - /// for the tracked value. - /// \return A ValueTrackerResult containing a set of registers - /// and sub registers with tracked values. A ValueTrackerResult with - /// an empty set of registers means no source was found. - ValueTrackerResult getNextSource(); -- -- /// \brief Get the last register where the initial value can be found. -- /// Initially this is the register of the definition. -- /// Then, after each successful call to getNextSource, this is the -- /// register of the last source. -- unsigned getReg() const { return Reg; } - }; - - } // end anonymous namespace -@@ -476,11 +440,11 @@ char PeepholeOptimizer::ID = 0; - char &llvm::PeepholeOptimizerID = PeepholeOptimizer::ID; - - INITIALIZE_PASS_BEGIN(PeepholeOptimizer, DEBUG_TYPE, -- "Peephole Optimizations", false, false) -+ "Peephole Optimizations", false, false) - INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree) - INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo) - INITIALIZE_PASS_END(PeepholeOptimizer, DEBUG_TYPE, -- "Peephole Optimizations", false, false) -+ "Peephole Optimizations", false, false) - - /// If instruction is a copy-like instruction, i.e. it reads a single register - /// and writes a single register and it does not modify the source, and if the -@@ -491,10 +455,10 @@ INITIALIZE_PASS_END(PeepholeOptimizer, D - /// the code. Since this code does not currently share EXTRACTs, just ignore all - /// debug uses. - bool PeepholeOptimizer:: --optimizeExtInstr(MachineInstr *MI, MachineBasicBlock *MBB, -+optimizeExtInstr(MachineInstr &MI, MachineBasicBlock &MBB, - SmallPtrSetImpl &LocalMIs) { - unsigned SrcReg, DstReg, SubIdx; -- if (!TII->isCoalescableExtInstr(*MI, SrcReg, DstReg, SubIdx)) -+ if (!TII->isCoalescableExtInstr(MI, SrcReg, DstReg, SubIdx)) - return false; - - if (TargetRegisterInfo::isPhysicalRegister(DstReg) || -@@ -535,7 +499,7 @@ optimizeExtInstr(MachineInstr *MI, Machi - bool ExtendLife = true; - for (MachineOperand &UseMO : MRI->use_nodbg_operands(SrcReg)) { - MachineInstr *UseMI = UseMO.getParent(); -- if (UseMI == MI) -+ if (UseMI == &MI) - continue; - - if (UseMI->isPHI()) { -@@ -568,7 +532,7 @@ optimizeExtInstr(MachineInstr *MI, Machi - continue; - - MachineBasicBlock *UseMBB = UseMI->getParent(); -- if (UseMBB == MBB) { -+ if (UseMBB == &MBB) { - // Local uses that come after the extension. - if (!LocalMIs.count(UseMI)) - Uses.push_back(&UseMO); -@@ -576,7 +540,7 @@ optimizeExtInstr(MachineInstr *MI, Machi - // Non-local uses where the result of the extension is used. Always - // replace these unless it's a PHI. - Uses.push_back(&UseMO); -- } else if (Aggressive && DT->dominates(MBB, UseMBB)) { -+ } else if (Aggressive && DT->dominates(&MBB, UseMBB)) { - // We may want to extend the live range of the extension result in order - // to replace these uses. - ExtendedUses.push_back(&UseMO); -@@ -640,19 +604,18 @@ optimizeExtInstr(MachineInstr *MI, Machi - /// against already sets (or could be modified to set) the same flag as the - /// compare, then we can remove the comparison and use the flag from the - /// previous instruction. --bool PeepholeOptimizer::optimizeCmpInstr(MachineInstr *MI, -- MachineBasicBlock *MBB) { -+bool PeepholeOptimizer::optimizeCmpInstr(MachineInstr &MI) { - // If this instruction is a comparison against zero and isn't comparing a - // physical register, we can try to optimize it. - unsigned SrcReg, SrcReg2; - int CmpMask, CmpValue; -- if (!TII->analyzeCompare(*MI, SrcReg, SrcReg2, CmpMask, CmpValue) || -+ if (!TII->analyzeCompare(MI, SrcReg, SrcReg2, CmpMask, CmpValue) || - TargetRegisterInfo::isPhysicalRegister(SrcReg) || - (SrcReg2 != 0 && TargetRegisterInfo::isPhysicalRegister(SrcReg2))) - return false; - - // Attempt to optimize the comparison instruction. -- if (TII->optimizeCompareInstr(*MI, SrcReg, SrcReg2, CmpMask, CmpValue, MRI)) { -+ if (TII->optimizeCompareInstr(MI, SrcReg, SrcReg2, CmpMask, CmpValue, MRI)) { - ++NumCmps; - return true; - } -@@ -661,27 +624,26 @@ bool PeepholeOptimizer::optimizeCmpInstr - } - - /// Optimize a select instruction. --bool PeepholeOptimizer::optimizeSelect(MachineInstr *MI, -+bool PeepholeOptimizer::optimizeSelect(MachineInstr &MI, - SmallPtrSetImpl &LocalMIs) { - unsigned TrueOp = 0; - unsigned FalseOp = 0; - bool Optimizable = false; - SmallVector Cond; -- if (TII->analyzeSelect(*MI, Cond, TrueOp, FalseOp, Optimizable)) -+ if (TII->analyzeSelect(MI, Cond, TrueOp, FalseOp, Optimizable)) - return false; - if (!Optimizable) - return false; -- if (!TII->optimizeSelect(*MI, LocalMIs)) -+ if (!TII->optimizeSelect(MI, LocalMIs)) - return false; -- MI->eraseFromParent(); -+ MI.eraseFromParent(); - ++NumSelects; - return true; - } - --/// \brief Check if a simpler conditional branch can be --/// generated --bool PeepholeOptimizer::optimizeCondBranch(MachineInstr *MI) { -- return TII->optimizeCondBranch(*MI); -+/// Check if a simpler conditional branch can be generated. -+bool PeepholeOptimizer::optimizeCondBranch(MachineInstr &MI) { -+ return TII->optimizeCondBranch(MI); - } - - /// \brief Try to find the next source that share the same register file -@@ -695,30 +657,29 @@ bool PeepholeOptimizer::optimizeCondBran - /// share the same register file as \p Reg and \p SubReg. The client should - /// then be capable to rewrite all intermediate PHIs to get the next source. - /// \return False if no alternative sources are available. True otherwise. --bool PeepholeOptimizer::findNextSource(unsigned Reg, unsigned SubReg, -+bool PeepholeOptimizer::findNextSource(RegSubRegPair RegSubReg, - RewriteMapTy &RewriteMap) { - // Do not try to find a new source for a physical register. - // So far we do not have any motivating example for doing that. - // Thus, instead of maintaining untested code, we will revisit that if - // that changes at some point. -+ unsigned Reg = RegSubReg.Reg; - if (TargetRegisterInfo::isPhysicalRegister(Reg)) - return false; - const TargetRegisterClass *DefRC = MRI->getRegClass(Reg); - -- SmallVector SrcToLook; -- TargetInstrInfo::RegSubRegPair CurSrcPair(Reg, SubReg); -+ SmallVector SrcToLook; -+ RegSubRegPair CurSrcPair = RegSubReg; - SrcToLook.push_back(CurSrcPair); - - unsigned PHICount = 0; -- while (!SrcToLook.empty() && PHICount < RewritePHILimit) { -- TargetInstrInfo::RegSubRegPair Pair = SrcToLook.pop_back_val(); -+ do { -+ CurSrcPair = SrcToLook.pop_back_val(); - // As explained above, do not handle physical registers -- if (TargetRegisterInfo::isPhysicalRegister(Pair.Reg)) -+ if (TargetRegisterInfo::isPhysicalRegister(CurSrcPair.Reg)) - return false; - -- CurSrcPair = Pair; -- ValueTracker ValTracker(CurSrcPair.Reg, CurSrcPair.SubReg, *MRI, -- !DisableAdvCopyOpt, TII); -+ ValueTracker ValTracker(CurSrcPair.Reg, CurSrcPair.SubReg, *MRI, TII); - - // Follow the chain of copies until we find a more suitable source, a phi - // or have to abort. -@@ -747,14 +708,17 @@ bool PeepholeOptimizer::findNextSource(u - unsigned NumSrcs = Res.getNumSources(); - if (NumSrcs > 1) { - PHICount++; -+ if (PHICount >= RewritePHILimit) { -+ DEBUG(dbgs() << "findNextSource: PHI limit reached\n"); -+ return false; -+ } -+ - for (unsigned i = 0; i < NumSrcs; ++i) -- SrcToLook.push_back(TargetInstrInfo::RegSubRegPair( -- Res.getSrcReg(i), Res.getSrcSubReg(i))); -+ SrcToLook.push_back(Res.getSrc(i)); - break; - } - -- CurSrcPair.Reg = Res.getSrcReg(0); -- CurSrcPair.SubReg = Res.getSrcSubReg(0); -+ CurSrcPair = Res.getSrc(0); - // Do not extend the live-ranges of physical registers as they add - // constraints to the register allocator. Moreover, if we want to extend - // the live-range of a physical register, unlike SSA virtual register, -@@ -764,7 +728,8 @@ bool PeepholeOptimizer::findNextSource(u - - // Keep following the chain if the value isn't any better yet. - const TargetRegisterClass *SrcRC = MRI->getRegClass(CurSrcPair.Reg); -- if (!TRI->shouldRewriteCopySrc(DefRC, SubReg, SrcRC, CurSrcPair.SubReg)) -+ if (!TRI->shouldRewriteCopySrc(DefRC, RegSubReg.SubReg, SrcRC, -+ CurSrcPair.SubReg)) - continue; - - // We currently cannot deal with subreg operands on PHI instructions -@@ -775,7 +740,7 @@ bool PeepholeOptimizer::findNextSource(u - // We found a suitable source, and are done with this chain. - break; - } -- } -+ } while (!SrcToLook.empty()); - - // If we did not find a more suitable source, there is nothing to optimize. - return CurSrcPair.Reg != Reg; -@@ -786,54 +751,50 @@ bool PeepholeOptimizer::findNextSource(u - /// successfully traverse a PHI instruction and find suitable sources coming - /// from its edges. By inserting a new PHI, we provide a rewritten PHI def - /// suitable to be used in a new COPY instruction. --static MachineInstr * --insertPHI(MachineRegisterInfo *MRI, const TargetInstrInfo *TII, -- const SmallVectorImpl &SrcRegs, -- MachineInstr *OrigPHI) { -+static MachineInstr & -+insertPHI(MachineRegisterInfo &MRI, const TargetInstrInfo &TII, -+ const SmallVectorImpl &SrcRegs, -+ MachineInstr &OrigPHI) { - assert(!SrcRegs.empty() && "No sources to create a PHI instruction?"); - -- const TargetRegisterClass *NewRC = MRI->getRegClass(SrcRegs[0].Reg); -+ const TargetRegisterClass *NewRC = MRI.getRegClass(SrcRegs[0].Reg); - // NewRC is only correct if no subregisters are involved. findNextSource() - // should have rejected those cases already. - assert(SrcRegs[0].SubReg == 0 && "should not have subreg operand"); -- unsigned NewVR = MRI->createVirtualRegister(NewRC); -- MachineBasicBlock *MBB = OrigPHI->getParent(); -- MachineInstrBuilder MIB = BuildMI(*MBB, OrigPHI, OrigPHI->getDebugLoc(), -- TII->get(TargetOpcode::PHI), NewVR); -+ unsigned NewVR = MRI.createVirtualRegister(NewRC); -+ MachineBasicBlock *MBB = OrigPHI.getParent(); -+ MachineInstrBuilder MIB = BuildMI(*MBB, &OrigPHI, OrigPHI.getDebugLoc(), -+ TII.get(TargetOpcode::PHI), NewVR); - - unsigned MBBOpIdx = 2; -- for (auto RegPair : SrcRegs) { -+ for (const RegSubRegPair &RegPair : SrcRegs) { - MIB.addReg(RegPair.Reg, 0, RegPair.SubReg); -- MIB.addMBB(OrigPHI->getOperand(MBBOpIdx).getMBB()); -+ MIB.addMBB(OrigPHI.getOperand(MBBOpIdx).getMBB()); - // Since we're extended the lifetime of RegPair.Reg, clear the - // kill flags to account for that and make RegPair.Reg reaches - // the new PHI. -- MRI->clearKillFlags(RegPair.Reg); -+ MRI.clearKillFlags(RegPair.Reg); - MBBOpIdx += 2; - } - -- return MIB; -+ return *MIB; - } - - namespace { - --/// \brief Helper class to rewrite the arguments of a copy-like instruction. --class CopyRewriter { -+/// Interface to query instructions amenable to copy rewriting. -+class Rewriter { - protected: -- /// The copy-like instruction. - MachineInstr &CopyLike; -- -- /// The index of the source being rewritten. -- unsigned CurrentSrcIdx = 0; -- -+ unsigned CurrentSrcIdx = 0; ///< The index of the source being rewritten. - public: -- CopyRewriter(MachineInstr &MI) : CopyLike(MI) {} -- virtual ~CopyRewriter() = default; -+ Rewriter(MachineInstr &CopyLike) : CopyLike(CopyLike) {} -+ virtual ~Rewriter() {} - - /// \brief Get the next rewritable source (SrcReg, SrcSubReg) and -- /// the related value that it affects (TrackReg, TrackSubReg). -+ /// the related value that it affects (DstReg, DstSubReg). - /// A source is considered rewritable if its register class and the -- /// register class of the related TrackReg may not be register -+ /// register class of the related DstReg may not be register - /// coalescer friendly. In other words, given a copy-like instruction - /// not all the arguments may be returned at rewritable source, since - /// some arguments are none to be register coalescer friendly. -@@ -848,137 +809,72 @@ public: - /// the only source this instruction has: - /// (SrcReg, SrcSubReg) = (src, srcSubIdx). - /// This source defines the whole definition, i.e., -- /// (TrackReg, TrackSubReg) = (dst, dstSubIdx). -+ /// (DstReg, DstSubReg) = (dst, dstSubIdx). - /// - /// The second and subsequent calls will return false, as there is only one - /// rewritable source. - /// - /// \return True if a rewritable source has been found, false otherwise. - /// The output arguments are valid if and only if true is returned. -- virtual bool getNextRewritableSource(unsigned &SrcReg, unsigned &SrcSubReg, -- unsigned &TrackReg, -- unsigned &TrackSubReg) { -- // If CurrentSrcIdx == 1, this means this function has already been called -- // once. CopyLike has one definition and one argument, thus, there is -- // nothing else to rewrite. -- if (!CopyLike.isCopy() || CurrentSrcIdx == 1) -+ virtual bool getNextRewritableSource(RegSubRegPair &Src, -+ RegSubRegPair &Dst) = 0; -+ -+ /// Rewrite the current source with \p NewReg and \p NewSubReg if possible. -+ /// \return True if the rewriting was possible, false otherwise. -+ virtual bool RewriteCurrentSource(unsigned NewReg, unsigned NewSubReg) = 0; -+}; -+ -+/// Rewriter for COPY instructions. -+class CopyRewriter : public Rewriter { -+public: -+ CopyRewriter(MachineInstr &MI) : Rewriter(MI) { -+ assert(MI.isCopy() && "Expected copy instruction"); -+ } -+ virtual ~CopyRewriter() = default; -+ -+ bool getNextRewritableSource(RegSubRegPair &Src, -+ RegSubRegPair &Dst) override { -+ // CurrentSrcIdx > 0 means this function has already been called. -+ if (CurrentSrcIdx > 0) - return false; - // This is the first call to getNextRewritableSource. - // Move the CurrentSrcIdx to remember that we made that call. - CurrentSrcIdx = 1; - // The rewritable source is the argument. - const MachineOperand &MOSrc = CopyLike.getOperand(1); -- SrcReg = MOSrc.getReg(); -- SrcSubReg = MOSrc.getSubReg(); -+ Src = RegSubRegPair(MOSrc.getReg(), MOSrc.getSubReg()); - // What we track are the alternative sources of the definition. - const MachineOperand &MODef = CopyLike.getOperand(0); -- TrackReg = MODef.getReg(); -- TrackSubReg = MODef.getSubReg(); -+ Dst = RegSubRegPair(MODef.getReg(), MODef.getSubReg()); - return true; - } - -- /// \brief Rewrite the current source with \p NewReg and \p NewSubReg -- /// if possible. -- /// \return True if the rewriting was possible, false otherwise. -- virtual bool RewriteCurrentSource(unsigned NewReg, unsigned NewSubReg) { -- if (!CopyLike.isCopy() || CurrentSrcIdx != 1) -+ bool RewriteCurrentSource(unsigned NewReg, unsigned NewSubReg) override { -+ if (CurrentSrcIdx != 1) - return false; - MachineOperand &MOSrc = CopyLike.getOperand(CurrentSrcIdx); - MOSrc.setReg(NewReg); - MOSrc.setSubReg(NewSubReg); - return true; - } -- -- /// \brief Given a \p Def.Reg and Def.SubReg pair, use \p RewriteMap to find -- /// the new source to use for rewrite. If \p HandleMultipleSources is true and -- /// multiple sources for a given \p Def are found along the way, we found a -- /// PHI instructions that needs to be rewritten. -- /// TODO: HandleMultipleSources should be removed once we test PHI handling -- /// with coalescable copies. -- TargetInstrInfo::RegSubRegPair -- getNewSource(MachineRegisterInfo *MRI, const TargetInstrInfo *TII, -- TargetInstrInfo::RegSubRegPair Def, -- PeepholeOptimizer::RewriteMapTy &RewriteMap, -- bool HandleMultipleSources = true) { -- TargetInstrInfo::RegSubRegPair LookupSrc(Def.Reg, Def.SubReg); -- do { -- ValueTrackerResult Res = RewriteMap.lookup(LookupSrc); -- // If there are no entries on the map, LookupSrc is the new source. -- if (!Res.isValid()) -- return LookupSrc; -- -- // There's only one source for this definition, keep searching... -- unsigned NumSrcs = Res.getNumSources(); -- if (NumSrcs == 1) { -- LookupSrc.Reg = Res.getSrcReg(0); -- LookupSrc.SubReg = Res.getSrcSubReg(0); -- continue; -- } -- -- // TODO: Remove once multiple srcs w/ coalescable copies are supported. -- if (!HandleMultipleSources) -- break; -- -- // Multiple sources, recurse into each source to find a new source -- // for it. Then, rewrite the PHI accordingly to its new edges. -- SmallVector NewPHISrcs; -- for (unsigned i = 0; i < NumSrcs; ++i) { -- TargetInstrInfo::RegSubRegPair PHISrc(Res.getSrcReg(i), -- Res.getSrcSubReg(i)); -- NewPHISrcs.push_back( -- getNewSource(MRI, TII, PHISrc, RewriteMap, HandleMultipleSources)); -- } -- -- // Build the new PHI node and return its def register as the new source. -- MachineInstr *OrigPHI = const_cast(Res.getInst()); -- MachineInstr *NewPHI = insertPHI(MRI, TII, NewPHISrcs, OrigPHI); -- DEBUG(dbgs() << "-- getNewSource\n"); -- DEBUG(dbgs() << " Replacing: " << *OrigPHI); -- DEBUG(dbgs() << " With: " << *NewPHI); -- const MachineOperand &MODef = NewPHI->getOperand(0); -- return TargetInstrInfo::RegSubRegPair(MODef.getReg(), MODef.getSubReg()); -- -- } while (true); -- -- return TargetInstrInfo::RegSubRegPair(0, 0); -- } -- -- /// \brief Rewrite the source found through \p Def, by using the \p RewriteMap -- /// and create a new COPY instruction. More info about RewriteMap in -- /// PeepholeOptimizer::findNextSource. Right now this is only used to handle -- /// Uncoalescable copies, since they are copy like instructions that aren't -- /// recognized by the register allocator. -- virtual MachineInstr * -- RewriteSource(TargetInstrInfo::RegSubRegPair Def, -- PeepholeOptimizer::RewriteMapTy &RewriteMap) { -- return nullptr; -- } - }; - - /// \brief Helper class to rewrite uncoalescable copy like instructions - /// into new COPY (coalescable friendly) instructions. --class UncoalescableRewriter : public CopyRewriter { --protected: -- const TargetInstrInfo &TII; -- MachineRegisterInfo &MRI; -- -- /// The number of defs in the bitcast -- unsigned NumDefs; -+class UncoalescableRewriter : public Rewriter { -+ unsigned NumDefs; ///< Number of defs in the bitcast. - - public: -- UncoalescableRewriter(MachineInstr &MI, const TargetInstrInfo &TII, -- MachineRegisterInfo &MRI) -- : CopyRewriter(MI), TII(TII), MRI(MRI) { -+ UncoalescableRewriter(MachineInstr &MI) : Rewriter(MI) { - NumDefs = MI.getDesc().getNumDefs(); - } - -- /// \brief Get the next rewritable def source (TrackReg, TrackSubReg) -+ /// \see See Rewriter::getNextRewritableSource() - /// All such sources need to be considered rewritable in order to - /// rewrite a uncoalescable copy-like instruction. This method return - /// each definition that must be checked if rewritable. -- bool getNextRewritableSource(unsigned &SrcReg, unsigned &SrcSubReg, -- unsigned &TrackReg, -- unsigned &TrackSubReg) override { -+ bool getNextRewritableSource(RegSubRegPair &Src, -+ RegSubRegPair &Dst) override { - // Find the next non-dead definition and continue from there. - if (CurrentSrcIdx == NumDefs) - return false; -@@ -990,64 +886,27 @@ public: - } - - // What we track are the alternative sources of the definition. -+ Src = RegSubRegPair(0, 0); - const MachineOperand &MODef = CopyLike.getOperand(CurrentSrcIdx); -- TrackReg = MODef.getReg(); -- TrackSubReg = MODef.getSubReg(); -+ Dst = RegSubRegPair(MODef.getReg(), MODef.getSubReg()); - - CurrentSrcIdx++; - return true; - } - -- /// \brief Rewrite the source found through \p Def, by using the \p RewriteMap -- /// and create a new COPY instruction. More info about RewriteMap in -- /// PeepholeOptimizer::findNextSource. Right now this is only used to handle -- /// Uncoalescable copies, since they are copy like instructions that aren't -- /// recognized by the register allocator. -- MachineInstr * -- RewriteSource(TargetInstrInfo::RegSubRegPair Def, -- PeepholeOptimizer::RewriteMapTy &RewriteMap) override { -- assert(!TargetRegisterInfo::isPhysicalRegister(Def.Reg) && -- "We do not rewrite physical registers"); -- -- // Find the new source to use in the COPY rewrite. -- TargetInstrInfo::RegSubRegPair NewSrc = -- getNewSource(&MRI, &TII, Def, RewriteMap); -- -- // Insert the COPY. -- const TargetRegisterClass *DefRC = MRI.getRegClass(Def.Reg); -- unsigned NewVR = MRI.createVirtualRegister(DefRC); -- -- MachineInstr *NewCopy = -- BuildMI(*CopyLike.getParent(), &CopyLike, CopyLike.getDebugLoc(), -- TII.get(TargetOpcode::COPY), NewVR) -- .addReg(NewSrc.Reg, 0, NewSrc.SubReg); -- -- NewCopy->getOperand(0).setSubReg(Def.SubReg); -- if (Def.SubReg) -- NewCopy->getOperand(0).setIsUndef(); -- -- DEBUG(dbgs() << "-- RewriteSource\n"); -- DEBUG(dbgs() << " Replacing: " << CopyLike); -- DEBUG(dbgs() << " With: " << *NewCopy); -- MRI.replaceRegWith(Def.Reg, NewVR); -- MRI.clearKillFlags(NewVR); -- -- // We extended the lifetime of NewSrc.Reg, clear the kill flags to -- // account for that. -- MRI.clearKillFlags(NewSrc.Reg); -- -- return NewCopy; -+ bool RewriteCurrentSource(unsigned NewReg, unsigned NewSubReg) override { -+ return false; - } - }; - --/// \brief Specialized rewriter for INSERT_SUBREG instruction. --class InsertSubregRewriter : public CopyRewriter { -+/// Specialized rewriter for INSERT_SUBREG instruction. -+class InsertSubregRewriter : public Rewriter { - public: -- InsertSubregRewriter(MachineInstr &MI) : CopyRewriter(MI) { -+ InsertSubregRewriter(MachineInstr &MI) : Rewriter(MI) { - assert(MI.isInsertSubreg() && "Invalid instruction"); - } - -- /// \brief See CopyRewriter::getNextRewritableSource. -+ /// \see See Rewriter::getNextRewritableSource() - /// Here CopyLike has the following form: - /// dst = INSERT_SUBREG Src1, Src2.src2SubIdx, subIdx. - /// Src1 has the same register class has dst, hence, there is -@@ -1055,29 +914,27 @@ public: - /// Src2.src2SubIdx, may not be register coalescer friendly. - /// Therefore, the first call to this method returns: - /// (SrcReg, SrcSubReg) = (Src2, src2SubIdx). -- /// (TrackReg, TrackSubReg) = (dst, subIdx). -+ /// (DstReg, DstSubReg) = (dst, subIdx). - /// - /// Subsequence calls will return false. -- bool getNextRewritableSource(unsigned &SrcReg, unsigned &SrcSubReg, -- unsigned &TrackReg, -- unsigned &TrackSubReg) override { -+ bool getNextRewritableSource(RegSubRegPair &Src, -+ RegSubRegPair &Dst) override { - // If we already get the only source we can rewrite, return false. - if (CurrentSrcIdx == 2) - return false; - // We are looking at v2 = INSERT_SUBREG v0, v1, sub0. - CurrentSrcIdx = 2; - const MachineOperand &MOInsertedReg = CopyLike.getOperand(2); -- SrcReg = MOInsertedReg.getReg(); -- SrcSubReg = MOInsertedReg.getSubReg(); -+ Src = RegSubRegPair(MOInsertedReg.getReg(), MOInsertedReg.getSubReg()); - const MachineOperand &MODef = CopyLike.getOperand(0); - - // We want to track something that is compatible with the - // partial definition. -- TrackReg = MODef.getReg(); - if (MODef.getSubReg()) - // Bail if we have to compose sub-register indices. - return false; -- TrackSubReg = (unsigned)CopyLike.getOperand(3).getImm(); -+ Dst = RegSubRegPair(MODef.getReg(), -+ (unsigned)CopyLike.getOperand(3).getImm()); - return true; - } - -@@ -1092,41 +949,39 @@ public: - } - }; - --/// \brief Specialized rewriter for EXTRACT_SUBREG instruction. --class ExtractSubregRewriter : public CopyRewriter { -+/// Specialized rewriter for EXTRACT_SUBREG instruction. -+class ExtractSubregRewriter : public Rewriter { - const TargetInstrInfo &TII; - - public: - ExtractSubregRewriter(MachineInstr &MI, const TargetInstrInfo &TII) -- : CopyRewriter(MI), TII(TII) { -+ : Rewriter(MI), TII(TII) { - assert(MI.isExtractSubreg() && "Invalid instruction"); - } - -- /// \brief See CopyRewriter::getNextRewritableSource. -+ /// \see Rewriter::getNextRewritableSource() - /// Here CopyLike has the following form: - /// dst.dstSubIdx = EXTRACT_SUBREG Src, subIdx. - /// There is only one rewritable source: Src.subIdx, - /// which defines dst.dstSubIdx. -- bool getNextRewritableSource(unsigned &SrcReg, unsigned &SrcSubReg, -- unsigned &TrackReg, -- unsigned &TrackSubReg) override { -+ bool getNextRewritableSource(RegSubRegPair &Src, -+ RegSubRegPair &Dst) override { - // If we already get the only source we can rewrite, return false. - if (CurrentSrcIdx == 1) - return false; - // We are looking at v1 = EXTRACT_SUBREG v0, sub0. - CurrentSrcIdx = 1; - const MachineOperand &MOExtractedReg = CopyLike.getOperand(1); -- SrcReg = MOExtractedReg.getReg(); - // If we have to compose sub-register indices, bail out. - if (MOExtractedReg.getSubReg()) - return false; - -- SrcSubReg = CopyLike.getOperand(2).getImm(); -+ Src = RegSubRegPair(MOExtractedReg.getReg(), -+ CopyLike.getOperand(2).getImm()); - - // We want to track something that is compatible with the definition. - const MachineOperand &MODef = CopyLike.getOperand(0); -- TrackReg = MODef.getReg(); -- TrackSubReg = MODef.getSubReg(); -+ Dst = RegSubRegPair(MODef.getReg(), MODef.getSubReg()); - return true; - } - -@@ -1156,14 +1011,14 @@ public: - } - }; - --/// \brief Specialized rewriter for REG_SEQUENCE instruction. --class RegSequenceRewriter : public CopyRewriter { -+/// Specialized rewriter for REG_SEQUENCE instruction. -+class RegSequenceRewriter : public Rewriter { - public: -- RegSequenceRewriter(MachineInstr &MI) : CopyRewriter(MI) { -+ RegSequenceRewriter(MachineInstr &MI) : Rewriter(MI) { - assert(MI.isRegSequence() && "Invalid instruction"); - } - -- /// \brief See CopyRewriter::getNextRewritableSource. -+ /// \see Rewriter::getNextRewritableSource() - /// Here CopyLike has the following form: - /// dst = REG_SEQUENCE Src1.src1SubIdx, subIdx1, Src2.src2SubIdx, subIdx2. - /// Each call will return a different source, walking all the available -@@ -1171,17 +1026,16 @@ public: - /// - /// The first call returns: - /// (SrcReg, SrcSubReg) = (Src1, src1SubIdx). -- /// (TrackReg, TrackSubReg) = (dst, subIdx1). -+ /// (DstReg, DstSubReg) = (dst, subIdx1). - /// - /// The second call returns: - /// (SrcReg, SrcSubReg) = (Src2, src2SubIdx). -- /// (TrackReg, TrackSubReg) = (dst, subIdx2). -+ /// (DstReg, DstSubReg) = (dst, subIdx2). - /// - /// And so on, until all the sources have been traversed, then - /// it returns false. -- bool getNextRewritableSource(unsigned &SrcReg, unsigned &SrcSubReg, -- unsigned &TrackReg, -- unsigned &TrackSubReg) override { -+ bool getNextRewritableSource(RegSubRegPair &Src, -+ RegSubRegPair &Dst) override { - // We are looking at v0 = REG_SEQUENCE v1, sub1, v2, sub2, etc. - - // If this is the first call, move to the first argument. -@@ -1194,17 +1048,17 @@ public: - return false; - } - const MachineOperand &MOInsertedReg = CopyLike.getOperand(CurrentSrcIdx); -- SrcReg = MOInsertedReg.getReg(); -+ Src.Reg = MOInsertedReg.getReg(); - // If we have to compose sub-register indices, bail out. -- if ((SrcSubReg = MOInsertedReg.getSubReg())) -+ if ((Src.SubReg = MOInsertedReg.getSubReg())) - return false; - - // We want to track something that is compatible with the related - // partial definition. -- TrackSubReg = CopyLike.getOperand(CurrentSrcIdx + 1).getImm(); -+ Dst.SubReg = CopyLike.getOperand(CurrentSrcIdx + 1).getImm(); - - const MachineOperand &MODef = CopyLike.getOperand(0); -- TrackReg = MODef.getReg(); -+ Dst.Reg = MODef.getReg(); - // If we have to compose sub-registers, bail. - return MODef.getSubReg() == 0; - } -@@ -1224,16 +1078,14 @@ public: - - } // end anonymous namespace - --/// \brief Get the appropriated CopyRewriter for \p MI. --/// \return A pointer to a dynamically allocated CopyRewriter or nullptr --/// if no rewriter works for \p MI. --static CopyRewriter *getCopyRewriter(MachineInstr &MI, -- const TargetInstrInfo &TII, -- MachineRegisterInfo &MRI) { -+/// Get the appropriated Rewriter for \p MI. -+/// \return A pointer to a dynamically allocated Rewriter or nullptr if no -+/// rewriter works for \p MI. -+static Rewriter *getCopyRewriter(MachineInstr &MI, const TargetInstrInfo &TII) { - // Handle uncoalescable copy-like instructions. -- if (MI.isBitcast() || (MI.isRegSequenceLike() || MI.isInsertSubregLike() || -- MI.isExtractSubregLike())) -- return new UncoalescableRewriter(MI, TII, MRI); -+ if (MI.isBitcast() || MI.isRegSequenceLike() || MI.isInsertSubregLike() || -+ MI.isExtractSubregLike()) -+ return new UncoalescableRewriter(MI); - - switch (MI.getOpcode()) { - default: -@@ -1247,53 +1099,102 @@ static CopyRewriter *getCopyRewriter(Mac - case TargetOpcode::REG_SEQUENCE: - return new RegSequenceRewriter(MI); - } -- llvm_unreachable(nullptr); - } - --/// \brief Optimize generic copy instructions to avoid cross --/// register bank copy. The optimization looks through a chain of --/// copies and tries to find a source that has a compatible register --/// class. --/// Two register classes are considered to be compatible if they share --/// the same register bank. -+/// \brief Given a \p Def.Reg and Def.SubReg pair, use \p RewriteMap to find -+/// the new source to use for rewrite. If \p HandleMultipleSources is true and -+/// multiple sources for a given \p Def are found along the way, we found a -+/// PHI instructions that needs to be rewritten. -+/// TODO: HandleMultipleSources should be removed once we test PHI handling -+/// with coalescable copies. -+static RegSubRegPair -+getNewSource(MachineRegisterInfo *MRI, const TargetInstrInfo *TII, -+ RegSubRegPair Def, -+ const PeepholeOptimizer::RewriteMapTy &RewriteMap, -+ bool HandleMultipleSources = true) { -+ RegSubRegPair LookupSrc(Def.Reg, Def.SubReg); -+ while (true) { -+ ValueTrackerResult Res = RewriteMap.lookup(LookupSrc); -+ // If there are no entries on the map, LookupSrc is the new source. -+ if (!Res.isValid()) -+ return LookupSrc; -+ -+ // There's only one source for this definition, keep searching... -+ unsigned NumSrcs = Res.getNumSources(); -+ if (NumSrcs == 1) { -+ LookupSrc.Reg = Res.getSrcReg(0); -+ LookupSrc.SubReg = Res.getSrcSubReg(0); -+ continue; -+ } -+ -+ // TODO: Remove once multiple srcs w/ coalescable copies are supported. -+ if (!HandleMultipleSources) -+ break; -+ -+ // Multiple sources, recurse into each source to find a new source -+ // for it. Then, rewrite the PHI accordingly to its new edges. -+ SmallVector NewPHISrcs; -+ for (unsigned i = 0; i < NumSrcs; ++i) { -+ RegSubRegPair PHISrc(Res.getSrcReg(i), Res.getSrcSubReg(i)); -+ NewPHISrcs.push_back( -+ getNewSource(MRI, TII, PHISrc, RewriteMap, HandleMultipleSources)); -+ } -+ -+ // Build the new PHI node and return its def register as the new source. -+ MachineInstr &OrigPHI = const_cast(*Res.getInst()); -+ MachineInstr &NewPHI = insertPHI(*MRI, *TII, NewPHISrcs, OrigPHI); -+ DEBUG(dbgs() << "-- getNewSource\n"); -+ DEBUG(dbgs() << " Replacing: " << OrigPHI); -+ DEBUG(dbgs() << " With: " << NewPHI); -+ const MachineOperand &MODef = NewPHI.getOperand(0); -+ return RegSubRegPair(MODef.getReg(), MODef.getSubReg()); -+ } -+ -+ return RegSubRegPair(0, 0); -+} -+ -+/// Optimize generic copy instructions to avoid cross register bank copy. -+/// The optimization looks through a chain of copies and tries to find a source -+/// that has a compatible register class. -+/// Two register classes are considered to be compatible if they share the same -+/// register bank. - /// New copies issued by this optimization are register allocator - /// friendly. This optimization does not remove any copy as it may - /// overconstrain the register allocator, but replaces some operands - /// when possible. - /// \pre isCoalescableCopy(*MI) is true. - /// \return True, when \p MI has been rewritten. False otherwise. --bool PeepholeOptimizer::optimizeCoalescableCopy(MachineInstr *MI) { -- assert(MI && isCoalescableCopy(*MI) && "Invalid argument"); -- assert(MI->getDesc().getNumDefs() == 1 && -+bool PeepholeOptimizer::optimizeCoalescableCopy(MachineInstr &MI) { -+ assert(isCoalescableCopy(MI) && "Invalid argument"); -+ assert(MI.getDesc().getNumDefs() == 1 && - "Coalescer can understand multiple defs?!"); -- const MachineOperand &MODef = MI->getOperand(0); -+ const MachineOperand &MODef = MI.getOperand(0); - // Do not rewrite physical definitions. - if (TargetRegisterInfo::isPhysicalRegister(MODef.getReg())) - return false; - - bool Changed = false; - // Get the right rewriter for the current copy. -- std::unique_ptr CpyRewriter(getCopyRewriter(*MI, *TII, *MRI)); -+ std::unique_ptr CpyRewriter(getCopyRewriter(MI, *TII)); - // If none exists, bail out. - if (!CpyRewriter) - return false; - // Rewrite each rewritable source. -- unsigned SrcReg, SrcSubReg, TrackReg, TrackSubReg; -- while (CpyRewriter->getNextRewritableSource(SrcReg, SrcSubReg, TrackReg, -- TrackSubReg)) { -+ RegSubRegPair Src; -+ RegSubRegPair TrackPair; -+ while (CpyRewriter->getNextRewritableSource(Src, TrackPair)) { - // Keep track of PHI nodes and its incoming edges when looking for sources. - RewriteMapTy RewriteMap; - // Try to find a more suitable source. If we failed to do so, or get the - // actual source, move to the next source. -- if (!findNextSource(TrackReg, TrackSubReg, RewriteMap)) -+ if (!findNextSource(TrackPair, RewriteMap)) - continue; - - // Get the new source to rewrite. TODO: Only enable handling of multiple - // sources (PHIs) once we have a motivating example and testcases for it. -- TargetInstrInfo::RegSubRegPair TrackPair(TrackReg, TrackSubReg); -- TargetInstrInfo::RegSubRegPair NewSrc = CpyRewriter->getNewSource( -- MRI, TII, TrackPair, RewriteMap, false /* multiple sources */); -- if (SrcReg == NewSrc.Reg || NewSrc.Reg == 0) -+ RegSubRegPair NewSrc = getNewSource(MRI, TII, TrackPair, RewriteMap, -+ /*HandleMultipleSources=*/false); -+ if (Src.Reg == NewSrc.Reg || NewSrc.Reg == 0) - continue; - - // Rewrite source. -@@ -1312,6 +1213,47 @@ bool PeepholeOptimizer::optimizeCoalesca - return Changed; - } - -+/// \brief Rewrite the source found through \p Def, by using the \p RewriteMap -+/// and create a new COPY instruction. More info about RewriteMap in -+/// PeepholeOptimizer::findNextSource. Right now this is only used to handle -+/// Uncoalescable copies, since they are copy like instructions that aren't -+/// recognized by the register allocator. -+MachineInstr & -+PeepholeOptimizer::rewriteSource(MachineInstr &CopyLike, -+ RegSubRegPair Def, RewriteMapTy &RewriteMap) { -+ assert(!TargetRegisterInfo::isPhysicalRegister(Def.Reg) && -+ "We do not rewrite physical registers"); -+ -+ // Find the new source to use in the COPY rewrite. -+ RegSubRegPair NewSrc = getNewSource(MRI, TII, Def, RewriteMap); -+ -+ // Insert the COPY. -+ const TargetRegisterClass *DefRC = MRI->getRegClass(Def.Reg); -+ unsigned NewVReg = MRI->createVirtualRegister(DefRC); -+ -+ MachineInstr *NewCopy = -+ BuildMI(*CopyLike.getParent(), &CopyLike, CopyLike.getDebugLoc(), -+ TII->get(TargetOpcode::COPY), NewVReg) -+ .addReg(NewSrc.Reg, 0, NewSrc.SubReg); -+ -+ if (Def.SubReg) { -+ NewCopy->getOperand(0).setSubReg(Def.SubReg); -+ NewCopy->getOperand(0).setIsUndef(); -+ } -+ -+ DEBUG(dbgs() << "-- RewriteSource\n"); -+ DEBUG(dbgs() << " Replacing: " << CopyLike); -+ DEBUG(dbgs() << " With: " << *NewCopy); -+ MRI->replaceRegWith(Def.Reg, NewVReg); -+ MRI->clearKillFlags(NewVReg); -+ -+ // We extended the lifetime of NewSrc.Reg, clear the kill flags to -+ // account for that. -+ MRI->clearKillFlags(NewSrc.Reg); -+ -+ return *NewCopy; -+} -+ - /// \brief Optimize copy-like instructions to create - /// register coalescer friendly instruction. - /// The optimization tries to kill-off the \p MI by looking -@@ -1324,48 +1266,40 @@ bool PeepholeOptimizer::optimizeCoalesca - /// been removed from its parent. - /// All COPY instructions created, are inserted in \p LocalMIs. - bool PeepholeOptimizer::optimizeUncoalescableCopy( -- MachineInstr *MI, SmallPtrSetImpl &LocalMIs) { -- assert(MI && isUncoalescableCopy(*MI) && "Invalid argument"); -- -- // Check if we can rewrite all the values defined by this instruction. -- SmallVector RewritePairs; -- // Get the right rewriter for the current copy. -- std::unique_ptr CpyRewriter(getCopyRewriter(*MI, *TII, *MRI)); -- // If none exists, bail out. -- if (!CpyRewriter) -- return false; -+ MachineInstr &MI, SmallPtrSetImpl &LocalMIs) { -+ assert(isUncoalescableCopy(MI) && "Invalid argument"); -+ UncoalescableRewriter CpyRewriter(MI); - - // Rewrite each rewritable source by generating new COPYs. This works - // differently from optimizeCoalescableCopy since it first makes sure that all - // definitions can be rewritten. - RewriteMapTy RewriteMap; -- unsigned Reg, SubReg, CopyDefReg, CopyDefSubReg; -- while (CpyRewriter->getNextRewritableSource(Reg, SubReg, CopyDefReg, -- CopyDefSubReg)) { -+ RegSubRegPair Src; -+ RegSubRegPair Def; -+ SmallVector RewritePairs; -+ while (CpyRewriter.getNextRewritableSource(Src, Def)) { - // If a physical register is here, this is probably for a good reason. - // Do not rewrite that. -- if (TargetRegisterInfo::isPhysicalRegister(CopyDefReg)) -+ if (TargetRegisterInfo::isPhysicalRegister(Def.Reg)) - return false; - - // If we do not know how to rewrite this definition, there is no point - // in trying to kill this instruction. -- TargetInstrInfo::RegSubRegPair Def(CopyDefReg, CopyDefSubReg); -- if (!findNextSource(Def.Reg, Def.SubReg, RewriteMap)) -+ if (!findNextSource(Def, RewriteMap)) - return false; - - RewritePairs.push_back(Def); - } - - // The change is possible for all defs, do it. -- for (const auto &Def : RewritePairs) { -+ for (const RegSubRegPair &Def : RewritePairs) { - // Rewrite the "copy" in a way the register coalescer understands. -- MachineInstr *NewCopy = CpyRewriter->RewriteSource(Def, RewriteMap); -- assert(NewCopy && "Should be able to always generate a new copy"); -- LocalMIs.insert(NewCopy); -+ MachineInstr &NewCopy = rewriteSource(MI, Def, RewriteMap); -+ LocalMIs.insert(&NewCopy); - } - - // MI is now dead. -- MI->eraseFromParent(); -+ MI.eraseFromParent(); - ++NumUncoalescableCopies; - return true; - } -@@ -1374,18 +1308,18 @@ bool PeepholeOptimizer::optimizeUncoales - /// We only fold loads to virtual registers and the virtual register defined - /// has a single use. - bool PeepholeOptimizer::isLoadFoldable( -- MachineInstr *MI, SmallSet &FoldAsLoadDefCandidates) { -- if (!MI->canFoldAsLoad() || !MI->mayLoad()) -+ MachineInstr &MI, SmallSet &FoldAsLoadDefCandidates) { -+ if (!MI.canFoldAsLoad() || !MI.mayLoad()) - return false; -- const MCInstrDesc &MCID = MI->getDesc(); -+ const MCInstrDesc &MCID = MI.getDesc(); - if (MCID.getNumDefs() != 1) - return false; - -- unsigned Reg = MI->getOperand(0).getReg(); -+ unsigned Reg = MI.getOperand(0).getReg(); - // To reduce compilation time, we check MRI->hasOneNonDBGUse when inserting - // loads. It should be checked when processing uses of the load, since - // uses can be removed during peephole. -- if (!MI->getOperand(0).getSubReg() && -+ if (!MI.getOperand(0).getSubReg() && - TargetRegisterInfo::isVirtualRegister(Reg) && - MRI->hasOneNonDBGUse(Reg)) { - FoldAsLoadDefCandidates.insert(Reg); -@@ -1395,16 +1329,16 @@ bool PeepholeOptimizer::isLoadFoldable( - } - - bool PeepholeOptimizer::isMoveImmediate( -- MachineInstr *MI, SmallSet &ImmDefRegs, -+ MachineInstr &MI, SmallSet &ImmDefRegs, - DenseMap &ImmDefMIs) { -- const MCInstrDesc &MCID = MI->getDesc(); -- if (!MI->isMoveImmediate()) -+ const MCInstrDesc &MCID = MI.getDesc(); -+ if (!MI.isMoveImmediate()) - return false; - if (MCID.getNumDefs() != 1) - return false; -- unsigned Reg = MI->getOperand(0).getReg(); -+ unsigned Reg = MI.getOperand(0).getReg(); - if (TargetRegisterInfo::isVirtualRegister(Reg)) { -- ImmDefMIs.insert(std::make_pair(Reg, MI)); -+ ImmDefMIs.insert(std::make_pair(Reg, &MI)); - ImmDefRegs.insert(Reg); - return true; - } -@@ -1415,11 +1349,11 @@ bool PeepholeOptimizer::isMoveImmediate( - /// Try folding register operands that are defined by move immediate - /// instructions, i.e. a trivial constant folding optimization, if - /// and only if the def and use are in the same BB. --bool PeepholeOptimizer::foldImmediate( -- MachineInstr *MI, MachineBasicBlock *MBB, SmallSet &ImmDefRegs, -+bool PeepholeOptimizer::foldImmediate(MachineInstr &MI, -+ SmallSet &ImmDefRegs, - DenseMap &ImmDefMIs) { -- for (unsigned i = 0, e = MI->getDesc().getNumOperands(); i != e; ++i) { -- MachineOperand &MO = MI->getOperand(i); -+ for (unsigned i = 0, e = MI.getDesc().getNumOperands(); i != e; ++i) { -+ MachineOperand &MO = MI.getOperand(i); - if (!MO.isReg() || MO.isDef()) - continue; - // Ignore dead implicit defs. -@@ -1432,7 +1366,7 @@ bool PeepholeOptimizer::foldImmediate( - continue; - DenseMap::iterator II = ImmDefMIs.find(Reg); - assert(II != ImmDefMIs.end() && "couldn't find immediate definition"); -- if (TII->FoldImmediate(*MI, *II->second, Reg, MRI)) { -+ if (TII->FoldImmediate(MI, *II->second, Reg, MRI)) { - ++NumImmFold; - return true; - } -@@ -1454,28 +1388,28 @@ bool PeepholeOptimizer::foldImmediate( - // %2 = COPY %0:sub1 - // - // Should replace %2 uses with %1:sub1 --bool PeepholeOptimizer::foldRedundantCopy( -- MachineInstr *MI, SmallSet &CopySrcRegs, -+bool PeepholeOptimizer::foldRedundantCopy(MachineInstr &MI, -+ SmallSet &CopySrcRegs, - DenseMap &CopyMIs) { -- assert(MI->isCopy() && "expected a COPY machine instruction"); -+ assert(MI.isCopy() && "expected a COPY machine instruction"); - -- unsigned SrcReg = MI->getOperand(1).getReg(); -+ unsigned SrcReg = MI.getOperand(1).getReg(); - if (!TargetRegisterInfo::isVirtualRegister(SrcReg)) - return false; - -- unsigned DstReg = MI->getOperand(0).getReg(); -+ unsigned DstReg = MI.getOperand(0).getReg(); - if (!TargetRegisterInfo::isVirtualRegister(DstReg)) - return false; - - if (CopySrcRegs.insert(SrcReg).second) { - // First copy of this reg seen. -- CopyMIs.insert(std::make_pair(SrcReg, MI)); -+ CopyMIs.insert(std::make_pair(SrcReg, &MI)); - return false; - } - - MachineInstr *PrevCopy = CopyMIs.find(SrcReg)->second; - -- unsigned SrcSubReg = MI->getOperand(1).getSubReg(); -+ unsigned SrcSubReg = MI.getOperand(1).getSubReg(); - unsigned PrevSrcSubReg = PrevCopy->getOperand(1).getSubReg(); - - // Can't replace different subregister extracts. -@@ -1504,19 +1438,19 @@ bool PeepholeOptimizer::isNAPhysCopy(uns - } - - bool PeepholeOptimizer::foldRedundantNAPhysCopy( -- MachineInstr *MI, DenseMap &NAPhysToVirtMIs) { -- assert(MI->isCopy() && "expected a COPY machine instruction"); -+ MachineInstr &MI, DenseMap &NAPhysToVirtMIs) { -+ assert(MI.isCopy() && "expected a COPY machine instruction"); - - if (DisableNAPhysCopyOpt) - return false; - -- unsigned DstReg = MI->getOperand(0).getReg(); -- unsigned SrcReg = MI->getOperand(1).getReg(); -+ unsigned DstReg = MI.getOperand(0).getReg(); -+ unsigned SrcReg = MI.getOperand(1).getReg(); - if (isNAPhysCopy(SrcReg) && TargetRegisterInfo::isVirtualRegister(DstReg)) { - // %vreg = COPY %physreg - // Avoid using a datastructure which can track multiple live non-allocatable - // phys->virt copies since LLVM doesn't seem to do this. -- NAPhysToVirtMIs.insert({SrcReg, MI}); -+ NAPhysToVirtMIs.insert({SrcReg, &MI}); - return false; - } - -@@ -1528,8 +1462,7 @@ bool PeepholeOptimizer::foldRedundantNAP - if (PrevCopy == NAPhysToVirtMIs.end()) { - // We can't remove the copy: there was an intervening clobber of the - // non-allocatable physical register after the copy to virtual. -- DEBUG(dbgs() << "NAPhysCopy: intervening clobber forbids erasing " << *MI -- << '\n'); -+ DEBUG(dbgs() << "NAPhysCopy: intervening clobber forbids erasing " << MI); - return false; - } - -@@ -1537,7 +1470,7 @@ bool PeepholeOptimizer::foldRedundantNAP - if (PrevDstReg == SrcReg) { - // Remove the virt->phys copy: we saw the virtual register definition, and - // the non-allocatable physical register's state hasn't changed since then. -- DEBUG(dbgs() << "NAPhysCopy: erasing " << *MI << '\n'); -+ DEBUG(dbgs() << "NAPhysCopy: erasing " << MI); - ++NumNAPhysCopies; - return true; - } -@@ -1546,7 +1479,7 @@ bool PeepholeOptimizer::foldRedundantNAP - // register get a copy of the non-allocatable physical register, and we only - // track one such copy. Avoid getting confused by this new non-allocatable - // physical register definition, and remove it from the tracked copies. -- DEBUG(dbgs() << "NAPhysCopy: missed opportunity " << *MI << '\n'); -+ DEBUG(dbgs() << "NAPhysCopy: missed opportunity " << MI); - NAPhysToVirtMIs.erase(PrevCopy); - return false; - } -@@ -1611,11 +1544,11 @@ bool PeepholeOptimizer::findTargetRecurr - return false; - } - --/// \brief Phi instructions will eventually be lowered to copy instructions. If --/// phi is in a loop header, a recurrence may formulated around the source and --/// destination of the phi. For such case commuting operands of the instructions --/// in the recurrence may enable coalescing of the copy instruction generated --/// from the phi. For example, if there is a recurrence of -+/// Phi instructions will eventually be lowered to copy instructions. -+/// If phi is in a loop header, a recurrence may formulated around the source -+/// and destination of the phi. For such case commuting operands of the -+/// instructions in the recurrence may enable coalescing of the copy instruction -+/// generated from the phi. For example, if there is a recurrence of - /// - /// LoopHeader: - /// %1 = phi(%0, %100) -@@ -1725,27 +1658,25 @@ bool PeepholeOptimizer::runOnMachineFunc - } - - if (!MI->isCopy()) { -- for (const auto &Op : MI->operands()) { -+ for (const MachineOperand &MO : MI->operands()) { - // Visit all operands: definitions can be implicit or explicit. -- if (Op.isReg()) { -- unsigned Reg = Op.getReg(); -- if (Op.isDef() && isNAPhysCopy(Reg)) { -+ if (MO.isReg()) { -+ unsigned Reg = MO.getReg(); -+ if (MO.isDef() && isNAPhysCopy(Reg)) { - const auto &Def = NAPhysToVirtMIs.find(Reg); - if (Def != NAPhysToVirtMIs.end()) { - // A new definition of the non-allocatable physical register - // invalidates previous copies. -- DEBUG(dbgs() << "NAPhysCopy: invalidating because of " << *MI -- << '\n'); -+ DEBUG(dbgs() << "NAPhysCopy: invalidating because of " << *MI); - NAPhysToVirtMIs.erase(Def); - } - } -- } else if (Op.isRegMask()) { -- const uint32_t *RegMask = Op.getRegMask(); -+ } else if (MO.isRegMask()) { -+ const uint32_t *RegMask = MO.getRegMask(); - for (auto &RegMI : NAPhysToVirtMIs) { - unsigned Def = RegMI.first; - if (MachineOperand::clobbersPhysReg(RegMask, Def)) { -- DEBUG(dbgs() << "NAPhysCopy: invalidating because of " << *MI -- << '\n'); -+ DEBUG(dbgs() << "NAPhysCopy: invalidating because of " << *MI); - NAPhysToVirtMIs.erase(Def); - } - } -@@ -1761,58 +1692,57 @@ bool PeepholeOptimizer::runOnMachineFunc - // don't know what's correct anymore. - // - // FIXME: handle explicit asm clobbers. -- DEBUG(dbgs() << "NAPhysCopy: blowing away all info due to " << *MI -- << '\n'); -+ DEBUG(dbgs() << "NAPhysCopy: blowing away all info due to " << *MI); - NAPhysToVirtMIs.clear(); - } - - if ((isUncoalescableCopy(*MI) && -- optimizeUncoalescableCopy(MI, LocalMIs)) || -- (MI->isCompare() && optimizeCmpInstr(MI, &MBB)) || -- (MI->isSelect() && optimizeSelect(MI, LocalMIs))) { -+ optimizeUncoalescableCopy(*MI, LocalMIs)) || -+ (MI->isCompare() && optimizeCmpInstr(*MI)) || -+ (MI->isSelect() && optimizeSelect(*MI, LocalMIs))) { - // MI is deleted. - LocalMIs.erase(MI); - Changed = true; - continue; - } - -- if (MI->isConditionalBranch() && optimizeCondBranch(MI)) { -+ if (MI->isConditionalBranch() && optimizeCondBranch(*MI)) { - Changed = true; - continue; - } - -- if (isCoalescableCopy(*MI) && optimizeCoalescableCopy(MI)) { -+ if (isCoalescableCopy(*MI) && optimizeCoalescableCopy(*MI)) { - // MI is just rewritten. - Changed = true; - continue; - } - - if (MI->isCopy() && -- (foldRedundantCopy(MI, CopySrcRegs, CopySrcMIs) || -- foldRedundantNAPhysCopy(MI, NAPhysToVirtMIs))) { -+ (foldRedundantCopy(*MI, CopySrcRegs, CopySrcMIs) || -+ foldRedundantNAPhysCopy(*MI, NAPhysToVirtMIs))) { - LocalMIs.erase(MI); - MI->eraseFromParent(); - Changed = true; - continue; - } - -- if (isMoveImmediate(MI, ImmDefRegs, ImmDefMIs)) { -+ if (isMoveImmediate(*MI, ImmDefRegs, ImmDefMIs)) { - SeenMoveImm = true; - } else { -- Changed |= optimizeExtInstr(MI, &MBB, LocalMIs); -+ Changed |= optimizeExtInstr(*MI, MBB, LocalMIs); - // optimizeExtInstr might have created new instructions after MI - // and before the already incremented MII. Adjust MII so that the - // next iteration sees the new instructions. - MII = MI; - ++MII; - if (SeenMoveImm) -- Changed |= foldImmediate(MI, &MBB, ImmDefRegs, ImmDefMIs); -+ Changed |= foldImmediate(*MI, ImmDefRegs, ImmDefMIs); - } - - // Check whether MI is a load candidate for folding into a later - // instruction. If MI is not a candidate, check whether we can fold an - // earlier load into MI. -- if (!isLoadFoldable(MI, FoldAsLoadDefCandidates) && -+ if (!isLoadFoldable(*MI, FoldAsLoadDefCandidates) && - !FoldAsLoadDefCandidates.empty()) { - - // We visit each operand even after successfully folding a previous -@@ -1861,7 +1791,7 @@ bool PeepholeOptimizer::runOnMachineFunc - // the load candidates. Note: We might be able to fold *into* this - // instruction, so this needs to be after the folding logic. - if (MI->isLoadFoldBarrier()) { -- DEBUG(dbgs() << "Encountered load fold barrier on " << *MI << "\n"); -+ DEBUG(dbgs() << "Encountered load fold barrier on " << *MI); - FoldAsLoadDefCandidates.clear(); - } - } -@@ -1958,14 +1888,14 @@ ValueTrackerResult ValueTracker::getNext - // duplicate the code from the generic TII. - return ValueTrackerResult(); - -- SmallVector RegSeqInputRegs; -+ SmallVector RegSeqInputRegs; - if (!TII->getRegSequenceInputs(*Def, DefIdx, RegSeqInputRegs)) - return ValueTrackerResult(); - - // We are looking at: - // Def = REG_SEQUENCE v0, sub0, v1, sub1, ... - // Check if one of the operand defines the subreg we are interested in. -- for (auto &RegSeqInput : RegSeqInputRegs) { -+ for (const RegSubRegPairAndIdx &RegSeqInput : RegSeqInputRegs) { - if (RegSeqInput.SubIdx == DefSubReg) { - if (RegSeqInput.SubReg) - // Bail if we have to compose sub registers. -@@ -1996,8 +1926,8 @@ ValueTrackerResult ValueTracker::getNext - // duplicate the code from the generic TII. - return ValueTrackerResult(); - -- TargetInstrInfo::RegSubRegPair BaseReg; -- TargetInstrInfo::RegSubRegPairAndIdx InsertedReg; -+ RegSubRegPair BaseReg; -+ RegSubRegPairAndIdx InsertedReg; - if (!TII->getInsertSubregInputs(*Def, DefIdx, BaseReg, InsertedReg)) - return ValueTrackerResult(); - -@@ -2050,7 +1980,7 @@ ValueTrackerResult ValueTracker::getNext - // duplicate the code from the generic TII. - return ValueTrackerResult(); - -- TargetInstrInfo::RegSubRegPairAndIdx ExtractSubregInputReg; -+ RegSubRegPairAndIdx ExtractSubregInputReg; - if (!TII->getExtractSubregInputs(*Def, DefIdx, ExtractSubregInputReg)) - return ValueTrackerResult(); - -@@ -2083,7 +2013,7 @@ ValueTrackerResult ValueTracker::getNext - Def->getOperand(3).getImm()); - } - --/// \brief Explore each PHI incoming operand and return its sources -+/// Explore each PHI incoming operand and return its sources. - ValueTrackerResult ValueTracker::getNextSourceFromPHI() { - assert(Def->isPHI() && "Invalid definition"); - ValueTrackerResult Res; -@@ -2095,7 +2025,7 @@ ValueTrackerResult ValueTracker::getNext - - // Return all register sources for PHI instructions. - for (unsigned i = 1, e = Def->getNumOperands(); i < e; i += 2) { -- auto &MO = Def->getOperand(i); -+ const MachineOperand &MO = Def->getOperand(i); - assert(MO.isReg() && "Invalid PHI instruction"); - // We have no code to deal with undef operands. They shouldn't happen in - // normal programs anyway. -@@ -2121,7 +2051,7 @@ ValueTrackerResult ValueTracker::getNext - return getNextSourceFromBitcast(); - // All the remaining cases involve "complex" instructions. - // Bail if we did not ask for the advanced tracking. -- if (!UseAdvancedTracking) -+ if (DisableAdvCopyOpt) - return ValueTrackerResult(); - if (Def->isRegSequence() || Def->isRegSequenceLike()) - return getNextSourceFromRegSequence(); diff --git a/debian/patches/rL338481-cherry-pick-really-subtle-miscompile.diff b/debian/patches/rL338481-cherry-pick-really-subtle-miscompile.diff deleted file mode 100644 index 07653e53..00000000 --- a/debian/patches/rL338481-cherry-pick-really-subtle-miscompile.diff +++ /dev/null @@ -1,153 +0,0 @@ -Index: llvm-toolchain-6.0-6.0.1/test/CodeGen/X86/flags-copy-lowering.mir -=================================================================== ---- llvm-toolchain-6.0-6.0.1.orig/test/CodeGen/X86/flags-copy-lowering.mir -+++ llvm-toolchain-6.0-6.0.1/test/CodeGen/X86/flags-copy-lowering.mir -@@ -72,6 +72,18 @@ - call void @foo() - ret void - } -+ -+ define i32 @test_existing_setcc(i64 %a, i64 %b) { -+ entry: -+ call void @foo() -+ ret i32 0 -+ } -+ -+ define i32 @test_existing_setcc_memory(i64 %a, i64 %b) { -+ entry: -+ call void @foo() -+ ret i32 0 -+ } - ... - --- - name: test_branch -@@ -553,3 +565,110 @@ body: | - RET 0 - - ... -+--- -+name: test_existing_setcc -+# CHECK-LABEL: name: test_existing_setcc -+liveins: -+ - { reg: '$rdi', virtual-reg: '%0' } -+ - { reg: '$rsi', virtual-reg: '%1' } -+body: | -+ bb.0: -+ successors: %bb.1, %bb.2, %bb.3 -+ liveins: $rdi, $rsi -+ -+ %0:gr64 = COPY $rdi -+ %1:gr64 = COPY $rsi -+ CMP64rr %0, %1, implicit-def $eflags -+ %2:gr8 = SETAr implicit $eflags -+ %3:gr8 = SETAEr implicit $eflags -+ %4:gr64 = COPY $eflags -+ ; CHECK: CMP64rr %0, %1, implicit-def $eflags -+ ; CHECK-NEXT: %[[A_REG:[^:]*]]:gr8 = SETAr implicit $eflags -+ ; CHECK-NEXT: %[[AE_REG:[^:]*]]:gr8 = SETAEr implicit $eflags -+ ; CHECK-NOT: COPY{{( killed)?}} $eflags -+ -+ ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp -+ CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax -+ ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp -+ -+ $eflags = COPY %4 -+ JA_1 %bb.1, implicit $eflags -+ JB_1 %bb.2, implicit $eflags -+ JMP_1 %bb.3 -+ ; CHECK-NOT: $eflags = -+ ; -+ ; CHECK: TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags -+ ; CHECK-NEXT: JNE_1 %bb.1, implicit killed $eflags -+ ; CHECK-SAME: {{$[[:space:]]}} -+ ; CHECK-NEXT: bb.4: -+ ; CHECK-NEXT: successors: {{.*$}} -+ ; CHECK-SAME: {{$[[:space:]]}} -+ ; CHECK-NEXT: TEST8rr %[[AE_REG]], %[[AE_REG]], implicit-def $eflags -+ ; CHECK-NEXT: JE_1 %bb.2, implicit killed $eflags -+ ; CHECK-NEXT: JMP_1 %bb.3 -+ -+ bb.1: -+ %5:gr32 = MOV32ri64 42 -+ $eax = COPY %5 -+ RET 0, $eax -+ -+ bb.2: -+ %6:gr32 = MOV32ri64 43 -+ $eax = COPY %6 -+ RET 0, $eax -+ -+ bb.3: -+ %7:gr32 = MOV32r0 implicit-def dead $eflags -+ $eax = COPY %7 -+ RET 0, $eax -+ -+... -+--- -+name: test_existing_setcc_memory -+# CHECK-LABEL: name: test_existing_setcc_memory -+liveins: -+ - { reg: '$rdi', virtual-reg: '%0' } -+ - { reg: '$rsi', virtual-reg: '%1' } -+body: | -+ bb.0: -+ successors: %bb.1, %bb.2 -+ liveins: $rdi, $rsi -+ -+ %0:gr64 = COPY $rdi -+ %1:gr64 = COPY $rsi -+ CMP64rr %0, %1, implicit-def $eflags -+ SETEm %0, 1, $noreg, -16, $noreg, implicit $eflags -+ %2:gr64 = COPY $eflags -+ ; CHECK: CMP64rr %0, %1, implicit-def $eflags -+ ; We cannot reuse this SETE because it stores the flag directly to memory, -+ ; so we have two SETEs here. FIXME: It'd be great if something could fold -+ ; these automatically. If not, maybe we want to unfold SETcc instructions -+ ; writing to memory so we can reuse them. -+ ; CHECK-NEXT: SETEm {{.*}} implicit $eflags -+ ; CHECK-NEXT: %[[E_REG:[^:]*]]:gr8 = SETEr implicit $eflags -+ ; CHECK-NOT: COPY{{( killed)?}} $eflags -+ -+ ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp -+ CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax -+ ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp -+ -+ $eflags = COPY %2 -+ JE_1 %bb.1, implicit $eflags -+ JMP_1 %bb.2 -+ ; CHECK-NOT: $eflags = -+ ; -+ ; CHECK: TEST8rr %[[E_REG]], %[[E_REG]], implicit-def $eflags -+ ; CHECK-NEXT: JNE_1 %bb.1, implicit killed $eflags -+ ; CHECK-NEXT: JMP_1 %bb.2 -+ -+ bb.1: -+ %3:gr32 = MOV32ri64 42 -+ $eax = COPY %3 -+ RET 0, $eax -+ -+ bb.2: -+ %4:gr32 = MOV32ri64 43 -+ $eax = COPY %4 -+ RET 0, $eax -+ -+... -Index: llvm-toolchain-6.0-6.0.1/lib/Target/X86/X86FlagsCopyLowering.cpp -=================================================================== ---- llvm-toolchain-6.0-6.0.1.orig/lib/Target/X86/X86FlagsCopyLowering.cpp -+++ llvm-toolchain-6.0-6.0.1/lib/Target/X86/X86FlagsCopyLowering.cpp -@@ -608,9 +608,12 @@ X86FlagsCopyLoweringPass::collectCondsIn - for (MachineInstr &MI : llvm::reverse( - llvm::make_range(MBB.instr_begin(), CopyDefI.getIterator()))) { - X86::CondCode Cond = X86::getCondFromSETOpc(MI.getOpcode()); -- if (Cond != X86::COND_INVALID && MI.getOperand(0).isReg() && -- TRI->isVirtualRegister(MI.getOperand(0).getReg())) -+ if (Cond != X86::COND_INVALID && !MI.mayStore() && MI.getOperand(0).isReg() && -+ TRI->isVirtualRegister(MI.getOperand(0).getReg())) { -+ assert(MI.getOperand(0).isDef() && -+ "A non-storing SETcc should always define a register!"); - CondRegs[Cond] = MI.getOperand(0).getReg(); -+ } - - // Stop scanning when we see the first definition of the EFLAGS as prior to - // this we would potentially capture the wrong flag state. From 378cf95ac2d3a1d3aa7b57ae650dd37616b04167 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Tue, 11 Sep 2018 12:03:44 +0200 Subject: [PATCH 2/4] bring back the patch --- debian/patches/D51108.diff | 65 ++++++++++++++++++++++++++++++++++++++ debian/patches/series | 4 +++ 2 files changed, 69 insertions(+) create mode 100644 debian/patches/D51108.diff diff --git a/debian/patches/D51108.diff b/debian/patches/D51108.diff new file mode 100644 index 00000000..aa7f7196 --- /dev/null +++ b/debian/patches/D51108.diff @@ -0,0 +1,65 @@ +Index: llvm-toolchain-6.0-6.0.1/lib/Target/PowerPC/PPCISelLowering.cpp +=================================================================== +--- llvm-toolchain-6.0-6.0.1.orig/lib/Target/PowerPC/PPCISelLowering.cpp ++++ llvm-toolchain-6.0-6.0.1/lib/Target/PowerPC/PPCISelLowering.cpp +@@ -3351,9 +3351,14 @@ + // Argument stored in memory. + assert(VA.isMemLoc()); + ++ // Get the extended size of the argument type in stack + unsigned ArgSize = VA.getLocVT().getStoreSize(); +- int FI = MFI.CreateFixedObject(ArgSize, VA.getLocMemOffset(), +- isImmutable); ++ // Get the actual size of the argument type ++ unsigned ObjSize = VA.getValVT().getStoreSize(); ++ unsigned ArgOffset = VA.getLocMemOffset(); ++ // Stack objects in PPC32 are right justified. ++ ArgOffset += ArgSize - ObjSize; ++ int FI = MFI.CreateFixedObject(ArgSize, ArgOffset, isImmutable); + + // Create load nodes to retrieve arguments from the stack. + SDValue FIN = DAG.getFrameIndex(FI, PtrVT); +@@ -5303,10 +5308,11 @@ + Arg = PtrOff; + } + +- if (VA.isRegLoc()) { +- if (Arg.getValueType() == MVT::i1) +- Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i32, Arg); ++ // Ensure callee will get either 0x00000001 or 0x00000000. ++ if (Arg.getValueType() == MVT::i1) ++ Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i32, Arg); + ++ if (VA.isRegLoc()) { + seenFloatArg |= VA.getLocVT().isFloatingPoint(); + // Put argument in a physical register. + RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); +Index: llvm-toolchain-6.0-6.0.1/test/CodeGen/PowerPC/ppc32-i1-stack-arguments-abi-bug.ll +=================================================================== +--- /dev/null ++++ llvm-toolchain-6.0-6.0.1/test/CodeGen/PowerPC/ppc32-i1-stack-arguments-abi-bug.ll +@@ -0,0 +1,24 @@ ++; RUN: llc -verify-machineinstrs < %s -mcpu=ppc32 -mattr=+crbits | FileCheck %s ++target triple = "powerpc-unknown-linux-gnu" ++ ++define zeroext i1 @check_callee( ++ i1 zeroext, i1 zeroext, i1 zeroext, i1 zeroext, ++ i1 zeroext, i1 zeroext, i1 zeroext, i1 zeroext, ++ i1 zeroext %s1 ++) { ++ call void @check_caller( ++ i1 zeroext true, i1 zeroext true, i1 zeroext true, i1 zeroext true, ++ i1 zeroext true, i1 zeroext true, i1 zeroext true, i1 zeroext true, ++ i1 zeroext %s1) ++ ret i1 true ++} ++ ++; CHECK-LABEL: @check_callee ++; CHECK: lbz {{[0-9]+}}, 27(1) ++; CHECK: stw {{[0-9]+}}, 8(1) ++ ++declare void @check_caller( ++ i1 zeroext, i1 zeroext, i1 zeroext, i1 zeroext, ++ i1 zeroext, i1 zeroext, i1 zeroext, i1 zeroext, ++ i1 zeroext ++) diff --git a/debian/patches/series b/debian/patches/series index bdfeff29..03767add 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -68,3 +68,7 @@ libcxx-test-atomics-set-compare-exchange-to-be-expected-fails-on-arm.patch libcxx-silent-test-libcxx.diff libcxx-silent-failure-ppc64el.diff libcxx-silent-failure-arm64.diff + +# Rust on ppc +D51108.diff + From 667fdfb8fc4ee00a3b5937b3894e21416afe343d Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Tue, 11 Sep 2018 12:08:46 +0200 Subject: [PATCH 3/4] bring back the patch + refresh --- debian/patches/D51108.diff | 14 +++++++------- debian/patches/series | 1 - 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/debian/patches/D51108.diff b/debian/patches/D51108.diff index aa7f7196..bb321ed4 100644 --- a/debian/patches/D51108.diff +++ b/debian/patches/D51108.diff @@ -1,8 +1,8 @@ -Index: llvm-toolchain-6.0-6.0.1/lib/Target/PowerPC/PPCISelLowering.cpp +Index: llvm-toolchain-7-7~+rc2/lib/Target/PowerPC/PPCISelLowering.cpp =================================================================== ---- llvm-toolchain-6.0-6.0.1.orig/lib/Target/PowerPC/PPCISelLowering.cpp -+++ llvm-toolchain-6.0-6.0.1/lib/Target/PowerPC/PPCISelLowering.cpp -@@ -3351,9 +3351,14 @@ +--- llvm-toolchain-7-7~+rc2.orig/lib/Target/PowerPC/PPCISelLowering.cpp ++++ llvm-toolchain-7-7~+rc2/lib/Target/PowerPC/PPCISelLowering.cpp +@@ -3480,9 +3480,14 @@ SDValue PPCTargetLowering::LowerFormalAr // Argument stored in memory. assert(VA.isMemLoc()); @@ -19,7 +19,7 @@ Index: llvm-toolchain-6.0-6.0.1/lib/Target/PowerPC/PPCISelLowering.cpp // Create load nodes to retrieve arguments from the stack. SDValue FIN = DAG.getFrameIndex(FI, PtrVT); -@@ -5303,10 +5308,11 @@ +@@ -5437,10 +5442,11 @@ SDValue PPCTargetLowering::LowerCall_32S Arg = PtrOff; } @@ -34,10 +34,10 @@ Index: llvm-toolchain-6.0-6.0.1/lib/Target/PowerPC/PPCISelLowering.cpp seenFloatArg |= VA.getLocVT().isFloatingPoint(); // Put argument in a physical register. RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); -Index: llvm-toolchain-6.0-6.0.1/test/CodeGen/PowerPC/ppc32-i1-stack-arguments-abi-bug.ll +Index: llvm-toolchain-7-7~+rc2/test/CodeGen/PowerPC/ppc32-i1-stack-arguments-abi-bug.ll =================================================================== --- /dev/null -+++ llvm-toolchain-6.0-6.0.1/test/CodeGen/PowerPC/ppc32-i1-stack-arguments-abi-bug.ll ++++ llvm-toolchain-7-7~+rc2/test/CodeGen/PowerPC/ppc32-i1-stack-arguments-abi-bug.ll @@ -0,0 +1,24 @@ +; RUN: llc -verify-machineinstrs < %s -mcpu=ppc32 -mattr=+crbits | FileCheck %s +target triple = "powerpc-unknown-linux-gnu" diff --git a/debian/patches/series b/debian/patches/series index 03767add..3213c479 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -58,7 +58,6 @@ impl-path-hurd.diff openmp-check-execstack.diff openmp-soname.diff openmp-mips-affinity.patch -D51108.diff # libcxx libcxxabi-test-don-t-fail-extended-long-double.patch From 3e29ccee3a1b2d5081e3d4e66e38902586210e48 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Tue, 11 Sep 2018 12:12:04 +0200 Subject: [PATCH 4/4] rename the patch --- debian/patches/{D51108.diff => D51108-rust-powerpc.diff} | 0 debian/patches/series | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename debian/patches/{D51108.diff => D51108-rust-powerpc.diff} (100%) diff --git a/debian/patches/D51108.diff b/debian/patches/D51108-rust-powerpc.diff similarity index 100% rename from debian/patches/D51108.diff rename to debian/patches/D51108-rust-powerpc.diff diff --git a/debian/patches/series b/debian/patches/series index 3213c479..2743a781 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -69,5 +69,5 @@ libcxx-silent-failure-ppc64el.diff libcxx-silent-failure-arm64.diff # Rust on ppc -D51108.diff +D51108-rust-powerpc.diff