aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Utils/LoopUnrollAndJam.cpp
AgeCommit message (Collapse)AuthorFilesLines
2025-03-22[llvm] Use *Set::insert_range (NFC) (#132591)Kazu Hirata1-2/+2
DenseSet, SmallPtrSet, SmallSet, SetVector, and StringSet recently gained C++23-style insert_range. This patch uses insert_range with iterator ranges. For each case, I've verified that foos is defined as make_range(foo_begin(), foo_end()) or in a similar manner.
2025-03-19[Transforms] Use *Set::insert_range (NFC) (#132056)Kazu Hirata1-3/+3
DenseSet, SmallPtrSet, SmallSet, SetVector, and StringSet recently gained C++23-style insert_range. This patch replaces: Dest.insert(Src.begin(), Src.end()); with: Dest.insert_range(Src); This patch does not touch custom begin like succ_begin for now.
2025-03-12[Utils] Avoid repeated hash lookups (NFC) (#130892)Kazu Hirata1-2/+3
2025-02-14[Utils] Avoid repeated hash lookups (NFC) (#127171)Kazu Hirata1-2/+3
2025-02-11[DependenceAnalysis][NFC] Removing PossiblyLoopIndependent parameter (#124615)Alireza Torabian1-1/+1
Parameter PossiblyLoopIndependent has lost its intended purpose. This flag is always set to true in all cases when depends() is called, hence we want to reconsider the utility of this variable and remove it from the function signature entirely. This is an NFC patch.
2025-01-27[NFC][DebugInfo] Switch more call-sites to using iterator-insertion (#124283)Jeremy Morse1-2/+3
To finalise the "RemoveDIs" work removing debug intrinsics, we're updating call sites that insert instructions to use iterators instead. This set of changes are those where it's not immediately obvious that just calling getIterator to fetch an iterator is correct, and one or two places where more than one line needs to change. Overall the same rule holds though: iterators generated for the start of a block such as getFirstNonPHIIt need to be passed into insert/move methods without being unwrapped/rewrapped, everything else can use getIterator.
2024-12-02[TTI] Add SCEVExpansionBudget to loop unrolling options. (#118316)Florian Hahn1-1/+3
Add an extra know to UnrollingPreferences to let backends control the maximum budget for SCEV expansions. This gives backends more fine-grained control on the cost of the runtime checks for runtime unrolling. PR: https://github.com/llvm/llvm-project/pull/118316
2024-09-07[Transforms] Avoid repeated hash looksup (NFC) (#107727)Kazu Hirata1-3/+1
2024-03-04[RemoveDIs] Reapply 3fda50d3915, insert instructions using iteratorsJeremy Morse1-3/+3
I'd reverted this in 6c7805d5d1 after a bad stage. Original commit messsage follows: [NFC][RemoveDIs] Bulk update utilities to insert with iterators As part of the RemoveDIs project we need LLVM to insert instructions using iterators wherever possible, so that the iterators can carry a bit of debug-info. This commit implements some of that by updating the contents of llvm/lib/Transforms/Utils to always use iterator-versions of instruction constructors. There are two general flavours of update: * Almost all call-sites just call getIterator on an instruction * Several make use of an existing iterator (scenarios where the code is actually significant for debug-info) The underlying logic is that any call to getFirstInsertionPt or similar APIs that identify the start of a block need to have that iterator passed directly to the insertion function, without being converted to a bare Instruction pointer along the way. I've also switched DemotePHIToStack to take an optional iterator: it needs to take an iterator, and having a no-insert-location behaviour appears to be important. The constructors for ICmpInst and FCmpInst have been updated too. They're the only instructions that take block _references_ rather than pointers for certain calls, and a future patch is going to make use of default-null block insertion locations. All of this should be NFC.
2024-02-29Revert "[NFC][RemoveDIs] Bulk update utilities to insert with iterators"Jeremy Morse1-3/+3
This reverts commit 3fda50d3915b2163a54a37b602be7783a89dd808. Apparently I've missed a hunk while staging this; will back out for now. Picked up here: https://lab.llvm.org/buildbot/#/builders/139/builds/60429/steps/6/logs/stdio
2024-02-29[NFC][RemoveDIs] Bulk update utilities to insert with iteratorsJeremy Morse1-3/+3
As part of the RemoveDIs project we need LLVM to insert instructions using iterators wherever possible, so that the iterators can carry a bit of debug-info. This commit implements some of that by updating the contents of llvm/lib/Transforms/Utils to always use iterator-versions of instruction constructors. There are two general flavours of update: * Almost all call-sites just call getIterator on an instruction * Several make use of an existing iterator (scenarios where the code is actually significant for debug-info) The underlying logic is that any call to getFirstInsertionPt or similar APIs that identify the start of a block need to have that iterator passed directly to the insertion function, without being converted to a bare Instruction pointer along the way. I've also switched DemotePHIToStack to take an optional iterator: it needs to take an iterator, and having a no-insert-location behaviour appears to be important. The constructors for ICmpInst and FCmpInst have been updated too. They're the only instructions that take block _references_ rather than pointers for certain calls, and a future patch is going to make use of default-null block insertion locations. All of this should be NFC.
2024-02-26[RemoveDIs] Use iterators for moving PHIs in loop-unroll-and-jam (#83003)Jeremy Morse1-2/+2
With no debug intrinsics, correctly identifying the start of a block with iterators becomes important. We need to use the iterator-returning methods here in loop-unroll-and-jam where we're shifting PHIs around. Otherwise they can be inserted after debug-info records, leading to debug-info attached to PHIs, which is ill formed. Fixes #83000
2023-10-22[llvm] Stop including llvm/ADT/iterator_range.h (NFC)Kazu Hirata1-1/+0
Identified with misc-include-cleaner.
2023-05-10[PseudoProbe] Clean up dwarf discriminator and avoid duplicating factor.Hongtao Yu1-1/+1
A pseudo probe is created with dwarf line information shared with its nearest instruction. If the instruction comes with a dwarf discriminator, it will be shared with the probe as well. This can confuse the later FS-AFDO discriminator assignment pass. To fix this, I'm cleaning up the discriminator fields for probes when they are inserted. I also notice another possibility to change the discriminator field of pseudo probes in the pipeline before the FS discriminator assignment pass. That is the loop unroller, which assigns duplication factor to instruction being vectorized. I'm disabling that for pseudo probe intrinsics specifically, also for callsites with probes. Reviewed By: wenlei Differential Revision: https://reviews.llvm.org/D148569
2023-03-14[Transforms] Use *{Set,Map}::contains (NFC)Kazu Hirata1-2/+2
2023-01-05[LoopUnrollAndJam] Visit phi operand dependencies in post-orderJoshua Cao1-22/+17
Fixes https://github.com/llvm/llvm-project/issues/58565 The previous implementation visits operands in pre-order, but this does not guarantee an instruction is visited before its uses. This can cause instructions to be copied in the incorrect order. For example: ``` a = ... b = add a, 1 c = add a, b d = add b, a ``` Pre-order visits does not guarantee the order in which `a` and `b` are visited. LoopUnrollAndJam may incorrectly insert `b` before `a`. This patch implements post-order visits. By visiting dependencies first, we guarantee that an instruction's dependencies are visited first. Differential Revision: https://reviews.llvm.org/D140255
2023-01-04[LoopUnrollAndJam] Forget scalar evolution dispositions. Do no explicitly ↵Joshua Cao1-1/+1
forget subloop. Fixes https://github.com/llvm/llvm-project/issues/58454 Scalar evolution dispositions need to be forgotten to pass verification. We do not need to forget the subloop since it is automatically forgotten when forgetting the parent loop. Differential Revision: https://reviews.llvm.org/D140953
2022-12-21[NFC] Rename Function::isDebugInfoForProfiling to shouldEmit[...]Mircea Trofin1-1/+2
The function name was misleading - the expectation set both by the name and by other members of Function (like isDeclaration or isIntrinsic) would be that the function somehow would "be" "debug info for profiling". But that's not the case - the property indicates (as the comment over the declaration also explains) whether debug info should be emitted (for profiling).
2022-12-15[NFC] Rename Function::insertBasicBlockAt() to Function::insert().Vasileios Porpodas1-1/+1
I think this is a better name because it is what STL uses. Differential Revision: https://reviews.llvm.org/D140068
2022-12-12[IR][NFC] Adds Function::insertBasicBlockAt() to replace things like ↵Vasileios Porpodas1-1/+1
F->getBasicBlockList().insert() This is part of a series of patches that aim at making Function::getBasicBlockList() private. Differential Revision: https://reviews.llvm.org/D139906
2022-12-05Remove unused #include "llvm/ADT/Optional.h"Fangrui Song1-1/+0
2022-11-23[NFC] Replaced BB->getInstList().{erase(),pop_front(),pop_back()} with ↵Vasileios Porpodas1-1/+1
eraseFromParent(). Differential Revision: https://reviews.llvm.org/D138617
2022-06-20[llvm] Don't use Optional::getValue (NFC)Kazu Hirata1-1/+1
2022-05-26[iwyu] Handle regressions in libLLVM header includeserge-sans-paille1-1/+0
Running iwyu-diff on LLVM codebase since 7030654296a0416bd9402a0278 detected a few regressions, fixing them. Differential Revision: https://reviews.llvm.org/D126417
2022-03-01Cleanup includes: TransformsUtilsserge-sans-paille1-1/+0
Estimation on the impact on preprocessor output: before: 1065307662 after: 1064800684 Discourse thread: https://discourse.llvm.org/t/include-what-you-use-include-cleanup Differential Revision: https://reviews.llvm.org/D120741
2021-06-19[LoopUnroll] Push runtime unrolling decision up into tryToUnrollLoop()Nikita Popov1-1/+1
Currently, UnrollLoop() is passed an AllowRuntime flag and decides itself whether runtime unrolling should be used or not. This patch pushes the decision into the caller and allows us to eliminate the ULO.TripCount and ULO.TripMultiple parameters. Differential Revision: https://reviews.llvm.org/D104487
2021-05-25Revert "[LoopUnrollAndJam] Change LoopUnrollAndJamPass to LoopNest pass"maekawatoshiki1-10/+7
This reverts commit d65c32fb41b03a35a2a16330ba1ea15cf6818f04.
2021-05-23[LoopUnrollAndJam] Change LoopUnrollAndJamPass to LoopNest passmaekawatoshiki1-7/+10
This patch changes LoopUnrollAndJamPass from FunctionPass to LoopNest pass. The next patch will utilize LoopNest to effectively handle loop nests. Reviewed By: Whitney Differential Revision: https://reviews.llvm.org/D99149
2021-05-18[SampleFDO] New hierarchical discriminator for Flow Sensitive SampleFDORong Xu1-1/+3
This patch implements first part of Flow Sensitive SampleFDO (FSAFDO). It has the following changes: (1) disable current discriminator encoding scheme, (2) new hierarchical discriminator for FSAFDO. For this patch, option "-enable-fs-discriminator=true" turns on the new functionality. Option "-enable-fs-discriminator=false" (the default) keeps the current SampleFDO behavior. When the fs-discriminator is enabled, we insert a flag variable, namely, llvm_fs_discriminator, to the object. This symbol will checked by create_llvm_prof tool, and used to generate a profile with FS-AFDO discriminators enabled. If this happens, for an extbinary format profile, create_llvm_prof tool will add a flag to profile summary section. Differential Revision: https://reviews.llvm.org/D102246
2021-04-15[LoopUnrollAndJam] Avoid repeated instructions for UAJ analysisDanilo C. Grael1-1/+4
Avoid visiting repeated instructions for processHeaderPhiOperands as it can cause a scenario of endless loop. Test case is attached and can be ran with `opt -basic-aa -tbaa -loop-unroll-and-jam -allow-unroll-and-jam -unroll-and-jam-count=4`. Reviewed By: dmgreen Differential Revision: https://reviews.llvm.org/D97407
2021-04-06Add a subclass of IntrinsicInst for llvm.assume [nfc]Philip Reames1-3/+2
Add the subclass, update a few places which check for the intrinsic to use idiomatic dyn_cast, and update the public interface of AssumptionCache to use the new class. A follow up change will do the same for the newer assumption query/bundle mechanisms.
2021-02-05LoopUnrollAndJam] Only allow loops with single exit(ing) blocksSidharth Baveja1-0/+17
Summary: This resolves an issue posted on Bugzilla. https://bugs.llvm.org/show_bug.cgi?id=48764 In this issue, the loop had multiple exit blocks, which resulted in the function getExitBlock to return a nullptr, which resulted in hitting the assert. This patch ensures that loops which only have one exit block as allowed to be unrolled and jammed. Reviewed By: Whitney, Meinersbur, dmgreen Differential Revision: https://reviews.llvm.org/D95806
2021-01-23[llvm] Use pop_back_val (NFC)Kazu Hirata1-2/+1
2020-08-11[NFC][LoopUnrollAndJam] Use BasicBlock::replacePhiUsesWith instead ofWhitney Tsang1-20/+12
static function updatePHIBlocks. Reviewed By: dmgreen Differential Revision: https://reviews.llvm.org/D85673
2020-05-28Create utility function to Merge Adjacent Basic BlocksSidharth Baveja1-16/+3
Summary: The following code from /llvm/lib/Transforms/Utils/LoopUnrollAndJam.cpp can be used by other transformations: while (!MergeBlocks.empty()) { BasicBlock *BB = *MergeBlocks.begin(); BranchInst *Term = dyn_cast<BranchInst>(BB->getTerminator()); if (Term && Term->isUnconditional() && L->contains(Term->getSuccessor(0))) { BasicBlock *Dest = Term->getSuccessor(0); BasicBlock *Fold = Dest->getUniquePredecessor(); if (MergeBlockIntoPredecessor(Dest, &DTU, LI)) { // Don't remove BB and add Fold as they are the same BB assert(Fold == BB); (void)Fold; MergeBlocks.erase(Dest); } else MergeBlocks.erase(BB); } else MergeBlocks.erase(BB); } Hence it should be separated into its own utility function. Authored By: sidbav Reviewer: Whitney, Meinersbur, asbirlea, dmgreen, etiotto Reviewed By: asbirlea Subscribers: hiraditya, zzheng, llvm-commits Tag: LLVM Differential Revision: https://reviews.llvm.org/D80583
2020-05-27[UnJ] Update LI for inner nested loopsDavid Green1-6/+6
This makes sure to correctly register the loop info of the children of unroll and jammed loops. It re-uses some code from the unroller for registering subloops. Differential Revision: https://reviews.llvm.org/D80619
2020-05-06[LoopUnrollAndJam] Changed safety checks to consider more than 2-levelsWhitney Tsang1-125/+278
loop nest. Summary: As discussed in https://reviews.llvm.org/D73129. Example Before unroll and jam: for A for B for C D E After unroll and jam (currently): for A A' for B for C D B' for C' D' E E' After unroll and jam (Ideal): for A A' for B B' for C C' D D' E E' This is the first patch to change unroll and jam to work in the ideal way. This patch change the safety checks needed to make sure is safe to unroll and jam in the ideal way. Reviewer: dmgreen, jdoerfert, Meinersbur, kbarton, bmahjour, etiotto Reviewed By: Meinersbur Subscribers: fhahn, hiraditya, zzheng, llvm-commits, anhtuyen, prithayan Tag: LLVM Differential Revision: https://reviews.llvm.org/D76132
2020-02-25[NFC][SCEV] Piping to pass TTI into SCEVExpander::isHighCostExpansionHelper()Roman Lebedev1-7/+10
Summary: Future patches will make use of TTI to perform cost-model-driven `SCEVExpander::isHighCostExpansionHelper()` This is a fully NFC patch to make things reviewable. Reviewers: reames, mkazantsev, wmi, sanjoy Reviewed By: mkazantsev Subscribers: hiraditya, zzheng, javed.absar, dmgreen, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D73704
2020-02-12[NFC] Remove extra headers included in Loop Unroll and LoopUnrollAndJam filesAnh Tuyen Tran1-8/+30
Summary: This refactor patch removes some header files which are not needed and also add some to meet IWYU principles. Reviewers: rnk (Reid Kleckner), Meinersbur (Michael Kruse), dmgreen (Dave Green) Reviewed By: dmgreen (Dave Green), rnk (Reid Kleckner), Meinersbur (Michael Kruse) Subscribers: dmgreen (Dave Green), Whitney (Whitney Tsang), hiraditya (Aditya Kumar), zzheng (Z. Zheng), llvm-commits, LLVM Tag: LLVM Differential Revision: https://reviews.llvm.org/D73498
2020-01-28[NFCI][LoopUnrollAndJam] Minor changes.Whitney Tsang1-17/+23
Summary: 1. Add assertions. 2. Verify more analyses. These changes are moved out of https://reviews.llvm.org/D73129 to simplify that review. Reviewer: dmgreen, jdoerfert, Meinersbur, kbarton, bmahjour, etiotto Reviewed By: dmgreen Subscribers: fhahn, hiraditya, zzheng, llvm-commits, prithayan, anhtuyen Tag: LLVM Differential Revision: https://reviews.llvm.org/D73204
2020-01-27[LoopUnroll] Remove remapInstruction().Whitney Tsang1-2/+2
Summary: LoopUnroll can reuse the RemapInstruction() in ValueMapper, or remapInstructionsInBlocks() in CloneFunction, depending on the needs. There is no need to have its own version in LoopUnroll. By calling RemapInstruction() without TypeMapper or Materializer and with Flags (RF_NoModuleLevelChanges | RF_IgnoreMissingLocals), it does the same as remapInstruction(). remapInstructionsInBlocks() calls RemapInstruction() exactly as described. Looking at the history, I cannot find any obvious reason to have its own version. Reviewer: dmgreen, jdoerfert, Meinersbur, kbarton, bmahjour, etiotto, foad, aprantl Reviewed By: jdoerfert Subscribers: hiraditya, zzheng, llvm-commits, prithayan, anhtuyen Tag: LLVM Differential Revision: https://reviews.llvm.org/D73277
2020-01-04[SCEV] Remove unused ScalarEvolutionExpander.h includes (NFC).Florian Hahn1-1/+0
2019-11-03[LoopUnrollAndJam] Fixed null check after dereferencing warning. NFCI.Dávid Bolvanský1-1/+3
2019-08-29[LoopUnrollAndJam] Use Lazy strategy for DTU.Florian Hahn1-2/+4
We can also apply the earlier updates to the lazy DTU, instead of applying them directly. Reviewers: kuhar, brzycki, asbirlea, SjoerdMeijer Reviewed By: brzycki, asbirlea, SjoerdMeijer Differential Revision: https://reviews.llvm.org/D66918 llvm-svn: 370391
2019-06-04[Utils] Clean another duplicated util method.Alina Sbirlea1-1/+3
Summary: Following the cleanup in D48202, method foldBlockIntoPredecessor has the same behavior. Replace its uses with MergeBlockIntoPredecessor. Remove foldBlockIntoPredecessor. Reviewers: chandlerc, dmgreen Subscribers: jlebar, javed.absar, zzheng, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D62751 llvm-svn: 362538
2019-04-12[SCEV] Add option to forget everything in SCEV.Alina Sbirlea1-2/+2
Summary: Create a method to forget everything in SCEV. Add a cl::opt and PassManagerBuilder option to use this in LoopUnroll. Motivation: Certain Halide applications spend a very long time compiling in forgetLoop, and prefer to forget everything and rebuild SCEV from scratch. Sample difference in compile time reduction: 21.04 to 14.78 using current ToT release build. Testcase showcasing this cannot be opensourced and is fairly large. The option disabled by default, but it may be desirable to enable by default. Evidence in favor (two difference runs on different days/ToT state): File Before (s) After (s) clang-9.bc 7267.91 6639.14 llvm-as.bc 194.12 194.12 llvm-dis.bc 62.50 62.50 opt.bc 1855.85 1857.53 File Before (s) After (s) clang-9.bc 8588.70 7812.83 llvm-as.bc 196.20 194.78 llvm-dis.bc 61.55 61.97 opt.bc 1739.78 1886.26 Reviewers: sanjoy Subscribers: mehdi_amini, jlebar, zzheng, javed.absar, dmgreen, jdoerfert, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D60144 llvm-svn: 358304
2019-01-24[llvm] Clarify responsiblity of some of DILocation discriminator APIsMircea Trofin1-1/+1
Summary: Renamed setBaseDiscriminator to cloneWithBaseDiscriminator, to match similar APIs. Also changed its behavior to copy over the other discriminator components, instead of eliding them. Renamed cloneWithDuplicationFactor to cloneByMultiplyingDuplicationFactor, which more closely matches what this API does. Reviewers: dblaikie, wmi Reviewed By: dblaikie Subscribers: zzheng, llvm-commits Differential Revision: https://reviews.llvm.org/D56220 llvm-svn: 351996
2019-01-19Update the file headers across all of the LLVM projects in the monorepoChandler Carruth1-4/+3
to reflect the new license. We understand that people may be surprised that we're moving the header entirely to discuss the new license. We checked this carefully with the Foundation's lawyer and we believe this is the correct approach. Essentially, all code in the project is now made available by the LLVM project under our new license, so you will see that the license headers include that license only. Some of our contributors have contributed code under our old license, and accordingly, we have retained a copy of our old license notice in the top-level files in each project and repository. llvm-svn: 351636
2018-12-21[llvm] API for encoding/decoding DWARF discriminators.Mircea Trofin1-2/+9
Summary: Added a pair of APIs for encoding/decoding the 3 components of a DWARF discriminator described in http://lists.llvm.org/pipermail/llvm-dev/2016-October/106532.html: the base discriminator, the duplication factor (useful in profile-guided optimization) and the copy index (used to identify copies of code in cases like loop unrolling) The encoding packs 3 unsigned values in 32 bits. This CL addresses 2 issues: - communicates overflow back to the user - supports encoding all 3 components together. Current APIs assume a sequencing of events. For example, creating a new discriminator based on an existing one by changing the base discriminator was not supported. Reviewers: davidxl, danielcdh, wmi, dblaikie Reviewed By: dblaikie Subscribers: zzheng, dmgreen, aprantl, JDevlieghere, llvm-commits Differential Revision: https://reviews.llvm.org/D55681 llvm-svn: 349973
2018-12-12[Unroll/UnrollAndJam/Vectorizer/Distribute] Add followup loop attributes.Michael Kruse1-6/+9
When multiple loop transformation are defined in a loop's metadata, their order of execution is defined by the order of their respective passes in the pass pipeline. For instance, e.g. #pragma clang loop unroll_and_jam(enable) #pragma clang loop distribute(enable) is the same as #pragma clang loop distribute(enable) #pragma clang loop unroll_and_jam(enable) and will try to loop-distribute before Unroll-And-Jam because the LoopDistribute pass is scheduled after UnrollAndJam pass. UnrollAndJamPass only supports one inner loop, i.e. it will necessarily fail after loop distribution. It is not possible to specify another execution order. Also,t the order of passes in the pipeline is subject to change between versions of LLVM, optimization options and which pass manager is used. This patch adds 'followup' attributes to various loop transformation passes. These attributes define which attributes the resulting loop of a transformation should have. For instance, !0 = !{!0, !1, !2} !1 = !{!"llvm.loop.unroll_and_jam.enable"} !2 = !{!"llvm.loop.unroll_and_jam.followup_inner", !3} !3 = !{!"llvm.loop.distribute.enable"} defines a loop ID (!0) to be unrolled-and-jammed (!1) and then the attribute !3 to be added to the jammed inner loop, which contains the instruction to distribute the inner loop. Currently, in both pass managers, pass execution is in a fixed order and UnrollAndJamPass will not execute again after LoopDistribute. We hope to fix this in the future by allowing pass managers to run passes until a fixpoint is reached, use Polly to perform these transformations, or add a loop transformation pass which takes the order issue into account. For mandatory/forced transformations (e.g. by having been declared by #pragma omp simd), the user must be notified when a transformation could not be performed. It is not possible that the responsible pass emits such a warning because the transformation might be 'hidden' in a followup attribute when it is executed, or it is not present in the pipeline at all. For this reason, this patche introduces a WarnMissedTransformations pass, to warn about orphaned transformations. Since this changes the user-visible diagnostic message when a transformation is applied, two test cases in the clang repository need to be updated. To ensure that no other transformation is executed before the intended one, the attribute `llvm.loop.disable_nonforced` can be added which should disable transformation heuristics before the intended transformation is applied. E.g. it would be surprising if a loop is distributed before a #pragma unroll_and_jam is applied. With more supported code transformations (loop fusion, interchange, stripmining, offloading, etc.), transformations can be used as building blocks for more complex transformations (e.g. stripmining+stripmining+interchange -> tiling). Reviewed By: hfinkel, dmgreen Differential Revision: https://reviews.llvm.org/D49281 Differential Revision: https://reviews.llvm.org/D55288 llvm-svn: 348944