Discussion:
vex: r3351 - in /branches/VEX_JIT_HACKS: priv/host_generic_reg_alloc2.c priv/host_generic_regs.c priv/host_generic_regs.h priv/host_x86_defs.c priv/host_x86_defs.h priv/host_x86_isel.c priv/ir_defs.c priv/main_main.c pub/libvex_ir.h
Add Reply
s***@valgrind.org
2017-04-19 21:21:22 UTC
Reply
Permalink
Raw Message
Author: iraisr
Date: Wed Apr 19 22:21:22 2017
New Revision: 3351

Log:
Add support for HInstrIfThenElse into x86 instruction selector backend.
Now on to register allocator...

Modified:
branches/VEX_JIT_HACKS/priv/host_generic_reg_alloc2.c
branches/VEX_JIT_HACKS/priv/host_generic_regs.c
branches/VEX_JIT_HACKS/priv/host_generic_regs.h
branches/VEX_JIT_HACKS/priv/host_x86_defs.c
branches/VEX_JIT_HACKS/priv/host_x86_defs.h
branches/VEX_JIT_HACKS/priv/host_x86_isel.c
branches/VEX_JIT_HACKS/priv/ir_defs.c
branches/VEX_JIT_HACKS/priv/main_main.c
branches/VEX_JIT_HACKS/pub/libvex_ir.h

Modified: branches/VEX_JIT_HACKS/priv/host_generic_reg_alloc2.c
==============================================================================
--- branches/VEX_JIT_HACKS/priv/host_generic_reg_alloc2.c (original)
+++ branches/VEX_JIT_HACKS/priv/host_generic_reg_alloc2.c Wed Apr 19 22:21:22 2017
@@ -410,6 +410,7 @@

/* For debug printing only. */
void (*ppInstr)(const HInstr*, Bool);
+ void (*ppCondCode)(HCondCode);
void (*ppReg)(HReg);

/* 32/64bit mode */
@@ -428,8 +429,8 @@
void (*genReload)( HInstr**, HInstr**, HReg, Int, Bool),
HInstr* (*directReload)( HInstr*, HReg, Short),
UInt guest_sizeB,
- void (*ppInstr)(const HInstr*, Bool), void (*ppReg)(HReg),
- Bool mode64, const HInstrVec* instrs_in, UInt n_vregs)
+ void (*ppInstr)(const HInstr*, Bool), void (*ppCondCode)(HCondCode),
+ void (*ppReg)(HReg), Bool mode64, const HInstrVec* instrs_in, UInt n_vregs)
{
/* Initialize Register Allocator state. */
state->univ = univ;
@@ -442,6 +443,7 @@
state->directReload = directReload;
state->guest_sizeB = guest_sizeB;
state->ppInstr = ppInstr;
+ state->ppCondCode = ppCondCode;
state->ppReg = ppReg;
state->mode64 = mode64;

@@ -595,7 +597,7 @@
const HInstr* instr = instrs_in->insns[ii];

if (state->isIfThenElse(instr) != NULL) {
- vpanic("IfThenElse unimplemented");
+ vpanic("regAlloc_HInstrVec: IfThenElse unimplemented");
}

state->getRegUsage(&state->reg_usage_arr[ii], instr, state->mode64);
@@ -1689,6 +1691,7 @@

/* For debug printing only. */
void (*ppInstr) ( const HInstr*, Bool ),
+ void (*ppCondCode)(HCondCode),
void (*ppReg) ( HReg ),

/* 32/64bit mode */
@@ -1704,7 +1707,7 @@
RegAllocState state;
initRegAllocState(&state, univ, isMove, getRegUsage, mapRegs, isIfThenElse,
genSpill, genReload, directReload, guest_sizeB, ppInstr,
- ppReg, mode64, sb_in->insns, sb_in->n_vregs);
+ ppCondCode, ppReg, mode64, sb_in->insns, sb_in->n_vregs);
sb_out->insns = regAlloc_HInstrVec(&state, sb_in->insns);
return sb_out;
}

Modified: branches/VEX_JIT_HACKS/priv/host_generic_regs.c
==============================================================================
--- branches/VEX_JIT_HACKS/priv/host_generic_regs.c (original)
+++ branches/VEX_JIT_HACKS/priv/host_generic_regs.c Wed Apr 19 22:21:22 2017
@@ -304,25 +304,63 @@
addHInstr(hv, instr);
}

