llvm / Polygeist

C/C++ frontend for MLIR. Also features polyhedral optimizations, parallel optimizations, and more!
https://polygeist.llvm.org
Other
462 stars 105 forks source link

Support for overloading built-in operators #205

Open mortbopet opened 2 years ago

mortbopet commented 2 years ago

Hi! While Polygeist seems to have good support for structs, member functions and templating, I came across issues when trying to overload built-in operators.

A simple case is:

struct Pair {
  int first;
  int second;
  Pair operator+(Pair other) {
    return Pair{this->first + other.first, this->second + other.second};
  }
};
Pair timesTwo(Pair p) { return p + p; }

running: mlir-clang -v -S -function=* -scal-rep=0 --memref-fullrank ${file} produces:

CXXConstructExpr 0xeb86c20 'struct Pair' 'void (struct Pair &&) noexcept' elidable
`-MaterializeTemporaryExpr 0xeb86c08 'struct Pair' xvalue
  `-CXXOperatorCallExpr 0xeb86bd0 'struct Pair' '+'
    |-ImplicitCastExpr 0xeb86bb8 'struct Pair (*)(struct Pair)' <FunctionToPointerDecay>
    | `-DeclRefExpr 0xeb86b70 'struct Pair (struct Pair)' lvalue CXXMethod 0xeb682e8 'operator+' 'struct Pair (struct Pair)'
    |-DeclRefExpr 0xeb86980 'struct Pair' lvalue ParmVar 0xeb86800 'p' 'struct Pair'
    `-CXXConstructExpr 0xeb86b40 'struct Pair' 'void (const struct Pair &) noexcept'
      `-ImplicitCastExpr 0xeb869c0 'const struct Pair' lvalue <NoOp>
        `-DeclRefExpr 0xeb869a0 'struct Pair' lvalue ParmVar 0xeb86800 'p' 'struct Pair'
cleanup not handled
CXXConstructExpr 0xeb86780 'struct Pair' 'void (struct Pair &&) noexcept' elidable
`-MaterializeTemporaryExpr 0xeb68be8 'struct Pair' xvalue
  `-CXXFunctionalCastExpr 0xeb68758 'struct Pair' functional cast to struct Pair <NoOp>
    `-InitListExpr 0xeb685c8 'struct Pair'
      |-BinaryOperator 0xeb68478 'int' '+'
      | |-ImplicitCastExpr 0xeb68448 'int' <LValueToRValue>
      | | `-MemberExpr 0xeb683c8 'int' lvalue ->first 0xeb68130
      | |   `-CXXThisExpr 0xeb683b8 'struct Pair *' this
      | `-ImplicitCastExpr 0xeb68460 'int' <LValueToRValue>
      |   `-MemberExpr 0xeb68418 'int' lvalue .first 0xeb68130
      |     `-DeclRefExpr 0xeb683f8 'struct Pair' lvalue ParmVar 0xeb681f8 'other' 'struct Pair'
      `-BinaryOperator 0xeb68558 'int' '+'
        |-ImplicitCastExpr 0xeb68528 'int' <LValueToRValue>
        | `-MemberExpr 0xeb684a8 'int' lvalue ->second 0xeb68198
        |   `-CXXThisExpr 0xeb68498 'struct Pair *' this
        `-ImplicitCastExpr 0xeb68540 'int' <LValueToRValue>
          `-MemberExpr 0xeb684f8 'int' lvalue .second 0xeb68198
            `-DeclRefExpr 0xeb684d8 'struct Pair' lvalue ParmVar 0xeb681f8 'other' 'struct Pair'
cleanup not handled
wsmoses commented 2 years ago

Overloads should be supported, this feels like a default construction issue (incidentally which may have just been fixed by a very large bugfix and other merge): https://github.com/wsmoses/Polygeist/pull/204

Running your example on current main I see the following, which looks fine?:

wmoses@beast:~/git/Polygeist/build (m2r2) $ ./bin/mlir-clang --function=* 205.cpp -S
CXXConstructExpr 0x562dc391aa20 'struct Pair' 'void (struct Pair &&) noexcept' elidable
`-MaterializeTemporaryExpr 0x562dc391aa08 'struct Pair' xvalue
  `-CXXOperatorCallExpr 0x562dc391a9d0 'struct Pair' '+'
    |-ImplicitCastExpr 0x562dc391a9b8 'struct Pair (*)(struct Pair)' <FunctionToPointerDecay>
    | `-DeclRefExpr 0x562dc391a970 'struct Pair (struct Pair)' lvalue CXXMethod 0x562dc38fc1b8 'operator+' 'struct Pair (struct Pair)'
    |-DeclRefExpr 0x562dc391a780 'struct Pair' lvalue ParmVar 0x562dc391a600 'p' 'struct Pair'
    `-CXXConstructExpr 0x562dc391a940 'struct Pair' 'void (const struct Pair &) noexcept'
      `-ImplicitCastExpr 0x562dc391a7c0 'const struct Pair' lvalue <NoOp>
        `-DeclRefExpr 0x562dc391a7a0 'struct Pair' lvalue ParmVar 0x562dc391a600 'p' 'struct Pair'
