-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[RISCV] Use bseti 31 for (or X, -2147483648) when upper 32 bits aren't used. #159678
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
…t used. If the original type was i32, type legalization will sign extend the constant. This prevents it from having a single bit set or clear so other patterns can't match. If the upper bits aren't used, we can ignore the sign extension. Similar for bclri and binvi.
@llvm/pr-subscribers-backend-risc-v Author: Craig Topper (topperc) ChangesIf the original type was i32, type legalization will sign extend Similar for bclri and binvi. Full diff: https://github.com/llvm/llvm-project/pull/159678.diff 2 Files Affected:
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td
index a2b4302e19edc..9b98588073212 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td
@@ -574,6 +574,19 @@ def : Pat<(XLenVT (and GPR:$r, BCLRIANDIMask:$i)),
(BCLRITwoBitsMaskHigh BCLRIANDIMask:$i))>;
} // Predicates = [HasStdExtZbs]
+let Predicates = [HasStdExtZbs, IsRV64] in {
+// If the original code was setting, clearing, or inverting bit 31 or an i32,
+// type legalization might have sign extended the constant so it doesn't have a
+// single 0 or 1 bit. If the upper 32 bits aren't used by later instructions we
+// can still use bseti/bclri.
+def : Pat<(binop_allwusers<and> GPR:$rs1, (XLenVT 2147483647)),
+ (BCLRI GPR:$rs1, 31)>;
+def : Pat<(binop_allwusers<or> GPR:$rs1, (XLenVT -2147483648)),
+ (BSETI GPR:$rs1, 31)>;
+def : Pat<(binop_allwusers<xor> GPR:$rs1, (XLenVT -2147483648)),
+ (BINVI GPR:$rs1, 31)>;
+}
+
let Predicates = [HasStdExtZbb] in
def : PatGpr<riscv_orc_b, ORC_B>;
diff --git a/llvm/test/CodeGen/RISCV/rv64zbs.ll b/llvm/test/CodeGen/RISCV/rv64zbs.ll
index a8b06b2af5764..b4edcf6cc55cf 100644
--- a/llvm/test/CodeGen/RISCV/rv64zbs.ll
+++ b/llvm/test/CodeGen/RISCV/rv64zbs.ll
@@ -547,10 +547,28 @@ define signext i32 @bclri_i32_31(i32 signext %a) nounwind {
; CHECK-NEXT: slli a0, a0, 33
; CHECK-NEXT: srli a0, a0, 33
; CHECK-NEXT: ret
- %and = and i32 %a, -2147483649
+ %and = and i32 %a, 2147483647
ret i32 %and
}
+define signext i32 @bclri_i32_31_allWUsers(i32 signext %a) nounwind {
+; RV64I-LABEL: bclri_i32_31_allWUsers:
+; RV64I: # %bb.0:
+; RV64I-NEXT: slli a0, a0, 33
+; RV64I-NEXT: srli a0, a0, 33
+; RV64I-NEXT: addiw a0, a0, 1
+; RV64I-NEXT: ret
+;
+; RV64ZBS-LABEL: bclri_i32_31_allWUsers:
+; RV64ZBS: # %bb.0:
+; RV64ZBS-NEXT: bclri a0, a0, 31
+; RV64ZBS-NEXT: addiw a0, a0, 1
+; RV64ZBS-NEXT: ret
+ %and = and i32 %a, 2147483647
+ %add = add i32 %and, 1
+ ret i32 %add
+}
+
define i64 @bclri_i64_10(i64 %a) nounwind {
; CHECK-LABEL: bclri_i64_10:
; CHECK: # %bb.0:
@@ -724,6 +742,24 @@ define signext i32 @bseti_i32_31(i32 signext %a) nounwind {
ret i32 %or
}
+define signext i32 @bseti_i32_31_allWUsers(i32 signext %a) nounwind {
+; RV64I-LABEL: bseti_i32_31_allWUsers:
+; RV64I: # %bb.0:
+; RV64I-NEXT: lui a1, 524288
+; RV64I-NEXT: or a0, a0, a1
+; RV64I-NEXT: addiw a0, a0, 1
+; RV64I-NEXT: ret
+;
+; RV64ZBS-LABEL: bseti_i32_31_allWUsers:
+; RV64ZBS: # %bb.0:
+; RV64ZBS-NEXT: bseti a0, a0, 31
+; RV64ZBS-NEXT: addiw a0, a0, 1
+; RV64ZBS-NEXT: ret
+ %or = or i32 %a, 2147483648
+ %add = add i32 %or, 1
+ ret i32 %add
+}
+
define i64 @bseti_i64_10(i64 %a) nounwind {
; CHECK-LABEL: bseti_i64_10:
; CHECK: # %bb.0:
@@ -862,6 +898,24 @@ define signext i32 @binvi_i32_31(i32 signext %a) nounwind {
ret i32 %xor
}
+define void @binvi_i32_31_allWUsers(i32 signext %a, ptr %p) nounwind {
+; RV64I-LABEL: binvi_i32_31_allWUsers:
+; RV64I: # %bb.0:
+; RV64I-NEXT: lui a2, 524288
+; RV64I-NEXT: xor a0, a0, a2
+; RV64I-NEXT: sw a0, 0(a1)
+; RV64I-NEXT: ret
+;
+; RV64ZBS-LABEL: binvi_i32_31_allWUsers:
+; RV64ZBS: # %bb.0:
+; RV64ZBS-NEXT: binvi a0, a0, 31
+; RV64ZBS-NEXT: sw a0, 0(a1)
+; RV64ZBS-NEXT: ret
+ %xor = xor i32 %a, 2147483648
+ store i32 %xor, ptr %p
+ ret void
+}
+
define i64 @binvi_i64_10(i64 %a) nounwind {
; CHECK-LABEL: binvi_i64_10:
; CHECK: # %bb.0:
|
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
Co-authored-by: Sam Elliott <sam@lenary.co.uk>
As a quick sanity check to make sure this had real world value, this triggered about 18 times in 502.gcc_r from spec2017. |
If the original type was i32, type legalization will sign extend
the constant. This prevents it from having a single bit set or clear
so other patterns can't match. If the upper bits aren't used, we
can ignore the sign extension.
Similar for bclri and binvi.