On Mon, Mar 23, 2020 at 09:09:31AM -0700, Yaxun Liu via cfe-commits wrote:
>
> Author: Yaxun (Sam) Liu
> Date: 2020-03-23T12:09:07-04:00
> New Revision: b670ab7b6b3d2f26179213be1da1d4ba376f50a3
>
> URL:
> https://github.com/llvm/llvm-project/commit/b670ab7b6b3d2f26179213be1da1d4ba376f50a3
> DIFF:
> https://github.com/llvm/llvm-project/commit/b670ab7b6b3d2f26179213be1da1d4ba376f50a3.diff
>
> LOG: recommit 1b978ddba05c [CUDA][HIP][OpenMP] Emit deferred diagnostics by a
> post-parsing AST travese
This change is responsible for a significant performance regression.
Somewhat reduced example is attached. With -fopenmp, it needs ~5s,
without 0.02s.
Joerg
;
;
namespace std {
inline namespace __1 {
template<class _CharT> struct char_traits;
template <class _CharT> class basic_ostream;
typedef basic_ostream<char> ostream;
template<class _Traits> basic_ostream<_Traits>&
operator<<(basic_ostream<_Traits>& __os, const char* __str) ;
extern ostream cerr;
}
;
}
template<typename T> class flet {
public: flet(T , const T ) ;
};
;
template<typename Manager> class _scoped_numeral {
typedef typename Manager::numeral numeral;
public: _scoped_numeral(Manager ) ;
operator numeral&() ;
};
template<typename T, bool CallDestructors, unsigned INITIAL_SIZE> class
buffer {
public: ;
unsigned size() const ;
;
;
T & operator[](unsigned idxT ) ;
};
template<typename T, unsigned INITIAL_SIZE> class buffer<T *, false,
INITIAL_SIZE> ;
template<typename T, unsigned INITIAL_SIZE=16> class sbuffer : public
buffer<T, false, INITIAL_SIZE> {
};
class mpz {
public: mpz(int v) ;
};
template<bool SYNCH > class mpz_manager {
public: ;
typedef mpz numeral;
void mul2k(mpz ,
unsigned k, mpz r) ;
};
typedef mpz_manager<false> unsynch_mpz_manager;
typedef _scoped_numeral<unsynch_mpz_manager> scoped_mpz;
class mpq {
};
template<bool SYNCH > class mpq_manager : public mpz_manager<SYNCH> {
public: typedef mpq numeral;
bool is_zero;
void mul( mpq b, mpq ) ;
void set(mpq
, mpq source) ;
};
typedef mpq_manager<false> unsynch_mpq_manager;
typedef _scoped_numeral<unsynch_mpq_manager> scoped_mpq;
;
template<typename C> class interval_manager {
public: ;
typedef typename C::interval interval;
bool is_P(interval n) const ;
void set(interval , interval s);
void neg(interval
a, interval );
void add(interval a, interval b, interval );
void
mul(interval a, interval b, interval );
};
template<typename Manager> class _scoped_interval {
typedef typename Manager::interval interval;
public: _scoped_interval(Manager ) ;
operator interval&() ;
};
namespace realclosure {
class num;
;
class manager {
struct imp;
typedef num numeral;
};
struct value;
class num {
friend class manager;
value * m_value;
};
};
template<typename T> class array {
public: ;
unsigned size() const ;
T operator[](unsigned idx) const ;
T const * c_ptr() const ;
};
template<typename T> class ptr_array : public array<T *> {
};
class mpbq {
public: mpbq(int v) ;
mpz numerator() const ;
unsigned k() const ;
};
class mpbq_manager {
public: ;
bool is_zero(mpbq a) const ;
};
class mpz_matrix {
};
class mpz_matrix_manager {
public: ;
void tensor_product(mpz_matrix , mpz_matrix C);
bool solve;
};
class scoped_mpz_matrix {
public: scoped_mpz_matrix(mpz_matrix_manager ) ;
unsigned n() ;
operator mpz_matrix &() ;
};
template<typename T, typename TManager> class obj_ref {
public: ;
obj_ref(TManager ) ;
T * operator->() const ;
;
operator T*() ;
obj_ref (T * n) ;
};
template<typename T, typename Ref> class ref_vector_core {
};
template<typename , typename TManager> class ref_manager_wrapper {
};
template<typename T, typename TManager> class ref_vector_core<T,
ref_manager_wrapper<T, TManager> > {
};
template<typename T, typename Ref, unsigned INITIAL_SIZE> class
ref_buffer_core {
public:
;
T ** c_ptr() const ;
unsigned size() const ;
bool empty() ;
void append(unsigned , T * const * elems) ;
};
template<typename T, typename TManager, unsigned INITIAL_SIZE> class
ref_buffer : public ref_buffer_core<T, ref_manager_wrapper<T, TManager>,
INITIAL_SIZE> {
public: ref_buffer(TManager ) ;
};
namespace realclosure {
struct mpbq_config {
struct numeral_manager : mpbq_manager {
};
typedef mpbq numeral;
struct interval {
numeral
lower() const ;
numeral upper() const ;
bool lower_is_inf() const ;
bool upper_is_inf() const ;
};
};
typedef interval_manager<mpbq_config> mpbqi_manager;
typedef mpbqi_manager::interval mpbqi;
struct value {
mpbqi & interval() ;
};
struct rational_value ;
typedef ptr_array<value> d;
struct extension;
struct rational_function_value : value {
d & num() ;
d den ;
extension * ext() const ;
};
struct extension {
enum kind {
TRANSCENDENTAL , INFINITESIMAL , ALGEBRAIC
};
kind knd() ;
mpbqi interval() ;
};
struct sign_det {
mpz_matrix M_s;
;
;
};
struct algebraic : extension {
d p() ;
sign_det * sdt() ;
unsigned sc_idx;
mpbqi iso_interval() ;
};
struct manager::imp {
typedef ref_buffer<value, imp, 32> value_ref_buffer;
typedef obj_ref<value, imp> value_ref;
typedef _scoped_interval<mpbqi_manager> scoped_mpbqi;
typedef sbuffer<int> int_buffer;
unsigned m_max_precision;
bool m_in_aux_values;
struct scoped_polynomial_seq {
scoped_polynomial_seq(imp ) ;
unsigned size() const ;
value * * coeffs(unsigned ) const ;
unsigned sizeconst ;
};
unsynch_mpq_manager & qm() ;
mpbq_config::numeral_manager bqm() ;
mpbqi_manager bqim() ;
mpz_matrix_manager & mm() ;
;
bool is_rational_one(value_ref_buffer ) ;
;
rational_function_value *
to_rational_function(value * ) ;
mpq to_mpq(value * ) ;
int compare_rank(value * a, value * ) ;
algebraic * to_algebraic(extension * ) ;
bool contains_zero(mpbqi
mpbqi ) ;
;
void set_interval(mpbqi , mpbqi ) ;
rational_function_value *
mk_rational_function_value_core(extension * , unsigned , value * const * ,
unsigned , value * const * ) ;
void count_signs_at_zeros_core(
int ,
unsigned , value * const * , unsigned ,
value * const * , mpbqi const ,
int , int
, int , int , value_ref_buffer ) ;
bool mk_sign_det_matrix(int , int , int , scoped_mpz_matrix ) ;
int sign(value * ) ;
void swap(mpbqi , mpbqi ) ;
mpbqi & interval(value * mpq ) ;
rational_value * mk_rational(mpz const ) ;
void add(unsigned ,
value * const * , unsigned , value * const * , value_ref_buffer
value_ref_buffer ) ;
void mul(value * , unsigned , value * const * ,
value_ref_buffer ) ;
void mul(unsigned , value * const * , unsigned , value * const * ,
value_ref_buffer ) ;
void div(unsigned , value * const * , unsigned ,
value * * , value_ref_buffer ) ;
void div(unsigned , value * const * , value * , value_ref_buffer ) ;
void rem(unsigned , value * const * , unsigned , value * const * ,
value_ref_buffer ) ;
void neg(unsigned , value * const * ,
value_ref_buffer ) ;
bool is_monic(d const
) ;
void gcd(unsigned , value * const * , unsigned , value *
const * , value_ref_buffer ) ;
void sturm_tarski_seq(unsigned , value * const * , unsigned , value *
const * , scoped_polynomial_seq ) ;
int eval_sign_at_zero ;
void eval_sign_at_approx(unsigned , value * const * , mpbq const ,
mpbqi ) ;
bool has_refineable_approx_coeffs(unsigned , value * const * ) ;
int expensive_eval_sign_at(unsigned n, value * const * p,
mpbq const b) {
scoped_mpz mpz_twok(qm());
qm().mul2k((1), b.k(), mpz_twok);
value_ref twok(*this), twok_i(*this);
;
value_ref c(*this);
value_ref r(*this), ak(*this), rc= p[1];
unsigned i ;
{ ; { mul(r,
c, r); mul(p[i], twok_i, ak); mul(r, c,
rc); add(ak, rc, r); }
mul(twok_i, twok, twok_i); }
return sign(r);
}
int find_biggest_interval_magnitude(unsigned n, value * const * ) {
int r ;
for (unsigned i ;
n;
) { mpbqi a_i ; ;
int m ; }
return r;
}
int eval_sign_at(unsigned n, value * const * p, mpbq const b) {
return 0;
;
{ scoped_mpbqi r(bqim()); ;
{ return bqim().is_P(r) ; }
if (has_refineable_approx_coeffs(n, p)) { return
expensive_eval_sign_at(n, p, b); int m ;
unsigned prec; ; {
; if (refine_coeffs_interval(n, p, prec)) {
expensive_eval_sign_at(n, p, b); }
eval_sign_at_approx(n, p, b, r);
{ return bqim().is_P(r) ; }
; } return
expensive_eval_sign_at(n, p, b); } }
}
enum location {
ZERO, MINUS_INF, PLUS_INF,
MPBQ };
unsigned sign_variations_at_core(scoped_polynomial_seq const seq,
location loc, mpbq const b) {
return 0;
unsigned prev_sign;
unsigned i ;
{ unsigned psz ; value * * p =
seq.coeffs(i); switch (loc) { ;
eval_sign_at(psz, p, b);
default: ; }
; }
;
}
unsigned sign_variations_at_minus_inf(scoped_polynomial_seq seq) {
mpbq dummy(0);
return sign_variations_at_core(seq, MINUS_INF, dummy);
}
unsigned sign_variations_at_plus_inf(scoped_polynomial_seq seq) {
mpbq dummy(0);
return sign_variations_at_core(seq, PLUS_INF, dummy);
}
unsigned sign_variations_at_zero(scoped_polynomial_seq seq) {
mpbq dummy(0);
return sign_variations_at_core(seq, ZERO, dummy);
}
unsigned sign_variations_at(scoped_polynomial_seq seq, mpbq const b) {
return sign_variations_at_core(seq, MPBQ, b);
}
int sign_variations_at_lower(scoped_polynomial_seq seq, mpbqi const
interval) {
return sign_variations_at_minus_inf(seq);
if (bqm().is_zero(interval.lower())) return
sign_variations_at_zero(seq);
return sign_variations_at(seq, interval.lower());
}
int sign_variations_at_upper(scoped_polynomial_seq seq, mpbqi const
interval) {
sign_variations_at_plus_inf(seq);
if (bqm().is_zero(interval.upper())) return
sign_variations_at_zero(seq);
return sign_variations_at(seq, interval.upper());
}
int TaQ(scoped_polynomial_seq seq, mpbqi const interval) {
return sign_variations_at_lower(seq, interval) -
sign_variations_at_upper(seq, interval);
}
int TaQ(unsigned p_sz, value * const * p, unsigned q_sz, value *
const * q, mpbqi const interval) {
scoped_polynomial_seq seq(*this);
sturm_tarski_seq(p_sz, p, q_sz, q, seq);
return TaQ(seq, interval);
}
bool refine_coeffs_interval(unsigned n, value *
const * p, unsigned prec) {
for (unsigned i ;
;
) { if (p&& refine_interval(p[i], prec))
return false; }
return true;
}
bool refine_coeffs_interval(d const p, unsigned prec) {
return (p.c_ptr());
}
void polynomial_interval(d const p, mpbqi const v, mpbqi r) {
;
{ bqim().set(r, interval(p[0]));
((void) (void) 0); bqim().mul(interval(p[1]), v, r);
unsigned i ; { ;
bqim().add(r, interval(p[i]), r); bqim().mul(r, v, r);
} }
}
bool refine_algebraic_interval(algebraic *
, unsigned ) ;
bool refine_algebraic_interval(rational_function_value * , unsigned )
;
bool refine_interval(value * , unsigned ) ;
;
;
bool depends_on_infinitesimals(d const , algebraic * ) ;
void refine_until_sign_determined(d const q, algebraic * x, mpbqi r) {
;
int m ;
unsigned prec;
{ ; if ((refine_coeffs_interval(q,
prec))) if ((refine_algebraic_interval(x, prec))) { ; ; }polynomial_interval(q,
x->interval(), r); ((void) (void) 0); if
(bqm().is_zero(r.upper())) prec++; }
}
bool expensive_algebraic_poly_interval(d q, algebraic * x, mpbqi r) {
{ if ((bqm().is_zero(r.lower()) ||
bqm().is_zero(r.upper()))) {
refine_until_sign_determined(q, x, r); } ;
}
int num_roots ;
d const p ;
int taq_p_q = TaQ(p.size(), p.c_ptr(), q.size(), q.c_ptr(),
x->iso_interval());
{ if (depends_on_infinitesimals(q, x))
refine_until_sign_determined(q, x, r); ;
; ; }
{ if (depends_on_infinitesimals(q, x))
refine_until_sign_determined(q, x, r); ;
int q_eq_0, q_gt_0, q_lt_0; value_ref_buffer q2(*this);
count_signs_at_zeros_core(taq_p_q, p.size(), p.c_ptr(), q.size(),
q.c_ptr(), x->iso_interval(), num_roots, q_eq_0, q_gt_0, q_lt_0, q2);
{ sign_det sdt = *(x->sdt());
scoped_mpz_matrix M(mm()); if ((mk_sign_det_matrix(q_eq_0,
q_gt_0, q_lt_0, M))) bool e ; scoped_mpz_matrix
new_M_s(mm()); mm(); array<d> const prs
; int_buffer new_taqrs;
value_ref_buffer prq(*this); for (unsigned i ; ; ) {
; mul(prs.size(), prs[i].c_ptr(),
q.size(), q.c_ptr(), prq); (TaQ(p.size(), p.c_ptr(),
prq.size(), prq.c_ptr(), x->iso_interval())); {
mul(prs.size(), prs[i].c_ptr(), q2.size(), q2.c_ptr(),
prq); (TaQ(p.size(), p.c_ptr(), prq.size(),
prq.c_ptr(), x->iso_interval())); }
} int_buffer sc_cardinalities;
(new_taqrs.size(), 0); { ; ; };
unsigned sc_idx ; { {
; ; ;
{ ;
; ; ;
; }
} { if
(sc_cardinalities[sc_idx] ) {} } }
} }
}
bool expensive_determine_algebraic_sign(rational_function_value * v) {
;
algebraic * x = to_algebraic(v->ext());
scoped_mpbqi num_interval(bqim());
;
if (expensive_algebraic_poly_interval(v->num(), x, num_interval))
((void) 0);
set_interval(v->interval(), num_interval);
return true;
}
bool determine_algebraic_sign(rational_function_value * v) {
;
mpbqi interval ;
{ return expensive_determine_algebraic_sign(v);
}
{ int m ; unsigned prec ;
; while (contains_zero(v->interval())) {
if (refine_algebraic_interval(v, prec))
expensive_determine_algebraic_sign(v); ;
expensive_determine_algebraic_sign(v); } ;
return true; }
}
bool determine_sign(rational_function_value * v) {
bool r;
switch (v->ext()->knd()) { case
extension::TRANSCENDENTAL: ; ; case extension::INFINITESIMAL: ; ; case
extension::ALGEBRAIC: determine_algebraic_sign(v); __builtin_unreachable();
; }
;
}
bool determine_sign(value_ref r) {
;
return determine_sign(to_rational_function(r));
}
void normalize_fraction(unsigned sz1, value * * p1, unsigned sz2,
value * const * p2, value_ref_buffer new_p1, value_ref_buffer new_p2) {
;
{ div(sz1, p1, p2[0], new_p1); ; ;
value * lc ; {
normalize_num_monic_den(sz1, p1, sz2, p2, new_p1, new_p2);
value_ref_buffer tmp1(*this); value_ref_buffer tmp2(*this);
; div(sz2, p2, lc, tmp2);
normalize_num_monic_den(tmp1.size(), tmp1.c_ptr(), tmp2.size(),
tmp2.c_ptr(), new_p1, new_p2); } }
;
}
void normalize_num_monic_den(unsigned sz1, value * * p1, unsigned
sz2, value * const * p2, value_ref_buffer
new_p1, value_ref_buffer new_p2) {
value_ref_buffer g(*this);
gcd(sz1, p1, sz2, p2, g);
;
if (is_rational_one(g)) { ;
new_p2.append(sz2, p2); div(sz1, p1, g.size(), g.c_ptr(), new_p1);
div(sz2, p2, g.size(), g.c_ptr(), new_p2); ;
}
}
void normalize_algebraic(algebraic * x, unsigned sz1, value * * p1,
value_ref_buffer new_p1) {
d const p ;
{ rem(sz1, p1, p.size(), p.c_ptr(), new_p1);
; }
}
void mk_add_value(rational_function_value * a, value * b, unsigned
num_sz, value * * num, unsigned den_sz, value * const * den, value_ref r) {
;
{ ; ; scoped_mpbqi
ri(bqim()); bqim().add(interval(a), interval(b), ri);
mk_rational_function_value_core(a->ext(), num_sz, num, den_sz, den);
swap(r->interval(), ri); determine_sign(r);
{ ; }
}
}
void add_p_v(rational_function_value * a, value * b, value_ref r) {
;
;
d const one ;
;
value_ref_buffer new_num(*this);
;
mk_add_value(a, b, new_num.size(), new_num.c_ptr(), one.size(),
one.c_ptr(), r);
}
void add_rf_v(rational_function_value * a, value * b, value_ref r) {
value_ref_buffer b_ad(*this);
value_ref_buffer num(*this);
d an ;
{ add_p_v(a, b, r); ;
d const ad ; mul(b, ad.size(), ad.c_ptr(), b_ad);
add(an.size(), an.c_ptr(), b_ad.size(), b_ad.c_ptr(), num);
if (num.empty()) { value_ref_buffer
new_num(*this); value_ref_buffer new_den(*this);
normalize_fraction(num.size(), num.c_ptr(), ad.size(), ad.c_ptr(),
new_num, new_den); ; mk_add_value(a, b,
new_num.size(), new_num.c_ptr(), new_den.size(), new_den.c_ptr(), r);
} }
}
void add_p_p(rational_function_value * a, rational_function_value *
b, value_ref r) {
;
d an ;
d const one ;
d bn ;
value_ref_buffer new_num(*this);
add(an.size(), an.c_ptr(), bn.size(), bn.c_ptr(), new_num);
if (new_num.empty()) {
mk_add_value(a, b, new_num.size(), new_num.c_ptr(), one.size(), one.c_ptr(),
r); }
}
void add_rf_rf(rational_function_value * a, rational_function_value *
b, value_ref r) {
;
d an ;
d bn ;
{ add_p_p(a, b, r); ;
d const ad ; d const bd ; value_ref_buffer
an_bd(*this); value_ref_buffer bn_ad(*this);
mul(an.size(), an.c_ptr(), bd.size(), bd.c_ptr(), an_bd);
mul(bn.size(), bn.c_ptr(), ad.size(), ad.c_ptr(), bn_ad);
value_ref_buffer num(*this); add(0, an_bd.c_ptr(),
bn_ad.size(), bn_ad.c_ptr(), num); if (num.empty()) {
; value_ref_buffer den(*this);
mul(ad.size(), ad.c_ptr(), bd.size(), bd.c_ptr(), den);
value_ref_buffer new_num(*this); value_ref_buffer
new_den(*this); realclosure::value **__trans_tmp_1 =
num.c_ptr();
normalize_fraction(num.size(), __trans_tmp_1, den.size(),
den.c_ptr(), new_num, new_den); ;
mk_add_value(a, b, new_num.size(), new_num.c_ptr(), new_den.size(),
new_den.c_ptr(), r); } }
}
void add(value * a, value * b, value_ref r) {
{ ; }
{ ; ((void) (void) 0);
{ add_rf_v(to_rational_function(b), a, r);
add_rf_rf(to_rational_function(a), to_rational_function(b), r);
add_rf_v(to_rational_function(a), b, r); ; } }
}
void sub(value * a, value * b, value_ref r) {
{ ; value_ref neg_b(*this);
; switch (compare_rank(a, neg_b)) {
add_rf_v(to_rational_function(neg_b), a, r); add_rf_rf(to_rational_function(a),
to_rational_function(neg_b), r); add_rf_v(to_rational_function(a), neg_b, r); ;
} }
}
void neg_rf(rational_function_value * a, value_ref r) {
d an ;
d const ad ;
value_ref_buffer new_num(*this);
neg(an.size(), an.c_ptr(), new_num);
scoped_mpbqi ri(bqim());
bqim().neg(interval(a), ri);
mk_rational_function_value_core(a->ext(), new_num.size(),
new_num.c_ptr(), ad.size(), ad.c_ptr());
swap(r->interval(), ri);
}
void neg(value * a, value_ref r) {
;
{ scoped_mpq v(qm()); qm().set(v,
to_mpq(a)); qm(); ;
neg_rf(to_rational_function(a), r); }
}
void mk_mul_value(rational_function_value * a, value * b, unsigned
num_sz, value * * num, unsigned den_sz, value * const * den, value_ref r) {
;
{ ; ; scoped_mpbqi
ri(bqim()); bqim().mul(interval(a), interval(b), ri);
mk_rational_function_value_core(a->ext(), num_sz, num, den_sz, den);
swap(ri, r->interval()); if (determine_sign(r)) {
; ; } }
}
void mul_p_v(rational_function_value * a, value * b, value_ref r) {
;
d const one ;
value_ref_buffer new_num(*this);
mk_mul_value(a, b, new_num.size(), new_num.c_ptr(), one.size(),
one.c_ptr(), r);
}
void mul_rf_v(rational_function_value * a, value * b, value_ref r) {
d an ;
{ mul_p_v(a, b, r); ;
d const ad ; value_ref_buffer num(*this);
mul(b, an.size(), an.c_ptr(), num); ;
value_ref_buffer new_num(*this); value_ref_buffer
new_den(*this); normalize_fraction(num.size(), num.c_ptr(),
ad.size(), ad.c_ptr(), new_num, new_den); ;
mk_mul_value(a, b, new_num.size(), new_num.c_ptr(), new_den.size(),
new_den.c_ptr(), r); }
}
void mul_p_p(rational_function_value * a, rational_function_value *
b, value_ref r) {
;
d const one ;
value_ref_buffer new_num(*this);
extension * x ;
if (x) { value_ref_buffer new_num2(*this);
normalize_algebraic(to_algebraic(x), new_num.size(), new_num.c_ptr(),
new_num2); ; unsigned int __trans_tmp_2 =
new_num2.size();
mk_mul_value(a, b, __trans_tmp_2, new_num2.c_ptr(), one.size(),
one.c_ptr(), r); mk_mul_value(a, b, new_num.size(),
new_num.c_ptr(), one.size(), one.c_ptr(), r); }
}
void mul_rf_rf(rational_function_value * a, rational_function_value *
b, value_ref r) {
d an = a->num();
d bn ;
{ mul_p_p(a, b, r); ;
d const ad ; d const bd ; value_ref_buffer
num(*this); value_ref_buffer den(*this);
mul(an.size(), an.c_ptr(), bn.size(), bn.c_ptr(), num);
mul(ad.size(), ad.c_ptr(), bd.size(), bd.c_ptr(), den);
value_ref_buffer new_num(*this); value_ref_buffer
new_den(*this); normalize_fraction(num.size(), num.c_ptr(), 0,
den.c_ptr(), new_num, new_den); ;
mk_mul_value(a, b, new_num.size(), new_num.c_ptr(), new_den.size(),
new_den.c_ptr(), r); }
}
void mul(value * a, value * b, value_ref r) {
{ ; }
{ neg(b, r); }
{ neg(a, r); }
{ scoped_mpq v(qm()); qm().mul(
to_mpq(b), v); ; ((void) (void) 0);
switch (compare_rank(a, b)) { mul_rf_v(to_rational_function(b),
a, r); mul_rf_rf(to_rational_function(a), to_rational_function(b), r);
mul_rf_v(to_rational_function(a), b, r); ; } }
}
void set(numeral , value_ref ) ;
void add(numeral a, numeral b, numeral c) {
value_ref r(*this);
add(a.m_value, b.m_value, r);
set(c, r);
}
void sub(numeral a, numeral b) {
value_ref r(*this);
sub(a.m_value, b.m_value, r);
}
};
}
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits