<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/130509>130509</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            Illegal Instruction Fault From Improper CPU Feature Detection
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          EmmaJaneBonestell
      </td>
    </tr>
</table>

<pre>
    **LLVM Versions Tested**: 18, 19, 20, current tip

### Issue Summary
LLVM components incorrectly detect supported CPU instructions, resulting in the generation of illegal instructions, resulting in faulting binaries.

### Detailed Description
The compiler infrastructure appears to use static CPU model mappings to determine available instruction sets, instead of querying what the CPU actually supports (via `/proc/cpuinfo` or hwcap on AArch64). This causes particular problems on:

1. Arm-V9 CPUs from Qualcomm SoCs that do not implement SVE despite the Arm-V9 specification requiring it
2. Potentially any system where the Linux kernel is not configured with `CONFIG_ARM64_SVE=Y`

But is not necessarily limited to AArch64 or the above.

This affects instruction selection/codegen/runtime dispatching for all of LLVM like Clang, Flang, OpenMP, ORC JIT, etc.

### Reproduction Steps
Below is a relatively minimal test case using ORC JIT that demonstrates the issue. A Termux environment on Android devices using Qualcomm chips is likely the easiest target for reproduction. This could also be reproduced with a vectorizable loop in C code, with Clang, using the "-march=native" flag.