+HInstrIfThenElse* newHInstrIfThenElse(HCondCode condCode, HPhiNode* phi_nodes,
+ UInt n_phis)
+{
+ HInstrIfThenElse* hite = LibVEX_Alloc_inline(sizeof(HInstrIfThenElse));
+ hite->ccOOL = condCode;
+ hite->fallThrough = newHInstrVec();
+ hite->outOfLine = newHInstrVec();
+ hite->phi_nodes = phi_nodes;
+ hite->n_phis = n_phis;
+ return hite;
+}
+
static void print_depth(UInt depth) {
for (UInt i = 0; i < depth; i++) {
vex_printf(" ");
}
}

+void ppHPhiNode(const HPhiNode* phi_node)
+{
+ ppHReg(phi_node->dst);
+ vex_printf(" = phi(");
+ ppHReg(phi_node->srcFallThrough);
+ vex_printf(",");
+ ppHReg(phi_node->srcOutOfLine);
+ vex_printf(")");
+}
+
static void ppHInstrVec(const HInstrVec* code,
HInstrIfThenElse* (*isIfThenElse)(const HInstr*),
void (*ppInstr)(const HInstr*, Bool),
+ void (*ppCondCode)(HCondCode),
Bool mode64, UInt depth, UInt *insn_num)
{
for (UInt i = 0; i < code->insns_used; i++) {
const HInstr* instr = code->insns[i];
const HInstrIfThenElse* hite = isIfThenElse(instr);
if (UNLIKELY(hite != NULL)) {
- ppHInstrVec(hite->fallThrough, isIfThenElse, ppInstr, mode64,
- depth + 1, insn_num);
- ppHInstrVec(hite->outOfLine, isIfThenElse, ppInstr, mode64,
- depth + 1, insn_num);
+ print_depth(depth);
+ vex_printf(" if (!");
+ ppCondCode(hite->ccOOL);
+ vex_printf(") then fall-through {\n");
+ ppHInstrVec(hite->fallThrough, isIfThenElse, ppInstr, ppCondCode,
+ mode64, depth + 1, insn_num);
+ print_depth(depth);
+ vex_printf(" } else out-of-line {\n");
+ ppHInstrVec(hite->outOfLine, isIfThenElse, ppInstr, ppCondCode,
+ mode64, depth + 1, insn_num);
+ print_depth(depth);
+ vex_printf(" }\n");
+
+ for (UInt j = 0; j < hite->n_phis; j++) {
+ print_depth(depth);
+ vex_printf(" ");
+ ppHPhiNode(&hite->phi_nodes[j]);
+ vex_printf("\n");
+ }
} else {
vex_printf("%3u ", (*insn_num)++);
print_depth(depth);
@@ -342,10 +380,12 @@

void ppHInstrSB(const HInstrSB* code,
HInstrIfThenElse* (*isIfThenElse)(const HInstr*),
- void (*ppInstr)(const HInstr*, Bool), Bool mode64)
+ void (*ppInstr)(const HInstr*, Bool),
+ void (*ppCondCode)(HCondCode), Bool mode64)
{
UInt insn_num = 0;
- ppHInstrVec(code->insns, isIfThenElse, ppInstr, mode64, 0, &insn_num);
+ ppHInstrVec(code->insns, isIfThenElse, ppInstr, ppCondCode, mode64, 0,
+ &insn_num);
}



Modified: branches/VEX_JIT_HACKS/priv/host_generic_regs.h
==============================================================================
--- branches/VEX_JIT_HACKS/priv/host_generic_regs.h (original)
+++ branches/VEX_JIT_HACKS/priv/host_generic_regs.h Wed Apr 19 22:21:22 2017
@@ -368,18 +368,37 @@
}
}

+/* Host-independent condition code. Stands for X86CondCode, ARM64CondCode... */
+typedef UInt HCondCode;
+
+
+/* Phi node expressed in terms of HReg's. Analogy to IRPhi. */
+typedef
+ struct {
+ HReg dst;
+ HReg srcFallThrough;
+ HReg srcOutOfLine;
+ }
+ HPhiNode;
+
+extern void ppHPhiNode(const HPhiNode* phi_node);
+

/* Represents two alternative code paths:
- - one more likely taken (hot path)
- - one not so likely taken (cold path) */
+ - One more likely taken (hot path)
+ - One not so likely taken (cold path) */
typedef
struct {
- // HCondCode ccOOL; // TODO-JIT: condition code for the OOL branch
+ HCondCode ccOOL; // condition code for the OOL branch
HInstrVec* fallThrough; // generated from the likely-taken IR
HInstrVec* outOfLine; // generated from likely-not-taken IR
+ HPhiNode* phi_nodes;
+ UInt n_phis;
}
HInstrIfThenElse;

+extern HInstrIfThenElse* newHInstrIfThenElse(HCondCode, HPhiNode* phi_nodes,
+ UInt n_phis);

/* Code block of HInstr's.
n_vregs indicates the number of virtual registers mentioned in the code,
@@ -395,7 +414,8 @@
extern HInstrSB* newHInstrSB(void);
extern void ppHInstrSB(const HInstrSB* code,
HInstrIfThenElse* (*isIfThenElse)(const HInstr*),
- void (*ppInstr)(const HInstr*, Bool), Bool mode64);
+ void (*ppInstr)(const HInstr*, Bool),
+ void (*ppCondCode)(HCondCode), Bool mode64);


/*---------------------------------------------------------*/
@@ -500,6 +520,7 @@

/* For debug printing only. */
void (*ppInstr) ( const HInstr*, Bool ),
+ void (*ppCondCode)(HCondCode),
void (*ppReg) ( HReg ),

/* 32/64bit mode */

Modified: branches/VEX_JIT_HACKS/priv/host_x86_defs.c
==============================================================================
--- branches/VEX_JIT_HACKS/priv/host_x86_defs.c (original)
+++ branches/VEX_JIT_HACKS/priv/host_x86_defs.c Wed Apr 19 22:21:22 2017
@@ -922,6 +922,13 @@
i->tag = Xin_ProfInc;
return i;
}
+X86Instr* X86Instr_IfThenElse(HInstrIfThenElse* hite)
+{
+ X86Instr* i = LibVEX_Alloc_inline(sizeof(X86Instr));
+ i->tag = Xin_IfThenElse;
+ i->Xin.IfThenElse.hite = hite;
+ return i;
+}

void ppX86Instr ( const X86Instr* i, Bool mode64 ) {
vassert(mode64 == False);
@@ -1212,11 +1219,20 @@
vex_printf("(profInc) addl $1,NotKnownYet; "
"adcl $0,NotKnownYet+4");
return;
+ case Xin_IfThenElse:
+ vex_printf("if (!%s) then {...",
+ showX86CondCode(i->Xin.IfThenElse.hite->ccOOL));
+ return;
default:
vpanic("ppX86Instr");
}
}

+void ppX86CondCode(X86CondCode condCode)
+{
+ vex_printf("%s", showX86CondCode(condCode));
+}
+
/* --------- Helpers for register allocation. --------- */

void getRegUsage_X86Instr (HRegUsage* u, const X86Instr* i, Bool mode64)

Modified: branches/VEX_JIT_HACKS/priv/host_x86_defs.h
==============================================================================
--- branches/VEX_JIT_HACKS/priv/host_x86_defs.h (original)
+++ branches/VEX_JIT_HACKS/priv/host_x86_defs.h Wed Apr 19 22:21:22 2017
@@ -712,9 +712,11 @@
extern X86Instr* X86Instr_EvCheck ( X86AMode* amCounter,
X86AMode* amFailAddr );
extern X86Instr* X86Instr_ProfInc ( void );
+extern X86Instr* X86Instr_IfThenElse(HInstrIfThenElse*);


extern void ppX86Instr ( const X86Instr*, Bool );
+extern void ppX86CondCode(X86CondCode);

/* Some functions that insulate the register allocator from details
of the underlying instruction set. */

Modified: branches/VEX_JIT_HACKS/priv/host_x86_isel.c
==============================================================================
--- branches/VEX_JIT_HACKS/priv/host_x86_isel.c (original)
+++ branches/VEX_JIT_HACKS/priv/host_x86_isel.c Wed Apr 19 22:21:22 2017
@@ -124,6 +124,19 @@
// && e->Iex.Const.con->Ico.U64 == 0ULL;
//}

