[llvm] [RISCV] Implement RISCVTTIImpl::shouldConsiderAddressTypePromotion for RISCV (PR #102560)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Aug 11 23:58:22 PDT 2024
https://github.com/LiqinWeng updated https://github.com/llvm/llvm-project/pull/102560
>From dc423e4727560c5257b9a624fa2a8bee30e7b4e2 Mon Sep 17 00:00:00 2001
From: LiqinWeng <liqin.weng at spacemit.com>
Date: Mon, 5 Aug 2024 17:54:05 +0800
Subject: [PATCH 1/2] [Test] add test to implement
'RISCVTTIImpl::shouldConsiderAddressTypePromotion' for RISCV
---
.../RISCV/riscv-codegen-prepare-atp.ll | 95 +++++++++++++++++++
1 file changed, 95 insertions(+)
create mode 100644 llvm/test/CodeGen/RISCV/riscv-codegen-prepare-atp.ll
diff --git a/llvm/test/CodeGen/RISCV/riscv-codegen-prepare-atp.ll b/llvm/test/CodeGen/RISCV/riscv-codegen-prepare-atp.ll
new file mode 100644
index 00000000000000..06d95366e3f83b
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/riscv-codegen-prepare-atp.ll
@@ -0,0 +1,95 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
+; RUN: opt -passes='require<profile-summary>,function(codegenprepare)' < %s -S | FileCheck %s
+
+target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "riscv64"
+
+%struct.match_state = type { i64, i64 }
+
+; %add is also promoted by forking an extra sext.
+define void @promoteTwoOne(i32 %i, i32 %j, ptr %P1, ptr %P2 ) {
+; CHECK-LABEL: define void @promoteTwoOne(
+; CHECK-SAME: i32 [[I:%.*]], i32 [[J:%.*]], ptr [[P1:%.*]], ptr [[P2:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[I]], [[J]]
+; CHECK-NEXT: [[S:%.*]] = sext i32 [[ADD]] to i64
+; CHECK-NEXT: [[ADDR1:%.*]] = getelementptr inbounds i64, ptr [[P1]], i64 [[S]]
+; CHECK-NEXT: store i64 [[S]], ptr [[ADDR1]], align 8
+; CHECK-NEXT: [[S2:%.*]] = sext i32 [[I]] to i64
+; CHECK-NEXT: [[ADDR2:%.*]] = getelementptr inbounds i64, ptr [[P2]], i64 [[S2]]
+; CHECK-NEXT: store i64 [[S2]], ptr [[ADDR2]], align 8
+; CHECK-NEXT: ret void
+;
+entry:
+ %add = add nsw i32 %i, %j
+ %s = sext i32 %add to i64
+ %addr1 = getelementptr inbounds i64, ptr %P1, i64 %s
+ store i64 %s, ptr %addr1
+ %s2 = sext i32 %i to i64
+ %addr2 = getelementptr inbounds i64, ptr %P2, i64 %s2
+ store i64 %s2, ptr %addr2
+ ret void
+}
+
+; Both %add1 and %add2 are promoted by forking extra sexts.
+define void @promoteTwoTwo(i32 %i, i32 %j, i32 %k, ptr %P1, ptr %P2) {
+; CHECK-LABEL: define void @promoteTwoTwo(
+; CHECK-SAME: i32 [[I:%.*]], i32 [[J:%.*]], i32 [[K:%.*]], ptr [[P1:%.*]], ptr [[P2:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[ADD1:%.*]] = add nsw i32 [[J]], [[I]]
+; CHECK-NEXT: [[S:%.*]] = sext i32 [[ADD1]] to i64
+; CHECK-NEXT: [[ADDR1:%.*]] = getelementptr inbounds i64, ptr [[P1]], i64 [[S]]
+; CHECK-NEXT: store i64 [[S]], ptr [[ADDR1]], align 8
+; CHECK-NEXT: [[ADD2:%.*]] = add nsw i32 [[J]], [[K]]
+; CHECK-NEXT: [[S2:%.*]] = sext i32 [[ADD2]] to i64
+; CHECK-NEXT: [[ADDR2:%.*]] = getelementptr inbounds i64, ptr [[P2]], i64 [[S2]]
+; CHECK-NEXT: store i64 [[S2]], ptr [[ADDR2]], align 8
+; CHECK-NEXT: ret void
+;
+entry:
+ %add1 = add nsw i32 %j, %i
+ %s = sext i32 %add1 to i64
+ %addr1 = getelementptr inbounds i64, ptr %P1, i64 %s
+ store i64 %s, ptr %addr1
+ %add2 = add nsw i32 %j, %k
+ %s2 = sext i32 %add2 to i64
+ %addr2 = getelementptr inbounds i64, ptr %P2, i64 %s2
+ store i64 %s2, ptr %addr2
+ ret void
+}
+
+define i64 @promoteGEPSunk(i1 %cond, ptr %base, i32 %i) {
+; CHECK-LABEL: define i64 @promoteGEPSunk(
+; CHECK-SAME: i1 [[COND:%.*]], ptr [[BASE:%.*]], i32 [[I:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[I]], 1
+; CHECK-NEXT: [[S:%.*]] = sext i32 [[ADD]] to i64
+; CHECK-NEXT: [[ADDR:%.*]] = getelementptr inbounds i64, ptr [[BASE]], i64 [[S]]
+; CHECK-NEXT: [[ADD2:%.*]] = add nsw i32 [[I]], 2
+; CHECK-NEXT: [[S2:%.*]] = sext i32 [[ADD2]] to i64
+; CHECK-NEXT: [[ADDR2:%.*]] = getelementptr inbounds i64, ptr [[BASE]], i64 [[S2]]
+; CHECK-NEXT: br i1 [[COND]], label [[IF_THEN:%.*]], label [[IF_THEN2:%.*]]
+; CHECK: if.then:
+; CHECK-NEXT: [[V:%.*]] = load i64, ptr [[ADDR]], align 8
+; CHECK-NEXT: [[V2:%.*]] = load i64, ptr [[ADDR2]], align 8
+; CHECK-NEXT: [[R:%.*]] = add i64 [[V]], [[V2]]
+; CHECK-NEXT: ret i64 [[R]]
+; CHECK: if.then2:
+; CHECK-NEXT: ret i64 0
+;
+entry:
+ %add = add nsw i32 %i, 1
+ %s = sext i32 %add to i64
+ %addr = getelementptr inbounds i64, ptr %base, i64 %s
+ %add2 = add nsw i32 %i, 2
+ %s2 = sext i32 %add2 to i64
+ %addr2 = getelementptr inbounds i64, ptr %base, i64 %s2
+ br i1 %cond, label %if.then, label %if.then2
+if.then:
+ %v = load i64, ptr %addr
+ %v2 = load i64, ptr %addr2
+ %r = add i64 %v, %v2
+ ret i64 %r
+if.then2:
+ ret i64 0;
+}
>From b88f35f5c866d8268dc205829bf37ce6eb11b51c Mon Sep 17 00:00:00 2001
From: LiqinWeng <liqin.weng at spacemit.com>
Date: Tue, 6 Aug 2024 14:26:50 +0800
Subject: [PATCH 2/2] [RISCV] Implement
RISCVTTIImpl::shouldConsiderAddressTypePromotion for RISCV
---
llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 1 +
.../Target/RISCV/RISCVTargetTransformInfo.cpp | 32 +++++++++++++++++++
.../Target/RISCV/RISCVTargetTransformInfo.h | 4 ++-
.../RISCV/riscv-codegen-prepare-atp.ll | 22 ++++++-------
4 files changed, 47 insertions(+), 12 deletions(-)
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 872c288f5ad8cd..be19bc23805e49 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -1424,6 +1424,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
// Disable strict node mutation.
IsStrictFPEnabled = true;
+ EnableExtLdPromotion = true;
// Let the subtarget decide if a predictable select is more expensive than the
// corresponding branch. This information is used in CGP/SelectOpt to decide
diff --git a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp
index 4cd904c039a984..b8e9c26e1513d5 100644
--- a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp
@@ -1989,3 +1989,35 @@ bool RISCVTTIImpl::areInlineCompatible(const Function *Caller,
// target-features.
return (CallerBits & CalleeBits) == CalleeBits;
}
+
+/// See if \p I should be considered for address type promotion. We check if \p
+/// I is a sext with right type and used in memory accesses. If it used in a
+/// "complex" getelementptr, we allow it to be promoted without finding other
+/// sext instructions that sign extended the same initial value. A getelementptr
+/// is considered as "complex" if it has more than 2 operands.
+bool RISCVTTIImpl::shouldConsiderAddressTypePromotion(
+ const Instruction &I, bool &AllowPromotionWithoutCommonHeader) {
+ bool Considerable = false;
+ AllowPromotionWithoutCommonHeader = false;
+ if (!isa<SExtInst>(&I))
+ return false;
+ Type *ConsideredSExtType =
+ Type::getInt64Ty(I.getParent()->getParent()->getContext());
+ if (I.getType() != ConsideredSExtType)
+ return false;
+ // See if the sext is the one with the right type and used in at least one
+ // GetElementPtrInst.
+ for (const User *U : I.users()) {
+ if (const GetElementPtrInst *GEPInst = dyn_cast<GetElementPtrInst>(U)) {
+ Considerable = true;
+ // A getelementptr is considered as "complex" if it has more than 2
+ // operands. We will promote a SExt used in such complex GEP as we
+ // expect some computation to be merged if they are done on 64 bits.
+ if (GEPInst->getNumOperands() > 2) {
+ AllowPromotionWithoutCommonHeader = true;
+ break;
+ }
+ }
+ }
+ return Considerable;
+}
diff --git a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h
index 9c37a4f6ec2d04..f5eca2839acd05 100644
--- a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h
+++ b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h
@@ -397,7 +397,9 @@ class RISCVTTIImpl : public BasicTTIImplBase<RISCVTTIImpl> {
bool shouldFoldTerminatingConditionAfterLSR() const {
return true;
}
-
+ bool
+ shouldConsiderAddressTypePromotion(const Instruction &I,
+ bool &AllowPromotionWithoutCommonHeader);
std::optional<unsigned> getMinPageSize() const { return 4096; }
};
diff --git a/llvm/test/CodeGen/RISCV/riscv-codegen-prepare-atp.ll b/llvm/test/CodeGen/RISCV/riscv-codegen-prepare-atp.ll
index 06d95366e3f83b..b733c6a1c787ba 100644
--- a/llvm/test/CodeGen/RISCV/riscv-codegen-prepare-atp.ll
+++ b/llvm/test/CodeGen/RISCV/riscv-codegen-prepare-atp.ll
@@ -11,11 +11,11 @@ define void @promoteTwoOne(i32 %i, i32 %j, ptr %P1, ptr %P2 ) {
; CHECK-LABEL: define void @promoteTwoOne(
; CHECK-SAME: i32 [[I:%.*]], i32 [[J:%.*]], ptr [[P1:%.*]], ptr [[P2:%.*]]) {
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[I]], [[J]]
-; CHECK-NEXT: [[S:%.*]] = sext i32 [[ADD]] to i64
+; CHECK-NEXT: [[S2:%.*]] = sext i32 [[I]] to i64
+; CHECK-NEXT: [[PROMOTED2:%.*]] = sext i32 [[J]] to i64
+; CHECK-NEXT: [[S:%.*]] = add nsw i64 [[S2]], [[PROMOTED2]]
; CHECK-NEXT: [[ADDR1:%.*]] = getelementptr inbounds i64, ptr [[P1]], i64 [[S]]
; CHECK-NEXT: store i64 [[S]], ptr [[ADDR1]], align 8
-; CHECK-NEXT: [[S2:%.*]] = sext i32 [[I]] to i64
; CHECK-NEXT: [[ADDR2:%.*]] = getelementptr inbounds i64, ptr [[P2]], i64 [[S2]]
; CHECK-NEXT: store i64 [[S2]], ptr [[ADDR2]], align 8
; CHECK-NEXT: ret void
@@ -36,12 +36,13 @@ define void @promoteTwoTwo(i32 %i, i32 %j, i32 %k, ptr %P1, ptr %P2) {
; CHECK-LABEL: define void @promoteTwoTwo(
; CHECK-SAME: i32 [[I:%.*]], i32 [[J:%.*]], i32 [[K:%.*]], ptr [[P1:%.*]], ptr [[P2:%.*]]) {
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[ADD1:%.*]] = add nsw i32 [[J]], [[I]]
-; CHECK-NEXT: [[S:%.*]] = sext i32 [[ADD1]] to i64
+; CHECK-NEXT: [[PROMOTED3:%.*]] = sext i32 [[J]] to i64
+; CHECK-NEXT: [[PROMOTED4:%.*]] = sext i32 [[I]] to i64
+; CHECK-NEXT: [[S:%.*]] = add nsw i64 [[PROMOTED3]], [[PROMOTED4]]
; CHECK-NEXT: [[ADDR1:%.*]] = getelementptr inbounds i64, ptr [[P1]], i64 [[S]]
; CHECK-NEXT: store i64 [[S]], ptr [[ADDR1]], align 8
-; CHECK-NEXT: [[ADD2:%.*]] = add nsw i32 [[J]], [[K]]
-; CHECK-NEXT: [[S2:%.*]] = sext i32 [[ADD2]] to i64
+; CHECK-NEXT: [[PROMOTED2:%.*]] = sext i32 [[K]] to i64
+; CHECK-NEXT: [[S2:%.*]] = add nsw i64 [[PROMOTED3]], [[PROMOTED2]]
; CHECK-NEXT: [[ADDR2:%.*]] = getelementptr inbounds i64, ptr [[P2]], i64 [[S2]]
; CHECK-NEXT: store i64 [[S2]], ptr [[ADDR2]], align 8
; CHECK-NEXT: ret void
@@ -62,11 +63,10 @@ define i64 @promoteGEPSunk(i1 %cond, ptr %base, i32 %i) {
; CHECK-LABEL: define i64 @promoteGEPSunk(
; CHECK-SAME: i1 [[COND:%.*]], ptr [[BASE:%.*]], i32 [[I:%.*]]) {
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[I]], 1
-; CHECK-NEXT: [[S:%.*]] = sext i32 [[ADD]] to i64
+; CHECK-NEXT: [[PROMOTED1:%.*]] = sext i32 [[I]] to i64
+; CHECK-NEXT: [[S:%.*]] = add nsw i64 [[PROMOTED1]], 1
; CHECK-NEXT: [[ADDR:%.*]] = getelementptr inbounds i64, ptr [[BASE]], i64 [[S]]
-; CHECK-NEXT: [[ADD2:%.*]] = add nsw i32 [[I]], 2
-; CHECK-NEXT: [[S2:%.*]] = sext i32 [[ADD2]] to i64
+; CHECK-NEXT: [[S2:%.*]] = add nsw i64 [[PROMOTED1]], 2
; CHECK-NEXT: [[ADDR2:%.*]] = getelementptr inbounds i64, ptr [[BASE]], i64 [[S2]]
; CHECK-NEXT: br i1 [[COND]], label [[IF_THEN:%.*]], label [[IF_THEN2:%.*]]
; CHECK: if.then:
More information about the llvm-commits
mailing list