Skip to content

Commit 58bfee6

Browse files
authored
merge main into amd-staging (#716)
2 parents ea568b2 + 774ed58 commit 58bfee6

30 files changed

+1843
-280
lines changed

clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,7 @@ void FormatStringConverter::finalizeFormatText() {
700700
/// Append literal parts of the format text, reinstating escapes as required.
701701
void FormatStringConverter::appendFormatText(const StringRef Text) {
702702
for (const char Ch : Text) {
703+
const auto UCh = static_cast<unsigned char>(Ch);
703704
if (Ch == '\a')
704705
StandardFormatString += "\\a";
705706
else if (Ch == '\b')
@@ -724,10 +725,10 @@ void FormatStringConverter::appendFormatText(const StringRef Text) {
724725
} else if (Ch == '}') {
725726
StandardFormatString += "}}";
726727
FormatStringNeededRewriting = true;
727-
} else if (Ch < 32) {
728+
} else if (UCh < 32) {
728729
StandardFormatString += "\\x";
729-
StandardFormatString += llvm::hexdigit(Ch >> 4, true);
730-
StandardFormatString += llvm::hexdigit(Ch & 0xf, true);
730+
StandardFormatString += llvm::hexdigit(UCh >> 4, true);
731+
StandardFormatString += llvm::hexdigit(UCh & 0xf, true);
731732
} else
732733
StandardFormatString += Ch;
733734
}

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ Potentially Breaking Changes
6969
- `CharTypdefsToIgnore` to `CharTypedefsToIgnore` in
7070
:doc:`bugprone-signed-char-misuse
7171
<clang-tidy/checks/bugprone/signed-char-misuse>`
72-
72+
7373
- Modified the custom message format of :doc:`bugprone-unsafe-functions
7474
<clang-tidy/checks/bugprone/unsafe-functions>` by assigning a special meaning
7575
to the character ``>`` at the start of the value of the option
@@ -394,7 +394,7 @@ Changes in existing checks
394394
<clang-tidy/checks/bugprone/unhandled-self-assignment>` check by adding
395395
an additional matcher that generalizes the copy-and-swap idiom pattern
396396
detection.
397-
397+
398398
- Improved :doc:`bugprone-unsafe-functions
399399
<clang-tidy/checks/bugprone/unsafe-functions>` check by hiding the default
400400
suffix when the reason starts with the character `>` in the `CustomFunctions`
@@ -497,7 +497,8 @@ Changes in existing checks
497497
- Improved :doc:`modernize-use-std-print
498498
<clang-tidy/checks/modernize/use-std-print>` check to correctly match
499499
when the format string is converted to a different type by an implicit
500-
constructor call.
500+
constructor call, and fixed a crash when handling format strings
501+
containing non-ASCII characters.
501502

502503
- Improved :doc:`performance-unnecessary-copy-initialization
503504
<clang-tidy/checks/performance/unnecessary-copy-initialization>` by printing

clang-tools-extra/test/clang-tidy/check_clang_tidy.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,8 @@ def parse_arguments() -> Tuple[argparse.Namespace, List[str]]:
398398

399399

400400
def main() -> None:
401+
sys.stdout.reconfigure(encoding="utf-8")
402+
sys.stderr.reconfigure(encoding="utf-8")
401403
args, extra_args = parse_arguments()
402404

403405
abbreviated_stds = args.std

clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ void printf_deceptive_newline() {
5454
// CHECK-FIXES: std::println("Hello");
5555
}
5656

57+
void printf_utf8_text() {
58+
printf("你好世界\n");
59+
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
60+
// CHECK-FIXES: std::println("你好世界");
61+
}
62+
5763
void printf_crlf_newline() {
5864
printf("Hello\r\n");
5965
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
@@ -303,6 +309,12 @@ void fprintf_simple() {
303309
// CHECK-FIXES: std::print(stderr, "Hello");
304310
}
305311

312+
void fprintf_utf8_text() {
313+
fprintf(stderr, "你好世界\n");
314+
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'fprintf' [modernize-use-std-print]
315+
// CHECK-FIXES: std::println(stderr, "你好世界");
316+
}
317+
306318
void std_printf_simple() {
307319
std::printf("std::Hello");
308320
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]

llvm/docs/InstCombineContributorGuide.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ complexity and increasing compile-time overhead.
338338

339339
We do not require explicit proof of real-world usefulness for every transform
340340
-- in most cases the usefulness is fairly "obvious". However, the question may
341-
come up for complex or unusual folds. Keep this in mind when chosing what you
341+
come up for complex or unusual folds. Keep this in mind when choosing what you
342342
work on.
343343

344344
In particular, fixes for fuzzer-generated missed optimization reports will

llvm/docs/KeyInstructionsDebugInfo.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ int c =
8282
```
8383
In the current implementation an `is_stmt` won't be generated for the `a + b` instruction, meaning debuggers will likely step over the `add` and stop at the `store` of the result into `c` (which does get `is_stmt`). A user might have wished to edit `a` or `b` on the previous line in order to alter the result stored to `c`, which they now won't have the chance to do (they'd need to edit the variables on a previous line instead). If the expression was all on one line then they would be able to edit the values before the `add`. For these reasons we're choosing to recommend that the feature should not be enabled at O0.
8484

85-
It should be possible to fix this case if we make a few changes: add all the instructions in the statement (i.e., including the loads) to the atom, and tweak the DwarfEmission code to understand this situation (same atom, different line). So there is room to persue this in the future. Though that gets tricky in some cases due to the [other limitation mentioned above](#lack-of-multiple-atom-membership), e.g.:
85+
It should be possible to fix this case if we make a few changes: add all the instructions in the statement (i.e., including the loads) to the atom, and tweak the DwarfEmission code to understand this situation (same atom, different line). So there is room to pursue this in the future. Though that gets tricky in some cases due to the [other limitation mentioned above](#lack-of-multiple-atom-membership), e.g.:
8686
```c
8787
int e = // atom 1
8888
(a + b) // atom 1

llvm/docs/Telemetry.rst

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ Important notes
3232
* There is no concrete implementation of a Telemetry library in upstream LLVM.
3333
We only provide the abstract API here. Any tool that wants telemetry will
3434
implement one.
35-
35+
3636
The rationale for this is that all the tools in LLVM are very different in
3737
what they care about (what/where/when to instrument data). Hence, it might not
3838
be practical to have a single implementation.
@@ -41,16 +41,16 @@ Important notes
4141

4242
* No implementation of Telemetry in upstream LLVM shall store any of the
4343
collected data due to privacy and security reasons:
44-
44+
4545
* Different organizations have different privacy models:
46-
46+
4747
* Which data is sensitive, which is not?
4848
* Whether it is acceptable for instrumented data to be stored anywhere?
4949
(to a local file, what not?)
50-
50+
5151
* Data ownership and data collection consents are hard to accommodate from
5252
LLVM developers' point of view:
53-
53+
5454
* E.g., data collected by Telemetry is not necessarily owned by the user
5555
of an LLVM tool with Telemetry enabled, hence the user's consent to data
5656
collection is not meaningful. On the other hand, LLVM developers have no
@@ -75,7 +75,7 @@ The framework consists of four important classes:
7575
It is up to the vendor to decide which pieces of data to forward and where
7676
to forward them to for their final storage.
7777
* ``llvm::telemetry::Config``: Configurations for the ``Manager``.
78-
78+
7979
.. image:: llvm_telemetry_design.png
8080

8181
How to implement and interact with the API
@@ -123,20 +123,20 @@ To use Telemetry in your tool, you need to provide a concrete implementation of
123123
void write(StringRef KeyName, unsigned long Value) override {
124124
writeHelper(KeyName, Value);
125125
}
126-
126+
127127
void write(StringRef KeyName, unsigned long long Value) override {
128128
writeHelper(KeyName, Value);
129129
}
130130

131131
void write(StringRef KeyName, StringRef Value) override {
132132
writeHelper(KeyName, Value);
133133
}
134-
134+
135135
void beginObject(StringRef KeyName) override {
136136
Children.push_back(json::Object());
137137
ChildrenNames.push_back(KeyName.str());
138138
}
139-
139+
140140
void endObject() override {
141141
assert(!Children.empty() && !ChildrenNames.empty());
142142
json::Value Val = json::Value(std::move(Children.back()));
@@ -146,7 +146,7 @@ To use Telemetry in your tool, you need to provide a concrete implementation of
146146
ChildrenNames.pop_back();
147147
writeHelper(Name, std::move(Val));
148148
}
149-
149+
150150
Error finalize() override {
151151
if (!Started)
152152
return createStringError("Serializer not currently in use");
@@ -167,10 +167,10 @@ To use Telemetry in your tool, you need to provide a concrete implementation of
167167
std::vector<json::Object> Children;
168168
std::vector<std::string> ChildrenNames;
169169
};
170-
171-
class MyManager : public telemery::Manager {
170+
171+
class MyManager : public telemetry::Manager {
172172
public:
173-
static std::unique_ptr<MyManager> createInstatnce(telemetry::Config *Config) {
173+
static std::unique_ptr<MyManager> createInstance(telemetry::Config *Config) {
174174
// If Telemetry is not enabled, then just return null;
175175
if (!Config->EnableTelemetry)
176176
return nullptr;
@@ -182,19 +182,19 @@ To use Telemetry in your tool, you need to provide a concrete implementation of
182182
Entry->SessionId = SessionId;
183183
return Error::success();
184184
}
185-
185+
186186
// You can also define additional instrumentation points.
187187
void logStartup(TelemetryInfo *Entry) {
188188
// Add some additional data to entry.
189189
Entry->Msg = "Some message";
190190
dispatch(Entry);
191191
}
192-
192+
193193
void logAdditionalPoint(TelemetryInfo *Entry) {
194194
// .... code here
195195
}
196-
197-
private:
196+
197+
private:
198198
const std::string SessionId;
199199
};
200200

@@ -203,11 +203,11 @@ To use Telemetry in your tool, you need to provide a concrete implementation of
203203
Error receiveEntry(const TelemetryInfo *Entry) override {
204204
if (Error Err = Serializer.init())
205205
return Err;
206-
206+
207207
Entry->serialize(Serializer);
208208
if (Error Err = Serializer.finalize())
209209
return Err;
210-
210+
211211
json::Object Copied = *Serializer.getOutputObject();
212212
// Send the `Copied` object to wherever.
213213
return Error::success();
@@ -220,16 +220,16 @@ To use Telemetry in your tool, you need to provide a concrete implementation of
220220
// This defines a custom TelemetryInfo that has an additional Msg field.
221221
struct MyTelemetryInfo : public telemetry::TelemetryInfo {
222222
std::string Msg;
223-
223+
224224
Error serialize(Serializer &Serializer) const override {
225225
TelemetryInfo::serialize(serializer);
226226
Serializer.writeString("MyMsg", Msg);
227227
}
228-
228+
229229
// Note: implement getKind() and classof() to support dyn_cast operations.
230230
};
231231

232-
232+
233233
2) Use the library in your tool.
234234

235235
Logging the tool init-process:
@@ -241,10 +241,10 @@ Logging the tool init-process:
241241
telemetry::Config MyConfig = makeConfig(); // Build up the appropriate Config struct here.
242242
auto Manager = MyManager::createInstance(&MyConfig);
243243

244-
244+
245245
// Any other tool's init code can go here.
246246
// ...
247-
247+
248248
// Finally, take a snapshot of the time now so we know how long it took the
249249
// init process to finish.
250250
auto EndTime = std::chrono::time_point<std::chrono::steady_clock>::now();

llvm/include/llvm/Analysis/IVDescriptors.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,12 +95,17 @@ class RecurrenceDescriptor {
9595
RecurKind K, FastMathFlags FMF, Instruction *ExactFP,
9696
Type *RT, bool Signed, bool Ordered,
9797
SmallPtrSetImpl<Instruction *> &CI,
98-
unsigned MinWidthCastToRecurTy)
98+
unsigned MinWidthCastToRecurTy,
99+
bool PhiHasUsesOutsideReductionChain = false)
99100
: IntermediateStore(Store), StartValue(Start), LoopExitInstr(Exit),
100101
Kind(K), FMF(FMF), ExactFPMathInst(ExactFP), RecurrenceType(RT),
101102
IsSigned(Signed), IsOrdered(Ordered),
103+
PhiHasUsesOutsideReductionChain(PhiHasUsesOutsideReductionChain),
102104
MinWidthCastToRecurrenceType(MinWidthCastToRecurTy) {
103105
CastInsts.insert_range(CI);
106+
assert(
107+
(!PhiHasUsesOutsideReductionChain || isMinMaxRecurrenceKind(K)) &&
108+
"Only min/max recurrences are allowed to have multiple uses currently");
104109
}
105110

106111
/// This POD struct holds information about a potential recurrence operation.
@@ -339,6 +344,13 @@ class RecurrenceDescriptor {
339344
/// Expose an ordered FP reduction to the instance users.
340345
bool isOrdered() const { return IsOrdered; }
341346

347+
/// Returns true if the reduction PHI has any uses outside the reduction
348+
/// chain. This is relevant for min/max reductions that are part of a
349+
/// FindLastIV pattern.
350+
bool hasUsesOutsideReductionChain() const {
351+
return PhiHasUsesOutsideReductionChain;
352+
}
353+
342354
/// Attempts to find a chain of operations from Phi to LoopExitInst that can
343355
/// be treated as a set of reductions instructions for in-loop reductions.
344356
LLVM_ABI SmallVector<Instruction *, 4> getReductionOpChain(PHINode *Phi,
@@ -376,6 +388,10 @@ class RecurrenceDescriptor {
376388
// Currently only a non-reassociative FAdd can be considered in-order,
377389
// if it is also the only FAdd in the PHI's use chain.
378390
bool IsOrdered = false;
391+
// True if the reduction PHI has in-loop users outside the reduction chain.
392+
// This is relevant for min/max reductions that are part of a FindLastIV
393+
// pattern.
394+
bool PhiHasUsesOutsideReductionChain = false;
379395
// Instructions used for type-promoting the recurrence.
380396
SmallPtrSet<Instruction *, 8> CastInsts;
381397
// The minimum width used by the recurrence.

llvm/include/llvm/IR/IntrinsicsRISCVXCV.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,8 @@ let TargetPrefix = "riscv" in {
9090
def int_riscv_cv_mac_machhuRN : ScalarCoreVMacGprGprGprImmIntrinsic;
9191
def int_riscv_cv_mac_macsRN : ScalarCoreVMacGprGprGprImmIntrinsic;
9292
def int_riscv_cv_mac_machhsRN : ScalarCoreVMacGprGprGprImmIntrinsic;
93+
94+
def int_riscv_cv_elw_elw
95+
: Intrinsic<[llvm_i32_ty], [llvm_ptr_ty],
96+
[IntrReadMem, IntrArgMemOnly, IntrHasSideEffects]>;
9397
} // TargetPrefix = "riscv"

llvm/lib/Analysis/IVDescriptors.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,52 @@ static bool checkOrderedReduction(RecurKind Kind, Instruction *ExactFPMathInst,
216216
return true;
217217
}
218218

219+
/// Returns true if \p Phi is a min/max reduction matching \p Kind where \p Phi
220+
/// is used outside the reduction chain. This is common for loops selecting the
221+
/// index of a minimum/maximum value (argmin/argmax).
222+
static bool isMinMaxReductionPhiWithUsersOutsideReductionChain(
223+
PHINode *Phi, RecurKind Kind, Loop *TheLoop, RecurrenceDescriptor &RedDes) {
224+
BasicBlock *Latch = TheLoop->getLoopLatch();
225+
if (!Latch)
226+
return false;
227+
228+
assert(Phi->getNumIncomingValues() == 2 && "phi must have 2 incoming values");
229+
Value *Inc = Phi->getIncomingValueForBlock(Latch);
230+
if (Phi->hasOneUse() || !Inc->hasOneUse() ||
231+
!RecurrenceDescriptor::isIntMinMaxRecurrenceKind(Kind))
232+
return false;
233+
234+
Value *A, *B;
235+
bool IsMinMax = [&]() {
236+
switch (Kind) {
237+
case RecurKind::UMax:
238+
return match(Inc, m_UMax(m_Value(A), m_Value(B)));
239+
case RecurKind::UMin:
240+
return match(Inc, m_UMin(m_Value(A), m_Value(B)));
241+
case RecurKind::SMax:
242+
return match(Inc, m_SMax(m_Value(A), m_Value(B)));
243+
case RecurKind::SMin:
244+
return match(Inc, m_SMin(m_Value(A), m_Value(B)));
245+
default:
246+
llvm_unreachable("all min/max kinds must be handled");
247+
}
248+
}();
249+
if (!IsMinMax)
250+
return false;
251+
252+
if (A == B || (A != Phi && B != Phi))
253+
return false;
254+
255+
SmallPtrSet<Instruction *, 4> CastInsts;
256+
Value *RdxStart = Phi->getIncomingValueForBlock(TheLoop->getLoopPreheader());
257+
RedDes =
258+
RecurrenceDescriptor(RdxStart, /*Exit=*/nullptr, /*Store=*/nullptr, Kind,
259+
FastMathFlags(), /*ExactFP=*/nullptr, Phi->getType(),
260+
/*Signed=*/false, /*Ordered=*/false, CastInsts,
261+
/*MinWidthCastToRecurTy=*/-1U, /*PhiMultiUse=*/true);
262+
return true;
263+
}
264+
219265
bool RecurrenceDescriptor::AddReductionVar(
220266
PHINode *Phi, RecurKind Kind, Loop *TheLoop, FastMathFlags FuncFMF,
221267
RecurrenceDescriptor &RedDes, DemandedBits *DB, AssumptionCache *AC,
@@ -227,6 +273,11 @@ bool RecurrenceDescriptor::AddReductionVar(
227273
if (Phi->getParent() != TheLoop->getHeader())
228274
return false;
229275

276+
// Check for min/max reduction variables that feed other users in the loop.
277+
if (isMinMaxReductionPhiWithUsersOutsideReductionChain(Phi, Kind, TheLoop,
278+
RedDes))
279+
return true;
280+
230281
// Obtain the reduction start value from the value that comes from the loop
231282
// preheader.
232283
Value *RdxStart = Phi->getIncomingValueForBlock(TheLoop->getLoopPreheader());

0 commit comments

Comments
 (0)