diff options
| author | Jay Foad <jay.foad@gmail.com> | 2019-06-21 14:10:18 +0000 | 
|---|---|---|
| committer | Jay Foad <jay.foad@gmail.com> | 2019-06-21 14:10:18 +0000 | 
| commit | d9d3c91b48c6730c850a24580dab3fe3c1083ee1 (patch) | |
| tree | 4057ef73691bb2e34a662df8c08294d7c0f59d9b | |
| parent | 5b4cc84b87232e67afb63e2bad429b3211b26964 (diff) | |
| download | bcm5719-llvm-d9d3c91b48c6730c850a24580dab3fe3c1083ee1.tar.gz bcm5719-llvm-d9d3c91b48c6730c850a24580dab3fe3c1083ee1.zip  | |
[Scalarizer] Propagate IR flags
Summary:
The motivation for this was to propagate fast-math flags like nnan and
ninf on vector floating point operations to the corresponding scalar
operations to take advantage of follow-on optimizations. But I think
the same argument applies to all of our IR flags: if they apply to the
vector operation then they also apply to all the individual scalar
operations, and they might enable follow-on optimizations.
Subscribers: hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D63593
llvm-svn: 364051
| -rw-r--r-- | llvm/lib/Transforms/Scalar/Scalarizer.cpp | 10 | ||||
| -rw-r--r-- | llvm/test/Transforms/Scalarizer/basic.ll | 53 | 
2 files changed, 59 insertions, 4 deletions
diff --git a/llvm/lib/Transforms/Scalar/Scalarizer.cpp b/llvm/lib/Transforms/Scalar/Scalarizer.cpp index 515a6482773..2ee1a3a95f2 100644 --- a/llvm/lib/Transforms/Scalar/Scalarizer.cpp +++ b/llvm/lib/Transforms/Scalar/Scalarizer.cpp @@ -200,7 +200,7 @@ private:    Scatterer scatter(Instruction *Point, Value *V);    void gather(Instruction *Op, const ValueVector &CV);    bool canTransferMetadata(unsigned Kind); -  void transferMetadata(Instruction *Op, const ValueVector &CV); +  void transferMetadataAndIRFlags(Instruction *Op, const ValueVector &CV);    bool getVectorLayout(Type *Ty, unsigned Alignment, VectorLayout &Layout,                         const DataLayout &DL);    bool finish(); @@ -361,7 +361,7 @@ void ScalarizerVisitor::gather(Instruction *Op, const ValueVector &CV) {    for (unsigned I = 0, E = Op->getNumOperands(); I != E; ++I)      Op->setOperand(I, UndefValue::get(Op->getOperand(I)->getType())); -  transferMetadata(Op, CV); +  transferMetadataAndIRFlags(Op, CV);    // If we already have a scattered form of Op (created from ExtractElements    // of Op itself), replace them with the new form. @@ -397,7 +397,8 @@ bool ScalarizerVisitor::canTransferMetadata(unsigned Tag) {  // Transfer metadata from Op to the instructions in CV if it is known  // to be safe to do so. -void ScalarizerVisitor::transferMetadata(Instruction *Op, const ValueVector &CV) { +void ScalarizerVisitor::transferMetadataAndIRFlags(Instruction *Op, +                                                   const ValueVector &CV) {    SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;    Op->getAllMetadataOtherThanDebugLoc(MDs);    for (unsigned I = 0, E = CV.size(); I != E; ++I) { @@ -405,6 +406,7 @@ void ScalarizerVisitor::transferMetadata(Instruction *Op, const ValueVector &CV)        for (const auto &MD : MDs)          if (canTransferMetadata(MD.first))            New->setMetadata(MD.first, MD.second); +      New->copyIRFlags(Op);        if (Op->getDebugLoc() && !New->getDebugLoc())          New->setDebugLoc(Op->getDebugLoc());      } @@ -809,7 +811,7 @@ bool ScalarizerVisitor::visitStoreInst(StoreInst &SI) {      unsigned Align = Layout.getElemAlign(I);      Stores[I] = Builder.CreateAlignedStore(Val[I], Ptr[I], Align);    } -  transferMetadata(&SI, Stores); +  transferMetadataAndIRFlags(&SI, Stores);    return true;  } diff --git a/llvm/test/Transforms/Scalarizer/basic.ll b/llvm/test/Transforms/Scalarizer/basic.ll index 577f0b19bb1..ba6aa933aa8 100644 --- a/llvm/test/Transforms/Scalarizer/basic.ll +++ b/llvm/test/Transforms/Scalarizer/basic.ll @@ -506,6 +506,59 @@ exit:    ret void  } +; Check that IR flags are preserved. +define <2 x i32> @f16(<2 x i32> %i, <2 x i32> %j) { +; CHECK-LABEL: @f16( +; CHECK: %res.i0 = add nuw nsw i32 +; CHECK: %res.i1 = add nuw nsw i32 +  %res = add nuw nsw <2 x i32> %i, %j +  ret <2 x i32> %res +} +define <2 x i32> @f17(<2 x i32> %i, <2 x i32> %j) { +; CHECK-LABEL: @f17( +; CHECK: %res.i0 = sdiv exact i32 +; CHECK: %res.i1 = sdiv exact i32 +  %res = sdiv exact <2 x i32> %i, %j +  ret <2 x i32> %res +} +define <2 x float> @f18(<2 x float> %x, <2 x float> %y) { +; CHECK-LABEL: @f18( +; CHECK: %res.i0 = fadd fast float +; CHECK: %res.i1 = fadd fast float +  %res = fadd fast <2 x float> %x, %y +  ret <2 x float> %res +} +define <2 x float> @f19(<2 x float> %x) { +; CHECK-LABEL: @f19( +; CHECK: %res.i0 = fneg fast float +; CHECK: %res.i1 = fneg fast float +  %res = fneg fast <2 x float> %x +  ret <2 x float> %res +} +define <2 x i1> @f20(<2 x float> %x, <2 x float> %y) { +; CHECK-LABEL: @f20( +; CHECK: %res.i0 = fcmp fast ogt float +; CHECK: %res.i1 = fcmp fast ogt float +  %res = fcmp fast ogt <2 x float> %x, %y +  ret <2 x i1> %res +} +declare <2 x float> @llvm.sqrt.v2f32(<2 x float>) +define <2 x float> @f21(<2 x float> %x) { +; CHECK-LABEL: @f21( +; CHECK: %res.i0 = call fast float @llvm.sqrt.f32 +; CHECK: %res.i1 = call fast float @llvm.sqrt.f32 +  %res = call fast <2 x float> @llvm.sqrt.v2f32(<2 x float> %x) +  ret <2 x float> %res +} +declare <2 x float> @llvm.fma.v2f32(<2 x float>, <2 x float>, <2 x float>) +define <2 x float> @f22(<2 x float> %x, <2 x float> %y, <2 x float> %z) { +; CHECK-LABEL: @f22( +; CHECK: %res.i0 = call fast float @llvm.fma.f32 +; CHECK: %res.i1 = call fast float @llvm.fma.f32 +  %res = call fast <2 x float> @llvm.fma.v2f32(<2 x float> %x, <2 x float> %y, <2 x float> %z) +  ret <2 x float> %res +} +  !0 = !{ !"root" }  !1 = !{ !"set1", !0 }  !2 = !{ !"set2", !0 }  | 

