Skip to content

Commit 1a31075

Browse files
committed
IR: introduce ICmpInst::PredicateSign
Introduce CmpInst::PredicateSign, an abstraction over a floating-point predicate, and a pack of an integer predicate with samesign information, in order to ease extending large portions of the codebase that take a CmpInst::Predicate to respect the samesign flag. We have chosen to demonstrate the utility of this new abstraction by migrating ValueTracking, InstructionSimplify, and InstCombine from CmpInst::Predicate to CmpInst::PredicateSign. There should be no functional changes, as we don't perform any extra optimizations with samesign in this patch. The design approach taken by this patch allows for unaudited callers of APIs that take a CmpInst::PredicateSign to silently drop the samesign information; it does not pose a correctness issue, and allows us to migrate the codebase piece-wise.
1 parent 4e8eabd commit 1a31075

File tree

16 files changed

+269
-138
lines changed

16 files changed

+269
-138
lines changed

llvm/include/llvm/Analysis/InstSimplifyFolder.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "llvm/ADT/ArrayRef.h"
2323
#include "llvm/Analysis/InstructionSimplify.h"
2424
#include "llvm/Analysis/TargetFolder.h"
25+
#include "llvm/IR/CmpPredicate.h"
2526
#include "llvm/IR/IRBuilderFolder.h"
2627
#include "llvm/IR/Instruction.h"
2728

llvm/include/llvm/Analysis/InstructionSimplify.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class DataLayout;
4444
class DominatorTree;
4545
class Function;
4646
class Instruction;
47+
class CmpPredicate;
4748
class LoadInst;
4849
struct LoopStandardAnalysisResults;
4950
class Pass;
@@ -152,11 +153,11 @@ Value *simplifyOrInst(Value *LHS, Value *RHS, const SimplifyQuery &Q);
152153
Value *simplifyXorInst(Value *LHS, Value *RHS, const SimplifyQuery &Q);
153154

154155
/// Given operands for an ICmpInst, fold the result or return null.
155-
Value *simplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
156+
Value *simplifyICmpInst(CmpPredicate Pred, Value *LHS, Value *RHS,
156157
const SimplifyQuery &Q);
157158

158159
/// Given operands for an FCmpInst, fold the result or return null.
159-
Value *simplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
160+
Value *simplifyFCmpInst(CmpPredicate Predicate, Value *LHS, Value *RHS,
160161
FastMathFlags FMF, const SimplifyQuery &Q);
161162

