Skip to content

[RISCV] Select Zvkb VANDN for shorter constant loading sequences #123345

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

Merged
merged 1 commit into from
Jan 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3224,8 +3224,25 @@ bool RISCVDAGToDAGISel::selectInvLogicImm(SDValue N, SDValue &Val) {

// Abandon this transform if the constant is needed elsewhere.
for (const SDNode *U : N->users()) {
if (!ISD::isBitwiseLogicOp(U->getOpcode()))
switch (U->getOpcode()) {
case ISD::AND:
case ISD::OR:
case ISD::XOR:
if (!(Subtarget->hasStdExtZbb() || Subtarget->hasStdExtZbkb()))
return false;
break;
case RISCVISD::VMV_V_X_VL:
if (!Subtarget->hasStdExtZvkb())
return false;
if (!all_of(U->users(), [](const SDNode *V) {
return V->getOpcode() == ISD::AND ||
V->getOpcode() == RISCVISD::AND_VL;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shall I check if that's not the passthru operand? If so, how to test it?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ISD::AND doesn't have a passthru. For RISCV::AND_VL you would need to loop through U->uses() instead of U->users(). That will give you an SDUse &. From there you can call SDUse::getUser() to get V and SDUse::getOperandNo to get the operand number of the use. The passthru will be operand 2.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How to test? Is @llvm.riscv.vand's first operand the passthru?

Would it be possible for the same VMV_V_X_VL to be the AND_VL passthru and one of the AND_VL "and" operands at the same time?

Would the following work:

      if (!all_of(U->users(), [U](const SDNode *V) {
             return V->getOpcode() == ISD::AND ||
                   (V->getOpcode() == RISCVISD::AND_VL &&
                    U != V->getOperand(2).getNode()); // not passthru
           }))

?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How to test? Is @llvm.riscv.vand's first operand the passthru?

@llvm.riscv.vand uses ISD::INTRINSIC_WO_CHAIN rather than than RISCVISD::AND_VL. RISCVISD::AND_VL is primarily created from @llvm.vp.and or and on fixed vectors. There may be other sequences that requires an AND as part of a larger pattern.

I'm not sure if we ever use the passthru operand of RISCVISD::AND_VL for anything other than undef. There are many opcodes that are defined with the same operand structure, but we don't use the passthru for all of them.

Would it be possible for the same VMV_V_X_VL to be the AND_VL passthru and one of the AND_VL "and" operands at the same time?

I think its possible.

Would the following work:

  if (!all_of(U->users(), [U](const SDNode *V) {
         return V->getOpcode() == ISD::AND ||
               (V->getOpcode() == RISCVISD::AND_VL &&
                U != V->getOperand(2).getNode()); // not passthru
       }))

I think that works.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will you approve this PR as-is then?
I don't think adding untested code is a good idea. In the unlikely event of U somehow appearing in passthru, it would only lead to somewhat suboptimal code.

}))
return false;
break;
default:
return false;
}
}

// For 64-bit constants, the instruction sequences get complex,
Expand Down
21 changes: 21 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfoZvk.td
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,13 @@ foreach vti = AllIntegerVectors in {
vti.RegClass:$rs2,
vti.ScalarRegClass:$rs1,
vti.AVL, vti.Log2SEW, TA_MA)>;
def : Pat<(vti.Vector (and (riscv_splat_vector invLogicImm:$rs1),
vti.RegClass:$rs2)),
(!cast<Instruction>("PseudoVANDN_VX_"#vti.LMul.MX)
(vti.Vector (IMPLICIT_DEF)),
vti.RegClass:$rs2,
invLogicImm:$rs1,
vti.AVL, vti.Log2SEW, TA_MA)>;
}
}

Expand Down Expand Up @@ -758,6 +765,20 @@ foreach vti = AllIntegerVectors in {
GPR:$vl,
vti.Log2SEW,
TAIL_AGNOSTIC)>;

