Skip to content

Commit

Permalink
Ashton Wiersdorf: optimize that the range of x*x is positive for floa…
Browse files Browse the repository at this point in the history
…ts (llvm#44)

* First draft of optimization for x^2 + c₁ >= c₂

Optimize x^2 + c₁ >= c₂ → True whenever c₁ >= c₂

* WIP refactoring

* Update logic

Still not working—seems to be a wraparound issue

* Convert optimization to floating point; seems to work

* Fix bug; add test

* Wrap optimization in {} to keep variables scoped easily

* Fix whitespace change
  • Loading branch information
ashton314 authored Sep 10, 2024
1 parent 426f051 commit 42044da
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 0 deletions.
86 changes: 86 additions & 0 deletions llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5159,6 +5159,92 @@ Instruction* cs6475_optimizer(Instruction *I, InstCombinerImpl &IC, LazyValueInf
}
// END JOHN REGEHR

// BEGIN ASHTON WIERSDORF
// x : float; c1, c2 are literal constants
// x * x + c1 > c2 && c1 > c2 ⇒ is_nan(x)
// x * x + c1 < c2 && c1 > c2 ⇒ false
{
ConstantFP *C1 = nullptr;
ConstantFP *C2 = nullptr;
CmpInst::Predicate Pred;
Value *X1 = nullptr;
Value *X2 = nullptr;

if (match(I,
m_FCmp(Pred, m_FAdd(m_FMul(m_Value(X1), m_Value(X2)),
m_ConstantFP(C1)), m_ConstantFP(C2)))) {

if (match(X1, m_Specific(X2))) {
bool Decidable = false;
bool TheConst = false;
APFloatBase::cmpResult Ord = C1->getValue().compare(C2->getValue());

switch(Pred) {
case CmpInst::FCMP_OGT: // x*x + c1 > c2 ⇒ true if c1 > c2
switch (Ord) {
case APFloatBase::cmpResult::cmpGreaterThan:
Decidable = true;
TheConst = true;
break;
default:
Decidable = false;
}
break;
case CmpInst::FCMP_OGE: // x*x + c1 ≥ c2 ⇒ true if c1 ≥ c2
switch (Ord) {
case APFloatBase::cmpResult::cmpEqual:
case APFloatBase::cmpResult::cmpGreaterThan:
Decidable = true;
TheConst = true;
break;
default:
Decidable = false;
}
break;
case CmpInst::FCMP_OLT: // x*x + c1 < c2 ⇒ false if c1 ≥ c2
switch (Ord) {
case APFloatBase::cmpResult::cmpEqual:
case APFloatBase::cmpResult::cmpGreaterThan:
Decidable = true;
TheConst = false;
break;
default:
Decidable = false;
}
break;
case CmpInst::FCMP_OLE: // x*x + c1 ≤ c2 ⇒ false if c1 > c2
switch (Ord) {
case APFloatBase::cmpResult::cmpGreaterThan:
Decidable = true;
TheConst = false;
break;
default:
Decidable = false;
}
break;
default:
Decidable = false;
}

if (Decidable) {
log_optzn("Ashton Wiersdorf");
if (TheConst) {
// We only know that this might be true if x*x isn't NaN, so
// we generate code that checks if x = x; if x is NaN, x = x
// returns false, which matches what the original expression
// would return.
return new FCmpInst(FCmpInst::FCMP_OEQ, X1, X1);
}
// In this case, we know that the condition will always return
// false, even if x is Nan.
Value *LiteralTrue = ConstantInt::getTrue(I->getContext());
return new ICmpInst(ICmpInst::ICMP_NE, LiteralTrue, LiteralTrue);
}
}
}
}
// END ASHTON WIERSDORF

//BEGIN ZEYUAN WANG
{
// x*(x+2) + 1 -> (x+1)*(x+1)
Expand Down
41 changes: 41 additions & 0 deletions llvm/test/Transforms/InstCombine/square_positive.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
; RUN: opt < %s -passes=instcombine -S | FileCheck %s

; positive tests
; x * x + c1 > c2 where c1 > c2 => isnan(x)
define i32 @t1(float %x) {
%1 = fmul float %x, %x
%2 = fadd float %1, 77.0e+00
%3 = fcmp ogt float %2, 22.0e+00
%4 = select i1 %3, i32 1, i32 2
ret i32 %4
; CHECK-LABEL: @t1(
; CHECK: [[r1:%.*]] = fcmp ord float %x, 0.000000e+00
; CHECK-NEXT: [[r2:%.*]] = select i1 [[r1]], i32 1, i32 2
; CHECK-NEXT: ret i32 [[r2]]
}

; x * x + c1 < c2 where c1 > c2 => false
define i32 @t2(float %x) {
%1 = fmul float %x, %x
%2 = fadd float %1, 77.0e+00
%3 = fcmp olt float %2, 22.0e+00
%4 = select i1 %3, i32 1, i32 2
ret i32 %4
; CHECK-LABEL: @t2(
; CHECK-NEXT: ret i32 2
}

; negative test
; x * x + c1 > c2 where c1 < c2 => no optimization
define i32 @t3(float %x) {
%1 = fmul float %x, %x
%2 = fadd float %1, 22.0e+00
%3 = fcmp ogt float %2, 77.0e+00
%4 = select i1 %3, i32 1, i32 2
ret i32 %4
; CHECK-LABEL: @t3(
; CHECK-NOT: [[r0:%.*]] = fcmp ord float %x, 0.000000e+00
; CHECK: [[r1:%.*]] = fcmp ogt float %2, 7.700000e+01
; CHECK-NEXT: [[r2:%.*]] = select i1 [[r1]], i32 1, i32 2
; CHECK-NEXT: ret i32 [[r2]]
}

0 comments on commit 42044da

Please sign in to comment.