Skip to content

Commit 5b14559

Browse files
committed
[DAG] Improve known bits of Zext/Sext loads with range metadata
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 BitWidths.
1 parent 8f7ae64 commit 5b14559

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().getSizeInBits()
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)