llvm-project/llvm/lib/Analysis
Hans Wennborg 2bc57d85eb Don't override __attribute__((no_stack_protector)) by inlining (PR52886)
Since 26c6a3e736, LLVM's inliner will "upgrade" the caller's stack protector
attribute based on the callee. This lead to surprising results with Clang's
no_stack_protector attribute added in 4fbf84c173 (D46300). Consider the
following code compiled with clang -fstack-protector-strong -Os
(https://godbolt.org/z/7s3rW7a1q).

  extern void h(int* p);

  inline __attribute__((always_inline)) int g() {
    return 0;
  }

  int __attribute__((__no_stack_protector__)) f() {
    int a[1];
    h(a);
    return g();
  }

LLVM will inline g() into f(), and f() would get a stack protector, against the
users explicit wishes, potentially breaking the program e.g. if h() changes the
value of the stack cookie. That's a miscompile.

More recently, bc044a88ee (D91816) addressed this problem by preventing
inlining when the stack protector is disabled in the caller and enabled in the
callee or vice versa. However, the problem remained if the callee is marked
always_inline as in the example above. This affected users, see e.g.
http://crbug.com/1274129 and http://llvm.org/pr52886.

One way to fix this would be to prevent inlining also in the always_inline
case. Despite the name, always_inline does not guarantee inlining, so this
would be legal but potentially surprising to users.

However, I think the better fix is to not enable the stack protector in a
caller based on the callee. The motivation for the old behaviour is unclear, it
seems counter-intuitive, and causes real problems as we've seen.

This commit implements that fix, which means in the example above, g() gets
inlined into f() (also without always_inline), and f() is emitted without stack
protector. I think that matches most developers' expectations, and that's also
what GCC does.

Another effect of this change is that a no_stack_protector function can now be
inlined into a stack protected function, e.g. (https://godbolt.org/z/hafP6W856):

  extern void h(int* p);

  inline int __attribute__((__no_stack_protector__)) __attribute__((always_inline)) g() {
    return 0;
  }

  int f() {
    int a[1];
    h(a);
    return g();
  }

I think that's fine. Such code would be unusual since no_stack_protector is
normally applied to a program entry point which sets up the stack canary. And
even if such code exists, inlining doesn't change the semantics: there is still
no stack cookie setup/check around entry/exit of the g() code region, but there
may be in the surrounding context, as there was before inlining. This also
matches GCC.

See also the discussion at https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94722

Differential revision: https://reviews.llvm.org/D116589
2022-01-13 12:04:49 +01:00
..
models [NFC][mlgo]Make the test model generator inlining-specific 2021-12-22 13:38:45 -08:00
AliasAnalysis.cpp Rename doesNotReadMemory to onlyWritesMemory globally [NFC] 2022-01-05 08:52:55 -08:00
AliasAnalysisEvaluator.cpp [AA] Updates for D95543. 2021-04-15 12:22:03 +03:00
AliasAnalysisSummary.cpp
AliasAnalysisSummary.h
AliasSetTracker.cpp [NFC][AA] Prepare to convert AliasResult to class with PartialAlias offset. 2021-04-09 12:54:22 +03:00
Analysis.cpp Reapply CycleInfo: Introduce cycles as a generalization of loops 2021-12-10 14:36:43 +05:30
AssumeBundleQueries.cpp Make various assume bundle data structures use uint64_t 2021-10-13 10:38:41 -07:00
AssumptionCache.cpp [InferAddressSpaces] Support assumed addrspaces from addrspace predicates. 2021-11-08 16:51:57 -05:00
BasicAliasAnalysis.cpp Rename doesNotReadMemory to onlyWritesMemory globally [NFC] 2022-01-05 08:52:55 -08:00
BlockFrequencyInfo.cpp Internalize some cl::opt global variables or move them under namespace llvm 2021-05-07 11:15:43 -07:00
BlockFrequencyInfoImpl.cpp [NFC] Use Optional<ProfileCount> to model invalid counts 2021-11-14 19:03:30 -08:00
BranchProbabilityInfo.cpp [BPI] Look-up tables for non-loop branches. NFC. 2021-11-22 10:30:42 +00:00
CFG.cpp [CFG] Move reachable from entry checks into basic block variant 2021-05-15 15:42:02 +02:00
CFGPrinter.cpp Use `-cfg-func-name` value as filter for `-view-cfg`, etc. 2021-06-16 23:54:51 +02:00
CFLAndersAliasAnalysis.cpp [NFC][AA] Prepare to convert AliasResult to class with PartialAlias offset. 2021-04-09 12:54:22 +03:00
CFLGraph.h [CFLGraph] Fix a crash due to missing handling of freeze 2021-03-21 02:14:13 +09:00
CFLSteensAliasAnalysis.cpp [llvm] Remove redundant member initialization (NFC) 2022-01-07 17:45:09 -08:00
CGSCCPassManager.cpp [NewPM] Add option to prevent rerunning function pipeline on functions in CGSCC adaptor 2021-11-17 09:06:46 -08:00
CMakeLists.txt [NFC][mlgo]Make the test model generator inlining-specific 2021-12-22 13:38:45 -08:00
CallGraph.cpp Set IgnoreLLVMUsed to false in CallGraph::addToCallGraph() 2021-04-08 11:14:09 -07:00
CallGraphSCCPass.cpp [llvm] Remove redundant member initialization (NFC) 2022-01-07 17:45:09 -08:00
CallPrinter.cpp Revert "[NFC] Remove LinkAll*.h" 2021-11-02 09:08:09 -07:00
CaptureTracking.cpp [capturetracking] Explicitly check for callee operand [NFC] 2021-12-17 09:21:35 -08:00
CmpInstAnalysis.cpp [APInt] Stop using soft-deprecated constructors and methods in llvm. NFC. 2021-10-04 08:57:44 +01:00
CodeMetrics.cpp [CodeMetrics] Don't require speculatability for ephemeral values 2021-10-21 20:30:01 +02:00
ConstantFolding.cpp [ConstantFolding] Clean up Intrinsics::abs undef handling 2022-01-10 17:04:03 +00:00
ConstraintSystem.cpp
CostModel.cpp Port the cost model printer to New PM 2021-09-08 14:47:05 -07:00
CycleAnalysis.cpp Reapply CycleInfo: Introduce cycles as a generalization of loops 2021-12-10 14:36:43 +05:30
DDG.cpp [llvm] Remove redundant member initialization (NFC) 2022-01-07 17:45:09 -08:00
DDGPrinter.cpp Support: Stop using F_{None,Text,Append} compatibility synonyms, NFC 2021-04-30 11:00:03 -07:00
Delinearization.cpp [SCEV] Move getIndexExpressionsFromGEP to delinearize [NFC] 2021-09-08 16:56:49 -07:00
DemandedBits.cpp [APInt] Normalize naming on keep constructors / predicate methods. 2021-09-09 09:50:24 -07:00
DependenceAnalysis.cpp [APInt] Normalize naming on keep constructors / predicate methods. 2021-09-09 09:50:24 -07:00
DependenceGraphBuilder.cpp
DevelopmentModeInlineAdvisor.cpp [NFC][MLGO] Use LazyCallGraph::Node to track functions. 2022-01-11 19:23:47 -08:00
DivergenceAnalysis.cpp [DivergenceAnalysis] Simplify inRegion test based on whether the RegionLoop pointer is null or not 2022-01-08 14:30:10 +00:00
DomPrinter.cpp Introduce NewPM .dot printers for DomTree 2022-01-05 23:25:40 +00:00
DomTreeUpdater.cpp [NFCI][DomTreeUpdater] applyUpdates(): reserve space for updates first 2021-04-11 23:56:22 +03:00
DominanceFrontier.cpp [llvm] Remove redundant member initialization (NFC) 2022-01-07 17:45:09 -08:00
EHPersonalities.cpp [XCOFF] Handle the case when personality routine is an alias 2021-04-29 22:03:30 +00:00
FunctionPropertiesAnalysis.cpp
GlobalsModRef.cpp [GlobalsModRef] Apply indirect-global rule to all globals initialized from noalias calls 2022-01-11 08:44:31 -08:00
GuardUtils.cpp
HeatUtils.cpp [llvm][clang][NFC] updates inline licence info 2021-08-11 02:48:53 +00:00
IRSimilarityIdentifier.cpp [IROutliner] Move global namespace cl::opt inside llvm:: 2021-12-30 01:12:55 -08:00
IVDescriptors.cpp [LoopVectorize][CostModel] Choose smaller VFs for in-loop reductions without loads/stores 2022-01-04 10:12:57 +00:00
IVUsers.cpp [llvm] Remove redundant member initialization (NFC) 2022-01-07 17:45:09 -08:00
ImportedFunctionsInliningStatistics.cpp [Analysis] ImportedFunctionsInliningStatistics.h - add <memory> and remove unused <string> include. NFCI. 2021-04-19 16:20:56 +01:00
IndirectCallPromotionAnalysis.cpp
InlineAdvisor.cpp [NFC][MLGO] Use LazyCallGraph::Node to track functions. 2022-01-11 19:23:47 -08:00
InlineCost.cpp Don't override __attribute__((no_stack_protector)) by inlining (PR52886) 2022-01-13 12:04:49 +01:00
InlineSizeEstimatorAnalysis.cpp [llvm][clang][NFC] updates inline licence info 2021-08-11 02:48:53 +00:00
InstCount.cpp
InstructionPrecedenceTracking.cpp Revert "[IPT] Restructure cache to allow lazy update following invalidation [NFC]" 2021-10-21 10:48:41 -07:00
InstructionSimplify.cpp [InstSimplify] use knownbits to fold more udiv/urem 2022-01-12 14:59:43 -05:00
Interval.cpp
IntervalPartition.cpp [llvm] Use range-based for loops (NFC) 2021-11-20 18:42:10 -08:00
LazyBlockFrequencyInfo.cpp Make dependency between certain analysis passes transitive (reapply) 2021-05-05 15:17:55 +02:00
LazyBranchProbabilityInfo.cpp Make dependency between certain analysis passes transitive (reapply) 2021-05-05 15:17:55 +02:00
LazyCallGraph.cpp [NFC][LazyCallGraph] Remove check in removeDeadFunction() if graph is empty 2022-01-11 10:17:13 -08:00
LazyValueInfo.cpp [LVI] Drop requirement that modulus is constant 2021-11-20 21:06:08 +01:00
LegacyDivergenceAnalysis.cpp
Lint.cpp Put implementation details into anonymous namespaces. NFCI. 2021-11-07 15:18:30 +01:00
Loads.cpp [Loads] Handle addrspacecast constant expressions when determining dereferenceability 2021-11-16 11:17:57 -08:00
LoopAccessAnalysis.cpp [LAA] Remove overeager assertion for aggregate types. 2022-01-04 15:20:35 +00:00
LoopAnalysisManager.cpp [NewPM] Don't mark AA analyses as preserved 2021-05-18 13:49:03 -07:00
LoopCacheAnalysis.cpp [llvm] Remove redundant member initialization (NFC) 2022-01-07 17:45:09 -08:00
LoopInfo.cpp [LoopInfo] Fix function getInductionVariable 2021-11-11 16:22:42 +08:00
LoopNestAnalysis.cpp LoopNest Analysis expansion to return instructions that prevent a Loop 2021-08-17 22:25:49 +00:00
LoopPass.cpp [llvm] Remove redundant member initialization (NFC) 2022-01-07 17:45:09 -08:00
LoopUnrollAnalyzer.cpp [unroll] Use value domain for symbolic execution based cost model 2021-05-26 08:41:25 -07:00
MLInlineAdvisor.cpp [NFC][MLGO] Use LazyCallGraph::Node to track functions. 2022-01-11 19:23:47 -08:00
MemDepPrinter.cpp
MemDerefPrinter.cpp [NFC] Remove more calls to getAlignment() 2021-12-15 14:40:57 -08:00
MemoryBuiltins.cpp [MemoryBuiltins] Remove unused isOpNewLikeFn() (NFC) 2022-01-11 12:27:23 +01:00
MemoryDependenceAnalysis.cpp [MemoryBuiltins] Remove isNoAliasFn() in favor of isNoAliasCall() 2022-01-10 09:18:15 +01:00
MemoryLocation.cpp [DSE][MemLoc] Handle intrinsics more generically 2021-12-24 09:29:57 +01:00
MemorySSA.cpp [CSSPGO] Unblock optimizations with pseudo probe instrumentation part 3. 2021-10-12 09:44:12 -07:00
MemorySSAUpdater.cpp [llvm] Use range-based for loops (NFC) 2021-11-18 09:09:52 -08:00
ModelUnderTrainingRunner.cpp [NFC][MLGO] Remove the word "inliner" in a generic error message. 2022-01-11 12:39:16 -08:00
ModuleDebugInfoPrinter.cpp
ModuleSummaryAnalysis.cpp [LTO][WPD] Simplify mustBeUnreachableFunction and test after D115492 2021-12-15 15:43:35 -08:00
MustExecute.cpp
NoInferenceModelRunner.cpp [NFC][MLGO]Add RTTI support for MLModelRunner and simplify runner setup 2022-01-04 19:46:14 -08:00
ObjCARCAliasAnalysis.cpp [NFC][AA] Prepare to convert AliasResult to class with PartialAlias offset. 2021-04-09 12:54:22 +03:00
ObjCARCAnalysisUtils.cpp
ObjCARCInstKind.cpp [llvm] Use range-based for loops (NFC) 2021-11-18 09:09:52 -08:00
OptimizationRemarkEmitter.cpp
OverflowInstAnalysis.cpp Ensure newlines at the end of files (NFC) 2021-10-23 08:45:29 -07:00
PHITransAddr.cpp [LLVM][NFC]Inclusive language: remove occurances of sanity check/test from llvm 2021-11-24 17:29:55 -05:00
PhiValues.cpp
PostDominators.cpp
ProfileSummaryInfo.cpp [NFC] Use Optional<ProfileCount> to model invalid counts 2021-11-14 19:03:30 -08:00
PtrUseVisitor.cpp
README.txt
RegionInfo.cpp Revert "[NFC] Remove LinkAll*.h" 2021-11-02 09:08:09 -07:00
RegionPass.cpp [llvm] Remove redundant member initialization (NFC) 2022-01-07 17:45:09 -08:00
RegionPrinter.cpp
ReplayInlineAdvisor.cpp [InlineAdvisor] Add fallback/format switches and negative remark processing to Replay Inliner 2021-10-29 12:32:03 -07:00
ScalarEvolution.cpp [SCEV] `getSequentialMinMaxExpr()`: look into `umin` when deduplicating operands 2022-01-11 18:51:57 +03:00
ScalarEvolutionAliasAnalysis.cpp [SCEVAA] Avoid forming malformed pointer diff expressions 2021-11-17 12:38:04 -08:00
ScalarEvolutionDivision.cpp
ScalarEvolutionNormalization.cpp
ScopedNoAliasAA.cpp [NFC][AA] Prepare to convert AliasResult to class with PartialAlias offset. 2021-04-09 12:54:22 +03:00
StackLifetime.cpp [NPM] Added -print-pipeline-passes print params for a few passes. 2021-09-15 08:34:04 +02:00
StackSafetyAnalysis.cpp [stack-safety] Check SCEV constraints at memory instructions. 2021-11-23 15:29:23 -08:00
StratifiedSets.h
SyncDependenceAnalysis.cpp [DA][NFC] Update publication - add remarks 2021-11-22 12:58:19 +01:00
SyntheticCountsUtils.cpp
TFUtils.cpp [MLGO] Add support for multiple training traces per module 2022-01-11 16:13:31 -08:00
TargetLibraryInfo.cpp Revert "Revert "Use VersionTuple for parsing versions in Triple, fixing issues that caused the original change to be reverted. This makes it possible to distinguish between "16" and "16.0" after parsing, which previously was not possible."" 2021-12-07 23:15:21 +00:00
TargetTransformInfo.cpp [LoopVectorize] Pass a vector type to isLegalMaskedGather/Scatter 2022-01-12 13:34:12 +00:00
Trace.cpp
TypeBasedAliasAnalysis.cpp [IR] Re-group AAMDNodes relevant interfaces. NFC. 2021-09-21 14:29:33 -04:00
TypeMetadataUtils.cpp [GlobalDCE] In VFE, replace the whole 'sub' expression of unused relative-pointer-based vtable slots 2021-10-06 15:55:55 -07:00
VFABIDemangling.cpp [LLVM][NFC]Inclusive language: remove occurances of sanity check/test from llvm 2021-11-24 17:29:55 -05:00
ValueLattice.cpp
ValueLatticeUtils.cpp
ValueTracking.cpp [Analysis] fix swapped operands to computeConstantRange 2022-01-04 13:13:50 -05:00
VectorUtils.cpp [Analysis] add utility function for unary shuffle mask creation 2021-10-18 09:00:39 -04:00

README.txt

Analysis Opportunities:

//===---------------------------------------------------------------------===//

In test/Transforms/LoopStrengthReduce/quadradic-exit-value.ll, the
ScalarEvolution expression for %r is this:

  {1,+,3,+,2}<loop>

Outside the loop, this could be evaluated simply as (%n * %n), however
ScalarEvolution currently evaluates it as

  (-2 + (2 * (trunc i65 (((zext i64 (-2 + %n) to i65) * (zext i64 (-1 + %n) to i65)) /u 2) to i64)) + (3 * %n))

In addition to being much more complicated, it involves i65 arithmetic,
which is very inefficient when expanded into code.

//===---------------------------------------------------------------------===//

In formatValue in test/CodeGen/X86/lsr-delayed-fold.ll,

ScalarEvolution is forming this expression:

((trunc i64 (-1 * %arg5) to i32) + (trunc i64 %arg5 to i32) + (-1 * (trunc i64 undef to i32)))

This could be folded to

(-1 * (trunc i64 undef to i32))

//===---------------------------------------------------------------------===//