[llvm-branch-commits] [llvm][ProfDataUtils] provide getNumBranchWeights API (PR #90146)
https://github.com/MatzeB approved this pull request. LGTM https://github.com/llvm/llvm-project/pull/90146 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm][IR] Extend BranchWeightMetadata to track provenance of weights (PR #86609)
https://github.com/MatzeB edited https://github.com/llvm/llvm-project/pull/86609 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm][IR] Extend BranchWeightMetadata to track provenance of weights (PR #86609)
https://github.com/MatzeB edited https://github.com/llvm/llvm-project/pull/86609 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm][IR] Extend BranchWeightMetadata to track provenance of weights (PR #86609)
@@ -4756,8 +4757,10 @@ void Verifier::visitProfMetadata(Instruction , MDNode *MD) { // Check consistency of !prof branch_weights metadata. if (ProfName.equals("branch_weights")) { +unsigned int Offset = getBranchWeightOffset(I); if (isa()) { - Check(MD->getNumOperands() == 2 || MD->getNumOperands() == 3, + Check(MD->getNumOperands() == (1 + Offset) || +MD->getNumOperands() == (2 + Offset), MatzeB wrote: More opportunities for a possible `getNumBranchWeights(...)` API... https://github.com/llvm/llvm-project/pull/86609 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm][IR] Extend BranchWeightMetadata to track provenance of weights (PR #86609)
@@ -55,6 +55,20 @@ MDNode *getBranchWeightMDNode(const Instruction ); /// Nullptr otherwise. MDNode *getValidBranchWeightMDNode(const Instruction ); +/// Check if Branch Weight Metadata has an "expected" field from an llvm.expect* +/// intrinsic +bool hasExpectedProvenance(const Instruction ); MatzeB wrote: Hmm maybe this should somehow have the name "Weight" in the name, to not introduce confusion with alias-analysis things (at least I immediately think "alias analysis" when I see the word "provenance") or find different term than "provenance"? https://github.com/llvm/llvm-project/pull/86609 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm][IR] Extend BranchWeightMetadata to track provenance of weights (PR #86609)
@@ -55,6 +55,20 @@ MDNode *getBranchWeightMDNode(const Instruction ); /// Nullptr otherwise. MDNode *getValidBranchWeightMDNode(const Instruction ); +/// Check if Branch Weight Metadata has an "expected" field from an llvm.expect* +/// intrinsic +bool hasExpectedProvenance(const Instruction ); + +/// Check if Branch Weight Metadata has an "expected" field from an llvm.expect* +/// intrinsic +bool hasExpectedProvenance(const MDNode *ProfileData); MatzeB wrote: FWIW: I usually prefer references like `const MDNode ` to indicate that an argument mustn't be `nullptr`. Though admittedly that remark comes too late given we already have other `const MDNode *` APIs in this header consistency is also worth something... So I guess I'm fine either way... https://github.com/llvm/llvm-project/pull/86609 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm][IR] Extend BranchWeightMetadata to track provenance of weights (PR #86609)
@@ -1210,12 +1210,22 @@ Instruction *Instruction::cloneImpl() const { void Instruction::swapProfMetadata() { MDNode *ProfileData = getBranchWeightMDNode(*this); - if (!ProfileData || ProfileData->getNumOperands() != 3) + if (!isBranchWeightMD(ProfileData)) return; - // The first operand is the name. Fetch them backwards and build a new one. - Metadata *Ops[] = {ProfileData->getOperand(0), ProfileData->getOperand(2), - ProfileData->getOperand(1)}; + SmallVector Ops; + unsigned int FirstIdx = getBranchWeightOffset(ProfileData); + unsigned int SecondIdx = FirstIdx + 1; + // If there are more weights past the second, we can't swap them + if (ProfileData->getNumOperands() > SecondIdx + 1) +return; + Ops.push_back(ProfileData->getOperand(0)); + if (hasExpectedProvenance(ProfileData)) { +Ops.push_back(ProfileData->getOperand(1)); + } MatzeB wrote: Maybe this (I just have a feeling that leaving it more generic may help in case new sources are added one day): ```suggestion for (unsigned I = 0; I < FirstIdx; I++) { Ops.push_back(ProfileData->getOperand(I)); } ``` https://github.com/llvm/llvm-project/pull/86609 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm][IR] Extend BranchWeightMetadata to track provenance of weights (PR #86609)
@@ -1210,12 +1210,22 @@ Instruction *Instruction::cloneImpl() const { void Instruction::swapProfMetadata() { MDNode *ProfileData = getBranchWeightMDNode(*this); - if (!ProfileData || ProfileData->getNumOperands() != 3) + if (!isBranchWeightMD(ProfileData)) return; - // The first operand is the name. Fetch them backwards and build a new one. - Metadata *Ops[] = {ProfileData->getOperand(0), ProfileData->getOperand(2), - ProfileData->getOperand(1)}; + SmallVector Ops; + unsigned int FirstIdx = getBranchWeightOffset(ProfileData); MatzeB wrote: Not a strong opinion, but I think most people just write `unsigned` in LLVM codebase... ```suggestion unsigned FirstIdx = getBranchWeightOffset(ProfileData); ``` https://github.com/llvm/llvm-project/pull/86609 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm][IR] Extend BranchWeightMetadata to track provenance of weights (PR #86609)
@@ -5196,7 +5198,11 @@ void SwitchInstProfUpdateWrapper::init() { if (!ProfileData) return; - if (ProfileData->getNumOperands() != SI.getNumSuccessors() + 1) { + // FIXME: This check belongs in ProfDataUtils. Its almost equivalent to + // getValidBranchWeightMDNode(), but the need to use llvm_unreachable + // makes them slightly different. + if (ProfileData->getNumOperands() != + SI.getNumSuccessors() + getBranchWeightOffset(ProfileData)) { MatzeB wrote: This seems simple enough to do something about it? Could for example add a `getNumBranchWeights()` API so this can become `getNumBranchWeights(ProfileData) != SI.getNumSuccessors()`? https://github.com/llvm/llvm-project/pull/86609 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm][IR] Extend BranchWeightMetadata to track provenance of weights (PR #86609)
@@ -106,6 +104,30 @@ bool hasValidBranchWeightMD(const Instruction ) { return getValidBranchWeightMDNode(I); } +bool hasExpectedProvenance(const Instruction ) { + auto *ProfileData = I.getMetadata(LLVMContext::MD_prof); + return hasExpectedProvenance(ProfileData); +} + +bool hasExpectedProvenance(const MDNode *ProfileData) { + if (!isBranchWeightMD(ProfileData)) +return false; + + auto *ProfDataName = dyn_cast(ProfileData->getOperand(1)); + if (!ProfDataName) +return false; + return ProfDataName->getString().equals("expected"); +} + +unsigned getBranchWeightOffset(const Instruction ) { + auto *ProfileData = I.getMetadata(LLVMContext::MD_prof); + return getBranchWeightOffset(ProfileData); +} + +unsigned getBranchWeightOffset(const MDNode *ProfileData) { + return hasExpectedProvenance(ProfileData) ? 2 : 1; +} MatzeB wrote: What about a `hasBranchWeightProvenance()` API instead that just checks whether there is a string? That way you would get the same effect today but can skip the string comparison (and maybe get better behavior if there is a string that isn't actually "expected") https://github.com/llvm/llvm-project/pull/86609 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm][IR] Extend BranchWeightMetadata to track provenance of weights (PR #86609)
@@ -55,6 +55,20 @@ MDNode *getBranchWeightMDNode(const Instruction ); /// Nullptr otherwise. MDNode *getValidBranchWeightMDNode(const Instruction ); +/// Check if Branch Weight Metadata has an "expected" field from an llvm.expect* +/// intrinsic +bool hasExpectedProvenance(const Instruction ); + +/// Check if Branch Weight Metadata has an "expected" field from an llvm.expect* +/// intrinsic +bool hasExpectedProvenance(const MDNode *ProfileData); + +/// Return the offset to the first branch weight data +unsigned getBranchWeightOffset(const Instruction ); MatzeB wrote: Is this API really helpful? Don't you have to get your hands on an `MDNode` anyway to do something useful with that offset? https://github.com/llvm/llvm-project/pull/86609 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm][IR] Extend BranchWeightMetadata to track provenance of weights (PR #86609)
https://github.com/MatzeB commented: I guess this is deliberately designed around a `bool IsExpected` rather than a more generic API. I guess I'm fine with it given the current patch, though I would bet it's just a question of time for someone to add more sources now... (so gotta make sure to turn the API into a generic one when there is more sources coming around) Added a bunch of nitpicks, naming discussions etc. Though all-in-all this looks good to me. https://github.com/llvm/llvm-project/pull/86609 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm][IR] Extend BranchWeightMetadata to track provenance of weights (PR #86609)
https://github.com/MatzeB edited https://github.com/llvm/llvm-project/pull/86609 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [LivePhysRegs] Add callee-saved regs from MFI in addLiveOutsNoPristines. (PR #73553)
MatzeB wrote: Looking at the `MachineOutliner` it seems to already be using `addLiveOuts()` so I must be missing something on why this change has any effect anyway... https://github.com/llvm/llvm-project/pull/73553 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [LivePhysRegs] Add callee-saved regs from MFI in addLiveOutsNoPristines. (PR #73553)
MatzeB wrote: Which code/pass is using `LivePhysRegs` that is causing you trouble here? https://github.com/llvm/llvm-project/pull/73553 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [LivePhysRegs] Add callee-saved regs from MFI in addLiveOutsNoPristines. (PR #73553)
MatzeB wrote: I still feel like I am missing something here, and it's been a while since I looked at this. But my impression is that LLVM modeling is "cheating" a bit in that technically all the callee-saves should be implicit-uses of the return instruction (and not live afterwards) but we don't model it that way and instead make them appear as live-outs of the return block? So doesn't seem like overestimating the liveness because of our current modeling? If I'm reading your patch correctly it would mean we would start adding all pristine registers for the return block. I am just confused so far because this is happening in a function called `addLiveOutsNoPristines`... https://github.com/llvm/llvm-project/pull/73553 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [LivePhysRegs] Add callee-saved regs from MFI in addLiveOutsNoPristines. (PR #73553)
MatzeB wrote: I don't remember the situation on aarch64, but if by chance LR is modeled with this "pristine register" concept, then maybe the caller needs to use `addLiveIns()` rather than `addLiveInsNoPristines()`? https://github.com/llvm/llvm-project/pull/73553 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] [LivePhysRegs] Add callee-saved regs from MFI in addLiveOutsNoPristines. (PR #73553)
MatzeB wrote: Is this about computing *live-outs* of the return block as the code suggests? (The summary currently talks about live-ins?) https://github.com/llvm/llvm-project/pull/73553 ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm] ad25f8a - X86InstrInfo: Support immediates that are +1/-1 different in optimizeCompareInstr
Author: Matthias Braun Date: 2022-01-11T09:07:29-08:00 New Revision: ad25f8a556d239d8b7d17383cf1a0771359521fd URL: https://github.com/llvm/llvm-project/commit/ad25f8a556d239d8b7d17383cf1a0771359521fd DIFF: https://github.com/llvm/llvm-project/commit/ad25f8a556d239d8b7d17383cf1a0771359521fd.diff LOG: X86InstrInfo: Support immediates that are +1/-1 different in optimizeCompareInstr This is a re-commit of e2c7ee0743592e39274e28dbe0d0c213ba342317 which was reverted in a2a58d91e82db38fbdf88cc317dcb3753d79d492 and ea81cea8163a1a0e54df42103ee1c657bbf03791. This includes a fix to consistently check for EFLAGS being live-out. See phabricator review. Original Summary: This extends `optimizeCompareInstr` to re-use previous comparison results if the previous comparison was with an immediate that was 1 bigger or smaller. Example: CMP x, 13 ... CMP x, 12 ; can be removed if we change the SETg SETg ...; x > 12 changed to `SETge` (x >= 13) removing CMP Motivation: This often happens because SelectionDAG canonicalization tends to add/subtract 1 often when optimizing for fallthrough blocks. Example for `x > C` the fallthrough optimization switches true/false blocks with `!(x > C)` --> `x <= C` and canonicalization turns this into `x < C + 1`. Differential Revision: https://reviews.llvm.org/D110867 Added: llvm/test/CodeGen/X86/peep-test-5.ll Modified: llvm/lib/Target/X86/X86InstrInfo.cpp llvm/lib/Target/X86/X86InstrInfo.h llvm/test/CodeGen/X86/optimize-compare.mir llvm/test/CodeGen/X86/use-cr-result-of-dom-icmp-st.ll Removed: diff --git a/llvm/lib/Target/X86/X86InstrInfo.cpp b/llvm/lib/Target/X86/X86InstrInfo.cpp index c379aa8d9258..4dcd886fa3b2 100644 --- a/llvm/lib/Target/X86/X86InstrInfo.cpp +++ b/llvm/lib/Target/X86/X86InstrInfo.cpp @@ -4088,8 +4088,8 @@ bool X86InstrInfo::analyzeCompare(const MachineInstr , Register , bool X86InstrInfo::isRedundantFlagInstr(const MachineInstr , Register SrcReg, Register SrcReg2, int64_t ImmMask, int64_t ImmValue, -const MachineInstr , -bool *IsSwapped) const { +const MachineInstr , bool *IsSwapped, +int64_t *ImmDelta) const { switch (OI.getOpcode()) { case X86::CMP64rr: case X86::CMP32rr: @@ -4140,10 +4140,21 @@ bool X86InstrInfo::isRedundantFlagInstr(const MachineInstr , int64_t OIMask; int64_t OIValue; if (analyzeCompare(OI, OISrcReg, OISrcReg2, OIMask, OIValue) && - SrcReg == OISrcReg && ImmMask == OIMask && OIValue == ImmValue) { -assert(SrcReg2 == X86::NoRegister && OISrcReg2 == X86::NoRegister && - "should not have 2nd register"); -return true; + SrcReg == OISrcReg && ImmMask == OIMask) { +if (OIValue == ImmValue) { + *ImmDelta = 0; + return true; +} else if (static_cast(ImmValue) == + static_cast(OIValue) - 1) { + *ImmDelta = -1; + return true; +} else if (static_cast(ImmValue) == + static_cast(OIValue) + 1) { + *ImmDelta = 1; + return true; +} else { + return false; +} } } return FlagI.isIdenticalTo(OI); @@ -4393,6 +4404,7 @@ bool X86InstrInfo::optimizeCompareInstr(MachineInstr , Register SrcReg, bool ShouldUpdateCC = false; bool IsSwapped = false; X86::CondCode NewCC = X86::COND_INVALID; + int64_t ImmDelta = 0; // Search backward from CmpInstr for the next instruction defining EFLAGS. const TargetRegisterInfo *TRI = (); @@ -4439,7 +4451,7 @@ bool X86InstrInfo::optimizeCompareInstr(MachineInstr , Register SrcReg, // ... // EFLAGS not changed // cmp x, y // <-- can be removed if (isRedundantFlagInstr(CmpInstr, SrcReg, SrcReg2, CmpMask, CmpValue, - Inst, )) { + Inst, , )) { Sub = break; } @@ -4473,7 +4485,7 @@ bool X86InstrInfo::optimizeCompareInstr(MachineInstr , Register SrcReg, // It is safe to remove CmpInstr if EFLAGS is redefined or killed. // If we are done with the basic block, we need to check whether EFLAGS is // live-out. - bool IsSafe = false; + bool FlagsMayLiveOut = true; SmallVector, 4> OpsToUpdate; MachineBasicBlock::iterator AfterCmpInstr = std::next(MachineBasicBlock::iterator(CmpInstr)); @@ -4483,7 +4495,7 @@ bool X86InstrInfo::optimizeCompareInstr(MachineInstr , Register SrcReg, // We should check the usage if this instruction uses and updates EFLAGS. if (!UseEFLAGS && ModifyEFLAGS) { // It is safe to remove CmpInstr if EFLAGS is
[llvm-branch-commits] [llvm] d72980a - Tests for D112754
Author: Matthias Braun Date: 2021-11-29T16:02:06-08:00 New Revision: d72980acfa54375eb3415af72cd67e85faaac168 URL: https://github.com/llvm/llvm-project/commit/d72980acfa54375eb3415af72cd67e85faaac168 DIFF: https://github.com/llvm/llvm-project/commit/d72980acfa54375eb3415af72cd67e85faaac168.diff LOG: Tests for D112754 Differential Revision: https://reviews.llvm.org/D113151 Added: llvm/test/CodeGen/X86/fold-masked-merge.ll Modified: Removed: diff --git a/llvm/test/CodeGen/X86/fold-masked-merge.ll b/llvm/test/CodeGen/X86/fold-masked-merge.ll new file mode 100644 index 0..e26ec40afb3c6 --- /dev/null +++ b/llvm/test/CodeGen/X86/fold-masked-merge.ll @@ -0,0 +1,287 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -o - %s -mtriple=x86_64-- | FileCheck %s --check-prefixes=CHECK,NOBMI +; RUN: llc -o - %s -mtriple=x86_64-- -mattr=+bmi | FileCheck %s --check-prefixes=CHECK,BMI +; +; test that masked-merge code is generated as "xor;and;xor" sequence or +; "andn ; and; or" if and-not is available. + +define i32 @masked_merge0(i32 %a0, i32 %a1, i32 %a2) { +; NOBMI-LABEL: masked_merge0: +; NOBMI: # %bb.0: +; NOBMI-NEXT:movl %edi, %eax +; NOBMI-NEXT:andl %edi, %esi +; NOBMI-NEXT:notl %eax +; NOBMI-NEXT:andl %edx, %eax +; NOBMI-NEXT:orl %esi, %eax +; NOBMI-NEXT:retq +; +; BMI-LABEL: masked_merge0: +; BMI: # %bb.0: +; BMI-NEXT:andl %edi, %esi +; BMI-NEXT:andnl %edx, %edi, %eax +; BMI-NEXT:orl %esi, %eax +; BMI-NEXT:retq + %and0 = and i32 %a0, %a1 + %not = xor i32 %a0, -1 + %and1 = and i32 %not, %a2 + %or = or i32 %and0, %and1 + ret i32 %or +} + +define i16 @masked_merge1(i16 %a0, i16 %a1, i16 %a2) { +; NOBMI-LABEL: masked_merge1: +; NOBMI: # %bb.0: +; NOBMI-NEXT:movl %edi, %eax +; NOBMI-NEXT:andl %edi, %esi +; NOBMI-NEXT:notl %eax +; NOBMI-NEXT:andl %edx, %eax +; NOBMI-NEXT:orl %esi, %eax +; NOBMI-NEXT:# kill: def $ax killed $ax killed $eax +; NOBMI-NEXT:retq +; +; BMI-LABEL: masked_merge1: +; BMI: # %bb.0: +; BMI-NEXT:andl %edi, %esi +; BMI-NEXT:andnl %edx, %edi, %eax +; BMI-NEXT:orl %esi, %eax +; BMI-NEXT:# kill: def $ax killed $ax killed $eax +; BMI-NEXT:retq + %and0 = and i16 %a0, %a1 + %not = xor i16 %a0, -1 + %and1 = and i16 %a2, %not + %or = or i16 %and0, %and1 + ret i16 %or +} + +define i8 @masked_merge2(i8 %a0, i8 %a1, i8 %a2) { +; CHECK-LABEL: masked_merge2: +; CHECK: # %bb.0: +; CHECK-NEXT:movl %edi, %eax +; CHECK-NEXT:notb %al +; CHECK-NEXT:andb %sil, %al +; CHECK-NEXT:andb %dil, %sil +; CHECK-NEXT:orb %sil, %al +; CHECK-NEXT:retq + %not = xor i8 %a0, -1 + %and0 = and i8 %not, %a1 + %and1 = and i8 %a1, %a0 + %or = or i8 %and0, %and1 + ret i8 %or +} + +define i64 @masked_merge3(i64 %a0, i64 %a1, i64 %a2) { +; NOBMI-LABEL: masked_merge3: +; NOBMI: # %bb.0: +; NOBMI-NEXT:movq %rdi, %rax +; NOBMI-NEXT:notq %rsi +; NOBMI-NEXT:notq %rdx +; NOBMI-NEXT:andq %rdi, %rsi +; NOBMI-NEXT:notq %rax +; NOBMI-NEXT:andq %rdx, %rax +; NOBMI-NEXT:orq %rsi, %rax +; NOBMI-NEXT:retq +; +; BMI-LABEL: masked_merge3: +; BMI: # %bb.0: +; BMI-NEXT:notq %rdx +; BMI-NEXT:andnq %rdx, %rdi, %rcx +; BMI-NEXT:andnq %rdi, %rsi, %rax +; BMI-NEXT:orq %rcx, %rax +; BMI-NEXT:retq + %v0 = xor i64 %a1, -1 + %v1 = xor i64 %a2, -1 + %not = xor i64 %a0, -1 + %and0 = and i64 %not, %v1 + %and1 = and i64 %v0, %a0 + %or = or i64 %and0, %and1 + ret i64 %or +} + +; not a masked merge: there is no `not` operation. +define i32 @not_a_masked_merge0(i32 %a0, i32 %a1, i32 %a2) { +; CHECK-LABEL: not_a_masked_merge0: +; CHECK: # %bb.0: +; CHECK-NEXT:movl %edi, %eax +; CHECK-NEXT:andl %edi, %esi +; CHECK-NEXT:negl %eax +; CHECK-NEXT:andl %edx, %eax +; CHECK-NEXT:orl %esi, %eax +; CHECK-NEXT:retq + %and0 = and i32 %a0, %a1 + %not_a_not = sub i32 0, %a0 + %and1 = and i32 %not_a_not, %a2 + %or = or i32 %and0, %and1 + ret i32 %or +} + +; not a masked merge: `not` operand does not match another `and`-operand. +define i32 @not_a_masked_merge1(i32 %a0, i32 %a1, i32 %a2, i32 %a3) { +; NOBMI-LABEL: not_a_masked_merge1: +; NOBMI: # %bb.0: +; NOBMI-NEXT:movl %ecx, %eax +; NOBMI-NEXT:andl %esi, %edi +; NOBMI-NEXT:notl %eax +; NOBMI-NEXT:andl %edx, %eax +; NOBMI-NEXT:orl %edi, %eax +; NOBMI-NEXT:retq +; +; BMI-LABEL: not_a_masked_merge1: +; BMI: # %bb.0: +; BMI-NEXT:andl %esi, %edi +; BMI-NEXT:andnl %edx, %ecx, %eax +; BMI-NEXT:orl %edi, %eax +; BMI-NEXT:retq + %and0 = and i32 %a0, %a1 + %not = xor i32 %a3, -1 + %and1 = and i32 %not, %a2 + %or = or i32 %and0, %and1 + ret i32 %or +} + +; not a masked merge: one of the operands of `or` is not an `and`. +define i32 @not_a_masked_merge2(i32 %a0, i32 %a1,
[llvm-branch-commits] [llvm] 4db1cf5 - X86InstrInfo: Optimize more combinations of SUB+CMP
Author: Matthias Braun Date: 2021-10-28T10:23:28-07:00 New Revision: 4db1cf53740a8770b51ac1c03e8e9cc5e66eb83d URL: https://github.com/llvm/llvm-project/commit/4db1cf53740a8770b51ac1c03e8e9cc5e66eb83d DIFF: https://github.com/llvm/llvm-project/commit/4db1cf53740a8770b51ac1c03e8e9cc5e66eb83d.diff LOG: X86InstrInfo: Optimize more combinations of SUB+CMP `X86InstrInfo::optimizeCompareInstr` would only optimize a `SUB` followed by a `CMP` in `isRedundantFlagInstr`. This extends the code to also look for other combinations like `CMP`+`CMP`, `TEST`+`TEST`, `SUB x,0`+`TEST`. - Change `isRedundantFlagInstr` to run `analyzeCompareInstr` on the candidate instruction and compare the results. This normalizes things and gives consistent results for various comparisons (`CMP x, y`, `SUB x, y`) and immediate cases (`TEST x, x`, `SUB x, 0`, `CMP x, 0`...). - Turn `isRedundantFlagInstr` into a member function so it can call `analyzeCompare`. - We now also check `isRedundantFlagInstr` even if `IsCmpZero` is true, since we now have cases like `TEST`+`TEST`. Differential Revision: https://reviews.llvm.org/D110865 Added: Modified: llvm/lib/Target/X86/X86InstrInfo.cpp llvm/lib/Target/X86/X86InstrInfo.h llvm/test/CodeGen/X86/2007-02-16-BranchFold.ll llvm/test/CodeGen/X86/optimize-compare.mir llvm/test/CodeGen/X86/postalloc-coalescing.ll Removed: diff --git a/llvm/lib/Target/X86/X86InstrInfo.cpp b/llvm/lib/Target/X86/X86InstrInfo.cpp index 96180e2b2bf2..81e7184fa07a 100644 --- a/llvm/lib/Target/X86/X86InstrInfo.cpp +++ b/llvm/lib/Target/X86/X86InstrInfo.cpp @@ -4011,42 +4011,72 @@ bool X86InstrInfo::analyzeCompare(const MachineInstr , Register , return false; } -/// Check whether the first instruction, whose only -/// purpose is to update flags, can be made redundant. -/// CMPrr can be made redundant by SUBrr if the operands are the same. -/// This function can be extended later on. -/// SrcReg, SrcRegs: register operands for FlagI. -/// ImmValue: immediate for FlagI if it takes an immediate. -inline static bool isRedundantFlagInstr(const MachineInstr , +bool X86InstrInfo::isRedundantFlagInstr(const MachineInstr , Register SrcReg, Register SrcReg2, int64_t ImmMask, int64_t ImmValue, -const MachineInstr ) { - if (((FlagI.getOpcode() == X86::CMP64rr && OI.getOpcode() == X86::SUB64rr) || - (FlagI.getOpcode() == X86::CMP32rr && OI.getOpcode() == X86::SUB32rr) || - (FlagI.getOpcode() == X86::CMP16rr && OI.getOpcode() == X86::SUB16rr) || - (FlagI.getOpcode() == X86::CMP8rr && OI.getOpcode() == X86::SUB8rr)) && - ((OI.getOperand(1).getReg() == SrcReg && -OI.getOperand(2).getReg() == SrcReg2) || - (OI.getOperand(1).getReg() == SrcReg2 && -OI.getOperand(2).getReg() == SrcReg))) -return true; - - if (ImmMask != 0 && - ((FlagI.getOpcode() == X86::CMP64ri32 && -OI.getOpcode() == X86::SUB64ri32) || - (FlagI.getOpcode() == X86::CMP64ri8 && -OI.getOpcode() == X86::SUB64ri8) || - (FlagI.getOpcode() == X86::CMP32ri && OI.getOpcode() == X86::SUB32ri) || - (FlagI.getOpcode() == X86::CMP32ri8 && -OI.getOpcode() == X86::SUB32ri8) || - (FlagI.getOpcode() == X86::CMP16ri && OI.getOpcode() == X86::SUB16ri) || - (FlagI.getOpcode() == X86::CMP16ri8 && -OI.getOpcode() == X86::SUB16ri8) || - (FlagI.getOpcode() == X86::CMP8ri && OI.getOpcode() == X86::SUB8ri)) && - OI.getOperand(1).getReg() == SrcReg && - OI.getOperand(2).getImm() == ImmValue) -return true; - return false; +const MachineInstr , +bool *IsSwapped) const { + switch (OI.getOpcode()) { + case X86::CMP64rr: + case X86::CMP32rr: + case X86::CMP16rr: + case X86::CMP8rr: + case X86::SUB64rr: + case X86::SUB32rr: + case X86::SUB16rr: + case X86::SUB8rr: { +Register OISrcReg; +Register OISrcReg2; +int64_t OIMask; +int64_t OIValue; +if (!analyzeCompare(OI, OISrcReg, OISrcReg2, OIMask, OIValue) || +OIMask != ImmMask || OIValue != ImmValue) + return false; +if (SrcReg == OISrcReg && SrcReg2 == OISrcReg2) { + *IsSwapped = false; + return true; +} +if (SrcReg == OISrcReg2 && SrcReg2 == OISrcReg) { + *IsSwapped = true; + return true; +} +return false; + } + case X86::CMP64ri32: + case X86::CMP64ri8: + case X86::CMP32ri: + case X86::CMP32ri8: + case X86::CMP16ri: + case X86::CMP16ri8: + case X86::CMP8ri: + case X86::SUB64ri32: + case X86::SUB64ri8: + case X86::SUB32ri: + case X86::SUB32ri8: + case X86::SUB16ri: + case X86::SUB16ri8: + case X86::SUB8ri: + case X86::TEST64rr: + case X86::TEST32rr: + case X86::TEST16rr: + case
[llvm-branch-commits] [llvm-branch] r294656 - ReleaseNotes.rst: Add a section about .mir testing
Author: matze Date: Thu Feb 9 17:25:27 2017 New Revision: 294656 URL: http://llvm.org/viewvc/llvm-project?rev=294656=rev Log: ReleaseNotes.rst: Add a section about .mir testing Modified: llvm/branches/release_40/docs/ReleaseNotes.rst Modified: llvm/branches/release_40/docs/ReleaseNotes.rst URL: http://llvm.org/viewvc/llvm-project/llvm/branches/release_40/docs/ReleaseNotes.rst?rev=294656=294655=294656=diff == --- llvm/branches/release_40/docs/ReleaseNotes.rst (original) +++ llvm/branches/release_40/docs/ReleaseNotes.rst Thu Feb 9 17:25:27 2017 @@ -75,6 +75,21 @@ Non-comprehensive list of changes in thi * Significant build-time and binary-size improvements when compiling with debug info (-g). +Code Generation Testing +--- + +Passes that work on the machine instruction representation can be tested with +the .mir serialization format. ``llc`` supports the ``-run-pass``, +``-stop-after``, ``-stop-before``, ``-start-after``, ``-start-before`` to to +run a single pass of the code generation pipeline, or to stop or start the code +generation pipeline at a given point. + +Additional information can be found in the :doc:`MIRLangRef`. The format is +used by the tests ending in ``.mir`` in the ``test/CodeGen`` directory. + +This feature is available since 2015. It is used more often lately and was not +mentioned in the release notes yet. + Intrusive list API overhaul --- ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm-branch] r294630 - RegisterCoalescer: Cleanup joinReservedPhysReg(); NFC
Author: matze Date: Thu Feb 9 15:45:29 2017 New Revision: 294630 URL: http://llvm.org/viewvc/llvm-project?rev=294630=rev Log: RegisterCoalescer: Cleanup joinReservedPhysReg(); NFC Merging r293856: - Factor out a common subexpression - Add some helpful comments - Fix printing of a register in a debug message Preparation for http://llvm.org/PR31889 Modified: llvm/branches/release_40/lib/CodeGen/RegisterCoalescer.cpp Modified: llvm/branches/release_40/lib/CodeGen/RegisterCoalescer.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/branches/release_40/lib/CodeGen/RegisterCoalescer.cpp?rev=294630=294629=294630=diff == --- llvm/branches/release_40/lib/CodeGen/RegisterCoalescer.cpp (original) +++ llvm/branches/release_40/lib/CodeGen/RegisterCoalescer.cpp Thu Feb 9 15:45:29 2017 @@ -1556,9 +1556,10 @@ bool RegisterCoalescer::joinCopy(Machine bool RegisterCoalescer::joinReservedPhysReg(CoalescerPair ) { unsigned DstReg = CP.getDstReg(); + unsigned SrcReg = CP.getSrcReg(); assert(CP.isPhys() && "Must be a physreg copy"); assert(MRI->isReserved(DstReg) && "Not a reserved register"); - LiveInterval = LIS->getInterval(CP.getSrcReg()); + LiveInterval = LIS->getInterval(SrcReg); DEBUG(dbgs() << "\t\tRHS = " << RHS << '\n'); assert(RHS.containsOneValue() && "Invalid join with reserved register"); @@ -1592,17 +1593,31 @@ bool RegisterCoalescer::joinReservedPhys // Delete the identity copy. MachineInstr *CopyMI; if (CP.isFlipped()) { -CopyMI = MRI->getVRegDef(RHS.reg); +// Physreg is copied into vreg +// %vregY = COPY %X +// ... //< no other def of %X here +// use %vregY +// => +// ... +// use %X +CopyMI = MRI->getVRegDef(SrcReg); } else { -if (!MRI->hasOneNonDBGUse(RHS.reg)) { +// VReg is copied into physreg: +// %vregX = def +// ... //< no other def or use of %Y here +// %Y = COPY %vregX +// => +// %Y = def +// ... +if (!MRI->hasOneNonDBGUse(SrcReg)) { DEBUG(dbgs() << "\t\tMultiple vreg uses!\n"); return false; } -MachineInstr *DestMI = MRI->getVRegDef(RHS.reg); -CopyMI = &*MRI->use_instr_nodbg_begin(RHS.reg); -const SlotIndex CopyRegIdx = LIS->getInstructionIndex(*CopyMI).getRegSlot(); -const SlotIndex DestRegIdx = LIS->getInstructionIndex(*DestMI).getRegSlot(); +MachineInstr = *MRI->getVRegDef(SrcReg); +CopyMI = &*MRI->use_instr_nodbg_begin(SrcReg); +SlotIndex CopyRegIdx = LIS->getInstructionIndex(*CopyMI).getRegSlot(); +SlotIndex DestRegIdx = LIS->getInstructionIndex(DestMI).getRegSlot(); if (!MRI->isConstantPhysReg(DstReg)) { // We checked above that there are no interfering defs of the physical @@ -1629,8 +1644,8 @@ bool RegisterCoalescer::joinReservedPhys // We're going to remove the copy which defines a physical reserved // register, so remove its valno, etc. -DEBUG(dbgs() << "\t\tRemoving phys reg def of " << DstReg << " at " - << CopyRegIdx << "\n"); +DEBUG(dbgs() << "\t\tRemoving phys reg def of " << PrintReg(DstReg, TRI) + << " at " << CopyRegIdx << "\n"); LIS->removePhysRegDefAt(DstReg, CopyRegIdx); // Create a new dead def at the new def location. ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm-branch] r294631 - RegisterCoalescer: Fix joinReservedPhysReg()
Author: matze Date: Thu Feb 9 15:45:33 2017 New Revision: 294631 URL: http://llvm.org/viewvc/llvm-project?rev=294631=rev Log: RegisterCoalescer: Fix joinReservedPhysReg() Merging r294268: joinReservedPhysReg() can only deal with a liverange in a single basic block when copying from a vreg into a physreg. See also rdar://30306405 Differential Revision: https://reviews.llvm.org/D29436 Fixes http://llvm.org/PR31889 Modified: llvm/branches/release_40/lib/CodeGen/RegisterCoalescer.cpp llvm/branches/release_40/test/CodeGen/AArch64/regcoal-physreg.mir Modified: llvm/branches/release_40/lib/CodeGen/RegisterCoalescer.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/branches/release_40/lib/CodeGen/RegisterCoalescer.cpp?rev=294631=294630=294631=diff == --- llvm/branches/release_40/lib/CodeGen/RegisterCoalescer.cpp (original) +++ llvm/branches/release_40/lib/CodeGen/RegisterCoalescer.cpp Thu Feb 9 15:45:33 2017 @@ -1614,6 +1614,11 @@ bool RegisterCoalescer::joinReservedPhys return false; } +if (!LIS->intervalIsInOneMBB(RHS)) { + DEBUG(dbgs() << "\t\tComplex control flow!\n"); + return false; +} + MachineInstr = *MRI->getVRegDef(SrcReg); CopyMI = &*MRI->use_instr_nodbg_begin(SrcReg); SlotIndex CopyRegIdx = LIS->getInstructionIndex(*CopyMI).getRegSlot(); Modified: llvm/branches/release_40/test/CodeGen/AArch64/regcoal-physreg.mir URL: http://llvm.org/viewvc/llvm-project/llvm/branches/release_40/test/CodeGen/AArch64/regcoal-physreg.mir?rev=294631=294630=294631=diff == --- llvm/branches/release_40/test/CodeGen/AArch64/regcoal-physreg.mir (original) +++ llvm/branches/release_40/test/CodeGen/AArch64/regcoal-physreg.mir Thu Feb 9 15:45:33 2017 @@ -1,19 +1,24 @@ # RUN: llc -mtriple=aarch64-apple-ios -run-pass=simple-register-coalescing %s -o - | FileCheck %s --- | - define void @func() { ret void } + define void @func0() { ret void } + define void @func1() { ret void } + define void @func2() { ret void } ... --- # Check coalescing of COPYs from reserved physregs. -# CHECK-LABEL: name: func -name: func +# CHECK-LABEL: name: func0 +name: func0 registers: - - { id: 0, class: gpr32 } - - { id: 1, class: gpr64 } - - { id: 2, class: gpr64 } - - { id: 3, class: gpr32 } - - { id: 4, class: gpr64 } - - { id: 5, class: gpr32 } - - { id: 6, class: xseqpairsclass } + - { id: 0, class: gpr32 } + - { id: 1, class: gpr64 } + - { id: 2, class: gpr64 } + - { id: 3, class: gpr32 } + - { id: 4, class: gpr64 } + - { id: 5, class: gpr32 } + - { id: 6, class: xseqpairsclass } + - { id: 7, class: gpr64 } + - { id: 8, class: gpr64sp } + - { id: 9, class: gpr64sp } body: | bb.0: ; We usually should not coalesce copies from allocatable physregs. @@ -60,8 +65,74 @@ body: | ; Only coalesce when the source register is reserved as a whole (this is ; a limitation of the current code which cannot update liveness information ; of the non-reserved part). -; CHECK: %6 = COPY %xzr_x0 +; CHECK: %6 = COPY %x28_fp ; CHECK: HINT 0, implicit %6 -%6 = COPY %xzr_x0 +%6 = COPY %x28_fp HINT 0, implicit %6 + +; This can be coalesced. +; CHECK: %fp = SUBXri %fp, 4, 0 +%8 = SUBXri %fp, 4, 0 +%fp = COPY %8 + +; Cannot coalesce when there are reads of the physreg. +; CHECK-NOT: %fp = SUBXri %fp, 8, 0 +; CHECK: %9 = SUBXri %fp, 8, 0 +; CHECK: STRXui %fp, %fp, 0 +; CHECK: %fp = COPY %9 +%9 = SUBXri %fp, 8, 0 +STRXui %fp, %fp, 0 +%fp = COPY %9 +... +--- +# Check coalescing of COPYs from reserved physregs. +# CHECK-LABEL: name: func1 +name: func1 +registers: + - { id: 0, class: gpr64sp } +body: | + bb.0: +successors: %bb.1, %bb.2 +; Cannot coalesce physreg because we have reads on other CFG paths (we +; currently abort for any control flow) +; CHECK-NOT: %fp = SUBXri +; CHECK: %0 = SUBXri %fp, 12, 0 +; CHECK: CBZX undef %x0, %bb.1 +; CHECK: B %bb.2 +%0 = SUBXri %fp, 12, 0 +CBZX undef %x0, %bb.1 +B %bb.2 + + bb.1: +%fp = COPY %0 +RET_ReallyLR + + bb.2: +STRXui %fp, %fp, 0 +RET_ReallyLR +... +--- +# CHECK-LABEL: name: func2 +name: func2 +registers: + - { id: 0, class: gpr64sp } +body: | + bb.0: +successors: %bb.1, %bb.2 +; We can coalesce copies from physreg to vreg across multiple blocks. +; CHECK-NOT: COPY +; CHECK: CBZX undef %x0, %bb.1 +; CHECK-NEXT: B %bb.2 +%0 = COPY %fp +CBZX undef %x0, %bb.1 +B %bb.2 + + bb.1: +; CHECK: STRXui undef %x0, %fp, 0 +; CHECK-NEXT: RET_ReallyLR +STRXui undef %x0, %0, 0 +RET_ReallyLR + + bb.2: +RET_ReallyLR ... ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
[llvm-branch-commits] [llvm-branch] r282615 - Cherry pick r281957 (see http://llvm.org/PR30463)
Author: matze Date: Wed Sep 28 13:17:12 2016 New Revision: 282615 URL: http://llvm.org/viewvc/llvm-project?rev=282615=rev Log: Cherry pick r281957 (see http://llvm.org/PR30463) Added: llvm/branches/release_39/test/CodeGen/X86/branchfolding-undef.mir - copied unchanged from r281957, llvm/trunk/test/CodeGen/X86/branchfolding-undef.mir Modified: llvm/branches/release_39/ (props changed) llvm/branches/release_39/lib/CodeGen/BranchFolding.cpp Propchange: llvm/branches/release_39/ -- --- svn:mergeinfo (original) +++ svn:mergeinfo Wed Sep 28 13:17:12 2016 @@ -1,3 +1,3 @@ /llvm/branches/Apple/Pertwee:110850,110961 /llvm/branches/type-system-rewrite:133420-134817 -/llvm/trunk:155241,275868-275870,275879,275898,275928,275935,275946,275978,275981,276015,276051,276077,276109,276119,276181,276209,276236-276237,276358,276364,276368,276389,276435,276438,276479,276510,276648,276676,276712,276740,276823,276956,276980,277093,277114,277135,277371,277399,277500,277504,277625,277691,277693,23,278002,278086,278133,278157,278343,278370,278413,278558-278559,278562,278569,278571,278573,278575,278584,278841,278900,278938,278999,279125,279268,279369,279647 +/llvm/trunk:155241,275868-275870,275879,275898,275928,275935,275946,275978,275981,276015,276051,276077,276109,276119,276181,276209,276236-276237,276358,276364,276368,276389,276435,276438,276479,276510,276648,276676,276712,276740,276823,276956,276980,277093,277114,277135,277371,277399,277500,277504,277625,277691,277693,23,278002,278086,278133,278157,278343,278370,278413,278558-278559,278562,278569,278571,278573,278575,278584,278841,278900,278938,278999,279125,279268,279369,279647,281957 Modified: llvm/branches/release_39/lib/CodeGen/BranchFolding.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/branches/release_39/lib/CodeGen/BranchFolding.cpp?rev=282615=282614=282615=diff == --- llvm/branches/release_39/lib/CodeGen/BranchFolding.cpp (original) +++ llvm/branches/release_39/lib/CodeGen/BranchFolding.cpp Wed Sep 28 13:17:12 2016 @@ -776,9 +776,8 @@ bool BranchFolder::CreateCommonTailOnlyB } static void -mergeMMOsFromMemoryOperations(MachineBasicBlock::iterator MBBIStartPos, - MachineBasicBlock ) { - // Merge MMOs from memory operations in the common block. +mergeOperations(MachineBasicBlock::iterator MBBIStartPos, +MachineBasicBlock ) { MachineBasicBlock *MBB = MBBIStartPos->getParent(); // Note CommonTailLen does not necessarily matches the size of // the common BB nor all its instructions because of debug @@ -808,8 +807,18 @@ mergeMMOsFromMemoryOperations(MachineBas "Reached BB end within common tail length!"); assert(MBBICommon->isIdenticalTo(*MBBI) && "Expected matching MIIs!"); +// Merge MMOs from memory operations in the common block. if (MBBICommon->mayLoad() || MBBICommon->mayStore()) MBBICommon->setMemRefs(MBBICommon->mergeMemRefsWith(*MBBI)); +// Drop undef flags if they aren't present in all merged instructions. +for (unsigned I = 0, E = MBBICommon->getNumOperands(); I != E; ++I) { + MachineOperand = MBBICommon->getOperand(I); + if (MO.isReg() && MO.isUndef()) { +const MachineOperand = MBBI->getOperand(I); +if (!OtherMO.isUndef()) + MO.setIsUndef(false); + } +} ++MBBI; ++MBBICommon; @@ -928,8 +937,8 @@ bool BranchFolder::TryTailMergeBlocks(Ma continue; DEBUG(dbgs() << "BB#" << SameTails[i].getBlock()->getNumber() << (i == e-1 ? "" : ", ")); - // Merge MMOs from memory operations as needed. - mergeMMOsFromMemoryOperations(SameTails[i].getTailStartPos(), *MBB); + // Merge operations (MMOs, undef flags) + mergeOperations(SameTails[i].getTailStartPos(), *MBB); // Hack the end off BB i, making it jump to BB commonTailIndex instead. ReplaceTailWithBranchTo(SameTails[i].getTailStartPos(), MBB); // BB i is no longer a predecessor of SuccBB; remove it from the worklist. ___ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits