i386[stv]: Handle REG_EH_REGION note
When we split (insn 37 36 38 10 (set (reg:DI 104 [ _18 ]) (mem:DI (reg/f:SI 98 [ CallNative_nclosure.0_1 ]) [6 MEM[(struct SQRefCounted *)CallNative_nclosure.0_1]._uiRef+0 S8 A32])) "test.C":22:42 84 {*movdi_internal} (expr_list:REG_EH_REGION (const_int -11 [0xfffffffffffffff5]) into (insn 104 36 37 10 (set (subreg:V2DI (reg:DI 124) 0) (vec_concat:V2DI (mem:DI (reg/f:SI 98 [ CallNative_nclosure.0_1 ]) [6 MEM[(struct SQRefCounted *)CallNative_nclosure.0_1]._uiRef+0 S8 A32]) (const_int 0 [0]))) "test.C":22:42 -1 (nil))) (insn 37 104 105 10 (set (subreg:V2DI (reg:DI 104 [ _18 ]) 0) (subreg:V2DI (reg:DI 124) 0)) "test.C":22:42 2024 {movv2di_internal} (expr_list:REG_EH_REGION (const_int -11 [0xfffffffffffffff5]) (nil))) we must copy the REG_EH_REGION note to the first insn and split the block after the newly added insn. The REG_EH_REGION on the second insn will be removed later since it no longer traps. gcc/ChangeLog: * config/i386/i386-features.cc (general_scalar_chain::convert_op): Handle REG_EH_REGION note. (convert_scalars_to_vector): Ditto. * config/i386/i386-features.h (class scalar_chain): New memeber control_flow_insns. gcc/testsuite/ChangeLog: * g++.target/i386/pr111822.C: New test.
This commit is contained in:
parent
746b71e26b
commit
618e34d56c
3 changed files with 91 additions and 5 deletions
|
@ -998,20 +998,36 @@ general_scalar_chain::convert_op (rtx *op, rtx_insn *insn)
|
|||
}
|
||||
else if (MEM_P (*op))
|
||||
{
|
||||
rtx_insn* eh_insn, *movabs = NULL;
|
||||
rtx tmp = gen_reg_rtx (GET_MODE (*op));
|
||||
|
||||
/* Handle movabs. */
|
||||
/* Emit MOVABS to load from a 64-bit absolute address to a GPR. */
|
||||
if (!memory_operand (*op, GET_MODE (*op)))
|
||||
{
|
||||
rtx tmp2 = gen_reg_rtx (GET_MODE (*op));
|
||||
movabs = emit_insn_before (gen_rtx_SET (tmp2, *op), insn);
|
||||
|
||||
emit_insn_before (gen_rtx_SET (tmp2, *op), insn);
|
||||
*op = tmp2;
|
||||
}
|
||||
|
||||
emit_insn_before (gen_rtx_SET (gen_rtx_SUBREG (vmode, tmp, 0),
|
||||
gen_gpr_to_xmm_move_src (vmode, *op)),
|
||||
insn);
|
||||
eh_insn
|
||||
= emit_insn_before (gen_rtx_SET (gen_rtx_SUBREG (vmode, tmp, 0),
|
||||
gen_gpr_to_xmm_move_src (vmode, *op)),
|
||||
insn);
|
||||
|
||||
if (cfun->can_throw_non_call_exceptions)
|
||||
{
|
||||
/* Handle REG_EH_REGION note. */
|
||||
rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
|
||||
if (note)
|
||||
{
|
||||
if (movabs)
|
||||
eh_insn = movabs;
|
||||
control_flow_insns.safe_push (eh_insn);
|
||||
add_reg_note (eh_insn, REG_EH_REGION, XEXP (note, 0));
|
||||
}
|
||||
}
|
||||
|
||||
*op = gen_rtx_SUBREG (vmode, tmp, 0);
|
||||
|
||||
if (dump_file)
|
||||
|
@ -2494,6 +2510,7 @@ convert_scalars_to_vector (bool timode_p)
|
|||
{
|
||||
basic_block bb;
|
||||
int converted_insns = 0;
|
||||
auto_vec<rtx_insn *> control_flow_insns;
|
||||
|
||||
bitmap_obstack_initialize (NULL);
|
||||
const machine_mode cand_mode[3] = { SImode, DImode, TImode };
|
||||
|
@ -2575,6 +2592,11 @@ convert_scalars_to_vector (bool timode_p)
|
|||
chain->chain_id);
|
||||
}
|
||||
|
||||
rtx_insn* iter_insn;
|
||||
unsigned int ii;
|
||||
FOR_EACH_VEC_ELT (chain->control_flow_insns, ii, iter_insn)
|
||||
control_flow_insns.safe_push (iter_insn);
|
||||
|
||||
delete chain;
|
||||
}
|
||||
}
|
||||
|
@ -2643,6 +2665,24 @@ convert_scalars_to_vector (bool timode_p)
|
|||
DECL_INCOMING_RTL (parm) = gen_rtx_SUBREG (TImode, r, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (!control_flow_insns.is_empty ())
|
||||
{
|
||||
free_dominance_info (CDI_DOMINATORS);
|
||||
|
||||
unsigned int i;
|
||||
rtx_insn* insn;
|
||||
FOR_EACH_VEC_ELT (control_flow_insns, i, insn)
|
||||
if (control_flow_insn_p (insn))
|
||||
{
|
||||
/* Split the block after insn. There will be a fallthru
|
||||
edge, which is OK so we keep it. We have to create
|
||||
the exception edges ourselves. */
|
||||
bb = BLOCK_FOR_INSN (insn);
|
||||
split_block (bb, insn);
|
||||
rtl_make_eh_edge (NULL, bb, BB_END (bb));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -155,6 +155,7 @@ class scalar_chain
|
|||
hash_map<rtx, rtx> defs_map;
|
||||
unsigned n_sse_to_integer;
|
||||
unsigned n_integer_to_sse;
|
||||
auto_vec<rtx_insn *> control_flow_insns;
|
||||
|
||||
bool build (bitmap candidates, unsigned insn_uid, bitmap disallowed);
|
||||
virtual int compute_convert_gain () = 0;
|
||||
|
|
45
gcc/testsuite/g++.target/i386/pr111822.C
Normal file
45
gcc/testsuite/g++.target/i386/pr111822.C
Normal file
|
@ -0,0 +1,45 @@
|
|||
/* PR target/111822 */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -flive-range-shrinkage -fno-dce -fnon-call-exceptions" } */
|
||||
|
||||
typedef union {
|
||||
int *pNativeClosure;
|
||||
struct SQRefCounted *pRefCounted;
|
||||
} SQObjectValue;
|
||||
typedef struct {
|
||||
SQObjectValue _unVal;
|
||||
} SQObject;
|
||||
typedef long SQFUNCTION(struct SQVM *);
|
||||
struct SQVM {
|
||||
void CallNative();
|
||||
};
|
||||
struct SQRefCounted {
|
||||
long long _uiRef;
|
||||
};
|
||||
void Null();
|
||||
struct SQObjectPtr : SQObject {
|
||||
SQObjectPtr() {}
|
||||
SQObjectPtr(int *pNativeClosure) {
|
||||
_unVal.pNativeClosure = pNativeClosure;
|
||||
_unVal.pRefCounted->_uiRef++;
|
||||
}
|
||||
~SQObjectPtr() { --_unVal.pRefCounted->_uiRef; }
|
||||
};
|
||||
struct CallInfo {
|
||||
SQObjectPtr _closure;
|
||||
};
|
||||
long long _top;
|
||||
SQFUNCTION _function;
|
||||
int *CallNative_nclosure;
|
||||
void SQVM::CallNative() {
|
||||
long long oldtop = _top;
|
||||
CallInfo lci;
|
||||
lci._closure = CallNative_nclosure;
|
||||
try {
|
||||
_function(this);
|
||||
} catch (...) {
|
||||
_top = oldtop;
|
||||
}
|
||||
while (oldtop)
|
||||
Null();
|
||||
}
|
Loading…
Add table
Reference in a new issue