-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[DAGCombiner][RISCV] Add target hook to decide hoisting LogicOp with extension #136677
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…extension. This patch introduces a new target hook `isDesirableToHoistLogicOpWithExt` to allow target to decide hoisting LogicOp where both operands have the same extension op. By default it returns true. On RISC-V, (or disjoint (sext/zext a), (sext/zext b)) can be combined as vwadd.vv/vwaddu.vv. So for such case, it returns false.
@llvm/pr-subscribers-backend-risc-v Author: Jim Lin (tclin914) ChangesThis patch introduces a new target hook On RISC-V, (or disjoint (sext/zext a), (sext/zext b)) can be combined as vwadd.vv/vwaddu.vv. So for such case, it returns false. Full diff: https://github.com/llvm/llvm-project/pull/136677.diff 5 Files Affected:
diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h
index 00c36266a069f..90a1d0e52d8c8 100644
--- a/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -4462,6 +4462,16 @@ class TargetLowering : public TargetLoweringBase {
return false;
}
+ /// Return true if it is profitable to hoist a LogicOp where both operands
+ /// have the same extension op. This transformation may not be desirable if
+ /// it disrupts a particularly auspicious target-specific tree (e.g.
+ /// (or disjoint (zext A), (zext B)) -> vwaddu.wv on RISC-V). By default it
+ /// returns true.
+ virtual bool isDesirableToHoistLogicOpWithExt(const SDNode *LogicOp,
+ unsigned ExtOp) const {
+ return true;
+ }
+
/// Return true if the target supports swifterror attribute. It optimizes
/// loads and stores to reading and writing a specific register.
virtual bool supportSwiftError() const {
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index b175e35385ec6..6cbf2b6682929 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -5981,6 +5981,9 @@ SDValue DAGCombiner::hoistLogicOpWithSameOpcodeHands(SDNode *N) {
HandOpcode == ISD::ANY_EXTEND_VECTOR_INREG) &&
LegalTypes && !TLI.isTypeDesirableForOp(LogicOpcode, XVT))
return SDValue();
+ // If it is not desirable to hoist LogicOp with extension.
+ if (!TLI.isDesirableToHoistLogicOpWithExt(N, HandOpcode))
+ return SDValue();
// logic_op (hand_op X), (hand_op Y) --> hand_op (logic_op X, Y)
SDValue Logic = DAG.getNode(LogicOpcode, DL, XVT, X, Y);
if (HandOpcode == ISD::SIGN_EXTEND_INREG)
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 98fba9e86e88a..fe520c0298148 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -19893,6 +19893,14 @@ bool RISCVTargetLowering::isDesirableToCommuteWithShift(
return true;
}
+bool RISCVTargetLowering::isDesirableToHoistLogicOpWithExt(
+ const SDNode *LogicOp, unsigned ExtOp) const {
+ if (NodeExtensionHelper::isSupportedRoot(LogicOp, Subtarget) &&
+ (ExtOp == ISD::ZERO_EXTEND || ExtOp == ISD::SIGN_EXTEND))
+ return false;
+ return true;
+}
+
bool RISCVTargetLowering::targetShrinkDemandedConstant(
SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts,
TargetLoweringOpt &TLO) const {
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h
index baf1b2e4d8e6e..63d2fa95d5034 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.h
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h
@@ -747,6 +747,9 @@ class RISCVTargetLowering : public TargetLowering {
bool isDesirableToCommuteWithShift(const SDNode *N,
CombineLevel Level) const override;
+ bool isDesirableToHoistLogicOpWithExt(const SDNode *LogicOp,
+ unsigned ExtOp) const override;
+
/// If a physical register, this returns the register that receives the
/// exception address on entry to an EH pad.
Register
diff --git a/llvm/test/CodeGen/RISCV/rvv/vwadd-sdnode.ll b/llvm/test/CodeGen/RISCV/rvv/vwadd-sdnode.ll
index 3f5d42f89337b..149950484c477 100644
--- a/llvm/test/CodeGen/RISCV/rvv/vwadd-sdnode.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/vwadd-sdnode.ll
@@ -1417,15 +1417,12 @@ define <vscale x 2 x i32> @vwaddu_vv_disjoint_or_add(<vscale x 2 x i8> %x.i8, <v
ret <vscale x 2 x i32> %add
}
-; TODO: We could select vwaddu.vv, but when both arms of the or are the same
-; DAGCombiner::hoistLogicOpWithSameOpcodeHands moves the zext above the or.
define <vscale x 2 x i32> @vwaddu_vv_disjoint_or(<vscale x 2 x i16> %x.i16, <vscale x 2 x i16> %y.i16) {
; CHECK-LABEL: vwaddu_vv_disjoint_or:
; CHECK: # %bb.0:
; CHECK-NEXT: vsetvli a0, zero, e16, mf2, ta, ma
-; CHECK-NEXT: vor.vv v9, v8, v9
-; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, ma
-; CHECK-NEXT: vzext.vf2 v8, v9
+; CHECK-NEXT: vwaddu.vv v10, v8, v9
+; CHECK-NEXT: vmv1r.v v8, v10
; CHECK-NEXT: ret
%x.i32 = zext <vscale x 2 x i16> %x.i16 to <vscale x 2 x i32>
%y.i32 = zext <vscale x 2 x i16> %y.i16 to <vscale x 2 x i32>
@@ -1433,15 +1430,12 @@ define <vscale x 2 x i32> @vwaddu_vv_disjoint_or(<vscale x 2 x i16> %x.i16, <vsc
ret <vscale x 2 x i32> %or
}
-; TODO: We could select vwadd.vv, but when both arms of the or are the same
-; DAGCombiner::hoistLogicOpWithSameOpcodeHands moves the zext above the or.
define <vscale x 2 x i32> @vwadd_vv_disjoint_or(<vscale x 2 x i16> %x.i16, <vscale x 2 x i16> %y.i16) {
; CHECK-LABEL: vwadd_vv_disjoint_or:
; CHECK: # %bb.0:
; CHECK-NEXT: vsetvli a0, zero, e16, mf2, ta, ma
-; CHECK-NEXT: vor.vv v9, v8, v9
-; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, ma
-; CHECK-NEXT: vsext.vf2 v8, v9
+; CHECK-NEXT: vwadd.vv v10, v8, v9
+; CHECK-NEXT: vmv1r.v v8, v10
; CHECK-NEXT: ret
%x.i32 = sext <vscale x 2 x i16> %x.i16 to <vscale x 2 x i32>
%y.i32 = sext <vscale x 2 x i16> %y.i16 to <vscale x 2 x i32>
|
@llvm/pr-subscribers-llvm-selectiondag Author: Jim Lin (tclin914) ChangesThis patch introduces a new target hook On RISC-V, (or disjoint (sext/zext a), (sext/zext b)) can be combined as vwadd.vv/vwaddu.vv. So for such case, it returns false. Full diff: https://github.com/llvm/llvm-project/pull/136677.diff 5 Files Affected:
diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h
index 00c36266a069f..90a1d0e52d8c8 100644
--- a/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -4462,6 +4462,16 @@ class TargetLowering : public TargetLoweringBase {
return false;
}
+ /// Return true if it is profitable to hoist a LogicOp where both operands
+ /// have the same extension op. This transformation may not be desirable if
+ /// it disrupts a particularly auspicious target-specific tree (e.g.
+ /// (or disjoint (zext A), (zext B)) -> vwaddu.wv on RISC-V). By default it
+ /// returns true.
+ virtual bool isDesirableToHoistLogicOpWithExt(const SDNode *LogicOp,
+ unsigned ExtOp) const {
+ return true;
+ }
+
/// Return true if the target supports swifterror attribute. It optimizes
/// loads and stores to reading and writing a specific register.
virtual bool supportSwiftError() const {
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index b175e35385ec6..6cbf2b6682929 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -5981,6 +5981,9 @@ SDValue DAGCombiner::hoistLogicOpWithSameOpcodeHands(SDNode *N) {
HandOpcode == ISD::ANY_EXTEND_VECTOR_INREG) &&
LegalTypes && !TLI.isTypeDesirableForOp(LogicOpcode, XVT))
return SDValue();
+ // If it is not desirable to hoist LogicOp with extension.
+ if (!TLI.isDesirableToHoistLogicOpWithExt(N, HandOpcode))
+ return SDValue();
// logic_op (hand_op X), (hand_op Y) --> hand_op (logic_op X, Y)
SDValue Logic = DAG.getNode(LogicOpcode, DL, XVT, X, Y);
if (HandOpcode == ISD::SIGN_EXTEND_INREG)
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 98fba9e86e88a..fe520c0298148 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -19893,6 +19893,14 @@ bool RISCVTargetLowering::isDesirableToCommuteWithShift(
return true;
}
+bool RISCVTargetLowering::isDesirableToHoistLogicOpWithExt(
+ const SDNode *LogicOp, unsigned ExtOp) const {
+ if (NodeExtensionHelper::isSupportedRoot(LogicOp, Subtarget) &&
+ (ExtOp == ISD::ZERO_EXTEND || ExtOp == ISD::SIGN_EXTEND))
+ return false;
+ return true;
+}
+
bool RISCVTargetLowering::targetShrinkDemandedConstant(
SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts,
TargetLoweringOpt &TLO) const {
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h
index baf1b2e4d8e6e..63d2fa95d5034 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.h
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h
@@ -747,6 +747,9 @@ class RISCVTargetLowering : public TargetLowering {
bool isDesirableToCommuteWithShift(const SDNode *N,
CombineLevel Level) const override;
+ bool isDesirableToHoistLogicOpWithExt(const SDNode *LogicOp,
+ unsigned ExtOp) const override;
+
/// If a physical register, this returns the register that receives the
/// exception address on entry to an EH pad.
Register
diff --git a/llvm/test/CodeGen/RISCV/rvv/vwadd-sdnode.ll b/llvm/test/CodeGen/RISCV/rvv/vwadd-sdnode.ll
index 3f5d42f89337b..149950484c477 100644
--- a/llvm/test/CodeGen/RISCV/rvv/vwadd-sdnode.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/vwadd-sdnode.ll
@@ -1417,15 +1417,12 @@ define <vscale x 2 x i32> @vwaddu_vv_disjoint_or_add(<vscale x 2 x i8> %x.i8, <v
ret <vscale x 2 x i32> %add
}
-; TODO: We could select vwaddu.vv, but when both arms of the or are the same
-; DAGCombiner::hoistLogicOpWithSameOpcodeHands moves the zext above the or.
define <vscale x 2 x i32> @vwaddu_vv_disjoint_or(<vscale x 2 x i16> %x.i16, <vscale x 2 x i16> %y.i16) {
; CHECK-LABEL: vwaddu_vv_disjoint_or:
; CHECK: # %bb.0:
; CHECK-NEXT: vsetvli a0, zero, e16, mf2, ta, ma
-; CHECK-NEXT: vor.vv v9, v8, v9
-; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, ma
-; CHECK-NEXT: vzext.vf2 v8, v9
+; CHECK-NEXT: vwaddu.vv v10, v8, v9
+; CHECK-NEXT: vmv1r.v v8, v10
; CHECK-NEXT: ret
%x.i32 = zext <vscale x 2 x i16> %x.i16 to <vscale x 2 x i32>
%y.i32 = zext <vscale x 2 x i16> %y.i16 to <vscale x 2 x i32>
@@ -1433,15 +1430,12 @@ define <vscale x 2 x i32> @vwaddu_vv_disjoint_or(<vscale x 2 x i16> %x.i16, <vsc
ret <vscale x 2 x i32> %or
}
-; TODO: We could select vwadd.vv, but when both arms of the or are the same
-; DAGCombiner::hoistLogicOpWithSameOpcodeHands moves the zext above the or.
define <vscale x 2 x i32> @vwadd_vv_disjoint_or(<vscale x 2 x i16> %x.i16, <vscale x 2 x i16> %y.i16) {
; CHECK-LABEL: vwadd_vv_disjoint_or:
; CHECK: # %bb.0:
; CHECK-NEXT: vsetvli a0, zero, e16, mf2, ta, ma
-; CHECK-NEXT: vor.vv v9, v8, v9
-; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, ma
-; CHECK-NEXT: vsext.vf2 v8, v9
+; CHECK-NEXT: vwadd.vv v10, v8, v9
+; CHECK-NEXT: vmv1r.v v8, v10
; CHECK-NEXT: ret
%x.i32 = sext <vscale x 2 x i16> %x.i16 to <vscale x 2 x i32>
%y.i32 = sext <vscale x 2 x i16> %y.i16 to <vscale x 2 x i32>
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. I wonder if we should just add a pattern for disjoint ors rather than adding yet another target hook for DAGCombiner. But I think we can explore that in a follow up
DAGCombiner::hoistLogicOpWithSameOpcodeHands will hoist (or disjoint (ext a), (ext b)) -> (ext (or disjoint a, b)) So this adds a pattern to match vwadd[u].vv in this case. We have to teach the combine to preserve the disjoint flag, and add a generic PatFrag for a disjoint or. This is meant to be a follow up to llvm#136677 which would allow us to remove the target hook added there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM w/ one nit comment
if ((ExtOp == ISD::ZERO_EXTEND || ExtOp == ISD::SIGN_EXTEND) && | ||
NodeExtensionHelper::isSupportedRoot(LogicOp, Subtarget)) | ||
return false; | ||
return true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe combine this into a single return?
Doesn't InstCombine do the same transform as isDesirableToHoistLogicOpWithExt? https://godbolt.org/z/rM3dWh83e Do we have a transform to turn it back into (or disjoint (sext/zext a), (sext/zext b))? If not then this patch isn't all that useful by itself. |
virtual bool isDesirableToHoistLogicOpWithExt(const SDNode *LogicOp, | ||
unsigned ExtOp) const { | ||
return true; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't you just select on the hoisted form of the pattern
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See #136716
Keep disjoint #136815 if it is transformed during InstCombine. |
This patch introduces a new target hook
isDesirableToHoistLogicOpWithExt
to allow target to decide hoisting LogicOp where both operands have the same extension op. By default it returns true.On RISC-V, (or disjoint (sext/zext a), (sext/zext b)) can be combined as vwadd.vv/vwaddu.vv. So for such case, it returns false.