Index: lib/Transforms/InstCombine/InstCombine.h =================================================================== --- lib/Transforms/InstCombine/InstCombine.h +++ lib/Transforms/InstCombine/InstCombine.h @@ -35,8 +35,8 @@ enum SelectPatternFlavor { SPF_UNKNOWN = 0, SPF_SMIN, SPF_UMIN, - SPF_SMAX, SPF_UMAX - //SPF_ABS - TODO. + SPF_SMAX, SPF_UMAX, + SPF_ABS }; /// getComplexity: Assign a complexity or rank value to LLVM Values... Index: lib/Transforms/InstCombine/InstCombineSelect.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineSelect.cpp +++ lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -31,13 +31,18 @@ ICmpInst *ICI = dyn_cast(SI->getCondition()); if (!ICI) return SPF_UNKNOWN; - LHS = ICI->getOperand(0); - RHS = ICI->getOperand(1); + ICmpInst::Predicate Pred = ICI->getPredicate(); + Value *CmpLHS = ICI->getOperand(0); + Value *CmpRHS = ICI->getOperand(1); + Value *TrueVal = SI->getTrueValue(); + Value *FalseVal = SI->getFalseValue(); + + LHS = CmpLHS; + RHS = CmpRHS; // (icmp X, Y) ? X : Y - if (SI->getTrueValue() == ICI->getOperand(0) && - SI->getFalseValue() == ICI->getOperand(1)) { - switch (ICI->getPredicate()) { + if (TrueVal == CmpLHS && FalseVal == CmpRHS) { + switch (Pred) { default: return SPF_UNKNOWN; // Equality. case ICmpInst::ICMP_UGT: case ICmpInst::ICMP_UGE: return SPF_UMAX; @@ -51,18 +56,30 @@ } // (icmp X, Y) ? Y : X - if (SI->getTrueValue() == ICI->getOperand(1) && - SI->getFalseValue() == ICI->getOperand(0)) { - switch (ICI->getPredicate()) { - default: return SPF_UNKNOWN; // Equality. + if (TrueVal == CmpRHS && FalseVal == CmpLHS) { + switch (Pred) { + default: return SPF_UNKNOWN; // Equality. + case ICmpInst::ICMP_UGT: + case ICmpInst::ICMP_UGE: return SPF_UMIN; + case ICmpInst::ICMP_SGT: + case ICmpInst::ICMP_SGE: return SPF_SMIN; + case ICmpInst::ICMP_ULT: + case ICmpInst::ICMP_ULE: return SPF_UMAX; + case ICmpInst::ICMP_SLT: + case ICmpInst::ICMP_SLE: return SPF_SMAX; + } + } + + // (X > -1) ? X : -X + if (ConstantInt *C1 = dyn_cast(CmpRHS)) { + if (C1->isMinusOne() && CmpLHS == TrueVal && + (match(TrueVal, m_Neg(m_Specific(FalseVal))) || + match(FalseVal, m_Neg(m_Specific(TrueVal))))) { + switch (Pred) { + default: return SPF_UNKNOWN; case ICmpInst::ICMP_UGT: - case ICmpInst::ICMP_UGE: return SPF_UMIN; - case ICmpInst::ICMP_SGT: - case ICmpInst::ICMP_SGE: return SPF_SMIN; - case ICmpInst::ICMP_ULT: - case ICmpInst::ICMP_ULE: return SPF_UMAX; - case ICmpInst::ICMP_SLT: - case ICmpInst::ICMP_SLE: return SPF_SMAX; + case ICmpInst::ICMP_SGT: return SPF_ABS; + } } } @@ -71,7 +88,6 @@ return SPF_UNKNOWN; } - /// GetSelectFoldableOperands - We want to turn code that looks like this: /// %C = or %A, %B /// %D = select %cond, %C, %A @@ -652,6 +668,11 @@ } // TODO: MIN(MIN(A, 23), 97) + + // ABS(ABS(X)) -> ABS(X) + if (SPF1 == SPF_ABS && SPF2 == SPF_ABS) + return ReplaceInstUsesWith(Outer, Inner); + return nullptr; } @@ -957,7 +978,6 @@ // TODO. // ABS(-X) -> ABS(X) - // ABS(ABS(X)) -> ABS(X) } // See if we can fold the select into a phi node if the condition is a select. Index: test/Transforms/InstCombine/select.ll =================================================================== --- test/Transforms/InstCombine/select.ll +++ test/Transforms/InstCombine/select.ll @@ -1031,3 +1031,17 @@ ; CHECK: lshr exact i32 %2, 1 ; CHECK: xor i32 %3, 42 } + +; ABS(ABS(X)) -> ABS(X) +define i32 @abs(i32 %x) { +entry: + %sub = sub nsw i32 0, %x + %ispos = icmp sgt i32 %sub, -1 + %0 = select i1 %ispos, i32 %sub, i32 %x + %ispos2 = icmp sgt i32 %0, -1 + %neg3 = sub i32 0, %0 + %1 = select i1 %ispos2, i32 %0, i32 %neg3 + ret i32 %1 +; CHECK-LABEL: @abs( +; CHECK: ret i32 %0 +} \ No newline at end of file