162163
/// Given operands for a SelectInst, fold the result or return null.
@@ -200,7 +201,7 @@ Value *simplifyShuffleVectorInst(Value *Op0, Value *Op1, ArrayRef<int> Mask,
200201
//=== Helper functions for higher up the class hierarchy.
201202

202203
/// Given operands for a CmpInst, fold the result or return null.
203-
Value *simplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
204+
Value *simplifyCmpInst(CmpPredicate Predicate, Value *LHS, Value *RHS,
204205
const SimplifyQuery &Q);
205206

206207
/// Given operand for a UnaryOperator, fold the result or return null.

llvm/include/llvm/Analysis/ValueTracking.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1245,8 +1245,7 @@ std::optional<bool> isImpliedCondition(const Value *LHS, const Value *RHS,
12451245
const DataLayout &DL,
12461246
bool LHSIsTrue = true,
12471247
unsigned Depth = 0);
1248-
std::optional<bool> isImpliedCondition(const Value *LHS,
1249-
CmpInst::Predicate RHSPred,
1248+
std::optional<bool> isImpliedCondition(const Value *LHS, CmpPredicate RHSPred,
12501249
const Value *RHSOp0, const Value *RHSOp1,
12511250
const DataLayout &DL,
12521251
bool LHSIsTrue = true,
@@ -1257,8 +1256,8 @@ std::optional<bool> isImpliedCondition(const Value *LHS,
12571256
std::optional<bool> isImpliedByDomCondition(const Value *Cond,
12581257
const Instruction *ContextI,
12591258
const DataLayout &DL);
1260-
std::optional<bool> isImpliedByDomCondition(CmpInst::Predicate Pred,
1261-
const Value *LHS, const Value *RHS,
1259+
std::optional<bool> isImpliedByDomCondition(CmpPredicate Pred, const Value *LHS,
1260+
const Value *RHS,
12621261
const Instruction *ContextI,
12631262
const DataLayout &DL);
12641263

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
//===- CmpPredicate.h - CmpInst Predicate with samesign information -------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// A CmpInst::Predicate with any samesign information (applicable to ICmpInst).
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef LLVM_IR_CMPPREDICATE_H
14+
#define LLVM_IR_CMPPREDICATE_H
15+
16+
#include "llvm/IR/InstrTypes.h"
17+
18+
namespace llvm {
19+
/// An abstraction over a floating-point predicate, and a pack of an integer
20+
/// predicate with samesign information. Functions in ICmpInst construct and
21+
/// return this type in place of a Predicate. It is also implictly constructed
22+
/// with a Predicate, dropping samesign information.
23+
class CmpPredicate {
24+
CmpInst::Predicate Pred;
25+
bool HasSameSign;
26+
27+
public:
28+
CmpPredicate(CmpInst::Predicate Pred, bool HasSameSign = false)
29+
: Pred(Pred), HasSameSign(HasSameSign) {
30+
assert(!HasSameSign || CmpInst::isIntPredicate(Pred));
31+
}
32+
33+
inline operator CmpInst::Predicate() const { return Pred; }
34+
35+
inline bool hasSameSign() const { return HasSameSign; }
36+
37+
static std::optional<CmpPredicate> getMatching(CmpPredicate A,
38+
CmpPredicate B) {
39+
if (A.Pred == B.Pred)
40+
return A.HasSameSign == B.HasSameSign ? A : CmpPredicate(A.Pred);
41+
if (A.HasSameSign &&
42+
A.Pred == CmpInst::getFlippedSignednessPredicate(B.Pred))
43+
return B.Pred;
44+
if (B.HasSameSign &&
45+
B.Pred == CmpInst::getFlippedSignednessPredicate(A.Pred))
46+
return A.Pred;
47+
return {};
48+
}
49+
50+
inline bool operator==(CmpInst::Predicate P) const { return Pred == P; }
51+
52+
inline bool operator==(CmpPredicate) const = delete;
53+
};
54+
} // namespace llvm
55+
56+
#endif

llvm/include/llvm/IR/InstrTypes.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -728,6 +728,24 @@ class CmpInst : public Instruction {
728728
InsertPosition InsertBefore = nullptr,
729729
Instruction *FlagsSource = nullptr);
730730

731+
/// Return the signed version of the predicate: variant that operates on
732+
/// Predicate; used by the corresponding function in ICmpInst, to operate with
733+
/// CmpPredicate.
734+
static Predicate getSignedPredicate(Predicate Pred);
735+
736+
/// Return the unsigned version of the predicate: variant that operates on
737+
/// Predicate; used by the corresponding function in ICmpInst, to operate with
738+
/// CmpPredicate.
739+
static Predicate getUnsignedPredicate(Predicate Pred);
740+
741+
/// Return the unsigned version of the signed predicate pred or the signed
742+
/// version of the signed predicate pred: variant that operates on Predicate;
743+
/// used by the corresponding function in ICmpInst, to operate with
744+
/// CmpPredicate.
745+
static Predicate getFlippedSignednessPredicate(Predicate Pred);
746+
747+
friend class CmpPredicate;
748+
731749
public:
732750
// allocate space for exactly two operands
733751
void *operator new(size_t S) { return User::operator new(S, AllocMarker); }

llvm/include/llvm/IR/Instructions.h

Lines changed: 58 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "llvm/ADT/iterator.h"
2525
#include "llvm/ADT/iterator_range.h"
2626
#include "llvm/IR/CFG.h"
27+
#include "llvm/IR/CmpPredicate.h"
2728
#include "llvm/IR/Constant.h"
2829
#include "llvm/IR/DerivedTypes.h"
2930
#include "llvm/IR/GEPNoWrapFlags.h"
@@ -1203,38 +1204,78 @@ class ICmpInst: public CmpInst {
12031204
#endif
12041205
}
12051206

1207+
/// @returns the predicate along with samesign information.
1208+
CmpPredicate getCmpPredicate() const {
1209+
return {getPredicate(), hasSameSign()};
1210+
}
1211+
1212+
/// @returns the inverse predicate along with samesign information: static
1213+
/// variant.
1214+
static CmpPredicate getInverseCmpPredicate(CmpPredicate Pred) {
1215+
return {getInversePredicate(Pred), Pred.hasSameSign()};
1216+
}
1217+
1218+
/// @returns the inverse predicate along with samesign information.
1219+
CmpPredicate getInverseCmpPredicate() const {
1220+
return getInverseCmpPredicate(getCmpPredicate());
1221+
}
1222+
1223+
/// @returns the swapped predicate along with samesign information: static
1224+
/// variant.
1225+
static CmpPredicate getSwappedCmpPredicate(CmpPredicate Pred) {
1226+
return {getSwappedPredicate(Pred), Pred.hasSameSign()};
1227+
}
1228+
1229+
/// @returns the swapped predicate along with samesign information.
1230+
CmpPredicate getSwappedCmpPredicate() const {
1231+
return getSwappedPredicate(getCmpPredicate());
1232+
}
1233+
12061234
/// For example, EQ->EQ, SLE->SLE, UGT->SGT, etc.
12071235
/// @returns the predicate that would be the result if the operand were
12081236
/// regarded as signed.
1209-
/// Return the signed version of the predicate.
1210-
Predicate getSignedPredicate() const {
1211-
return getSignedPredicate(getPredicate());
1237+
/// Return the signed version of the predicate along with samesign
1238+
/// information.
1239+
CmpPredicate getSignedPredicate() const {
1240+
return getSignedPredicate(getCmpPredicate());
12121241
}
12131242

1214-
/// Return the signed version of the predicate: static variant.
1215-
static Predicate getSignedPredicate(Predicate pred);
1243+
/// Return the signed version of the predicate along with samesign
1244+
/// information: static variant.
1245+
static CmpPredicate getSignedPredicate(CmpPredicate Pred) {
1246+
return {CmpInst::getSignedPredicate(Pred), Pred.hasSameSign()};
1247+
}
12161248

12171249
/// For example, EQ->EQ, SLE->ULE, UGT->UGT, etc.
12181250
/// @returns the predicate that would be the result if the operand were
12191251
/// regarded as unsigned.
1220-
/// Return the unsigned version of the predicate.
1221-
Predicate getUnsignedPredicate() const {
1222-
return getUnsignedPredicate(getPredicate());
1252+
/// Return the unsigned version of the predicate along with samesign
1253+
/// information.
1254+
CmpPredicate getUnsignedPredicate() const {
1255+
return getUnsignedPredicate(getCmpPredicate());
12231256
}
12241257

1225-
/// Return the unsigned version of the predicate: static variant.
1226-
static Predicate getUnsignedPredicate(Predicate pred);
1258+
/// Return the unsigned version of the predicate along with samesign
1259+
/// information: static variant.
1260+
static CmpPredicate getUnsignedPredicate(CmpPredicate Pred) {
1261+
return {CmpInst::getUnsignedPredicate(Pred), Pred.hasSameSign()};
1262+
}
12271263

1228-
/// For example, SLT->ULT, ULT->SLT, SLE->ULE, ULE->SLE, EQ->Failed assert
1264+
/// For example, SLT->ULT, ULT->SLT, SLE->ULE, ULE->SLE, EQ->EQ
12291265
/// @returns the unsigned version of the signed predicate pred or
1230-
/// the signed version of the signed predicate pred.
1231-
static Predicate getFlippedSignednessPredicate(Predicate pred);
1266+
/// the signed version of the signed predicate pred, along with
1267+
/// samesign information.
1268+
/// Static variant.
1269+
static CmpPredicate getFlippedSignednessPredicate(CmpPredicate Pred) {
1270+
return {CmpInst::getFlippedSignednessPredicate(Pred), Pred.hasSameSign()};
1271+
}
12321272

1233-
/// For example, SLT->ULT, ULT->SLT, SLE->ULE, ULE->SLE, EQ->Failed assert
1273+
/// For example, SLT->ULT, ULT->SLT, SLE->ULE, ULE->SLE, EQ->EQ
12341274
/// @returns the unsigned version of the signed predicate pred or
1235-
/// the signed version of the signed predicate pred.
1236-
Predicate getFlippedSignednessPredicate() const {
1237-
return getFlippedSignednessPredicate(getPredicate());
1275+
/// the signed version of the signed predicate pred, along with
1276+
/// samesign information.
1277+
CmpPredicate getFlippedSignednessPredicate() const {
1278+
return getFlippedSignednessPredicate(getCmpPredicate());
12381279
}
12391280

12401281
void setSameSign(bool B = true) {

llvm/include/llvm/Transforms/InstCombine/InstCombiner.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ class LLVM_LIBRARY_VISIBILITY InstCombiner {
157157
/// conditional branch or select to create a compare with a canonical
158158
/// (inverted) predicate which is then more likely to be matched with other
159159
/// values.
160-
static bool isCanonicalPredicate(CmpInst::Predicate Pred) {
160+
static bool isCanonicalPredicate(CmpPredicate Pred) {
161161
switch (Pred) {
162162
case CmpInst::ICMP_NE:
163163
case CmpInst::ICMP_ULE:
@@ -185,10 +185,9 @@ class LLVM_LIBRARY_VISIBILITY InstCombiner {
185185
}
186186

187187
std::optional<std::pair<
188-
CmpInst::Predicate,
189-
Constant *>> static getFlippedStrictnessPredicateAndConstant(CmpInst::
190-
Predicate
191-
Pred,
188+
CmpPredicate,
189+
Constant *>> static getFlippedStrictnessPredicateAndConstant(CmpPredicate
190+
Pred,
192191
Constant *C);
193192

194193
static bool shouldAvoidAbsorbingNotIntoSelect(const SelectInst &SI) {

0 commit comments

Comments
 (0)