105 changes: 105 additions & 0 deletions clang/test/AST/const-fpfeatures.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,108 @@ float V7 = []() -> float {
0x0.000001p0F);
}();
// CHECK: @V7 = {{.*}} float 1.000000e+00

#pragma STDC FENV_ROUND FE_DYNAMIC

template<float V> struct L {
constexpr L() : value(V) {}
float value;
};

#pragma STDC FENV_ROUND FE_DOWNWARD
L<0.1F> val_d;
// CHECK: @val_d = {{.*}} { float 0x3FB9999980000000 }

#pragma STDC FENV_ROUND FE_UPWARD
L<0.1F> val_u;
// CHECK: @val_u = {{.*}} { float 0x3FB99999A0000000 }


// Check literals in macros.

#pragma STDC FENV_ROUND FE_DOWNWARD
#define CONSTANT_0_1 0.1F

#pragma STDC FENV_ROUND FE_UPWARD
float C1_ru = CONSTANT_0_1;
// CHECK: @C1_ru = {{.*}} float 0x3FB99999A0000000

#pragma STDC FENV_ROUND FE_DOWNWARD
float C1_rd = CONSTANT_0_1;
// CHECK: @C1_rd = {{.*}} float 0x3FB9999980000000

#pragma STDC FENV_ROUND FE_DOWNWARD
#define PRAGMA(x) _Pragma(#x)
#define CONSTANT_0_1_RM(v, rm) ([](){ PRAGMA(STDC FENV_ROUND rm); return v; }())

#pragma STDC FENV_ROUND FE_UPWARD
float C2_rd = CONSTANT_0_1_RM(0.1F, FE_DOWNWARD);
float C2_ru = CONSTANT_0_1_RM(0.1F, FE_UPWARD);
// CHECK: @C2_rd = {{.*}} float 0x3FB9999980000000
// CHECK: @C2_ru = {{.*}} float 0x3FB99999A0000000

#pragma STDC FENV_ROUND FE_DOWNWARD
float C3_rd = CONSTANT_0_1_RM(0.1F, FE_DOWNWARD);
float C3_ru = CONSTANT_0_1_RM(0.1F, FE_UPWARD);
// CHECK: @C3_rd = {{.*}} float 0x3FB9999980000000
// CHECK: @C3_ru = {{.*}} float 0x3FB99999A0000000

// Check literals in template instantiations.

#pragma STDC FENV_ROUND FE_DYNAMIC

template<typename T, T C>
constexpr T foo() {
return C;
}

#pragma STDC FENV_ROUND FE_DOWNWARD
float var_d = foo<float, 0.1F>();
// CHECK: @var_d = {{.*}} float 0x3FB9999980000000

#pragma STDC FENV_ROUND FE_UPWARD
float var_u = foo<float, 0.1F>();
// CHECK: @var_u = {{.*}} float 0x3FB99999A0000000

#pragma STDC FENV_ROUND FE_DYNAMIC

template<typename T, T f> void foo2() {
T Val = f;
}

void func_01() {
#pragma STDC FENV_ROUND FE_DOWNWARD
foo2<float, 0.1f>();
}

void func_02() {
#pragma STDC FENV_ROUND FE_UPWARD
foo2<float, 0.1f>();
}

// CHECK-LABEL: define {{.*}} void @_Z4foo2IfTnT_Lf3dccccccEEvv()
// CHECK: store float 0x3FB9999980000000, ptr

// CHECK-LABEL: define {{.*}} void @_Z4foo2IfTnT_Lf3dcccccdEEvv()
// CHECK: store float 0x3FB99999A0000000, ptr


#pragma STDC FENV_ROUND FE_DOWNWARD
template <int C>
float tfunc_01() {
return 0.1F; // Must be 0x3FB9999980000000 in all instantiations.
}
template float tfunc_01<0>();
// CHECK-LABEL: define {{.*}} float @_Z8tfunc_01ILi0EEfv()
// CHECK: ret float 0x3FB9999980000000

#pragma STDC FENV_ROUND FE_UPWARD
template float tfunc_01<1>();
// CHECK-LABEL: define {{.*}} float @_Z8tfunc_01ILi1EEfv()
// CHECK: ret float 0x3FB9999980000000

template<> float tfunc_01<2>() {
return 0.1F;
}
// CHECK-LABEL: define {{.*}} float @_Z8tfunc_01ILi2EEfv()
// CHECK: ret float 0x3FB99999A0000000
7 changes: 5 additions & 2 deletions clang/test/CodeGen/array-init.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,8 @@ void testConstArrayInits(void)
// CHECK: @big_char ={{.*}} global <{ i8, [4294967295 x i8] }> <{ i8 1, [4294967295 x i8] zeroinitializer }>
char big_char[4294967296] = {1};

// CHECK: @big_int ={{.*}} global <{ i32, [2147483647 x i32] }> <{ i32 1, [2147483647 x i32] zeroinitializer }>
int big_int[0x200000000 >> 2] = {1};
// CHECK: @big_char2 ={{.*}} global <{ i8, i8, [4294967296 x i8] }> <{ i8 1, i8 2, [4294967296 x i8] zeroinitializer }>
char big_char2[4294967298] = {1, 2};

// CHECK: @big_int ={{.*}} global <{ i32, i32, i32, [2147483647 x i32] }> <{ i32 1, i32 2, i32 3, [2147483645 x i32] zeroinitializer }>
int big_int[0x200000000 >> 2] = {1, 2, 3};
10 changes: 5 additions & 5 deletions clang/test/SemaCXX/cxx20-ctad-type-alias.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %clang_cc1 -fsyntax-only -Wno-c++11-narrowing -Wno-literal-conversion -std=c++20 -verify %s
// RUN: %clang_cc1 -fsyntax-only -triple x86_64-unknown-linux -Wno-c++11-narrowing -Wno-literal-conversion -std=c++20 -verify %s

