-
Notifications
You must be signed in to change notification settings - Fork 11.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[InstCombine] Fold overflow bit of [u|s]mul.with.overflow in a poison…
…-safe way As discussed in D101191, this patch adds a poison-safe folding of overflow bit check: ``` %Op0 = icmp ne i4 %X, 0 %Agg = call { i4, i1 } @llvm.[us]mul.with.overflow.i4(i4 %X, i4 %Y) %Op1 = extractvalue { i4, i1 } %Agg, 1 %ret = select i1 %Op0, i1 %Op1, i1 false => %Y.fr = freeze %Y %Agg = call { i4, i1 } @llvm.[us]mul.with.overflow.i4(i4 %X, i4 %Y.fr) %Op1 = extractvalue { i4, i1 } %Agg, 1 %ret = %Op1 ``` https://alive2.llvm.org/ce/z/zgPUGT https://alive2.llvm.org/ce/z/h2gZ_6 Note that there are cases where inserting freeze is not necessary: e.g. %Y is `noundef`. In this case, LLVM is already good because `%ret` is already successfully folded into `and`, triggering the pre-existing optimization in InstSimplify: https://godbolt.org/z/v6qena15K Differential Revision: https://reviews.llvm.org/D101423
- Loading branch information
Showing
9 changed files
with
151 additions
and
95 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
//===-- OverflowInstAnalysis.h - Utils to fold overflow insts ----*- C++ -*-==// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// This file holds routines to help analyse overflow instructions | ||
// and fold them into constants or other overflow instructions | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef LLVM_ANALYSIS_OVERFLOWINSTANALYSIS_H | ||
#define LLVM_ANALYSIS_OVERFLOWINSTANALYSIS_H | ||
|
||
#include "llvm/IR/InstrTypes.h" | ||
|
||
namespace llvm { | ||
class Value; | ||
class Use; | ||
|
||
/// Match one of the patterns up to the select/logic op: | ||
/// %Op0 = icmp ne i4 %X, 0 | ||
/// %Agg = call { i4, i1 } @llvm.[us]mul.with.overflow.i4(i4 %X, i4 %Y) | ||
/// %Op1 = extractvalue { i4, i1 } %Agg, 1 | ||
/// %ret = select i1 %Op0, i1 %Op1, i1 false / %ret = and i1 %Op0, %Op1 | ||
/// | ||
/// %Op0 = icmp eq i4 %X, 0 | ||
/// %Agg = call { i4, i1 } @llvm.[us]mul.with.overflow.i4(i4 %X, i4 %Y) | ||
/// %NotOp1 = extractvalue { i4, i1 } %Agg, 1 | ||
/// %Op1 = xor i1 %NotOp1, true | ||
/// %ret = select i1 %Op0, i1 true, i1 %Op1 / %ret = or i1 %Op0, %Op1 | ||
/// | ||
/// Callers are expected to align that with the operands of the select/logic. | ||
/// IsAnd is set to true if the Op0 and Op1 are used as the first pattern. | ||
/// If Op0 and Op1 match one of the patterns above, return true and fill Y's | ||
/// use. | ||
|
||
bool isCheckForZeroAndMulWithOverflow(Value *Op0, Value *Op1, bool IsAnd, | ||
Use *&Y); | ||
bool isCheckForZeroAndMulWithOverflow(Value *Op0, Value *Op1, bool IsAnd); | ||
} // end namespace llvm | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
//==-- OverflowInstAnalysis.cpp - Utils to fold overflow insts ----*- C++ -*-=// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// This file holds routines to help analyse overflow instructions | ||
// and fold them into constants or other overflow instructions | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "llvm/Analysis/OverflowInstAnalysis.h" | ||
#include "llvm/IR/Constants.h" | ||
#include "llvm/IR/Instructions.h" | ||
#include "llvm/IR/PatternMatch.h" | ||
|
||
using namespace llvm; | ||
using namespace llvm::PatternMatch; | ||
|
||
bool llvm::isCheckForZeroAndMulWithOverflow(Value *Op0, Value *Op1, bool IsAnd, | ||
Use *&Y) { | ||
ICmpInst::Predicate Pred; | ||
Value *X, *NotOp1; | ||
int XIdx; | ||
IntrinsicInst *II; | ||
|
||
if (!match(Op0, m_ICmp(Pred, m_Value(X), m_Zero()))) | ||
return false; | ||
|
||
/// %Agg = call { i4, i1 } @llvm.[us]mul.with.overflow.i4(i4 %X, i4 %???) | ||
/// %V = extractvalue { i4, i1 } %Agg, 1 | ||
auto matchMulOverflowCheck = [X, &II, &XIdx](Value *V) { | ||
auto *Extract = dyn_cast<ExtractValueInst>(V); | ||
// We should only be extracting the overflow bit. | ||
if (!Extract || !Extract->getIndices().equals(1)) | ||
return false; | ||
|
||
II = dyn_cast<IntrinsicInst>(Extract->getAggregateOperand()); | ||
if (!match(II, m_CombineOr(m_Intrinsic<Intrinsic::umul_with_overflow>(), | ||
m_Intrinsic<Intrinsic::smul_with_overflow>()))) | ||
return false; | ||
|
||
if (II->getArgOperand(0) == X) | ||
XIdx = 0; | ||
else if (II->getArgOperand(1) == X) | ||
XIdx = 1; | ||
else | ||
return false; | ||
return true; | ||
}; | ||
|
||
bool Matched = | ||
(IsAnd && Pred == ICmpInst::Predicate::ICMP_NE && | ||
matchMulOverflowCheck(Op1)) || | ||
(!IsAnd && Pred == ICmpInst::Predicate::ICMP_EQ && | ||
match(Op1, m_Not(m_Value(NotOp1))) && matchMulOverflowCheck(NotOp1)); | ||
|
||
if (!Matched) | ||
return false; | ||
|
||
Y = &II->getArgOperandUse(!XIdx); | ||
return true; | ||
} | ||
|
||
bool llvm::isCheckForZeroAndMulWithOverflow(Value *Op0, Value *Op1, | ||
bool IsAnd) { | ||
Use *Y; | ||
return isCheckForZeroAndMulWithOverflow(Op0, Op1, IsAnd, Y); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters