add _and, _or, store, select, etc.g

dev
MITSUNARI Shigeo 9 years ago
parent f4c17f6f82
commit 57b53cd1cd
  1. 195
      src/gen.cpp
  2. 96
      src/llvm_gen.hpp

@ -1,6 +1,9 @@
#include "llvm_gen.hpp"
#include <map>
struct OnceCode : public mcl::Generator {
typedef std::map<int, Function> FunctionMap;
Operand Void;
uint32_t unit;
uint32_t bit;
uint32_t N;
@ -9,6 +12,11 @@ struct OnceCode : public mcl::Generator {
Function extractHigh;
Function mulPos;
Function makeNIST_P192;
Function mcl_fpDbl_mod_NIST_P192;
FunctionMap mcl_fp_addNCM;
FunctionMap mcl_fp_subNCM;
FunctionMap mcl_fp_addM;
FunctionMap mcl_fp_subM;
void gen_mulUU()
{
@ -56,16 +64,23 @@ struct OnceCode : public mcl::Generator {
ret(xy);
endFunc();
}
Operand extract192to64(const Operand& x, uint32_t shift)
{
Operand y = lshr(x, shift);
y = trunc(y, 64);
return y;
}
void gen_makeNIST_P192()
{
resetGlobalIdx();
Operand p(Int, 192);
Operand p0(Int, 64);
Operand p1(Int, 64);
Operand p2(Int, 64);
Operand _0 = makeImm(64, 0);
Operand _1 = makeImm(64, 1);
Operand _2 = makeImm(64, 2);
makeNIST_P192 = Function("makeNIST_P192", Operand());
makeNIST_P192 = Function("makeNIST_P192", p);
beginFunc(makeNIST_P192);
p0 = sub(_0, _1);
p1 = sub(_0, _2);
@ -75,30 +90,188 @@ struct OnceCode : public mcl::Generator {
p2 = zext(p2, 192);
p1 = shl(p1, 64);
p2 = shl(p2, 128);
p0 = add(p0, p1);
p0 = add(p0, p2);
ret(p0);
p = add(p0, p1);
p = add(p, p2);
ret(p);
endFunc();
}
void run(uint32_t unit, uint32_t bit)
void gen_mcl_fpDbl_mod_NIST_P192()
{
resetGlobalIdx();
Operand out(IntPtr, 192);
Operand px(IntPtr, 192);
mcl_fpDbl_mod_NIST_P192 = Function("mcl_fpDbl_mod_NIST_P192", Void, out, px);
beginFunc(mcl_fpDbl_mod_NIST_P192);
Operand L = load(px);
L = zext(L, 256);
Operand pH = getelementptr(px, makeImm(32, 1));
Operand H192 = load(pH);
Operand H = zext(H192, 256);
Operand H10 = shl(H192, 64);
H10 = zext(H10, 256);
Operand H2 = extract192to64(H192, 128);
H2 = zext(H2, 256);
Operand H102 = _or(H10, H2);
H2 = shl(H2, 64);
Operand t = add(L, H);
t = add(t, H102);
t = add(t, H2);
Operand e = lshr(t, 192);
e = trunc(e, 64);
e = zext(e, 256);
Operand e2 = shl(e, 64);
e = _or(e, e2);
t = trunc(t, 192);
t = zext(t, 256);
Operand z = add(t, e);
Operand p = call(makeNIST_P192);
p = zext(p, 256);
Operand zp = sub(z, p);
Operand c = lshr(zp, 192);
c = trunc(c, 1);
z = select(c, z, zp);
z = trunc(z, 192);
store(z, out);
ret(Void);
endFunc();
}
void gen_once()
{
this->unit = unit;
this->bit = bit;
N = bit / unit;
unit2 = unit * 2;
gen_mulUU();
gen_extractHigh();
gen_mulPos();
gen_makeNIST_P192();
gen_mcl_fpDbl_mod_NIST_P192();
}
Operand extract(const Operand& x, uint32_t shift)
{
Operand t = lshr(x, shift);
t = trunc(t, unit);
return t;
}
void gen_mcl_fp_addsubNC(bool isAdd)
{
resetGlobalIdx();
Operand pz(IntPtr, bit);
Operand px(IntPtr, bit);
Operand py(IntPtr, bit);
std::string name;
if (isAdd) {
name = "mcl_fp_addNC" + cybozu::itoa(bit);
mcl_fp_addNCM[bit] = Function(name, Void, pz, px, py);
beginFunc(mcl_fp_addNCM[bit]);
} else {
name = "mcl_fp_subNC" + cybozu::itoa(bit);
mcl_fp_subNCM[bit] = Function(name, Void, pz, px, py);
beginFunc(mcl_fp_subNCM[bit]);
}
Operand x = load(px);
Operand y = load(py);
Operand z;
if (isAdd) {
add(x, y);
} else {
sub(x, y);
}
store(z, pz);
ret(Void);
endFunc();
}
void gen_mcl_fp_add()
{
resetGlobalIdx();
Operand pz(IntPtr, bit);
Operand px(IntPtr, bit);
Operand py(IntPtr, bit);
Operand pp(IntPtr, bit);
std::string name = "mcl_fp_add" + cybozu::itoa(bit);
mcl_fp_addM[bit] = Function(name, Void, pz, px, py, pp);
beginFunc(mcl_fp_addM[bit]);
Operand x = load(px);
Operand y = load(py);
Operand p = load(pp);
x = zext(x, bit + unit);
y = zext(y, bit + unit);
p = zext(p, bit + unit);
Operand t0 = add(x, y);
Operand t1 = sub(t0, p);
Operand t = lshr(t1, bit);
t = trunc(t, 1);
t = select(t, t0, t1);
t = trunc(t, bit);
store(t, pz);
ret(Void);
endFunc();
}
void gen_mcl_fp_sub()
{
resetGlobalIdx();
Operand pz(IntPtr, bit);
Operand px(IntPtr, bit);
Operand py(IntPtr, bit);
Operand pp(IntPtr, bit);
std::string name = "mcl_fp_sub" + cybozu::itoa(bit);
mcl_fp_subM[bit] = Function(name, Void, pz, px, py, pp);
beginFunc(mcl_fp_subM[bit]);
Operand x = load(px);
Operand y = load(py);
x = zext(x, bit + unit);
y = zext(y, bit + unit);
Operand vc = sub(x, y);
Operand v = trunc(vc, bit); // v = x - y
Operand c = lshr(vc, bit + unit - 1);
c = trunc(c, 1);
Operand p = load(pp);
Operand z = select(c, p, makeImm(bit, 0));
v = add(v, z);
store(v, pz);
ret(Void);
endFunc();
}
void gen_all()
{
gen_mcl_fp_addsubNC(true);
gen_mcl_fp_addsubNC(false);
}
void gen_short()
{
gen_mcl_fp_add();
gen_mcl_fp_sub();
}
void set(uint32_t unit, uint32_t bit)
{
this->unit = unit;
this->bit = bit;
N = bit / unit;
unit2 = unit * 2;
}
void gen()
{
set(64, 128);
gen_short();
gen_once();
for (int i = 128; i < 256; i += unit) {
set(64, i);
gen_all();
gen_short();
}
}
};
int main()
try
{
OnceCode c;
c.run(64, 256);
c.gen();
} catch (std::exception& e) {
printf("ERR %s\n", e.what());
return 1;

@ -6,6 +6,7 @@
@license modified new BSD license
http://opensource.org/licenses/BSD-3-Clause
*/
//#define CYBOZU_EXCEPTION_WITH_STACKTRACE
#include <string>
#include <vector>
#include <cybozu/exception.hpp>
@ -53,7 +54,7 @@ File Param<dummy>::f;
} // mcl::impl
struct Generator {
static const uint8_t Void = 0;
static const uint8_t None = 0;
static const uint8_t Int = 1;
static const uint8_t Imm = 2;
static const uint8_t Ptr = 1 << 7;
@ -81,17 +82,12 @@ struct Generator {
static inline int& getGlobalIdx()
{
static int globalIdx = 0;
return globalIdx;
return ++globalIdx;
}
static inline void resetGlobalIdx()
{
getGlobalIdx() = 0;
}
static inline std::string getGlobalName()
{
int& idx = getGlobalIdx();
return std::string("reg") + cybozu::itoa(idx++);
}
static inline void put(const std::string& str)
{
impl::Param<>::f.write(str);
@ -105,46 +101,53 @@ struct Generator {
Eval mul(const Operand& x, const Operand& y);
Eval add(const Operand& x, const Operand& y);
Eval sub(const Operand& x, const Operand& y);
Eval _and(const Operand& x, const Operand& y);
Eval _or(const Operand& x, const Operand& y);
void ret(const Operand& r);
Eval lshr(const Operand& x, uint32_t size);
Eval shl(const Operand& x, uint32_t size);
Eval trunc(const Operand& x, uint32_t size);
Eval getelementptr(const Operand& p, const Operand& i);
Eval load(const Operand& p);
void store(const Operand& r, const Operand& p);
Eval select(const Operand& c, const Operand& r1, const Operand& r2);
Eval call(const Function& f);
Eval call(const Function& f, const Operand& op1);
Eval call(const Function& f, const Operand& op1, const Operand& op2);
Eval call(const Function& f, const Operand& op1, const Operand& op2, const Operand& op3);
Eval call(const Function& f, const Operand& op1, const Operand& op2, const Operand& op3, const Operand& op4);
static inline Operand makeImm(uint32_t bit, uint64_t imm);
Operand makeImm(uint32_t bit, int64_t imm);
};
struct Generator::Operand {
Type type;
uint32_t bit;
uint64_t imm;
int64_t imm;
uint32_t idx;
std::string name;
Operand() : type(Void), bit(0), imm(0), idx(0) {}
Operand(Type type, uint32_t bit, const std::string& name = "")
: type(type), bit(bit), imm(0), idx(0), name(name)
Operand() : type(None), bit(0), imm(0), idx(0) {}
Operand(Type type, uint32_t bit)
: type(type), bit(bit), imm(0), idx(getGlobalIdx())
{
if (name.empty()) {
this->name = getGlobalName();
}
Operand(const Operand& rhs)
: type(rhs.type), bit(rhs.bit), imm(rhs.imm), idx(rhs.idx)
{
}
Operand(const Eval& e);
void operator=(const Eval& e);
// set (bit, type, imm) by rhs
void set(const Operand& rhs)
void operator=(const Operand& rhs)
{
bit = rhs.bit;
type = rhs.type;
bit = rhs.bit;
imm = rhs.imm;
idx = rhs.idx;
}
void update() { idx++; }
void update()
{
idx = getGlobalIdx();
}
Operand(const Eval& e);
void operator=(const Eval& e);
std::string toStr() const
{
if (type.isPtr) {
@ -180,19 +183,14 @@ struct Generator::Operand {
default:
return "";
case Int:
{
std::string str("%");
str += name;
if (idx > 0) str += "_" + cybozu::itoa(idx);
return str;
}
return std::string("%r") + cybozu::itoa(idx);
case Imm:
return cybozu::itoa(imm);
}
}
};
inline Generator::Operand Generator::makeImm(uint32_t bit, uint64_t imm)
inline Generator::Operand Generator::makeImm(uint32_t bit, int64_t imm)
{
Generator::Operand v(Generator::Imm, bit);
v.imm = imm;
@ -221,10 +219,7 @@ inline Generator::Operand::Operand(const Generator::Eval& e)
inline void Generator::Operand::operator=(const Generator::Eval& e)
{
type = e.op.type;
bit = e.op.bit;
imm = e.op.imm;
if (name.empty()) name = e.op.name;
*this = e.op;
update();
put(getName() + " = " + e.s);
e.used = true;
@ -310,7 +305,6 @@ inline Generator::Eval aluSub(const char *name, const Generator::Operand& x, con
Generator::Eval e;
e.op.type = Generator::Int;
e.op.bit = x.bit;
e.op.name = x.name;
e.s = name;
e.s += " ";
e.s += x.toStr() + ", " + y.getName();
@ -360,6 +354,16 @@ inline Generator::Eval Generator::sub(const Generator::Operand& x, const Generat
return impl::aluSub("sub", x, y);
}
inline Generator::Eval Generator::_and(const Generator::Operand& x, const Generator::Operand& y)
{
return impl::aluSub("and", x, y);
}
inline Generator::Eval Generator::_or(const Generator::Operand& x, const Generator::Operand& y)
{
return impl::aluSub("or", x, y);
}
inline void Generator::ret(const Generator::Operand& x)
{
std::string s = "ret " + x.toStr();
@ -406,6 +410,30 @@ inline Generator::Eval Generator::load(const Generator::Operand& p)
return e;
}
inline void Generator::store(const Generator::Operand& r, const Generator::Operand& p)
{
if (!p.type.isPtr) throw cybozu::Exception("Generator:store:not pointer") << p.type;
std::string s = "store ";
s += r.toStr();
s += ", ";
s += p.toStr();
put(s);
}
inline Generator::Eval Generator::select(const Generator::Operand& c, const Generator::Operand& r1, const Generator::Operand& r2)
{
if (c.bit != 1) throw cybozu::Exception("Generator:select:bad bit") << c.bit;
Eval e;
e.op = r1;
e.s = "select ";
e.s += c.toStr();
e.s += ", ";
e.s += r1.toStr();
e.s += ", ";
e.s += r2.toStr();
return e;
}
inline Generator::Eval Generator::call(const Generator::Function& f)
{
return impl::callSub(f, 0, 0);

Loading…
Cancel
Save