JuliaHubOSS / llvm-cbe

resurrected LLVM "C Backend", with improvements
Other
826 stars 141 forks source link

llvm-cbe complains intrinsic function `llvm.is.constant.i64` not support #102

Closed hzhangxyz closed 7 months ago

hzhangxyz commented 3 years ago

The source is compiled to bc via clang-11.1.0

And I build llvm-cbe with system llvm(of course 11.1.0)

llvm-cbe xxx.bc output the following

LLVM ERROR: Code generator does not support intrinsic function 'llvm.is.constant.i64'!
 #0 0x00007f145db9c0db llvm::sys::PrintStackTrace(llvm::raw_ostream&) (/usr/lib/libLLVM-11.so+0xa760db)
 #1 0x00007f145db99e14 llvm::sys::RunSignalHandlers() (/usr/lib/libLLVM-11.so+0xa73e14)
 #2 0x00007f145db99f61 (/usr/lib/libLLVM-11.so+0xa73f61)
 #3 0x00007f145cd9ef80 __restore_rt (/usr/lib/libc.so.6+0x3cf80)
 #4 0x00007f145cd9eef5 raise (/usr/lib/libc.so.6+0x3cef5)
 #5 0x00007f145cd88862 abort (/usr/lib/libc.so.6+0x26862)
 #6 0x00007f145dabfeb4 llvm::report_fatal_error(llvm::Twine const&, bool) (/usr/lib/libLLVM-11.so+0x999eb4)
 #7 0x00007f145de70e39 llvm::IntrinsicLowering::LowerIntrinsicCall(llvm::CallInst*) (/usr/lib/libLLVM-11.so+0xd4ae39)
 #8 0x0000562e79c7bf3a (/usr/bin/llvm-cbe+0x16f3a)
 #9 0x0000562e79c92225 (/usr/bin/llvm-cbe+0x2d225)
#10 0x00007f145dce9a60 llvm::FPPassManager::runOnFunction(llvm::Function&) (/usr/lib/libLLVM-11.so+0xbc3a60)
#11 0x00007f145dceb03d llvm::FPPassManager::runOnModule(llvm::Module&) (/usr/lib/libLLVM-11.so+0xbc503d)
#12 0x00007f145dce8b20 llvm::legacy::PassManagerImpl::run(llvm::Module&) (/usr/lib/libLLVM-11.so+0xbc2b20)
#13 0x0000562e79c75d5f (/usr/bin/llvm-cbe+0x10d5f)
#14 0x0000562e79c74421 (/usr/bin/llvm-cbe+0xf421)
#15 0x00007f145cd89b25 __libc_start_main (/usr/lib/libc.so.6+0x27b25)
#16 0x0000562e79c7451e (/usr/bin/llvm-cbe+0xf51e)
PLEASE submit a bug report to https://bugs.llvm.org/ and include the crash backtrace.
Stack dump:
0.      Program arguments: llvm-cbe test_contract.bc
1.      Running pass 'Function Pass Manager' on module 'test_contract.bc'.
2.      Running pass 'C backend' on function '@_ZNSt11char_traitsIcE7compareEPKcS2_m'
[1]    1603923 abort (core dumped)  llvm-cbe test_contract.bc
hikari-no-yume commented 3 years ago

Presumably this means that LLVM-CBE needs to implement this intrinsic itself.

From looking at the description of llvm.is.constant in the LLVM Language Reference, I think we can just replace it with false? I wonder if “It is guaranteed to fold to either true or false before generating machine code.” means we shouldn't be encountering the intrinsic, though.

@hzhangxyz Can you provide the original program that triggered the problem?

vtjnash commented 3 years ago

Yes, false should be correct, or it could lower to the gcc function __builtin_constant_p, but define that to false elsewhere.

hzhangxyz commented 3 years ago

Hello, This is a small example to reproduce this issue:

#include <algorithm>

struct NoSymmetry {
   bool operator==(NoSymmetry) {
      return true;
   }
   NoSymmetry operator+=(NoSymmetry) {
      return *this;
   }
};

template<typename Symmetry>
struct Edge {
   static constexpr bool conjugated = false;

   using symmetry_t = Symmetry;
   using map_t = std::vector<std::pair<Symmetry, int>>;

   map_t map;

   Edge(const int dimension) : map({{Symmetry(), dimension}}) {}
};

template<bool check_conjugated = false, typename Edges>
[[nodiscard]] auto initialize_block_symmetries_with_check(const Edges& edges) {
   using Edge = typename Edges::value_type;
   using Symmetry = typename Edge::symmetry_t;
   int rank = edges.size();
   using ResultItem = std::pair<std::vector<Symmetry>, int>;
   auto result = std::vector<ResultItem>();
   auto symmetries = std::vector<Symmetry>(rank);
   auto sizes = std::vector<int>(rank);
   if (rank == 0) {
      result.emplace_back(std::piecewise_construct, std::tuple{}, std::tuple{1});
      return result;
   }
   using Iterator = typename Edge::map_t::const_iterator;
   auto symmetry_iterator_list = std::vector<Iterator>();
   symmetry_iterator_list.reserve(rank);
   for (auto i = 0; i != rank; ++i) {
      const auto& map = edges[i].map;
      if (edges[i].map.empty()) {
         return result;
      }
      symmetry_iterator_list.push_back((check_conjugated && edges[i].conjugated) ? std::prev(map.end()) : map.begin());
   }
   int minimum_changed = 0;
   while (true) {
      {
         auto symmetry_summary = Symmetry();
         for (const auto& symmetry_iterator : symmetry_iterator_list) {
            symmetry_summary += symmetry_iterator->first;
         }
         if (symmetry_summary == Symmetry()) {
            for (auto i = minimum_changed; i < rank; i++) {
               symmetries[i] = symmetry_iterator_list[i]->first;
               sizes[i] = symmetry_iterator_list[i]->second * (i ? sizes[i - 1] : 1);
            }
            result.emplace_back(std::piecewise_construct, std::tuple{symmetries.begin(), symmetries.end()}, std::tuple{sizes.back()});
            minimum_changed = rank;
         }
      }
      auto edge_position = rank - 1;

      while ((check_conjugated && edges[edge_position].conjugated) ? symmetry_iterator_list[edge_position]-- == edges[edge_position].map.begin() :
                                                                     ++symmetry_iterator_list[edge_position] == edges[edge_position].map.end()) {
         if (edge_position == 0) {
            return result;
         }
         symmetry_iterator_list[edge_position] =
               (check_conjugated && edges[edge_position].conjugated) ? std::prev(edges[edge_position].map.end()) : edges[edge_position].map.begin();
         --edge_position;
      }
      minimum_changed = minimum_changed < edge_position ? minimum_changed : edge_position;
   }
}

int main() {
   using E = Edge<NoSymmetry>;
   auto edges = std::vector<E>{2, 3};
   auto r = initialize_block_symmetries_with_check(edges);
}

I compile with

clang++ test.cpp -std=c++17 -S -emit-llvm
llvm-cbe test.ll

Then the error reported.

My clang version is 11.1.0, llvm-cbe is build from current master (139e254)