namespace test1 {
template <typename T>
Expand Down Expand Up @@ -74,7 +74,7 @@ struct Foo {
template <typename T>
using AF = Foo<T, 1>;

AF b{0};
AF b{0};
} // namespace test6

namespace test7 {
Expand All @@ -86,8 +86,8 @@ struct Foo {
template <typename U>
using AF1 = Foo<U>;
template <typename K>
using AF2 = AF1<K>;
AF2 b = 1;
using AF2 = AF1<K>;
AF2 b = 1;
} // namespace test7

namespace test8 {
Expand Down Expand Up @@ -149,7 +149,7 @@ namespace test12 {
template<typename X>
struct Foo {
template<typename K>
struct Bar {
struct Bar {
Bar(K);
};

Expand Down
15 changes: 3 additions & 12 deletions clang/test/SemaTemplate/cwg2398.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,25 +62,19 @@ namespace templ {
namespace type_pack1 {
template<class T2> struct A;
template<template<class ...T3s> class TT1, class T4> struct A<TT1<T4>> ;
// new-note@-1 {{partial specialization matches}}
template<template<class T5 > class TT2, class T6> struct A<TT2<T6>> {};
// new-note@-1 {{partial specialization matches}}

template<class T1> struct B;
template struct A<B<char>>;
// new-error@-1 {{ambiguous partial specialization}}
} // namespace type_pack1

namespace type_pack2 {
template<class T2> struct A;
template<template<class ...T3s> class TT1, class ...T4> struct A<TT1<T4...>> ;
// new-note@-1 {{partial specialization matches}}
template<template<class T5 > class TT2, class ...T6> struct A<TT2<T6...>> {};
// new-note@-1 {{partial specialization matches}}

template<class T1> struct B;
template struct A<B<char>>;
// new-error@-1 {{ambiguous partial specialization}}
} // namespace type_pack2

namespace type_pack3 {
Expand Down Expand Up @@ -140,13 +134,10 @@ namespace ttp_defaults {

namespace ttp_only {
template <template <class... > class TT1> struct A { static constexpr int V = 0; };
// new-note@-1 2{{template is declared here}}
template <template <class > class TT2> struct A<TT2> { static constexpr int V = 1; };
// new-error@-1 {{not more specialized than the primary template}}
// new-note@-2 {{partial specialization matches}}
// new-note@-1 {{partial specialization matches}}
template <template <class, class> class TT3> struct A<TT3> { static constexpr int V = 2; };
// new-error@-1 {{not more specialized than the primary template}}
// new-note@-2 {{partial specialization matches}}
// new-note@-1 {{partial specialization matches}}

template <class ... > struct B;
template <class > struct C;
Expand Down Expand Up @@ -193,5 +184,5 @@ namespace consistency {

template struct A<B<int>, B<int>, B<int>>;
// new-error@-1 {{ambiguous partial specializations}}
} // namespace t1
} // namespace t2
} // namespace consistency
11 changes: 11 additions & 0 deletions clang/unittests/Format/FormatTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10539,6 +10539,17 @@ TEST_F(FormatTest, KeepStringLabelValuePairsOnALine) {
" bbbbbbbbbbbbbbbbbbbbbbb);");
}

TEST_F(FormatTest, WrapBeforeInsertionOperatorbetweenStringLiterals) {
verifyFormat("QStringList() << \"foo\" << \"bar\";");

verifyNoChange("QStringList() << \"foo\"\n"
" << \"bar\";");

verifyFormat("log_error(log, \"foo\" << \"bar\");",
"log_error(log, \"foo\"\n"
" << \"bar\");");
}

TEST_F(FormatTest, UnderstandsEquals) {
verifyFormat(
"aaaaaaaaaaaaaaaaa =\n"
Expand Down
5 changes: 5 additions & 0 deletions clang/unittests/Format/TokenAnnotatorTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2903,6 +2903,11 @@ TEST_F(TokenAnnotatorTest, BraceKind) {
EXPECT_BRACE_KIND(Tokens[5], BK_Block);
EXPECT_BRACE_KIND(Tokens[6], BK_Block);

Tokens = annotate("struct Foo<int> : Base {};");
ASSERT_EQ(Tokens.size(), 11u) << Tokens;
EXPECT_BRACE_KIND(Tokens[7], BK_Block);
EXPECT_BRACE_KIND(Tokens[8], BK_Block);

Tokens = annotate("struct Foo final {};");
ASSERT_EQ(Tokens.size(), 7u) << Tokens;
EXPECT_BRACE_KIND(Tokens[3], BK_Block);
Expand Down
3 changes: 3 additions & 0 deletions flang/lib/Lower/DirectivesCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,9 @@ static inline void genOmpAccAtomicWriteStatement(
// Generate `atomic.write` operation for atomic assignment statements
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();

mlir::Type varType = fir::unwrapRefType(lhsAddr.getType());
rhsExpr = firOpBuilder.createConvert(loc, varType, rhsExpr);

if constexpr (std::is_same<AtomicListT,
Fortran::parser::OmpAtomicClauseList>()) {
// If no hint clause is specified, the effect is as if
Expand Down
14 changes: 14 additions & 0 deletions flang/test/Lower/OpenMP/atomic-write.f90
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,17 @@ subroutine atomic_write_typed_assign
!$omp atomic write
r2 = 0
end subroutine

!CHECK-LABEL: func.func @_QPatomic_write_logical()
!CHECK: %[[L_REF:.*]] = fir.alloca !fir.logical<4> {bindc_name = "l", uniq_name = "_QFatomic_write_logicalEl"}
!CHECK: %[[L_DECL:.*]]:2 = hlfir.declare %[[L_REF]] {uniq_name = "_QFatomic_write_logicalEl"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>)
!CHECK: %true = arith.constant true
!CHECK: %[[CVT:.*]] = fir.convert %true : (i1) -> !fir.logical<4>
!CHECK: omp.atomic.write %[[L_DECL]]#1 = %[[CVT]] : !fir.ref<!fir.logical<4>>, !fir.logical<4>

subroutine atomic_write_logical
logical :: l
!$omp atomic write
l = .true.
!$omp end atomic
end
4 changes: 2 additions & 2 deletions lldb/source/Commands/CommandObjectThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,14 +151,14 @@ class CommandObjectThreadBacktrace : public CommandObjectIterateOverThreads {

for (size_t idx = 0; idx < num_entries; idx++) {
llvm::StringRef arg_string = copy_args[idx].ref();
if (arg_string.equals("-c") || count_opt.starts_with(arg_string)) {
if (arg_string == "-c" || count_opt.starts_with(arg_string)) {
idx++;
if (idx == num_entries)
return std::nullopt;
count_idx = idx;
if (copy_args[idx].ref().getAsInteger(0, count_val))
return std::nullopt;
} else if (arg_string.equals("-s") || start_opt.starts_with(arg_string)) {
} else if (arg_string == "-s" || start_opt.starts_with(arg_string)) {
idx++;
if (idx == num_entries)
return std::nullopt;
Expand Down
12 changes: 6 additions & 6 deletions lldb/source/Core/FormatEntity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1921,7 +1921,7 @@ static Status ParseEntry(const llvm::StringRef &format_str,
const size_t n = parent->num_children;
for (size_t i = 0; i < n; ++i) {
const Definition *entry_def = parent->children + i;
if (key.equals(entry_def->name) || entry_def->name[0] == '*') {
if (key == entry_def->name || entry_def->name[0] == '*') {
llvm::StringRef value;
if (sep_char)
value =
Expand Down Expand Up @@ -2002,7 +2002,7 @@ static const Definition *FindEntry(const llvm::StringRef &format_str,
const size_t n = parent->num_children;
for (size_t i = 0; i < n; ++i) {
const Definition *entry_def = parent->children + i;
if (p.first.equals(entry_def->name) || entry_def->name[0] == '*') {
if (p.first == entry_def->name || entry_def->name[0] == '*') {
if (p.second.empty()) {
if (format_str.back() == '.')
remainder = format_str.drop_front(format_str.size() - 1);
Expand Down Expand Up @@ -2351,13 +2351,13 @@ Status FormatEntity::ExtractVariableInfo(llvm::StringRef &format_str,
bool FormatEntity::FormatFileSpec(const FileSpec &file_spec, Stream &s,
llvm::StringRef variable_name,
llvm::StringRef variable_format) {
if (variable_name.empty() || variable_name.equals(".fullpath")) {
if (variable_name.empty() || variable_name == ".fullpath") {
file_spec.Dump(s.AsRawOstream());
return true;
} else if (variable_name.equals(".basename")) {
} else if (variable_name == ".basename") {
s.PutCString(file_spec.GetFilename().GetStringRef());
return true;
} else if (variable_name.equals(".dirname")) {
} else if (variable_name == ".dirname") {
s.PutCString(file_spec.GetFilename().GetStringRef());
return true;
}
Expand Down Expand Up @@ -2440,7 +2440,7 @@ void FormatEntity::AutoComplete(CompletionRequest &request) {
// "${thread.id" <TAB>
request.AddCompletion(MakeMatch(str, "}"));
}
} else if (remainder.equals(".")) {
} else if (remainder == ".") {
// "${thread." <TAB>
StringList new_matches;
AddMatches(entry_def, str, llvm::StringRef(), new_matches);
Expand Down
34 changes: 17 additions & 17 deletions lldb/source/Expression/IRExecutionUnit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -534,63 +534,63 @@ lldb::SectionType IRExecutionUnit::GetSectionTypeFromSectionName(
}

if (!name.empty()) {
if (name.equals("__text") || name.equals(".text"))
if (name == "__text" || name == ".text")
sect_type = lldb::eSectionTypeCode;
else if (name.equals("__data") || name.equals(".data"))
else if (name == "__data" || name == ".data")
sect_type = lldb::eSectionTypeCode;
else if (name.starts_with("__debug_") || name.starts_with(".debug_")) {
const uint32_t name_idx = name[0] == '_' ? 8 : 7;
llvm::StringRef dwarf_name(name.substr(name_idx));
switch (dwarf_name[0]) {
case 'a':
if (dwarf_name.equals("abbrev"))
if (dwarf_name == "abbrev")
sect_type = lldb::eSectionTypeDWARFDebugAbbrev;
else if (dwarf_name.equals("aranges"))
else if (dwarf_name == "aranges")
sect_type = lldb::eSectionTypeDWARFDebugAranges;
else if (dwarf_name.equals("addr"))
else if (dwarf_name == "addr")
sect_type = lldb::eSectionTypeDWARFDebugAddr;
break;

case 'f':
if (dwarf_name.equals("frame"))
if (dwarf_name == "frame")
sect_type = lldb::eSectionTypeDWARFDebugFrame;
break;

case 'i':
if (dwarf_name.equals("info"))
if (dwarf_name == "info")
sect_type = lldb::eSectionTypeDWARFDebugInfo;
break;

case 'l':
if (dwarf_name.equals("line"))
if (dwarf_name == "line")
sect_type = lldb::eSectionTypeDWARFDebugLine;
else if (dwarf_name.equals("loc"))
else if (dwarf_name == "loc")
sect_type = lldb::eSectionTypeDWARFDebugLoc;
else if (dwarf_name.equals("loclists"))
else if (dwarf_name == "loclists")
sect_type = lldb::eSectionTypeDWARFDebugLocLists;
break;

case 'm':
if (dwarf_name.equals("macinfo"))
if (dwarf_name == "macinfo")
sect_type = lldb::eSectionTypeDWARFDebugMacInfo;
break;

case 'p':
if (dwarf_name.equals("pubnames"))
if (dwarf_name == "pubnames")
sect_type = lldb::eSectionTypeDWARFDebugPubNames;
else if (dwarf_name.equals("pubtypes"))
else if (dwarf_name == "pubtypes")
sect_type = lldb::eSectionTypeDWARFDebugPubTypes;
break;

case 's':
if (dwarf_name.equals("str"))
if (dwarf_name == "str")
sect_type = lldb::eSectionTypeDWARFDebugStr;
else if (dwarf_name.equals("str_offsets"))
else if (dwarf_name == "str_offsets")
sect_type = lldb::eSectionTypeDWARFDebugStrOffsets;
break;

case 'r':
if (dwarf_name.equals("ranges"))
if (dwarf_name == "ranges")
sect_type = lldb::eSectionTypeDWARFDebugRanges;
break;

Expand All @@ -599,7 +599,7 @@ lldb::SectionType IRExecutionUnit::GetSectionTypeFromSectionName(
}
} else if (name.starts_with("__apple_") || name.starts_with(".apple_"))
sect_type = lldb::eSectionTypeInvalid;
else if (name.equals("__objc_imageinfo"))
else if (name == "__objc_imageinfo")
sect_type = lldb::eSectionTypeOther;
}
return sect_type;
Expand Down
8 changes: 4 additions & 4 deletions lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1449,7 +1449,7 @@ bool IRForTarget::ReplaceVariables(Function &llvm_function) {

Argument *argument = &*iter;

if (argument->getName().equals("this")) {
if (argument->getName() == "this") {
++iter;

if (iter == llvm_function.arg_end()) {
Expand All @@ -1461,7 +1461,7 @@ bool IRForTarget::ReplaceVariables(Function &llvm_function) {
}

argument = &*iter;
} else if (argument->getName().equals("self")) {
} else if (argument->getName() == "self") {
++iter;

if (iter == llvm_function.arg_end()) {
Expand All @@ -1472,7 +1472,7 @@ bool IRForTarget::ReplaceVariables(Function &llvm_function) {
return false;
}

if (!iter->getName().equals("_cmd")) {
if (iter->getName() != "_cmd") {
m_error_stream.Format("Internal error [IRForTarget]: Wrapper takes '{0}' "
"after 'self' argument (should take '_cmd')",
iter->getName());
Expand All @@ -1493,7 +1493,7 @@ bool IRForTarget::ReplaceVariables(Function &llvm_function) {
argument = &*iter;
}

if (!argument->getName().equals("$__lldb_arg")) {
if (argument->getName() != "$__lldb_arg") {
m_error_stream.Format("Internal error [IRForTarget]: Wrapper takes an "
"argument named '{0}' instead of the struct pointer",
argument->getName());
Expand Down
2 changes: 1 addition & 1 deletion lldb/source/Plugins/Language/ObjC/Cocoa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -802,7 +802,7 @@ bool lldb_private::formatters::NSURLSummaryProvider(

llvm::StringRef class_name = descriptor->GetClassName().GetStringRef();

if (!class_name.equals("NSURL"))
if (class_name != "NSURL")
return false;

uint64_t offset_text = ptr_size + ptr_size +
Expand Down
2 changes: 1 addition & 1 deletion lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3557,7 +3557,7 @@ ObjectFile::Strata ObjectFileELF::CalculateStrata() {
// decrease by one
llvm::StringRef loader_name(buffer, read_size - 1);
llvm::StringRef freebsd_kernel_loader_name("/red/herring");
if (loader_name.equals(freebsd_kernel_loader_name))
if (loader_name == freebsd_kernel_loader_name)
return eStrataKernel;
}
}
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -340,13 +340,13 @@ GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo(
llvm::StringRef value;
while (packet.GetNameColonValue(key, value)) {
bool success = true;
if (key.equals("name")) {
if (key == "name") {
StringExtractor extractor(value);
std::string file;
extractor.GetHexByteString(file);
match_info.GetProcessInfo().GetExecutableFile().SetFile(
file, FileSpec::Style::native);
} else if (key.equals("name_match")) {
} else if (key == "name_match") {
NameMatch name_match = llvm::StringSwitch<NameMatch>(value)
.Case("equals", NameMatch::Equals)
.Case("starts_with", NameMatch::StartsWith)
Expand All @@ -357,40 +357,40 @@ GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo(
match_info.SetNameMatchType(name_match);
if (name_match == NameMatch::Ignore)
return SendErrorResponse(2);
} else if (key.equals("pid")) {
} else if (key == "pid") {
lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
if (value.getAsInteger(0, pid))
return SendErrorResponse(2);
match_info.GetProcessInfo().SetProcessID(pid);
} else if (key.equals("parent_pid")) {
} else if (key == "parent_pid") {
lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
if (value.getAsInteger(0, pid))
return SendErrorResponse(2);
match_info.GetProcessInfo().SetParentProcessID(pid);
} else if (key.equals("uid")) {
} else if (key == "uid") {
uint32_t uid = UINT32_MAX;
if (value.getAsInteger(0, uid))
return SendErrorResponse(2);
match_info.GetProcessInfo().SetUserID(uid);
} else if (key.equals("gid")) {
} else if (key == "gid") {
uint32_t gid = UINT32_MAX;
if (value.getAsInteger(0, gid))
return SendErrorResponse(2);
match_info.GetProcessInfo().SetGroupID(gid);
} else if (key.equals("euid")) {
} else if (key == "euid") {
uint32_t uid = UINT32_MAX;
if (value.getAsInteger(0, uid))
return SendErrorResponse(2);
match_info.GetProcessInfo().SetEffectiveUserID(uid);
} else if (key.equals("egid")) {
} else if (key == "egid") {
uint32_t gid = UINT32_MAX;
if (value.getAsInteger(0, gid))
return SendErrorResponse(2);
match_info.GetProcessInfo().SetEffectiveGroupID(gid);
} else if (key.equals("all_users")) {
} else if (key == "all_users") {
match_info.SetMatchAllUsers(
OptionArgParser::ToBoolean(value, false, &success));
} else if (key.equals("triple")) {
} else if (key == "triple") {
match_info.GetProcessInfo().GetArchitecture() =
HostInfo::GetAugmentedArchSpec(value);
} else {
Expand Down Expand Up @@ -472,7 +472,7 @@ GDBRemoteCommunicationServerCommon::Handle_qSpeedTest(
llvm::StringRef key;
llvm::StringRef value;
bool success = packet.GetNameColonValue(key, value);
if (success && key.equals("response_size")) {
if (success && key == "response_size") {
uint32_t response_size = 0;
if (!value.getAsInteger(0, response_size)) {
if (response_size == 0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -239,9 +239,9 @@ GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer(
llvm::StringRef value;
std::optional<uint16_t> port;
while (packet.GetNameColonValue(name, value)) {
if (name.equals("host"))
if (name == "host")
hostname = std::string(value);
else if (name.equals("port")) {
else if (name == "port") {
// Make the Optional valid so we can use its value
port = 0;
value.getAsInteger(0, *port);
Expand Down
26 changes: 13 additions & 13 deletions lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -448,20 +448,20 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) {
DynamicRegisterInfo::Register reg_info;

while (response.GetNameColonValue(name, value)) {
if (name.equals("name")) {
if (name == "name") {
reg_info.name.SetString(value);
} else if (name.equals("alt-name")) {
} else if (name == "alt-name") {
reg_info.alt_name.SetString(value);
} else if (name.equals("bitsize")) {
} else if (name == "bitsize") {
if (!value.getAsInteger(0, reg_info.byte_size))
reg_info.byte_size /= CHAR_BIT;
} else if (name.equals("offset")) {
} else if (name == "offset") {
value.getAsInteger(0, reg_info.byte_offset);
} else if (name.equals("encoding")) {
} else if (name == "encoding") {
const Encoding encoding = Args::StringToEncoding(value);
if (encoding != eEncodingInvalid)
reg_info.encoding = encoding;
} else if (name.equals("format")) {
} else if (name == "format") {
if (!OptionArgParser::ToFormat(value.str().c_str(), reg_info.format, nullptr)
.Success())
reg_info.format =
Expand All @@ -480,17 +480,17 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) {
.Case("vector-uint64", eFormatVectorOfUInt64)
.Case("vector-uint128", eFormatVectorOfUInt128)
.Default(eFormatInvalid);
} else if (name.equals("set")) {
} else if (name == "set") {
reg_info.set_name.SetString(value);
} else if (name.equals("gcc") || name.equals("ehframe")) {
} else if (name == "gcc" || name == "ehframe") {
value.getAsInteger(0, reg_info.regnum_ehframe);
} else if (name.equals("dwarf")) {
} else if (name == "dwarf") {
value.getAsInteger(0, reg_info.regnum_dwarf);
} else if (name.equals("generic")) {
} else if (name == "generic") {
reg_info.regnum_generic = Args::StringToGenericRegister(value);
} else if (name.equals("container-regs")) {
} else if (name == "container-regs") {
SplitCommaSeparatedRegisterNumberString(value, reg_info.value_regs, 16);
} else if (name.equals("invalidate-regs")) {
} else if (name == "invalidate-regs") {
SplitCommaSeparatedRegisterNumberString(value, reg_info.invalidate_regs, 16);
}
}
Expand Down Expand Up @@ -5082,7 +5082,7 @@ std::string ProcessGDBRemote::HarmonizeThreadIdsForProfileData(
llvm::StringRef usec_name, usec_value;
uint32_t input_file_pos = profileDataExtractor.GetFilePos();
if (profileDataExtractor.GetNameColonValue(usec_name, usec_value)) {
if (usec_name.equals("thread_used_usec")) {
if (usec_name == "thread_used_usec") {
has_used_usec = true;
usec_value.getAsInteger(0, curr_used_usec);
} else {
Expand Down
2 changes: 1 addition & 1 deletion lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1139,7 +1139,7 @@ PDBASTParser::FindNamespaceDecl(const clang::DeclContext *parent,
assert(set);

for (clang::NamespaceDecl *namespace_decl : *set)
if (namespace_decl->getName().equals(name))
if (namespace_decl->getName() == name)
return namespace_decl;

for (clang::NamespaceDecl *namespace_decl : *set)
Expand Down
4 changes: 2 additions & 2 deletions lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1141,8 +1141,8 @@ void SymbolFilePDB::FindGlobalVariables(
sc.module_sp = m_objfile_sp->GetModule();
lldbassert(sc.module_sp.get());

if (!name.GetStringRef().equals(
MSVCUndecoratedNameParser::DropScope(pdb_data->getName())))
if (name.GetStringRef() !=
MSVCUndecoratedNameParser::DropScope(pdb_data->getName()))
continue;

sc.comp_unit = ParseCompileUnitForUID(GetCompilandId(*pdb_data)).get();
Expand Down
17 changes: 8 additions & 9 deletions lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6692,7 +6692,7 @@ size_t TypeSystemClang::GetIndexOfChildMemberWithName(
return child_indexes.size();
child_indexes.pop_back();

} else if (field_name.equals(name)) {
} else if (field_name == name) {
// We have to add on the number of base classes to this index!
child_indexes.push_back(
child_idx + TypeSystemClang::GetNumBaseClasses(
Expand Down Expand Up @@ -6779,7 +6779,7 @@ size_t TypeSystemClang::GetIndexOfChildMemberWithName(
ivar_pos != ivar_end; ++ivar_pos, ++child_idx) {
const clang::ObjCIvarDecl *ivar_decl = *ivar_pos;

if (ivar_decl->getName().equals(name_sref)) {
if (ivar_decl->getName() == name_sref) {
if ((!omit_empty_base_classes && superclass_interface_decl) ||
(omit_empty_base_classes &&
ObjCDeclHasIVars(superclass_interface_decl, true)))
Expand Down Expand Up @@ -6948,7 +6948,7 @@ TypeSystemClang::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type,
for (field = record_decl->field_begin(),
field_end = record_decl->field_end();
field != field_end; ++field, ++child_idx) {
if (field->getName().equals(name))
if (field->getName() == name)
return child_idx;
}
}
Expand All @@ -6975,7 +6975,7 @@ TypeSystemClang::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type,
ivar_pos != ivar_end; ++ivar_pos, ++child_idx) {
const clang::ObjCIvarDecl *ivar_decl = *ivar_pos;

if (ivar_decl->getName().equals(name)) {
if (ivar_decl->getName() == name) {
if ((!omit_empty_base_classes && superclass_interface_decl) ||
(omit_empty_base_classes &&
ObjCDeclHasIVars(superclass_interface_decl, true)))
Expand All @@ -6986,7 +6986,7 @@ TypeSystemClang::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type,
}

if (superclass_interface_decl) {
if (superclass_interface_decl->getName().equals(name))
if (superclass_interface_decl->getName() == name)
return 0;
}
}
Expand Down Expand Up @@ -9231,15 +9231,14 @@ std::vector<CompilerDecl> TypeSystemClang::DeclContextFindDeclByName(
if (clang::NamedDecl *nd =
llvm::dyn_cast<clang::NamedDecl>(target)) {
IdentifierInfo *ii = nd->getIdentifier();
if (ii != nullptr &&
ii->getName().equals(name.AsCString(nullptr)))
if (ii != nullptr && ii->getName() == name.AsCString(nullptr))
found_decls.push_back(GetCompilerDecl(nd));
}
}
} else if (clang::NamedDecl *nd =
llvm::dyn_cast<clang::NamedDecl>(child)) {
IdentifierInfo *ii = nd->getIdentifier();
if (ii != nullptr && ii->getName().equals(name.AsCString(nullptr)))
if (ii != nullptr && ii->getName() == name.AsCString(nullptr))
found_decls.push_back(GetCompilerDecl(nd));
}
}
Expand Down Expand Up @@ -9349,7 +9348,7 @@ uint32_t TypeSystemClang::CountDeclLevels(clang::DeclContext *frame_decl_ctx,
// Check names.
IdentifierInfo *ii = nd->getIdentifier();
if (ii == nullptr ||
!ii->getName().equals(child_name->AsCString(nullptr)))
ii->getName() != child_name->AsCString(nullptr))
continue;
// Check types, if one was provided.
if (child_type) {
Expand Down
4 changes: 2 additions & 2 deletions lldb/source/Target/PathMappingList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ bool PathMappingList::AppendUnique(llvm::StringRef path,
auto normalized_replacement = NormalizePath(replacement);
std::lock_guard<std::recursive_mutex> lock(m_mutex);
for (const auto &pair : m_pairs) {
if (pair.first.GetStringRef().equals(normalized_path) &&
pair.second.GetStringRef().equals(normalized_replacement))
if (pair.first.GetStringRef() == normalized_path &&
pair.second.GetStringRef() == normalized_replacement)
return false;
}
Append(path, replacement, notify);
Expand Down
22 changes: 16 additions & 6 deletions llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,14 @@ enum EdgeKind_aarch64 : Edge::Kind {
///
/// Fixup expression:
///
/// Fixup <- (Target - Fixup) >> 2 : int19
/// Fixup <- (Target - Fixup + Addend) >> 2 : int19
///
/// Notes:
/// The '19' in the name refers to the number operand bits and follows the
/// naming convention used by the corresponding ELF relocation.
/// Since the low two bits must be zero (because of the 32-bit alignment of
/// the target) the operand is effectively a signed 21-bit number.
///
///
/// Errors:
/// - The result of the unshifted part of the fixup expression must be
Expand Down Expand Up @@ -377,6 +384,11 @@ inline bool isADR(uint32_t Instr) {
return (Instr & ADRMask) == 0x10000000;
}

inline bool isLDRLiteral(uint32_t Instr) {
constexpr uint32_t LDRLitMask = 0x3b000000;
return (Instr & LDRLitMask) == 0x18000000;
}

// Returns the amount the address operand of LD/ST (imm12)
// should be shifted right by.
//
Expand Down Expand Up @@ -494,16 +506,14 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E) {
}
case LDRLiteral19: {
assert((FixupAddress.getValue() & 0x3) == 0 && "LDR is not 32-bit aligned");
assert(E.getAddend() == 0 && "LDRLiteral19 with non-zero addend");
uint32_t RawInstr = *(ulittle32_t *)FixupPtr;
assert(RawInstr == 0x58000010 && "RawInstr isn't a 64-bit LDR literal");
int64_t Delta = E.getTarget().getAddress() - FixupAddress;
assert(isLDRLiteral(RawInstr) && "RawInstr is not an LDR Literal");
int64_t Delta = E.getTarget().getAddress() + E.getAddend() - FixupAddress;
if (Delta & 0x3)
return make_error<JITLinkError>("LDR literal target is not 32-bit "
"aligned");
if (Delta < -(1 << 20) || Delta > ((1 << 20) - 1))
if (!isInt<21>(Delta))
return makeTargetOutOfRangeError(G, B, E);

uint32_t EncodedImm = ((static_cast<uint32_t>(Delta) >> 2) & 0x7ffff) << 5;
uint32_t FixedInstr = RawInstr | EncodedImm;
*(ulittle32_t *)FixupPtr = FixedInstr;
Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm/TableGen/Record.h
Original file line number Diff line number Diff line change
Expand Up @@ -2098,7 +2098,7 @@ class RecordKeeper {
/// Sorting predicate to sort record pointers by name.
struct LessRecord {
bool operator()(const Record *Rec1, const Record *Rec2) const {
return StringRef(Rec1->getName()).compare_numeric(Rec2->getName()) < 0;
return Rec1->getName().compare_numeric(Rec2->getName()) < 0;
}
};

Expand Down
42 changes: 29 additions & 13 deletions llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,12 @@ extern cl::opt<unsigned> MaxNumVTableAnnotations;
// global vars at all. When importing function we aren't interested if any
// instruction in it takes an address of any basic block, because instruction
// can only take an address of basic block located in the same function.
// Set `RefLocalLinkageIFunc` to true if the analyzed value references a
// local-linkage ifunc.
static bool findRefEdges(ModuleSummaryIndex &Index, const User *CurUser,
SetVector<ValueInfo, std::vector<ValueInfo>> &RefEdges,
SmallPtrSet<const User *, 8> &Visited) {
SmallPtrSet<const User *, 8> &Visited,
bool &RefLocalLinkageIFunc) {
bool HasBlockAddress = false;
SmallVector<const User *, 32> Worklist;
if (Visited.insert(CurUser).second)
Expand All @@ -119,8 +122,18 @@ static bool findRefEdges(ModuleSummaryIndex &Index, const User *CurUser,
// We have a reference to a global value. This should be added to
// the reference set unless it is a callee. Callees are handled
// specially by WriteFunction and are added to a separate list.
if (!(CB && CB->isCallee(&OI)))
if (!(CB && CB->isCallee(&OI))) {
// If an ifunc has local linkage, do not add it into ref edges, and
// sets `RefLocalLinkageIFunc` to true. The referencer is not eligible
// for import. An ifunc doesn't have summary and ThinLTO cannot
// promote it; importing the referencer may cause linkage errors.
if (auto *GI = dyn_cast_if_present<GlobalIFunc>(GV);
GI && GI->hasLocalLinkage()) {
RefLocalLinkageIFunc = true;
continue;
}
RefEdges.insert(Index.getOrInsertValueInfo(GV));
}
continue;
}
if (Visited.insert(Operand).second)
Expand Down Expand Up @@ -313,7 +326,8 @@ static void computeFunctionSummary(

// Add personality function, prefix data and prologue data to function's ref
// list.
findRefEdges(Index, &F, RefEdges, Visited);
bool HasLocalIFuncCallOrRef = false;
findRefEdges(Index, &F, RefEdges, Visited, HasLocalIFuncCallOrRef);
std::vector<const Instruction *> NonVolatileLoads;
std::vector<const Instruction *> NonVolatileStores;

Expand All @@ -326,7 +340,6 @@ static void computeFunctionSummary(

bool HasInlineAsmMaybeReferencingInternal = false;
bool HasIndirBranchToBlockAddress = false;
bool HasIFuncCall = false;
bool HasUnknownCall = false;
bool MayThrow = false;
for (const BasicBlock &BB : F) {
Expand Down Expand Up @@ -372,11 +385,11 @@ static void computeFunctionSummary(
// of calling it we should add GV to RefEdges directly.
RefEdges.insert(Index.getOrInsertValueInfo(GV));
else if (auto *U = dyn_cast<User>(Stored))
findRefEdges(Index, U, RefEdges, Visited);
findRefEdges(Index, U, RefEdges, Visited, HasLocalIFuncCallOrRef);
continue;
}
}
findRefEdges(Index, &I, RefEdges, Visited);
findRefEdges(Index, &I, RefEdges, Visited, HasLocalIFuncCallOrRef);
const auto *CB = dyn_cast<CallBase>(&I);
if (!CB) {
if (I.mayThrow())
Expand Down Expand Up @@ -450,7 +463,7 @@ static void computeFunctionSummary(
// Non-local ifunc is not cloned and does not have the issue.
if (auto *GI = dyn_cast_if_present<GlobalIFunc>(CalledValue))
if (GI->hasLocalLinkage())
HasIFuncCall = true;
HasLocalIFuncCallOrRef = true;
// Skip inline assembly calls.
if (CI && CI->isInlineAsm())
continue;
Expand Down Expand Up @@ -555,7 +568,7 @@ static void computeFunctionSummary(
SmallPtrSet<const User *, 8> &Cache) {
for (const auto *I : Instrs) {
Cache.erase(I);
findRefEdges(Index, I, Edges, Cache);
findRefEdges(Index, I, Edges, Cache, HasLocalIFuncCallOrRef);
}
};

Expand Down Expand Up @@ -631,9 +644,9 @@ static void computeFunctionSummary(
#endif

bool NonRenamableLocal = isNonRenamableLocal(F);
bool NotEligibleForImport = NonRenamableLocal ||
HasInlineAsmMaybeReferencingInternal ||
HasIndirBranchToBlockAddress || HasIFuncCall;
bool NotEligibleForImport =
NonRenamableLocal || HasInlineAsmMaybeReferencingInternal ||
HasIndirBranchToBlockAddress || HasLocalIFuncCallOrRef;
GlobalValueSummary::GVFlags Flags(
F.getLinkage(), F.getVisibility(), NotEligibleForImport,
/* Live = */ false, F.isDSOLocal(), F.canBeOmittedFromSymbolTable(),
Expand Down Expand Up @@ -787,7 +800,10 @@ static void computeVariableSummary(ModuleSummaryIndex &Index,
SmallVectorImpl<MDNode *> &Types) {
SetVector<ValueInfo, std::vector<ValueInfo>> RefEdges;
SmallPtrSet<const User *, 8> Visited;
bool HasBlockAddress = findRefEdges(Index, &V, RefEdges, Visited);
bool RefLocalIFunc = false;
bool HasBlockAddress =
findRefEdges(Index, &V, RefEdges, Visited, RefLocalIFunc);
const bool NotEligibleForImport = (HasBlockAddress || RefLocalIFunc);
bool NonRenamableLocal = isNonRenamableLocal(V);
GlobalValueSummary::GVFlags Flags(
V.getLinkage(), V.getVisibility(), NonRenamableLocal,
Expand Down Expand Up @@ -821,7 +837,7 @@ static void computeVariableSummary(ModuleSummaryIndex &Index,
RefEdges.takeVector());
if (NonRenamableLocal)
CantBePromoted.insert(V.getGUID());
if (HasBlockAddress)
if (NotEligibleForImport)
GVarSummary->setNotEligibleToImport();
if (!VTableFuncs.empty())
GVarSummary->setVTableFuncs(VTableFuncs);
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ Error BasicBlockSectionsProfileReader::ReadV1Profile() {
return false;
// Return a match if debug-info-filename is not specified. Otherwise,
// check for equality.
return DIFilename.empty() || It->second.equals(DIFilename);
return DIFilename.empty() || It->second == DIFilename;
});
if (!FunctionFound) {
// Skip the following profile by setting the profile iterator (FI) to
Expand Down Expand Up @@ -317,7 +317,7 @@ Error BasicBlockSectionsProfileReader::ReadV0Profile() {
return false;
// Return a match if debug-info-filename is not specified. Otherwise,
// check for equality.
return DIFilename.empty() || It->second.equals(DIFilename);
return DIFilename.empty() || It->second == DIFilename;
});
if (!FunctionFound) {
// Skip the following profile by setting the profile iterator (FI) to
Expand Down
12 changes: 12 additions & 0 deletions llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
private:
enum ELFAArch64RelocationKind : Edge::Kind {
ELFCall26 = Edge::FirstRelocation,
ELFLdrLo19,
ELFAdrLo21,
ELFAdrPage21,
ELFAddAbs12,
Expand Down Expand Up @@ -82,6 +83,8 @@ class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
case ELF::R_AARCH64_CALL26:
case ELF::R_AARCH64_JUMP26:
return ELFCall26;
case ELF::R_AARCH64_LD_PREL_LO19:
return ELFLdrLo19;
case ELF::R_AARCH64_ADR_PREL_LO21:
return ELFAdrLo21;
case ELF::R_AARCH64_ADR_PREL_PG_HI21:
Expand Down Expand Up @@ -191,6 +194,15 @@ class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
Kind = aarch64::Branch26PCRel;
break;
}
case ELFLdrLo19: {
uint32_t Instr = *(const ulittle32_t *)FixupContent;
if (!aarch64::isLDRLiteral(Instr))
return make_error<JITLinkError>(
"R_AARCH64_LDR_PREL_LO19 target is not an LDR Literal instruction");

Kind = aarch64::LDRLiteral19;
break;
}
case ELFAdrLo21: {
uint32_t Instr = *(const ulittle32_t *)FixupContent;
if (!aarch64::isADR(Instr))
Expand Down
4 changes: 1 addition & 3 deletions llvm/lib/TableGen/Record.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3251,9 +3251,7 @@ std::vector<Record *> RecordKeeper::getAllDerivedDefinitions(
Defs.push_back(OneDef.second.get());
}

llvm::sort(Defs, [](Record *LHS, Record *RHS) {
return LHS->getName().compare_numeric(RHS->getName()) < 0;
});
llvm::sort(Defs, LessRecord());

return Defs;
}
Expand Down
17 changes: 17 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4983,3 +4983,20 @@ ISD::NodeType LoongArchTargetLowering::getExtendForAtomicCmpSwapArg() const {
// TODO: LAMCAS will use amcas{_DB,}.[bhwd] which does not require extension.
return ISD::SIGN_EXTEND;
}

bool LoongArchTargetLowering::shouldSignExtendTypeInLibCall(
EVT Type, bool IsSigned) const {
if (Subtarget.is64Bit() && Type == MVT::i32)
return true;

return IsSigned;
}

bool LoongArchTargetLowering::shouldExtendTypeInLibCall(EVT Type) const {
// Return false to suppress the unnecessary extensions if the LibCall
// arguments or return value is a float narrower than GRLEN on a soft FP ABI.
if (Subtarget.isSoftFPABI() && (Type.isFloatingPoint() && !Type.isVector() &&
Type.getSizeInBits() < Subtarget.getGRLen()))
return false;
return true;
}
2 changes: 2 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchISelLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,8 @@ class LoongArchTargetLowering : public TargetLowering {
return false;
}
bool shouldConsiderGEPOffsetSplit() const override { return true; }
bool shouldSignExtendTypeInLibCall(EVT Type, bool IsSigned) const override;
bool shouldExtendTypeInLibCall(EVT Type) const override;

private:
/// Target-specific function used to lower LoongArch calling conventions.
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchSubtarget.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ class LoongArchSubtarget : public LoongArchGenSubtargetInfo {
MVT getGRLenVT() const { return GRLenVT; }
unsigned getGRLen() const { return GRLen; }
LoongArchABI::ABI getTargetABI() const { return TargetABI; }
bool isSoftFPABI() const {
return TargetABI == LoongArchABI::ABI_LP64S ||
TargetABI == LoongArchABI::ABI_ILP32S;
}
bool isXRaySupported() const override { return is64Bit(); }
Align getPrefFunctionAlignment() const { return PrefFunctionAlignment; }
Align getPrefLoopAlignment() const { return PrefLoopAlignment; }
Expand Down
100 changes: 70 additions & 30 deletions llvm/lib/Target/X86/X86ISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,13 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM,
if (!Subtarget.is64Bit())
setOperationAction(ISD::ATOMIC_LOAD, MVT::i64, Custom);

if (Subtarget.is64Bit() && Subtarget.hasAVX()) {
// All CPUs supporting AVX will atomically load/store aligned 128-bit
// values, so we can emit [V]MOVAPS/[V]MOVDQA.
setOperationAction(ISD::ATOMIC_LOAD, MVT::i128, Custom);
setOperationAction(ISD::ATOMIC_STORE, MVT::i128, Custom);
}

if (Subtarget.canUseCMPXCHG16B())
setOperationAction(ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS, MVT::i128, Custom);

Expand Down Expand Up @@ -30415,32 +30422,40 @@ TargetLoweringBase::AtomicExpansionKind
X86TargetLowering::shouldExpandAtomicStoreInIR(StoreInst *SI) const {
Type *MemType = SI->getValueOperand()->getType();

bool NoImplicitFloatOps =
SI->getFunction()->hasFnAttribute(Attribute::NoImplicitFloat);
if (MemType->getPrimitiveSizeInBits() == 64 && !Subtarget.is64Bit() &&
!Subtarget.useSoftFloat() && !NoImplicitFloatOps &&
(Subtarget.hasSSE1() || Subtarget.hasX87()))
return AtomicExpansionKind::None;
if (!SI->getFunction()->hasFnAttribute(Attribute::NoImplicitFloat) &&
!Subtarget.useSoftFloat()) {
if (MemType->getPrimitiveSizeInBits() == 64 && !Subtarget.is64Bit() &&
(Subtarget.hasSSE1() || Subtarget.hasX87()))
return AtomicExpansionKind::None;

if (MemType->getPrimitiveSizeInBits() == 128 && Subtarget.is64Bit() &&
Subtarget.hasAVX())
return AtomicExpansionKind::None;
}

return needsCmpXchgNb(MemType) ? AtomicExpansionKind::Expand
: AtomicExpansionKind::None;
}

// Note: this turns large loads into lock cmpxchg8b/16b.
// TODO: In 32-bit mode, use MOVLPS when SSE1 is available?
TargetLowering::AtomicExpansionKind
X86TargetLowering::shouldExpandAtomicLoadInIR(LoadInst *LI) const {
Type *MemType = LI->getType();

// If this a 64 bit atomic load on a 32-bit target and SSE2 is enabled, we
// can use movq to do the load. If we have X87 we can load into an 80-bit
// X87 register and store it to a stack temporary.
bool NoImplicitFloatOps =
LI->getFunction()->hasFnAttribute(Attribute::NoImplicitFloat);
if (MemType->getPrimitiveSizeInBits() == 64 && !Subtarget.is64Bit() &&
!Subtarget.useSoftFloat() && !NoImplicitFloatOps &&
(Subtarget.hasSSE1() || Subtarget.hasX87()))
return AtomicExpansionKind::None;
if (!LI->getFunction()->hasFnAttribute(Attribute::NoImplicitFloat) &&
!Subtarget.useSoftFloat()) {
// If this a 64 bit atomic load on a 32-bit target and SSE2 is enabled, we
// can use movq to do the load. If we have X87 we can load into an 80-bit
// X87 register and store it to a stack temporary.
if (MemType->getPrimitiveSizeInBits() == 64 && !Subtarget.is64Bit() &&
(Subtarget.hasSSE1() || Subtarget.hasX87()))
return AtomicExpansionKind::None;

// If this is a 128-bit load with AVX, 128-bit SSE loads/stores are atomic.
if (MemType->getPrimitiveSizeInBits() == 128 && Subtarget.is64Bit() &&
Subtarget.hasAVX())
return AtomicExpansionKind::None;
}

return needsCmpXchgNb(MemType) ? AtomicExpansionKind::CmpXChg
: AtomicExpansionKind::None;
Expand Down Expand Up @@ -31683,14 +31698,21 @@ static SDValue LowerATOMIC_STORE(SDValue Op, SelectionDAG &DAG,
if (!IsSeqCst && IsTypeLegal)
return Op;

if (VT == MVT::i64 && !IsTypeLegal) {
if (!IsTypeLegal && !Subtarget.useSoftFloat() &&
!DAG.getMachineFunction().getFunction().hasFnAttribute(
Attribute::NoImplicitFloat)) {
SDValue Chain;
// For illegal i128 atomic_store, when AVX is enabled, we can simply emit a
// vector store.
if (VT == MVT::i128 && Subtarget.is64Bit() && Subtarget.hasAVX()) {
SDValue VecVal = DAG.getBitcast(MVT::v2i64, Node->getVal());
Chain = DAG.getStore(Node->getChain(), dl, VecVal, Node->getBasePtr(),
Node->getMemOperand());
}

// For illegal i64 atomic_stores, we can try to use MOVQ or MOVLPS if SSE
// is enabled.
bool NoImplicitFloatOps =
DAG.getMachineFunction().getFunction().hasFnAttribute(
Attribute::NoImplicitFloat);
if (!Subtarget.useSoftFloat() && !NoImplicitFloatOps) {
SDValue Chain;
if (VT == MVT::i64) {
if (Subtarget.hasSSE1()) {
SDValue SclToVec =
DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, MVT::v2i64, Node->getVal());
Expand Down Expand Up @@ -31722,15 +31744,15 @@ static SDValue LowerATOMIC_STORE(SDValue Op, SelectionDAG &DAG,
DAG.getMemIntrinsicNode(X86ISD::FIST, dl, DAG.getVTList(MVT::Other),
StoreOps, MVT::i64, Node->getMemOperand());
}
}

if (Chain) {
// If this is a sequentially consistent store, also emit an appropriate
// barrier.
if (IsSeqCst)
Chain = emitLockedStackOp(DAG, Subtarget, Chain, dl);
if (Chain) {
// If this is a sequentially consistent store, also emit an appropriate
// barrier.
if (IsSeqCst)
Chain = emitLockedStackOp(DAG, Subtarget, Chain, dl);

return Chain;
}
return Chain;
}
}

Expand Down Expand Up @@ -33303,12 +33325,30 @@ void X86TargetLowering::ReplaceNodeResults(SDNode *N,
return;
}
case ISD::ATOMIC_LOAD: {
assert(N->getValueType(0) == MVT::i64 && "Unexpected VT!");
assert(
(N->getValueType(0) == MVT::i64 || N->getValueType(0) == MVT::i128) &&
"Unexpected VT!");
bool NoImplicitFloatOps =
DAG.getMachineFunction().getFunction().hasFnAttribute(
Attribute::NoImplicitFloat);
if (!Subtarget.useSoftFloat() && !NoImplicitFloatOps) {
auto *Node = cast<AtomicSDNode>(N);

if (N->getValueType(0) == MVT::i128) {
if (Subtarget.is64Bit() && Subtarget.hasAVX()) {
SDValue Ld = DAG.getLoad(MVT::v2i64, dl, Node->getChain(),
Node->getBasePtr(), Node->getMemOperand());
SDValue ResL = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::i64, Ld,
DAG.getIntPtrConstant(0, dl));
SDValue ResH = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::i64, Ld,
DAG.getIntPtrConstant(1, dl));
Results.push_back(DAG.getNode(ISD::BUILD_PAIR, dl, N->getValueType(0),
{ResL, ResH}));
Results.push_back(Ld.getValue(1));
return;
}
break;
}
if (Subtarget.hasSSE1()) {
// Use a VZEXT_LOAD which will be selected as MOVQ or XORPS+MOVLPS.
// Then extract the lower 64-bits.
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Transforms/IPO/GlobalOpt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2224,6 +2224,9 @@ static bool mayHaveOtherReferences(GlobalValue &GV, const LLVMUsed &U) {

static bool hasUsesToReplace(GlobalAlias &GA, const LLVMUsed &U,
bool &RenameTarget) {
if (GA.isWeakForLinker())
return false;

RenameTarget = false;
bool Ret = false;
if (hasUseOtherThanLLVMUsed(GA, U))
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/CodeGen/LoongArch/calling-conv-lp64s.ll
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ define i64 @callee_float_in_regs(i64 %a, float %b) nounwind {
; CHECK-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
; CHECK-NEXT: st.d $fp, $sp, 0 # 8-byte Folded Spill
; CHECK-NEXT: move $fp, $a0
; CHECK-NEXT: bstrpick.d $a0, $a1, 31, 0
; CHECK-NEXT: move $a0, $a1
; CHECK-NEXT: bl %plt(__fixsfdi)
; CHECK-NEXT: add.d $a0, $fp, $a0
; CHECK-NEXT: ld.d $fp, $sp, 0 # 8-byte Folded Reload
Expand Down
45 changes: 45 additions & 0 deletions llvm/test/CodeGen/LoongArch/libcall-extend.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
; RUN: llc --mtriple=loongarch64 --target-abi=lp64s --mattr=-f < %s | FileCheck %s

define signext i32 @convert_float_to_i32(i32 %tmp, float %a) nounwind {
; CHECK-LABEL: convert_float_to_i32:
; CHECK: # %bb.0:
; CHECK-NEXT: addi.d $sp, $sp, -16
; CHECK-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
; CHECK-NEXT: move $a0, $a1
; CHECK-NEXT: bl %plt(__fixsfsi)
; CHECK-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
; CHECK-NEXT: addi.d $sp, $sp, 16
; CHECK-NEXT: ret
%1 = fptosi float %a to i32
ret i32 %1
}

define signext i32 @convert_double_to_i32(i32 %tmp, double %a) nounwind {
; CHECK-LABEL: convert_double_to_i32:
; CHECK: # %bb.0:
; CHECK-NEXT: addi.d $sp, $sp, -16
; CHECK-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
; CHECK-NEXT: move $a0, $a1
; CHECK-NEXT: bl %plt(__fixdfsi)
; CHECK-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
; CHECK-NEXT: addi.d $sp, $sp, 16
; CHECK-NEXT: ret
%1 = fptosi double %a to i32
ret i32 %1
}

define signext i32 @convert_fp128_to_i32(i32 %tmp, fp128 %a) nounwind {
; CHECK-LABEL: convert_fp128_to_i32:
; CHECK: # %bb.0:
; CHECK-NEXT: addi.d $sp, $sp, -16
; CHECK-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
; CHECK-NEXT: move $a0, $a1
; CHECK-NEXT: move $a1, $a2
; CHECK-NEXT: bl %plt(__fixtfsi)
; CHECK-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
; CHECK-NEXT: addi.d $sp, $sp, 16
; CHECK-NEXT: ret
%1 = fptosi fp128 %a to i32
ret i32 %1
}
8 changes: 2 additions & 6 deletions llvm/test/CodeGen/LoongArch/sextw-removal.ll
Original file line number Diff line number Diff line change
Expand Up @@ -257,8 +257,7 @@ define void @test6(i32 signext %arg, i32 signext %arg1) nounwind {
; CHECK-NEXT: # =>This Inner Loop Header: Depth=1
; CHECK-NEXT: addi.w $a0, $fp, 0
; CHECK-NEXT: bl %plt(baz)
; CHECK-NEXT: bstrpick.d $s0, $a0, 31, 0
; CHECK-NEXT: move $a0, $s0
; CHECK-NEXT: move $s0, $a0
; CHECK-NEXT: bl %plt(__fixsfsi)
; CHECK-NEXT: move $fp, $a0
; CHECK-NEXT: move $a0, $s0
Expand All @@ -284,8 +283,7 @@ define void @test6(i32 signext %arg, i32 signext %arg1) nounwind {
; NORMV-NEXT: # =>This Inner Loop Header: Depth=1
; NORMV-NEXT: addi.w $a0, $fp, 0
; NORMV-NEXT: bl %plt(baz)
; NORMV-NEXT: bstrpick.d $s0, $a0, 31, 0
; NORMV-NEXT: move $a0, $s0
; NORMV-NEXT: move $s0, $a0
; NORMV-NEXT: bl %plt(__fixsfsi)
; NORMV-NEXT: move $fp, $a0
; NORMV-NEXT: move $a0, $s0
Expand Down Expand Up @@ -562,7 +560,6 @@ define void @test10(i32 signext %arg, i32 signext %arg1) nounwind {
; CHECK-NEXT: addi.w $a0, $fp, 0
; CHECK-NEXT: bl %plt(baz)
; CHECK-NEXT: move $fp, $a0
; CHECK-NEXT: bstrpick.d $a0, $a0, 31, 0
; CHECK-NEXT: move $a1, $zero
; CHECK-NEXT: bl %plt(__nesf2)
; CHECK-NEXT: bnez $a0, .LBB9_1
Expand All @@ -584,7 +581,6 @@ define void @test10(i32 signext %arg, i32 signext %arg1) nounwind {
; NORMV-NEXT: addi.w $a0, $fp, 0
; NORMV-NEXT: bl %plt(baz)
; NORMV-NEXT: move $fp, $a0
; NORMV-NEXT: bstrpick.d $a0, $a0, 31, 0
; NORMV-NEXT: move $a1, $zero
; NORMV-NEXT: bl %plt(__nesf2)
; NORMV-NEXT: bnez $a0, .LBB9_1
Expand Down
2 changes: 0 additions & 2 deletions llvm/test/CodeGen/LoongArch/soft-fp-to-int.ll
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ define i32 @fptosi_i32_float(float %X) nounwind {
; LA64: # %bb.0:
; LA64-NEXT: addi.d $sp, $sp, -16
; LA64-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
; LA64-NEXT: bstrpick.d $a0, $a0, 31, 0
; LA64-NEXT: bl %plt(__fixsfsi)
; LA64-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
; LA64-NEXT: addi.d $sp, $sp, 16
Expand Down Expand Up @@ -145,7 +144,6 @@ define i64 @fptosi_i64_float(float %X) nounwind {
; LA64: # %bb.0:
; LA64-NEXT: addi.d $sp, $sp, -16
; LA64-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
; LA64-NEXT: bstrpick.d $a0, $a0, 31, 0
; LA64-NEXT: bl %plt(__fixsfdi)
; LA64-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
; LA64-NEXT: addi.d $sp, $sp, 16
Expand Down
31 changes: 3 additions & 28 deletions llvm/test/CodeGen/X86/atomic-non-integer-fp128.ll
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,7 @@ define void @store_fp128(ptr %fptr, fp128 %v) {
;
; X64-AVX-LABEL: store_fp128:
; X64-AVX: # %bb.0:
; X64-AVX-NEXT: pushq %rbx
; X64-AVX-NEXT: .cfi_def_cfa_offset 16
; X64-AVX-NEXT: .cfi_offset %rbx, -16
; X64-AVX-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp)
; X64-AVX-NEXT: movq -{{[0-9]+}}(%rsp), %rbx
; X64-AVX-NEXT: movq -{{[0-9]+}}(%rsp), %rcx
; X64-AVX-NEXT: movq (%rdi), %rax
; X64-AVX-NEXT: movq 8(%rdi), %rdx
; X64-AVX-NEXT: .p2align 4, 0x90
; X64-AVX-NEXT: .LBB0_1: # %atomicrmw.start
; X64-AVX-NEXT: # =>This Inner Loop Header: Depth=1
; X64-AVX-NEXT: lock cmpxchg16b (%rdi)
; X64-AVX-NEXT: jne .LBB0_1
; X64-AVX-NEXT: # %bb.2: # %atomicrmw.end
; X64-AVX-NEXT: popq %rbx
; X64-AVX-NEXT: .cfi_def_cfa_offset 8
; X64-AVX-NEXT: vmovaps %xmm0, (%rdi)
; X64-AVX-NEXT: retq
store atomic fp128 %v, ptr %fptr unordered, align 16
ret void
Expand All @@ -69,19 +54,9 @@ define fp128 @load_fp128(ptr %fptr) {
;
; X64-AVX-LABEL: load_fp128:
; X64-AVX: # %bb.0:
; X64-AVX-NEXT: pushq %rbx
; X64-AVX-NEXT: .cfi_def_cfa_offset 16
; X64-AVX-NEXT: .cfi_offset %rbx, -16
; X64-AVX-NEXT: xorl %eax, %eax
; X64-AVX-NEXT: xorl %edx, %edx
; X64-AVX-NEXT: xorl %ecx, %ecx
; X64-AVX-NEXT: xorl %ebx, %ebx
; X64-AVX-NEXT: lock cmpxchg16b (%rdi)
; X64-AVX-NEXT: movq %rdx, -{{[0-9]+}}(%rsp)
; X64-AVX-NEXT: movq %rax, -{{[0-9]+}}(%rsp)
; X64-AVX-NEXT: vmovaps (%rdi), %xmm0
; X64-AVX-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp)
; X64-AVX-NEXT: vmovaps -{{[0-9]+}}(%rsp), %xmm0
; X64-AVX-NEXT: popq %rbx
; X64-AVX-NEXT: .cfi_def_cfa_offset 8
; X64-AVX-NEXT: retq
%v = load atomic fp128, ptr %fptr unordered, align 16
ret fp128 %v
Expand Down
1 change: 0 additions & 1 deletion llvm/test/CodeGen/X86/atomic-non-integer.ll
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,6 @@ define void @store_double(ptr %fptr, double %v) {
ret void
}


define half @load_half(ptr %fptr) {
; X86-SSE1-LABEL: load_half:
; X86-SSE1: # %bb.0:
Expand Down
33 changes: 33 additions & 0 deletions llvm/test/CodeGen/X86/atomic-unaligned.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
; RUN: llc -mtriple=x86_64 < %s | FileCheck %s

; Quick test to ensure that atomics which are not naturally-aligned
; emit unsized libcalls, and aren't emitted as native instructions or
; sized libcalls.
define void @test_i32(ptr %a) nounwind {
; CHECK-LABEL: test_i32:
; CHECK: callq __atomic_load
; CHECK: callq __atomic_store
; CHECK: callq __atomic_exchange
; CHECK: callq __atomic_compare_exchange
; CHECK: callq __atomic_compare_exchange
%t0 = load atomic i32, ptr %a seq_cst, align 2
store atomic i32 1, ptr %a seq_cst, align 2
%t1 = atomicrmw xchg ptr %a, i32 1 seq_cst, align 2
%t3 = atomicrmw add ptr %a, i32 2 seq_cst, align 2
%t2 = cmpxchg ptr %a, i32 0, i32 1 seq_cst seq_cst, align 2
ret void
}

define void @test_i128(ptr %a) nounwind {
; CHECK-LABEL: test_i128:
; CHECK: callq __atomic_load
; CHECK: callq __atomic_store
; CHECK: callq __atomic_exchange
; CHECK: callq __atomic_compare_exchange
%t0 = load atomic i128, ptr %a seq_cst, align 8
store atomic i128 1, ptr %a seq_cst, align 8
%t1 = atomicrmw xchg ptr %a, i128 1 seq_cst, align 8
%t2 = atomicrmw add ptr %a, i128 2 seq_cst, align 8
%t3 = cmpxchg ptr %a, i128 0, i128 1 seq_cst seq_cst, align 8
ret void
}
83 changes: 14 additions & 69 deletions llvm/test/CodeGen/X86/atomic-unordered.ll
Original file line number Diff line number Diff line change
Expand Up @@ -228,86 +228,31 @@ define void @widen_broadcast_unaligned(ptr %p0, i32 %v) {
}

define i128 @load_i128(ptr %ptr) {
; CHECK-O0-LABEL: load_i128:
; CHECK-O0: # %bb.0:
; CHECK-O0-NEXT: pushq %rbx
; CHECK-O0-NEXT: .cfi_def_cfa_offset 16
; CHECK-O0-NEXT: .cfi_offset %rbx, -16
; CHECK-O0-NEXT: xorl %eax, %eax
; CHECK-O0-NEXT: movl %eax, %ebx
; CHECK-O0-NEXT: movq %rbx, %rax
; CHECK-O0-NEXT: movq %rbx, %rdx
; CHECK-O0-NEXT: movq %rbx, %rcx
; CHECK-O0-NEXT: lock cmpxchg16b (%rdi)
; CHECK-O0-NEXT: popq %rbx
; CHECK-O0-NEXT: .cfi_def_cfa_offset 8
; CHECK-O0-NEXT: retq
;
; CHECK-O3-LABEL: load_i128:
; CHECK-O3: # %bb.0:
; CHECK-O3-NEXT: pushq %rbx
; CHECK-O3-NEXT: .cfi_def_cfa_offset 16
; CHECK-O3-NEXT: .cfi_offset %rbx, -16
; CHECK-O3-NEXT: xorl %eax, %eax
; CHECK-O3-NEXT: xorl %edx, %edx
; CHECK-O3-NEXT: xorl %ecx, %ecx
; CHECK-O3-NEXT: xorl %ebx, %ebx
; CHECK-O3-NEXT: lock cmpxchg16b (%rdi)
; CHECK-O3-NEXT: popq %rbx
; CHECK-O3-NEXT: .cfi_def_cfa_offset 8
; CHECK-O3-NEXT: retq
; CHECK-LABEL: load_i128:
; CHECK: # %bb.0:
; CHECK-NEXT: vmovdqa (%rdi), %xmm0
; CHECK-NEXT: vmovq %xmm0, %rax
; CHECK-NEXT: vpextrq $1, %xmm0, %rdx
; CHECK-NEXT: retq
%v = load atomic i128, ptr %ptr unordered, align 16
ret i128 %v
}

define void @store_i128(ptr %ptr, i128 %v) {
; CHECK-O0-LABEL: store_i128:
; CHECK-O0: # %bb.0:
; CHECK-O0-NEXT: pushq %rbx
; CHECK-O0-NEXT: .cfi_def_cfa_offset 16
; CHECK-O0-NEXT: .cfi_offset %rbx, -16
; CHECK-O0-NEXT: movq %rdi, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
; CHECK-O0-NEXT: movq %rdx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
; CHECK-O0-NEXT: movq %rsi, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
; CHECK-O0-NEXT: movq (%rdi), %rax
; CHECK-O0-NEXT: movq 8(%rdi), %rdx
; CHECK-O0-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
; CHECK-O0-NEXT: movq %rdx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
; CHECK-O0-NEXT: jmp .LBB16_1
; CHECK-O0-NEXT: .LBB16_1: # %atomicrmw.start
; CHECK-O0-NEXT: # =>This Inner Loop Header: Depth=1
; CHECK-O0-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rdx # 8-byte Reload
; CHECK-O0-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload
; CHECK-O0-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rsi # 8-byte Reload
; CHECK-O0-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rbx # 8-byte Reload
; CHECK-O0-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rcx # 8-byte Reload
; CHECK-O0-NEXT: lock cmpxchg16b (%rsi)
; CHECK-O0-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
; CHECK-O0-NEXT: movq %rdx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
; CHECK-O0-NEXT: jne .LBB16_1
; CHECK-O0-NEXT: jmp .LBB16_2
; CHECK-O0-NEXT: .LBB16_2: # %atomicrmw.end
; CHECK-O0-NEXT: popq %rbx
; CHECK-O0-NEXT: .cfi_def_cfa_offset 8
; CHECK-O0-NEXT: vmovq %rsi, %xmm0
; CHECK-O0-NEXT: vmovq %rdx, %xmm1
; CHECK-O0-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm1[0]
; CHECK-O0-NEXT: vmovdqa %xmm0, (%rdi)
; CHECK-O0-NEXT: retq
;
; CHECK-O3-LABEL: store_i128:
; CHECK-O3: # %bb.0:
; CHECK-O3-NEXT: pushq %rbx
; CHECK-O3-NEXT: .cfi_def_cfa_offset 16
; CHECK-O3-NEXT: .cfi_offset %rbx, -16
; CHECK-O3-NEXT: movq %rdx, %rcx
; CHECK-O3-NEXT: movq %rsi, %rbx
; CHECK-O3-NEXT: movq (%rdi), %rax
; CHECK-O3-NEXT: movq 8(%rdi), %rdx
; CHECK-O3-NEXT: .p2align 4, 0x90
; CHECK-O3-NEXT: .LBB16_1: # %atomicrmw.start
; CHECK-O3-NEXT: # =>This Inner Loop Header: Depth=1
; CHECK-O3-NEXT: lock cmpxchg16b (%rdi)
; CHECK-O3-NEXT: jne .LBB16_1
; CHECK-O3-NEXT: # %bb.2: # %atomicrmw.end
; CHECK-O3-NEXT: popq %rbx
; CHECK-O3-NEXT: .cfi_def_cfa_offset 8
; CHECK-O3-NEXT: vmovq %rdx, %xmm0
; CHECK-O3-NEXT: vmovq %rsi, %xmm1
; CHECK-O3-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0]
; CHECK-O3-NEXT: vmovdqa %xmm0, (%rdi)
; CHECK-O3-NEXT: retq
store atomic i128 %v, ptr %ptr unordered, align 16
ret void
Expand Down
224 changes: 136 additions & 88 deletions llvm/test/CodeGen/X86/atomic128.ll
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=x86_64-apple-macosx10.9 -verify-machineinstrs -mattr=cx16 | FileCheck %s
; RUN: llc < %s -mtriple=x86_64-apple-macosx10.9 -verify-machineinstrs -mattr=cx16 | FileCheck %s --check-prefixes=CHECK,CHECK-NOAVX
; RUN: llc < %s -mtriple=x86_64-apple-macosx10.9 -verify-machineinstrs -mattr=cx16,avx | FileCheck %s --check-prefixes=CHECK,CHECK-AVX

; Codegen of i128 without cx16 is tested in atomic-nocx16.ll

Expand Down Expand Up @@ -28,20 +29,28 @@ define i128 @val_compare_and_swap(ptr %p, i128 %oldval, i128 %newval) {
@cmpxchg16b_global = external dso_local global { i128, i128 }, align 16

;; Make sure we retain the offset of the global variable.
define void @cmpxchg16b_global_with_offset() nounwind {
; CHECK-LABEL: cmpxchg16b_global_with_offset:
; CHECK: ## %bb.0: ## %entry
; CHECK-NEXT: pushq %rbx
; CHECK-NEXT: xorl %eax, %eax
; CHECK-NEXT: xorl %edx, %edx
; CHECK-NEXT: xorl %ecx, %ecx
; CHECK-NEXT: xorl %ebx, %ebx
; CHECK-NEXT: lock cmpxchg16b _cmpxchg16b_global+16(%rip)
; CHECK-NEXT: popq %rbx
; CHECK-NEXT: retq
define i128 @load_global_with_offset() nounwind {
; CHECK-NOAVX-LABEL: load_global_with_offset:
; CHECK-NOAVX: ## %bb.0: ## %entry
; CHECK-NOAVX-NEXT: pushq %rbx
; CHECK-NOAVX-NEXT: xorl %eax, %eax
; CHECK-NOAVX-NEXT: xorl %edx, %edx
; CHECK-NOAVX-NEXT: xorl %ecx, %ecx
; CHECK-NOAVX-NEXT: xorl %ebx, %ebx
; CHECK-NOAVX-NEXT: lock cmpxchg16b _cmpxchg16b_global+16(%rip)
; CHECK-NOAVX-NEXT: popq %rbx
; CHECK-NOAVX-NEXT: retq
;
; CHECK-AVX-LABEL: load_global_with_offset:
; CHECK-AVX: ## %bb.0: ## %entry
; CHECK-AVX-NEXT: vmovdqa _cmpxchg16b_global+16(%rip), %xmm0
; CHECK-AVX-NEXT: vmovq %xmm0, %rax
; CHECK-AVX-NEXT: vpextrq $1, %xmm0, %rdx
; CHECK-AVX-NEXT: retq
;
entry:
%0 = load atomic i128, ptr getelementptr inbounds ({i128, i128}, ptr @cmpxchg16b_global, i64 0, i32 1) acquire, align 16
ret void
ret i128 %0
}

define void @fetch_and_nand(ptr %p, i128 %bits) {
Expand Down Expand Up @@ -283,101 +292,140 @@ define void @fetch_and_umax(ptr %p, i128 %bits) {
}

define i128 @atomic_load_seq_cst(ptr %p) {
; CHECK-LABEL: atomic_load_seq_cst:
; CHECK: ## %bb.0:
; CHECK-NEXT: pushq %rbx
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: .cfi_offset %rbx, -16
; CHECK-NEXT: xorl %eax, %eax
; CHECK-NEXT: xorl %edx, %edx
; CHECK-NEXT: xorl %ecx, %ecx
; CHECK-NEXT: xorl %ebx, %ebx
; CHECK-NEXT: lock cmpxchg16b (%rdi)
; CHECK-NEXT: popq %rbx
; CHECK-NEXT: retq
; CHECK-NOAVX-LABEL: atomic_load_seq_cst:
; CHECK-NOAVX: ## %bb.0:
; CHECK-NOAVX-NEXT: pushq %rbx
; CHECK-NOAVX-NEXT: .cfi_def_cfa_offset 16
; CHECK-NOAVX-NEXT: .cfi_offset %rbx, -16
; CHECK-NOAVX-NEXT: xorl %eax, %eax
; CHECK-NOAVX-NEXT: xorl %edx, %edx
; CHECK-NOAVX-NEXT: xorl %ecx, %ecx
; CHECK-NOAVX-NEXT: xorl %ebx, %ebx
; CHECK-NOAVX-NEXT: lock cmpxchg16b (%rdi)
; CHECK-NOAVX-NEXT: popq %rbx
; CHECK-NOAVX-NEXT: retq
;
; CHECK-AVX-LABEL: atomic_load_seq_cst:
; CHECK-AVX: ## %bb.0:
; CHECK-AVX-NEXT: vmovdqa (%rdi), %xmm0
; CHECK-AVX-NEXT: vmovq %xmm0, %rax
; CHECK-AVX-NEXT: vpextrq $1, %xmm0, %rdx
; CHECK-AVX-NEXT: retq
%r = load atomic i128, ptr %p seq_cst, align 16
ret i128 %r
}

define i128 @atomic_load_relaxed(ptr %p) {
; CHECK-LABEL: atomic_load_relaxed:
; CHECK: ## %bb.0:
; CHECK-NEXT: pushq %rbx
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: .cfi_offset %rbx, -16
; CHECK-NEXT: xorl %eax, %eax
; CHECK-NEXT: xorl %edx, %edx
; CHECK-NEXT: xorl %ecx, %ecx
; CHECK-NEXT: xorl %ebx, %ebx
; CHECK-NEXT: lock cmpxchg16b (%rdi)
; CHECK-NEXT: popq %rbx
; CHECK-NEXT: retq
; CHECK-NOAVX-LABEL: atomic_load_relaxed:
; CHECK-NOAVX: ## %bb.0:
; CHECK-NOAVX-NEXT: pushq %rbx
; CHECK-NOAVX-NEXT: .cfi_def_cfa_offset 16
; CHECK-NOAVX-NEXT: .cfi_offset %rbx, -16
; CHECK-NOAVX-NEXT: xorl %eax, %eax
; CHECK-NOAVX-NEXT: xorl %edx, %edx
; CHECK-NOAVX-NEXT: xorl %ecx, %ecx
; CHECK-NOAVX-NEXT: xorl %ebx, %ebx
; CHECK-NOAVX-NEXT: lock cmpxchg16b (%rdi)
; CHECK-NOAVX-NEXT: popq %rbx
; CHECK-NOAVX-NEXT: retq
;
; CHECK-AVX-LABEL: atomic_load_relaxed:
; CHECK-AVX: ## %bb.0:
; CHECK-AVX-NEXT: vmovdqa (%rdi), %xmm0
; CHECK-AVX-NEXT: vmovq %xmm0, %rax
; CHECK-AVX-NEXT: vpextrq $1, %xmm0, %rdx
; CHECK-AVX-NEXT: retq
%r = load atomic i128, ptr %p monotonic, align 16
ret i128 %r
}

define void @atomic_store_seq_cst(ptr %p, i128 %in) {
; CHECK-LABEL: atomic_store_seq_cst:
; CHECK: ## %bb.0:
; CHECK-NEXT: pushq %rbx
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: .cfi_offset %rbx, -16
; CHECK-NEXT: movq %rdx, %rcx
; CHECK-NEXT: movq %rsi, %rbx
; CHECK-NEXT: movq (%rdi), %rax
; CHECK-NEXT: movq 8(%rdi), %rdx
; CHECK-NEXT: .p2align 4, 0x90
; CHECK-NEXT: LBB12_1: ## %atomicrmw.start
; CHECK-NEXT: ## =>This Inner Loop Header: Depth=1
; CHECK-NEXT: lock cmpxchg16b (%rdi)
; CHECK-NEXT: jne LBB12_1
; CHECK-NEXT: ## %bb.2: ## %atomicrmw.end
; CHECK-NEXT: popq %rbx
; CHECK-NEXT: retq
; CHECK-NOAVX-LABEL: atomic_store_seq_cst:
; CHECK-NOAVX: ## %bb.0:
; CHECK-NOAVX-NEXT: pushq %rbx
; CHECK-NOAVX-NEXT: .cfi_def_cfa_offset 16
; CHECK-NOAVX-NEXT: .cfi_offset %rbx, -16
; CHECK-NOAVX-NEXT: movq %rdx, %rcx
; CHECK-NOAVX-NEXT: movq %rsi, %rbx
; CHECK-NOAVX-NEXT: movq (%rdi), %rax
; CHECK-NOAVX-NEXT: movq 8(%rdi), %rdx
; CHECK-NOAVX-NEXT: .p2align 4, 0x90
; CHECK-NOAVX-NEXT: LBB12_1: ## %atomicrmw.start
; CHECK-NOAVX-NEXT: ## =>This Inner Loop Header: Depth=1
; CHECK-NOAVX-NEXT: lock cmpxchg16b (%rdi)
; CHECK-NOAVX-NEXT: jne LBB12_1
; CHECK-NOAVX-NEXT: ## %bb.2: ## %atomicrmw.end
; CHECK-NOAVX-NEXT: popq %rbx
; CHECK-NOAVX-NEXT: retq
;
; CHECK-AVX-LABEL: atomic_store_seq_cst:
; CHECK-AVX: ## %bb.0:
; CHECK-AVX-NEXT: vmovq %rdx, %xmm0
; CHECK-AVX-NEXT: vmovq %rsi, %xmm1
; CHECK-AVX-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0]
; CHECK-AVX-NEXT: vmovdqa %xmm0, (%rdi)
; CHECK-AVX-NEXT: lock orl $0, -{{[0-9]+}}(%rsp)
; CHECK-AVX-NEXT: retq
store atomic i128 %in, ptr %p seq_cst, align 16
ret void
}

define void @atomic_store_release(ptr %p, i128 %in) {
; CHECK-LABEL: atomic_store_release:
; CHECK: ## %bb.0:
; CHECK-NEXT: pushq %rbx
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: .cfi_offset %rbx, -16
; CHECK-NEXT: movq %rdx, %rcx
; CHECK-NEXT: movq %rsi, %rbx
; CHECK-NEXT: movq (%rdi), %rax
; CHECK-NEXT: movq 8(%rdi), %rdx
; CHECK-NEXT: .p2align 4, 0x90
; CHECK-NEXT: LBB13_1: ## %atomicrmw.start
; CHECK-NEXT: ## =>This Inner Loop Header: Depth=1
; CHECK-NEXT: lock cmpxchg16b (%rdi)
; CHECK-NEXT: jne LBB13_1
; CHECK-NEXT: ## %bb.2: ## %atomicrmw.end
; CHECK-NEXT: popq %rbx
; CHECK-NEXT: retq
; CHECK-NOAVX-LABEL: atomic_store_release:
; CHECK-NOAVX: ## %bb.0:
; CHECK-NOAVX-NEXT: pushq %rbx
; CHECK-NOAVX-NEXT: .cfi_def_cfa_offset 16
; CHECK-NOAVX-NEXT: .cfi_offset %rbx, -16
; CHECK-NOAVX-NEXT: movq %rdx, %rcx
; CHECK-NOAVX-NEXT: movq %rsi, %rbx
; CHECK-NOAVX-NEXT: movq (%rdi), %rax
; CHECK-NOAVX-NEXT: movq 8(%rdi), %rdx
; CHECK-NOAVX-NEXT: .p2align 4, 0x90
; CHECK-NOAVX-NEXT: LBB13_1: ## %atomicrmw.start
; CHECK-NOAVX-NEXT: ## =>This Inner Loop Header: Depth=1
; CHECK-NOAVX-NEXT: lock cmpxchg16b (%rdi)
; CHECK-NOAVX-NEXT: jne LBB13_1
; CHECK-NOAVX-NEXT: ## %bb.2: ## %atomicrmw.end
; CHECK-NOAVX-NEXT: popq %rbx
; CHECK-NOAVX-NEXT: retq
;
; CHECK-AVX-LABEL: atomic_store_release:
; CHECK-AVX: ## %bb.0:
; CHECK-AVX-NEXT: vmovq %rdx, %xmm0
; CHECK-AVX-NEXT: vmovq %rsi, %xmm1
; CHECK-AVX-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0]
; CHECK-AVX-NEXT: vmovdqa %xmm0, (%rdi)
; CHECK-AVX-NEXT: retq
store atomic i128 %in, ptr %p release, align 16
ret void
}

define void @atomic_store_relaxed(ptr %p, i128 %in) {
; CHECK-LABEL: atomic_store_relaxed:
; CHECK: ## %bb.0:
; CHECK-NEXT: pushq %rbx
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: .cfi_offset %rbx, -16
; CHECK-NEXT: movq %rdx, %rcx
; CHECK-NEXT: movq %rsi, %rbx
; CHECK-NEXT: movq (%rdi), %rax
; CHECK-NEXT: movq 8(%rdi), %rdx
; CHECK-NEXT: .p2align 4, 0x90
; CHECK-NEXT: LBB14_1: ## %atomicrmw.start
; CHECK-NEXT: ## =>This Inner Loop Header: Depth=1
; CHECK-NEXT: lock cmpxchg16b (%rdi)
; CHECK-NEXT: jne LBB14_1
; CHECK-NEXT: ## %bb.2: ## %atomicrmw.end
; CHECK-NEXT: popq %rbx
; CHECK-NEXT: retq
; CHECK-NOAVX-LABEL: atomic_store_relaxed:
; CHECK-NOAVX: ## %bb.0:
; CHECK-NOAVX-NEXT: pushq %rbx
; CHECK-NOAVX-NEXT: .cfi_def_cfa_offset 16
; CHECK-NOAVX-NEXT: .cfi_offset %rbx, -16
; CHECK-NOAVX-NEXT: movq %rdx, %rcx
; CHECK-NOAVX-NEXT: movq %rsi, %rbx
; CHECK-NOAVX-NEXT: movq (%rdi), %rax
; CHECK-NOAVX-NEXT: movq 8(%rdi), %rdx
; CHECK-NOAVX-NEXT: .p2align 4, 0x90
; CHECK-NOAVX-NEXT: LBB14_1: ## %atomicrmw.start
; CHECK-NOAVX-NEXT: ## =>This Inner Loop Header: Depth=1
; CHECK-NOAVX-NEXT: lock cmpxchg16b (%rdi)
; CHECK-NOAVX-NEXT: jne LBB14_1
; CHECK-NOAVX-NEXT: ## %bb.2: ## %atomicrmw.end
; CHECK-NOAVX-NEXT: popq %rbx
; CHECK-NOAVX-NEXT: retq
;
; CHECK-AVX-LABEL: atomic_store_relaxed:
; CHECK-AVX: ## %bb.0:
; CHECK-AVX-NEXT: vmovq %rdx, %xmm0
; CHECK-AVX-NEXT: vmovq %rsi, %xmm1
; CHECK-AVX-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0]
; CHECK-AVX-NEXT: vmovdqa %xmm0, (%rdi)
; CHECK-AVX-NEXT: retq
store atomic i128 %in, ptr %p unordered, align 16
ret void
}
Expand Down
8 changes: 3 additions & 5 deletions llvm/test/CodeGen/X86/cmpxchg-i128-i1.ll
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,9 @@ define i128 @cmpxchg_use_eflags_and_val(ptr %addr, i128 %offset) {
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: .cfi_offset %rbx, -16
; CHECK-NEXT: movq %rdx, %r8
; CHECK-NEXT: xorl %eax, %eax
; CHECK-NEXT: xorl %edx, %edx
; CHECK-NEXT: xorl %ecx, %ecx
; CHECK-NEXT: xorl %ebx, %ebx
; CHECK-NEXT: lock cmpxchg16b (%rdi)
; CHECK-NEXT: vmovdqa (%rdi), %xmm0
; CHECK-NEXT: vpextrq $1, %xmm0, %rdx
; CHECK-NEXT: vmovq %xmm0, %rax
; CHECK-NEXT: .p2align 4, 0x90
; CHECK-NEXT: .LBB4_1: # %loop
; CHECK-NEXT: # =>This Inner Loop Header: Depth=1
Expand Down
11 changes: 11 additions & 0 deletions llvm/test/ExecutionEngine/JITLink/AArch64/ELF_relocations.s
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,17 @@ test_adr_prel_lo21:
## to test this bit better
adr_data = test_adr_prel_lo21 + 0xe46f2

# Check R_AARCH64_LD_PREL_LO19 relocation of a local symbol
#
# jitlink-check: decode_operand(test_ldr_prel_lo19 + 0, 1)[19:0] = \
# jitlink-check: (ldr_data - test_ldr_prel_lo19 + 0x4)[21:2]
.globl test_ldr_prel_lo19, ldr_data
.p2align 2
test_ldr_prel_lo19:
ldr x0, ldr_data + 0x4
.size test_ldr_prel_lo19, .-test_ldr_prel_lo19
ldr_data = test_ldr_prel_lo19 + 4

# Check R_AARCH64_ADR_PREL_PG_HI21 / R_AARCH64_ADD_ABS_LO12_NC relocation of a local symbol
#
# For the ADR_PREL_PG_HI21/ADRP instruction we have the 21-bit delta to the 4k page
Expand Down
52 changes: 52 additions & 0 deletions llvm/test/ThinLTO/X86/ref-ifunc.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
; RUN: opt -module-summary %s -o %t.bc

; RUN: llvm-dis %t.bc -o - | FileCheck %s

; Tests that var and caller are not eligible to import and they don't have refs to ifunc 'callee'

; CHECK: gv: (name: "var", summaries: (variable: ({{.*}}, flags: ({{.*}}notEligibleToImport: 1
; CHECK-NOT: refs
; CHECK-SAME: guid = 7919382516565939378

; CHECK: gv: (name: "caller", summaries: (function: ({{.*}}, flags: ({{.*}}notEligibleToImport: 1
; CHECK-NOT: refs
; CHECK-SAME: guid = 16677772384402303968

target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

@__cpu_model = external global { i32, i32, i32, [1 x i32] }

@callee = internal ifunc void(), ptr @callee.resolver

@var = constant { [1 x ptr] } { [1 x ptr] [ptr @callee]}

define void @dispatch(ptr %func) {
tail call void %func()
ret void
}

define void @caller() {
tail call void @dispatch(ptr @callee)
ret void
}

define internal ptr @callee.resolver() {
resolver_entry:
tail call void @__cpu_indicator_init()
%0 = load i32, ptr getelementptr inbounds ({ i32, i32, i32, [1 x i32] }, ptr @__cpu_model, i64 0, i32 3, i64 0)
%1 = and i32 %0, 1024
%.not = icmp eq i32 %1, 0
%func_sel = select i1 %.not, ptr @callee.default.1, ptr @callee.avx2.0
ret ptr %func_sel
}

define internal void @callee.default.1(i32 %a) {
ret void
}

define internal void @callee.avx2.0(i32 %a) {
ret void
}

declare void @__cpu_indicator_init()
57 changes: 57 additions & 0 deletions llvm/test/Transforms/GlobalOpt/alias-weak.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --include-generated-funcs --version 4
; RUN: opt < %s -passes=globalopt -S | FileCheck %s

@f1_alias = linkonce_odr hidden alias void (), ptr @f1
@f2_alias = linkonce_odr hidden alias void (), ptr @f2

define void @foo() {
call void @f1_alias()
ret void
}

define void @bar() {
call void @f1()
ret void
}

define void @baz() {
call void @f2_alias()
ret void
}

; We cannot use `f1_alias` to replace `f1` because they are both in use
; and `f1_alias` could be replaced at link time.
define internal void @f1() {
ret void
}

; FIXME: We can use `f2_alias` to replace `f2` because `b2` is not in use.
define internal void @f2() {
ret void
}
;.
; CHECK: @f1_alias = linkonce_odr hidden alias void (), ptr @f1
; CHECK: @f2_alias = linkonce_odr hidden alias void (), ptr @f2
;.
; CHECK-LABEL: define void @foo() local_unnamed_addr {
; CHECK-NEXT: call void @f1_alias()
; CHECK-NEXT: ret void
;
;
; CHECK-LABEL: define void @bar() local_unnamed_addr {
; CHECK-NEXT: call void @f1()
; CHECK-NEXT: ret void
;
;
; CHECK-LABEL: define void @baz() local_unnamed_addr {
; CHECK-NEXT: call void @f2_alias()
; CHECK-NEXT: ret void
;
;
; CHECK-LABEL: define internal void @f1() {
; CHECK-NEXT: ret void
;
;
; CHECK-LABEL: define internal void @f2() {
; CHECK-NEXT: ret void
;
48 changes: 48 additions & 0 deletions mlir/docs/DefiningDialects/Operations.md
Original file line number Diff line number Diff line change
Expand Up @@ -291,8 +291,27 @@ Right now, the following primitive constraints are supported:
equal to `N`
* `IntMaxValue<N>`: Specifying an integer attribute to be less than or equal
to `N`
* `IntNEQValue<N>`: Specifying an integer attribute to be not equal
to `N`
* `IntPositive`: Specifying an integer attribute whose value is positive
* `IntNonNegative`: Specifying an integer attribute whose value is
non-negative
* `ArrayMinCount<N>`: Specifying an array attribute to have at least `N`
elements
* `ArrayMaxCount<N>`: Specifying an array attribute to have at most `N`
elements
* `ArrayCount<N>`: Specifying an array attribute to have exactly `N`
elements
* `DenseArrayCount<N>`: Specifying a dense array attribute to have
exactly `N` elements
* `DenseArrayStrictlyPositive<arrayType>`: Specifying a dense array attribute
of type `arrayType` to have all positive elements
* `DenseArrayStrictlyNonNegative<arrayType>`: Specifying a dense array attribute
of type `arrayType` to have all non-negative elements
* `DenseArraySorted<arrayType>`: Specifying a dense array attribute
of type `arrayType` to have elements in non-decreasing order
* `DenseArrayStrictlySorted<arrayType>`: Specifying a dense array attribute
of type `arrayType` to have elements in increasing order
* `IntArrayNthElemEq<I, N>`: Specifying an integer array attribute's `I`-th
element to be equal to `N`
* `IntArrayNthElemMinValue<I, N>`: Specifying an integer array attribute's
Expand All @@ -301,9 +320,36 @@ Right now, the following primitive constraints are supported:
`I`-th element to be less than or equal to `N`
* `IntArrayNthElemInRange<I, M, N>`: Specifying an integer array attribute's
`I`-th element to be greater than or equal to `M` and less than or equal to `N`
* `IsNullAttr`: Specifying an optional attribute which must be empty

TODO: Design and implement more primitive constraints

#### Combining constraints

`AllAttrOf` is provided to allow combination of multiple constraints which
must all hold.

For example:
```tablegen
def OpAllAttrConstraint1 : TEST_Op<"all_attr_constraint_of1"> {
let arguments = (ins I64ArrayAttr:$attr);
let results = (outs I32);
}
def OpAllAttrConstraint2 : TEST_Op<"all_attr_constraint_of2"> {
let arguments = (ins I64ArrayAttr:$attr);
let results = (outs I32);
}
def Constraint0 : AttrConstraint<
CPred<"::llvm::cast<::mlir::IntegerAttr>(::llvm::cast<ArrayAttr>($_self)[0]).getInt() == 0">,
"[0] == 0">;
def Constraint1 : AttrConstraint<
CPred<"::llvm::cast<::mlir::IntegerAttr>(::llvm::cast<ArrayAttr>($_self)[1]).getInt() == 1">,
"[1] == 1">;
def : Pat<(OpAllAttrConstraint1
AllAttrOf<[Constraint0, Constraint1]>:$attr),
(OpAllAttrConstraint2 $attr)>;
```

### Operation regions

The regions of an operation are specified inside of the `dag`-typed `regions`,
Expand Down Expand Up @@ -1398,6 +1444,8 @@ optionality, default values, etc.:
* `OptionalAttr`: specifies an attribute as [optional](#optional-attributes).
* `ConfinedAttr`: adapts an attribute with
[further constraints](#confining-attributes).
* `AllAttrOf`: adapts an attribute with
[multiple constraints](#combining-constraints).

### Enum attributes

Expand Down
4 changes: 4 additions & 0 deletions mlir/include/mlir/IR/CommonAttrConstraints.td
Original file line number Diff line number Diff line change
Expand Up @@ -773,6 +773,10 @@ def IntPositive : AttrConstraint<
CPred<"::llvm::cast<::mlir::IntegerAttr>($_self).getValue().isStrictlyPositive()">,
"whose value is positive">;

class ArrayMaxCount<int n> : AttrConstraint<
CPred<"::llvm::cast<::mlir::ArrayAttr>($_self).size() <= " # n>,
"with at most " # n # " elements">;

class ArrayMinCount<int n> : AttrConstraint<
CPred<"::llvm::cast<::mlir::ArrayAttr>($_self).size() >= " # n>,
"with at least " # n # " elements">;
Expand Down