This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c++/12902] Invalid assembly generated when using SSE / xmmintrin.h
- From: "kbowers at lanl dot gov" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 7 Nov 2003 01:02:11 -0000
- Subject: [Bug c++/12902] Invalid assembly generated when using SSE / xmmintrin.h
- References: <20031105013127.12902.kbowers@lanl.gov>
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
PLEASE REPLY TO gcc-bugzilla@gcc.gnu.org ONLY, *NOT* gcc-bugs@gcc.gnu.org.
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12902
kbowers at lanl dot gov changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|WAITING |NEW
------- Additional Comments From kbowers at lanl dot gov 2003-11-07 01:02 -------
I've done some further diagnostics and I think the instruction pattern matching
is confused about when to emit a memory-store movlps/movhps and a memory-load
movlps/movhps.
Here is a snippet from from gcc/config/i386/i386.c:ix86_expand_builtin() around
lines 13470. Given this is my first serious look into gcc's internals, I've
annotated it with my best guess as to what it is doing:
// op0 is the "__A" of the xmmintrin.h:_mm_loadl_pi
// op1 is the "__P" of the xmmintrin.h:_mm_loadl_pi
// If A is a not a nonimmediate V4SF-mode operand, copy A into a
// V4SF-mode register temporary
if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
op0 = copy_to_mode_reg (mode0, op0);
// Copy P into a register and mark that register as a V4SF-mode memory
// operand
op1 = gen_rtx_MEM (mode1, copy_to_mode_reg (Pmode, op1));
// Create a temporary V4SF-mode register target if one of the following
// is true:
// - There is no return target
// - The target is not a V4SF-mode operand
// - The target is not in a non-immediate V4SF-mode operand
if (target == 0
|| GET_MODE (target) != tmode
|| ! (*insn_data[icode].operand[0].predicate) (target, tmode))
target = gen_reg_rtx (tmode);
// Create the appropriate RTL instructions.
// Return failure if we could not generate the RTL.
// Otherwise, emit the RTL and return where the result went.
//
// GEN_FCN(icode) is in LOADLPS case calls gen_sse_movlps.
// For this case, the "pat =" line is equivalent to:
// pat = gen_rtx_SET( VOIDmode, target,
// gen_rtx_fmt_eee( VEC_MERGE, V4SFmode, op0, op1, GEN_INT(3) ));
pat = GEN_FCN (icode) (target, op0, op1);
if (! pat)
return 0;
emit_insn (pat);
return target;
Here is the movlps description from gcc/config/i386/i386.md(line 18549):
(define_insn "sse_movlps"
[(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,m")
(vec_merge:V4SF
(match_operand:V4SF 1 "nonimmediate_operand" "0,0")
(match_operand:V4SF 2 "nonimmediate_operand" "m,x")
(const_int 3)))]
"TARGET_SSE
&& (GET_CODE (operands[1]) == MEM || GET_CODE (operands[2]) == MEM)"
"movlps\t{%2, %0|%0, %2}"
[(set_attr "type" "ssecvt")
(set_attr "mode" "V4SF")])
If my annotations are correct, how does the instruction pattern matching
determine if a memory-store "movlps" or a memory-load "movlps" is emitted in the
case where both "target" and "op0" are memory operands? If the instruction
pattern matching was confused and picked the storing movlps case instead of the
loading movlps case, it would explain the fault I am seeing.
So, should the i386 machine description split the movlps/movhps descriptions
split into a separate load and store cases to eliminate this ambiguity?
For example, maybe something like this for the loadlps case:
(define_insn "sse_loadlps"
[(set (match_operand:V4SF 0 "nonimmediate_operand" "=x")
(vec_merge:V4SF
(match_operand:V4SF 1 "nonimmediate_operand" "0")
(match_operand:V4SF 2 "nonimmediate_operand" "m")
(const_int 3)))]
"TARGET_SSE
&& (GET_CODE (operands[1]) == MEM || GET_CODE (operands[2]) == MEM)"
"movlps\t{%2, %0|%0, %2}"
[(set_attr "type" "ssecvt")
(set_attr "mode" "V4SF")])