Skip to content

Commit b9dbe77

Browse files
committed
[InstSimplify] Simplify fcmp implied by dominating fcmp
1 parent 85c59b2 commit b9dbe77

File tree

5 files changed

+102
-26
lines changed

5 files changed

+102
-26
lines changed

llvm/lib/Analysis/InstructionSimplify.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4164,6 +4164,10 @@ static Value *simplifyFCmpInst(CmpPredicate Pred, Value *LHS, Value *RHS,
41644164
return ConstantInt::get(RetTy, Pred == CmpInst::FCMP_UNO);
41654165
}
41664166

4167+
if (std::optional<bool> Res =
4168+
isImpliedByDomCondition(Pred, LHS, RHS, Q.CxtI, Q.DL))
4169+
return ConstantInt::getBool(RetTy, *Res);
4170+
41674171
const APFloat *C = nullptr;
41684172
match(RHS, m_APFloatAllowPoison(C));
41694173
std::optional<KnownFPClass> FullKnownClassLHS;

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 89 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "llvm/IR/Attributes.h"
4040
#include "llvm/IR/BasicBlock.h"
4141
#include "llvm/IR/Constant.h"
42+
#include "llvm/IR/ConstantFPRange.h"
4243
#include "llvm/IR/ConstantRange.h"
4344
#include "llvm/IR/Constants.h"
4445
#include "llvm/IR/DerivedTypes.h"
@@ -9447,6 +9448,69 @@ isImpliedCondICmps(CmpPredicate LPred, const Value *L0, const Value *L1,
94479448
return std::nullopt;
94489449
}
94499450

