Skip to content

Commit dbca8a4

Browse files
authored
[DAG] Improve known bits of Zext/Sext loads with range metadata (#80829)
This extends the known bits for extending loads which have range metadata, handling the range metadata on the original memory type, extending that to the correct BitWidth.
1 parent 23f3651 commit dbca8a4

File tree

3 files changed

+98
-22
lines changed

3 files changed

+98
-22
lines changed

llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3645,32 +3645,42 @@ KnownBits SelectionDAG::computeKnownBits(SDValue Op, const APInt &DemandedElts,
36453645
}
36463646
}
36473647
}
3648-
} else if (ISD::isZEXTLoad(Op.getNode()) && Op.getResNo() == 0) {
3649-
// If this is a ZEXTLoad and we are looking at the loaded value.
3650-
EVT VT = LD->getMemoryVT();
3651-
unsigned MemBits = VT.getScalarSizeInBits();
3652-
Known.Zero.setBitsFrom(MemBits);
3653-
} else if (const MDNode *Ranges = LD->getRanges()) {
3654-
EVT VT = LD->getValueType(0);
3655-
3656-
// TODO: Handle for extending loads
3657-
if (LD->getExtensionType() == ISD::NON_EXTLOAD) {
3648+
} else if (Op.getResNo() == 0) {
3649+
KnownBits Known0(!LD->getMemoryVT().isScalableVT()
3650+
? LD->getMemoryVT().getFixedSizeInBits()
3651+
: BitWidth);
3652+
EVT VT = Op.getValueType();
3653+
// Fill in any known bits from range information. There are 3 types being
3654+
// used. The results VT (same vector elt size as BitWidth), the loaded
3655+
// MemoryVT (which may or may not be vector) and the range VTs original
3656+
// type. The range matadata needs the full range (i.e
3657+
// MemoryVT().getSizeInBits()), which is truncated to the correct elt size
3658+
// if it is know. These are then extended to the original VT sizes below.
3659+
if (const MDNode *MD = LD->getRanges()) {
3660+
computeKnownBitsFromRangeMetadata(*MD, Known0);
36583661
if (VT.isVector()) {
36593662
// Handle truncation to the first demanded element.
36603663
// TODO: Figure out which demanded elements are covered
36613664
if (DemandedElts != 1 || !getDataLayout().isLittleEndian())
36623665
break;
3666+
Known0 = Known0.trunc(BitWidth);
3667+
}
3668+
}
36633669

3664-
// Handle the case where a load has a vector type, but scalar memory
3665-
// with an attached range.
3666-
EVT MemVT = LD->getMemoryVT();
3667-
KnownBits KnownFull(MemVT.getSizeInBits());
3670+
if (LD->getMemoryVT().isVector())
3671+
Known0 = Known0.trunc(LD->getMemoryVT().getScalarSizeInBits());
36683672

3669-
computeKnownBitsFromRangeMetadata(*Ranges, KnownFull);
3670-
Known = KnownFull.trunc(BitWidth);
3671-
} else
3672-
computeKnownBitsFromRangeMetadata(*Ranges, Known);
3673-
}
3673+
// Extend the Known bits from memory to the size of the result.
3674+
if (ISD::isZEXTLoad(Op.getNode()))
3675+
Known = Known0.zext(BitWidth);
3676+
else if (ISD::isSEXTLoad(Op.getNode()))
3677+
Known = Known0.sext(BitWidth);
3678+
else if (ISD::isEXTLoad(Op.getNode()))
3679+
Known = Known0.anyext(BitWidth);
3680+
else
3681+
Known = Known0;
3682+
assert(Known.getBitWidth() == BitWidth);
3683+
return Known;
36743684
}
36753685
break;
36763686
}

