Skip to content

Commit 8aba264

Browse files
committed
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 678f32a commit 8aba264

File tree

11 files changed

+86
-18
lines changed

11 files changed

+86
-18
lines changed

llvm/docs/LangRef.rst

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

11751+
The ``nneg`` (non-negative) flag, if present, specifies that the
11752+
operand is non-negative. This property may be used by optimization
11753+
passes to later convert the ``uitofp`` into a ``sitofp``.
11754+
1175111755
Arguments:
1175211756
""""""""""
1175311757

@@ -11765,6 +11769,9 @@ integer quantity and converts it to the corresponding floating-point
1176511769
value. If the value cannot be exactly represented, it is rounded using
1176611770
the default rounding mode.
1176711771

11772+
If the ``nneg`` flag is set, and the ``uitofp`` argument is negative,
11773+
the result is a poison value.
11774+
1176811775

1176911776
Example:
1177011777
""""""""
@@ -11774,6 +11781,9 @@ Example:
1177411781
%X = uitofp i32 257 to float ; yields float:257.0
1177511782
%Y = uitofp i8 -1 to double ; yields double:255.0
1177611783

11784+
%a = uitofp nneg i32 256 to i32 ; yields float:256.0
11785+
%b = uitofp nneg i32 -256 to i32 ; yields i32 poison
11786+
1177711787
'``sitofp .. to``' Instruction
1177811788
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1177911789

llvm/include/llvm/IR/IRBuilder.h

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2010,14 +2010,7 @@ class IRBuilderBase {
20102010

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

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

2071-
Value *CreateUIToFP(Value *V, Type *DestTy, const Twine &Name = ""){
2064+
Value *CreateUIToFP(Value *V, Type *DestTy, const Twine &Name = "",
2065+
bool IsNonNeg = false) {
20722066
if (IsFPConstrained)
20732067
return CreateConstrainedFPCast(Intrinsic::experimental_constrained_uitofp,
20742068
V, DestTy, nullptr, Name);
2075-
return CreateCast(Instruction::UIToFP, V, DestTy, Name);
2069+
return CreateCast(Instruction::UIToFP, V, DestTy, Name, IsNonNeg);
20762070
}
20772071

20782072
Value *CreateSIToFP(Value *V, Type *DestTy, const Twine &Name = ""){
@@ -2143,12 +2137,15 @@ class IRBuilderBase {
21432137
}
21442138

21452139
Value *CreateCast(Instruction::CastOps Op, Value *V, Type *DestTy,
2146-
const Twine &Name = "") {
2140+
const Twine &Name = "", bool IsNonNeg = false) {
21472141
if (V->getType() == DestTy)
21482142
return V;
21492143
if (Value *Folded = Folder.FoldCast(Op, V, DestTy))
21502144
return Folded;
2151-
return Insert(CastInst::Create(Op, V, DestTy), Name);
2145+
Instruction *I = Insert(CastInst::Create(Op, V, DestTy), Name);
2146+
if (IsNonNeg)
2147+
I->setNonNeg();
2148+
return I;
21522149
}
21532150

21542151
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
@@ -927,13 +927,19 @@ class CastInst : public UnaryInstruction {
927927
}
928928
};
929929

930-
/// Instruction that can have a nneg flag (only zext).
930+
/// Instruction that can have a nneg flag (zext/uitofp).
931931
class PossiblyNonNegInst : public CastInst {
932932
public:
933933
enum { NonNeg = (1 << 0) };
934934

935935
static bool classof(const Instruction *I) {
936-
return I->getOpcode() == Instruction::ZExt;
936+
switch (I->getOpcode()) {
937+
case Instruction::ZExt:
938+
case Instruction::UIToFP:
939+
return true;
940+
default:
941+
return false;
942+
}
937943
}
938944

939945
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
@@ -6805,6 +6805,7 @@ int LLParser::parseInstruction(Instruction *&Inst, BasicBlock *BB,
68056805
}
68066806

68076807
// Casts.
6808+
case lltok::kw_uitofp:
68086809
case lltok::kw_zext: {
68096810
bool NonNeg = EatIfPresent(lltok::kw_nneg);
68106811
bool Res = parseCast(Inst, PFS, KeywordVal);
@@ -6832,7 +6833,6 @@ int LLParser::parseInstruction(Instruction *&Inst, BasicBlock *BB,
68326833
case lltok::kw_fpext:
68336834
case lltok::kw_bitcast:
68346835
case lltok::kw_addrspacecast:
6835-
case lltok::kw_uitofp:
68366836
case lltok::kw_sitofp:
68376837
case lltok::kw_fptoui:
68386838
case lltok::kw_fptosi:

llvm/lib/Bitcode/Reader/BitcodeReader.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5024,7 +5024,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
50245024
}
50255025

50265026
if (OpNum < Record.size()) {
5027-
if (Opc == Instruction::ZExt) {
5027+
if (Opc == Instruction::ZExt || Opc == Instruction::UIToFP) {
50285028
if (Record[OpNum] & (1 << bitc::PNNI_NON_NEG))
50295029
cast<PossiblyNonNegInst>(I)->setNonNeg(true);
50305030
} else if (Opc == Instruction::Trunc) {

llvm/lib/IR/Instruction.cpp

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

390390
void Instruction::setNonNeg(bool b) {
391-
assert(isa<PossiblyNonNegInst>(this) && "Must be zext");
391+
assert(isa<PossiblyNonNegInst>(this) && "Must be zext/uitofp");
392392
SubclassOptionalData = (SubclassOptionalData & ~PossiblyNonNegInst::NonNeg) |
393393
(b * PossiblyNonNegInst::NonNeg);
394394
}
@@ -408,7 +408,7 @@ bool Instruction::hasNoSignedWrap() const {
408408
}
409409

410410
bool Instruction::hasNonNeg() const {
411-
assert(isa<PossiblyNonNegInst>(this) && "Must be zext");
411+
assert(isa<PossiblyNonNegInst>(this) && "Must be zext/uitofp");
412412
return (SubclassOptionalData & PossiblyNonNegInst::NonNeg) != 0;
413413
}
414414

@@ -441,6 +441,7 @@ void Instruction::dropPoisonGeneratingFlags() {
441441
cast<GetElementPtrInst>(this)->setIsInBounds(false);
442442
break;
443443

444+
case Instruction::UIToFP:
444445
case Instruction::ZExt:
445446
setNonNeg(false);
446447
break;

llvm/lib/IR/Operator.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ bool Operator::hasPoisonGeneratingFlags() const {
4444
// Note: inrange exists on constexpr only
4545
return GEP->isInBounds() || GEP->getInRange() != std::nullopt;
4646
}
47+
case Instruction::UIToFP:
4748
case Instruction::ZExt:
4849
if (auto *NNI = dyn_cast<PossiblyNonNegInst>(this))
4950
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
%tu = trunc nuw i32 %a to i16
@@ -39,6 +41,8 @@ first: ; preds = %entry
3941
%zz = add i32 %a, 0 ; <i32> [#uses=0]
4042
%kk = zext nneg i32 %a to i64
4143
%rr = zext i32 %ss to i64
44+
%ww = uitofp nneg i32 %a to float
45+
%xx = uitofp i32 %ss to float
4246
%mm = or disjoint i32 %a, 0
4347
%nn = or i32 %a, 0
4448
%tuu = trunc nuw i32 %a to i16

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)