9451+
/// Return true if LHS implies RHS (expanded to its components as "R0 RPred R1")
9452+
/// is true. Return false if LHS implies RHS is false. Otherwise, return
9453+
/// std::nullopt if we can't infer anything.
9454+
static std::optional<bool>
9455+
isImpliedCondFCmps(FCmpInst::Predicate LPred, const Value *L0, const Value *L1,
9456+
FCmpInst::Predicate RPred, const Value *R0, const Value *R1,
9457+
const DataLayout &DL, bool LHSIsTrue) {
9458+
// The rest of the logic assumes the LHS condition is true. If that's not the
9459+
// case, invert the predicate to make it so.
9460+
if (!LHSIsTrue)
9461+
LPred = FCmpInst::getInversePredicate(LPred);
9462+
9463+
// We can have non-canonical operands, so try to normalize any common operand
9464+
// to L0/R0.
9465+
if (L0 == R1) {
9466+
std::swap(R0, R1);
9467+
RPred = FCmpInst::getSwappedPredicate(RPred);
9468+
}
9469+
if (R0 == L1) {
9470+
std::swap(L0, L1);
9471+
LPred = FCmpInst::getSwappedPredicate(LPred);
9472+
}
9473+
if (L1 == R1) {
9474+
// If we have L0 == R0 and L1 == R1, then make L1/R1 the constants.
9475+
if (L0 != R0 || match(L0, m_ImmConstant())) {
9476+
std::swap(L0, L1);
9477+
LPred = ICmpInst::getSwappedCmpPredicate(LPred);
9478+
std::swap(R0, R1);
9479+
RPred = ICmpInst::getSwappedCmpPredicate(RPred);
9480+
}
9481+
}
9482+
9483+
// Can we infer anything when the two compares have matching operands?
9484+
if (L0 == R0 && L1 == R1) {
9485+
if ((LPred & RPred) == LPred)
9486+
return true;
9487+
if ((LPred & ~RPred) == LPred)
9488+
return false;
9489+
}
9490+
9491+
// See if we can infer anything if operand-0 matches and we have at least one
9492+
// constant.
9493+
const APFloat *L1C, *R1C;
9494+
if (L0 == R0 && match(L1, m_APFloat(L1C)) && match(R1, m_APFloat(R1C))) {
9495+
if (std::optional<ConstantFPRange> DomCR =
9496+
ConstantFPRange::makeExactFCmpRegion(LPred, *L1C)) {
9497+
if (std::optional<ConstantFPRange> ImpliedCR =
9498+
ConstantFPRange::makeExactFCmpRegion(RPred, *R1C)) {
9499+
if (ImpliedCR->contains(*DomCR))
9500+
return true;
9501+
}
9502+
if (std::optional<ConstantFPRange> ImpliedCR =
9503+
ConstantFPRange::makeExactFCmpRegion(
9504+
FCmpInst::getInversePredicate(RPred), *R1C)) {
9505+
if (ImpliedCR->contains(*DomCR))
9506+
return false;
9507+
}
9508+
}
9509+
}
9510+
9511+
return std::nullopt;
9512+
}
9513+
94509514
/// Return true if LHS implies RHS is true. Return false if LHS implies RHS is
94519515
/// false. Otherwise, return std::nullopt if we can't infer anything. We
94529516
/// expect the RHS to be an icmp and the LHS to be an 'and', 'or', or a 'select'
@@ -9502,15 +9566,24 @@ llvm::isImpliedCondition(const Value *LHS, CmpPredicate RHSPred,
95029566
LHSIsTrue = !LHSIsTrue;
95039567

95049568
// Both LHS and RHS are icmps.
9505-
if (const auto *LHSCmp = dyn_cast<ICmpInst>(LHS))
9506-
return isImpliedCondICmps(LHSCmp->getCmpPredicate(), LHSCmp->getOperand(0),
9507-
LHSCmp->getOperand(1), RHSPred, RHSOp0, RHSOp1,
9508-
DL, LHSIsTrue);
9509-
const Value *V;
9510-
if (match(LHS, m_NUWTrunc(m_Value(V))))
9511-
return isImpliedCondICmps(CmpInst::ICMP_NE, V,
9512-
ConstantInt::get(V->getType(), 0), RHSPred,
9513-
RHSOp0, RHSOp1, DL, LHSIsTrue);
9569+
if (RHSOp0->getType()->getScalarType()->isIntOrPtrTy()) {
9570+
if (const auto *LHSCmp = dyn_cast<ICmpInst>(LHS))
9571+
return isImpliedCondICmps(LHSCmp->getCmpPredicate(),
9572+
LHSCmp->getOperand(0), LHSCmp->getOperand(1),
9573+
RHSPred, RHSOp0, RHSOp1, DL, LHSIsTrue);
9574+
const Value *V;
9575+
if (match(LHS, m_NUWTrunc(m_Value(V))))
9576+
return isImpliedCondICmps(CmpInst::ICMP_NE, V,
9577+
ConstantInt::get(V->getType(), 0), RHSPred,
9578+
RHSOp0, RHSOp1, DL, LHSIsTrue);
9579+
} else {
9580+
assert(RHSOp0->getType()->isFPOrFPVectorTy() &&
9581+
"Expected floating point type only!");
9582+
if (const auto *LHSCmp = dyn_cast<FCmpInst>(LHS))
9583+
return isImpliedCondFCmps(LHSCmp->getPredicate(), LHSCmp->getOperand(0),
9584+
LHSCmp->getOperand(1), RHSPred, RHSOp0, RHSOp1,
9585+
DL, LHSIsTrue);
9586+
}
95149587

95159588
/// The LHS should be an 'or', 'and', or a 'select' instruction. We expect
95169589
/// the RHS to be an icmp.
@@ -9547,6 +9620,13 @@ std::optional<bool> llvm::isImpliedCondition(const Value *LHS, const Value *RHS,
95479620
return InvertRHS ? !*Implied : *Implied;
95489621
return std::nullopt;
95499622
}
9623+
if (const FCmpInst *RHSCmp = dyn_cast<FCmpInst>(RHS)) {
9624+
if (auto Implied = isImpliedCondition(
9625+
LHS, RHSCmp->getPredicate(), RHSCmp->getOperand(0),
9626+
RHSCmp->getOperand(1), DL, LHSIsTrue, Depth))
9627+
return InvertRHS ? !*Implied : *Implied;
9628+
return std::nullopt;
9629+
}
95509630

95519631
const Value *V;
95529632
if (match(RHS, m_NUWTrunc(m_Value(V)))) {

llvm/test/CodeGen/AMDGPU/sgpr-copy.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ endif: ; preds = %else, %if
256256
define amdgpu_kernel void @copy1(ptr addrspace(1) %out, ptr addrspace(1) %in0) {
257257
entry:
258258
%tmp = load float, ptr addrspace(1) %in0
259-
%tmp1 = fcmp oeq float %tmp, 0.000000e+00
259+
%tmp1 = fcmp one float %tmp, 0.000000e+00
260260
br i1 %tmp1, label %if0, label %endif
261261

262262
if0: ; preds = %entry

llvm/test/Transforms/InstCombine/clamp-to-minmax.ll

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -172,10 +172,8 @@ define float @clamp_negative_wrong_const(float %x) {
172172
; Like @clamp_test_1 but both are min
173173
define float @clamp_negative_same_op(float %x) {
174174
; CHECK-LABEL: @clamp_negative_same_op(
175-
; CHECK-NEXT: [[INNER_CMP_INV:%.*]] = fcmp fast oge float [[X:%.*]], 2.550000e+02
176-
; CHECK-NEXT: [[INNER_SEL:%.*]] = select nnan ninf i1 [[INNER_CMP_INV]], float 2.550000e+02, float [[X]]
177-
; CHECK-NEXT: [[OUTER_CMP:%.*]] = fcmp fast ult float [[X]], 1.000000e+00
178-
; CHECK-NEXT: [[R:%.*]] = select i1 [[OUTER_CMP]], float [[INNER_SEL]], float 1.000000e+00
175+
; CHECK-NEXT: [[OUTER_CMP_INV:%.*]] = fcmp fast oge float [[X:%.*]], 1.000000e+00
176+
; CHECK-NEXT: [[R:%.*]] = select nnan ninf i1 [[OUTER_CMP_INV]], float 1.000000e+00, float [[X]]
179177
; CHECK-NEXT: ret float [[R]]
180178
;
181179
%inner_cmp = fcmp fast ult float %x, 255.0

llvm/test/Transforms/InstSimplify/domcondition.ll

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -285,8 +285,7 @@ define i1 @simplify_fcmp_implied_by_dom_cond_range_true(float %x) {
285285
; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[X:%.*]], 0.000000e+00
286286
; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
287287
; CHECK: if.then:
288-
; CHECK-NEXT: [[CMP2:%.*]] = fcmp olt float [[X]], 1.000000e+00
289-
; CHECK-NEXT: ret i1 [[CMP2]]
288+
; CHECK-NEXT: ret i1 true
290289
; CHECK: if.else:
291290
; CHECK-NEXT: ret i1 false
292291
;
@@ -308,8 +307,7 @@ define i1 @simplify_fcmp_in_else_implied_by_dom_cond_range_true(float %x) {
308307
; CHECK: if.then:
309308
; CHECK-NEXT: ret i1 true
310309
; CHECK: if.else:
311-
; CHECK-NEXT: [[CMP2:%.*]] = fcmp uge float [[X]], 5.000000e-01
312-
; CHECK-NEXT: ret i1 [[CMP2]]
310+
; CHECK-NEXT: ret i1 true
313311
;
314312
%cmp = fcmp olt float %x, 1.0
315313
br i1 %cmp, label %if.then, label %if.else
@@ -327,8 +325,7 @@ define i1 @simplify_fcmp_implied_by_dom_cond_range_false(float %x) {
327325
; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[X:%.*]], 0.000000e+00
328326
; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
329327
; CHECK: if.then:
330-
; CHECK-NEXT: [[CMP2:%.*]] = fcmp ogt float [[X]], 1.000000e+00
331-
; CHECK-NEXT: ret i1 [[CMP2]]
328+
; CHECK-NEXT: ret i1 false
332329
; CHECK: if.else:
333330
; CHECK-NEXT: ret i1 false
334331
;
@@ -348,8 +345,7 @@ define i1 @simplify_fcmp_implied_by_dom_cond_pred_true(float %x, float %y) {
348345
; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[X:%.*]], [[Y:%.*]]
349346
; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
350347
; CHECK: if.then:
351-
; CHECK-NEXT: [[CMP2:%.*]] = fcmp ole float [[X]], [[Y]]
352-
; CHECK-NEXT: ret i1 [[CMP2]]
348+
; CHECK-NEXT: ret i1 true
353349
; CHECK: if.else:
354350
; CHECK-NEXT: ret i1 false
355351
;
@@ -369,8 +365,7 @@ define i1 @simplify_fcmp_implied_by_dom_cond_pred_false(float %x, float %y) {
369365
; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[X:%.*]], [[Y:%.*]]
370366
; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
371367
; CHECK: if.then:
372-
; CHECK-NEXT: [[CMP2:%.*]] = fcmp ogt float [[X]], [[Y]]
373-
; CHECK-NEXT: ret i1 [[CMP2]]
368+
; CHECK-NEXT: ret i1 false
374369
; CHECK: if.else:
375370
; CHECK-NEXT: ret i1 false
376371
;
@@ -390,8 +385,7 @@ define i1 @simplify_fcmp_implied_by_dom_cond_pred_commuted(float %x, float %y) {
390385
; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[X:%.*]], [[Y:%.*]]
391386
; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
392387
; CHECK: if.then:
393-
; CHECK-NEXT: [[CMP2:%.*]] = fcmp oge float [[Y]], [[X]]
394-
; CHECK-NEXT: ret i1 [[CMP2]]
388+
; CHECK-NEXT: ret i1 true
395389
; CHECK: if.else:
396390
; CHECK-NEXT: ret i1 false
397391
;

0 commit comments

Comments
 (0)