Skip to content

Commit 9170e38

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. Closes #86141
1 parent 788be0d commit 9170e38

File tree

11 files changed

+85
-8
lines changed

11 files changed

+85
-8
lines changed

llvm/docs/LangRef.rst

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

11754+
The ``nneg`` (non-negative) flag, if present, specifies that the
11755+
operand is non-negative. This property may be used by optimization
11756+
passes to later convert the ``uitofp`` into a ``sitofp``.
11757+
1175411758
Arguments:
1175511759
""""""""""
1175611760

@@ -11768,6 +11772,9 @@ integer quantity and converts it to the corresponding floating-point
1176811772
value. If the value cannot be exactly represented, it is rounded using
1176911773
the default rounding mode.
1177011774

11775+
If the ``nneg`` flag is set, and the ``uitofp`` argument is negative,
11776+
the result is a poison value.
11777+
1177111778

1177211779
Example:
1177311780
""""""""
@@ -11777,6 +11784,9 @@ Example:
1177711784
%X = uitofp i32 257 to float ; yields float:257.0
1177811785
%Y = uitofp i8 -1 to double ; yields double:255.0
1177911786

11787+
%a = uitofp nneg i32 256 to i32 ; yields float:256.0
11788+
%b = uitofp nneg i32 -256 to i32 ; yields i32 poison
11789+
1178011790
'``sitofp .. to``' Instruction
1178111791
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1178211792

llvm/include/llvm/IR/IRBuilder.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2068,11 +2068,17 @@ class IRBuilderBase {
20682068
return CreateCast(Instruction::FPToSI, V, DestTy, Name);
20692069
}
20702070

2071-
Value *CreateUIToFP(Value *V, Type *DestTy, const Twine &Name = ""){
2071+
Value *CreateUIToFP(Value *V, Type *DestTy, const Twine &Name = "",
2072+
bool IsNonNeg = false) {
20722073
if (IsFPConstrained)
20732074
return CreateConstrainedFPCast(Intrinsic::experimental_constrained_uitofp,
20742075
V, DestTy, nullptr, Name);
2075-
return CreateCast(Instruction::UIToFP, V, DestTy, Name);
2076+
if (Value *Folded = Folder.FoldCast(Instruction::UIToFP, V, DestTy))
2077+
return Folded;
2078+
Instruction *I = Insert(new UIToFPInst(V, DestTy), Name);
2079+
if (IsNonNeg)
2080+
I->setNonNeg();
2081+
return I;
20762082
}
20772083

20782084
Value *CreateSIToFP(Value *V, Type *DestTy, const Twine &Name = ""){

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
@@ -6816,6 +6816,7 @@ int LLParser::parseInstruction(Instruction *&Inst, BasicBlock *BB,
68166816
}
68176817

68186818
// Casts.
6819+
case lltok::kw_uitofp:
68196820
case lltok::kw_zext: {
68206821
bool NonNeg = EatIfPresent(lltok::kw_nneg);
68216822
bool Res = parseCast(Inst, PFS, KeywordVal);
@@ -6843,7 +6844,6 @@ int LLParser::parseInstruction(Instruction *&Inst, BasicBlock *BB,
68436844
case lltok::kw_fpext:
68446845
case lltok::kw_bitcast:
68456846
case lltok::kw_addrspacecast:
6846-
case lltok::kw_uitofp:
68476847
case lltok::kw_sitofp:
68486848
case lltok::kw_fptoui:
68496849
case lltok::kw_fptosi:

llvm/lib/Bitcode/Reader/BitcodeReader.cpp

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

50415041
if (OpNum < Record.size()) {
5042-
if (Opc == Instruction::ZExt) {
5042+
if (Opc == Instruction::ZExt || Opc == Instruction::UIToFP) {
50435043
if (Record[OpNum] & (1 << bitc::PNNI_NON_NEG))
50445044
cast<PossiblyNonNegInst>(I)->setNonNeg(true);
50455045
} 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)