Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions llvm/lib/Transforms/Scalar/FPBuiltinFnSelection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Scalar/FPBuiltinFnSelection.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/CodeGen/Passes.h"
Expand All @@ -20,10 +21,12 @@
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/IntrinsicsNVPTX.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/InitializePasses.h"
#include "llvm/Support/FormatVariadic.h"

using namespace llvm;
using namespace llvm::PatternMatch;

#define DEBUG_TYPE "fpbuiltin-fn-selection"

Expand Down Expand Up @@ -85,9 +88,21 @@ static bool replaceWithLLVMIR(FPBuiltinIntrinsic &BuiltinCall) {
case Intrinsic::fpbuiltin_fmul:
Replacement = IRBuilder.CreateFMul(Args[0], Args[1]);
break;
case Intrinsic::fpbuiltin_fdiv:
Replacement = IRBuilder.CreateFDiv(Args[0], Args[1]);
case Intrinsic::fpbuiltin_fdiv: {
// X / C --> X * (1 / C) when C has an exact FP reciprocal. InstCombine
// already does this for plain fdiv, but by the time this pass lowers
// llvm.fpbuiltin.fdiv to a real fdiv, InstCombine has already run and
// won't see it again, so the fold is replicated here.
Constant *C;
Constant *RecipC = nullptr;
if (match(Args[1], m_Constant(C)) && C->hasExactInverseFP())
RecipC = ConstantFoldBinaryOpOperands(
Instruction::FDiv, ConstantFP::get(BuiltinCall.getType(), 1.0), C,
BuiltinCall.getModule()->getDataLayout());
Replacement = RecipC ? IRBuilder.CreateFMul(Args[0], RecipC)
: IRBuilder.CreateFDiv(Args[0], Args[1]);
break;
}
case Intrinsic::fpbuiltin_frem:
Replacement = IRBuilder.CreateFRem(Args[0], Args[1]);
break;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
; RUN: opt -fpbuiltin-fn-selection -S < %s | FileCheck %s

; llvm.fpbuiltin.fdiv by a constant divisor with an exact FP reciprocal
; should lower to a multiply by the reciprocal, matching what InstCombine
; would do for a plain fdiv (see CMPLRLLVM-77622).

; CHECK-LABEL: @test_fdiv_exact_reciprocal
; CHECK: %{{.*}} = fmul float %x, 2.500000e-01
; CHECK-NOT: fdiv
define float @test_fdiv_exact_reciprocal(float %x) {
entry:
%r = call float @llvm.fpbuiltin.fdiv.f32(float %x, float 4.0) #0
ret float %r
}

; CHECK-LABEL: @test_fdiv_inexact_reciprocal
; CHECK: %{{.*}} = fdiv float %x, 3.000000e+00
define float @test_fdiv_inexact_reciprocal(float %x) {
entry:
%r = call float @llvm.fpbuiltin.fdiv.f32(float %x, float 3.0) #0
ret float %r
}

; CHECK-LABEL: @test_fdiv_nonconstant_divisor
; CHECK: %{{.*}} = fdiv float %x, %y
define float @test_fdiv_nonconstant_divisor(float %x, float %y) {
entry:
%r = call float @llvm.fpbuiltin.fdiv.f32(float %x, float %y) #0
ret float %r
}

declare float @llvm.fpbuiltin.fdiv.f32(float, float)

attributes #0 = { "fpbuiltin-max-error"="2.5" }
Loading