aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Jonson <andjo403@hotmail.com>2024-06-14 10:04:33 +0200
committerGitHub <noreply@github.com>2024-06-14 10:04:33 +0200
commitae71609e91ec9f38df7e92ba3c50a1f9cebb772e (patch)
tree6a2ad37d583bfd3cf255781d61b0a6d374e5934a
parent706e1975400b3f30bd406b694bb711a7c7dbe1c4 (diff)
downloadllvm-ae71609e91ec9f38df7e92ba3c50a1f9cebb772e.zip
llvm-ae71609e91ec9f38df7e92ba3c50a1f9cebb772e.tar.gz
llvm-ae71609e91ec9f38df7e92ba3c50a1f9cebb772e.tar.bz2
[SDAG] Lower range attribute to AssertZext (#95450)
Add support for range attributes on calls, in addition to range metadata.
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp22
-rw-r--r--llvm/test/CodeGen/AArch64/lower-range-metadata-func-call.ll22
-rw-r--r--llvm/test/CodeGen/X86/legalize-vec-assertzext.ll18
3 files changed, 55 insertions, 7 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 2b82d87..98555b3 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -4487,6 +4487,17 @@ static const MDNode *getRangeMetadata(const Instruction &I) {
return I.getMetadata(LLVMContext::MD_range);
}
+static std::optional<ConstantRange> getRange(const Instruction &I) {
+ if (const auto *CB = dyn_cast<CallBase>(&I)) {
+ // see comment in getRangeMetadata about this check
+ if (CB->hasRetAttr(Attribute::NoUndef))
+ return CB->getRange();
+ }
+ if (const MDNode *Range = getRangeMetadata(I))
+ return getConstantRangeFromMetadata(*Range);
+ return std::nullopt;
+}
+
void SelectionDAGBuilder::visitLoad(const LoadInst &I) {
if (I.isAtomic())
return visitAtomicLoad(I);
@@ -10230,19 +10241,16 @@ void SelectionDAGBuilder::visitVACopy(const CallInst &I) {
SDValue SelectionDAGBuilder::lowerRangeToAssertZExt(SelectionDAG &DAG,
const Instruction &I,
SDValue Op) {
- const MDNode *Range = getRangeMetadata(I);
- if (!Range)
- return Op;
+ std::optional<ConstantRange> CR = getRange(I);
- ConstantRange CR = getConstantRangeFromMetadata(*Range);
- if (CR.isFullSet() || CR.isEmptySet() || CR.isUpperWrapped())
+ if (!CR || CR->isFullSet() || CR->isEmptySet() || CR->isUpperWrapped())
return Op;
- APInt Lo = CR.getUnsignedMin();
+ APInt Lo = CR->getUnsignedMin();
if (!Lo.isMinValue())
return Op;
- APInt Hi = CR.getUnsignedMax();
+ APInt Hi = CR->getUnsignedMax();
unsigned Bits = std::max(Hi.getActiveBits(),
static_cast<unsigned>(IntegerType::MIN_INT_BITS));
diff --git a/llvm/test/CodeGen/AArch64/lower-range-metadata-func-call.ll b/llvm/test/CodeGen/AArch64/lower-range-metadata-func-call.ll
index 5b9a734..5af8189 100644
--- a/llvm/test/CodeGen/AArch64/lower-range-metadata-func-call.ll
+++ b/llvm/test/CodeGen/AArch64/lower-range-metadata-func-call.ll
@@ -34,6 +34,28 @@ entry:
ret i32 %and
}
+; and can be eliminated
+; CHECK-LABEL: {{^}}test_call_known_max_range_attr:
+; CHECK: bl foo
+; CHECK-NOT: and
+; CHECK: ret
+define i32 @test_call_known_max_range_attr() #0 {
+entry:
+ %id = tail call noundef range(i32 0, 1024) i32 @foo()
+ %and = and i32 %id, 1023
+ ret i32 %and
+}
+
+; CHECK-LABEL: {{^}}test_call_known_max_range_attr_no_noundef:
+; CHECK: bl foo
+; CHECK: and w{{[0-9]+}}, w0, #0x3ff
+; CHECK: ret
+define i32 @test_call_known_max_range_attr_no_noundef() #0 {
+entry:
+ %id = tail call range(i32 0, 1024) i32 @foo()
+ %and = and i32 %id, 1023
+ ret i32 %and
+}
declare i32 @foo()
diff --git a/llvm/test/CodeGen/X86/legalize-vec-assertzext.ll b/llvm/test/CodeGen/X86/legalize-vec-assertzext.ll
index 1c595b7..2cf37c6 100644
--- a/llvm/test/CodeGen/X86/legalize-vec-assertzext.ll
+++ b/llvm/test/CodeGen/X86/legalize-vec-assertzext.ll
@@ -34,6 +34,24 @@ define i64 @widen_assertzext(ptr %x) nounwind {
ret i64 %d
}
+define i64 @widen_assertzext_range_attr(ptr %x) nounwind {
+; CHECK-LABEL: widen_assertzext_range_attr:
+; CHECK: # %bb.0:
+; CHECK-NEXT: pushq %rax
+; CHECK-NEXT: callq test2@PLT
+; CHECK-NEXT: movb $127, %al
+; CHECK-NEXT: kmovw %eax, %k1
+; CHECK-NEXT: vpexpandq %zmm0, %zmm0 {%k1} {z}
+; CHECK-NEXT: vextracti32x4 $3, %zmm0, %xmm0
+; CHECK-NEXT: vmovq %xmm0, %rax
+; CHECK-NEXT: popq %rcx
+; CHECK-NEXT: vzeroupper
+; CHECK-NEXT: retq
+ %e = call noundef range(i64 0, 2) <7 x i64> @test2()
+ %d = extractelement <7 x i64> %e, i32 6
+ ret i64 %d
+}
+
declare <16 x i64> @test()
declare <7 x i64> @test2()
!0 = !{ i64 0, i64 2 }