+static void print_depth(UInt depth)
+{
+ for (UInt i = 0; i < depth; i++) {
+ vex_printf(" ");
+ }
+}
+
+static void print_IRStmt_prefix(UInt depth)
+{
+ vex_printf("\n");
+ print_depth(depth);
+ vex_printf("-- ");
+}

/*---------------------------------------------------------*/
/*--- ISelEnv ---*/
@@ -147,7 +160,8 @@
32-bit virtual HReg, which holds the high half
of the value.

- - The code array, that is, the insns selected so far.
+ - The code vector, that is, the insns selected so far. HInstrVec 'code'
+ changes according to the current IRStmtVec being processed.

- A counter, for generating new virtual registers.

@@ -171,13 +185,12 @@

typedef
struct {
- /* Constant -- are set at the start and do not change. */
- IRTypeEnv* type_env;
- IRStmtVec* stmts;
+ /* Constant -- set at the start and do not change. */
+ const IRTypeEnv* type_env;

HReg* vregmap;
HReg* vregmapHI;
- Int n_vregmap;
+ UInt n_vregmap;

UInt hwcaps;

@@ -185,8 +198,10 @@
Addr32 max_ga;

/* These are modified as we go along. */
- HInstrSB* code;
- Int vreg_ctr;
+ HInstrSB* code_sb;
+ HInstrVec* code;
+ UInt vreg_ctr;
+ UInt depth;
}
ISelEnv;

@@ -209,8 +224,9 @@

