<div dir="ltr"><div dir="ltr"><div>Something like this should work I think.</div><div><br></div><div><div>; ModuleID = 'test.ll'</div><div>source_filename = "test.ll"</div><div><br></div><div>define void @entry(<4 x i32>* %a, <4 x i32>* %b, <4 x i32>* %x) {</div><div>Entry:</div><div>  %tmp = load <4 x i32>, <4 x i32>* %a, align 16</div><div>  %tmp1 = load <4 x i32>, <4 x i32>* %b, align 16</div><div>  %tmp2 = add <4 x i32> %tmp, %tmp1</div><div>  %tmpsign = icmp slt <4 x i32> %tmp, zeroinitializer</div><div>  %tmp1sign = icmp slt <4 x i32> %tmp1, zeroinitializer</div><div>  %sumsign = icmp slt <4 x i32> %tmp2, zeroinitializer</div><div>  %signsequal = icmp eq <4 x i1> %tmpsign, %tmp1sign</div><div>  %summismatch = icmp ne <4 x i1> %sumsign, %tmpsign</div><div>  %overflow = and <4 x i1> %signsequal, %summismatch</div><div>  %tmp5 = bitcast <4 x i1> %overflow to i4</div><div>  %tmp6 = icmp ne i4 %tmp5, 0</div><div>  br i1 %tmp6, label %OverflowFail, label %OverflowOk</div><div><br></div><div>OverflowFail:                                     ; preds = %Entry</div><div>  tail call fastcc void @panic()</div><div>  unreachable</div><div><br></div><div>OverflowOk:                                       ; preds = %Entry</div><div>  store <4 x i32> %tmp2, <4 x i32>* %x, align 16</div><div>  ret void</div><div>}</div><div><br></div><div>declare fastcc void @panic()</div></div><div><br></div><br clear="all"><div><div dir="ltr" class="gmail_signature">~Craig</div></div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sat, Feb 9, 2019 at 10:05 AM Andrew Kelley <<a href="mailto:andrew@ziglang.org">andrew@ziglang.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">>>     On Sat, Feb 9, 2019 at 1:42 AM Craig Topper via llvm-dev<br>
>>     <<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a> <mailto:<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>>> wrote:<br>
>><br>
>>         I don't think I understand your pseudocode using<br>
>>         llvm.experimental.vector.reduce.umax. All of the types you<br>
>>         showed are scalar, but that intrinsic doesn't work on scalars<br>
>>         so I'm having a hard time understanding what you're trying to<br>
>>         do with it. llvm.experimental.vector.reduce.umax takes a<br>
>>         vector input and returns a scalar result. Are you wanting to<br>
>>         find if any of the additions overflowed or a mask of which<br>
>>         addition overflowed?<br>
<br>
Apologies for the confusion - let me try to clarify. Here is frontend<br>
code that works now:<br>
<br>
export fn entry() void {<br>
    var a: @Vector(4, i32) = []i32{ 1, 2, 3, 4 };<br>
    var b: @Vector(4, i32) = []i32{ 5, 6, 7, 8 };<br>
    var x = a +% b;<br>
}<br>
<br>
This generates the following LLVM IR code:<br>
<br>
define void @entry() #2 !dbg !41 {<br>
Entry:<br>
  %a = alloca <4 x i32>, align 16<br>
  %b = alloca <4 x i32>, align 16<br>
  %x = alloca <4 x i32>, align 16<br>
  store <4 x i32> <i32 1, i32 2, i32 3, i32 4>, <4 x i32>* %a, align 16,<br>
!dbg !55<br>
  call void @llvm.dbg.declare(metadata <4 x i32>* %a, metadata !45,<br>
metadata !DIExpression()), !dbg !55<br>
  store <4 x i32> <i32 5, i32 6, i32 7, i32 8>, <4 x i32>* %b, align 16,<br>
