mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-28 19:31:58 +00:00
[PowerPC] Materialize i64 constants using rotation with masking
r225135 added the ability to materialize i64 constants using rotations in order to reduce the instruction count. Sometimes we can use a rotation only with some extra masking, so that we take advantage of the fact that generating a bunch of extra higher-order 1 bits is easy using li/lis. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@225147 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
5634622da9
commit
9cad6c8a24
@ -608,9 +608,23 @@ static uint64_t Rot64(uint64_t Imm, unsigned R) {
|
||||
|
||||
static unsigned SelectInt64Count(int64_t Imm) {
|
||||
unsigned Count = SelectInt64CountDirect(Imm);
|
||||
if (Count == 1)
|
||||
return Count;
|
||||
|
||||
for (unsigned r = 1; r < 63; ++r) {
|
||||
unsigned RCount = SelectInt64CountDirect(Rot64(Imm, r)) + 1;
|
||||
uint64_t RImm = Rot64(Imm, r);
|
||||
unsigned RCount = SelectInt64CountDirect(RImm) + 1;
|
||||
Count = std::min(Count, RCount);
|
||||
|
||||
// See comments in SelectInt64 for an explanation of the logic below.
|
||||
unsigned LS = findLastSet(RImm);
|
||||
if (LS != r-1)
|
||||
continue;
|
||||
|
||||
uint64_t OnesMask = -(int64_t) (UINT64_C(1) << (LS+1));
|
||||
uint64_t RImmWithOnes = RImm | OnesMask;
|
||||
|
||||
RCount = SelectInt64CountDirect(RImmWithOnes) + 1;
|
||||
Count = std::min(Count, RCount);
|
||||
}
|
||||
|
||||
@ -695,13 +709,45 @@ static SDNode *SelectInt64Direct(SelectionDAG *CurDAG, SDLoc dl, int64_t Imm) {
|
||||
|
||||
static SDNode *SelectInt64(SelectionDAG *CurDAG, SDLoc dl, int64_t Imm) {
|
||||
unsigned Count = SelectInt64CountDirect(Imm);
|
||||
if (Count == 1)
|
||||
return SelectInt64Direct(CurDAG, dl, Imm);
|
||||
|
||||
unsigned RMin = 0;
|
||||
|
||||
int64_t MatImm;
|
||||
unsigned MaskEnd;
|
||||
|
||||
for (unsigned r = 1; r < 63; ++r) {
|
||||
unsigned RCount = SelectInt64CountDirect(Rot64(Imm, r)) + 1;
|
||||
uint64_t RImm = Rot64(Imm, r);
|
||||
unsigned RCount = SelectInt64CountDirect(RImm) + 1;
|
||||
if (RCount < Count) {
|
||||
Count = RCount;
|
||||
RMin = r;
|
||||
MatImm = RImm;
|
||||
MaskEnd = 63;
|
||||
}
|
||||
|
||||
// If the immediate to generate has many trailing zeros, it might be
|
||||
// worthwhile to generate a rotated value with too many leading ones
|
||||
// (because that's free with li/lis's sign-extension semantics), and then
|
||||
// mask them off after rotation.
|
||||
|
||||
unsigned LS = findLastSet(RImm);
|
||||
// We're adding (63-LS) higher-order ones, and we expect to mask them off
|
||||
// after performing the inverse rotation by (64-r). So we need that:
|
||||
// 63-LS == 64-r => LS == r-1
|
||||
if (LS != r-1)
|
||||
continue;
|
||||
|
||||
uint64_t OnesMask = -(int64_t) (UINT64_C(1) << (LS+1));
|
||||
uint64_t RImmWithOnes = RImm | OnesMask;
|
||||
|
||||
RCount = SelectInt64CountDirect(RImmWithOnes) + 1;
|
||||
if (RCount < Count) {
|
||||
Count = RCount;
|
||||
RMin = r;
|
||||
MatImm = RImmWithOnes;
|
||||
MaskEnd = LS;
|
||||
}
|
||||
}
|
||||
|
||||
@ -712,9 +758,9 @@ static SDNode *SelectInt64(SelectionDAG *CurDAG, SDLoc dl, int64_t Imm) {
|
||||
return CurDAG->getTargetConstant(Imm, MVT::i32);
|
||||
};
|
||||
|
||||
SDValue Val = SDValue(SelectInt64Direct(CurDAG, dl, Rot64(Imm, RMin)), 0);
|
||||
return CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64, Val,
|
||||
getI32Imm(64 - RMin), getI32Imm(0));
|
||||
SDValue Val = SDValue(SelectInt64Direct(CurDAG, dl, MatImm), 0);
|
||||
return CurDAG->getMachineNode(PPC::RLDICR, dl, MVT::i64, Val,
|
||||
getI32Imm(64 - RMin), getI32Imm(MaskEnd));
|
||||
}
|
||||
|
||||
// Select a 64-bit constant.
|
||||
|
@ -5,27 +5,6 @@ TODO:
|
||||
|
||||
===-------------------------------------------------------------------------===
|
||||
|
||||
On PPC64, this:
|
||||
|
||||
long f2 (long x) { return 0xfffffff000000000UL; }
|
||||
|
||||
could compile into:
|
||||
|
||||
_f2:
|
||||
li r3,-1
|
||||
rldicr r3,r3,0,27
|
||||
blr
|
||||
|
||||
we produce:
|
||||
|
||||
_f2:
|
||||
lis r2, 4095
|
||||
ori r2, r2, 65535
|
||||
sldi r3, r2, 36
|
||||
blr
|
||||
|
||||
===-------------------------------------------------------------------------===
|
||||
|
||||
This code:
|
||||
|
||||
unsigned add32carry(unsigned sum, unsigned x) {
|
||||
|
@ -9,7 +9,7 @@ entry:
|
||||
|
||||
; CHECK-LABEL: @cn1
|
||||
; CHECK: lis [[REG1:[0-9]+]], -1
|
||||
; CHECK: rldicl 3, [[REG1]], 48, 0
|
||||
; CHECK: rldicr 3, [[REG1]], 48, 63
|
||||
; CHECK: blr
|
||||
}
|
||||
|
||||
@ -20,7 +20,29 @@ entry:
|
||||
|
||||
; CHECK-LABEL: @cnb
|
||||
; CHECK: lis [[REG1:[0-9]+]], -81
|
||||
; CHECK: rldicl 3, [[REG1]], 48, 0
|
||||
; CHECK: rldicr 3, [[REG1]], 48, 63
|
||||
; CHECK: blr
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind readnone
|
||||
define i64 @f2(i64 %x) #0 {
|
||||
entry:
|
||||
ret i64 -68719476736
|
||||
|
||||
; CHECK-LABEL: @f2
|
||||
; CHECK: li [[REG1:[0-9]+]], -1
|
||||
; CHECK: sldi 3, [[REG1]], 36
|
||||
; CHECK: blr
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind readnone
|
||||
define i64 @f2a(i64 %x) #0 {
|
||||
entry:
|
||||
ret i64 -361850994688
|
||||
|
||||
; CHECK-LABEL: @f2a
|
||||
; CHECK: li [[REG1:[0-9]+]], -337
|
||||
; CHECK: sldi 3, [[REG1]], 30
|
||||
; CHECK: blr
|
||||
}
|
||||
|
||||
@ -31,7 +53,7 @@ entry:
|
||||
|
||||
; CHECK-LABEL: @f2n
|
||||
; CHECK: lis [[REG1:[0-9]+]], -4096
|
||||
; CHECK: rldicl 3, [[REG1]], 36, 0
|
||||
; CHECK: rldicr 3, [[REG1]], 36, 63
|
||||
; CHECK: blr
|
||||
}
|
||||
|
||||
@ -42,7 +64,7 @@ entry:
|
||||
|
||||
; CHECK-LABEL: @f3
|
||||
; CHECK: lis [[REG1:[0-9]+]], -32768
|
||||
; CHECK: rldicl 3, [[REG1]], 33, 0
|
||||
; CHECK: rldicr 3, [[REG1]], 33, 63
|
||||
; CHECK: blr
|
||||
}
|
||||
|
||||
@ -54,11 +76,9 @@ entry:
|
||||
; CHECK-LABEL: @cn2n
|
||||
; CHECK: lis [[REG1:[0-9]+]], -5121
|
||||
; CHECK: ori [[REG2:[0-9]+]], [[REG1]], 65534
|
||||
; CHECK: rldicl 3, [[REG2]], 22, 0
|
||||
; CHECK: rldicr 3, [[REG2]], 22, 63
|
||||
; CHECK: blr
|
||||
}
|
||||
|
||||
|
||||
attributes #0 = { nounwind readnone }
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user