Skip to content

Commit 599a5be

Browse files
committed
Merge branch 'main' into mlir-scf2gpu-affineapply-crash
Signed-off-by: Shashi Shankar <[email protected]>
2 parents 9102a84 + 7fe3564 commit 599a5be

File tree

86 files changed

+1792
-966
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+1792
-966
lines changed

clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,12 @@ class Fact {
4242
/// it. Otherwise, the source's loan set is merged into the destination's
4343
/// loan set.
4444
OriginFlow,
45-
/// An origin escapes the function by flowing into the return value.
46-
ReturnOfOrigin,
4745
/// An origin is used (eg. appears as l-value expression like DeclRefExpr).
4846
Use,
4947
/// A marker for a specific point in the code, for testing.
5048
TestPoint,
49+
/// An origin that escapes the function scope (e.g., via return).
50+
OriginEscapes,
5151
};
5252

5353
private:
@@ -136,16 +136,19 @@ class OriginFlowFact : public Fact {
136136
const OriginManager &OM) const override;
137137
};
138138

139-
class ReturnOfOriginFact : public Fact {
139+
class OriginEscapesFact : public Fact {
140140
OriginID OID;
141+
const Expr *EscapeExpr;
141142

142143
public:
143144
static bool classof(const Fact *F) {
144-
return F->getKind() == Kind::ReturnOfOrigin;
145+
return F->getKind() == Kind::OriginEscapes;
145146
}
146147

147-
ReturnOfOriginFact(OriginID OID) : Fact(Kind::ReturnOfOrigin), OID(OID) {}
148-
OriginID getReturnedOriginID() const { return OID; }
148+
OriginEscapesFact(OriginID OID, const Expr *EscapeExpr)
149+
: Fact(Kind::OriginEscapes), OID(OID), EscapeExpr(EscapeExpr) {}
150+
OriginID getEscapedOriginID() const { return OID; }
151+
const Expr *getEscapeExpr() const { return EscapeExpr; };
149152
void dump(llvm::raw_ostream &OS, const LoanManager &,
150153
const OriginManager &OM) const override;
151154
};
@@ -225,6 +228,9 @@ class FactManager {
225228
/// user-defined locations in the code.
226229
/// \note This is intended for testing only.
227230
llvm::StringMap<ProgramPoint> getTestPoints() const;
231+
/// Retrieves all the facts in the block containing Program Point P.
232+
/// \note This is intended for testing only.
233+
llvm::ArrayRef<const Fact *> getBlockContaining(ProgramPoint P) const;
228234

229235
unsigned getNumFacts() const { return NextFactID.Value; }
230236

clang/include/clang/Analysis/Analyses/LifetimeSafety/FactsGenerator.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,10 @@ class FactsGenerator : public ConstStmtVisitor<FactsGenerator> {
9494
FactManager &FactMgr;
9595
AnalysisDeclContext &AC;
9696
llvm::SmallVector<Fact *> CurrentBlockFacts;
97+
// Collect origins that escape the function in this block (OriginEscapesFact),
98+
// appended at the end of CurrentBlockFacts to ensure they appear after
99+
// ExpireFact entries.
100+
llvm::SmallVector<Fact *> EscapesInCurrentBlock;
97101
// To distinguish between reads and writes for use-after-free checks, this map
98102
// stores the `UseFact` for each `DeclRefExpr`. We initially identify all
99103
// `DeclRefExpr`s as "read" uses. When an assignment is processed, the use

clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ class LifetimeSafetyReporter {
4242
virtual void reportUseAfterFree(const Expr *IssueExpr, const Expr *UseExpr,
4343
SourceLocation FreeLoc,
4444
Confidence Confidence) {}
45+
46+
virtual void reportUseAfterReturn(const Expr *IssueExpr,
47+
const Expr *EscapeExpr,
48+
SourceLocation ExpiryLoc,
49+
Confidence Confidence) {}
4550
};
4651

4752
/// The main entry point for the analysis.

clang/include/clang/Analysis/Analyses/LifetimeSafety/LiveOrigins.h

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@
3131

3232
namespace clang::lifetimes::internal {
3333

34+
using CausingFactType =
35+
::llvm::PointerUnion<const UseFact *, const OriginEscapesFact *>;
36+
3437
enum class LivenessKind : uint8_t {
3538
Dead, // Not alive
3639
Maybe, // Live on some path but not all paths (may-be-live)
@@ -43,7 +46,7 @@ struct LivenessInfo {
4346
/// multiple uses along different paths, this will point to the use appearing
4447
/// earlier in the translation unit.
4548
/// This is 'null' when the origin is not live.
46-
const UseFact *CausingUseFact;
49+
CausingFactType CausingFact;
4750

4851
/// The kind of liveness of the origin.
4952
/// `Must`: The origin is live on all control-flow paths from the current
@@ -56,17 +59,16 @@ struct LivenessInfo {
5659
/// while `Maybe`-be-alive suggests a potential one on some paths.
5760
LivenessKind Kind;
5861

59-
LivenessInfo() : CausingUseFact(nullptr), Kind(LivenessKind::Dead) {}
60-
LivenessInfo(const UseFact *UF, LivenessKind K)
61-
: CausingUseFact(UF), Kind(K) {}
62+
LivenessInfo() : CausingFact(nullptr), Kind(LivenessKind::Dead) {}
63+
LivenessInfo(CausingFactType CF, LivenessKind K) : CausingFact(CF), Kind(K) {}
6264

6365
bool operator==(const LivenessInfo &Other) const {
64-
return CausingUseFact == Other.CausingUseFact && Kind == Other.Kind;
66+
return CausingFact == Other.CausingFact && Kind == Other.Kind;
6567
}
6668
bool operator!=(const LivenessInfo &Other) const { return !(*this == Other); }
6769

6870
void Profile(llvm::FoldingSetNodeID &IDBuilder) const {
69-
IDBuilder.AddPointer(CausingUseFact);
71+
IDBuilder.AddPointer(CausingFact.getOpaqueValue());
7072
IDBuilder.Add(Kind);
7173
}
7274
};

clang/include/clang/Basic/Builtins.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "llvm/ADT/StringMap.h"
2020
#include "llvm/ADT/StringRef.h"
2121
#include "llvm/ADT/StringTable.h"
22+
#include "llvm/TargetParser/Triple.h"
2223
#include <cstring>
2324

2425
// VC++ defines 'alloca' as an object-like macro, which interferes with our
@@ -405,6 +406,22 @@ class Context {
405406
return strchr(getAttributesString(ID), 'g') != nullptr;
406407
}
407408

409+
/// Determine whether we can generate LLVM intrinsics for the given
410+
/// builtin ID, based on whether it has side effects such as setting errno.
411+
///
412+
/// \param BuiltinID The builtin ID to check.
413+
/// \param Trip The target triple.
414+
/// \param ErrnoOverwritten Indicates whether the errno setting behavior
415+
/// has been overwritten via '#pragma float_control(precise, on/off)'.
416+
/// \param MathErrnoEnabled Indicates whether math-errno is enabled on
417+
/// command line.
418+
/// \param HasOptNoneAttr True iff 'attribute__((optnone))' is used.
419+
/// \param IsOptimizationEnabled True iff the optimization level is not 'O0'.
420+
bool shouldGenerateFPMathIntrinsic(unsigned BuiltinID, llvm::Triple Trip,
421+
std::optional<bool> ErrnoOverwritten,
422+
bool MathErrnoEnabled, bool HasOptNoneAttr,
423+
bool IsOptimizationEnabled) const;
424+
408425
const char *getRequiredFeatures(unsigned ID) const;
409426

410427
unsigned getRequiredVectorWidth(unsigned ID) const;

clang/include/clang/Basic/BuiltinsX86.td

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,7 @@ let Features = "avx", Attributes = [NoThrow, Const, RequiredVectorWidth<256>] in
512512
def vperm2f128_si256 : X86Builtin<"_Vector<8, int>(_Vector<8, int>, _Vector<8, int>, _Constant int)">;
513513
}
514514

515-
let Features = "avx", Attributes = [NoThrow, Const, RequiredVectorWidth<128>] in {
515+
let Features = "avx", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<128>] in {
516516
def vpermilpd : X86Builtin<"_Vector<2, double>(_Vector<2, double>, _Constant int)">;
517517
def vpermilps : X86Builtin<"_Vector<4, float>(_Vector<4, float>, _Constant int)">;
518518
}
@@ -528,6 +528,8 @@ let Features = "avx", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWid
528528
def vinsertf128_pd256 : X86Builtin<"_Vector<4, double>(_Vector<4, double>, _Vector<2, double>, _Constant int)">;
529529
def vinsertf128_ps256 : X86Builtin<"_Vector<8, float>(_Vector<8, float>, _Vector<4, float>, _Constant int)">;
530530
def vinsertf128_si256 : X86Builtin<"_Vector<8, int>(_Vector<8, int>, _Vector<4, int>, _Constant int)">;
531+
def vpermilpd256 : X86Builtin<"_Vector<4, double>(_Vector<4, double>, _Constant int)">;
532+
def vpermilps256 : X86Builtin<"_Vector<8, float>(_Vector<8, float>, _Constant int)">;
531533

532534
foreach Op = ["hadd", "hsub"] in {
533535
def Op#pd256 : X86Builtin<"_Vector<4, double>(_Vector<4, double>, _Vector<4, double>)">;
@@ -536,8 +538,6 @@ let Features = "avx", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWid
536538
}
537539

538540
let Features = "avx", Attributes = [NoThrow, Const, RequiredVectorWidth<256>] in {
539-
def vpermilpd256 : X86Builtin<"_Vector<4, double>(_Vector<4, double>, _Constant int)">;
540-
def vpermilps256 : X86Builtin<"_Vector<8, float>(_Vector<8, float>, _Constant int)">;
541541
def sqrtpd256 : X86Builtin<"_Vector<4, double>(_Vector<4, double>)">;
542542
def sqrtps256 : X86Builtin<"_Vector<8, float>(_Vector<8, float>)">;
543543
def rsqrtps256 : X86Builtin<"_Vector<8, float>(_Vector<8, float>)">;
@@ -2375,10 +2375,12 @@ let Features = "avx512f", Attributes = [NoThrow, Const, RequiredVectorWidth<128>
23752375
def vcvttss2si32 : X86Builtin<"int(_Vector<4, float>, _Constant int)">;
23762376
def vcvttss2usi32 : X86Builtin<"unsigned int(_Vector<4, float>, _Constant int)">;
23772377
}
2378-
2379-
let Features = "avx512f", Attributes = [NoThrow, Const, RequiredVectorWidth<512>] in {
2378+
let Features = "avx512f", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<512>] in {
23802379
def vpermilpd512 : X86Builtin<"_Vector<8, double>(_Vector<8, double>, _Constant int)">;
23812380
def vpermilps512 : X86Builtin<"_Vector<16, float>(_Vector<16, float>, _Constant int)">;
2381+
}
2382+
2383+
let Features = "avx512f", Attributes = [NoThrow, Const, RequiredVectorWidth<512>] in {
23822384
def vpermilvarpd512 : X86Builtin<"_Vector<8, double>(_Vector<8, double>, _Vector<8, long long int>)">;
23832385
def vpermilvarps512 : X86Builtin<"_Vector<16, float>(_Vector<16, float>, _Vector<16, int>)">;
23842386
}

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10744,8 +10744,19 @@ def warn_lifetime_safety_loan_expires_permissive : Warning<
1074410744
def warn_lifetime_safety_loan_expires_strict : Warning<
1074510745
"object whose reference is captured may not live long enough">,
1074610746
InGroup<LifetimeSafetyStrict>, DefaultIgnore;
10747+
10748+
def warn_lifetime_safety_return_stack_addr_permissive
10749+
: Warning<"address of stack memory is returned later">,
10750+
InGroup<LifetimeSafetyPermissive>,
10751+
DefaultIgnore;
10752+
def warn_lifetime_safety_return_stack_addr_strict
10753+
: Warning<"address of stack memory may be returned later">,
10754+
InGroup<LifetimeSafetyStrict>,
10755+
DefaultIgnore;
10756+
1074710757
def note_lifetime_safety_used_here : Note<"later used here">;
1074810758
def note_lifetime_safety_destroyed_here : Note<"destroyed here">;
10759+
def note_lifetime_safety_returned_here : Note<"returned here">;
1074910760

1075010761
// For non-floating point, expressions of the form x == x or x != x
1075110762
// should result in a warning, since these always evaluate to a constant.

clang/lib/AST/ByteCode/InterpBuiltin.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4620,6 +4620,9 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
46204620
case X86::BI__builtin_ia32_pshufd:
46214621
case X86::BI__builtin_ia32_pshufd256:
46224622
case X86::BI__builtin_ia32_pshufd512:
4623+
case X86::BI__builtin_ia32_vpermilps:
4624+
case X86::BI__builtin_ia32_vpermilps256:
4625+
case X86::BI__builtin_ia32_vpermilps512:
46234626
return interp__builtin_ia32_shuffle_generic(
46244627
S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
46254628
unsigned LaneBase = (DstIdx / 4) * 4;
@@ -4628,6 +4631,22 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
46284631
return std::make_pair(0, static_cast<int>(LaneBase + Sel));
46294632
});
46304633

4634+
case X86::BI__builtin_ia32_vpermilpd:
4635+
case X86::BI__builtin_ia32_vpermilpd256:
4636+
case X86::BI__builtin_ia32_vpermilpd512:
4637+
return interp__builtin_ia32_shuffle_generic(
4638+
S, OpPC, Call, [](unsigned DstIdx, unsigned Control) {
4639+
unsigned NumElemPerLane = 2;
4640+
unsigned BitsPerElem = 1;
4641+
unsigned MaskBits = 8;
4642+
unsigned IndexMask = 0x1;
4643+
unsigned Lane = DstIdx / NumElemPerLane;
4644+
unsigned LaneOffset = Lane * NumElemPerLane;
4645+
unsigned BitIndex = (DstIdx * BitsPerElem) % MaskBits;
4646+
unsigned Index = (Control >> BitIndex) & IndexMask;
4647+
return std::make_pair(0, static_cast<int>(LaneOffset + Index));
4648+
});
4649+
46314650
case X86::BI__builtin_ia32_kandqi:
46324651
case X86::BI__builtin_ia32_kandhi:
46334652
case X86::BI__builtin_ia32_kandsi:

clang/lib/AST/ExprConstant.cpp

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13023,7 +13023,10 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
1302313023

1302413024
case X86::BI__builtin_ia32_pshufd:
1302513025
case X86::BI__builtin_ia32_pshufd256:
13026-
case X86::BI__builtin_ia32_pshufd512: {
13026+
case X86::BI__builtin_ia32_pshufd512:
13027+
case X86::BI__builtin_ia32_vpermilps:
13028+
case X86::BI__builtin_ia32_vpermilps256:
13029+
case X86::BI__builtin_ia32_vpermilps512: {
1302713030
APValue R;
1302813031
if (!evalShuffleGeneric(
1302913032
Info, E, R,
@@ -13040,6 +13043,25 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
1304013043
return Success(R, E);
1304113044
}
1304213045

13046+
case X86::BI__builtin_ia32_vpermilpd:
13047+
case X86::BI__builtin_ia32_vpermilpd256:
13048+
case X86::BI__builtin_ia32_vpermilpd512: {
13049+
APValue R;
13050+
if (!evalShuffleGeneric(Info, E, R, [](unsigned DstIdx, unsigned Control) {
13051+
unsigned NumElemPerLane = 2;
13052+
unsigned BitsPerElem = 1;
13053+
unsigned MaskBits = 8;
13054+
unsigned IndexMask = 0x1;
13055+
unsigned Lane = DstIdx / NumElemPerLane;
13056+
unsigned LaneOffset = Lane * NumElemPerLane;
13057+
unsigned BitIndex = (DstIdx * BitsPerElem) % MaskBits;
13058+
unsigned Index = (Control >> BitIndex) & IndexMask;
13059+
return std::make_pair(0, static_cast<int>(LaneOffset + Index));
13060+
}))
13061+
return false;
13062+
return Success(R, E);
13063+
}
13064+
1304313065
case X86::BI__builtin_ia32_phminposuw128: {
1304413066
APValue Source;
1304513067
if (!Evaluate(Source, Info, E->getArg(0)))

clang/lib/Analysis/LifetimeSafety/Checker.cpp

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ namespace {
4343
/// Struct to store the complete context for a potential lifetime violation.
4444
struct PendingWarning {
4545
SourceLocation ExpiryLoc; // Where the loan expired.
46-
const Expr *UseExpr; // Where the origin holding this loan was used.
46+
llvm::PointerUnion<const UseFact *, const OriginEscapesFact *> CausingFact;
4747
Confidence ConfidenceLevel;
4848
};
4949

@@ -68,7 +68,7 @@ class LifetimeChecker {
6868
issuePendingWarnings();
6969
}
7070

71-
/// Checks for use-after-free errors when a loan expires.
71+
/// Checks for use-after-free & use-after-return errors when a loan expires.
7272
///
7373
/// This method examines all live origins at the expiry point and determines
7474
/// if any of them hold the expiring loan. If so, it creates a pending
@@ -83,7 +83,11 @@ class LifetimeChecker {
8383
LoanID ExpiredLoan = EF->getLoanID();
8484
LivenessMap Origins = LiveOrigins.getLiveOriginsAt(EF);
8585
Confidence CurConfidence = Confidence::None;
86-
const UseFact *BadUse = nullptr;
86+
// The UseFact or OriginEscapesFact most indicative of a lifetime error,
87+
// prioritized by earlier source location.
88+
llvm::PointerUnion<const UseFact *, const OriginEscapesFact *>
89+
BestCausingFact = nullptr;
90+
8791
for (auto &[OID, LiveInfo] : Origins) {
8892
LoanSet HeldLoans = LoanPropagation.getLoans(OID, EF);
8993
if (!HeldLoans.contains(ExpiredLoan))
@@ -92,17 +96,17 @@ class LifetimeChecker {
9296
Confidence NewConfidence = livenessKindToConfidence(LiveInfo.Kind);
9397
if (CurConfidence < NewConfidence) {
9498
CurConfidence = NewConfidence;
95-
BadUse = LiveInfo.CausingUseFact;
99+
BestCausingFact = LiveInfo.CausingFact;
96100
}
97101
}
98-
if (!BadUse)
102+
if (!BestCausingFact)
99103
return;
100104
// We have a use-after-free.
101105
Confidence LastConf = FinalWarningsMap.lookup(ExpiredLoan).ConfidenceLevel;
102106
if (LastConf >= CurConfidence)
103107
return;
104108
FinalWarningsMap[ExpiredLoan] = {/*ExpiryLoc=*/EF->getExpiryLoc(),
105-
/*UseExpr=*/BadUse->getUseExpr(),
109+
/*BestCausingFact=*/BestCausingFact,
106110
/*ConfidenceLevel=*/CurConfidence};
107111
}
108112

@@ -112,8 +116,20 @@ class LifetimeChecker {
112116
for (const auto &[LID, Warning] : FinalWarningsMap) {
113117
const Loan &L = FactMgr.getLoanMgr().getLoan(LID);
114118
const Expr *IssueExpr = L.IssueExpr;
115-
Reporter->reportUseAfterFree(IssueExpr, Warning.UseExpr,
116-
Warning.ExpiryLoc, Warning.ConfidenceLevel);
119+
llvm::PointerUnion<const UseFact *, const OriginEscapesFact *>
120+
CausingFact = Warning.CausingFact;
121+
Confidence Confidence = Warning.ConfidenceLevel;
122+
SourceLocation ExpiryLoc = Warning.ExpiryLoc;
123+
124+
if (const auto *UF = CausingFact.dyn_cast<const UseFact *>())
125+
Reporter->reportUseAfterFree(IssueExpr, UF->getUseExpr(), ExpiryLoc,
126+
Confidence);
127+
else if (const auto *OEF =
128+
CausingFact.dyn_cast<const OriginEscapesFact *>())
129+
Reporter->reportUseAfterReturn(IssueExpr, OEF->getEscapeExpr(),
130+
ExpiryLoc, Confidence);
131+
else
132+
llvm_unreachable("Unhandled CausingFact type");
117133
}
118134
}
119135
};

0 commit comments

Comments
 (0)