static void addInstr ( ISelEnv* env, X86Instr* instr )
{
- addHInstr(env->code->insns, instr);
+ addHInstr(env->code, instr);
if (vex_traceflags & VEX_TRACE_VCODE) {
+ print_depth(env->depth);
ppX86Instr(instr, False);
vex_printf("\n");
}
@@ -3860,10 +3876,111 @@
/*--- ISEL: Statements ---*/
/*---------------------------------------------------------*/

+static void iselStmt(ISelEnv* env, IRStmt* stmt);
+
+static HPhiNode* convertPhiNodes(ISelEnv* env, const IRPhiVec* phi_nodes,
+ IRIfThenElse_Hint hint, UInt *n_phis)
+{
+ *n_phis = phi_nodes->phis_used;
+ HPhiNode* hphis = LibVEX_Alloc_inline(*n_phis * sizeof(HPhiNode));
+
+ for (UInt i = 0; i < *n_phis; i++) {
+ const IRPhi* phi = phi_nodes->phis[i];
+ hphis[i].dst = lookupIRTemp(env, phi->dst);
+
+ switch (hint) {
+ case IfThenElse_ThenLikely:
+ hphis[i].srcFallThrough = lookupIRTemp(env, phi->srcThen);
+ hphis[i].srcOutOfLine = lookupIRTemp(env, phi->srcElse);
+ break;
+ case IfThenElse_ElseLikely:
+ hphis[i].srcFallThrough = lookupIRTemp(env, phi->srcElse);
+ hphis[i].srcOutOfLine = lookupIRTemp(env, phi->srcThen);
+ break;
+ default:
+ vassert(0);
+ }
+ }
+ return hphis;
+}
+
+static void iselStmtVec(ISelEnv* env, IRStmtVec* stmts)
+{
+ for (UInt i = 0; i < stmts->stmts_used; i++) {
+ IRStmt* st = stmts->stmts[i];
+ if (st->tag != Ist_IfThenElse) {
+ iselStmt(env, stmts->stmts[i]);
+ continue;
+ }
+
+ /* Deal with IfThenElse. */
+ HInstrVec* current_code = env->code;
+ IRIfThenElse* ite = st->Ist.IfThenElse.details;
+ if (vex_traceflags & VEX_TRACE_VCODE) {
+ print_IRStmt_prefix(env->depth);
+ ppIRIfThenElseCondHint(ite);
+ vex_printf(" then {\n");
+ }
+
+ UInt n_phis;
+ HPhiNode* phi_nodes = convertPhiNodes(env, ite->phi_nodes,
+ ite->hint, &n_phis);
+
+ X86CondCode cc = iselCondCode(env, ite->cond);
+ HInstrIfThenElse* hite = newHInstrIfThenElse(cc, phi_nodes, n_phis);
+ X86Instr* instr = X86Instr_IfThenElse(hite);
+ addInstr(env, instr);
+
+ env->depth += 1;
+
+ IRStmtVec* likely_leg;
+ IRStmtVec* unlikely_leg;
+ switch (ite->hint) {
+ case IfThenElse_ThenLikely:
+ likely_leg = ite->then_leg;
+ unlikely_leg = ite->else_leg;
+ break;
+ case IfThenElse_ElseLikely:
+ likely_leg = ite->else_leg;
+ unlikely_leg = ite->then_leg;
+ break;
+ default:
+ vassert(0);
+ }
+
+ env->code = hite->fallThrough;
+ iselStmtVec(env, likely_leg);
+ if (vex_traceflags & VEX_TRACE_VCODE) {
+ print_IRStmt_prefix(env->depth - 1);
+ vex_printf("} else {\n");
+ }
+ env->code = hite->outOfLine;
+ iselStmtVec(env, unlikely_leg);
+
+ env->depth -= 1;
+ env->code = current_code;
+
+ if (vex_traceflags & VEX_TRACE_VCODE) {
+ print_IRStmt_prefix(env->depth);
+ vex_printf("}\n");
+
+ for (UInt j = 0; j < hite->n_phis; j++) {
+ print_IRStmt_prefix(env->depth);
+ ppIRPhi(ite->phi_nodes->phis[j]);
+ vex_printf("\n");
+
+ print_depth(env->depth);
+ ppHPhiNode(&hite->phi_nodes[j]);
+ vex_printf("\n");
+ }
+ }
+ }
+}
+
static void iselStmt ( ISelEnv* env, IRStmt* stmt )
{
if (vex_traceflags & VEX_TRACE_VCODE) {
- vex_printf("\n-- ");
+ print_IRStmt_prefix(env->depth);
ppIRStmt(stmt, env->type_env, 0);
vex_printf("\n");
}
@@ -4430,9 +4547,6 @@
Bool addProfInc,
Addr max_ga )
{
- Int i, j;
- HReg hreg, hregHI;
- ISelEnv* env;
UInt hwcaps_host = archinfo_host->hwcaps;
X86AMode *amCounter, *amFailAddr;

@@ -4449,17 +4563,16 @@
vassert(archinfo_host->endness == VexEndnessLE);

/* Make up an initial environment to use. */
- env = LibVEX_Alloc_inline(sizeof(ISelEnv));
+ ISelEnv* env = LibVEX_Alloc_inline(sizeof(ISelEnv));
env->vreg_ctr = 0;

- /* Set up output code array. */
- env->code = newHInstrSB();
+ /* Set up output HInstrSB and the first processed HInstrVec. */
+ env->code_sb = newHInstrSB();
+ env->code = env->code_sb->insns;
+ env->depth = 0;

/* Copy BB's type env. */
- /* TODO-JIT: Currently works only with no if-then-else statements. */
- vassert(bb->id_seq == 1);
env->type_env = bb->tyenv;
- env->stmts = bb->stmts;

/* Make up an IRTemp -> virtual HReg mapping. This doesn't
change as we go along. */
@@ -4474,9 +4587,10 @@

/* For each IR temporary, allocate a suitably-kinded virtual
register. */
- j = 0;
- for (i = 0; i < env->n_vregmap; i++) {
- hregHI = hreg = INVALID_HREG;
+ UInt j = 0;
+ for (UInt i = 0; i < env->n_vregmap; i++) {
+ HReg hreg = INVALID_HREG;
+ HReg hregHI = INVALID_HREG;
switch (bb->tyenv->types[i]) {
case Ity_I1:
case Ity_I8:
@@ -4509,14 +4623,13 @@
}

/* Ok, finally we can iterate over the statements. */
- for (i = 0; i < bb->stmts->stmts_used; i++)
- iselStmt(env, bb->stmts->stmts[i]);
+ iselStmtVec(env, bb->stmts);

iselNext(env, bb->next, bb->jumpkind, bb->offsIP);

/* record the number of vregs we used. */
- env->code->n_vregs = env->vreg_ctr;
- return env->code;
+ env->code_sb->n_vregs = env->vreg_ctr;
+ return env->code_sb;
}



Modified: branches/VEX_JIT_HACKS/priv/ir_defs.c
==============================================================================
--- branches/VEX_JIT_HACKS/priv/ir_defs.c (original)
+++ branches/VEX_JIT_HACKS/priv/ir_defs.c Wed Apr 19 22:21:22 2017
@@ -1610,13 +1610,19 @@
}
}

-void ppIRIfThenElse(const IRIfThenElse* ite, const IRTypeEnv* tyenv, UInt depth)
+void ppIRIfThenElseCondHint(const IRIfThenElse* ite)
{
vex_printf("if (");
ppIRExpr(ite->cond);
vex_printf(") [");
ppIRIfThenElse_Hint(ite->hint);
- vex_printf("] then {\n");
+ vex_printf("]");
+}
+
+void ppIRIfThenElse(const IRIfThenElse* ite, const IRTypeEnv* tyenv, UInt depth)
+{
+ ppIRIfThenElseCondHint(ite);
+ vex_printf(" then {\n");
ppIRStmtVec(ite->then_leg, tyenv, depth + 1);
print_depth(depth);
vex_printf("} else {\n");

Modified: branches/VEX_JIT_HACKS/priv/main_main.c
==============================================================================
--- branches/VEX_JIT_HACKS/priv/main_main.c (original)
+++ branches/VEX_JIT_HACKS/priv/main_main.c Wed Apr 19 22:21:22 2017
@@ -331,6 +331,7 @@
void (*genReload) ( HInstr**, HInstr**, HReg, Int, Bool );
HInstr* (*directReload) ( HInstr*, HReg, Short );
void (*ppInstr) ( const HInstr*, Bool );
+ void (*ppCondCode) ( HCondCode );
void (*ppReg) ( HReg );
HInstrSB* (*iselSB) ( const IRSB*, VexArch, const VexArchInfo*,
const VexAbiInfo*, Int, Int, Bool, Bool,
@@ -367,6 +368,7 @@
genReload = NULL;
directReload = NULL;
ppInstr = NULL;
+ ppCondCode = NULL;
ppReg = NULL;
iselSB = NULL;
emit = NULL;
@@ -419,6 +421,7 @@
genReload = (__typeof__(genReload)) X86FN(genReload_X86);
directReload = (__typeof__(directReload)) X86FN(directReload_X86);
ppInstr = (__typeof__(ppInstr)) X86FN(ppX86Instr);
+ ppCondCode = (__typeof__(ppCondCode)) X86FN(ppX86CondCode);
ppReg = (__typeof__(ppReg)) X86FN(ppHRegX86);
iselSB = X86FN(iselSB_X86);
emit = (__typeof__(emit)) X86FN(emit_X86Instr);
@@ -1044,7 +1047,7 @@
vex_printf("\n");

if (vex_traceflags & VEX_TRACE_VCODE) {
- ppHInstrSB(vcode, isIfThenElse, ppInstr, mode64);
+ ppHInstrSB(vcode, isIfThenElse, ppInstr, ppCondCode, mode64);
vex_printf("\n");
}

@@ -1053,7 +1056,7 @@
isMove, getRegUsage, mapRegs, isIfThenElse,
genSpill, genReload, directReload,
guest_sizeB,
- ppInstr, ppReg, mode64 );
+ ppInstr, ppCondCode, ppReg, mode64 );

vexAllocSanityCheck();

@@ -1061,7 +1064,7 @@
vex_printf("\n------------------------"
" Register-allocated code "
"------------------------\n\n");
- ppHInstrSB(rcode, isIfThenElse, ppInstr, mode64);
+ ppHInstrSB(rcode, isIfThenElse, ppInstr, ppCondCode, mode64);
vex_printf("\n");
}


Modified: branches/VEX_JIT_HACKS/pub/libvex_ir.h
==============================================================================
--- branches/VEX_JIT_HACKS/pub/libvex_ir.h (original)
+++ branches/VEX_JIT_HACKS/pub/libvex_ir.h Wed Apr 19 22:21:22 2017
@@ -2817,6 +2817,8 @@
IRIfThenElse;

extern void ppIRIfThenElse_Hint(IRIfThenElse_Hint hint);
+/* Pretty print only If-Then-Else preamble: condition and hint. Not the legs. */
+extern void ppIRIfThenElseCondHint(const IRIfThenElse* ite);
extern void ppIRIfThenElse(const IRIfThenElse* ite, const IRTypeEnv* tyenv,
UInt depth);
extern IRIfThenElse* mkIRIfThenElse(IRExpr* cond, IRIfThenElse_Hint hint,
Loading...