forked from OSchip/llvm-project
[PowerPC] Exploit RLDIMI for OR with large immediates
This patch exploits rldimi instruction for patterns like `or %a, 0b000011110000`, which saves number of instructions when the operand has only one use, compared with `li-ori-sldi-or`. Reviewed By: nemanjai Differential Revision: https://reviews.llvm.org/D77850
This commit is contained in:
parent
daadb48553
commit
c12722cde8
|
@ -352,6 +352,7 @@ private:
|
|||
bool tryAsSingleRLWINM8(SDNode *N);
|
||||
bool tryAsSingleRLWIMI(SDNode *N);
|
||||
bool tryAsPairOfRLDICL(SDNode *N);
|
||||
bool tryAsSingleRLDIMI(SDNode *N);
|
||||
|
||||
void PeepholePPC64();
|
||||
void PeepholePPC64ZExt();
|
||||
|
@ -4597,6 +4598,31 @@ bool PPCDAGToDAGISel::tryAsSingleRLDICR(SDNode *N) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool PPCDAGToDAGISel::tryAsSingleRLDIMI(SDNode *N) {
|
||||
assert(N->getOpcode() == ISD::OR && "ISD::OR SDNode expected");
|
||||
uint64_t Imm64;
|
||||
unsigned MB, ME;
|
||||
SDValue N0 = N->getOperand(0);
|
||||
|
||||
// We won't get fewer instructions if the imm is 32-bit integer.
|
||||
// rldimi requires the imm to have consecutive ones with both sides zero.
|
||||
// Also, make sure the first Op has only one use, otherwise this may increase
|
||||
// register pressure since rldimi is destructive.
|
||||
if (!isInt64Immediate(N->getOperand(1).getNode(), Imm64) ||
|
||||
isUInt<32>(Imm64) || !isRunOfOnes64(Imm64, MB, ME) || !N0.hasOneUse())
|
||||
return false;
|
||||
|
||||
unsigned SH = 63 - ME;
|
||||
SDLoc Dl(N);
|
||||
// Use select64Imm for making LI instr instead of directly putting Imm64
|
||||
SDValue Ops[] = {
|
||||
N->getOperand(0),
|
||||
SDValue(selectI64Imm(CurDAG, getI64Imm(-1, Dl).getNode()), 0),
|
||||
getI32Imm(SH, Dl), getI32Imm(MB, Dl)};
|
||||
CurDAG->SelectNodeTo(N, PPC::RLDIMI, MVT::i64, Ops);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Select - Convert the specified operand from a target-independent to a
|
||||
// target-specific node if it hasn't already been changed.
|
||||
void PPCDAGToDAGISel::Select(SDNode *N) {
|
||||
|
@ -4844,6 +4870,11 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
|
|||
}
|
||||
}
|
||||
|
||||
// If this is 'or' against an imm with consecutive ones and both sides zero,
|
||||
// try to emit rldimi
|
||||
if (tryAsSingleRLDIMI(N))
|
||||
return;
|
||||
|
||||
// OR with a 32-bit immediate can be handled by ori + oris
|
||||
// without creating an immediate in a GPR.
|
||||
uint64_t Imm64 = 0;
|
||||
|
|
|
@ -16,9 +16,8 @@ entry:
|
|||
define i64 @ori_test_b(i64 %a) {
|
||||
; CHECK-LABEL: ori_test_b:
|
||||
; CHECK: # %bb.0: # %entry
|
||||
; CHECK-NEXT: li 4, 1
|
||||
; CHECK-NEXT: sldi 4, 4, 32
|
||||
; CHECK-NEXT: or 3, 3, 4
|
||||
; CHECK-NEXT: li 4, -1
|
||||
; CHECK-NEXT: rldimi 3, 4, 32, 31
|
||||
; CHECK-NEXT: blr
|
||||
entry:
|
||||
%or = or i64 %a, 4294967296
|
||||
|
|
|
@ -15,10 +15,8 @@ entry:
|
|||
define i64 @ori_test_2(i64 %a) {
|
||||
; CHECK-LABEL: ori_test_2:
|
||||
; CHECK: # %bb.0: # %entry
|
||||
; CHECK-NEXT: lis 4, 15
|
||||
; CHECK-NEXT: ori 4, 4, 65535
|
||||
; CHECK-NEXT: sldi 4, 4, 29
|
||||
; CHECK-NEXT: or 3, 3, 4
|
||||
; CHECK-NEXT: li 4, -1
|
||||
; CHECK-NEXT: rldimi 3, 4, 29, 15
|
||||
; CHECK-NEXT: blr
|
||||
entry:
|
||||
%or = or i64 %a, 562949416550400 ; 0x1ffffe0000000
|
||||
|
@ -28,9 +26,8 @@ entry:
|
|||
define i64 @ori_test_3(i64 %a) {
|
||||
; CHECK-LABEL: ori_test_3:
|
||||
; CHECK: # %bb.0: # %entry
|
||||
; CHECK-NEXT: lis 4, -32768
|
||||
; CHECK-NEXT: rldicr 4, 4, 36, 63
|
||||
; CHECK-NEXT: or 3, 3, 4
|
||||
; CHECK-NEXT: li 4, -1
|
||||
; CHECK-NEXT: rldimi 3, 4, 3, 28
|
||||
; CHECK-NEXT: blr
|
||||
entry:
|
||||
%or = or i64 %a, 68719476728 ; 0xffffffff8
|
||||
|
@ -50,3 +47,20 @@ entry:
|
|||
%or = or i64 %a, 17661175070719 ; 0x10101010ffff
|
||||
ret i64 %or
|
||||
}
|
||||
|
||||
; Don't exploit rldimi if operand has multiple uses
|
||||
define i64 @test_test_5(i64 %a, i64 %b) {
|
||||
; CHECK-LABEL: test_test_5:
|
||||
; CHECK: # %bb.0: # %entry
|
||||
; CHECK-NEXT: li 5, 1
|
||||
; CHECK-NEXT: sldi 5, 5, 32
|
||||
; CHECK-NEXT: or 5, 3, 5
|
||||
; CHECK-NEXT: add 4, 5, 4
|
||||
; CHECK-NEXT: sub 3, 3, 4
|
||||
; CHECK-NEXT: blr
|
||||
entry:
|
||||
%or = or i64 %a, 4294967296
|
||||
%add = add i64 %or, %b
|
||||
%div = sub i64 %a, %add
|
||||
ret i64 %div
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue