This is an archive of the discontinued LLVM Phabricator instance.

[IR] Update to use new shufflevector semantics
ClosedPublic

Authored by ManuelJBrito on Apr 30 2023, 6:52 AM.

Diff Detail

Event Timeline

ManuelJBrito created this revision.Apr 30 2023, 6:52 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 30 2023, 6:52 AM
ManuelJBrito requested review of this revision.Apr 30 2023, 6:52 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 30 2023, 6:52 AM
nikic accepted this revision.Apr 30 2023, 6:58 AM

LGTM

This revision is now accepted and ready to land.Apr 30 2023, 6:58 AM

This change is visible in clang in particular in codegen for the vec_promote builtin.
It now produces poison instead of undef for the undefined elements.
I think this is OK according to IBM's documentation[https://www.ibm.com/docs/en/epfz/5.3?topic=book-semantics]:

When a result or behavior is undefined, it is something you “must not” do.
Use of an undefined feature is likely to produce different results on different > implementations or releases of a PL/I product.
The application program is considered to be in error.

Herald added a project: Restricted Project. · View Herald TranscriptMay 1 2023, 7:23 AM
Herald added a subscriber: cfe-commits. · View Herald Transcript
ManuelJBrito added a reviewer: nemanjai.EditedMay 6 2023, 7:01 AM

Hello Nemanja is the change in codegen for vec_promote OK?

Adding some PowerPC folks to review the change in codegen for vec_promote.
AFAICT its OK to have the undefined values be poison.

Why this changes IR output of following case?

// RUN: clang vecpromote.c -S -o - -O0 -target s390x-linux-gnu -fzvector -emit-llvm
#include <vecintrin.h>

vector int si;
int g;
int i;

void foo() {
  si = vec_promote(g, i);
}

// store <4 x i32> undef, ptr %__vec.i, align 16, !noalias !6  ; this undef becomes poison after this patch
// %2 = load i32, ptr %__scalar.addr.i, align 4, !noalias !6
// %3 = load i32, ptr %__index.addr.i, align 4, !noalias !6
// %4 = load <4 x i32>, ptr %__vec.i, align 16, !noalias !6
// %vecins.i = insertelement <4 x i32> %4, i32 %2, i32 %and.i

I see no PowerPC related case changes. Maybe adding SystemZ folks for comments @uweigand @jonpa

Why this changes IR output of following case?

// RUN: clang vecpromote.c -S -o - -O0 -target s390x-linux-gnu -fzvector -emit-llvm
#include <vecintrin.h>

vector int si;
int g;
int i;

void foo() {
  si = vec_promote(g, i);
}

// store <4 x i32> undef, ptr %__vec.i, align 16, !noalias !6  ; this undef becomes poison after this patch
// %2 = load i32, ptr %__scalar.addr.i, align 4, !noalias !6
// %3 = load i32, ptr %__index.addr.i, align 4, !noalias !6
// %4 = load <4 x i32>, ptr %__vec.i, align 16, !noalias !6
// %vecins.i = insertelement <4 x i32> %4, i32 %2, i32 %and.i

I think it's because vec_promote is implemented in clang using a shufflevector with an undefined mask (-1).
ConstantFold sees that we have a fully undefined mask and it folds the shufflevector to poison.(previously undef)
My concern : is it Ok to have the undefined values of the vector be poison or was the undef used to abide to some specific semantics?
Hope this makes sense.

I see no PowerPC related case changes. Maybe adding SystemZ folks for comments @uweigand @jonpa

My bad I pinged the wrong people, thanks for adding SystemZ folks.

So the semantics of the vec_promote(a, b) intrinsic is defined as:

Returns a vector with a in element position b. The result is a vector with a in element position b. [...] The other elements of the vector are undefined.

This is currently implemented by using insertvector to place a at position b into a source vector that is undef. The effect should be that when using element b of that vector, we are guaranteed to get a, while using any other element is undefined behavior (just like accessing an uninitialized variable).

To be honest, I'm not sure how exactly the LLVM IR semantics changes here when using a poison source vector instead of undef. I seem to recall that poison propagates over operations - is it true that the result of insertvector on a poison vector is itself poison? If so, then this change would break semantics. However, if the result is a vector with a in element b, and poison only in the other elements, then I guess this would still preserve the expected semantics.

So the semantics of the vec_promote(a, b) intrinsic is defined as:

Returns a vector with a in element position b. The result is a vector with a in element position b. [...] The other elements of the vector are undefined.

This is currently implemented by using insertvector to place a at position b into a source vector that is undef. The effect should be that when using element b of that vector, we are guaranteed to get a, while using any other element is undefined behavior (just like accessing an uninitialized variable).

To be honest, I'm not sure how exactly the LLVM IR semantics changes here when using a poison source vector instead of undef. I seem to recall that poison propagates over operations - is it true that the result of insertvector on a poison vector is itself poison? If so, then this change would break semantics. However, if the result is a vector with a in element b, and poison only in the other elements, then I guess this would still preserve the expected semantics.

If a vector is fully initialized with insertvector (i.e., one operation per index), then the value of the base vector is irrelevant. It can be poison.
Poison in vectors is element-wise. <poison, 42> doesn't propagate to <poison, poison>.

If a vector is fully initialized with insertvector (i.e., one operation per index), then the value of the base vector is irrelevant. It can be poison.
Poison in vectors is element-wise. <poison, 42> doesn't propagate to <poison, poison>.

OK, that should be fine for SystemZ then. Thanks!

If a vector is fully initialized with insertvector (i.e., one operation per index), then the value of the base vector is irrelevant. It can be poison.
Poison in vectors is element-wise. <poison, 42> doesn't propagate to <poison, poison>.

OK, that should be fine for SystemZ then. Thanks!

Thanks! I'll move forward then.

This revision was landed with ongoing or failed builds.Jun 13 2023, 9:14 AM
This revision was automatically updated to reflect the committed changes.