```cpp
#include <iostream>
#include <vector>
#include <string>

#include "llvm/ExecutionEngine/Orc/LLJIT.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/TargetParser/Host.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Target/TargetMachine.h"

using namespace llvm;
using namespace llvm::orc;

// Diagnostic handler to suppress remarks
class SilenceRemarksHandler : public DiagnosticHandler {
public:
  bool handleDiagnostics(const DiagnosticInfo &DI) override {
    // Ignore remarks, pass through other diagnostics
    if (DI.getSeverity() == DS_Remark) {
      return true;
    }
    return false;
 }
};

std::unique_ptr<Module> createVectorModule(LLVMContext &Context) {
 auto M = std::make_unique<Module>("VecTest", Context);
  
  auto *FloatTy = Type::getFloatTy(Context);
  auto *FloatPtrTy = PointerType::get(FloatTy, 0);
  auto *Int32Ty = Type::getInt32Ty(Context);
 
  FunctionType *FT = FunctionType::get(
      Type::getVoidTy(Context),
 {FloatPtrTy, FloatPtrTy, FloatPtrTy, Int32Ty},
      false);
  
 Function *F = Function::Create(FT, Function::ExternalLinkage, "vector_op", M.get());
  F->addFnAttr(Attribute::NoUnwind);
  
  auto Args = F->arg_begin();
  Value *A = &*Args++;
  Value *B = &*Args++;
  Value *Result = &*Args++;
  Value *Length = &*Args++;
  
  BasicBlock *EntryBB = BasicBlock::Create(Context, "entry", F);
  BasicBlock *LoopBB = BasicBlock::Create(Context, "loop", F);
  BasicBlock *ExitBB = BasicBlock::Create(Context, "exit", F);
  
  IRBuilder<> Builder(Context);
  
  Builder.SetInsertPoint(EntryBB);
  Value *IndexAlloca = Builder.CreateAlloca(Int32Ty, nullptr, "i");
 Builder.CreateStore(ConstantInt::get(Int32Ty, 0), IndexAlloca);
 Builder.CreateBr(LoopBB);
  
  Builder.SetInsertPoint(LoopBB);
  Value *Index = Builder.CreateLoad(Int32Ty, IndexAlloca, "idx");
  Value *LoopCond = Builder.CreateICmpSLT(Index, Length, "cond");
  
  Value *APtr = Builder.CreateGEP(FloatTy, A, Index, "a_ptr");
  Value *BPtr = Builder.CreateGEP(FloatTy, B, Index, "b_ptr");
  Value *ResultPtr = Builder.CreateGEP(FloatTy, Result, Index, "result_ptr");
  
  MDNode *AccessGroup = MDNode::get(Context, {});
  
  Value *AVal = Builder.CreateLoad(FloatTy, APtr, "a_val");
  Value *BVal = Builder.CreateLoad(FloatTy, BPtr, "b_val");
  
 cast<Instruction>(AVal)->setMetadata("llvm.mem.parallel_loop_access", AccessGroup);
 cast<Instruction>(BVal)->setMetadata("llvm.mem.parallel_loop_access", AccessGroup);
  
  Value *Square = Builder.CreateFMul(AVal, AVal, "square");
  Value *AddResult = Builder.CreateFAdd(Square, BVal, "add");
  
  auto *StoreInst = Builder.CreateStore(AddResult, ResultPtr);
  StoreInst->setMetadata("llvm.mem.parallel_loop_access", AccessGroup);
  
  Value *NextIndex = Builder.CreateAdd(Index, ConstantInt::get(Int32Ty, 1), "next_idx");
 Builder.CreateStore(NextIndex, IndexAlloca);
  
  // Loop metadata to force vectorization
  MDNode *ForcedVec = MDNode::get(Context, {
 MDString::get(Context, "llvm.loop.vectorize.enable"),
 ConstantAsMetadata::get(ConstantInt::get(Type::getInt1Ty(Context), 1))
 });
  
  MDNode *LoopID = MDNode::get(Context, {MDNode::get(Context, {}), ForcedVec});
  LoopID->replaceOperandWith(0, LoopID);
  
 Builder.CreateCondBr(LoopCond, LoopBB, ExitBB)->setMetadata("llvm.loop", LoopID);
  Builder.SetInsertPoint(ExitBB);
  Builder.CreateRetVoid();
  
 verifyFunction(*F);
  return M;
}

// Apply optimization passes to force vectorization
void optimizeModule(Module &M, TargetMachine *TM) {
 PassBuilder PB;
  
  LoopAnalysisManager LAM;
  FunctionAnalysisManager FAM;
  CGSCCAnalysisManager CGAM;
  ModuleAnalysisManager MAM;
  
 FAM.registerPass([&] { return TM->getTargetIRAnalysis(); });
  
 PB.registerModuleAnalyses(MAM);
  PB.registerCGSCCAnalyses(CGAM);
 PB.registerFunctionAnalyses(FAM);
  PB.registerLoopAnalyses(LAM);
 PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
  
  ModulePassManager MPM = PB.buildPerModuleDefaultPipeline(OptimizationLevel::O3);
  
  MPM.run(M, MAM);
}

int main(int argc, char** argv) {
  // Parse command line arguments
  bool useNoSVE = false;
  for (int i = 1; i < argc; i++) {
 if (std::string(argv[i]) == "--use-nosve") {
      useNoSVE = true;
 }
  }

  InitializeNativeTarget();
 InitializeNativeTargetAsmPrinter();
  InitializeNativeTargetAsmParser();
 
  // Silence remarks
  LLVMContext Context;
 Context.setDiagnosticHandler(std::make_unique<SilenceRemarksHandler>());
 
  auto JTMB = cantFail(JITTargetMachineBuilder::detectHost());
 JTMB.setCodeGenOptLevel(CodeGenOptLevel::Aggressive);
  
  if (useNoSVE) {
    JTMB.addFeatures(std::vector<std::string>{"-sve"});
  }
  
 std::unique_ptr<TargetMachine> TM(cantFail(JTMB.createTargetMachine()));
 auto M = createVectorModule(Context);
 M->setDataLayout(TM->createDataLayout());
  
  // Apply optimization passes to ensure and force vectorization
  optimizeModule(*M, TM.get());
  
  // Set-up JIT compiled function
  auto JIT = cantFail(LLJITBuilder().setJITTargetMachineBuilder(std::move(JTMB)).create());
 cantFail(JIT->addIRModule(ThreadSafeModule(std::move(M), std::make_unique<LLVMContext>())));
  auto VecOpAddr = cantFail(JIT->lookup("vector_op"));
  auto *VectorOp = (void(*)(float*, float*, float*, int))VecOpAddr.getValue();
  const int Length = 1024;
 std::vector<float> A(Length), B(Length), Result(Length);
  for (int i = 0; i < Length; i++) {
    A[i] = i;
    B[i] = i * 2;
  }
  
  // Execute JIT-compiled function
  // It should fault with an illegal instruction on such devices
  VectorOp(A.data(), B.data(), Result.data(), Length);
  
 // Will only reach here if execution succeeds
  std::cout << "Result[10]: " << Result[10] << std::endl;
  
  return 0;
}
```

