mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-22 04:22:57 +02:00
[InstCombine] partly fix FMF for fmul+log2 fold
The code was checking that all of the instructions in the sequence are 'fast', but that's not necessary. The final multiply is all that we need to check (tests adjusted). The fmul doesn't need to be fully 'fast' either, but that can be another patch. llvm-svn: 326608
This commit is contained in:
parent
3d24154888
commit
c1a07635a1
@ -447,35 +447,6 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) {
|
||||
return Changed ? &I : nullptr;
|
||||
}
|
||||
|
||||
/// Detect pattern log2(Y * 0.5) with corresponding fast math flags.
|
||||
static void detectLog2OfHalf(Value *&Op, Value *&Y, IntrinsicInst *&Log2) {
|
||||
if (!Op->hasOneUse())
|
||||
return;
|
||||
|
||||
IntrinsicInst *II = dyn_cast<IntrinsicInst>(Op);
|
||||
if (!II)
|
||||
return;
|
||||
if (II->getIntrinsicID() != Intrinsic::log2 || !II->isFast())
|
||||
return;
|
||||
Log2 = II;
|
||||
|
||||
Value *OpLog2Of = II->getArgOperand(0);
|
||||
if (!OpLog2Of->hasOneUse())
|
||||
return;
|
||||
|
||||
Instruction *I = dyn_cast<Instruction>(OpLog2Of);
|
||||
if (!I)
|
||||
return;
|
||||
|
||||
if (I->getOpcode() != Instruction::FMul || !I->isFast())
|
||||
return;
|
||||
|
||||
if (match(I->getOperand(0), m_SpecificFP(0.5)))
|
||||
Y = I->getOperand(1);
|
||||
else if (match(I->getOperand(1), m_SpecificFP(0.5)))
|
||||
Y = I->getOperand(0);
|
||||
}
|
||||
|
||||
/// Helper function of InstCombiner::visitFMul(). Return true iff the given
|
||||
/// value is FMul or FDiv with one and only one operand being a finite-non-zero
|
||||
/// constant (i.e. not Zero/NaN/Infinity).
|
||||
@ -617,30 +588,24 @@ Instruction *InstCombiner::visitFMul(BinaryOperator &I) {
|
||||
if (Op0 == Op1 && match(Op0, m_Intrinsic<Intrinsic::fabs>(m_Value(X))))
|
||||
return BinaryOperator::CreateFMulFMF(X, X, &I);
|
||||
|
||||
// Under unsafe algebra do:
|
||||
// X * log2(0.5*Y) = X*log2(Y) - X
|
||||
if (AllowReassociate) {
|
||||
Value *OpX = nullptr;
|
||||
Value *OpY = nullptr;
|
||||
IntrinsicInst *Log2;
|
||||
detectLog2OfHalf(Op0, OpY, Log2);
|
||||
if (OpY) {
|
||||
OpX = Op1;
|
||||
} else {
|
||||
detectLog2OfHalf(Op1, OpY, Log2);
|
||||
if (OpY) {
|
||||
OpX = Op0;
|
||||
}
|
||||
// log2(X * 0.5) * Y = log2(X) * Y - Y
|
||||
if (I.isFast()) {
|
||||
IntrinsicInst *Log2 = nullptr;
|
||||
if (match(Op0, m_OneUse(m_Intrinsic<Intrinsic::log2>(
|
||||
m_OneUse(m_FMul(m_Value(X), m_SpecificFP(0.5))))))) {
|
||||
Log2 = cast<IntrinsicInst>(Op0);
|
||||
Y = Op1;
|
||||
}
|
||||
// if pattern detected emit alternate sequence
|
||||
if (OpX && OpY) {
|
||||
BuilderTy::FastMathFlagGuard Guard(Builder);
|
||||
Builder.setFastMathFlags(Log2->getFastMathFlags());
|
||||
Log2->setArgOperand(0, OpY);
|
||||
Value *FMulVal = Builder.CreateFMul(OpX, Log2);
|
||||
Value *FSub = Builder.CreateFSub(FMulVal, OpX);
|
||||
FSub->takeName(&I);
|
||||
return replaceInstUsesWith(I, FSub);
|
||||
if (match(Op1, m_OneUse(m_Intrinsic<Intrinsic::log2>(
|
||||
m_OneUse(m_FMul(m_Value(X), m_SpecificFP(0.5))))))) {
|
||||
Log2 = cast<IntrinsicInst>(Op1);
|
||||
Y = Op0;
|
||||
}
|
||||
if (Log2) {
|
||||
Log2->setArgOperand(0, X);
|
||||
Log2->copyFastMathFlags(&I);
|
||||
Value *LogXTimesY = Builder.CreateFMulFMF(Log2, Y, &I);
|
||||
return BinaryOperator::CreateFSubFMF(LogXTimesY, Y, &I);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -302,7 +302,7 @@ define float @reassoc_common_operand_multi_use(float %x, float %y) {
|
||||
|
||||
declare float @llvm.log2.f32(float)
|
||||
|
||||
; X * log2(Y * 0.5) = X * log2(Y) - X
|
||||
; log2(Y * 0.5) * X = log2(Y) * X - X
|
||||
|
||||
define float @log2half(float %x, float %y) {
|
||||
; CHECK-LABEL: @log2half(
|
||||
@ -311,8 +311,8 @@ define float @log2half(float %x, float %y) {
|
||||
; CHECK-NEXT: [[MUL:%.*]] = fsub fast float [[TMP1]], [[X]]
|
||||
; CHECK-NEXT: ret float [[MUL]]
|
||||
;
|
||||
%halfy = fmul fast float %y, 0.5
|
||||
%log2 = call fast float @llvm.log2.f32(float %halfy)
|
||||
%halfy = fmul float %y, 0.5
|
||||
%log2 = call float @llvm.log2.f32(float %halfy)
|
||||
%mul = fmul fast float %log2, %x
|
||||
ret float %mul
|
||||
}
|
||||
@ -321,13 +321,13 @@ define float @log2half_commute(float %x1, float %y) {
|
||||
; CHECK-LABEL: @log2half_commute(
|
||||
; CHECK-NEXT: [[X:%.*]] = fdiv float [[X1:%.*]], 7.000000e+00
|
||||
; CHECK-NEXT: [[LOG2:%.*]] = call fast float @llvm.log2.f32(float [[Y:%.*]])
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = fmul fast float [[X]], [[LOG2]]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = fmul fast float [[LOG2]], [[X]]
|
||||
; CHECK-NEXT: [[MUL:%.*]] = fsub fast float [[TMP1]], [[X]]
|
||||
; CHECK-NEXT: ret float [[MUL]]
|
||||
;
|
||||
%x = fdiv float %x1, 7.0 ; thwart complexity-based canonicalization
|
||||
%halfy = fmul fast float %y, 0.5
|
||||
%log2 = call fast float @llvm.log2.f32(float %halfy)
|
||||
%halfy = fmul float %y, 0.5
|
||||
%log2 = call float @llvm.log2.f32(float %halfy)
|
||||
%mul = fmul fast float %x, %log2
|
||||
ret float %mul
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user