diff --git a/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp b/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp index 40d0f6b75d69b..06e5187a0c717 100644 --- a/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp +++ b/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp @@ -41,6 +41,7 @@ #include "llvm/IR/Intrinsics.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" +#include "llvm/IR/Operator.h" #include "llvm/IR/Type.h" #include "llvm/IR/User.h" #include "llvm/Support/Casting.h" @@ -1113,6 +1114,17 @@ void PromoteMem2Reg::RenamePass(BasicBlock *BB, BasicBlock *Pred, for (unsigned i = 0; i != NumEdges; ++i) APN->addIncoming(IncomingVals[AllocaNo], Pred); + // For the sequence `return X > 0.0 ? X : -X`, it is expected that this + // results in fabs intrinsic. However, without no-signed-zeros(nsz) flag + // on the phi node generated at this stage, fabs folding does not + // happen. So, we try to infer nsz flag from the function attributes to + // enable this fabs folding. + bool FnHasNSZAttr = APN->getFunction() + ->getFnAttribute("no-signed-zeros-fp-math") + .getValueAsBool(); + if (APN->isComplete() && isa(APN) && FnHasNSZAttr) + APN->setHasNoSignedZeros(true); + // The currently active variable for this block is now the PHI. IncomingVals[AllocaNo] = APN; AllocaATInfo[AllocaNo].updateForNewPhi(APN, DIB); diff --git a/llvm/test/Transforms/SROA/propagate-fast-math-flags-on-phi.ll b/llvm/test/Transforms/SROA/propagate-fast-math-flags-on-phi.ll new file mode 100644 index 0000000000000..6cda8c0d4404a --- /dev/null +++ b/llvm/test/Transforms/SROA/propagate-fast-math-flags-on-phi.ll @@ -0,0 +1,55 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt < %s -passes='sroa' -S | FileCheck %s +define double @phi_with_nsz(double %x) "no-signed-zeros-fp-math"="true" { +; CHECK-LABEL: define double @phi_with_nsz( +; CHECK-SAME: double [[X:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = fcmp olt double [[X]], 0.000000e+00 +; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[RETURN:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[FNEG:%.*]] = fneg double [[X]] +; CHECK-NEXT: br label [[RETURN]] +; CHECK: return: +; CHECK-NEXT: [[X_ADDR_0:%.*]] = phi nsz double [ [[FNEG]], [[IF_THEN]] ], [ undef, [[ENTRY:%.*]] ] +; CHECK-NEXT: ret double [[X_ADDR_0]] +entry: + %x.addr = alloca double + %cmp = fcmp olt double %x, 0.0 + br i1 %cmp, label %if.then, label %return + +if.then: ; preds = %entry + %fneg = fneg double %x + store double %fneg, ptr %x.addr + br label %return + +return: ; preds = %entry,%if.then + %retval = load double, ptr %x.addr + ret double %retval +} + +define double @phi_without_nsz(double %x) "no-signed-zeros-fp-math"="false" { +; CHECK-LABEL: define double @phi_without_nsz( +; CHECK-SAME: double [[X:%.*]]) #[[ATTR1:[0-9]+]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = fcmp olt double [[X]], 0.000000e+00 +; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[RETURN:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[FNEG:%.*]] = fneg double [[X]] +; CHECK-NEXT: br label [[RETURN]] +; CHECK: return: +; CHECK-NEXT: [[X_ADDR_0:%.*]] = phi double [ [[FNEG]], [[IF_THEN]] ], [ undef, [[ENTRY:%.*]] ] +; CHECK-NEXT: ret double [[X_ADDR_0]] +entry: + %x.addr = alloca double + %cmp = fcmp olt double %x, 0.0 + br i1 %cmp, label %if.then, label %return + +if.then: ; preds = %entry + %fneg = fneg double %x + store double %fneg, ptr %x.addr + br label %return + +return: ; preds = %entry,%if.then + %retval = load double, ptr %x.addr + ret double %retval +}