When executed normally, the program generates illegal instructions on hardware that meets the specified conditions. It will also accept an argument `--use-nosve` to add `-sve` to the JIT's features list which should cause it not crash.

### Additional Context
Attempting to workaround this issue locally revealed frustrating inconsistentencies in how LLVM CPU features are specified across different LLVM interfaces:
- `-march=`
- `-mcpu=`
- `-Xclang -target-feature`
- `llvm::orc::JITTargetMachineBuilder::addFeatures()`

Each of these accepts a different set of feature flags with inconsistent naming conventions and limited documentation.
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJy0Ok1z4rqyv8bZdIUiIh9kkYWBMIdTYYaX5OS8t0oJuwG9kSUfSSbh_vpbLcnG5mMmd3GnUh5jtfpb3a2WuLVirRAfkptRcjO54JXbaPPwWBT8T65wpBVah1JeLHW-e0hYmrD06eltDm9orNDKwisB5GEkGaRwNUzYGK7u6cn69MwqY1A5cKJM-in9sUH4g5m1FcJLVRTc7JJ-QJ3potQKlbMgVKaNwczJHeToMHNgq7LUxmEO48VfIJR1psocsUK0DNpKOqHWIBS4DcIaFRpO46BXIKTENZe_nrbi8X0pFDcCbe-Q7Qk6LiTmMEGbGVESnqSfvm7QMy8kGhBqZXigUhkEXpbIjQWnobII1nEnMi9CoXOUUPCyFGrtAUhSUwiFwLdcSL6U2OYYLDrPNX1DnpNg_1RodsTzx4Y7Lzih5pmruJS7WmkWEjbcCg7JbT9h09LoLGHTrKyEWunktg_awOYj4yVoBWlqss3tdcLue_C6ERYyXlm0UHLjRFZJbqA0eimxsKBVMkiDlq56kJri8u2eOLCwMrqA_6m4zHRRwIseW3DEYq5BaQeiKCUW5B0vb4-Qoy2FQ89_RGJLzMRKZMGEBv-phPF2ckk_ZT1YaIfKCS8lVzuwO-uwgI8NmoDnSajqE36iUShBWE8102ol1pXBHD6E25A6xj--T2ff3tPn-e31-8vbYzKY_B9pycs0qlw9VWGG1nIj5A6kKAQ5otO1skiBRJQv9Raj23jd8dUKM-_QbTNK9G9kA53jGunNVMqJAiEXtuQu25CwK22AS0mG9itEip8IY8nVmtxgWr_8KFHNF_7teQx_zl7pFV125L_PWBqdRzZeHJaWhESpP0hMDgYld2KLcgeFUKLgEhxaBxm3CJUlliKFaEwsNAnGHVovv6B13YMUXtEU1Seg2gqjlTc0uZbKjRY55LgVGdqIsvGSbCNKS5yQnHLnMSK3glhw3KzReY2YlhS1i-pK5sCl1bDEBqA2M4ctZk4b8S-_pKTWJa33MZD2SVceqtFr4IqIJ4xdFtxkm2QwUV4zCWOwknxdq_a2H_6ysgyaFiqTVY6QDMZCW2eQF8ng8WgsMHRqxDry8zjSHWRMym2RsOnjJ2YVif-o1kJhwqY_DK3op6c_Z6-9TcLYuZmz54RNp5UKyvst5Ox5VAmZo_k96FznlcTfwy24tXOu-PorSN_QiJX4DeRLCHIJm756J3nx6-uXUwLgghuLJmHTP7T9NTwxjTa-fEUlqeJyZ4VtaL0aruxKm2KmVvoLvDUvc06xYK_Yfhr8U_ECbckzBD9vMDo7QulZmyyAeKrThE1hIvhaaUvpaMNVTrnLaZ8xDFoLBgtuflKAyCS3Fl6ERJXhc_j8R5xBmb-sllJkLXzN4B1RDMMhTwAstZaR3n6CTdgwo0jSQkJ6goTdTmYJuwe9RWME6cnjBACIYszWShts2GVjKIldtzG6Wm9Auw0ayFukwmyxopw4mfW8w2zRCLdL2JBoJYNJMpjA5OU9COu_NWQBDLrKKHCmwqBTz83dJL7F4RWXth4Pg_SsbWBdHgxTKfFPhe-lM8lgHNZQMniEzCB3-OajRPzKhpQDxlo5_HSkmfjaYo9XTsOcBICGQMF_4nug0qbgZWVvmFEdR67FxrBHWMvlHx5rwtKp1Ny97jz6112JAf8aXRxI2PAYQ2fywpk4f6GFcmg6aBI2bDCNoX8CyUy5ATvFQRw4xYFHUEc8muS5efU42p_bbDSm7gy8aZEf0mDjYN_RXr6Qms__qnm9m8TZ_l9wl67ma_Y8xx2GA09j7ySkNp_xu4OPnw6N4vJJqJ987dNcwljIO--6jCaf96LEJEtDfHqZDB55nk9V6pxJ2JD-E8vKRWV813-pD6Hyk56SmrUNzHosZv2-xLVQkUgEf-Oy8pZIPWjCbundrG3CRvR3CDb6Gtizr-e_BvuEak014C9g_WPErchGUmc_adajcmY3CuzsRw7s0TiI1znSlKjvaUsHXcRPWpf_GV6qY36L9vFTuP-Q3U_hTqD1j6YeSAZjClP1r1MrPzATc-ULrVGLxvmFn7Bh1OMpl5ipHD9TKXXGA98RR-A3DCRs2Kz5MahKSoqgQQDhua_xdme_OG2iyNZxRYGjvfBbOPtheUOLm3NIR6SAYL8vy38E3hX_hOBPmuddFjusBdHzz47wLW_XuhxrlZ9APBsX5cvTq8ed4yehCmsjIs00rXR2KNp-CS-cOYH22-OiG9HThueImPu0d5rf0ReRjg6RLn-BNISHL2IOwIfoQ8fgmIZ_zCffdR50ktF28ZvRVelphZG2q7UX3d3IZ4Nz-n3j8rw_tBW8aNYAf99yeU61X8U32uNbHuOjR8atSwbj2X53G0oLYjlh95QALLo5Op5zx0PNQUVpr8CiV3LDpUT5ToHsnXuNxcDTUt-e4jlio_8GsQMbvPxTcYMntDadV7IReAz1_wlj1k85Y4M0z1u56gBlmpMhXuL8MYz2SHl-ainW9ZGPbqSfE1jryNdQ3vu4N3ODsUHyX1Xod_x05yJdkL9Zdb-P1VcxVieMKfx074dh8LQmGhbOhvnAc9xoUASFIiqDtkorbTLctxZiM7AdBaYEkb9h9rUY0E9hPnmJ-__TUNEApPNeTRl7qPhS1q4Wispaaalt7NdFeUqlhzX11XG5G3V9X29rzkZAUtds8iXBvxgcqSCpFdolHWiRvxosJc_wR4mGq_xvQUls6LvRAeaA365jUH5scvnYZ70wb-SzTCilfhlpWiXZEb3zpVCN9xAycPUcdh7d-pketGld7Zqqn8bTdsUWN6LzuOkMe9Bm-5-WpdyBLp0oovP6jTPa86691SKvZ2CzKw0vVEPPSe5O14Ic4XXe2qG2-iew6NbZpLC6bRIbRPCUzps9SZTzEGS6Bxl_exmPD8fH3_YAgdVDiPkewO-60nnP4FpYh4bYJcXejGiLcDMhMWq9vs7JD9bogsSz533PJ1rqxAJZjBrcbWaQJhEfe-gWZEsuD-hFaiBbgF0dedjpOaR7dXu4pwOUmdHWPtdqMPpT7MHGXukUmb-F_7uct1TdavbBfBE6E4tRb0kesKhVMEF_8rIQJUrfzRz-aHnlE25RhtjwY3BEZTHvmYp8_4iPxt-FclBwvwGlV27WmT-d2nATTq_o07bd5IkrxLcHIdNFwVUO0p_LmHVVoHJ238uqLH7XL2-PXrZ208f3qiNR4UevyCfodRy4oF9xw7mnHhpTTfsmtoPZ0DN5MxLJzaTVpEoYu7ysLF4qbbcxA3SaVR32Wi2rul_VqAlgpoQTXIp_4Xff664bka24cxoktcXC-H5ON0idh46N1-FBmyYqPrYaWy1IgHbvq84OYWb81bPojlqQbU12G2En25l1X-z-gC9fX_35Og_76IwrN-WCyr4_Z6-deNfsjolgOLj8Q9ujBguhIn7HOsdvqH6ULng5Jb7uF48oXa8NWuuPH7r-H5yltnHX9p4Iz_MpclcZv3obXdTHD-NDPxs8EgLGLqM3dQNY7TP9FE43MDvKSAaPQMF_2FYYMRWam13YRkMNuVYz82Q39KjjMI95ecIdf-I7XfmSxn8NCDoD3Y5X2_1-mRlRWX-sq_Kz9d9RhkxYCJOvp7ttHddHd1mV_oQtnijnsKoz_N4VZ6-HnuiPfvbtmITdk4Od88_2stBkaW-YwFY0zyGbXa-PDcLZcyPk68Ygz1_4ai_3IY15rOLOLMnWEu8sxI6yvPxvmP0o0zw3J9YjcSa1_kl7j-FRx_MIVcLS4Fc_ytgKHG7raiv18MMV7Yj9rzGce_eVHCFvWCNT-91ONyaGYw7KCa3-41WfXUeA4yUayAweISUzx8bMfex9dD_UG7vW13O5qL_PRRH4ZDYCgDRmHT9N7E88Rp3vpEhgpyJF7drh0BLJeS9P-3Z9ouPAbvyBrq8L4hmuOnWJA7QCW2Wb-kQ57DGjPWmz22sK9KCxg99BYQcfj5Tn80Dg7W8hJWgld2CQZxvw1w3ECrA-kSV2MsQ8sNJYM9MVbcrHpO-EsWiom9FVn_L5gPCzerw7WH9tUKHKZSd0xHq036l76oPpkNz_3qCKPGIOSpuCS-m3zm6DUBq9Nryo78ygPXlfhnS94Sb_4P6GBXdQILpw7h9va2BO_p0LD98jQ36Qvvy5PM8yLB3ZsS6iILntt4uX2z4FWJ7nfmD_hQj4Sw13FlYxmYEU1sHHRmSb2ln8NRUQLtz0MNxuju4_pHngjcumhuinqXNYlP7ij9Pwoc1PbnSlcnAbYcONBpA68zdNDG6Re781lb_3EK4O0aKmQlk5VJkg_SnY6I9waWO8-GvPNuluryzuq2zIxWqF_qqUn-ArqRUnd_aHppdeH_U9hGDT-C0rq4NP_5tJrtZwGe5LXEbCLYiDM2F6-WUV060gaFXUTvVIC0CvyD4Wo30t8JY4Fh0BRCb8xQkblnNbZ6B4QXrMtNqiCr4WKu5wzSbXmfcXn2F7F_nDIL8f3PMLfLi6u766uenf3rGLzcPV3Sq_vbm-us_ZHWPD4fK6318ub_Jlll0jX2UX4oH12U1_0L9n_f71gPVuhvkNy5d31_z6_n4wyJPrPhZcyJ7fy2uzvvDWf7ga9G_69xeSL1Faf2OOMYUfwTcordxMLswDTbpcVmubXPfJO-0ejRNO4sMsLqpWAxOmPsJNjS5gVpRGl7RjXfwFUeUw8TWk0OqiMvJh41zpncIHo7Vwm2rZy3SRsGm8POCZKI3-f8xcwqaeQ5uwaRRh-8D-HQAA___N_1-3">