def : Pat<(vti.Vector (riscv_and_vl (riscv_splat_vector invLogicImm:$rs1),
(vti.Vector vti.RegClass:$rs2),
(vti.Vector vti.RegClass:$passthru),
(vti.Mask V0),
VLOpFrag)),
(!cast<Instruction>("PseudoVANDN_VX_"#vti.LMul.MX#"_MASK")
vti.RegClass:$passthru,
vti.RegClass:$rs2,
invLogicImm:$rs1,
(vti.Mask V0),
GPR:$vl,
vti.Log2SEW,
TAIL_AGNOSTIC)>;
}
}

Expand Down
54 changes: 28 additions & 26 deletions llvm/test/CodeGen/RISCV/rvv/vandn-sdnode.ll
Original file line number Diff line number Diff line change
Expand Up @@ -1945,10 +1945,9 @@ define <vscale x 1 x i16> @vandn_vx_imm16(<vscale x 1 x i16> %x) {
;
; CHECK-ZVKB-LABEL: vandn_vx_imm16:
; CHECK-ZVKB: # %bb.0:
; CHECK-ZVKB-NEXT: lui a0, 8
; CHECK-ZVKB-NEXT: addi a0, a0, -1
; CHECK-ZVKB-NEXT: lui a0, 1048568
; CHECK-ZVKB-NEXT: vsetvli a1, zero, e16, mf4, ta, ma
; CHECK-ZVKB-NEXT: vand.vx v8, v8, a0
; CHECK-ZVKB-NEXT: vandn.vx v8, v8, a0
; CHECK-ZVKB-NEXT: ret
%a = and <vscale x 1 x i16> splat (i16 32767), %x
ret <vscale x 1 x i16> %a
Expand All @@ -1965,10 +1964,9 @@ define <vscale x 1 x i16> @vandn_vx_swapped_imm16(<vscale x 1 x i16> %x) {
;
; CHECK-ZVKB-LABEL: vandn_vx_swapped_imm16:
; CHECK-ZVKB: # %bb.0:
; CHECK-ZVKB-NEXT: lui a0, 8
; CHECK-ZVKB-NEXT: addi a0, a0, -1
; CHECK-ZVKB-NEXT: lui a0, 1048568
; CHECK-ZVKB-NEXT: vsetvli a1, zero, e16, mf4, ta, ma
; CHECK-ZVKB-NEXT: vand.vx v8, v8, a0
; CHECK-ZVKB-NEXT: vandn.vx v8, v8, a0
; CHECK-ZVKB-NEXT: ret
%a = and <vscale x 1 x i16> %x, splat (i16 32767)
ret <vscale x 1 x i16> %a
Expand Down Expand Up @@ -2018,11 +2016,10 @@ define <vscale x 1 x i64> @vandn_vx_imm64(<vscale x 1 x i64> %x) {
;
; CHECK-ZVKB64-LABEL: vandn_vx_imm64:
; CHECK-ZVKB64: # %bb.0:
; CHECK-ZVKB64-NEXT: li a0, -1
; CHECK-ZVKB64-NEXT: slli a0, a0, 56
; CHECK-ZVKB64-NEXT: addi a0, a0, 255
; CHECK-ZVKB64-NEXT: lui a0, 1048560
; CHECK-ZVKB64-NEXT: srli a0, a0, 8
; CHECK-ZVKB64-NEXT: vsetvli a1, zero, e64, m1, ta, ma
; CHECK-ZVKB64-NEXT: vand.vx v8, v8, a0
; CHECK-ZVKB64-NEXT: vandn.vx v8, v8, a0
; CHECK-ZVKB64-NEXT: ret
%a = and <vscale x 1 x i64> %x, splat (i64 -72057594037927681)
ret <vscale x 1 x i64> %a
Expand All @@ -2041,11 +2038,10 @@ define <vscale x 1 x i16> @vandn_vx_multi_imm16(<vscale x 1 x i16> %x, <vscale x
;
; CHECK-ZVKB-LABEL: vandn_vx_multi_imm16:
; CHECK-ZVKB: # %bb.0:
; CHECK-ZVKB-NEXT: lui a0, 4
; CHECK-ZVKB-NEXT: addi a0, a0, -1
; CHECK-ZVKB-NEXT: lui a0, 1048572
; CHECK-ZVKB-NEXT: vsetvli a1, zero, e16, mf4, ta, ma
; CHECK-ZVKB-NEXT: vand.vx v8, v8, a0
; CHECK-ZVKB-NEXT: vand.vx v9, v9, a0
; CHECK-ZVKB-NEXT: vandn.vx v8, v8, a0
; CHECK-ZVKB-NEXT: vandn.vx v9, v9, a0
; CHECK-ZVKB-NEXT: vadd.vv v8, v8, v9
; CHECK-ZVKB-NEXT: ret
%a = and <vscale x 1 x i16> %x, splat (i16 16383)
Expand All @@ -2065,15 +2061,24 @@ define <vscale x 1 x i16> @vandn_vx_multi_scalar_imm16(<vscale x 1 x i16> %x, i1
; CHECK-NEXT: vadd.vx v8, v8, a0
; CHECK-NEXT: ret
;
; CHECK-ZVKB-LABEL: vandn_vx_multi_scalar_imm16:
; CHECK-ZVKB: # %bb.0:
; CHECK-ZVKB-NEXT: lui a1, 8
; CHECK-ZVKB-NEXT: addi a1, a1, -1
; CHECK-ZVKB-NEXT: vsetvli a2, zero, e16, mf4, ta, ma
; CHECK-ZVKB-NEXT: vand.vx v8, v8, a1
; CHECK-ZVKB-NEXT: or a0, a0, a1
; CHECK-ZVKB-NEXT: vadd.vx v8, v8, a0
; CHECK-ZVKB-NEXT: ret
; CHECK-ZVKB-NOZBB-LABEL: vandn_vx_multi_scalar_imm16:
; CHECK-ZVKB-NOZBB: # %bb.0:
; CHECK-ZVKB-NOZBB-NEXT: lui a1, 8
; CHECK-ZVKB-NOZBB-NEXT: addi a1, a1, -1
; CHECK-ZVKB-NOZBB-NEXT: vsetvli a2, zero, e16, mf4, ta, ma
; CHECK-ZVKB-NOZBB-NEXT: vand.vx v8, v8, a1
; CHECK-ZVKB-NOZBB-NEXT: or a0, a0, a1
; CHECK-ZVKB-NOZBB-NEXT: vadd.vx v8, v8, a0
; CHECK-ZVKB-NOZBB-NEXT: ret
;
; CHECK-ZVKB-ZBB-LABEL: vandn_vx_multi_scalar_imm16:
; CHECK-ZVKB-ZBB: # %bb.0:
; CHECK-ZVKB-ZBB-NEXT: lui a1, 1048568
; CHECK-ZVKB-ZBB-NEXT: vsetvli a2, zero, e16, mf4, ta, ma
; CHECK-ZVKB-ZBB-NEXT: vandn.vx v8, v8, a1
; CHECK-ZVKB-ZBB-NEXT: orn a0, a0, a1
; CHECK-ZVKB-ZBB-NEXT: vadd.vx v8, v8, a0
; CHECK-ZVKB-ZBB-NEXT: ret
%a = and <vscale x 1 x i16> %x, splat (i16 32767)
%b = or i16 %y, 32767
%head = insertelement <vscale x 1 x i16> poison, i16 %b, i32 0
Expand Down Expand Up @@ -2104,6 +2109,3 @@ define <vscale x 1 x i16> @vand_vadd_vx_imm16(<vscale x 1 x i16> %x) {
%b = add <vscale x 1 x i16> %a, splat (i16 32767)
ret <vscale x 1 x i16> %b
}
;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
; CHECK-ZVKB-NOZBB: {{.*}}
; CHECK-ZVKB-ZBB: {{.*}}
17 changes: 7 additions & 10 deletions llvm/test/CodeGen/RISCV/rvv/vandn-vp.ll
Original file line number Diff line number Diff line change
Expand Up @@ -1441,10 +1441,9 @@ define <vscale x 1 x i16> @vandn_vx_vp_imm16(<vscale x 1 x i16> %x, <vscale x 1
;
; CHECK-ZVKB-LABEL: vandn_vx_vp_imm16:
; CHECK-ZVKB: # %bb.0:
; CHECK-ZVKB-NEXT: lui a1, 8
; CHECK-ZVKB-NEXT: addi a1, a1, -1
; CHECK-ZVKB-NEXT: lui a1, 1048568
; CHECK-ZVKB-NEXT: vsetvli zero, a0, e16, mf4, ta, ma
; CHECK-ZVKB-NEXT: vand.vx v8, v8, a1, v0.t
; CHECK-ZVKB-NEXT: vandn.vx v8, v8, a1, v0.t
; CHECK-ZVKB-NEXT: ret
%a = call <vscale x 1 x i16> @llvm.vp.and.nxv1i16(<vscale x 1 x i16> splat (i16 32767), <vscale x 1 x i16> %x, <vscale x 1 x i1> %mask, i32 %evl)
ret <vscale x 1 x i16> %a
Expand All @@ -1461,10 +1460,9 @@ define <vscale x 1 x i16> @vandn_vx_vp_swapped_imm16(<vscale x 1 x i16> %x, <vsc
;
; CHECK-ZVKB-LABEL: vandn_vx_vp_swapped_imm16:
; CHECK-ZVKB: # %bb.0:
; CHECK-ZVKB-NEXT: lui a1, 8
; CHECK-ZVKB-NEXT: addi a1, a1, -1
; CHECK-ZVKB-NEXT: lui a1, 1048568
; CHECK-ZVKB-NEXT: vsetvli zero, a0, e16, mf4, ta, ma
; CHECK-ZVKB-NEXT: vand.vx v8, v8, a1, v0.t
; CHECK-ZVKB-NEXT: vandn.vx v8, v8, a1, v0.t
; CHECK-ZVKB-NEXT: ret
%a = call <vscale x 1 x i16> @llvm.vp.and.nxv1i16(<vscale x 1 x i16> %x, <vscale x 1 x i16> splat (i16 32767), <vscale x 1 x i1> %mask, i32 %evl)
ret <vscale x 1 x i16> %a
Expand Down Expand Up @@ -1514,11 +1512,10 @@ define <vscale x 1 x i64> @vandn_vx_vp_imm64(<vscale x 1 x i64> %x, <vscale x 1
;
; CHECK-ZVKB64-LABEL: vandn_vx_vp_imm64:
; CHECK-ZVKB64: # %bb.0:
; CHECK-ZVKB64-NEXT: li a1, -1
; CHECK-ZVKB64-NEXT: slli a1, a1, 56
; CHECK-ZVKB64-NEXT: addi a1, a1, 255
; CHECK-ZVKB64-NEXT: lui a1, 1048560
; CHECK-ZVKB64-NEXT: srli a1, a1, 8
; CHECK-ZVKB64-NEXT: vsetvli zero, a0, e64, m1, ta, ma
; CHECK-ZVKB64-NEXT: vand.vx v8, v8, a1, v0.t
; CHECK-ZVKB64-NEXT: vandn.vx v8, v8, a1, v0.t
; CHECK-ZVKB64-NEXT: ret
%a = call <vscale x 1 x i64> @llvm.vp.and.nxv1i64(<vscale x 1 x i64> %x, <vscale x 1 x i64> splat (i64 -72057594037927681), <vscale x 1 x i1> %mask, i32 %evl)
ret <vscale x 1 x i64> %a
Expand Down
Loading