llvm/test/CodeGen/AArch64/setcc_knownbits.ll

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,7 @@ define noundef i1 @logger(i32 noundef %logLevel, ptr %ea, ptr %pll) {
2121
; CHECK-NEXT: ret
2222
; CHECK-NEXT: .LBB1_2: // %land.rhs
2323
; CHECK-NEXT: ldr x8, [x1]
24-
; CHECK-NEXT: ldrb w8, [x8]
25-
; CHECK-NEXT: cmp w8, #0
26-
; CHECK-NEXT: cset w0, ne
24+
; CHECK-NEXT: ldrb w0, [x8]
2725
; CHECK-NEXT: ret
2826
entry:
2927
%0 = load i32, ptr %pll, align 4

llvm/unittests/CodeGen/AArch64SelectionDAGTest.cpp

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
#include "llvm/Analysis/MemoryLocation.h"
910
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
1011
#include "llvm/AsmParser/Parser.h"
1112
#include "llvm/CodeGen/MachineModuleInfo.h"
1213
#include "llvm/CodeGen/SelectionDAG.h"
1314
#include "llvm/CodeGen/TargetLowering.h"
15+
#include "llvm/IR/MDBuilder.h"
1416
#include "llvm/MC/TargetRegistry.h"
1517
#include "llvm/Support/KnownBits.h"
1618
#include "llvm/Support/SourceMgr.h"
@@ -728,4 +730,70 @@ TEST_F(AArch64SelectionDAGTest, ReplaceAllUsesWith) {
728730
EXPECT_EQ(DAG->getPCSections(New.getNode()), MD);
729731
}
730732

733+
TEST_F(AArch64SelectionDAGTest, computeKnownBits_extload_known01) {
734+
SDLoc Loc;
735+
auto Int8VT = EVT::getIntegerVT(Context, 8);
736+
auto Int32VT = EVT::getIntegerVT(Context, 32);
737+
auto Int64VT = EVT::getIntegerVT(Context, 64);
738+
auto Ptr = DAG->getConstant(0, Loc, Int64VT);
739+
auto PtrInfo =
740+
MachinePointerInfo::getFixedStack(DAG->getMachineFunction(), 0);
741+
AAMDNodes AA;
742+
MDBuilder MDHelper(*DAG->getContext());
743+
MDNode *Range = MDHelper.createRange(APInt(8, 0), APInt(8, 2));
744+
MachineMemOperand *MMO = DAG->getMachineFunction().getMachineMemOperand(
745+
PtrInfo, MachineMemOperand::MOLoad, 8, Align(8), AA, Range);
746+
747+
auto ALoad = DAG->getExtLoad(ISD::EXTLOAD, Loc, Int32VT, DAG->getEntryNode(),
748+
Ptr, Int8VT, MMO);
749+
KnownBits Known = DAG->computeKnownBits(ALoad);
750+
EXPECT_EQ(Known.Zero, APInt(32, 0xfe));
751+
EXPECT_EQ(Known.One, APInt(32, 0));
752+
753+
auto ZLoad = DAG->getExtLoad(ISD::ZEXTLOAD, Loc, Int32VT, DAG->getEntryNode(),
754+
Ptr, Int8VT, MMO);
755+
Known = DAG->computeKnownBits(ZLoad);
756+
EXPECT_EQ(Known.Zero, APInt(32, 0xfffffffe));
757+
EXPECT_EQ(Known.One, APInt(32, 0));
758+
759+
auto SLoad = DAG->getExtLoad(ISD::SEXTLOAD, Loc, Int32VT, DAG->getEntryNode(),
760+
Ptr, Int8VT, MMO);
761+
Known = DAG->computeKnownBits(SLoad);
762+
EXPECT_EQ(Known.Zero, APInt(32, 0xfffffffe));
763+
EXPECT_EQ(Known.One, APInt(32, 0));
764+
}
765+
766+
TEST_F(AArch64SelectionDAGTest, computeKnownBits_extload_knownnegative) {
767+
SDLoc Loc;
768+
auto Int8VT = EVT::getIntegerVT(Context, 8);
769+
auto Int32VT = EVT::getIntegerVT(Context, 32);
770+
auto Int64VT = EVT::getIntegerVT(Context, 64);
771+
auto Ptr = DAG->getConstant(0, Loc, Int64VT);
772+
auto PtrInfo =
773+
MachinePointerInfo::getFixedStack(DAG->getMachineFunction(), 0);
774+
AAMDNodes AA;
775+
MDBuilder MDHelper(*DAG->getContext());
776+
MDNode *Range = MDHelper.createRange(APInt(8, 0xf0), APInt(8, 0xff));
777+
MachineMemOperand *MMO = DAG->getMachineFunction().getMachineMemOperand(
778+
PtrInfo, MachineMemOperand::MOLoad, 8, Align(8), AA, Range);
779+
780+
auto ALoad = DAG->getExtLoad(ISD::EXTLOAD, Loc, Int32VT, DAG->getEntryNode(),
781+
Ptr, Int8VT, MMO);
782+
KnownBits Known = DAG->computeKnownBits(ALoad);
783+
EXPECT_EQ(Known.Zero, APInt(32, 0));
784+
EXPECT_EQ(Known.One, APInt(32, 0xf0));
785+
786+
auto ZLoad = DAG->getExtLoad(ISD::ZEXTLOAD, Loc, Int32VT, DAG->getEntryNode(),
787+
Ptr, Int8VT, MMO);
788+
Known = DAG->computeKnownBits(ZLoad);
789+
EXPECT_EQ(Known.Zero, APInt(32, 0xffffff00));
790+
EXPECT_EQ(Known.One, APInt(32, 0x000000f0));
791+
792+
auto SLoad = DAG->getExtLoad(ISD::SEXTLOAD, Loc, Int32VT, DAG->getEntryNode(),
793+
Ptr, Int8VT, MMO);
794+
Known = DAG->computeKnownBits(SLoad);
795+
EXPECT_EQ(Known.Zero, APInt(32, 0));
796+
EXPECT_EQ(Known.One, APInt(32, 0xfffffff0));
797+
}
798+
731799
} // end namespace llvm

0 commit comments

Comments
 (0)