Index: llvm/lib/Analysis/ValueTracking.cpp =================================================================== --- llvm/lib/Analysis/ValueTracking.cpp +++ llvm/lib/Analysis/ValueTracking.cpp @@ -4502,6 +4502,29 @@ break; } + case Instruction::ExtractElement: { + // Look through extract element. If the index is non-constant or + // out-of-range demand all elements, otherwise just the extracted element. + const Value *Vec = Op->getOperand(0); + const Value *Idx = Op->getOperand(1); + auto *CIdx = dyn_cast(Idx); + + if (auto *VecTy = dyn_cast(Vec->getType())) { + unsigned NumElts = VecTy->getNumElements(); + APInt DemandedVecElts = APInt::getAllOnes(NumElts); + if (CIdx && CIdx->getValue().ult(NumElts)) + DemandedVecElts = APInt::getOneBitSet(NumElts, CIdx->getZExtValue()); + return computeKnownFPClass(Vec, DemandedVecElts, InterestedClasses, Known, + Depth + 1, Q, TLI); + } + + break; + } + case Instruction::ExtractValue: { + computeKnownFPClass(Op->getOperand(0), DemandedElts, InterestedClasses, + Known, Depth + 1, Q, TLI); + break; + } default: break; } Index: llvm/test/Transforms/Attributor/nofpclass.ll =================================================================== --- llvm/test/Transforms/Attributor/nofpclass.ll +++ llvm/test/Transforms/Attributor/nofpclass.ll @@ -742,3 +742,46 @@ ret float %arg } +define float @returned_extractelement_dynamic_index(<4 x float> nofpclass(nan) %vec, i32 %idx) { +; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) +; CHECK-LABEL: define nofpclass(nan) float @returned_extractelement_dynamic_index +; CHECK-SAME: (<4 x float> nofpclass(nan) [[VEC:%.*]], i32 [[IDX:%.*]]) #[[ATTR2]] { +; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement <4 x float> [[VEC]], i32 [[IDX]] +; CHECK-NEXT: ret float [[EXTRACT]] +; + %extract = extractelement <4 x float> %vec, i32 %idx + ret float %extract +} + +define float @returned_extractelement_index0(<4 x float> nofpclass(nan) %vec) { +; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) +; CHECK-LABEL: define nofpclass(nan) float @returned_extractelement_index0 +; CHECK-SAME: (<4 x float> nofpclass(nan) [[VEC:%.*]]) #[[ATTR2]] { +; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement <4 x float> [[VEC]], i32 0 +; CHECK-NEXT: ret float [[EXTRACT]] +; + %extract = extractelement <4 x float> %vec, i32 0 + ret float %extract +} + +define float @returned_extractelement_scalable( nofpclass(nan) %vec) { +; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) +; CHECK-LABEL: define float @returned_extractelement_scalable +; CHECK-SAME: ( nofpclass(nan) [[VEC:%.*]]) #[[ATTR2]] { +; CHECK-NEXT: [[EXTRACT:%.*]] = extractelement [[VEC]], i32 0 +; CHECK-NEXT: ret float [[EXTRACT]] +; + %extract = extractelement %vec, i32 0 + ret float %extract +} + +define float @returned_extractvalue([4 x float] nofpclass(nan) %array) { +; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) +; CHECK-LABEL: define nofpclass(nan) float @returned_extractvalue +; CHECK-SAME: ([4 x float] nofpclass(nan) [[ARRAY:%.*]]) #[[ATTR2]] { +; CHECK-NEXT: [[EXTRACT:%.*]] = extractvalue [4 x float] [[ARRAY]], 0 +; CHECK-NEXT: ret float [[EXTRACT]] +; + %extract = extractvalue [4 x float] %array, 0 + ret float %extract +}