Skip to content

Commit 0006184

Browse files
committed
InstSimplify: Simplifications for ldexp
Ported from old amdgcn intrinsic which will soon be deleted. https://reviews.llvm.org/D149587
1 parent ca8d253 commit 0006184

File tree

4 files changed

+569
-8
lines changed

4 files changed

+569
-8
lines changed

llvm/lib/Analysis/ConstantFolding.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1548,6 +1548,7 @@ bool llvm::canConstantFoldCallTo(const CallBase *Call, const Function *F) {
15481548
case Intrinsic::cos:
15491549
case Intrinsic::pow:
15501550
case Intrinsic::powi:
1551+
case Intrinsic::ldexp:
15511552
case Intrinsic::fma:
15521553
case Intrinsic::fmuladd:
15531554
case Intrinsic::frexp:
@@ -2627,6 +2628,11 @@ static Constant *ConstantFoldScalarCall2(StringRef Name,
26272628
}
26282629
} else if (auto *Op2C = dyn_cast<ConstantInt>(Operands[1])) {
26292630
switch (IntrinsicID) {
2631+
case Intrinsic::ldexp: {
2632+
return ConstantFP::get(
2633+
Ty->getContext(),
2634+
scalbn(Op1V, Op2C->getSExtValue(), APFloat::rmNearestTiesToEven));
2635+
}
26302636
case Intrinsic::is_fpclass: {
26312637
FPClassTest Mask = static_cast<FPClassTest>(Op2C->getZExtValue());
26322638
bool Result =

llvm/lib/Analysis/InstructionSimplify.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6094,6 +6094,56 @@ static Value *simplifyRelativeLoad(Constant *Ptr, Constant *Offset,
60946094
return LoadedLHSPtr;
60956095
}
60966096

6097+
// TODO: Need to pass in FastMathFlags
6098+
static Value *simplifyLdexp(Value *Op0, Value *Op1, const SimplifyQuery &Q,
6099+
bool IsStrict) {
6100+
// ldexp(poison, x) -> poison
6101+
// ldexp(x, poison) -> poison
6102+
if (isa<PoisonValue>(Op0) || isa<PoisonValue>(Op1))
6103+
return Op0;
6104+
6105+
// ldexp(undef, x) -> nan
6106+
if (Q.isUndefValue(Op0))
6107+
return ConstantFP::getNaN(Op0->getType());
6108+
6109+
if (!IsStrict) {
6110+
// TODO: Could insert a canonicalize for strict
6111+
6112+
// ldexp(x, undef) -> x
6113+
if (Q.isUndefValue(Op1))
6114+
return Op0;
6115+
}
6116+
6117+
const APFloat *C = nullptr;
6118+
match(Op0, PatternMatch::m_APFloat(C));
6119+
6120+
// These cases should be safe, even with strictfp.
6121+
// ldexp(0.0, x) -> 0.0
6122+
// ldexp(-0.0, x) -> -0.0
6123+
// ldexp(inf, x) -> inf
6124+
// ldexp(-inf, x) -> -inf
6125+
if (C && (C->isZero() || C->isInfinity()))
6126+
return Op0;
6127+
6128+
// These are canonicalization dropping, could do it if we knew how we could
6129+
// ignore denormal flushes and target handling of nan payload bits.
6130+
if (IsStrict)
6131+
return nullptr;
6132+
6133+
// TODO: Could quiet this with strictfp if the exception mode isn't strict.
6134+
if (C && C->isNaN())
6135+
return ConstantFP::get(Op0->getType(), C->makeQuiet());
6136+
6137+
// ldexp(x, 0) -> x
6138+
6139+
// TODO: Could fold this if we know the exception mode isn't
6140+
// strict, we know the denormal mode and other target modes.
6141+
if (match(Op1, PatternMatch::m_ZeroInt()))
6142+
return Op0;
6143+
6144+
return nullptr;
6145+
}
6146+
60976147
static Value *simplifyUnaryIntrinsic(Function *F, Value *Op0,
60986148
const SimplifyQuery &Q) {
60996149
// Idempotent functions return the same result when called repeatedly.
@@ -6446,6 +6496,8 @@ static Value *simplifyBinaryIntrinsic(Function *F, Value *Op0, Value *Op1,
64466496
return Op0;
64476497
}
64486498
break;
6499+
case Intrinsic::ldexp:
6500+
return simplifyLdexp(Op0, Op1, Q, false);
64496501
case Intrinsic::copysign:
64506502
// copysign X, X --> X
64516503
if (Op0 == Op1)
@@ -6709,6 +6761,8 @@ static Value *simplifyIntrinsic(CallBase *Call, Value *Callee,
67096761
*FPI->getExceptionBehavior(),
67106762
*FPI->getRoundingMode());
67116763
}
6764+
case Intrinsic::experimental_constrained_ldexp:
6765+
return simplifyLdexp(Args[0], Args[1], Q, true);
67126766
default:
67136767
return nullptr;
67146768
}

llvm/test/Transforms/InstCombine/ldexp.ll

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -488,8 +488,7 @@ define float @ldexp_ldexp_constants_nsz1(float %x) {
488488
define float @ldexp_ldexp_opposite_constants(float %x) {
489489
; CHECK-LABEL: define float @ldexp_ldexp_opposite_constants
490490
; CHECK-SAME: (float [[X:%.*]]) {
491-
; CHECK-NEXT: [[LDEXP1:%.*]] = call reassoc float @llvm.ldexp.f32.i32(float [[X]], i32 0)
492-
; CHECK-NEXT: ret float [[LDEXP1]]
491+
; CHECK-NEXT: ret float [[X]]
493492
;
494493
%ldexp0 = call reassoc float @llvm.ldexp.f32.i32(float %x, i32 8)
495494
%ldexp1 = call reassoc float @llvm.ldexp.f32.i32(float %ldexp0, i32 -8)
@@ -499,8 +498,7 @@ define float @ldexp_ldexp_opposite_constants(float %x) {
499498
define float @ldexp_ldexp_negated_variable_reassoc(float %x, i32 %a) {
500499
; CHECK-LABEL: define float @ldexp_ldexp_negated_variable_reassoc
501500
; CHECK-SAME: (float [[X:%.*]], i32 [[A:%.*]]) {
502-
; CHECK-NEXT: [[LDEXP1:%.*]] = call reassoc float @llvm.ldexp.f32.i32(float [[X]], i32 0)
503-
; CHECK-NEXT: ret float [[LDEXP1]]
501+
; CHECK-NEXT: ret float [[X]]
504502
;
505503
%ldexp0 = call reassoc float @llvm.ldexp.f32.i32(float %x, i32 %a)
506504
%neg.a = sub i32 0, %a
@@ -628,8 +626,7 @@ define float @ldexp_reassoc_ldexp_reassoc_0(float %x, i32 %y) {
628626
define float @ldexp_ldexp_0(float %x, i32 %y) {
629627
; CHECK-LABEL: define float @ldexp_ldexp_0
630628
; CHECK-SAME: (float [[X:%.*]], i32 [[Y:%.*]]) {
631-
; CHECK-NEXT: [[LDEXP0:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 0)
632-
; CHECK-NEXT: [[LDEXP1:%.*]] = call float @llvm.ldexp.f32.i32(float [[LDEXP0]], i32 [[Y]])
629+
; CHECK-NEXT: [[LDEXP1:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 [[Y]])
633630
; CHECK-NEXT: ret float [[LDEXP1]]
634631
;
635632
%ldexp0 = call float @llvm.ldexp.f32.i32(float %x, i32 0)
@@ -754,8 +751,7 @@ define float @ldexp_neg1(float %x) {
754751
define float @ldexp_0(float %x) {
755752
; CHECK-LABEL: define float @ldexp_0
756753
; CHECK-SAME: (float [[X:%.*]]) {
757-
; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 0)
758-
; CHECK-NEXT: ret float [[LDEXP]]
754+
; CHECK-NEXT: ret float [[X]]
759755
;
760756
%ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 0)
761757
ret float %ldexp

0 commit comments

Comments
 (0)