Index: lib/Analysis/ValueTracking.cpp =================================================================== --- lib/Analysis/ValueTracking.cpp +++ lib/Analysis/ValueTracking.cpp @@ -1389,6 +1389,14 @@ } } break; + case Instruction::ExtractElement: + // Look through extract element. At the moment we keep this simple and skip + // tracking the specific element. But at least we might find information + // valid for all elements of the vector (for example if vector is sign + // extended, shifted, etc). It could be questioned if Depth should be + // increased or not here. But since it isn't increased when looking thru + // ExtractValue I decided to keep the same logic here. + return computeKnownBits(I->getOperand(0), KnownZero, KnownOne, Depth, Q); case Instruction::ExtractValue: if (IntrinsicInst *II = dyn_cast(I->getOperand(0))) { const ExtractValueInst *EVI = cast(I); @@ -2220,6 +2228,13 @@ // FIXME: it's tricky to do anything useful for this, but it is an important // case for targets like X86. break; + + case Instruction::ExtractElement: + // Look through extract element. At the moment we keep this simple and skip + // tracking the specific element. But at least we might find information + // valid for all elements of the vector (for example if vector is sign + // extended, shifted, etc). + return ComputeNumSignBits(U->getOperand(0), Depth + 1, Q); } // Finally, if we can prove that the top bits of the result are 0's or 1's, Index: test/Analysis/ValueTracking/signbits-extract-elt.ll =================================================================== --- /dev/null +++ test/Analysis/ValueTracking/signbits-extract-elt.ll @@ -0,0 +1,38 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + + +; If computeKnownBits can do a simple look-thru for extractelement +; then InstCombine will know that we are adding two positive number, and that +; the addition is nsw. +; (test case may seem overly complicated, but without two extractelement + add +; this would be scalarized without testing computeKnownBits which is the +; purpopse with the test). +define i1 @test1(<4 x i16>* %in) { +; CHECK-LABEL: @test1( +; CHECK-NEXT: ret i1 false + %vec2 = load <4 x i16>, <4 x i16>* %in, align 1 + %vec3 = lshr <4 x i16> %vec2, + %vec4 = sext <4 x i16> %vec3 to <4 x i32> + %elt0 = extractelement <4 x i32> %vec4, i32 0 + %elt1 = extractelement <4 x i32> %vec4, i32 1 + %sum = add i32 %elt0, %elt1 + %bool = icmp slt i32 %sum, 0 + ret i1 %bool +} + +; This is to verify that computeKnownSignBits is doing a simple look-thru for +; extractelement. It is detected as the shift of %elt0 becoming "nsw". +define i32 @test2(<4 x i16>* %in) { +; CHECK-LABEL: @test2( +; CHECK: %tmp1 = shl nsw i32 %elt0, 18 +; CHECK: %tmp2 = shl i32 %elt1, 19 + %vec2 = load <4 x i16>, <4 x i16>* %in, align 1 + %vec3 = ashr <4 x i16> %vec2, + %vec4 = sext <4 x i16> %vec3 to <4 x i32> + %elt0 = extractelement <4 x i32> %vec4, i32 0 + %elt1 = extractelement <4 x i32> %vec4, i32 1 + %tmp1 = shl i32 %elt0, 18 + %tmp2 = shl i32 %elt1, 19 + %r1 = add i32 %tmp1, %tmp2 + ret i32 %r1 +}