cleanup not handled
CXXConstructExpr 0x562dc391a580 'struct Pair' 'void (struct Pair &&) noexcept' elidable
`-MaterializeTemporaryExpr 0x562dc38fcab8 'struct Pair' xvalue
  `-CXXFunctionalCastExpr 0x562dc38fc628 'struct Pair' functional cast to struct Pair <NoOp>
    `-InitListExpr 0x562dc38fc498 'struct Pair'
      |-BinaryOperator 0x562dc38fc348 'int' '+'
      | |-ImplicitCastExpr 0x562dc38fc318 'int' <LValueToRValue>
      | | `-MemberExpr 0x562dc38fc298 'int' lvalue ->first 0x562dc38fc000
      | |   `-CXXThisExpr 0x562dc38fc288 'struct Pair *' this
      | `-ImplicitCastExpr 0x562dc38fc330 'int' <LValueToRValue>
      |   `-MemberExpr 0x562dc38fc2e8 'int' lvalue .first 0x562dc38fc000
      |     `-DeclRefExpr 0x562dc38fc2c8 'struct Pair' lvalue ParmVar 0x562dc38fc0c8 'other' 'struct Pair'
      `-BinaryOperator 0x562dc38fc428 'int' '+'
        |-ImplicitCastExpr 0x562dc38fc3f8 'int' <LValueToRValue>
        | `-MemberExpr 0x562dc38fc378 'int' lvalue ->second 0x562dc38fc068
        |   `-CXXThisExpr 0x562dc38fc368 'struct Pair *' this
        `-ImplicitCastExpr 0x562dc38fc410 'int' <LValueToRValue>
          `-MemberExpr 0x562dc38fc3c8 'int' lvalue .second 0x562dc38fc068
            `-DeclRefExpr 0x562dc38fc3a8 'struct Pair' lvalue ParmVar 0x562dc38fc0c8 'other' 'struct Pair'
cleanup not handled
module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<"dlti.endianness", "little">, #dlti.dl_entry<i64, dense<64> : vector<2xi32>>, #dlti.dl_entry<f80, dense<128> : vector<2xi32>>, #dlti.dl_entry<i1, dense<8> : vector<2xi32>>, #dlti.dl_entry<i8, dense<8> : vector<2xi32>>, #dlti.dl_entry<i16, dense<16> : vector<2xi32>>, #dlti.dl_entry<i32, dense<32> : vector<2xi32>>, #dlti.dl_entry<f16, dense<16> : vector<2xi32>>, #dlti.dl_entry<f64, dense<64> : vector<2xi32>>, #dlti.dl_entry<f128, dense<128> : vector<2xi32>>>, llvm.data_layout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", llvm.target_triple = "x86_64-unknown-linux-gnu"} {
  func @_Z8timesTwo4Pair(%arg0: memref<?x2xi32>, %arg1: memref<?x2xi32>) attributes {llvm.linkage = #llvm.linkage<external>} {
    %0 = affine.load %arg0[0, 0] : memref<?x2xi32>
    %1 = affine.load %arg0[0, 1] : memref<?x2xi32>
    %2 = arith.addi %0, %0 : i32
    %3 = arith.addi %1, %1 : i32
    affine.store %2, %arg1[0, 0] : memref<?x2xi32>
    affine.store %3, %arg1[0, 1] : memref<?x2xi32>
    return
  }
  func @_ZN4PairC1EOS_(%arg0: memref<?x2xi32>, %arg1: memref<?x2xi32>) attributes {llvm.linkage = #llvm.linkage<linkonce_odr>} {
    %0 = affine.load %arg1[0, 0] : memref<?x2xi32>
    affine.store %0, %arg0[0, 0] : memref<?x2xi32>
    %1 = affine.load %arg1[0, 1] : memref<?x2xi32>
    affine.store %1, %arg0[0, 1] : memref<?x2xi32>
    return
  }
  func @_ZN4PairplES_(%arg0: memref<?x2xi32>, %arg1: memref<?x2xi32>, %arg2: memref<?x2xi32>) attributes {llvm.linkage = #llvm.linkage<linkonce_odr>} {
    %0 = affine.load %arg0[0, 0] : memref<?x2xi32>
    %1 = affine.load %arg1[0, 0] : memref<?x2xi32>
    %2 = arith.addi %0, %1 : i32
    %3 = affine.load %arg0[0, 1] : memref<?x2xi32>
    %4 = affine.load %arg1[0, 1] : memref<?x2xi32>
    %5 = arith.addi %3, %4 : i32
    affine.store %2, %arg2[0, 0] : memref<?x2xi32>
    affine.store %5, %arg2[0, 1] : memref<?x2xi32>
    return
  }
  func @_ZN4PairC1ERKS_(%arg0: memref<?x2xi32>, %arg1: memref<?x2xi32>) attributes {llvm.linkage = #llvm.linkage<linkonce_odr>} {
    %0 = affine.load %arg1[0, 0] : memref<?x2xi32>
    affine.store %0, %arg0[0, 0] : memref<?x2xi32>
    %1 = affine.load %arg1[0, 1] : memref<?x2xi32>
    affine.store %1, %arg0[0, 1] : memref<?x2xi32>
    return
  }
}

Can you try current main and let me know if you still have an error?

mortbopet commented 2 years ago

Sorry for the delay; pulling upstream changes, I still seem to run into the same error.