!dbg !56<br>
  call void @llvm.dbg.declare(metadata <4 x i32>* %b, metadata !51,<br>
metadata !DIExpression()), !dbg !56<br>
  %0 = load <4 x i32>, <4 x i32>* %a, align 16, !dbg !57<br>
  %1 = load <4 x i32>, <4 x i32>* %b, align 16, !dbg !58<br>
  %2 = add <4 x i32> %0, %1, !dbg !59<br>
  store <4 x i32> %2, <4 x i32>* %x, align 16, !dbg !60<br>
  call void @llvm.dbg.declare(metadata <4 x i32>* %x, metadata !53,<br>
metadata !DIExpression()), !dbg !60<br>
  ret void, !dbg !61<br>
}<br>
<br>
However I used the +% operator, which in Zig is wrapping addition. Now I<br>
want to implement the + operator for vectors, which Zig defines to panic<br>
if any of the elements overflowed. Here is how the IR could look for this:<br>
<br>
define void @entry() #2 !dbg !41 {<br>
Entry:<br>
  %a = alloca <4 x i32>, align 16<br>
  %b = alloca <4 x i32>, align 16<br>
  %x = alloca <4 x i32>, align 16<br>
  store <4 x i32> <i32 1, i32 2, i32 3, i32 4>, <4 x i32>* %a, align 16,<br>
!dbg !55<br>
  store <4 x i32> <i32 5, i32 6, i32 7, i32 8>, <4 x i32>* %b, align 16,<br>
!dbg !56<br>
  %0 = load <4 x i32>, <4 x i32>* %a, align 16, !dbg !57<br>
  %1 = load <4 x i32>, <4 x i32>* %b, align 16, !dbg !58<br>
  %2 = call { <4 x i32>, <4 x i1> } @llvm.sadd.with.overflow.i32(i32 %0,<br>
i32 %1)<br>
  %3 = extractvalue { <4 x i32>, <4 x i1> } %2, 0, !dbg !56<br>
  %4 = extractvalue { <4 x i32>, <4 x i1> } %2, 1, !dbg !56<br>
  %5 = call i1 @llvm.experimental.vector.reduce.umax.i1.v4i1(%4)<br>
  br i1 %5, label %OverflowFail, label %OverflowOk, !dbg !56<br>
<br>
OverflowFail:                                     ; preds = %Entry<br>
  tail call fastcc void @panic(%"[]u8"* @2, %StackTrace* null), !dbg !56<br>
  unreachable, !dbg !56<br>
<br>
OverflowOk:                                       ; preds = %Entry<br>
  store <4 x i32> %3, <4 x i32>* %x, align 16, !dbg !60<br>
  ret void, !dbg !61<br>
}<br>
<br>
You can see that it depends on @llvm.sadd.with.overflow working on<br>
vector types, and it relies on @llvm.experimental.vector.reduce.umax. I<br>
will note that my strategy with sign extension and icmp would be a<br>
semantically equivalent alternative to @llvm.sadd.with.overflow.<br>
<br>
On 2/9/19 12:37 PM, Nikita Popov wrote:<br>
> On Sat, Feb 9, 2019 at 6:25 PM Simon Pilgrim <<a href="mailto:llvm-dev@redking.me.uk" target="_blank">llvm-dev@redking.me.uk</a><br>
> <mailto:<a href="mailto:llvm-dev@redking.me.uk" target="_blank">llvm-dev@redking.me.uk</a>>> wrote:<br>
>     Regarding the reduction functions - I think the integer intrinsics<br>
>     at least are relatively stable and we can probably investigate<br>
>     dropping the experimental tag before the next release (assuming<br>
>     someone has the time to take on the work) - it'd be nice to have the<br>
>     SLP vectorizer emit reduction intrinsics directly for these.<br>
> <br>
> The vector reduction intrinsics still need quite a lot of work. Apart<br>
> from SplitVecOp, all legalizations are currently missing. This is only<br>
> noticeable on AArch64 right now, because all other targets expand vector<br>
> reductions prior to codegen.<br>
<br>
My follow-up question, then, is this:<br>
<br>
What do you recommend, in terms of LLVM IR, in order to obtain the %5<br>
value above?<br>
<br>
Thanks for the help,<br>
Andrew<br>
<br>
<br>
</blockquote></div>