Unexpected behavior reading/writing <8 x i1> vector to memory

I'm seeing some behavior that surprised me in writing an <8 x i1> vector to memory and reading it back. (Specifically, the surprise is that I didn't get the original value back!). This happens both with TOT and 2.9. This program illustrates the issue:

define i32 @foo() {
  %c = alloca <8 x i1>
  store <8 x i1> <i1 true, i1 false, i1 false, i1 false, i1 false, i1 false, i1 false, i1 false>, <8 x i1>* %c
  %val = load <8 x i1>* %c
  %vali8 = bitcast <8 x i1> %val to i8
  %vali32 = zext i8 %vali8 to i32
  ret i32 %vali32
}

If I run this through opt -mem2reg before compiling with llc, then I basically get:

_foo:
  movl $1, %eax
  ret

which looks good to me (and is the result I expect).

If I just run it through llc without mem2reg,I get this suspicious output, which returns zero.

_foo:
  movb $1, -8(%rsp)
  movb $0, -8(%rsp)
  movzbl -8(%rsp), %eax
  ret

Is this a bug? I double checked the LLVM assembly reference manual and didn't see anything about writing vectors of i1 to memory as being undefined.

(I recognize that I probably don't want to be doing this in general and wouldn't expect it to necessarily be super efficient. But this was unusual enough that it seemed worth checking about.)

Thanks,
-matt

There are longstanding issues with CodeGen (espcially loads/stores) of
i1 vectors. One of which is that we never actually decided what the
memory representation should be...

-Eli

Sounds reasonable--thanks. (As it turns out, the only reason I was doing this is in serializing a vector select into scalar selects; it looks like Nadav's patch landed today, so that works out nicely to fully avoid the situation anyway.)

Thanks,
-matt

Hi folks,

In this case, am I wrong in assuming that for the target that Matt is using the representation is an unpacked byte for each boolean value? If so, it might be handy to have a notation for a packed vector of bits as well. On some architectures, packing flags in a bitset not only saves memory but even has special opcodes for dealing with them.

Just a thought,

--Sam

Hi Matt,

I'm seeing some behavior that surprised me in writing an<8 x i1> vector to memory and reading it back. (Specifically, the surprise is that I didn't get the original value back!). This happens both with TOT and 2.9. This program illustrates the issue:

some new infrastructure, activated using the -promote-elements llc flag, is
supposed to take care of this. Unfortunately it crashes on your testcase :frowning:
Otherwise, as Eli mentioned, codegen simply doesn't support these types. I
had thought that all problems would result in an assertion firing but it seems
not...

Ciao, Duncan.