Skip to content

Commit bb7e56c

Browse files
committed
[IR][DAG] Add support for nneg flag with uitofp
As noted when #82404 was pushed (canonicalizing `sitofp` -> `uitofp`), different signedness on fp casts can have dramatic performance implications on different backends. So, it makes to create a reliable means for the backend to pick its cast signedness if either are correct. Further, this allows us to start canonicalizing `sitofp`- > `uitofp` which may easy middle end analysis.
1 parent f5c90f3 commit bb7e56c

File tree

12 files changed

+102
-18
lines changed

12 files changed

+102
-18
lines changed

llvm/docs/LangRef.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11616,6 +11616,10 @@ Overview:
1161611616
The '``uitofp``' instruction regards ``value`` as an unsigned integer
1161711617
and converts that value to the ``ty2`` type.
1161811618

11619+
The ``nneg`` (non-negative) flag, if present, specifies that the
11620+
operand is non-negative. This property may be used by optimization
11621+
passes to later convert the ``uitofp`` into a ``sitofp``.
11622+
1161911623
Arguments:
1162011624
""""""""""
1162111625

@@ -11633,6 +11637,9 @@ integer quantity and converts it to the corresponding floating-point
1163311637
value. If the value cannot be exactly represented, it is rounded using
1163411638
the default rounding mode.
1163511639

11640+
If the ``nneg`` flag is set, and the ``uitofp`` argument is negative,
11641+
the result is a poison value.
11642+
1163611643

1163711644
Example:
1163811645
""""""""
@@ -11642,6 +11649,9 @@ Example:
1164211649
%X = uitofp i32 257 to float ; yields float:257.0
1164311650
%Y = uitofp i8 -1 to double ; yields double:255.0
1164411651

11652+
%a = uitofp nneg i32 256 to i32 ; yields float:257.0
11653+
%b = uitofp nneg i32 -256 to i32 ; yields i32 poison
11654+
1164511655
'``sitofp .. to``' Instruction
1164611656
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1164711657

llvm/include/llvm/CodeGen/TargetLowering.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3005,6 +3005,12 @@ class TargetLoweringBase {
30053005
return false;
30063006
}
30073007

3008+
/// Return true if sitofp from FromTy to ToTy is cheaper than
3009+
/// uitofp.
3010+
virtual bool isSIToFPCheaperThanUIToFP(EVT FromTy, EVT ToTy) const {
3011+
return false;
3012+
}
3013+
30083014
/// Return true if this constant should be sign extended when promoting to
30093015
/// a larger type.
30103016
virtual bool signExtendConstant(const ConstantInt *C) const { return false; }

llvm/include/llvm/IR/IRBuilder.h

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2009,14 +2009,7 @@ class IRBuilderBase {
20092009

20102010
Value *CreateZExt(Value *V, Type *DestTy, const Twine &Name = "",
20112011
bool IsNonNeg = false) {
2012-
if (V->getType() == DestTy)
2013-
return V;
2014-
if (Value *Folded = Folder.FoldCast(Instruction::ZExt, V, DestTy))
2015-
return Folded;
2016-
Instruction *I = Insert(new ZExtInst(V, DestTy), Name);
2017-
if (IsNonNeg)
2018-
I->setNonNeg();
2019-
return I;
2012+
return CreateCast(Instruction::ZExt, V, DestTy, Name, IsNonNeg);
20202013
}
20212014

20222015
Value *CreateSExt(Value *V, Type *DestTy, const Twine &Name = "") {
@@ -2067,11 +2060,12 @@ class IRBuilderBase {
20672060
return CreateCast(Instruction::FPToSI, V, DestTy, Name);
20682061
}
20692062

2070-
Value *CreateUIToFP(Value *V, Type *DestTy, const Twine &Name = ""){
2063+
Value *CreateUIToFP(Value *V, Type *DestTy, const Twine &Name = "",
2064+
bool IsNonNeg = false) {
20712065
if (IsFPConstrained)
20722066
return CreateConstrainedFPCast(Intrinsic::experimental_constrained_uitofp,
20732067
V, DestTy, nullptr, Name);
2074-
return CreateCast(Instruction::UIToFP, V, DestTy, Name);
2068+
return CreateCast(Instruction::UIToFP, V, DestTy, Name, IsNonNeg);
20752069
}
20762070

20772071
Value *CreateSIToFP(Value *V, Type *DestTy, const Twine &Name = ""){
@@ -2142,12 +2136,17 @@ class IRBuilderBase {
21422136
}
21432137

21442138
Value *CreateCast(Instruction::CastOps Op, Value *V, Type *DestTy,
2145-
const Twine &Name = "") {
2139+
const Twine &Name = "", bool IsNonNeg = false) {
21462140
if (V->getType() == DestTy)
21472141
return V;
21482142
if (Value *Folded = Folder.FoldCast(Op, V, DestTy))
21492143
return Folded;
2150-
return Insert(CastInst::Create(Op, V, DestTy), Name);
2144+
Instruction *I = Insert(CastInst::Create(Op, V, DestTy), Name);
2145+
if (IsNonNeg) {
2146+
assert(isa<PossiblyNonNegInst>(I) && "Invalid use of IsNonNeg");
2147+
I->setNonNeg();
2148+
}
2149+
return I;
21512150
}
21522151

21532152
Value *CreatePointerCast(Value *V, Type *DestTy,

llvm/include/llvm/IR/InstrTypes.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -933,13 +933,19 @@ class CastInst : public UnaryInstruction {
933933
}
934934
};
935935

936-
/// Instruction that can have a nneg flag (only zext).
936+
/// Instruction that can have a nneg flag (zext/uitofp).
937937
class PossiblyNonNegInst : public CastInst {
938938
public:
939939
enum { NonNeg = (1 << 0) };
940940

941941
static bool classof(const Instruction *I) {
942-
return I->getOpcode() == Instruction::ZExt;
942+
switch (I->getOpcode()) {
943+
case Instruction::ZExt:
944+
case Instruction::UIToFP:
945+
return true;
946+
default:
947+
return false;
948+
}
943949
}
944950

945951
static bool classof(const Value *V) {

llvm/lib/AsmParser/LLParser.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6801,6 +6801,7 @@ int LLParser::parseInstruction(Instruction *&Inst, BasicBlock *BB,
68016801
}
68026802

68036803
// Casts.
6804+
case lltok::kw_uitofp:
68046805
case lltok::kw_zext: {
68056806
bool NonNeg = EatIfPresent(lltok::kw_nneg);
68066807
bool Res = parseCast(Inst, PFS, KeywordVal);
@@ -6816,7 +6817,6 @@ int LLParser::parseInstruction(Instruction *&Inst, BasicBlock *BB,
68166817
case lltok::kw_fpext:
68176818
case lltok::kw_bitcast:
68186819
case lltok::kw_addrspacecast:
6819-
case lltok::kw_uitofp:
68206820
case lltok::kw_sitofp:
68216821
case lltok::kw_fptoui:
68226822
case lltok::kw_fptosi:

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3882,7 +3882,15 @@ void SelectionDAGBuilder::visitUIToFP(const User &I) {
38823882
SDValue N = getValue(I.getOperand(0));
38833883
EVT DestVT = DAG.getTargetLoweringInfo().getValueType(DAG.getDataLayout(),
38843884
I.getType());
3885-
setValue(&I, DAG.getNode(ISD::UINT_TO_FP, getCurSDLoc(), DestVT, N));
3885+
bool IsNonNeg = false;
3886+
if (auto *PNI = dyn_cast<PossiblyNonNegInst>(&I))
3887+
IsNonNeg = true;
3888+
3889+
unsigned Opc = ISD::UINT_TO_FP;
3890+
if (IsNonNeg && DAG.getTargetLoweringInfo().isSIToFPCheaperThanUIToFP(
3891+
N.getValueType(), DestVT))
3892+
Opc = ISD::SINT_TO_FP;
3893+
setValue(&I, DAG.getNode(Opc, getCurSDLoc(), DestVT, N));
38863894
}
38873895

38883896
void SelectionDAGBuilder::visitSIToFP(const User &I) {

llvm/lib/IR/Instruction.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ void Instruction::setIsExact(bool b) {
382382
}
383383

384384
void Instruction::setNonNeg(bool b) {
385-
assert(isa<PossiblyNonNegInst>(this) && "Must be zext");
385+
assert(isa<PossiblyNonNegInst>(this) && "Must be zext/uitofp");
386386
SubclassOptionalData = (SubclassOptionalData & ~PossiblyNonNegInst::NonNeg) |
387387
(b * PossiblyNonNegInst::NonNeg);
388388
}
@@ -396,7 +396,7 @@ bool Instruction::hasNoSignedWrap() const {
396396
}
397397

398398
bool Instruction::hasNonNeg() const {
399-
assert(isa<PossiblyNonNegInst>(this) && "Must be zext");
399+
assert(isa<PossiblyNonNegInst>(this) && "Must be zext/uitofp");
400400
return (SubclassOptionalData & PossiblyNonNegInst::NonNeg) != 0;
401401
}
402402

@@ -429,6 +429,7 @@ void Instruction::dropPoisonGeneratingFlags() {
429429
cast<GetElementPtrInst>(this)->setIsInBounds(false);
430430
break;
431431

432+
case Instruction::UIToFP:
432433
case Instruction::ZExt:
433434
setNonNeg(false);
434435
break;

llvm/lib/IR/Operator.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ bool Operator::hasPoisonGeneratingFlags() const {
3939
// Note: inrange exists on constexpr only
4040
return GEP->isInBounds() || GEP->getInRange() != std::nullopt;
4141
}
42+
case Instruction::UIToFP:
4243
case Instruction::ZExt:
4344
if (auto *NNI = dyn_cast<PossiblyNonNegInst>(this))
4445
return NNI->hasNonNeg();

llvm/test/Assembler/flags.ll

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,13 @@ define i64 @test_zext(i32 %a) {
256256
ret i64 %res
257257
}
258258

259+
define float @test_uitofp(i32 %a) {
260+
; CHECK: %res = uitofp nneg i32 %a to float
261+
%res = uitofp nneg i32 %a to float
262+
ret float %res
263+
}
264+
265+
259266
define i64 @test_or(i64 %a, i64 %b) {
260267
; CHECK: %res = or disjoint i64 %a, %b
261268
%res = or disjoint i64 %a, %b

llvm/test/Bitcode/flags.ll

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ second: ; preds = %first
1818
%z = add i32 %a, 0 ; <i32> [#uses=0]
1919
%hh = zext nneg i32 %a to i64
2020
%ll = zext i32 %s to i64
21+
%ff = uitofp nneg i32 %a to float
22+
%bb = uitofp i32 %s to float
2123
%jj = or disjoint i32 %a, 0
2224
%oo = or i32 %a, 0
2325
unreachable
@@ -30,6 +32,8 @@ first: ; preds = %entry
3032
%zz = add i32 %a, 0 ; <i32> [#uses=0]
3133
%kk = zext nneg i32 %a to i64
3234
%rr = zext i32 %ss to i64
35+
%ww = uitofp nneg i32 %a to float
36+
%xx = uitofp i32 %ss to float
3337
%mm = or disjoint i32 %a, 0
3438
%nn = or i32 %a, 0
3539
br label %second

llvm/test/Transforms/InstCombine/freeze.ll

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,6 +1127,17 @@ define i32 @freeze_zext_nneg(i8 %x) {
11271127
ret i32 %fr
11281128
}
11291129

1130+
define float @freeze_uitofp_nneg(i8 %x) {
1131+
; CHECK-LABEL: @freeze_uitofp_nneg(
1132+
; CHECK-NEXT: [[X_FR:%.*]] = freeze i8 [[X:%.*]]
1133+
; CHECK-NEXT: [[UITOFP:%.*]] = uitofp i8 [[X_FR]] to float
1134+
; CHECK-NEXT: ret float [[UITOFP]]
1135+
;
1136+
%uitofp = uitofp nneg i8 %x to float
1137+
%fr = freeze float %uitofp
1138+
ret float %fr
1139+
}
1140+
11301141
define i32 @propagate_drop_flags_or(i32 %arg) {
11311142
; CHECK-LABEL: @propagate_drop_flags_or(
11321143
; CHECK-NEXT: [[ARG_FR:%.*]] = freeze i32 [[ARG:%.*]]

llvm/test/Transforms/SimplifyCFG/HoistCode.ll

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,37 @@ F:
125125
ret i32 %z2
126126
}
127127

128+
129+
define float @hoist_uitofp_flags_preserve(i1 %C, i8 %x) {
130+
; CHECK-LABEL: @hoist_uitofp_flags_preserve(
131+
; CHECK-NEXT: common.ret:
132+
; CHECK-NEXT: [[Z1:%.*]] = uitofp nneg i8 [[X:%.*]] to float
133+
; CHECK-NEXT: ret float [[Z1]]
134+
;
135+
br i1 %C, label %T, label %F
136+
T:
137+
%z1 = uitofp nneg i8 %x to float
138+
ret float %z1
139+
F:
140+
%z2 = uitofp nneg i8 %x to float
141+
ret float %z2
142+
}
143+
144+
define float @hoist_uitofp_flags_drop(i1 %C, i8 %x) {
145+
; CHECK-LABEL: @hoist_uitofp_flags_drop(
146+
; CHECK-NEXT: common.ret:
147+
; CHECK-NEXT: [[Z1:%.*]] = uitofp i8 [[X:%.*]] to float
148+
; CHECK-NEXT: ret float [[Z1]]
149+
;
150+
br i1 %C, label %T, label %F
151+
T:
152+
%z1 = uitofp nneg i8 %x to float
153+
ret float %z1
154+
F:
155+
%z2 = uitofp i8 %x to float
156+
ret float %z2
157+
}
158+
128159
define i32 @hoist_or_flags_preserve(i1 %C, i32 %x, i32 %y) {
129160
; CHECK-LABEL: @hoist_or_flags_preserve(
130161
; CHECK-NEXT: common.ret:

0 commit comments

Comments
 (0)