mirror of
https://github.com/intel/llvm.git
synced 2026-01-26 03:56:16 +08:00
[RISCV] Optimize or/xor with immediate in the zbs extension
Reviewed By: craig.topper Differential Revision: https://reviews.llvm.org/D102398
This commit is contained in:
@@ -87,6 +87,30 @@ def BSETINVMask : ImmLeaf<XLenVT, [{
|
||||
return !isInt<12>(Imm) && isPowerOf2_32(Imm);
|
||||
}], BSETINVXForm>;
|
||||
|
||||
// Check if (or r, i) can be optimized to (BSETI (BSETI r, i0), i1),
|
||||
// in which i = (1 << i0) | (1 << i1).
|
||||
def BSETINVTwoBitsMask : PatLeaf<(imm), [{
|
||||
if (!N->hasOneUse())
|
||||
return false;
|
||||
// The immediate should not be a simm12.
|
||||
if (isInt<12>(N->getSExtValue()))
|
||||
return false;
|
||||
// The immediate must have exactly two bits set.
|
||||
return countPopulation(N->getZExtValue()) == 2;
|
||||
}]>;
|
||||
|
||||
def BSETINVTwoBitsMaskLow : SDNodeXForm<imm, [{
|
||||
uint64_t I = N->getZExtValue();
|
||||
return CurDAG->getTargetConstant(countTrailingZeros(I), SDLoc(N),
|
||||
N->getValueType(0));
|
||||
}]>;
|
||||
|
||||
def BSETINVTwoBitsMaskHigh : SDNodeXForm<imm, [{
|
||||
uint64_t I = N->getZExtValue();
|
||||
return CurDAG->getTargetConstant(63 - countLeadingZeros(I), SDLoc(N),
|
||||
N->getValueType(0));
|
||||
}]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Instruction class templates
|
||||
//===----------------------------------------------------------------------===//
|
||||
@@ -723,6 +747,13 @@ def : Pat<(xor GPR:$rs1, BSETINVMask:$mask),
|
||||
|
||||
def : Pat<(and (srl GPR:$rs1, uimmlog2xlen:$shamt), (XLenVT 1)),
|
||||
(BEXTI GPR:$rs1, uimmlog2xlen:$shamt)>;
|
||||
|
||||
def : Pat<(or GPR:$r, BSETINVTwoBitsMask:$i),
|
||||
(BSETI (BSETI GPR:$r, (BSETINVTwoBitsMaskLow BSETINVTwoBitsMask:$i)),
|
||||
(BSETINVTwoBitsMaskHigh BSETINVTwoBitsMask:$i))>;
|
||||
def : Pat<(xor GPR:$r, BSETINVTwoBitsMask:$i),
|
||||
(BINVI (BINVI GPR:$r, (BSETINVTwoBitsMaskLow BSETINVTwoBitsMask:$i)),
|
||||
(BSETINVTwoBitsMaskHigh BSETINVTwoBitsMask:$i))>;
|
||||
}
|
||||
|
||||
// There's no encoding for roli in the the 'B' extension as it can be
|
||||
|
||||
@@ -720,16 +720,14 @@ define i32 @xor_i32_4098(i32 %a) nounwind {
|
||||
;
|
||||
; RV32IB-LABEL: xor_i32_4098:
|
||||
; RV32IB: # %bb.0:
|
||||
; RV32IB-NEXT: lui a1, 1
|
||||
; RV32IB-NEXT: addi a1, a1, 2
|
||||
; RV32IB-NEXT: xor a0, a0, a1
|
||||
; RV32IB-NEXT: binvi a0, a0, 1
|
||||
; RV32IB-NEXT: binvi a0, a0, 12
|
||||
; RV32IB-NEXT: ret
|
||||
;
|
||||
; RV32IBS-LABEL: xor_i32_4098:
|
||||
; RV32IBS: # %bb.0:
|
||||
; RV32IBS-NEXT: lui a1, 1
|
||||
; RV32IBS-NEXT: addi a1, a1, 2
|
||||
; RV32IBS-NEXT: xor a0, a0, a1
|
||||
; RV32IBS-NEXT: binvi a0, a0, 1
|
||||
; RV32IBS-NEXT: binvi a0, a0, 12
|
||||
; RV32IBS-NEXT: ret
|
||||
%xor = xor i32 %a, 4098
|
||||
ret i32 %xor
|
||||
@@ -789,16 +787,14 @@ define i32 @or_i32_4098(i32 %a) nounwind {
|
||||
;
|
||||
; RV32IB-LABEL: or_i32_4098:
|
||||
; RV32IB: # %bb.0:
|
||||
; RV32IB-NEXT: lui a1, 1
|
||||
; RV32IB-NEXT: addi a1, a1, 2
|
||||
; RV32IB-NEXT: or a0, a0, a1
|
||||
; RV32IB-NEXT: bseti a0, a0, 1
|
||||
; RV32IB-NEXT: bseti a0, a0, 12
|
||||
; RV32IB-NEXT: ret
|
||||
;
|
||||
; RV32IBS-LABEL: or_i32_4098:
|
||||
; RV32IBS: # %bb.0:
|
||||
; RV32IBS-NEXT: lui a1, 1
|
||||
; RV32IBS-NEXT: addi a1, a1, 2
|
||||
; RV32IBS-NEXT: or a0, a0, a1
|
||||
; RV32IBS-NEXT: bseti a0, a0, 1
|
||||
; RV32IBS-NEXT: bseti a0, a0, 12
|
||||
; RV32IBS-NEXT: ret
|
||||
%or = or i32 %a, 4098
|
||||
ret i32 %or
|
||||
|
||||
@@ -1221,18 +1221,14 @@ define i64 @xor_i64_large(i64 %a) nounwind {
|
||||
;
|
||||
; RV64IB-LABEL: xor_i64_large:
|
||||
; RV64IB: # %bb.0:
|
||||
; RV64IB-NEXT: addi a1, zero, 1
|
||||
; RV64IB-NEXT: slli a1, a1, 32
|
||||
; RV64IB-NEXT: addi a1, a1, 1
|
||||
; RV64IB-NEXT: xor a0, a0, a1
|
||||
; RV64IB-NEXT: binvi a0, a0, 0
|
||||
; RV64IB-NEXT: binvi a0, a0, 32
|
||||
; RV64IB-NEXT: ret
|
||||
;
|
||||
; RV64IBS-LABEL: xor_i64_large:
|
||||
; RV64IBS: # %bb.0:
|
||||
; RV64IBS-NEXT: addi a1, zero, 1
|
||||
; RV64IBS-NEXT: slli a1, a1, 32
|
||||
; RV64IBS-NEXT: addi a1, a1, 1
|
||||
; RV64IBS-NEXT: xor a0, a0, a1
|
||||
; RV64IBS-NEXT: binvi a0, a0, 0
|
||||
; RV64IBS-NEXT: binvi a0, a0, 32
|
||||
; RV64IBS-NEXT: ret
|
||||
%xor = xor i64 %a, 4294967297
|
||||
ret i64 %xor
|
||||
@@ -1293,18 +1289,14 @@ define i64 @or_i64_large(i64 %a) nounwind {
|
||||
;
|
||||
; RV64IB-LABEL: or_i64_large:
|
||||
; RV64IB: # %bb.0:
|
||||
; RV64IB-NEXT: addi a1, zero, 1
|
||||
; RV64IB-NEXT: slli a1, a1, 32
|
||||
; RV64IB-NEXT: addi a1, a1, 1
|
||||
; RV64IB-NEXT: or a0, a0, a1
|
||||
; RV64IB-NEXT: bseti a0, a0, 0
|
||||
; RV64IB-NEXT: bseti a0, a0, 32
|
||||
; RV64IB-NEXT: ret
|
||||
;
|
||||
; RV64IBS-LABEL: or_i64_large:
|
||||
; RV64IBS: # %bb.0:
|
||||
; RV64IBS-NEXT: addi a1, zero, 1
|
||||
; RV64IBS-NEXT: slli a1, a1, 32
|
||||
; RV64IBS-NEXT: addi a1, a1, 1
|
||||
; RV64IBS-NEXT: or a0, a0, a1
|
||||
; RV64IBS-NEXT: bseti a0, a0, 0
|
||||
; RV64IBS-NEXT: bseti a0, a0, 32
|
||||
; RV64IBS-NEXT: ret
|
||||
%or = or i64 %a, 4294967297
|
||||
ret i64 %or
|
||||
|
||||
Reference in New Issue
Block a user