From 02a33b72fd21cdbf476d6bda72faa462e073e510 Mon Sep 17 00:00:00 2001 From: Mark de Wever Date: Fri, 5 Jan 2024 19:43:10 +0100 Subject: =?UTF-8?q?"Reapply=20"[Sema]=20Fix=20crash=20on=20invalid=20code?= =?UTF-8?q?=20with=20parenthesized=20aggrega=E2=80=A6=20(#76833)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …te initialization" (#76272)"" With updates the libc++ tests. This reverts commit 2205d23 and relands 86dc6e1 and 7ab16fb. Original commit was reverted because of failing libc++ tests, see #76232 for the discussion. The errors in the tests are spurious in the first place (coming from initialization of invalid classes), so update the tests to match new behavior that does not show those errors. The original patch was written by @ilya-biryukov To fix the CI two libc++ tests are temporary disabled for clang-18. --- clang/lib/Sema/SemaInit.cpp | 8 +++++++ clang/test/SemaCXX/crash-GH76228.cpp | 28 ++++++++++++++++++++++ clang/test/SemaCXX/paren-list-agg-init.cpp | 2 +- .../transform_error.mandates.verify.cpp | 9 +++++++ .../transform_error.mandates.verify.cpp | 9 +++++++ 5 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 clang/test/SemaCXX/crash-GH76228.cpp diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 60c0e3e..e469e42 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -5512,6 +5512,14 @@ static void TryOrBuildParenListInitialization( } else if (auto *RT = Entity.getType()->getAs()) { bool IsUnion = RT->isUnionType(); const CXXRecordDecl *RD = cast(RT->getDecl()); + if (RD->isInvalidDecl()) { + // Exit early to avoid confusion when processing members. + // We do the same for braced list initialization in + // `CheckStructUnionTypes`. + Sequence.SetFailed( + clang::InitializationSequence::FK_ParenthesizedListInitFailed); + return; + } if (!IsUnion) { for (const CXXBaseSpecifier &Base : RD->bases()) { diff --git a/clang/test/SemaCXX/crash-GH76228.cpp b/clang/test/SemaCXX/crash-GH76228.cpp new file mode 100644 index 0000000..33a9395 --- /dev/null +++ b/clang/test/SemaCXX/crash-GH76228.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -std=c++20 -verify %s +// Check we don't crash on incomplete members and bases when handling parenthesized initialization. +class incomplete; // expected-note@-0 3 {{forward declaration of 'incomplete'}} +struct foo { + int a; + incomplete b; + // expected-error@-1 {{incomplete type}} +}; +foo a1(0); + +struct one_int { + int a; +}; +struct bar : one_int, incomplete {}; +// expected-error@-1 {{incomplete type}} +bar a2(0); + +incomplete a3[3](1,2,3); +// expected-error@-1 {{incomplete type}} + +struct qux : foo { +}; +qux a4(0); + +struct fred { + foo a[3]; +}; +fred a5(0); diff --git a/clang/test/SemaCXX/paren-list-agg-init.cpp b/clang/test/SemaCXX/paren-list-agg-init.cpp index f60b20e..c1964a5 100644 --- a/clang/test/SemaCXX/paren-list-agg-init.cpp +++ b/clang/test/SemaCXX/paren-list-agg-init.cpp @@ -289,7 +289,7 @@ int test() { // used to crash S a(0, 1); S b(0); - S c(0, 0, 1); // beforecxx20-warning {{aggregate initialization of type 'S' from a parenthesized list of values is a C++20 extension}} + S c(0, 0, 1); S d {0, 1}; S e {0}; diff --git a/libcxx/test/libcxx/utilities/expected/expected.expected/transform_error.mandates.verify.cpp b/libcxx/test/libcxx/utilities/expected/expected.expected/transform_error.mandates.verify.cpp index 965e82a..3184356 100644 --- a/libcxx/test/libcxx/utilities/expected/expected.expected/transform_error.mandates.verify.cpp +++ b/libcxx/test/libcxx/utilities/expected/expected.expected/transform_error.mandates.verify.cpp @@ -6,6 +6,15 @@ // //===----------------------------------------------------------------------===// +// https://github.com/llvm/llvm-project/pull/76232 breaks this libc++ test. +// The fix would be to update this file. The issue is that the CI uses 2 +// versions of Clang-18 +// - An older nightly build as the main compiler +// - A freshly bootstrap build +// This means the test can't be used until the nightly build is updated. +// TODO(mordante) Reenable clang-18. +// UNSUPPORTED: clang-18 + // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 // Test the mandates diff --git a/libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp b/libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp index 09aa133..d9f65e9 100644 --- a/libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp +++ b/libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp @@ -6,6 +6,15 @@ // //===----------------------------------------------------------------------===// +// https://github.com/llvm/llvm-project/pull/76232 breaks this libc++ test. +// The fix would be to update this file. The issue is that the CI uses 2 +// versions of Clang-18 +// - An older nightly build as the main compiler +// - A freshly bootstrap build +// This means the test can't be used until the nightly build is updated. +// TODO(mordante) Reenable clang-18. +// UNSUPPORTED: clang-18 + // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 // Test the mandates -- cgit v1.1 From 31626dadcef86e48bcc44e86e4411578094c8739 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Fri, 5 Jan 2024 13:50:44 -0500 Subject: [llvm][NFC] Refactor AutoUpgrader arm/aarch64 (#74145) Break out and refactor AArch64 & ARM intrinsic updating. There's a fair amount of comonality, but let's avoid continually checking the same prefixes. --- llvm/lib/IR/AutoUpgrade.cpp | 499 ++++++++++++---------- llvm/test/Assembler/autoupgrade-thread-pointer.ll | 4 +- 2 files changed, 284 insertions(+), 219 deletions(-) diff --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp index 6b54047..3a3b41fb 100644 --- a/llvm/lib/IR/AutoUpgrade.cpp +++ b/llvm/lib/IR/AutoUpgrade.cpp @@ -621,6 +621,284 @@ static bool UpgradeX86IntrinsicFunction(Function *F, StringRef Name, return false; } +// Upgrade ARM (IsArm) or Aarch64 (!IsArm) intrinsic fns. Return true iff so. +// IsArm: 'arm.*', !IsArm: 'aarch64.*'. +static bool UpgradeArmOrAarch64IntrinsicFunction(bool IsArm, Function *F, + StringRef Name, + Function *&NewFn) { + if (Name.starts_with("rbit")) { + // '(arm|aarch64).rbit'. + NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::bitreverse, + F->arg_begin()->getType()); + return true; + } + + if (Name == "thread.pointer") { + // '(arm|aarch64).thread.pointer'. + NewFn = + Intrinsic::getDeclaration(F->getParent(), Intrinsic::thread_pointer); + return true; + } + + bool Neon = Name.consume_front("neon."); + if (Neon) { + // '(arm|aarch64).neon.*'. + // Changed in 12.0: bfdot accept v4bf16 and v8bf16 instead of v8i8 and + // v16i8 respectively. + if (Name.consume_front("bfdot.")) { + // (arm|aarch64).neon.bfdot.*'. + Intrinsic::ID ID = StringSwitch(Name) + .Cases("v2f32.v8i8", "v4f32.v16i8", + IsArm ? Intrinsic::arm_neon_bfdot + : Intrinsic::aarch64_neon_bfdot) + .Default(Intrinsic::not_intrinsic); + if (ID != Intrinsic::not_intrinsic) { + size_t OperandWidth = F->getReturnType()->getPrimitiveSizeInBits(); + assert((OperandWidth == 64 || OperandWidth == 128) && + "Unexpected operand width"); + LLVMContext &Ctx = F->getParent()->getContext(); + std::array Tys{ + {F->getReturnType(), + FixedVectorType::get(Type::getBFloatTy(Ctx), OperandWidth / 16)}}; + NewFn = Intrinsic::getDeclaration(F->getParent(), ID, Tys); + return true; + } + return false; // No other '(arm|aarch64).neon.bfdot.*'. + } + + // Changed in 12.0: bfmmla, bfmlalb and bfmlalt are not polymorphic + // anymore and accept v8bf16 instead of v16i8. + if (Name.consume_front("bfm")) { + // (arm|aarch64).neon.bfm*'. + if (Name.consume_back(".v4f32.v16i8")) { + // (arm|aarch64).neon.bfm*.v4f32.v16i8'. + Intrinsic::ID ID = + StringSwitch(Name) + .Case("mla", IsArm ? Intrinsic::arm_neon_bfmmla + : Intrinsic::aarch64_neon_bfmmla) + .Case("lalb", IsArm ? Intrinsic::arm_neon_bfmlalb + : Intrinsic::aarch64_neon_bfmlalb) + .Case("lalt", IsArm ? Intrinsic::arm_neon_bfmlalt + : Intrinsic::aarch64_neon_bfmlalt) + .Default(Intrinsic::not_intrinsic); + if (ID != Intrinsic::not_intrinsic) { + NewFn = Intrinsic::getDeclaration(F->getParent(), ID); + return true; + } + return false; // No other '(arm|aarch64).neon.bfm*.v16i8'. + } + return false; // No other '(arm|aarch64).neon.bfm*. + } + // Continue on to Aarch64 Neon or Arm Neon. + } + // Continue on to Arm or Aarch64. + + if (IsArm) { + // 'arm.*'. + if (Neon) { + // 'arm.neon.*'. + Intrinsic::ID ID = StringSwitch(Name) + .StartsWith("vclz.", Intrinsic::ctlz) + .StartsWith("vcnt.", Intrinsic::ctpop) + .StartsWith("vqadds.", Intrinsic::sadd_sat) + .StartsWith("vqaddu.", Intrinsic::uadd_sat) + .StartsWith("vqsubs.", Intrinsic::ssub_sat) + .StartsWith("vqsubu.", Intrinsic::usub_sat) + .Default(Intrinsic::not_intrinsic); + if (ID != Intrinsic::not_intrinsic) { + NewFn = Intrinsic::getDeclaration(F->getParent(), ID, + F->arg_begin()->getType()); + return true; + } + + if (Name.consume_front("vst")) { + // 'arm.neon.vst*'. + static const Regex vstRegex("^([1234]|[234]lane)\\.v[a-z0-9]*$"); + SmallVector Groups; + if (vstRegex.match(Name, &Groups)) { + static const Intrinsic::ID StoreInts[] = { + Intrinsic::arm_neon_vst1, Intrinsic::arm_neon_vst2, + Intrinsic::arm_neon_vst3, Intrinsic::arm_neon_vst4}; + + static const Intrinsic::ID StoreLaneInts[] = { + Intrinsic::arm_neon_vst2lane, Intrinsic::arm_neon_vst3lane, + Intrinsic::arm_neon_vst4lane}; + + auto fArgs = F->getFunctionType()->params(); + Type *Tys[] = {fArgs[0], fArgs[1]}; + if (Groups[1].size() == 1) + NewFn = Intrinsic::getDeclaration(F->getParent(), + StoreInts[fArgs.size() - 3], Tys); + else + NewFn = Intrinsic::getDeclaration( + F->getParent(), StoreLaneInts[fArgs.size() - 5], Tys); + return true; + } + return false; // No other 'arm.neon.vst*'. + } + + return false; // No other 'arm.neon.*'. + } + + if (Name.consume_front("mve.")) { + // 'arm.mve.*'. + if (Name == "vctp64") { + if (cast(F->getReturnType())->getNumElements() == 4) { + // A vctp64 returning a v4i1 is converted to return a v2i1. Rename + // the function and deal with it below in UpgradeIntrinsicCall. + rename(F); + return true; + } + return false; // Not 'arm.mve.vctp64'. + } + + // These too are changed to accept a v2i1 instead of the old v4i1. + if (Name.consume_back(".v4i1")) { + // 'arm.mve.*.v4i1'. + if (Name.consume_back(".predicated.v2i64.v4i32")) + // 'arm.mve.*.predicated.v2i64.v4i32.v4i1' + return Name == "mull.int" || Name == "vqdmull"; + + if (Name.consume_back(".v2i64")) { + // 'arm.mve.*.v2i64.v4i1' + bool IsGather = Name.consume_front("vldr.gather."); + if (IsGather || Name.consume_front("vstr.scatter.")) { + if (Name.consume_front("base.")) { + // Optional 'wb.' prefix. + Name.consume_front("wb."); + // 'arm.mve.(vldr.gather|vstr.scatter).base.(wb.)? + // predicated.v2i64.v2i64.v4i1'. + return Name == "predicated.v2i64"; + } + + if (Name.consume_front("offset.predicated.")) + return Name == (IsGather ? "v2i64.p0i64" : "p0i64.v2i64") || + Name == (IsGather ? "v2i64.p0" : "p0.v2i64"); + + // No other 'arm.mve.(vldr.gather|vstr.scatter).*.v2i64.v4i1'. + return false; + } + + return false; // No other 'arm.mve.*.v2i64.v4i1'. + } + return false; // No other 'arm.mve.*.v4i1'. + } + return false; // No other 'arm.mve.*'. + } + + if (Name.consume_front("cde.vcx")) { + // 'arm.cde.vcx*'. + if (Name.consume_back(".predicated.v2i64.v4i1")) + // 'arm.cde.vcx*.predicated.v2i64.v4i1'. + return Name == "1q" || Name == "1qa" || Name == "2q" || Name == "2qa" || + Name == "3q" || Name == "3qa"; + + return false; // No other 'arm.cde.vcx*'. + } + } else { + // 'aarch64.*'. + if (Neon) { + // 'aarch64.neon.*'. + Intrinsic::ID ID = StringSwitch(Name) + .StartsWith("frintn", Intrinsic::roundeven) + .StartsWith("rbit", Intrinsic::bitreverse) + .Default(Intrinsic::not_intrinsic); + if (ID != Intrinsic::not_intrinsic) { + NewFn = Intrinsic::getDeclaration(F->getParent(), ID, + F->arg_begin()->getType()); + return true; + } + + if (Name.starts_with("addp")) { + // 'aarch64.neon.addp*'. + if (F->arg_size() != 2) + return false; // Invalid IR. + VectorType *Ty = dyn_cast(F->getReturnType()); + if (Ty && Ty->getElementType()->isFloatingPointTy()) { + NewFn = Intrinsic::getDeclaration(F->getParent(), + Intrinsic::aarch64_neon_faddp, Ty); + return true; + } + } + return false; // No other 'aarch64.neon.*'. + } + if (Name.consume_front("sve.")) { + // 'aarch64.sve.*'. + if (Name.consume_front("bf")) { + if (Name.consume_back(".lane")) { + // 'aarch64.sve.bf*.lane'. + Intrinsic::ID ID = + StringSwitch(Name) + .Case("dot", Intrinsic::aarch64_sve_bfdot_lane_v2) + .Case("mlalb", Intrinsic::aarch64_sve_bfmlalb_lane_v2) + .Case("mlalt", Intrinsic::aarch64_sve_bfmlalt_lane_v2) + .Default(Intrinsic::not_intrinsic); + if (ID != Intrinsic::not_intrinsic) { + NewFn = Intrinsic::getDeclaration(F->getParent(), ID); + return true; + } + return false; // No other 'aarch64.sve.bf*.lane'. + } + return false; // No other 'aarch64.sve.bf*'. + } + + if (Name.consume_front("ld")) { + // 'aarch64.sve.ld*'. + static const Regex LdRegex("^[234](.nxv[a-z0-9]+|$)"); + if (LdRegex.match(Name)) { + Type *ScalarTy = + dyn_cast(F->getReturnType())->getElementType(); + ElementCount EC = dyn_cast(F->arg_begin()->getType()) + ->getElementCount(); + Type *Ty = VectorType::get(ScalarTy, EC); + static const Intrinsic::ID LoadIDs[] = { + Intrinsic::aarch64_sve_ld2_sret, + Intrinsic::aarch64_sve_ld3_sret, + Intrinsic::aarch64_sve_ld4_sret, + }; + NewFn = Intrinsic::getDeclaration(F->getParent(), + LoadIDs[Name[0] - '2'], Ty); + return true; + } + return false; // No other 'aarch64.sve.ld*'. + } + + if (Name.consume_front("tuple.")) { + // 'aarch64.sve.tuple.*'. + if (Name.starts_with("get")) { + // 'aarch64.sve.tuple.get*'. + Type *Tys[] = {F->getReturnType(), F->arg_begin()->getType()}; + NewFn = Intrinsic::getDeclaration(F->getParent(), + Intrinsic::vector_extract, Tys); + return true; + } + + if (Name.starts_with("set")) { + // 'aarch64.sve.tuple.set*'. + auto Args = F->getFunctionType()->params(); + Type *Tys[] = {Args[0], Args[2], Args[1]}; + NewFn = Intrinsic::getDeclaration(F->getParent(), + Intrinsic::vector_insert, Tys); + return true; + } + + static const Regex CreateTupleRegex("^create[234](.nxv[a-z0-9]+|$)"); + if (CreateTupleRegex.match(Name)) { + // 'aarch64.sve.tuple.create*'. + auto Args = F->getFunctionType()->params(); + Type *Tys[] = {F->getReturnType(), Args[1]}; + NewFn = Intrinsic::getDeclaration(F->getParent(), + Intrinsic::vector_insert, Tys); + return true; + } + return false; // No other 'aarch64.sve.tuple.*'. + } + return false; // No other 'aarch64.sve.*'. + } + } + return false; // No other 'arm.*', 'aarch64.*'. +} + static Intrinsic::ID ShouldUpgradeNVPTXBF16Intrinsic(StringRef Name) { if (Name.consume_front("abs.")) return StringSwitch(Name) @@ -713,225 +991,12 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) { switch (Name[0]) { default: break; case 'a': { - if (Name.starts_with("arm.rbit") || Name.starts_with("aarch64.rbit")) { - NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::bitreverse, - F->arg_begin()->getType()); - return true; - } - if (Name.starts_with("aarch64.neon.frintn")) { - NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::roundeven, - F->arg_begin()->getType()); - return true; - } - if (Name.starts_with("aarch64.neon.rbit")) { - NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::bitreverse, - F->arg_begin()->getType()); - return true; - } - if (Name == "aarch64.sve.bfdot.lane") { - NewFn = Intrinsic::getDeclaration(F->getParent(), - Intrinsic::aarch64_sve_bfdot_lane_v2); - return true; - } - if (Name == "aarch64.sve.bfmlalb.lane") { - NewFn = Intrinsic::getDeclaration(F->getParent(), - Intrinsic::aarch64_sve_bfmlalb_lane_v2); - return true; - } - if (Name == "aarch64.sve.bfmlalt.lane") { - NewFn = Intrinsic::getDeclaration(F->getParent(), - Intrinsic::aarch64_sve_bfmlalt_lane_v2); - return true; - } - static const Regex LdRegex("^aarch64\\.sve\\.ld[234](.nxv[a-z0-9]+|$)"); - if (LdRegex.match(Name)) { - Type *ScalarTy = - dyn_cast(F->getReturnType())->getElementType(); - ElementCount EC = - dyn_cast(F->arg_begin()->getType())->getElementCount(); - Type *Ty = VectorType::get(ScalarTy, EC); - Intrinsic::ID ID = - StringSwitch(Name) - .StartsWith("aarch64.sve.ld2", Intrinsic::aarch64_sve_ld2_sret) - .StartsWith("aarch64.sve.ld3", Intrinsic::aarch64_sve_ld3_sret) - .StartsWith("aarch64.sve.ld4", Intrinsic::aarch64_sve_ld4_sret) - .Default(Intrinsic::not_intrinsic); - NewFn = Intrinsic::getDeclaration(F->getParent(), ID, Ty); - return true; - } - if (Name.starts_with("aarch64.sve.tuple.get")) { - Type *Tys[] = {F->getReturnType(), F->arg_begin()->getType()}; - NewFn = Intrinsic::getDeclaration(F->getParent(), - Intrinsic::vector_extract, Tys); - return true; - } - if (Name.starts_with("aarch64.sve.tuple.set")) { - auto Args = F->getFunctionType()->params(); - Type *Tys[] = {Args[0], Args[2], Args[1]}; - NewFn = Intrinsic::getDeclaration(F->getParent(), - Intrinsic::vector_insert, Tys); - return true; - } - static const Regex CreateTupleRegex( - "^aarch64\\.sve\\.tuple\\.create[234](.nxv[a-z0-9]+|$)"); - if (CreateTupleRegex.match(Name)) { - auto Args = F->getFunctionType()->params(); - Type *Tys[] = {F->getReturnType(), Args[1]}; - NewFn = Intrinsic::getDeclaration(F->getParent(), - Intrinsic::vector_insert, Tys); - return true; - } - if (Name.starts_with("arm.neon.vclz")) { - NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::ctlz, - F->arg_begin()->getType()); - return true; - } - if (Name.starts_with("arm.neon.vcnt")) { - NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::ctpop, - F->arg_begin()->getType()); - return true; - } - static const Regex vstRegex("^arm\\.neon\\.vst([1234]|[234]lane)\\.v[a-z0-9]*$"); - if (vstRegex.match(Name)) { - static const Intrinsic::ID StoreInts[] = {Intrinsic::arm_neon_vst1, - Intrinsic::arm_neon_vst2, - Intrinsic::arm_neon_vst3, - Intrinsic::arm_neon_vst4}; - - static const Intrinsic::ID StoreLaneInts[] = { - Intrinsic::arm_neon_vst2lane, Intrinsic::arm_neon_vst3lane, - Intrinsic::arm_neon_vst4lane - }; - - auto fArgs = F->getFunctionType()->params(); - Type *Tys[] = {fArgs[0], fArgs[1]}; - if (!Name.contains("lane")) - NewFn = Intrinsic::getDeclaration(F->getParent(), - StoreInts[fArgs.size() - 3], Tys); - else - NewFn = Intrinsic::getDeclaration(F->getParent(), - StoreLaneInts[fArgs.size() - 5], Tys); - return true; - } - if (Name == "aarch64.thread.pointer" || Name == "arm.thread.pointer") { - NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::thread_pointer); - return true; - } - if (Name.starts_with("arm.neon.vqadds.")) { - NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::sadd_sat, - F->arg_begin()->getType()); - return true; - } - if (Name.starts_with("arm.neon.vqaddu.")) { - NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::uadd_sat, - F->arg_begin()->getType()); - return true; - } - if (Name.starts_with("arm.neon.vqsubs.")) { - NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::ssub_sat, - F->arg_begin()->getType()); - return true; - } - if (Name.starts_with("arm.neon.vqsubu.")) { - NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::usub_sat, - F->arg_begin()->getType()); - return true; - } - if (Name.starts_with("aarch64.neon.addp")) { - if (F->arg_size() != 2) - break; // Invalid IR. - VectorType *Ty = dyn_cast(F->getReturnType()); - if (Ty && Ty->getElementType()->isFloatingPointTy()) { - NewFn = Intrinsic::getDeclaration(F->getParent(), - Intrinsic::aarch64_neon_faddp, Ty); + bool IsArm = Name.consume_front("arm."); + if (IsArm || Name.consume_front("aarch64.")) { + if (UpgradeArmOrAarch64IntrinsicFunction(IsArm, F, Name, NewFn)) return true; - } - } - - // Changed in 12.0: bfdot accept v4bf16 and v8bf16 instead of v8i8 and v16i8 - // respectively - if ((Name.starts_with("arm.neon.bfdot.") || - Name.starts_with("aarch64.neon.bfdot.")) && - Name.ends_with("i8")) { - Intrinsic::ID IID = - StringSwitch(Name) - .Cases("arm.neon.bfdot.v2f32.v8i8", - "arm.neon.bfdot.v4f32.v16i8", - Intrinsic::arm_neon_bfdot) - .Cases("aarch64.neon.bfdot.v2f32.v8i8", - "aarch64.neon.bfdot.v4f32.v16i8", - Intrinsic::aarch64_neon_bfdot) - .Default(Intrinsic::not_intrinsic); - if (IID == Intrinsic::not_intrinsic) - break; - - size_t OperandWidth = F->getReturnType()->getPrimitiveSizeInBits(); - assert((OperandWidth == 64 || OperandWidth == 128) && - "Unexpected operand width"); - LLVMContext &Ctx = F->getParent()->getContext(); - std::array Tys {{ - F->getReturnType(), - FixedVectorType::get(Type::getBFloatTy(Ctx), OperandWidth / 16) - }}; - NewFn = Intrinsic::getDeclaration(F->getParent(), IID, Tys); - return true; - } - - // Changed in 12.0: bfmmla, bfmlalb and bfmlalt are not polymorphic anymore - // and accept v8bf16 instead of v16i8 - if ((Name.starts_with("arm.neon.bfm") || - Name.starts_with("aarch64.neon.bfm")) && - Name.ends_with(".v4f32.v16i8")) { - Intrinsic::ID IID = - StringSwitch(Name) - .Case("arm.neon.bfmmla.v4f32.v16i8", - Intrinsic::arm_neon_bfmmla) - .Case("arm.neon.bfmlalb.v4f32.v16i8", - Intrinsic::arm_neon_bfmlalb) - .Case("arm.neon.bfmlalt.v4f32.v16i8", - Intrinsic::arm_neon_bfmlalt) - .Case("aarch64.neon.bfmmla.v4f32.v16i8", - Intrinsic::aarch64_neon_bfmmla) - .Case("aarch64.neon.bfmlalb.v4f32.v16i8", - Intrinsic::aarch64_neon_bfmlalb) - .Case("aarch64.neon.bfmlalt.v4f32.v16i8", - Intrinsic::aarch64_neon_bfmlalt) - .Default(Intrinsic::not_intrinsic); - if (IID == Intrinsic::not_intrinsic) - break; - - std::array Tys; - NewFn = Intrinsic::getDeclaration(F->getParent(), IID, Tys); - return true; - } - - if (Name == "arm.mve.vctp64" && - cast(F->getReturnType())->getNumElements() == 4) { - // A vctp64 returning a v4i1 is converted to return a v2i1. Rename the - // function and deal with it below in UpgradeIntrinsicCall. - rename(F); - return true; + break; } - // These too are changed to accept a v2i1 insteead of the old v4i1. - if (Name == "arm.mve.mull.int.predicated.v2i64.v4i32.v4i1" || - Name == "arm.mve.vqdmull.predicated.v2i64.v4i32.v4i1" || - Name == "arm.mve.vldr.gather.base.predicated.v2i64.v2i64.v4i1" || - Name == "arm.mve.vldr.gather.base.wb.predicated.v2i64.v2i64.v4i1" || - Name == - "arm.mve.vldr.gather.offset.predicated.v2i64.p0i64.v2i64.v4i1" || - Name == "arm.mve.vldr.gather.offset.predicated.v2i64.p0.v2i64.v4i1" || - Name == "arm.mve.vstr.scatter.base.predicated.v2i64.v2i64.v4i1" || - Name == "arm.mve.vstr.scatter.base.wb.predicated.v2i64.v2i64.v4i1" || - Name == - "arm.mve.vstr.scatter.offset.predicated.p0i64.v2i64.v2i64.v4i1" || - Name == "arm.mve.vstr.scatter.offset.predicated.p0.v2i64.v2i64.v4i1" || - Name == "arm.cde.vcx1q.predicated.v2i64.v4i1" || - Name == "arm.cde.vcx1qa.predicated.v2i64.v4i1" || - Name == "arm.cde.vcx2q.predicated.v2i64.v4i1" || - Name == "arm.cde.vcx2qa.predicated.v2i64.v4i1" || - Name == "arm.cde.vcx3q.predicated.v2i64.v4i1" || - Name == "arm.cde.vcx3qa.predicated.v2i64.v4i1") - return true; if (Name.consume_front("amdgcn.")) { if (Name == "alignbit") { diff --git a/llvm/test/Assembler/autoupgrade-thread-pointer.ll b/llvm/test/Assembler/autoupgrade-thread-pointer.ll index 2eaabb4..b1ed15a 100644 --- a/llvm/test/Assembler/autoupgrade-thread-pointer.ll +++ b/llvm/test/Assembler/autoupgrade-thread-pointer.ll @@ -5,14 +5,14 @@ declare ptr @llvm.aarch64.thread.pointer() declare ptr @llvm.arm.thread.pointer() define ptr @test1() { -; CHECK: test1() +; CHECK-LABEL: define ptr @test1() ; CHECK: call ptr @llvm.thread.pointer() %1 = call ptr @llvm.aarch64.thread.pointer() ret ptr %1 } define ptr @test2() { -; CHECK: test2() +; CHECK-LABEL: define ptr @test2() ; CHECK: call ptr @llvm.thread.pointer() %1 = call ptr @llvm.arm.thread.pointer() ret ptr %1 -- cgit v1.1 From 8d6784db04ee5d925a2d036a68f00a7c124c6cf9 Mon Sep 17 00:00:00 2001 From: Jordan Rupprecht Date: Fri, 5 Jan 2024 11:07:42 -0800 Subject: [bazel][libc][math] Add missing nan(f|l) deps After 0504e932880e0c4c333baeba9b8d674c5b9ae316 --- utils/bazel/llvm-project-overlay/libc/BUILD.bazel | 25 ++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel index 7d2bb29..f222831 100644 --- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel @@ -540,6 +540,7 @@ libc_support_library( ":__support_cpp_bit", ":__support_cpp_limits", ":__support_cpp_optional", + ":__support_cpp_string_view", ":__support_ctype_utils", ":__support_fputil_dyadic_float", ":__support_fputil_fenv_impl", @@ -1874,11 +1875,29 @@ libc_math_function(name = "llroundf") libc_math_function(name = "llroundl") -libc_math_function(name = "nan") +libc_math_function( + name = "nan", + additional_deps = [ + ":__support_str_to_float", + ":errno", + ], +) -libc_math_function(name = "nanf") +libc_math_function( + name = "nanf", + additional_deps = [ + ":__support_str_to_float", + ":errno", + ], +) -libc_math_function(name = "nanl") +libc_math_function( + name = "nanl", + additional_deps = [ + ":__support_str_to_float", + ":errno", + ], +) libc_math_function(name = "nearbyint") -- cgit v1.1 From 93d2e49b6aa6904620a7e9b559c04ec8756dc596 Mon Sep 17 00:00:00 2001 From: Shubham Sandeep Rastogi Date: Fri, 5 Jan 2024 11:15:18 -0800 Subject: Fix file index verifier when there is no file name in the prologue. (#77004) If there is no file name in the prologue of a line table, the verifier will try to verify the file index, which will be set to 1 by default. This will cause the DWARF verifier to throw an error even if there is no error. rdar://114476503 rdar://114343624 --- llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp | 9 +- llvm/test/tools/llvm-dwarfdump/verify-no-file.yaml | 356 +++++++++++++++++++++ 2 files changed, 363 insertions(+), 2 deletions(-) create mode 100644 llvm/test/tools/llvm-dwarfdump/verify-no-file.yaml diff --git a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp index 43ed60d..1837781 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp @@ -940,8 +940,13 @@ void DWARFVerifier::verifyDebugLineRows() { OS << '\n'; } - // Verify file index. - if (!LineTable->hasFileAtIndex(Row.File)) { + // If the prologue contains no file names and the line table has only one + // row, do not verify the file index, this is a line table of an empty + // file with an end_sequence, but the DWARF standard sets the file number + // to 1 by default, otherwise verify file index. + if (!(LineTable->Prologue.FileNames.size() == 0 && + LineTable->Rows.size() == 1) && + !LineTable->hasFileAtIndex(Row.File)) { ++NumDebugLineErrors; error() << ".debug_line[" << format("0x%08" PRIx64, diff --git a/llvm/test/tools/llvm-dwarfdump/verify-no-file.yaml b/llvm/test/tools/llvm-dwarfdump/verify-no-file.yaml new file mode 100644 index 0000000..e43bb88 --- /dev/null +++ b/llvm/test/tools/llvm-dwarfdump/verify-no-file.yaml @@ -0,0 +1,356 @@ +# RUN: rm -rf %t && mkdir -p %t +# RUN: yaml2obj %s -o %t/test.o +# RUN: llvm-dwarfdump --debug-line --verify %t/test.o 2>&1 | FileCheck %s + +# CHECK-NOT: error: .debug_line[0x{{[0-9a-f]+}}][0] has invalid file index 1 (valid values are [1,0]): +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x100000C + cpusubtype: 0x0 + filetype: 0x1 + ncmds: 4 + sizeofcmds: 1000 + flags: 0x2000 + reserved: 0x0 +LoadCommands: + - cmd: LC_SEGMENT_64 + cmdsize: 872 + segname: '' + vmaddr: 0 + vmsize: 635 + fileoff: 1032 + filesize: 635 + maxprot: 7 + initprot: 7 + nsects: 10 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0x0 + size: 4 + offset: 0x408 + align: 2 + reloff: 0x0 + nreloc: 0 + flags: 0x80000400 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: C0035FD6 + - sectname: __debug_abbrev + segname: __DWARF + addr: 0x4 + size: 50 + offset: 0x40C + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x2000000 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + - sectname: __debug_info + segname: __DWARF + addr: 0x36 + size: 76 + offset: 0x43E + align: 0 + reloff: 0x688 + nreloc: 2 + flags: 0x2000000 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + relocations: + - address: 0x33 + symbolnum: 1 + pcrel: false + length: 3 + extern: false + type: 0 + scattered: false + value: 0 + - address: 0x26 + symbolnum: 1 + pcrel: false + length: 3 + extern: false + type: 0 + scattered: false + value: 0 + - sectname: __debug_str + segname: __DWARF + addr: 0x82 + size: 196 + offset: 0x48A + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x2000000 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + - sectname: __apple_names + segname: __DWARF + addr: 0x146 + size: 88 + offset: 0x54E + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x2000000 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 485341480100000002000000020000000C000000000000000100000001000600FFFFFFFF000000008973880BEB28616A3800000048000000B8000000010000003200000000000000BC000000010000003200000000000000 + - sectname: __apple_objc + segname: __DWARF + addr: 0x19E + size: 36 + offset: 0x5A6 + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x2000000 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 485341480100000001000000000000000C000000000000000100000001000600FFFFFFFF + - sectname: __apple_namespac + segname: __DWARF + addr: 0x1C2 + size: 36 + offset: 0x5CA + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x2000000 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 485341480100000001000000000000000C000000000000000100000001000600FFFFFFFF + - sectname: __apple_types + segname: __DWARF + addr: 0x1E6 + size: 44 + offset: 0x5EE + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x2000000 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 48534148010000000100000000000000140000000000000003000000010006000300050004000B00FFFFFFFF + - sectname: __compact_unwind + segname: __LD + addr: 0x218 + size: 32 + offset: 0x620 + align: 3 + reloff: 0x698 + nreloc: 1 + flags: 0x2000000 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: '0000000000000000040000000000000200000000000000000000000000000000' + relocations: + - address: 0x0 + symbolnum: 1 + pcrel: false + length: 3 + extern: false + type: 0 + scattered: false + value: 0 + - sectname: __debug_line + segname: __DWARF + addr: 0x238 + size: 67 + offset: 0x640 + align: 0 + reloff: 0x6A0 + nreloc: 1 + flags: 0x2000000 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + relocations: + - address: 0x35 + symbolnum: 1 + pcrel: false + length: 3 + extern: false + type: 0 + scattered: false + value: 0 + - cmd: LC_BUILD_VERSION + cmdsize: 24 + platform: 1 + minos: 917504 + sdk: 918528 + ntools: 0 + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 1704 + nsyms: 3 + stroff: 1752 + strsize: 24 + - cmd: LC_DYSYMTAB + cmdsize: 80 + ilocalsym: 0 + nlocalsym: 2 + iextdefsym: 2 + nextdefsym: 1 + iundefsym: 3 + nundefsym: 0 + tocoff: 0 + ntoc: 0 + modtaboff: 0 + nmodtab: 0 + extrefsymoff: 0 + nextrefsyms: 0 + indirectsymoff: 0 + nindirectsyms: 0 + extreloff: 0 + nextrel: 0 + locreloff: 0 + nlocrel: 0 +LinkEditData: + NameList: + - n_strx: 16 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 0 + - n_strx: 10 + n_type: 0xE + n_sect: 9 + n_desc: 0 + n_value: 536 + - n_strx: 1 + n_type: 0xF + n_sect: 1 + n_desc: 0 + n_value: 0 + StringTable: + - '' + - __Z3foov + - ltmp1 + - ltmp0 + - '' + - '' +DWARF: + debug_str: + - 'Apple clang version 16.0.0 (clang-1600.0.9.14)' + - '/tmp/test.cpp' + - '/Library/Developer/CommandLineTools/SDKs/MacOSX14.4.sdk' + - MacOSX14.4.sdk + - '/Users/shubham/Development/llvm-project/build_ninja' + - foo + - _Z3foov + debug_abbrev: + - ID: 0 + Table: + - Code: 0x1 + Tag: DW_TAG_compile_unit + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_producer + Form: DW_FORM_strp + - Attribute: DW_AT_language + Form: DW_FORM_data2 + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_LLVM_sysroot + Form: DW_FORM_strp + - Attribute: DW_AT_APPLE_sdk + Form: DW_FORM_strp + - Attribute: DW_AT_stmt_list + Form: DW_FORM_sec_offset + - Attribute: DW_AT_comp_dir + Form: DW_FORM_strp + - Attribute: DW_AT_low_pc + Form: DW_FORM_addr + - Attribute: DW_AT_high_pc + Form: DW_FORM_data4 + - Code: 0x2 + Tag: DW_TAG_subprogram + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_low_pc + Form: DW_FORM_addr + - Attribute: DW_AT_high_pc + Form: DW_FORM_data4 + - Attribute: DW_AT_APPLE_omit_frame_ptr + Form: DW_FORM_flag_present + - Attribute: DW_AT_frame_base + Form: DW_FORM_exprloc + - Attribute: DW_AT_linkage_name + Form: DW_FORM_strp + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_decl_file + Form: DW_FORM_data1 + - Attribute: DW_AT_decl_line + Form: DW_FORM_data1 + - Attribute: DW_AT_external + Form: DW_FORM_flag_present + debug_info: + - Length: 0x48 + Version: 4 + AbbrevTableID: 0 + AbbrOffset: 0x0 + AddrSize: 8 + Entries: + - AbbrCode: 0x1 + Values: + - Value: 0x0 + - Value: 0x4 + - Value: 0x2F + - Value: 0x3D + - Value: 0x75 + - Value: 0x0 + - Value: 0x84 + - Value: 0x0 + - Value: 0x4 + - AbbrCode: 0x2 + Values: + - Value: 0x0 + - Value: 0x4 + - Value: 0x1 + - Value: 0x1 + BlockData: [ 0x6F ] + - Value: 0xBC + - Value: 0xB8 + - Value: 0x1 + - Value: 0x1 + - Value: 0x1 + - AbbrCode: 0x0 + debug_line: + - Length: 38 + Version: 4 + PrologueLength: 29 + MinInstLength: 1 + MaxOpsPerInst: 1 + DefaultIsStmt: 1 + LineBase: 251 + LineRange: 14 + OpcodeBase: 13 + StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ] + IncludeDirs: + - '/tmp' + Files: + - Name: '' + DirIdx: 10 + ModTime: 11 + Length: 12 + Opcodes: + - Opcode: DW_LNS_extended_op + ExtLen: 1 + SubOpcode: DW_LNE_end_sequence + Data: 0 +... -- cgit v1.1 From f9aba820eb6478a617145eb690ba8b06490d7ac5 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Fri, 5 Jan 2024 14:34:53 -0500 Subject: [gn] port a0e6b7c04292 --- llvm/utils/gn/secondary/llvm/utils/TableGen/BUILD.gn | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/utils/gn/secondary/llvm/utils/TableGen/BUILD.gn b/llvm/utils/gn/secondary/llvm/utils/TableGen/BUILD.gn index 36d5b10..ac0dd86 100644 --- a/llvm/utils/gn/secondary/llvm/utils/TableGen/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/utils/TableGen/BUILD.gn @@ -63,6 +63,7 @@ executable("llvm-tblgen") { "InfoByHwMode.cpp", "InstrDocsEmitter.cpp", "InstrInfoEmitter.cpp", + "MacroFusionPredicatorEmitter.cpp", "OptEmitter.cpp", "OptParserEmitter.cpp", "OptRSTEmitter.cpp", -- cgit v1.1 From f22dc88759a53d4224c17d3833a359ef5674b4ea Mon Sep 17 00:00:00 2001 From: Shubham Sandeep Rastogi Date: Fri, 5 Jan 2024 12:13:36 -0800 Subject: [NFC] Address review feedback from PR #77004 (#77134) Accidentally didn't commit the review feedback before merging the PR --- llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp | 4 ++-- llvm/test/tools/llvm-dwarfdump/verify-no-file.yaml | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp index 1837781..d25b732 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp @@ -944,8 +944,8 @@ void DWARFVerifier::verifyDebugLineRows() { // row, do not verify the file index, this is a line table of an empty // file with an end_sequence, but the DWARF standard sets the file number // to 1 by default, otherwise verify file index. - if (!(LineTable->Prologue.FileNames.size() == 0 && - LineTable->Rows.size() == 1) && + if ((LineTable->Prologue.FileNames.size() || + LineTable->Rows.size() != 1) && !LineTable->hasFileAtIndex(Row.File)) { ++NumDebugLineErrors; error() << ".debug_line[" diff --git a/llvm/test/tools/llvm-dwarfdump/verify-no-file.yaml b/llvm/test/tools/llvm-dwarfdump/verify-no-file.yaml index e43bb88..fc25fce 100644 --- a/llvm/test/tools/llvm-dwarfdump/verify-no-file.yaml +++ b/llvm/test/tools/llvm-dwarfdump/verify-no-file.yaml @@ -1,6 +1,5 @@ -# RUN: rm -rf %t && mkdir -p %t -# RUN: yaml2obj %s -o %t/test.o -# RUN: llvm-dwarfdump --debug-line --verify %t/test.o 2>&1 | FileCheck %s +# RUN: yaml2obj %s -o %t.o +# RUN: llvm-dwarfdump --debug-line --verify %t.o 2>&1 | FileCheck %s # CHECK-NOT: error: .debug_line[0x{{[0-9a-f]+}}][0] has invalid file index 1 (valid values are [1,0]): --- !mach-o -- cgit v1.1 From 5121e2cffd23751360e71a8ac69b7462dae23aa8 Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Fri, 5 Jan 2024 14:29:34 -0600 Subject: [OpenMP] Change `__tgt_device_image` to point to the image (#77003) Summary: We use the OffloadBinary to contain bundled offloading objects used to support many images / targets at the same time. The `__tgt_device_info` struct used to contain a pointer to this underlying binary format, which contains information about the triple and architecture. We used to parse this in the runtime to do image verification. Recent changes removed the need for this to be used internally, as we just parse it out of the ELF directly. This patch sets the pointers up so they point to the ELF without requiring any further parsing. --- clang/test/Driver/linker-wrapper-image.c | 4 ++-- .../tools/clang-linker-wrapper/OffloadWrapper.cpp | 24 +++++++++++++++++++--- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/clang/test/Driver/linker-wrapper-image.c b/clang/test/Driver/linker-wrapper-image.c index a2a1996..40dde2e 100644 --- a/clang/test/Driver/linker-wrapper-image.c +++ b/clang/test/Driver/linker-wrapper-image.c @@ -19,8 +19,8 @@ // OPENMP-COFF: @__start_omp_offloading_entries = hidden constant [0 x %struct.__tgt_offload_entry] zeroinitializer, section "omp_offloading_entries$OA" // OPENMP-COFF-NEXT: @__stop_omp_offloading_entries = hidden constant [0 x %struct.__tgt_offload_entry] zeroinitializer, section "omp_offloading_entries$OZ" -// OPENMP: @.omp_offloading.device_image = internal unnamed_addr constant [[[SIZE:[0-9]+]] x i8] c"\10\FF\10\AD{{.*}}" -// OPENMP-NEXT: @.omp_offloading.device_images = internal unnamed_addr constant [1 x %__tgt_device_image] [%__tgt_device_image { ptr @.omp_offloading.device_image, ptr getelementptr inbounds ([[[SIZE]] x i8], ptr @.omp_offloading.device_image, i64 1, i64 0), ptr @__start_omp_offloading_entries, ptr @__stop_omp_offloading_entries }] +// OPENMP-NEXT: @.omp_offloading.device_image = internal unnamed_addr constant [[[SIZE:[0-9]+]] x i8] c"\10\FF\10\AD\01{{.*}}", section ".llvm.offloading", align 8 +// OPENMP-NEXT: @.omp_offloading.device_images = internal unnamed_addr constant [1 x %__tgt_device_image] [%__tgt_device_image { ptr getelementptr inbounds ([[[BEGIN:[0-9]+]] x i8], ptr @.omp_offloading.device_image, i64 1, i64 0), ptr getelementptr inbounds ([[[END:[0-9]+]] x i8], ptr @.omp_offloading.device_image, i64 1, i64 0), ptr @__start_omp_offloading_entries, ptr @__stop_omp_offloading_entries }] // OPENMP-NEXT: @.omp_offloading.descriptor = internal constant %__tgt_bin_desc { i32 1, ptr @.omp_offloading.device_images, ptr @__start_omp_offloading_entries, ptr @__stop_omp_offloading_entries } // OPENMP-NEXT: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @.omp_offloading.descriptor_reg, ptr null }] // OPENMP-NEXT: @llvm.global_dtors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @.omp_offloading.descriptor_unreg, ptr null }] diff --git a/clang/tools/clang-linker-wrapper/OffloadWrapper.cpp b/clang/tools/clang-linker-wrapper/OffloadWrapper.cpp index f4f500b..161374a 100644 --- a/clang/tools/clang-linker-wrapper/OffloadWrapper.cpp +++ b/clang/tools/clang-linker-wrapper/OffloadWrapper.cpp @@ -8,6 +8,7 @@ #include "OffloadWrapper.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/BinaryFormat/Magic.h" #include "llvm/Frontend/Offloading/Utility.h" #include "llvm/IR/Constants.h" #include "llvm/IR/GlobalVariable.h" @@ -121,19 +122,36 @@ GlobalVariable *createBinDesc(Module &M, ArrayRef> Bufs) { SmallVector ImagesInits; ImagesInits.reserve(Bufs.size()); for (ArrayRef Buf : Bufs) { + // We embed the full offloading entry so the binary utilities can parse it. auto *Data = ConstantDataArray::get(C, Buf); - auto *Image = new GlobalVariable(M, Data->getType(), /*isConstant*/ true, + auto *Image = new GlobalVariable(M, Data->getType(), /*isConstant=*/true, GlobalVariable::InternalLinkage, Data, ".omp_offloading.device_image"); Image->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); Image->setSection(".llvm.offloading"); Image->setAlignment(Align(object::OffloadBinary::getAlignment())); - auto *Size = ConstantInt::get(getSizeTTy(M), Buf.size()); + StringRef Binary(Buf.data(), Buf.size()); + assert(identify_magic(Binary) == file_magic::offload_binary && + "Invalid binary format"); + + // The device image struct contains the pointer to the beginning and end of + // the image stored inside of the offload binary. There should only be one + // of these for each buffer so we parse it out manually. + const auto *Header = + reinterpret_cast( + Binary.bytes_begin()); + const auto *Entry = reinterpret_cast( + Binary.bytes_begin() + Header->EntryOffset); + + auto *Begin = ConstantInt::get(getSizeTTy(M), Entry->ImageOffset); + auto *Size = + ConstantInt::get(getSizeTTy(M), Entry->ImageOffset + Entry->ImageSize); + Constant *ZeroBegin[] = {Zero, Begin}; Constant *ZeroSize[] = {Zero, Size}; auto *ImageB = - ConstantExpr::getGetElementPtr(Image->getValueType(), Image, ZeroZero); + ConstantExpr::getGetElementPtr(Image->getValueType(), Image, ZeroBegin); auto *ImageE = ConstantExpr::getGetElementPtr(Image->getValueType(), Image, ZeroSize); -- cgit v1.1 From 7c3bcc307a8fa9153a171f6abb4e8fdc91bd6030 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Sat, 6 Jan 2024 04:30:07 +0800 Subject: [InstCombine] Fold `switch(zext/sext(X))` into `switch(X)` (#76988) This patch folds `switch(zext/sext(X))` into `switch(X)`. The original motivation of this patch is to optimize a pattern found in cvc5. For example: ``` %bf.load.i = load i16, ptr %d_kind.i, align 8 %bf.clear.i = and i16 %bf.load.i, 1023 %bf.cast.i = zext nneg i16 %bf.clear.i to i32 switch i32 %bf.cast.i, label %if.else [ i32 335, label %if.then i32 303, label %if.then ] if.then: ; preds = %entry, %entry %d_children.i.i = getelementptr inbounds %"class.cvc5::internal::expr::NodeValue", ptr %0, i64 0, i32 3 %cmp.i.i.i.i.i = icmp eq i16 %bf.clear.i, 1023 %cond.i.i.i.i.i = select i1 %cmp.i.i.i.i.i, i32 -1, i32 %bf.cast.i ``` `%cmp.i.i.i.i.i` always evaluates to false because `%bf.clear.i` can only be 335 or 303. Folding `switch i32 %bf.cast.i` to `switch i16 %bf.clear.i` will help `CVP` to handle this case. See also https://github.com/llvm/llvm-project/pull/76928#issuecomment-1877055722. Compile-time impact: http://llvm-compile-time-tracker.com/compare.php?from=7954c57124b495fbdc73674d71f2e366e4afe522&to=502b13ed34e561d995ae1f724cf06d20008bd86f&stat=instructions:u |stage1-O3|stage1-ReleaseThinLTO|stage1-ReleaseLTO-g|stage1-O0-g|stage2-O3|stage2-O0-g|stage2-clang| |--|--|--|--|--|--|--| |+0.03%|+0.06%|+0.07%|+0.00%|-0.02%|-0.03%|+0.02%| --- .../InstCombine/InstructionCombining.cpp | 19 ++++ llvm/test/Transforms/InstCombine/phi.ll | 30 +++-- .../Transforms/InstCombine/switch-zext-sext.ll | 122 +++++++++++++++++++++ llvm/test/Transforms/PhaseOrdering/switch-sext.ll | 48 ++++++++ 4 files changed, 202 insertions(+), 17 deletions(-) create mode 100644 llvm/test/Transforms/InstCombine/switch-zext-sext.ll create mode 100644 llvm/test/Transforms/PhaseOrdering/switch-sext.ll diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp index e845bf3..7f2018b 100644 --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -3247,6 +3247,25 @@ Instruction *InstCombinerImpl::visitSwitchInst(SwitchInst &SI) { } } + // Fold switch(zext/sext(X)) into switch(X) if possible. + if (match(Cond, m_ZExtOrSExt(m_Value(Op0)))) { + bool IsZExt = isa(Cond); + Type *SrcTy = Op0->getType(); + unsigned NewWidth = SrcTy->getScalarSizeInBits(); + + if (all_of(SI.cases(), [&](const auto &Case) { + const APInt &CaseVal = Case.getCaseValue()->getValue(); + return IsZExt ? CaseVal.isIntN(NewWidth) + : CaseVal.isSignedIntN(NewWidth); + })) { + for (auto &Case : SI.cases()) { + APInt TruncatedCase = Case.getCaseValue()->getValue().trunc(NewWidth); + Case.setValue(ConstantInt::get(SI.getContext(), TruncatedCase)); + } + return replaceOperand(SI, 0, Op0); + } + } + KnownBits Known = computeKnownBits(Cond, 0, &SI); unsigned LeadingKnownZeros = Known.countMinLeadingZeros(); unsigned LeadingKnownOnes = Known.countMinLeadingOnes(); diff --git a/llvm/test/Transforms/InstCombine/phi.ll b/llvm/test/Transforms/InstCombine/phi.ll index 9081877..717f4c6 100644 --- a/llvm/test/Transforms/InstCombine/phi.ll +++ b/llvm/test/Transforms/InstCombine/phi.ll @@ -996,10 +996,9 @@ done: define i1 @PR24766(i8 %x1, i8 %x2, i8 %condition) { ; CHECK-LABEL: @PR24766( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[CONDITION:%.*]] to i32 -; CHECK-NEXT: switch i32 [[CONV]], label [[EPILOG:%.*]] [ -; CHECK-NEXT: i32 0, label [[SW1:%.*]] -; CHECK-NEXT: i32 1, label [[SW2:%.*]] +; CHECK-NEXT: switch i8 [[CONDITION:%.*]], label [[EPILOG:%.*]] [ +; CHECK-NEXT: i8 0, label [[SW1:%.*]] +; CHECK-NEXT: i8 1, label [[SW2:%.*]] ; CHECK-NEXT: ] ; CHECK: sw1: ; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X1:%.*]], [[X2:%.*]] @@ -1040,10 +1039,9 @@ epilog: define i1 @PR24766_no_constants(i8 %x1, i8 %x2, i8 %condition, i1 %another_condition) { ; CHECK-LABEL: @PR24766_no_constants( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[CONDITION:%.*]] to i32 -; CHECK-NEXT: switch i32 [[CONV]], label [[EPILOG:%.*]] [ -; CHECK-NEXT: i32 0, label [[SW1:%.*]] -; CHECK-NEXT: i32 1, label [[SW2:%.*]] +; CHECK-NEXT: switch i8 [[CONDITION:%.*]], label [[EPILOG:%.*]] [ +; CHECK-NEXT: i8 0, label [[SW1:%.*]] +; CHECK-NEXT: i8 1, label [[SW2:%.*]] ; CHECK-NEXT: ] ; CHECK: sw1: ; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X1:%.*]], [[X2:%.*]] @@ -1085,10 +1083,9 @@ epilog: define i1 @PR24766_two_constants(i8 %x1, i8 %x2, i8 %condition) { ; CHECK-LABEL: @PR24766_two_constants( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[CONDITION:%.*]] to i32 -; CHECK-NEXT: switch i32 [[CONV]], label [[EPILOG:%.*]] [ -; CHECK-NEXT: i32 0, label [[SW1:%.*]] -; CHECK-NEXT: i32 1, label [[SW2:%.*]] +; CHECK-NEXT: switch i8 [[CONDITION:%.*]], label [[EPILOG:%.*]] [ +; CHECK-NEXT: i8 0, label [[SW1:%.*]] +; CHECK-NEXT: i8 1, label [[SW2:%.*]] ; CHECK-NEXT: ] ; CHECK: sw1: ; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X1:%.*]], [[X2:%.*]] @@ -1128,11 +1125,10 @@ epilog: define i1 @PR24766_two_constants_two_var(i8 %x1, i8 %x2, i8 %condition) { ; CHECK-LABEL: @PR24766_two_constants_two_var( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[CONDITION:%.*]] to i32 -; CHECK-NEXT: switch i32 [[CONV]], label [[EPILOG:%.*]] [ -; CHECK-NEXT: i32 0, label [[SW1:%.*]] -; CHECK-NEXT: i32 1, label [[SW2:%.*]] -; CHECK-NEXT: i32 2, label [[SW3:%.*]] +; CHECK-NEXT: switch i8 [[CONDITION:%.*]], label [[EPILOG:%.*]] [ +; CHECK-NEXT: i8 0, label [[SW1:%.*]] +; CHECK-NEXT: i8 1, label [[SW2:%.*]] +; CHECK-NEXT: i8 2, label [[SW3:%.*]] ; CHECK-NEXT: ] ; CHECK: sw1: ; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X1:%.*]], [[X2:%.*]] diff --git a/llvm/test/Transforms/InstCombine/switch-zext-sext.ll b/llvm/test/Transforms/InstCombine/switch-zext-sext.ll new file mode 100644 index 0000000..c094413 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/switch-zext-sext.ll @@ -0,0 +1,122 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt %s -passes=instcombine -S | FileCheck %s + +define i1 @test_switch_with_zext(i16 %a, i1 %b, i1 %c) { +; CHECK-LABEL: define i1 @test_switch_with_zext( +; CHECK-SAME: i16 [[A:%.*]], i1 [[B:%.*]], i1 [[C:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: switch i16 [[A]], label [[SW_DEFAULT:%.*]] [ +; CHECK-NEXT: i16 37, label [[SW_BB:%.*]] +; CHECK-NEXT: i16 38, label [[SW_BB]] +; CHECK-NEXT: i16 39, label [[SW_BB]] +; CHECK-NEXT: ] +; CHECK: sw.bb: +; CHECK-NEXT: ret i1 [[B]] +; CHECK: sw.default: +; CHECK-NEXT: ret i1 [[C]] +; +entry: + %a.ext = zext i16 %a to i32 + switch i32 %a.ext, label %sw.default [ + i32 37, label %sw.bb + i32 38, label %sw.bb + i32 39, label %sw.bb + ] + +sw.bb: + ret i1 %b +sw.default: + ret i1 %c +} + +define i1 @test_switch_with_sext(i16 %a, i1 %b, i1 %c) { +; CHECK-LABEL: define i1 @test_switch_with_sext( +; CHECK-SAME: i16 [[A:%.*]], i1 [[B:%.*]], i1 [[C:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: switch i16 [[A]], label [[SW_DEFAULT:%.*]] [ +; CHECK-NEXT: i16 37, label [[SW_BB:%.*]] +; CHECK-NEXT: i16 38, label [[SW_BB]] +; CHECK-NEXT: i16 39, label [[SW_BB]] +; CHECK-NEXT: ] +; CHECK: sw.bb: +; CHECK-NEXT: ret i1 [[B]] +; CHECK: sw.default: +; CHECK-NEXT: ret i1 [[C]] +; +entry: + %a.ext = sext i16 %a to i32 + switch i32 %a.ext, label %sw.default [ + i32 37, label %sw.bb + i32 38, label %sw.bb + i32 39, label %sw.bb + ] + +sw.bb: + ret i1 %b +sw.default: + ret i1 %c +} + +; Negative tests + +define i1 @test_switch_with_zext_unreachable_case(i16 %a, i1 %b, i1 %c) { +; CHECK-LABEL: define i1 @test_switch_with_zext_unreachable_case( +; CHECK-SAME: i16 [[A:%.*]], i1 [[B:%.*]], i1 [[C:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[A_EXT:%.*]] = zext i16 [[A]] to i32 +; CHECK-NEXT: switch i32 [[A_EXT]], label [[SW_DEFAULT:%.*]] [ +; CHECK-NEXT: i32 37, label [[SW_BB:%.*]] +; CHECK-NEXT: i32 38, label [[SW_BB]] +; CHECK-NEXT: i32 39, label [[SW_BB]] +; CHECK-NEXT: i32 65537, label [[SW_BB]] +; CHECK-NEXT: ] +; CHECK: sw.bb: +; CHECK-NEXT: ret i1 [[B]] +; CHECK: sw.default: +; CHECK-NEXT: ret i1 [[C]] +; +entry: + %a.ext = zext i16 %a to i32 + switch i32 %a.ext, label %sw.default [ + i32 37, label %sw.bb + i32 38, label %sw.bb + i32 39, label %sw.bb + i32 65537, label %sw.bb + ] + +sw.bb: + ret i1 %b +sw.default: + ret i1 %c +} + +define i1 @test_switch_with_sext_unreachable_case(i16 %a, i1 %b, i1 %c) { +; CHECK-LABEL: define i1 @test_switch_with_sext_unreachable_case( +; CHECK-SAME: i16 [[A:%.*]], i1 [[B:%.*]], i1 [[C:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[A_EXT:%.*]] = sext i16 [[A]] to i32 +; CHECK-NEXT: switch i32 [[A_EXT]], label [[SW_DEFAULT:%.*]] [ +; CHECK-NEXT: i32 37, label [[SW_BB:%.*]] +; CHECK-NEXT: i32 38, label [[SW_BB]] +; CHECK-NEXT: i32 39, label [[SW_BB]] +; CHECK-NEXT: i32 -65537, label [[SW_BB]] +; CHECK-NEXT: ] +; CHECK: sw.bb: +; CHECK-NEXT: ret i1 [[B]] +; CHECK: sw.default: +; CHECK-NEXT: ret i1 [[C]] +; +entry: + %a.ext = sext i16 %a to i32 + switch i32 %a.ext, label %sw.default [ + i32 37, label %sw.bb + i32 38, label %sw.bb + i32 39, label %sw.bb + i32 -65537, label %sw.bb + ] + +sw.bb: + ret i1 %b +sw.default: + ret i1 %c +} diff --git a/llvm/test/Transforms/PhaseOrdering/switch-sext.ll b/llvm/test/Transforms/PhaseOrdering/switch-sext.ll new file mode 100644 index 0000000..e39771b --- /dev/null +++ b/llvm/test/Transforms/PhaseOrdering/switch-sext.ll @@ -0,0 +1,48 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S -passes='default' < %s | FileCheck %s + +define i8 @test_switch_with_sext_phi(i8 %code) { +; CHECK-LABEL: define noundef i8 @test_switch_with_sext_phi( +; CHECK-SAME: i8 [[CODE:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: switch i8 [[CODE]], label [[SW_EPILOG:%.*]] [ +; CHECK-NEXT: i8 76, label [[SW_BB3:%.*]] +; CHECK-NEXT: i8 108, label [[SW_BB2:%.*]] +; CHECK-NEXT: ] +; CHECK: sw.bb2: +; CHECK-NEXT: br label [[SW_EPILOG]] +; CHECK: sw.bb3: +; CHECK-NEXT: br label [[SW_EPILOG]] +; CHECK: sw.epilog: +; CHECK-NEXT: [[PEP_CODE:%.*]] = phi i8 [ 81, [[SW_BB3]] ], [ 113, [[SW_BB2]] ], [ [[CODE]], [[ENTRY:%.*]] ] +; CHECK-NEXT: ret i8 [[PEP_CODE]] +; +entry: + %conv = sext i8 %code to i32 + switch i32 %conv, label %sw.default [ + i32 105, label %sw.epilog + i32 73, label %sw.bb1 + i32 108, label %sw.bb2 + i32 76, label %sw.bb3 + i32 63, label %sw.bb4 + ] + +sw.bb1: + br label %sw.epilog + +sw.bb2: + br label %sw.epilog + +sw.bb3: + br label %sw.epilog + +sw.bb4: + br label %sw.epilog + +sw.default: + br label %sw.epilog + +sw.epilog: + %pep_code = phi i8 [ %code, %sw.default ], [ 63, %sw.bb4 ], [ 81, %sw.bb3 ], [ 113, %sw.bb2 ], [ 73, %sw.bb1 ], [ 105, %entry ] + ret i8 %pep_code +} -- cgit v1.1 From fc1c478709e380164733560e4a2c8f9e8d5e2c1c Mon Sep 17 00:00:00 2001 From: Jordan R AW <103465530+ajordanr-google@users.noreply.github.com> Date: Fri, 5 Jan 2024 12:56:02 -0800 Subject: [libunwind] Replace process_vm_readv with SYS_rt_sigprocmask (#74791) process_vm_readv is generally considered dangerous from a syscall perspective, and is frequently blanket banned in seccomp filters such as those in Chromium and ChromiumOS. We can get the same behaviour during the invalid PC address case with the raw SYS_rt_sigprocmask syscall. Testing to ensure that process_vm_readv does not appear, I ran the output of check-unwind on an ARM64 device under strace. Previously, bad_unwind_info in particular would use process_vm_readv, but with this commit, it now no longer uses it: ``` strace test/Output/bad_unwind_info.pass.cpp.dir/t.tmp.exe \ |& grep process_vm_readv ``` The libunwind unittests were also tested on ARM64 ChromeOS (Gentoo Linux) devices. --- libunwind/src/UnwindCursor.hpp | 77 +++++++++++++++++++++++++++--------------- 1 file changed, 50 insertions(+), 27 deletions(-) diff --git a/libunwind/src/UnwindCursor.hpp b/libunwind/src/UnwindCursor.hpp index 647a5a9..8517d32 100644 --- a/libunwind/src/UnwindCursor.hpp +++ b/libunwind/src/UnwindCursor.hpp @@ -12,6 +12,8 @@ #define __UNWINDCURSOR_HPP__ #include "cet_unwind.h" +#include +#include #include #include #include @@ -990,6 +992,7 @@ private: R dummy; return stepThroughSigReturn(dummy); } + bool isReadableAddr(const pint_t addr) const; #if defined(_LIBUNWIND_TARGET_AARCH64) bool setInfoForSigReturn(Registers_arm64 &); int stepThroughSigReturn(Registers_arm64 &); @@ -2700,20 +2703,12 @@ bool UnwindCursor::setInfoForSigReturn(Registers_arm64 &) { // [1] https://github.com/torvalds/linux/blob/master/arch/arm64/kernel/vdso/sigreturn.S const pint_t pc = static_cast(this->getReg(UNW_REG_IP)); // The PC might contain an invalid address if the unwind info is bad, so - // directly accessing it could cause a segfault. Use process_vm_readv to read - // the memory safely instead. process_vm_readv was added in Linux 3.2, and - // AArch64 supported was added in Linux 3.7, so the syscall is guaranteed to - // be present. Unfortunately, there are Linux AArch64 environments where the - // libc wrapper for the syscall might not be present (e.g. Android 5), so call - // the syscall directly instead. - uint32_t instructions[2]; - struct iovec local_iov = {&instructions, sizeof instructions}; - struct iovec remote_iov = {reinterpret_cast(pc), sizeof instructions}; - long bytesRead = - syscall(SYS_process_vm_readv, getpid(), &local_iov, 1, &remote_iov, 1, 0); + // directly accessing it could cause a SIGSEGV. + if (!isReadableAddr(pc)) + return false; + auto *instructions = reinterpret_cast(pc); // Look for instructions: mov x8, #0x8b; svc #0x0 - if (bytesRead != sizeof instructions || instructions[0] != 0xd2801168 || - instructions[1] != 0xd4000001) + if (instructions[0] != 0xd2801168 || instructions[1] != 0xd4000001) return false; _info = {}; @@ -2762,18 +2757,17 @@ int UnwindCursor::stepThroughSigReturn(Registers_arm64 &) { template bool UnwindCursor::setInfoForSigReturn(Registers_riscv &) { const pint_t pc = static_cast(getReg(UNW_REG_IP)); - uint32_t instructions[2]; - struct iovec local_iov = {&instructions, sizeof instructions}; - struct iovec remote_iov = {reinterpret_cast(pc), sizeof instructions}; - long bytesRead = - syscall(SYS_process_vm_readv, getpid(), &local_iov, 1, &remote_iov, 1, 0); + // The PC might contain an invalid address if the unwind info is bad, so + // directly accessing it could cause a SIGSEGV. + if (!isReadableAddr(pc)) + return false; + const auto *instructions = reinterpret_cast(pc); // Look for the two instructions used in the sigreturn trampoline // __vdso_rt_sigreturn: // // 0x08b00893 li a7,0x8b // 0x00000073 ecall - if (bytesRead != sizeof instructions || instructions[0] != 0x08b00893 || - instructions[1] != 0x00000073) + if (instructions[0] != 0x08b00893 || instructions[1] != 0x00000073) return false; _info = {}; @@ -2822,13 +2816,11 @@ bool UnwindCursor::setInfoForSigReturn(Registers_s390x &) { // onto the stack. const pint_t pc = static_cast(this->getReg(UNW_REG_IP)); // The PC might contain an invalid address if the unwind info is bad, so - // directly accessing it could cause a segfault. Use process_vm_readv to - // read the memory safely instead. - uint16_t inst; - struct iovec local_iov = {&inst, sizeof inst}; - struct iovec remote_iov = {reinterpret_cast(pc), sizeof inst}; - long bytesRead = process_vm_readv(getpid(), &local_iov, 1, &remote_iov, 1, 0); - if (bytesRead == sizeof inst && (inst == 0x0a77 || inst == 0x0aad)) { + // directly accessing it could cause a SIGSEGV. + if (!isReadableAddr(pc)) + return false; + const auto inst = *reinterpret_cast(pc); + if (inst == 0x0a77 || inst == 0x0aad) { _info = {}; _info.start_ip = pc; _info.end_ip = pc + 2; @@ -2974,6 +2966,37 @@ bool UnwindCursor::getFunctionName(char *buf, size_t bufLen, buf, bufLen, offset); } +#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) +template +bool UnwindCursor::isReadableAddr(const pint_t addr) const { + // We use SYS_rt_sigprocmask, inspired by Abseil's AddressIsReadable. + + const auto sigsetAddr = reinterpret_cast(addr); + // We have to check that addr is nullptr because sigprocmask allows that + // as an argument without failure. + if (!sigsetAddr) + return false; + const auto saveErrno = errno; + // We MUST use a raw syscall here, as wrappers may try to access + // sigsetAddr which may cause a SIGSEGV. A raw syscall however is + // safe. Additionally, we need to pass the kernel_sigset_size, which is + // different from libc sizeof(sigset_t). For the majority of architectures, + // it's 64 bits (_NSIG), and libc NSIG is _NSIG + 1. + const auto kernelSigsetSize = NSIG / 8; + [[maybe_unused]] const int Result = syscall( + SYS_rt_sigprocmask, /*how=*/~0, sigsetAddr, nullptr, kernelSigsetSize); + // Because our "how" is invalid, this syscall should always fail, and our + // errno should always be EINVAL or an EFAULT. This relies on the Linux + // kernel to check copy_from_user before checking if the "how" argument is + // invalid. + assert(Result == -1); + assert(errno == EFAULT || errno == EINVAL); + const auto readable = errno != EFAULT; + errno = saveErrno; + return readable; +} +#endif + #if defined(_LIBUNWIND_USE_CET) extern "C" void *__libunwind_cet_get_registers(unw_cursor_t *cursor) { AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; -- cgit v1.1 From 365fbbfbcfefb8766f7716109b9c3767b58e6058 Mon Sep 17 00:00:00 2001 From: David Green Date: Fri, 5 Jan 2024 21:04:01 +0000 Subject: [AArch64] Add some extra tests for SelectOpt. NFC --- llvm/test/CodeGen/AArch64/selectopt.ll | 593 +++++++++++++++++++++++++++++++++ 1 file changed, 593 insertions(+) diff --git a/llvm/test/CodeGen/AArch64/selectopt.ll b/llvm/test/CodeGen/AArch64/selectopt.ll index 8922eba..f2b86dcb 100644 --- a/llvm/test/CodeGen/AArch64/selectopt.ll +++ b/llvm/test/CodeGen/AArch64/selectopt.ll @@ -268,3 +268,596 @@ if.end87: ; preds = %if.then, %while.bod while.end: ; preds = %land.rhs, %if.end87, %entry ret void } + + +define void @replace_or(ptr nocapture noundef %newst, ptr noundef %t, ptr noundef %h, i64 noundef %c, i64 noundef %rc, i64 noundef %ma, i64 noundef %n) { +; CHECKOO-LABEL: @replace_or( +; CHECKOO-NEXT: entry: +; CHECKOO-NEXT: [[T1:%.*]] = getelementptr inbounds [[STRUCT_ST:%.*]], ptr [[NEWST:%.*]], i64 0, i32 2 +; CHECKOO-NEXT: store ptr [[T:%.*]], ptr [[T1]], align 8 +; CHECKOO-NEXT: [[H3:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 0, i32 3 +; CHECKOO-NEXT: store ptr [[H:%.*]], ptr [[H3]], align 8 +; CHECKOO-NEXT: [[ORG_C:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 0, i32 8 +; CHECKOO-NEXT: store i64 [[C:%.*]], ptr [[ORG_C]], align 8 +; CHECKOO-NEXT: [[C6:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 0, i32 1 +; CHECKOO-NEXT: store i64 [[C]], ptr [[C6]], align 8 +; CHECKOO-NEXT: [[FLOW:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 0, i32 7 +; CHECKOO-NEXT: store i64 [[RC:%.*]], ptr [[FLOW]], align 8 +; CHECKOO-NEXT: [[CONV:%.*]] = trunc i64 [[N:%.*]] to i32 +; CHECKOO-NEXT: store i32 [[CONV]], ptr [[NEWST]], align 8 +; CHECKOO-NEXT: [[FLOW10:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 1, i32 7 +; CHECKOO-NEXT: [[TMP0:%.*]] = load i64, ptr [[FLOW10]], align 8 +; CHECKOO-NEXT: [[FLOW12:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 2, i32 7 +; CHECKOO-NEXT: [[TMP1:%.*]] = load i64, ptr [[FLOW12]], align 8 +; CHECKOO-NEXT: [[CMP13:%.*]] = icmp sgt i64 [[TMP0]], [[TMP1]] +; CHECKOO-NEXT: [[CONV15:%.*]] = select i1 [[CMP13]], i64 2, i64 3 +; CHECKOO-NEXT: [[CMP16_NOT149:%.*]] = icmp sgt i64 [[CONV15]], [[MA:%.*]] +; CHECKOO-NEXT: br i1 [[CMP16_NOT149]], label [[WHILE_END:%.*]], label [[LAND_RHS:%.*]] +; CHECKOO: land.rhs: +; CHECKOO-NEXT: [[CMP_0151:%.*]] = phi i64 [ [[CMP_1:%.*]], [[IF_END87:%.*]] ], [ [[CONV15]], [[ENTRY:%.*]] ] +; CHECKOO-NEXT: [[POS_0150:%.*]] = phi i64 [ [[CMP_0151]], [[IF_END87]] ], [ 1, [[ENTRY]] ] +; CHECKOO-NEXT: [[SUB:%.*]] = add nsw i64 [[CMP_0151]], -1 +; CHECKOO-NEXT: [[FLOW19:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 [[SUB]], i32 7 +; CHECKOO-NEXT: [[TMP2:%.*]] = load i64, ptr [[FLOW19]], align 8 +; CHECKOO-NEXT: [[CMP20:%.*]] = icmp sgt i64 [[TMP2]], [[RC]] +; CHECKOO-NEXT: br i1 [[CMP20]], label [[WHILE_BODY:%.*]], label [[WHILE_END]] +; CHECKOO: while.body: +; CHECKOO-NEXT: [[ARRAYIDX18:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 [[SUB]] +; CHECKOO-NEXT: [[T24:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 [[SUB]], i32 2 +; CHECKOO-NEXT: [[TMP3:%.*]] = load ptr, ptr [[T24]], align 8 +; CHECKOO-NEXT: [[SUB25:%.*]] = add nsw i64 [[POS_0150]], -1 +; CHECKOO-NEXT: [[ARRAYIDX26:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 [[SUB25]] +; CHECKOO-NEXT: [[T27:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 [[SUB25]], i32 2 +; CHECKOO-NEXT: store ptr [[TMP3]], ptr [[T27]], align 8 +; CHECKOO-NEXT: [[H30:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 [[SUB]], i32 3 +; CHECKOO-NEXT: [[TMP4:%.*]] = load ptr, ptr [[H30]], align 8 +; CHECKOO-NEXT: [[H33:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 [[SUB25]], i32 3 +; CHECKOO-NEXT: store ptr [[TMP4]], ptr [[H33]], align 8 +; CHECKOO-NEXT: [[C36:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 [[SUB]], i32 1 +; CHECKOO-NEXT: [[TMP5:%.*]] = load i64, ptr [[C36]], align 8 +; CHECKOO-NEXT: [[C39:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 [[SUB25]], i32 1 +; CHECKOO-NEXT: store i64 [[TMP5]], ptr [[C39]], align 8 +; CHECKOO-NEXT: [[ORG_C45:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 [[SUB25]], i32 8 +; CHECKOO-NEXT: store i64 [[TMP5]], ptr [[ORG_C45]], align 8 +; CHECKOO-NEXT: [[FLOW51:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 [[SUB25]], i32 7 +; CHECKOO-NEXT: store i64 [[TMP2]], ptr [[FLOW51]], align 8 +; CHECKOO-NEXT: [[TMP6:%.*]] = load i32, ptr [[ARRAYIDX18]], align 8 +; CHECKOO-NEXT: store i32 [[TMP6]], ptr [[ARRAYIDX26]], align 8 +; CHECKOO-NEXT: store ptr [[T]], ptr [[T24]], align 8 +; CHECKOO-NEXT: store ptr [[H]], ptr [[H30]], align 8 +; CHECKOO-NEXT: store i64 [[C]], ptr [[C36]], align 8 +; CHECKOO-NEXT: [[ORG_C69:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 [[SUB]], i32 8 +; CHECKOO-NEXT: store i64 [[C]], ptr [[ORG_C69]], align 8 +; CHECKOO-NEXT: store i64 [[RC]], ptr [[FLOW19]], align 8 +; CHECKOO-NEXT: store i32 [[CONV]], ptr [[ARRAYIDX18]], align 8 +; CHECKOO-NEXT: [[MUL:%.*]] = shl nsw i64 [[CMP_0151]], 1 +; CHECKOO-NEXT: [[CMP77_NOT_NOT:%.*]] = icmp slt i64 [[MUL]], [[MA]] +; CHECKOO-NEXT: br i1 [[CMP77_NOT_NOT]], label [[IF_THEN:%.*]], label [[IF_END87]] +; CHECKOO: if.then: +; CHECKOO-NEXT: [[SUB79:%.*]] = add nsw i64 [[MUL]], -1 +; CHECKOO-NEXT: [[FLOW81:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 [[SUB79]], i32 7 +; CHECKOO-NEXT: [[TMP7:%.*]] = load i64, ptr [[FLOW81]], align 8 +; CHECKOO-NEXT: [[FLOW83:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 [[MUL]], i32 7 +; CHECKOO-NEXT: [[TMP8:%.*]] = load i64, ptr [[FLOW83]], align 8 +; CHECKOO-NEXT: [[CMP84:%.*]] = icmp slt i64 [[TMP7]], [[TMP8]] +; CHECKOO-NEXT: [[ADD:%.*]] = zext i1 [[CMP84]] to i64 +; CHECKOO-NEXT: [[SPEC_SELECT:%.*]] = or disjoint i64 [[MUL]], [[ADD]] +; CHECKOO-NEXT: br label [[IF_END87]] +; CHECKOO: if.end87: +; CHECKOO-NEXT: [[CMP_1]] = phi i64 [ [[MUL]], [[WHILE_BODY]] ], [ [[SPEC_SELECT]], [[IF_THEN]] ] +; CHECKOO-NEXT: [[CMP16_NOT:%.*]] = icmp sgt i64 [[CMP_1]], [[MA]] +; CHECKOO-NEXT: br i1 [[CMP16_NOT]], label [[WHILE_END]], label [[LAND_RHS]] +; CHECKOO: while.end: +; CHECKOO-NEXT: ret void +; +; CHECKII-LABEL: @replace_or( +; CHECKII-NEXT: entry: +; CHECKII-NEXT: [[T1:%.*]] = getelementptr inbounds [[STRUCT_ST:%.*]], ptr [[NEWST:%.*]], i64 0, i32 2 +; CHECKII-NEXT: store ptr [[T:%.*]], ptr [[T1]], align 8 +; CHECKII-NEXT: [[H3:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 0, i32 3 +; CHECKII-NEXT: store ptr [[H:%.*]], ptr [[H3]], align 8 +; CHECKII-NEXT: [[ORG_C:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 0, i32 8 +; CHECKII-NEXT: store i64 [[C:%.*]], ptr [[ORG_C]], align 8 +; CHECKII-NEXT: [[C6:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 0, i32 1 +; CHECKII-NEXT: store i64 [[C]], ptr [[C6]], align 8 +; CHECKII-NEXT: [[FLOW:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 0, i32 7 +; CHECKII-NEXT: store i64 [[RC:%.*]], ptr [[FLOW]], align 8 +; CHECKII-NEXT: [[CONV:%.*]] = trunc i64 [[N:%.*]] to i32 +; CHECKII-NEXT: store i32 [[CONV]], ptr [[NEWST]], align 8 +; CHECKII-NEXT: [[FLOW10:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 1, i32 7 +; CHECKII-NEXT: [[TMP0:%.*]] = load i64, ptr [[FLOW10]], align 8 +; CHECKII-NEXT: [[FLOW12:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 2, i32 7 +; CHECKII-NEXT: [[TMP1:%.*]] = load i64, ptr [[FLOW12]], align 8 +; CHECKII-NEXT: [[CMP13:%.*]] = icmp sgt i64 [[TMP0]], [[TMP1]] +; CHECKII-NEXT: [[CONV15:%.*]] = select i1 [[CMP13]], i64 2, i64 3 +; CHECKII-NEXT: [[CMP16_NOT149:%.*]] = icmp sgt i64 [[CONV15]], [[MA:%.*]] +; CHECKII-NEXT: br i1 [[CMP16_NOT149]], label [[WHILE_END:%.*]], label [[LAND_RHS:%.*]] +; CHECKII: land.rhs: +; CHECKII-NEXT: [[CMP_0151:%.*]] = phi i64 [ [[CMP_1:%.*]], [[IF_END87:%.*]] ], [ [[CONV15]], [[ENTRY:%.*]] ] +; CHECKII-NEXT: [[POS_0150:%.*]] = phi i64 [ [[CMP_0151]], [[IF_END87]] ], [ 1, [[ENTRY]] ] +; CHECKII-NEXT: [[SUB:%.*]] = add nsw i64 [[CMP_0151]], -1 +; CHECKII-NEXT: [[FLOW19:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 [[SUB]], i32 7 +; CHECKII-NEXT: [[TMP2:%.*]] = load i64, ptr [[FLOW19]], align 8 +; CHECKII-NEXT: [[CMP20:%.*]] = icmp sgt i64 [[TMP2]], [[RC]] +; CHECKII-NEXT: br i1 [[CMP20]], label [[WHILE_BODY:%.*]], label [[WHILE_END]] +; CHECKII: while.body: +; CHECKII-NEXT: [[ARRAYIDX18:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 [[SUB]] +; CHECKII-NEXT: [[T24:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 [[SUB]], i32 2 +; CHECKII-NEXT: [[TMP3:%.*]] = load ptr, ptr [[T24]], align 8 +; CHECKII-NEXT: [[SUB25:%.*]] = add nsw i64 [[POS_0150]], -1 +; CHECKII-NEXT: [[ARRAYIDX26:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 [[SUB25]] +; CHECKII-NEXT: [[T27:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 [[SUB25]], i32 2 +; CHECKII-NEXT: store ptr [[TMP3]], ptr [[T27]], align 8 +; CHECKII-NEXT: [[H30:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 [[SUB]], i32 3 +; CHECKII-NEXT: [[TMP4:%.*]] = load ptr, ptr [[H30]], align 8 +; CHECKII-NEXT: [[H33:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 [[SUB25]], i32 3 +; CHECKII-NEXT: store ptr [[TMP4]], ptr [[H33]], align 8 +; CHECKII-NEXT: [[C36:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 [[SUB]], i32 1 +; CHECKII-NEXT: [[TMP5:%.*]] = load i64, ptr [[C36]], align 8 +; CHECKII-NEXT: [[C39:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 [[SUB25]], i32 1 +; CHECKII-NEXT: store i64 [[TMP5]], ptr [[C39]], align 8 +; CHECKII-NEXT: [[ORG_C45:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 [[SUB25]], i32 8 +; CHECKII-NEXT: store i64 [[TMP5]], ptr [[ORG_C45]], align 8 +; CHECKII-NEXT: [[FLOW51:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 [[SUB25]], i32 7 +; CHECKII-NEXT: store i64 [[TMP2]], ptr [[FLOW51]], align 8 +; CHECKII-NEXT: [[TMP6:%.*]] = load i32, ptr [[ARRAYIDX18]], align 8 +; CHECKII-NEXT: store i32 [[TMP6]], ptr [[ARRAYIDX26]], align 8 +; CHECKII-NEXT: store ptr [[T]], ptr [[T24]], align 8 +; CHECKII-NEXT: store ptr [[H]], ptr [[H30]], align 8 +; CHECKII-NEXT: store i64 [[C]], ptr [[C36]], align 8 +; CHECKII-NEXT: [[ORG_C69:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 [[SUB]], i32 8 +; CHECKII-NEXT: store i64 [[C]], ptr [[ORG_C69]], align 8 +; CHECKII-NEXT: store i64 [[RC]], ptr [[FLOW19]], align 8 +; CHECKII-NEXT: store i32 [[CONV]], ptr [[ARRAYIDX18]], align 8 +; CHECKII-NEXT: [[MUL:%.*]] = shl nsw i64 [[CMP_0151]], 1 +; CHECKII-NEXT: [[CMP77_NOT_NOT:%.*]] = icmp slt i64 [[MUL]], [[MA]] +; CHECKII-NEXT: br i1 [[CMP77_NOT_NOT]], label [[IF_THEN:%.*]], label [[IF_END87]] +; CHECKII: if.then: +; CHECKII-NEXT: [[SUB79:%.*]] = add nsw i64 [[MUL]], -1 +; CHECKII-NEXT: [[FLOW81:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 [[SUB79]], i32 7 +; CHECKII-NEXT: [[TMP7:%.*]] = load i64, ptr [[FLOW81]], align 8 +; CHECKII-NEXT: [[FLOW83:%.*]] = getelementptr inbounds [[STRUCT_ST]], ptr [[NEWST]], i64 [[MUL]], i32 7 +; CHECKII-NEXT: [[TMP8:%.*]] = load i64, ptr [[FLOW83]], align 8 +; CHECKII-NEXT: [[CMP84:%.*]] = icmp slt i64 [[TMP7]], [[TMP8]] +; CHECKII-NEXT: [[ADD:%.*]] = zext i1 [[CMP84]] to i64 +; CHECKII-NEXT: [[SPEC_SELECT:%.*]] = or disjoint i64 [[MUL]], [[ADD]] +; CHECKII-NEXT: br label [[IF_END87]] +; CHECKII: if.end87: +; CHECKII-NEXT: [[CMP_1]] = phi i64 [ [[MUL]], [[WHILE_BODY]] ], [ [[SPEC_SELECT]], [[IF_THEN]] ] +; CHECKII-NEXT: [[CMP16_NOT:%.*]] = icmp sgt i64 [[CMP_1]], [[MA]] +; CHECKII-NEXT: br i1 [[CMP16_NOT]], label [[WHILE_END]], label [[LAND_RHS]] +; CHECKII: while.end: +; CHECKII-NEXT: ret void +; +entry: + %t1 = getelementptr inbounds %struct.st, ptr %newst, i64 0, i32 2 + store ptr %t, ptr %t1, align 8 + %h3 = getelementptr inbounds %struct.st, ptr %newst, i64 0, i32 3 + store ptr %h, ptr %h3, align 8 + %org_c = getelementptr inbounds %struct.st, ptr %newst, i64 0, i32 8 + store i64 %c, ptr %org_c, align 8 + %c6 = getelementptr inbounds %struct.st, ptr %newst, i64 0, i32 1 + store i64 %c, ptr %c6, align 8 + %flow = getelementptr inbounds %struct.st, ptr %newst, i64 0, i32 7 + store i64 %rc, ptr %flow, align 8 + %conv = trunc i64 %n to i32 + store i32 %conv, ptr %newst, align 8 + %flow10 = getelementptr inbounds %struct.st, ptr %newst, i64 1, i32 7 + %0 = load i64, ptr %flow10, align 8 + %flow12 = getelementptr inbounds %struct.st, ptr %newst, i64 2, i32 7 + %1 = load i64, ptr %flow12, align 8 + %cmp13 = icmp sgt i64 %0, %1 + %conv15 = select i1 %cmp13, i64 2, i64 3 + %cmp16.not149 = icmp sgt i64 %conv15, %ma + br i1 %cmp16.not149, label %while.end, label %land.rhs + +land.rhs: ; preds = %entry, %if.end87 + %cmp.0151 = phi i64 [ %cmp.1, %if.end87 ], [ %conv15, %entry ] + %pos.0150 = phi i64 [ %cmp.0151, %if.end87 ], [ 1, %entry ] + %sub = add nsw i64 %cmp.0151, -1 + %flow19 = getelementptr inbounds %struct.st, ptr %newst, i64 %sub, i32 7 + %2 = load i64, ptr %flow19, align 8 + %cmp20 = icmp sgt i64 %2, %rc + br i1 %cmp20, label %while.body, label %while.end + +while.body: ; preds = %land.rhs + %arrayidx18 = getelementptr inbounds %struct.st, ptr %newst, i64 %sub + %t24 = getelementptr inbounds %struct.st, ptr %newst, i64 %sub, i32 2 + %3 = load ptr, ptr %t24, align 8 + %sub25 = add nsw i64 %pos.0150, -1 + %arrayidx26 = getelementptr inbounds %struct.st, ptr %newst, i64 %sub25 + %t27 = getelementptr inbounds %struct.st, ptr %newst, i64 %sub25, i32 2 + store ptr %3, ptr %t27, align 8 + %h30 = getelementptr inbounds %struct.st, ptr %newst, i64 %sub, i32 3 + %4 = load ptr, ptr %h30, align 8 + %h33 = getelementptr inbounds %struct.st, ptr %newst, i64 %sub25, i32 3 + store ptr %4, ptr %h33, align 8 + %c36 = getelementptr inbounds %struct.st, ptr %newst, i64 %sub, i32 1 + %5 = load i64, ptr %c36, align 8 + %c39 = getelementptr inbounds %struct.st, ptr %newst, i64 %sub25, i32 1 + store i64 %5, ptr %c39, align 8 + %org_c45 = getelementptr inbounds %struct.st, ptr %newst, i64 %sub25, i32 8 + store i64 %5, ptr %org_c45, align 8 + %flow51 = getelementptr inbounds %struct.st, ptr %newst, i64 %sub25, i32 7 + store i64 %2, ptr %flow51, align 8 + %6 = load i32, ptr %arrayidx18, align 8 + store i32 %6, ptr %arrayidx26, align 8 + store ptr %t, ptr %t24, align 8 + store ptr %h, ptr %h30, align 8 + store i64 %c, ptr %c36, align 8 + %org_c69 = getelementptr inbounds %struct.st, ptr %newst, i64 %sub, i32 8 + store i64 %c, ptr %org_c69, align 8 + store i64 %rc, ptr %flow19, align 8 + store i32 %conv, ptr %arrayidx18, align 8 + %mul = shl nsw i64 %cmp.0151, 1 + %cmp77.not.not = icmp slt i64 %mul, %ma + br i1 %cmp77.not.not, label %if.then, label %if.end87 + +if.then: ; preds = %while.body + %sub79 = add nsw i64 %mul, -1 + %flow81 = getelementptr inbounds %struct.st, ptr %newst, i64 %sub79, i32 7 + %7 = load i64, ptr %flow81, align 8 + %flow83 = getelementptr inbounds %struct.st, ptr %newst, i64 %mul, i32 7 + %8 = load i64, ptr %flow83, align 8 + %cmp84 = icmp slt i64 %7, %8 + %add = zext i1 %cmp84 to i64 + %spec.select = or disjoint i64 %mul, %add + br label %if.end87 + +if.end87: ; preds = %if.then, %while.body + %cmp.1 = phi i64 [ %mul, %while.body ], [ %spec.select, %if.then ] + %cmp16.not = icmp sgt i64 %cmp.1, %ma + br i1 %cmp16.not, label %while.end, label %land.rhs + +while.end: ; preds = %if.end87, %land.rhs, %entry + ret void +} + + +; This `or` is not transformed as it is not the last instruction in the block +define i32 @or_notatendofblock(ptr nocapture noundef %x, i32 noundef %n, ptr nocapture noundef readonly %z) { +; CHECKOO-LABEL: @or_notatendofblock( +; CHECKOO-NEXT: entry: +; CHECKOO-NEXT: [[CMP19:%.*]] = icmp sgt i32 [[N:%.*]], 0 +; CHECKOO-NEXT: br i1 [[CMP19]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] +; CHECKOO: for.body.preheader: +; CHECKOO-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext nneg i32 [[N]] to i64 +; CHECKOO-NEXT: br label [[FOR_BODY:%.*]] +; CHECKOO: for.cond.cleanup: +; CHECKOO-NEXT: [[Y_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[Y_1:%.*]], [[IF_END:%.*]] ] +; CHECKOO-NEXT: ret i32 [[Y_0_LCSSA]] +; CHECKOO: for.body: +; CHECKOO-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[IF_END]] ] +; CHECKOO-NEXT: [[Y_020:%.*]] = phi i32 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[Y_1]], [[IF_END]] ] +; CHECKOO-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[X:%.*]], i64 [[INDVARS_IV]] +; CHECKOO-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +; CHECKOO-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP0]], [[Y_020]] +; CHECKOO-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[ADD]], 0 +; CHECKOO-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_END]], label [[IF_THEN:%.*]] +; CHECKOO: if.then: +; CHECKOO-NEXT: [[ARRAYIDX4:%.*]] = getelementptr inbounds i32, ptr [[Z:%.*]], i64 [[INDVARS_IV]] +; CHECKOO-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX4]], align 4 +; CHECKOO-NEXT: [[DIV:%.*]] = sdiv i32 [[TMP0]], [[TMP1]] +; CHECKOO-NEXT: [[DIV1:%.*]] = sdiv i32 [[DIV]], [[TMP1]] +; CHECKOO-NEXT: [[DIV2:%.*]] = sdiv i32 [[DIV1]], [[TMP1]] +; CHECKOO-NEXT: [[CMP5:%.*]] = icmp sgt i32 [[DIV2]], 0 +; CHECKOO-NEXT: [[CONV:%.*]] = zext i1 [[CMP5]] to i32 +; CHECKOO-NEXT: [[OR1:%.*]] = or i32 [[CONV]], [[ADD]] +; CHECKOO-NEXT: [[OR:%.*]] = add i32 [[OR1]], 1 +; CHECKOO-NEXT: br label [[IF_END]] +; CHECKOO: if.end: +; CHECKOO-NEXT: [[Y_1]] = phi i32 [ [[OR]], [[IF_THEN]] ], [ 0, [[FOR_BODY]] ] +; CHECKOO-NEXT: store i32 [[Y_1]], ptr [[ARRAYIDX]], align 4 +; CHECKOO-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 +; CHECKOO-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]] +; CHECKOO-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP]], label [[FOR_BODY]] +; +; CHECKII-LABEL: @or_notatendofblock( +; CHECKII-NEXT: entry: +; CHECKII-NEXT: [[CMP19:%.*]] = icmp sgt i32 [[N:%.*]], 0 +; CHECKII-NEXT: br i1 [[CMP19]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] +; CHECKII: for.body.preheader: +; CHECKII-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext nneg i32 [[N]] to i64 +; CHECKII-NEXT: br label [[FOR_BODY:%.*]] +; CHECKII: for.cond.cleanup: +; CHECKII-NEXT: [[Y_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[Y_1:%.*]], [[IF_END:%.*]] ] +; CHECKII-NEXT: ret i32 [[Y_0_LCSSA]] +; CHECKII: for.body: +; CHECKII-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[IF_END]] ] +; CHECKII-NEXT: [[Y_020:%.*]] = phi i32 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[Y_1]], [[IF_END]] ] +; CHECKII-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[X:%.*]], i64 [[INDVARS_IV]] +; CHECKII-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +; CHECKII-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP0]], [[Y_020]] +; CHECKII-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[ADD]], 0 +; CHECKII-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_END]], label [[IF_THEN:%.*]] +; CHECKII: if.then: +; CHECKII-NEXT: [[ARRAYIDX4:%.*]] = getelementptr inbounds i32, ptr [[Z:%.*]], i64 [[INDVARS_IV]] +; CHECKII-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX4]], align 4 +; CHECKII-NEXT: [[DIV:%.*]] = sdiv i32 [[TMP0]], [[TMP1]] +; CHECKII-NEXT: [[DIV1:%.*]] = sdiv i32 [[DIV]], [[TMP1]] +; CHECKII-NEXT: [[DIV2:%.*]] = sdiv i32 [[DIV1]], [[TMP1]] +; CHECKII-NEXT: [[CMP5:%.*]] = icmp sgt i32 [[DIV2]], 0 +; CHECKII-NEXT: [[CONV:%.*]] = zext i1 [[CMP5]] to i32 +; CHECKII-NEXT: [[OR1:%.*]] = or i32 [[CONV]], [[ADD]] +; CHECKII-NEXT: [[OR:%.*]] = add i32 [[OR1]], 1 +; CHECKII-NEXT: br label [[IF_END]] +; CHECKII: if.end: +; CHECKII-NEXT: [[Y_1]] = phi i32 [ [[OR]], [[IF_THEN]] ], [ 0, [[FOR_BODY]] ] +; CHECKII-NEXT: store i32 [[Y_1]], ptr [[ARRAYIDX]], align 4 +; CHECKII-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 +; CHECKII-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]] +; CHECKII-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP]], label [[FOR_BODY]] +; +entry: + %cmp19 = icmp sgt i32 %n, 0 + br i1 %cmp19, label %for.body.preheader, label %for.cond.cleanup + +for.body.preheader: + %wide.trip.count = zext nneg i32 %n to i64 + br label %for.body + +for.cond.cleanup: + %y.0.lcssa = phi i32 [ 0, %entry ], [ %y.1, %if.end ] + ret i32 %y.0.lcssa + +for.body: + %indvars.iv = phi i64 [ 0, %for.body.preheader ], [ %indvars.iv.next, %if.end ] + %y.020 = phi i32 [ 0, %for.body.preheader ], [ %y.1, %if.end ] + %arrayidx = getelementptr inbounds i32, ptr %x, i64 %indvars.iv + %0 = load i32, ptr %arrayidx, align 4 + %add = add nsw i32 %0, %y.020 + %tobool.not = icmp eq i32 %add, 0 + br i1 %tobool.not, label %if.end, label %if.then + +if.then: + %arrayidx4 = getelementptr inbounds i32, ptr %z, i64 %indvars.iv + %1 = load i32, ptr %arrayidx4, align 4 + %div = sdiv i32 %0, %1 + %div1 = sdiv i32 %div, %1 + %div2 = sdiv i32 %div1, %1 + %cmp5 = icmp sgt i32 %div2, 0 + %conv = zext i1 %cmp5 to i32 + %or1 = or i32 %conv, %add + %or = add i32 %or1, 1 + br label %if.end + +if.end: + %y.1 = phi i32 [ %or, %if.then ], [ 0, %for.body ] + store i32 %y.1, ptr %arrayidx, align 4 + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 + %exitcond.not = icmp eq i64 %indvars.iv.next, %wide.trip.count + br i1 %exitcond.not, label %for.cond.cleanup, label %for.body +} + + +; Similar to the last test, an artificial test with the or as the last instruction and a select in the same group. +define i32 @or_samegroup(ptr nocapture noundef %x, i32 noundef %n, ptr nocapture noundef readonly %z) { +; CHECKOO-LABEL: @or_samegroup( +; CHECKOO-NEXT: entry: +; CHECKOO-NEXT: [[CMP19:%.*]] = icmp sgt i32 [[N:%.*]], 0 +; CHECKOO-NEXT: br i1 [[CMP19]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] +; CHECKOO: for.body.preheader: +; CHECKOO-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext nneg i32 [[N]] to i64 +; CHECKOO-NEXT: br label [[FOR_BODY:%.*]] +; CHECKOO: for.cond.cleanup: +; CHECKOO-NEXT: [[Y_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[Y_1:%.*]], [[IF_END:%.*]] ] +; CHECKOO-NEXT: ret i32 [[Y_0_LCSSA]] +; CHECKOO: for.body: +; CHECKOO-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[IF_END]] ] +; CHECKOO-NEXT: [[Y_020:%.*]] = phi i32 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[Y_1]], [[IF_END]] ] +; CHECKOO-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[X:%.*]], i64 [[INDVARS_IV]] +; CHECKOO-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +; CHECKOO-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP0]], [[Y_020]] +; CHECKOO-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[ADD]], 0 +; CHECKOO-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_END]], label [[IF_THEN:%.*]] +; CHECKOO: if.then: +; CHECKOO-NEXT: [[ARRAYIDX4:%.*]] = getelementptr inbounds i32, ptr [[Z:%.*]], i64 [[INDVARS_IV]] +; CHECKOO-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX4]], align 4 +; CHECKOO-NEXT: [[DIV:%.*]] = sdiv i32 [[Y_020]], [[TMP1]] +; CHECKOO-NEXT: [[DIV1:%.*]] = sdiv i32 [[DIV]], [[TMP1]] +; CHECKOO-NEXT: [[CMP5:%.*]] = icmp sgt i32 [[DIV1]], 0 +; CHECKOO-NEXT: [[CONV:%.*]] = zext i1 [[CMP5]] to i32 +; CHECKOO-NEXT: [[SEL_FROZEN:%.*]] = freeze i1 [[CMP5]] +; CHECKOO-NEXT: br i1 [[SEL_FROZEN]], label [[SELECT_END:%.*]], label [[SELECT_FALSE:%.*]] +; CHECKOO: select.false: +; CHECKOO-NEXT: br label [[SELECT_END]] +; CHECKOO: select.end: +; CHECKOO-NEXT: [[SEL:%.*]] = phi i32 [ [[ADD]], [[IF_THEN]] ], [ 1, [[SELECT_FALSE]] ] +; CHECKOO-NEXT: [[OR:%.*]] = or i32 [[CONV]], [[SEL]] +; CHECKOO-NEXT: br label [[IF_END]] +; CHECKOO: if.end: +; CHECKOO-NEXT: [[Y_1]] = phi i32 [ [[SEL]], [[SELECT_END]] ], [ 0, [[FOR_BODY]] ] +; CHECKOO-NEXT: store i32 [[Y_1]], ptr [[ARRAYIDX]], align 4 +; CHECKOO-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 +; CHECKOO-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]] +; CHECKOO-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP]], label [[FOR_BODY]] +; +; CHECKII-LABEL: @or_samegroup( +; CHECKII-NEXT: entry: +; CHECKII-NEXT: [[CMP19:%.*]] = icmp sgt i32 [[N:%.*]], 0 +; CHECKII-NEXT: br i1 [[CMP19]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] +; CHECKII: for.body.preheader: +; CHECKII-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext nneg i32 [[N]] to i64 +; CHECKII-NEXT: br label [[FOR_BODY:%.*]] +; CHECKII: for.cond.cleanup: +; CHECKII-NEXT: [[Y_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[Y_1:%.*]], [[IF_END:%.*]] ] +; CHECKII-NEXT: ret i32 [[Y_0_LCSSA]] +; CHECKII: for.body: +; CHECKII-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[IF_END]] ] +; CHECKII-NEXT: [[Y_020:%.*]] = phi i32 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[Y_1]], [[IF_END]] ] +; CHECKII-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[X:%.*]], i64 [[INDVARS_IV]] +; CHECKII-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +; CHECKII-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP0]], [[Y_020]] +; CHECKII-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[ADD]], 0 +; CHECKII-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_END]], label [[IF_THEN:%.*]] +; CHECKII: if.then: +; CHECKII-NEXT: [[ARRAYIDX4:%.*]] = getelementptr inbounds i32, ptr [[Z:%.*]], i64 [[INDVARS_IV]] +; CHECKII-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX4]], align 4 +; CHECKII-NEXT: [[DIV:%.*]] = sdiv i32 [[Y_020]], [[TMP1]] +; CHECKII-NEXT: [[DIV1:%.*]] = sdiv i32 [[DIV]], [[TMP1]] +; CHECKII-NEXT: [[CMP5:%.*]] = icmp sgt i32 [[DIV1]], 0 +; CHECKII-NEXT: [[CONV:%.*]] = zext i1 [[CMP5]] to i32 +; CHECKII-NEXT: [[SEL:%.*]] = select i1 [[CMP5]], i32 [[ADD]], i32 1 +; CHECKII-NEXT: [[OR:%.*]] = or i32 [[CONV]], [[SEL]] +; CHECKII-NEXT: br label [[IF_END]] +; CHECKII: if.end: +; CHECKII-NEXT: [[Y_1]] = phi i32 [ [[SEL]], [[IF_THEN]] ], [ 0, [[FOR_BODY]] ] +; CHECKII-NEXT: store i32 [[Y_1]], ptr [[ARRAYIDX]], align 4 +; CHECKII-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 +; CHECKII-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]] +; CHECKII-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP]], label [[FOR_BODY]] +; +entry: + %cmp19 = icmp sgt i32 %n, 0 + br i1 %cmp19, label %for.body.preheader, label %for.cond.cleanup + +for.body.preheader: + %wide.trip.count = zext nneg i32 %n to i64 + br label %for.body + +for.cond.cleanup: + %y.0.lcssa = phi i32 [ 0, %entry ], [ %y.1, %if.end ] + ret i32 %y.0.lcssa + +for.body: + %indvars.iv = phi i64 [ 0, %for.body.preheader ], [ %indvars.iv.next, %if.end ] + %y.020 = phi i32 [ 0, %for.body.preheader ], [ %y.1, %if.end ] + %arrayidx = getelementptr inbounds i32, ptr %x, i64 %indvars.iv + %0 = load i32, ptr %arrayidx, align 4 + %add = add nsw i32 %0, %y.020 + %tobool.not = icmp eq i32 %add, 0 + br i1 %tobool.not, label %if.end, label %if.then + +if.then: + %arrayidx4 = getelementptr inbounds i32, ptr %z, i64 %indvars.iv + %1 = load i32, ptr %arrayidx4, align 4 + %div = sdiv i32 %y.020, %1 + %div1 = sdiv i32 %div, %1 + %cmp5 = icmp sgt i32 %div1, 0 + %conv = zext i1 %cmp5 to i32 + %sel = select i1 %cmp5, i32 %add, i32 1 + %or = or i32 %conv, %sel + br label %if.end + +if.end: + %y.1 = phi i32 [ %sel, %if.then ], [ 0, %for.body ] + store i32 %y.1, ptr %arrayidx, align 4 + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 + %exitcond.not = icmp eq i64 %indvars.iv.next, %wide.trip.count + br i1 %exitcond.not, label %for.cond.cleanup, label %for.body +} + +; Same test again with a one use value group of values on the or +define i32 @or_oneusevalues(ptr nocapture noundef %x, i32 noundef %n, ptr nocapture noundef readonly %z) { +; CHECKOO-LABEL: @or_oneusevalues( +; CHECKOO-NEXT: entry: +; CHECKOO-NEXT: [[CMP19:%.*]] = icmp sgt i32 [[N:%.*]], 0 +; CHECKOO-NEXT: br i1 [[CMP19]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] +; CHECKOO: for.body.preheader: +; CHECKOO-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext nneg i32 [[N]] to i64 +; CHECKOO-NEXT: br label [[FOR_BODY:%.*]] +; CHECKOO: for.cond.cleanup: +; CHECKOO-NEXT: [[Y_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[Y_1:%.*]], [[IF_END:%.*]] ] +; CHECKOO-NEXT: ret i32 [[Y_0_LCSSA]] +; CHECKOO: for.body: +; CHECKOO-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[IF_END]] ] +; CHECKOO-NEXT: [[Y_020:%.*]] = phi i32 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[Y_1]], [[IF_END]] ] +; CHECKOO-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[X:%.*]], i64 [[INDVARS_IV]] +; CHECKOO-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +; CHECKOO-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP0]], [[Y_020]] +; CHECKOO-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[ADD]], 0 +; CHECKOO-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_END]], label [[IF_THEN:%.*]] +; CHECKOO: if.then: +; CHECKOO-NEXT: [[ARRAYIDX4:%.*]] = getelementptr inbounds i32, ptr [[Z:%.*]], i64 [[INDVARS_IV]] +; CHECKOO-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX4]], align 4 +; CHECKOO-NEXT: [[DIV:%.*]] = sdiv i32 [[Y_020]], [[TMP1]] +; CHECKOO-NEXT: [[DIV1:%.*]] = sdiv i32 [[DIV]], [[TMP1]] +; CHECKOO-NEXT: [[CMP5:%.*]] = icmp sgt i32 [[DIV1]], 0 +; CHECKOO-NEXT: [[CONV:%.*]] = zext i1 [[CMP5]] to i32 +; CHECKOO-NEXT: [[ADD1:%.*]] = add i32 [[ADD]], 1 +; CHECKOO-NEXT: [[ADD2:%.*]] = or i32 [[ADD1]], 1 +; CHECKOO-NEXT: [[OR:%.*]] = or i32 [[CONV]], [[ADD2]] +; CHECKOO-NEXT: br label [[IF_END]] +; CHECKOO: if.end: +; CHECKOO-NEXT: [[Y_1]] = phi i32 [ [[OR]], [[IF_THEN]] ], [ 0, [[FOR_BODY]] ] +; CHECKOO-NEXT: store i32 [[Y_1]], ptr [[ARRAYIDX]], align 4 +; CHECKOO-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 +; CHECKOO-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]] +; CHECKOO-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP]], label [[FOR_BODY]] +; +; CHECKII-LABEL: @or_oneusevalues( +; CHECKII-NEXT: entry: +; CHECKII-NEXT: [[CMP19:%.*]] = icmp sgt i32 [[N:%.*]], 0 +; CHECKII-NEXT: br i1 [[CMP19]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] +; CHECKII: for.body.preheader: +; CHECKII-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext nneg i32 [[N]] to i64 +; CHECKII-NEXT: br label [[FOR_BODY:%.*]] +; CHECKII: for.cond.cleanup: +; CHECKII-NEXT: [[Y_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[Y_1:%.*]], [[IF_END:%.*]] ] +; CHECKII-NEXT: ret i32 [[Y_0_LCSSA]] +; CHECKII: for.body: +; CHECKII-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[IF_END]] ] +; CHECKII-NEXT: [[Y_020:%.*]] = phi i32 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[Y_1]], [[IF_END]] ] +; CHECKII-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[X:%.*]], i64 [[INDVARS_IV]] +; CHECKII-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +; CHECKII-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP0]], [[Y_020]] +; CHECKII-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[ADD]], 0 +; CHECKII-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_END]], label [[IF_THEN:%.*]] +; CHECKII: if.then: +; CHECKII-NEXT: [[ARRAYIDX4:%.*]] = getelementptr inbounds i32, ptr [[Z:%.*]], i64 [[INDVARS_IV]] +; CHECKII-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX4]], align 4 +; CHECKII-NEXT: [[DIV:%.*]] = sdiv i32 [[Y_020]], [[TMP1]] +; CHECKII-NEXT: [[DIV1:%.*]] = sdiv i32 [[DIV]], [[TMP1]] +; CHECKII-NEXT: [[CMP5:%.*]] = icmp sgt i32 [[DIV1]], 0 +; CHECKII-NEXT: [[CONV:%.*]] = zext i1 [[CMP5]] to i32 +; CHECKII-NEXT: [[ADD1:%.*]] = add i32 [[ADD]], 1 +; CHECKII-NEXT: [[ADD2:%.*]] = or i32 [[ADD1]], 1 +; CHECKII-NEXT: [[OR:%.*]] = or i32 [[CONV]], [[ADD2]] +; CHECKII-NEXT: br label [[IF_END]] +; CHECKII: if.end: +; CHECKII-NEXT: [[Y_1]] = phi i32 [ [[OR]], [[IF_THEN]] ], [ 0, [[FOR_BODY]] ] +; CHECKII-NEXT: store i32 [[Y_1]], ptr [[ARRAYIDX]], align 4 +; CHECKII-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 +; CHECKII-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]] +; CHECKII-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP]], label [[FOR_BODY]] +; +entry: + %cmp19 = icmp sgt i32 %n, 0 + br i1 %cmp19, label %for.body.preheader, label %for.cond.cleanup + +for.body.preheader: + %wide.trip.count = zext nneg i32 %n to i64 + br label %for.body + +for.cond.cleanup: + %y.0.lcssa = phi i32 [ 0, %entry ], [ %y.1, %if.end ] + ret i32 %y.0.lcssa + +for.body: + %indvars.iv = phi i64 [ 0, %for.body.preheader ], [ %indvars.iv.next, %if.end ] + %y.020 = phi i32 [ 0, %for.body.preheader ], [ %y.1, %if.end ] + %arrayidx = getelementptr inbounds i32, ptr %x, i64 %indvars.iv + %0 = load i32, ptr %arrayidx, align 4 + %add = add nsw i32 %0, %y.020 + %tobool.not = icmp eq i32 %add, 0 + br i1 %tobool.not, label %if.end, label %if.then + +if.then: + %arrayidx4 = getelementptr inbounds i32, ptr %z, i64 %indvars.iv + %1 = load i32, ptr %arrayidx4, align 4 + %div = sdiv i32 %y.020, %1 + %div1 = sdiv i32 %div, %1 + %cmp5 = icmp sgt i32 %div1, 0 + %conv = zext i1 %cmp5 to i32 + %add1 = add i32 %add, 1 + %add2 = or i32 %add1, 1 + %or = or i32 %conv, %add2 + br label %if.end + +if.end: + %y.1 = phi i32 [ %or, %if.then ], [ 0, %for.body ] + store i32 %y.1, ptr %arrayidx, align 4 + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 + %exitcond.not = icmp eq i64 %indvars.iv.next, %wide.trip.count + br i1 %exitcond.not, label %for.cond.cleanup, label %for.body +} -- cgit v1.1 From dcdb4a36ae3549fb1852b2c0089247a8d477eaf3 Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Fri, 5 Jan 2024 13:31:35 -0800 Subject: [libc][cmake] append per obj compile options instead of prepending (#77126) This allows individual object files to override the common compile commands in their local CMakeLists' add_object_library call. For example, the common compile commands contain -Wall and -Wextra. Before this patch, the per object COMPILE_OPTIONS were prepended to these, so that builds of individual object files could not individually disable specific diagnostics from those groups explicitly. After this patch, the per-object file compile objects are appended to the list of compiler flags, enabling this use case. ARGN is a bit of cmake magic; let's be explicit in the APPEND that we're appending the compile options. Link: #77007 --- libc/cmake/modules/LLVMLibCObjectRules.cmake | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/libc/cmake/modules/LLVMLibCObjectRules.cmake b/libc/cmake/modules/LLVMLibCObjectRules.cmake index 5fbbfd5..c3e3fa2 100644 --- a/libc/cmake/modules/LLVMLibCObjectRules.cmake +++ b/libc/cmake/modules/LLVMLibCObjectRules.cmake @@ -26,7 +26,7 @@ function(_get_common_compile_options output_var flags) set(ADD_PREFER_GENERIC_FLAG TRUE) endif() - set(compile_options ${LIBC_COMPILE_OPTIONS_DEFAULT} ${ARGN}) + set(compile_options ${LIBC_COMPILE_OPTIONS_DEFAULT}) if(LLVM_COMPILER_IS_GCC_COMPATIBLE) list(APPEND compile_options "-fpie") @@ -357,11 +357,8 @@ function(create_object_library fq_target_name) set(internal_target_name ${fq_target_name}) endif() - _get_common_compile_options( - compile_options - "${ADD_OBJECT_FLAGS}" - ${ADD_OBJECT_COMPILE_OPTIONS} - ) + _get_common_compile_options(compile_options "${ADD_OBJECT_FLAGS}") + list(APPEND compile_options ${ADD_OBJECT_COMPILE_OPTIONS}) # GPU builds require special handling for the objects because we want to # export several different targets at once, e.g. for both Nvidia and AMD. @@ -640,11 +637,8 @@ function(create_entrypoint_object fq_target_name) set(ADD_ENTRYPOINT_OBJ_CXX_STANDARD ${CMAKE_CXX_STANDARD}) endif() - _get_common_compile_options( - common_compile_options - "${ADD_ENTRYPOINT_OBJ_FLAGS}" - ${ADD_ENTRYPOINT_OBJ_COMPILE_OPTIONS} - ) + _get_common_compile_options(common_compile_options "${ADD_ENTRYPOINT_OBJ_FLAGS}") + list(APPEND common_compile_options ${ADD_ENTRYPOINT_OBJ_COMPILE_OPTIONS}) get_fq_deps_list(fq_deps_list ${ADD_ENTRYPOINT_OBJ_DEPENDS}) set(full_deps_list ${fq_deps_list} libc.src.__support.common) -- cgit v1.1 From 6f4cc1310b12bc59210e4596a895db4cb9ad6075 Mon Sep 17 00:00:00 2001 From: Aiden Grossman Date: Fri, 5 Jan 2024 13:31:48 -0800 Subject: [llvm-exegesis] Remove unused Counter::read method (#76651) This method was simply a wrapper around readOrError. All users within the llvm-exegesis code base should have been processing an actual error rather than using the wrapper. This patch removes the wrapper and rewrites the users (just 1) to use the readOrError method. --- llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp | 6 +++++- llvm/tools/llvm-exegesis/lib/PerfHelper.cpp | 13 ------------- llvm/tools/llvm-exegesis/lib/PerfHelper.h | 3 --- 3 files changed, 5 insertions(+), 17 deletions(-) diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp index 5f08c67..dee7af5f 100644 --- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp +++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp @@ -356,7 +356,11 @@ private: if (ChildExitCode == 0) { // The child exited succesfully, read counter values and return // success - CounterValues[0] = Counter->read(); + auto CounterValueOrErr = Counter->readOrError(); + if (!CounterValueOrErr) + return CounterValueOrErr.takeError(); + CounterValues = std::move(*CounterValueOrErr); + return Error::success(); } // The child exited, but not successfully diff --git a/llvm/tools/llvm-exegesis/lib/PerfHelper.cpp b/llvm/tools/llvm-exegesis/lib/PerfHelper.cpp index 3ff1745..314de1e 100644 --- a/llvm/tools/llvm-exegesis/lib/PerfHelper.cpp +++ b/llvm/tools/llvm-exegesis/lib/PerfHelper.cpp @@ -148,17 +148,6 @@ void Counter::stop() { ioctl(FileDescriptor, PERF_EVENT_IOC_DISABLE, 0); } -int64_t Counter::read() const { - auto ValueOrError = readOrError(); - if (ValueOrError) { - if (!ValueOrError.get().empty()) - return ValueOrError.get()[0]; - errs() << "Counter has no reading\n"; - } else - errs() << ValueOrError.takeError() << "\n"; - return -1; -} - llvm::Expected> Counter::readOrError(StringRef /*unused*/) const { int64_t Count = 0; @@ -187,8 +176,6 @@ void Counter::start() {} void Counter::stop() {} -int64_t Counter::read() const { return 42; } - llvm::Expected> Counter::readOrError(StringRef /*unused*/) const { if (IsDummyEvent) { diff --git a/llvm/tools/llvm-exegesis/lib/PerfHelper.h b/llvm/tools/llvm-exegesis/lib/PerfHelper.h index a50974f..894aac1 100644 --- a/llvm/tools/llvm-exegesis/lib/PerfHelper.h +++ b/llvm/tools/llvm-exegesis/lib/PerfHelper.h @@ -95,9 +95,6 @@ public: /// Stops the measurement of the event. void stop(); - /// Returns the current value of the counter or -1 if it cannot be read. - int64_t read() const; - /// Returns the current value of the counter or error if it cannot be read. /// FunctionBytes: The benchmark function being executed. /// This is used to filter out the measurements to ensure they are only -- cgit v1.1 From d9c8edf08afce3d1e563e4521ae847a6809bb993 Mon Sep 17 00:00:00 2001 From: Aiden Grossman Date: Fri, 5 Jan 2024 13:38:05 -0800 Subject: [llvm-exegesis] Add matcher for register initial values (#76666) Currently, the unit tests for the BenchmarkResult struct do not check if the register initial values can be parsed back in. This patch adds a matcher and tests that the register initial values can be parsed correctly. This exercises code already contained within the benchmark to yaml infrastructure. --- .../tools/llvm-exegesis/X86/BenchmarkResultTest.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/llvm/unittests/tools/llvm-exegesis/X86/BenchmarkResultTest.cpp b/llvm/unittests/tools/llvm-exegesis/X86/BenchmarkResultTest.cpp index 6c558b5..616f7ba 100644 --- a/llvm/unittests/tools/llvm-exegesis/X86/BenchmarkResultTest.cpp +++ b/llvm/unittests/tools/llvm-exegesis/X86/BenchmarkResultTest.cpp @@ -46,6 +46,15 @@ MATCHER(EqMCInst, "") { return true; } +MATCHER(EqRegValue, "") { + const RegisterValue Lhs = get<0>(arg); + const RegisterValue Rhs = get<1>(arg); + if (Lhs.Register != Rhs.Register || Lhs.Value != Rhs.Value) + return false; + + return true; +} + namespace { TEST(BenchmarkResultTest, WriteToAndReadFromDisk) { @@ -120,6 +129,8 @@ TEST(BenchmarkResultTest, WriteToAndReadFromDisk) { EXPECT_THAT(FromDisk.Key.Instructions, Pointwise(EqMCInst(), ToDisk.Key.Instructions)); EXPECT_EQ(FromDisk.Key.Config, ToDisk.Key.Config); + EXPECT_THAT(FromDisk.Key.RegisterInitialValues, + Pointwise(EqRegValue(), ToDisk.Key.RegisterInitialValues)); EXPECT_EQ(FromDisk.Mode, ToDisk.Mode); EXPECT_EQ(FromDisk.CpuName, ToDisk.CpuName); EXPECT_EQ(FromDisk.LLVMTriple, ToDisk.LLVMTriple); @@ -137,6 +148,8 @@ TEST(BenchmarkResultTest, WriteToAndReadFromDisk) { EXPECT_THAT(FromDisk.Key.Instructions, Pointwise(EqMCInst(), ToDisk.Key.Instructions)); EXPECT_EQ(FromDisk.Key.Config, ToDisk.Key.Config); + EXPECT_THAT(FromDisk.Key.RegisterInitialValues, + Pointwise(EqRegValue(), ToDisk.Key.RegisterInitialValues)); EXPECT_EQ(FromDisk.Mode, ToDisk.Mode); EXPECT_EQ(FromDisk.CpuName, ToDisk.CpuName); EXPECT_EQ(FromDisk.LLVMTriple, ToDisk.LLVMTriple); -- cgit v1.1 From 853b13342a131e06d61293ec6e840642054c6c85 Mon Sep 17 00:00:00 2001 From: Jan Svoboda Date: Fri, 5 Jan 2024 22:41:51 +0100 Subject: [clang] Fix test for case-insensitive absolute includes (#76985) When CMake on Windows is told to generate the build into a directory whose real path has a different drive letter (e.g. due to a symlink), the "clang/test/Lexer/case-insensitive-include-absolute.c" test fails. That happens because because `trySimplifyPath()` in `PPDirectives.cpp` finds out there's more than a case difference between the `#include` path (containing `%/t`) and the real path, which prevents the diagnostic to fire. I thought this is only an issue on Windows due to the fact that LIT does not drag the path to the build directory through `os.path.realpath()` like it does on other systems (see `abs_path_preserve_drive()` in "llvm/utils/lit/lit/util.py"). However, even after only using `os.path.abspath()` on a Unix system, build generated into a symlinked directory tests correctly. I assume there must be something else at play, but I don't have the time to dig deeper. The fix is is fairly straightforward: use the real path in the `#include` (with `%{/t:real}`), which removes the non-case difference and unblocks the diagnostic. --- clang/test/Lexer/case-insensitive-include-absolute.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/test/Lexer/case-insensitive-include-absolute.c b/clang/test/Lexer/case-insensitive-include-absolute.c index 6247e48..ef9e131 100644 --- a/clang/test/Lexer/case-insensitive-include-absolute.c +++ b/clang/test/Lexer/case-insensitive-include-absolute.c @@ -1,8 +1,8 @@ // REQUIRES: case-insensitive-filesystem // RUN: rm -rf %t && split-file %s %t -// RUN: sed "s|DIR|%/t|g" %t/tu.c.in > %t/tu.c -// RUN: %clang_cc1 -fsyntax-only %t/tu.c 2>&1 | FileCheck %s --DDIR=%/t +// RUN: sed "s|DIR|%{/t:real}|g" %t/tu.c.in > %t/tu.c +// RUN: %clang_cc1 -fsyntax-only %t/tu.c 2>&1 | FileCheck %s -DDIR=%{/t:real} //--- header.h //--- tu.c.in -- cgit v1.1 From f1d75d08adb9841dd9cebad63b76d4823ec2bdac Mon Sep 17 00:00:00 2001 From: Jonathon Penix <107437988+jonathonpenix@users.noreply.github.com> Date: Fri, 5 Jan 2024 13:55:50 -0800 Subject: [clang][Driver] Don't warn when -nostdinc and -nostdinc++ are both specified (#77130) When -nostdinc and -nostdinc++ are both specified and the Baremetal toolchain is used, an unused command line argument warning for -nostdinc++ is produced. This doesn't seem particularly meaningful as -nostdinc++ would have been claimed/used had the check in AddClangCXXStdlibIncludeArgs not short-circuited. So, just claim all arguments in this check. I believe this is consistent with what was done for the GNU toolchain (see 6fe7de90b9e4e466a5c2baadafd5f72d3203651d), so hopefully this is appropriate here as well. --- clang/lib/Driver/ToolChains/BareMetal.cpp | 5 ++--- clang/test/Driver/nostdincxx.cpp | 1 + 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/lib/Driver/ToolChains/BareMetal.cpp b/clang/lib/Driver/ToolChains/BareMetal.cpp index 42c8336..391c47f 100644 --- a/clang/lib/Driver/ToolChains/BareMetal.cpp +++ b/clang/lib/Driver/ToolChains/BareMetal.cpp @@ -293,9 +293,8 @@ void BareMetal::addClangTargetOptions(const ArgList &DriverArgs, void BareMetal::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const { - if (DriverArgs.hasArg(options::OPT_nostdinc) || - DriverArgs.hasArg(options::OPT_nostdlibinc) || - DriverArgs.hasArg(options::OPT_nostdincxx)) + if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdlibinc, + options::OPT_nostdincxx)) return; const Driver &D = getDriver(); diff --git a/clang/test/Driver/nostdincxx.cpp b/clang/test/Driver/nostdincxx.cpp index ef5702a..94d74f2 100644 --- a/clang/test/Driver/nostdincxx.cpp +++ b/clang/test/Driver/nostdincxx.cpp @@ -2,6 +2,7 @@ // RUN: not %clangxx -nostdinc++ %s 2>&1 | FileCheck %s // RUN: not %clangxx -nostdlibinc %s 2>&1 | FileCheck %s // RUN: not %clangxx --target=x86_64-unknown-unknown-gnu -fsyntax-only -nostdinc -nostdinc++ %s 2>&1 | FileCheck /dev/null --implicit-check-not=-Wunused-command-line-argument +// RUN: not %clangxx --target=riscv64-unknown-elf -fsyntax-only -nostdinc -nostdinc++ %s 2>&1 | FileCheck /dev/null --implicit-check-not=-Wunused-command-line-argument // CHECK: 'vector' file not found #include -- cgit v1.1 From d7b4debf98fd740f821bda717de7b807e26ae95a Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Fri, 5 Jan 2024 22:13:25 +0000 Subject: [cmake,Apple] Check ld-classic when looking for ld64. (#77136) In newer SDKs, ld64 is called ld-classic. Look for it first, as ld in those SDKs is still missing some functionality some tests depend on. This enables running the tests from check-llvm-tools-lto with newer SDKs on ARM64 macOS. --- llvm/cmake/config-ix.cmake | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/llvm/cmake/config-ix.cmake b/llvm/cmake/config-ix.cmake index 3e12213..bf1b110 100644 --- a/llvm/cmake/config-ix.cmake +++ b/llvm/cmake/config-ix.cmake @@ -639,12 +639,25 @@ if(CMAKE_HOST_APPLE AND APPLE) if(NOT CMAKE_XCRUN) find_program(CMAKE_XCRUN NAMES xcrun) endif() + + # First, check if there's ld-classic, which is ld64 in newer SDKs. if(CMAKE_XCRUN) - execute_process(COMMAND ${CMAKE_XCRUN} -find ld + execute_process(COMMAND ${CMAKE_XCRUN} -find ld-classic OUTPUT_VARIABLE LD64_EXECUTABLE OUTPUT_STRIP_TRAILING_WHITESPACE) else() - find_program(LD64_EXECUTABLE NAMES ld DOC "The ld64 linker") + find_program(LD64_EXECUTABLE NAMES ld-classic DOC "The ld64 linker") + endif() + + # Otherwise look for ld directly. + if(NOT LD64_EXECUTABLE) + if(CMAKE_XCRUN) + execute_process(COMMAND ${CMAKE_XCRUN} -find ld + OUTPUT_VARIABLE LD64_EXECUTABLE + OUTPUT_STRIP_TRAILING_WHITESPACE) + else() + find_program(LD64_EXECUTABLE NAMES ld DOC "The ld64 linker") + endif() endif() endif() -- cgit v1.1 From 8e92d9ea8dfcc49223e4ac62c998aea4d2d4fc84 Mon Sep 17 00:00:00 2001 From: Shubham Sandeep Rastogi Date: Fri, 5 Jan 2024 14:22:29 -0800 Subject: Move verify-no-file.yaml to AArch64 folder (#77149) This test fails on power pc and solaris, moving it to AArch64 folder because the yaml is generated for an AArch64 MachO object file. --- .../llvm-dwarfdump/AArch64/verify-no-file.yaml | 355 +++++++++++++++++++++ llvm/test/tools/llvm-dwarfdump/verify-no-file.yaml | 355 --------------------- 2 files changed, 355 insertions(+), 355 deletions(-) create mode 100644 llvm/test/tools/llvm-dwarfdump/AArch64/verify-no-file.yaml delete mode 100644 llvm/test/tools/llvm-dwarfdump/verify-no-file.yaml diff --git a/llvm/test/tools/llvm-dwarfdump/AArch64/verify-no-file.yaml b/llvm/test/tools/llvm-dwarfdump/AArch64/verify-no-file.yaml new file mode 100644 index 0000000..1327cc2 --- /dev/null +++ b/llvm/test/tools/llvm-dwarfdump/AArch64/verify-no-file.yaml @@ -0,0 +1,355 @@ +# RUN: yaml2obj %s -o %t.o +# RUN: llvm-dwarfdump -arch arm64 --debug-line --verify %t.o 2>&1 | FileCheck %s + +# CHECK-NOT: error: .debug_line[0x{{[0-9a-f]+}}][0] has invalid file index 1 (valid values are [1,0]): +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x100000C + cpusubtype: 0x0 + filetype: 0x1 + ncmds: 4 + sizeofcmds: 1000 + flags: 0x2000 + reserved: 0x0 +LoadCommands: + - cmd: LC_SEGMENT_64 + cmdsize: 872 + segname: '' + vmaddr: 0 + vmsize: 635 + fileoff: 1032 + filesize: 635 + maxprot: 7 + initprot: 7 + nsects: 10 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0x0 + size: 4 + offset: 0x408 + align: 2 + reloff: 0x0 + nreloc: 0 + flags: 0x80000400 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: C0035FD6 + - sectname: __debug_abbrev + segname: __DWARF + addr: 0x4 + size: 50 + offset: 0x40C + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x2000000 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + - sectname: __debug_info + segname: __DWARF + addr: 0x36 + size: 76 + offset: 0x43E + align: 0 + reloff: 0x688 + nreloc: 2 + flags: 0x2000000 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + relocations: + - address: 0x33 + symbolnum: 1 + pcrel: false + length: 3 + extern: false + type: 0 + scattered: false + value: 0 + - address: 0x26 + symbolnum: 1 + pcrel: false + length: 3 + extern: false + type: 0 + scattered: false + value: 0 + - sectname: __debug_str + segname: __DWARF + addr: 0x82 + size: 196 + offset: 0x48A + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x2000000 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + - sectname: __apple_names + segname: __DWARF + addr: 0x146 + size: 88 + offset: 0x54E + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x2000000 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 485341480100000002000000020000000C000000000000000100000001000600FFFFFFFF000000008973880BEB28616A3800000048000000B8000000010000003200000000000000BC000000010000003200000000000000 + - sectname: __apple_objc + segname: __DWARF + addr: 0x19E + size: 36 + offset: 0x5A6 + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x2000000 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 485341480100000001000000000000000C000000000000000100000001000600FFFFFFFF + - sectname: __apple_namespac + segname: __DWARF + addr: 0x1C2 + size: 36 + offset: 0x5CA + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x2000000 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 485341480100000001000000000000000C000000000000000100000001000600FFFFFFFF + - sectname: __apple_types + segname: __DWARF + addr: 0x1E6 + size: 44 + offset: 0x5EE + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x2000000 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 48534148010000000100000000000000140000000000000003000000010006000300050004000B00FFFFFFFF + - sectname: __compact_unwind + segname: __LD + addr: 0x218 + size: 32 + offset: 0x620 + align: 3 + reloff: 0x698 + nreloc: 1 + flags: 0x2000000 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: '0000000000000000040000000000000200000000000000000000000000000000' + relocations: + - address: 0x0 + symbolnum: 1 + pcrel: false + length: 3 + extern: false + type: 0 + scattered: false + value: 0 + - sectname: __debug_line + segname: __DWARF + addr: 0x238 + size: 67 + offset: 0x640 + align: 0 + reloff: 0x6A0 + nreloc: 1 + flags: 0x2000000 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + relocations: + - address: 0x35 + symbolnum: 1 + pcrel: false + length: 3 + extern: false + type: 0 + scattered: false + value: 0 + - cmd: LC_BUILD_VERSION + cmdsize: 24 + platform: 1 + minos: 917504 + sdk: 918528 + ntools: 0 + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 1704 + nsyms: 3 + stroff: 1752 + strsize: 24 + - cmd: LC_DYSYMTAB + cmdsize: 80 + ilocalsym: 0 + nlocalsym: 2 + iextdefsym: 2 + nextdefsym: 1 + iundefsym: 3 + nundefsym: 0 + tocoff: 0 + ntoc: 0 + modtaboff: 0 + nmodtab: 0 + extrefsymoff: 0 + nextrefsyms: 0 + indirectsymoff: 0 + nindirectsyms: 0 + extreloff: 0 + nextrel: 0 + locreloff: 0 + nlocrel: 0 +LinkEditData: + NameList: + - n_strx: 16 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 0 + - n_strx: 10 + n_type: 0xE + n_sect: 9 + n_desc: 0 + n_value: 536 + - n_strx: 1 + n_type: 0xF + n_sect: 1 + n_desc: 0 + n_value: 0 + StringTable: + - '' + - __Z3foov + - ltmp1 + - ltmp0 + - '' + - '' +DWARF: + debug_str: + - 'Apple clang version 16.0.0 (clang-1600.0.9.14)' + - '/tmp/test.cpp' + - '/Library/Developer/CommandLineTools/SDKs/MacOSX14.4.sdk' + - MacOSX14.4.sdk + - '/Users/shubham/Development/llvm-project/build_ninja' + - foo + - _Z3foov + debug_abbrev: + - ID: 0 + Table: + - Code: 0x1 + Tag: DW_TAG_compile_unit + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_producer + Form: DW_FORM_strp + - Attribute: DW_AT_language + Form: DW_FORM_data2 + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_LLVM_sysroot + Form: DW_FORM_strp + - Attribute: DW_AT_APPLE_sdk + Form: DW_FORM_strp + - Attribute: DW_AT_stmt_list + Form: DW_FORM_sec_offset + - Attribute: DW_AT_comp_dir + Form: DW_FORM_strp + - Attribute: DW_AT_low_pc + Form: DW_FORM_addr + - Attribute: DW_AT_high_pc + Form: DW_FORM_data4 + - Code: 0x2 + Tag: DW_TAG_subprogram + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_low_pc + Form: DW_FORM_addr + - Attribute: DW_AT_high_pc + Form: DW_FORM_data4 + - Attribute: DW_AT_APPLE_omit_frame_ptr + Form: DW_FORM_flag_present + - Attribute: DW_AT_frame_base + Form: DW_FORM_exprloc + - Attribute: DW_AT_linkage_name + Form: DW_FORM_strp + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_decl_file + Form: DW_FORM_data1 + - Attribute: DW_AT_decl_line + Form: DW_FORM_data1 + - Attribute: DW_AT_external + Form: DW_FORM_flag_present + debug_info: + - Length: 0x48 + Version: 4 + AbbrevTableID: 0 + AbbrOffset: 0x0 + AddrSize: 8 + Entries: + - AbbrCode: 0x1 + Values: + - Value: 0x0 + - Value: 0x4 + - Value: 0x2F + - Value: 0x3D + - Value: 0x75 + - Value: 0x0 + - Value: 0x84 + - Value: 0x0 + - Value: 0x4 + - AbbrCode: 0x2 + Values: + - Value: 0x0 + - Value: 0x4 + - Value: 0x1 + - Value: 0x1 + BlockData: [ 0x6F ] + - Value: 0xBC + - Value: 0xB8 + - Value: 0x1 + - Value: 0x1 + - Value: 0x1 + - AbbrCode: 0x0 + debug_line: + - Length: 38 + Version: 4 + PrologueLength: 29 + MinInstLength: 1 + MaxOpsPerInst: 1 + DefaultIsStmt: 1 + LineBase: 251 + LineRange: 14 + OpcodeBase: 13 + StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ] + IncludeDirs: + - '/tmp' + Files: + - Name: '' + DirIdx: 10 + ModTime: 11 + Length: 12 + Opcodes: + - Opcode: DW_LNS_extended_op + ExtLen: 1 + SubOpcode: DW_LNE_end_sequence + Data: 0 +... diff --git a/llvm/test/tools/llvm-dwarfdump/verify-no-file.yaml b/llvm/test/tools/llvm-dwarfdump/verify-no-file.yaml deleted file mode 100644 index fc25fce..0000000 --- a/llvm/test/tools/llvm-dwarfdump/verify-no-file.yaml +++ /dev/null @@ -1,355 +0,0 @@ -# RUN: yaml2obj %s -o %t.o -# RUN: llvm-dwarfdump --debug-line --verify %t.o 2>&1 | FileCheck %s - -# CHECK-NOT: error: .debug_line[0x{{[0-9a-f]+}}][0] has invalid file index 1 (valid values are [1,0]): ---- !mach-o -FileHeader: - magic: 0xFEEDFACF - cputype: 0x100000C - cpusubtype: 0x0 - filetype: 0x1 - ncmds: 4 - sizeofcmds: 1000 - flags: 0x2000 - reserved: 0x0 -LoadCommands: - - cmd: LC_SEGMENT_64 - cmdsize: 872 - segname: '' - vmaddr: 0 - vmsize: 635 - fileoff: 1032 - filesize: 635 - maxprot: 7 - initprot: 7 - nsects: 10 - flags: 0 - Sections: - - sectname: __text - segname: __TEXT - addr: 0x0 - size: 4 - offset: 0x408 - align: 2 - reloff: 0x0 - nreloc: 0 - flags: 0x80000400 - reserved1: 0x0 - reserved2: 0x0 - reserved3: 0x0 - content: C0035FD6 - - sectname: __debug_abbrev - segname: __DWARF - addr: 0x4 - size: 50 - offset: 0x40C - align: 0 - reloff: 0x0 - nreloc: 0 - flags: 0x2000000 - reserved1: 0x0 - reserved2: 0x0 - reserved3: 0x0 - - sectname: __debug_info - segname: __DWARF - addr: 0x36 - size: 76 - offset: 0x43E - align: 0 - reloff: 0x688 - nreloc: 2 - flags: 0x2000000 - reserved1: 0x0 - reserved2: 0x0 - reserved3: 0x0 - relocations: - - address: 0x33 - symbolnum: 1 - pcrel: false - length: 3 - extern: false - type: 0 - scattered: false - value: 0 - - address: 0x26 - symbolnum: 1 - pcrel: false - length: 3 - extern: false - type: 0 - scattered: false - value: 0 - - sectname: __debug_str - segname: __DWARF - addr: 0x82 - size: 196 - offset: 0x48A - align: 0 - reloff: 0x0 - nreloc: 0 - flags: 0x2000000 - reserved1: 0x0 - reserved2: 0x0 - reserved3: 0x0 - - sectname: __apple_names - segname: __DWARF - addr: 0x146 - size: 88 - offset: 0x54E - align: 0 - reloff: 0x0 - nreloc: 0 - flags: 0x2000000 - reserved1: 0x0 - reserved2: 0x0 - reserved3: 0x0 - content: 485341480100000002000000020000000C000000000000000100000001000600FFFFFFFF000000008973880BEB28616A3800000048000000B8000000010000003200000000000000BC000000010000003200000000000000 - - sectname: __apple_objc - segname: __DWARF - addr: 0x19E - size: 36 - offset: 0x5A6 - align: 0 - reloff: 0x0 - nreloc: 0 - flags: 0x2000000 - reserved1: 0x0 - reserved2: 0x0 - reserved3: 0x0 - content: 485341480100000001000000000000000C000000000000000100000001000600FFFFFFFF - - sectname: __apple_namespac - segname: __DWARF - addr: 0x1C2 - size: 36 - offset: 0x5CA - align: 0 - reloff: 0x0 - nreloc: 0 - flags: 0x2000000 - reserved1: 0x0 - reserved2: 0x0 - reserved3: 0x0 - content: 485341480100000001000000000000000C000000000000000100000001000600FFFFFFFF - - sectname: __apple_types - segname: __DWARF - addr: 0x1E6 - size: 44 - offset: 0x5EE - align: 0 - reloff: 0x0 - nreloc: 0 - flags: 0x2000000 - reserved1: 0x0 - reserved2: 0x0 - reserved3: 0x0 - content: 48534148010000000100000000000000140000000000000003000000010006000300050004000B00FFFFFFFF - - sectname: __compact_unwind - segname: __LD - addr: 0x218 - size: 32 - offset: 0x620 - align: 3 - reloff: 0x698 - nreloc: 1 - flags: 0x2000000 - reserved1: 0x0 - reserved2: 0x0 - reserved3: 0x0 - content: '0000000000000000040000000000000200000000000000000000000000000000' - relocations: - - address: 0x0 - symbolnum: 1 - pcrel: false - length: 3 - extern: false - type: 0 - scattered: false - value: 0 - - sectname: __debug_line - segname: __DWARF - addr: 0x238 - size: 67 - offset: 0x640 - align: 0 - reloff: 0x6A0 - nreloc: 1 - flags: 0x2000000 - reserved1: 0x0 - reserved2: 0x0 - reserved3: 0x0 - relocations: - - address: 0x35 - symbolnum: 1 - pcrel: false - length: 3 - extern: false - type: 0 - scattered: false - value: 0 - - cmd: LC_BUILD_VERSION - cmdsize: 24 - platform: 1 - minos: 917504 - sdk: 918528 - ntools: 0 - - cmd: LC_SYMTAB - cmdsize: 24 - symoff: 1704 - nsyms: 3 - stroff: 1752 - strsize: 24 - - cmd: LC_DYSYMTAB - cmdsize: 80 - ilocalsym: 0 - nlocalsym: 2 - iextdefsym: 2 - nextdefsym: 1 - iundefsym: 3 - nundefsym: 0 - tocoff: 0 - ntoc: 0 - modtaboff: 0 - nmodtab: 0 - extrefsymoff: 0 - nextrefsyms: 0 - indirectsymoff: 0 - nindirectsyms: 0 - extreloff: 0 - nextrel: 0 - locreloff: 0 - nlocrel: 0 -LinkEditData: - NameList: - - n_strx: 16 - n_type: 0xE - n_sect: 1 - n_desc: 0 - n_value: 0 - - n_strx: 10 - n_type: 0xE - n_sect: 9 - n_desc: 0 - n_value: 536 - - n_strx: 1 - n_type: 0xF - n_sect: 1 - n_desc: 0 - n_value: 0 - StringTable: - - '' - - __Z3foov - - ltmp1 - - ltmp0 - - '' - - '' -DWARF: - debug_str: - - 'Apple clang version 16.0.0 (clang-1600.0.9.14)' - - '/tmp/test.cpp' - - '/Library/Developer/CommandLineTools/SDKs/MacOSX14.4.sdk' - - MacOSX14.4.sdk - - '/Users/shubham/Development/llvm-project/build_ninja' - - foo - - _Z3foov - debug_abbrev: - - ID: 0 - Table: - - Code: 0x1 - Tag: DW_TAG_compile_unit - Children: DW_CHILDREN_yes - Attributes: - - Attribute: DW_AT_producer - Form: DW_FORM_strp - - Attribute: DW_AT_language - Form: DW_FORM_data2 - - Attribute: DW_AT_name - Form: DW_FORM_strp - - Attribute: DW_AT_LLVM_sysroot - Form: DW_FORM_strp - - Attribute: DW_AT_APPLE_sdk - Form: DW_FORM_strp - - Attribute: DW_AT_stmt_list - Form: DW_FORM_sec_offset - - Attribute: DW_AT_comp_dir - Form: DW_FORM_strp - - Attribute: DW_AT_low_pc - Form: DW_FORM_addr - - Attribute: DW_AT_high_pc - Form: DW_FORM_data4 - - Code: 0x2 - Tag: DW_TAG_subprogram - Children: DW_CHILDREN_no - Attributes: - - Attribute: DW_AT_low_pc - Form: DW_FORM_addr - - Attribute: DW_AT_high_pc - Form: DW_FORM_data4 - - Attribute: DW_AT_APPLE_omit_frame_ptr - Form: DW_FORM_flag_present - - Attribute: DW_AT_frame_base - Form: DW_FORM_exprloc - - Attribute: DW_AT_linkage_name - Form: DW_FORM_strp - - Attribute: DW_AT_name - Form: DW_FORM_strp - - Attribute: DW_AT_decl_file - Form: DW_FORM_data1 - - Attribute: DW_AT_decl_line - Form: DW_FORM_data1 - - Attribute: DW_AT_external - Form: DW_FORM_flag_present - debug_info: - - Length: 0x48 - Version: 4 - AbbrevTableID: 0 - AbbrOffset: 0x0 - AddrSize: 8 - Entries: - - AbbrCode: 0x1 - Values: - - Value: 0x0 - - Value: 0x4 - - Value: 0x2F - - Value: 0x3D - - Value: 0x75 - - Value: 0x0 - - Value: 0x84 - - Value: 0x0 - - Value: 0x4 - - AbbrCode: 0x2 - Values: - - Value: 0x0 - - Value: 0x4 - - Value: 0x1 - - Value: 0x1 - BlockData: [ 0x6F ] - - Value: 0xBC - - Value: 0xB8 - - Value: 0x1 - - Value: 0x1 - - Value: 0x1 - - AbbrCode: 0x0 - debug_line: - - Length: 38 - Version: 4 - PrologueLength: 29 - MinInstLength: 1 - MaxOpsPerInst: 1 - DefaultIsStmt: 1 - LineBase: 251 - LineRange: 14 - OpcodeBase: 13 - StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ] - IncludeDirs: - - '/tmp' - Files: - - Name: '' - DirIdx: 10 - ModTime: 11 - Length: 12 - Opcodes: - - Opcode: DW_LNS_extended_op - ExtLen: 1 - SubOpcode: DW_LNE_end_sequence - Data: 0 -... -- cgit v1.1 From 5b54dd4f5eccc66c6352f9277d0a6edbd2e80435 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Fri, 5 Jan 2024 14:30:52 -0800 Subject: [tsan] Generalize FrameIsInternal (#77143) Prepare to move this into sanitizer_common. --- compiler-rt/lib/tsan/rtl/tsan_report.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/compiler-rt/lib/tsan/rtl/tsan_report.cpp b/compiler-rt/lib/tsan/rtl/tsan_report.cpp index 35cb671..167e4be 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_report.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_report.cpp @@ -278,13 +278,9 @@ static bool FrameIsInternal(const SymbolizedStack *frame) { return false; const char *file = frame->info.file; const char *module = frame->info.module; - if (file != 0 && - (internal_strstr(file, "tsan_interceptors_posix.cpp") || - internal_strstr(file, "tsan_interceptors_memintrinsics.cpp") || - internal_strstr(file, "sanitizer_common_interceptors.inc") || - internal_strstr(file, "tsan_interface_"))) + if (file != 0 && (internal_strstr(file, "/compiler-rt/lib/"))) return true; - if (module != 0 && (internal_strstr(module, "libclang_rt.tsan_"))) + if (module != 0 && (internal_strstr(module, "libclang_rt."))) return true; return false; } -- cgit v1.1