<div dir="ltr">Thanks, investigating now - sorry about the bug.<br></div><br><div class="gmail_quote"><div dir="ltr">On Mon, Oct 1, 2018 at 6:10 AM Hans Wennborg <<a href="mailto:hans@chromium.org">hans@chromium.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I've reverted in r343458 as it caused assertions while building Chromium.<br>
<br>
The repro is available here:<br>
<a href="https://bugs.chromium.org/p/chromium/issues/detail?id=890723#c1" rel="noreferrer" target="_blank">https://bugs.chromium.org/p/chromium/issues/detail?id=890723#c1</a><br>
<br>
On Sun, Sep 30, 2018 at 4:34 PM, Sanjay Patel via llvm-commits<br>
<<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>> wrote:<br>
> Author: spatel<br>
> Date: Sun Sep 30 07:34:01 2018<br>
> New Revision: 343407<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=343407&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=343407&view=rev</a><br>
> Log:<br>
> [InstCombine] try to convert vector insert+extract to trunc<br>
><br>
> This transform is requested for the backend in:<br>
> <a href="https://bugs.llvm.org/show_bug.cgi?id=39016" rel="noreferrer" target="_blank">https://bugs.llvm.org/show_bug.cgi?id=39016</a><br>
> ...but I figured it was worth doing in IR too, and it's probably<br>
> easier to implement here, so that's this patch.<br>
><br>
> In the simplest case, we are just truncating a scalar value. If the<br>
> extract index doesn't correspond to the LSBs of the scalar, then we<br>
> have to shift-right before the truncate. Endian-ness makes this tricky,<br>
> but hopefully the ASCII-art helps visualize the transform.<br>
><br>
> Differential Revision: <a href="https://reviews.llvm.org/D52439" rel="noreferrer" target="_blank">https://reviews.llvm.org/D52439</a><br>
><br>
> Modified:<br>
>     llvm/trunk/lib/Transforms/InstCombine/InstCombineVectorOps.cpp<br>
>     llvm/trunk/test/Transforms/InstCombine/extractelement.ll<br>
><br>
> Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineVectorOps.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineVectorOps.cpp?rev=343407&r1=343406&r2=343407&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineVectorOps.cpp?rev=343407&r1=343406&r2=343407&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Transforms/InstCombine/InstCombineVectorOps.cpp (original)<br>
> +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineVectorOps.cpp Sun Sep 30 07:34:01 2018<br>
> @@ -167,7 +167,8 @@ Instruction *InstCombiner::scalarizePHI(<br>
>  }<br>
><br>
>  static Instruction *foldBitcastExtElt(ExtractElementInst &Ext,<br>
> -                                      InstCombiner::BuilderTy &Builder) {<br>
> +                                      InstCombiner::BuilderTy &Builder,<br>
> +                                      bool IsBigEndian) {<br>
>    Value *X;<br>
>    uint64_t ExtIndexC;<br>
>    if (!match(Ext.getVectorOperand(), m_BitCast(m_Value(X))) ||<br>
> @@ -186,6 +187,47 @@ static Instruction *foldBitcastExtElt(Ex<br>
>      if (Value *Elt = findScalarElement(X, ExtIndexC))<br>
>        return new BitCastInst(Elt, DestTy);<br>
><br>
> +  // If the source elements are wider than the destination, try to shift and<br>
> +  // truncate a subset of scalar bits of an insert op.<br>
> +  if (NumSrcElts < NumElts && SrcTy->getScalarType()->isIntegerTy()) {<br>
> +    Value *Scalar;<br>
> +    uint64_t InsIndexC;<br>
> +    if (!match(X, m_InsertElement(m_Value(), m_Value(Scalar),<br>
> +                                  m_ConstantInt(InsIndexC))))<br>
> +      return nullptr;<br>
> +<br>
> +    // The extract must be from the subset of vector elements that we inserted<br>
> +    // into. Example: if we inserted element 1 of a <2 x i64> and we are<br>
> +    // extracting an i16 (narrowing ratio = 4), then this extract must be from 1<br>
> +    // of elements 4-7 of the bitcasted vector.<br>
> +    unsigned NarrowingRatio = NumElts / NumSrcElts;<br>
> +    if (ExtIndexC / NarrowingRatio != InsIndexC)<br>
> +      return nullptr;<br>
> +<br>
> +    // We are extracting part of the original scalar. How that scalar is<br>
> +    // inserted into the vector depends on the endian-ness. Example:<br>
> +    //              Vector Byte Elt Index:    0  1  2  3  4  5  6  7<br>
> +    //                                       +--+--+--+--+--+--+--+--+<br>
> +    // inselt <2 x i32> V, <i32> S, 1:       |V0|V1|V2|V3|S0|S1|S2|S3|<br>
> +    // extelt <4 x i16> V', 3:               |                 |S2|S3|<br>
> +    //                                       +--+--+--+--+--+--+--+--+<br>
> +    // If this is little-endian, S2|S3 are the MSB of the 32-bit 'S' value.<br>
> +    // If this is big-endian, S2|S3 are the LSB of the 32-bit 'S' value.<br>
> +    // In this example, we must right-shift little-endian. Big-endian is just a<br>
> +    // truncate.<br>
> +    unsigned Chunk = ExtIndexC % NarrowingRatio;<br>
> +    if (IsBigEndian)<br>
> +      Chunk = NarrowingRatio - 1 - Chunk;<br>
> +    unsigned ShAmt = Chunk * DestTy->getPrimitiveSizeInBits();<br>
> +    if (ShAmt) {<br>
> +      // Bail out if we could end with more instructions than we started with.<br>
> +      if (!Ext.getVectorOperand()->hasOneUse())<br>
> +        return nullptr;<br>
> +      Scalar = Builder.CreateLShr(Scalar, ShAmt);<br>
> +    }<br>
> +    return new TruncInst(Scalar, DestTy);<br>
> +  }<br>
> +<br>
>    return nullptr;<br>
>  }<br>
><br>
> @@ -224,7 +266,7 @@ Instruction *InstCombiner::visitExtractE<br>
>        }<br>
>      }<br>
><br>
> -    if (Instruction *I = foldBitcastExtElt(EI, Builder))<br>
> +    if (Instruction *I = foldBitcastExtElt(EI, Builder, DL.isBigEndian()))<br>
>        return I;<br>
><br>
>      // If there's a vector PHI feeding a scalar use through this extractelement<br>
><br>
> Modified: llvm/trunk/test/Transforms/InstCombine/extractelement.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/extractelement.ll?rev=343407&r1=343406&r2=343407&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/extractelement.ll?rev=343407&r1=343406&r2=343407&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/test/Transforms/InstCombine/extractelement.ll (original)<br>
> +++ llvm/trunk/test/Transforms/InstCombine/extractelement.ll Sun Sep 30 07:34:01 2018<br>
> @@ -42,11 +42,14 @@ define i64 @test2(i64 %in) {<br>
>  }<br>
><br>
>  define i32 @bitcasted_inselt_wide_source_zero_elt(i64 %x) {<br>
> -; ANY-LABEL: @bitcasted_inselt_wide_source_zero_elt(<br>
> -; ANY-NEXT:    [[I:%.*]] = insertelement <2 x i64> undef, i64 [[X:%.*]], i32 0<br>
> -; ANY-NEXT:    [[B:%.*]] = bitcast <2 x i64> [[I]] to <4 x i32><br>
> -; ANY-NEXT:    [[R:%.*]] = extractelement <4 x i32> [[B]], i32 0<br>
> -; ANY-NEXT:    ret i32 [[R]]<br>
> +; LE-LABEL: @bitcasted_inselt_wide_source_zero_elt(<br>
> +; LE-NEXT:    [[R:%.*]] = trunc i64 [[X:%.*]] to i32<br>
> +; LE-NEXT:    ret i32 [[R]]<br>
> +;<br>
> +; BE-LABEL: @bitcasted_inselt_wide_source_zero_elt(<br>
> +; BE-NEXT:    [[TMP1:%.*]] = lshr i64 [[X:%.*]], 32<br>
> +; BE-NEXT:    [[R:%.*]] = trunc i64 [[TMP1]] to i32<br>
> +; BE-NEXT:    ret i32 [[R]]<br>
>  ;<br>
>    %i = insertelement <2 x i64> zeroinitializer, i64 %x, i32 0<br>
>    %b = bitcast <2 x i64> %i to <4 x i32><br>
> @@ -55,11 +58,14 @@ define i32 @bitcasted_inselt_wide_source<br>
>  }<br>
><br>
>  define i16 @bitcasted_inselt_wide_source_modulo_elt(i64 %x) {<br>
> -; ANY-LABEL: @bitcasted_inselt_wide_source_modulo_elt(<br>
> -; ANY-NEXT:    [[I:%.*]] = insertelement <2 x i64> undef, i64 [[X:%.*]], i32 1<br>
> -; ANY-NEXT:    [[B:%.*]] = bitcast <2 x i64> [[I]] to <8 x i16><br>
> -; ANY-NEXT:    [[R:%.*]] = extractelement <8 x i16> [[B]], i32 4<br>
> -; ANY-NEXT:    ret i16 [[R]]<br>
> +; LE-LABEL: @bitcasted_inselt_wide_source_modulo_elt(<br>
> +; LE-NEXT:    [[R:%.*]] = trunc i64 [[X:%.*]] to i16<br>
> +; LE-NEXT:    ret i16 [[R]]<br>
> +;<br>
> +; BE-LABEL: @bitcasted_inselt_wide_source_modulo_elt(<br>
> +; BE-NEXT:    [[TMP1:%.*]] = lshr i64 [[X:%.*]], 48<br>
> +; BE-NEXT:    [[R:%.*]] = trunc i64 [[TMP1]] to i16<br>
> +; BE-NEXT:    ret i16 [[R]]<br>
>  ;<br>
>    %i = insertelement <2 x i64> undef, i64 %x, i32 1<br>
>    %b = bitcast <2 x i64> %i to <8 x i16><br>
> @@ -68,11 +74,14 @@ define i16 @bitcasted_inselt_wide_source<br>
>  }<br>
><br>
>  define i32 @bitcasted_inselt_wide_source_not_modulo_elt(i64 %x) {<br>
> -; ANY-LABEL: @bitcasted_inselt_wide_source_not_modulo_elt(<br>
> -; ANY-NEXT:    [[I:%.*]] = insertelement <2 x i64> undef, i64 [[X:%.*]], i32 0<br>
> -; ANY-NEXT:    [[B:%.*]] = bitcast <2 x i64> [[I]] to <4 x i32><br>
> -; ANY-NEXT:    [[R:%.*]] = extractelement <4 x i32> [[B]], i32 1<br>
> -; ANY-NEXT:    ret i32 [[R]]<br>
> +; LE-LABEL: @bitcasted_inselt_wide_source_not_modulo_elt(<br>
> +; LE-NEXT:    [[TMP1:%.*]] = lshr i64 [[X:%.*]], 32<br>
> +; LE-NEXT:    [[R:%.*]] = trunc i64 [[TMP1]] to i32<br>
> +; LE-NEXT:    ret i32 [[R]]<br>
> +;<br>
> +; BE-LABEL: @bitcasted_inselt_wide_source_not_modulo_elt(<br>
> +; BE-NEXT:    [[R:%.*]] = trunc i64 [[X:%.*]] to i32<br>
> +; BE-NEXT:    ret i32 [[R]]<br>
>  ;<br>
>    %i = insertelement <2 x i64> undef, i64 %x, i32 0<br>
>    %b = bitcast <2 x i64> %i to <4 x i32><br>
> @@ -81,11 +90,15 @@ define i32 @bitcasted_inselt_wide_source<br>
>  }<br>
><br>
>  define i8 @bitcasted_inselt_wide_source_not_modulo_elt_not_half(i32 %x) {<br>
> -; ANY-LABEL: @bitcasted_inselt_wide_source_not_modulo_elt_not_half(<br>
> -; ANY-NEXT:    [[I:%.*]] = insertelement <2 x i32> undef, i32 [[X:%.*]], i32 0<br>
> -; ANY-NEXT:    [[B:%.*]] = bitcast <2 x i32> [[I]] to <8 x i8><br>
> -; ANY-NEXT:    [[R:%.*]] = extractelement <8 x i8> [[B]], i32 2<br>
> -; ANY-NEXT:    ret i8 [[R]]<br>
> +; LE-LABEL: @bitcasted_inselt_wide_source_not_modulo_elt_not_half(<br>
> +; LE-NEXT:    [[TMP1:%.*]] = lshr i32 [[X:%.*]], 16<br>
> +; LE-NEXT:    [[R:%.*]] = trunc i32 [[TMP1]] to i8<br>
> +; LE-NEXT:    ret i8 [[R]]<br>
> +;<br>
> +; BE-LABEL: @bitcasted_inselt_wide_source_not_modulo_elt_not_half(<br>
> +; BE-NEXT:    [[TMP1:%.*]] = lshr i32 [[X:%.*]], 8<br>
> +; BE-NEXT:    [[R:%.*]] = trunc i32 [[TMP1]] to i8<br>
> +; BE-NEXT:    ret i8 [[R]]<br>
>  ;<br>
>    %i = insertelement <2 x i32> undef, i32 %x, i32 0<br>
>    %b = bitcast <2 x i32> %i to <8 x i8><br>
> @@ -94,11 +107,15 @@ define i8 @bitcasted_inselt_wide_source_<br>
>  }<br>
><br>
>  define i3 @bitcasted_inselt_wide_source_not_modulo_elt_not_half_weird_types(i15 %x) {<br>
> -; ANY-LABEL: @bitcasted_inselt_wide_source_not_modulo_elt_not_half_weird_types(<br>
> -; ANY-NEXT:    [[I:%.*]] = insertelement <3 x i15> undef, i15 [[X:%.*]], i32 0<br>
> -; ANY-NEXT:    [[B:%.*]] = bitcast <3 x i15> [[I]] to <15 x i3><br>
> -; ANY-NEXT:    [[R:%.*]] = extractelement <15 x i3> [[B]], i32 1<br>
> -; ANY-NEXT:    ret i3 [[R]]<br>
> +; LE-LABEL: @bitcasted_inselt_wide_source_not_modulo_elt_not_half_weird_types(<br>
> +; LE-NEXT:    [[TMP1:%.*]] = lshr i15 [[X:%.*]], 3<br>
> +; LE-NEXT:    [[R:%.*]] = trunc i15 [[TMP1]] to i3<br>
> +; LE-NEXT:    ret i3 [[R]]<br>
> +;<br>
> +; BE-LABEL: @bitcasted_inselt_wide_source_not_modulo_elt_not_half_weird_types(<br>
> +; BE-NEXT:    [[TMP1:%.*]] = lshr i15 [[X:%.*]], 9<br>
> +; BE-NEXT:    [[R:%.*]] = trunc i15 [[TMP1]] to i3<br>
> +; BE-NEXT:    ret i3 [[R]]<br>
>  ;<br>
>    %i = insertelement <3 x i15> undef, i15 %x, i32 0<br>
>    %b = bitcast <3 x i15> %i to <15 x i3><br>
> @@ -125,12 +142,19 @@ define i8 @bitcasted_inselt_wide_source_<br>
>  declare void @use(<8 x i8>)<br>
><br>
>  define i8 @bitcasted_inselt_wide_source_uses(i32 %x) {<br>
> -; ANY-LABEL: @bitcasted_inselt_wide_source_uses(<br>
> -; ANY-NEXT:    [[I:%.*]] = insertelement <2 x i32> undef, i32 [[X:%.*]], i32 0<br>
> -; ANY-NEXT:    [[B:%.*]] = bitcast <2 x i32> [[I]] to <8 x i8><br>
> -; ANY-NEXT:    call void @use(<8 x i8> [[B]])<br>
> -; ANY-NEXT:    [[R:%.*]] = extractelement <8 x i8> [[B]], i32 3<br>
> -; ANY-NEXT:    ret i8 [[R]]<br>
> +; LE-LABEL: @bitcasted_inselt_wide_source_uses(<br>
> +; LE-NEXT:    [[I:%.*]] = insertelement <2 x i32> undef, i32 [[X:%.*]], i32 0<br>
> +; LE-NEXT:    [[B:%.*]] = bitcast <2 x i32> [[I]] to <8 x i8><br>
> +; LE-NEXT:    call void @use(<8 x i8> [[B]])<br>
> +; LE-NEXT:    [[R:%.*]] = extractelement <8 x i8> [[B]], i32 3<br>
> +; LE-NEXT:    ret i8 [[R]]<br>
> +;<br>
> +; BE-LABEL: @bitcasted_inselt_wide_source_uses(<br>
> +; BE-NEXT:    [[I:%.*]] = insertelement <2 x i32> undef, i32 [[X:%.*]], i32 0<br>
> +; BE-NEXT:    [[B:%.*]] = bitcast <2 x i32> [[I]] to <8 x i8><br>
> +; BE-NEXT:    call void @use(<8 x i8> [[B]])<br>
> +; BE-NEXT:    [[R:%.*]] = trunc i32 [[X]] to i8<br>
> +; BE-NEXT:    ret i8 [[R]]<br>
>  ;<br>
>    %i = insertelement <2 x i32> undef, i32 %x, i32 0<br>
>    %b = bitcast <2 x i32> %i to <8 x i8><br>
><br>
><br>
> _______________________________________________<br>
> llvm-commits mailing list<br>
> <a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
> <a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div>