mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-03-26 07:34:14 +00:00
LegalizeIntegerTypes: Reenable the large shift with small amount optimization.
To avoid problems with zero shifts when getting the bits that move between words we use a trick: first shift the by amount-1, then do another shift by one. When amount is 0 (and size 32) we first shift by 31, then by one, instead of by 32. Also fix a latent bug that emitted the low and high words in the wrong order when shifting right. Fixes PR12113. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@151637 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
20bd5296ce
commit
3bf15ced2b
@ -1397,15 +1397,15 @@ ExpandShiftWithKnownAmountBit(SDNode *N, SDValue &Lo, SDValue &Hi) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
// FIXME: This code is broken for shifts with a zero amount!
|
|
||||||
// If we know that all of the high bits of the shift amount are zero, then we
|
// If we know that all of the high bits of the shift amount are zero, then we
|
||||||
// can do this as a couple of simple shifts.
|
// can do this as a couple of simple shifts.
|
||||||
if ((KnownZero & HighBitMask) == HighBitMask) {
|
if ((KnownZero & HighBitMask) == HighBitMask) {
|
||||||
// Compute 32-amt.
|
// Calculate 31-x. 31 is used instead of 32 to avoid creating an undefined
|
||||||
SDValue Amt2 = DAG.getNode(ISD::SUB, ShTy,
|
// shift if x is zero. We can use XOR here because x is known to be smaller
|
||||||
DAG.getConstant(NVTBits, ShTy),
|
// than 31.
|
||||||
Amt);
|
SDValue Amt2 = DAG.getNode(ISD::XOR, dl, ShTy, Amt,
|
||||||
|
DAG.getConstant(NVTBits-1, ShTy));
|
||||||
|
|
||||||
unsigned Op1, Op2;
|
unsigned Op1, Op2;
|
||||||
switch (N->getOpcode()) {
|
switch (N->getOpcode()) {
|
||||||
default: llvm_unreachable("Unknown shift");
|
default: llvm_unreachable("Unknown shift");
|
||||||
@ -1414,13 +1414,23 @@ ExpandShiftWithKnownAmountBit(SDNode *N, SDValue &Lo, SDValue &Hi) {
|
|||||||
case ISD::SRA: Op1 = ISD::SRL; Op2 = ISD::SHL; break;
|
case ISD::SRA: Op1 = ISD::SRL; Op2 = ISD::SHL; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Lo = DAG.getNode(N->getOpcode(), NVT, InL, Amt);
|
// When shifting right the arithmetic for Lo and Hi is swapped.
|
||||||
Hi = DAG.getNode(ISD::OR, NVT,
|
if (N->getOpcode() != ISD::SHL)
|
||||||
DAG.getNode(Op1, NVT, InH, Amt),
|
std::swap(InL, InH);
|
||||||
DAG.getNode(Op2, NVT, InL, Amt2));
|
|
||||||
|
// Use a little trick to get the bits that move from Lo to Hi. First
|
||||||
|
// calculate the shift with amount-1.
|
||||||
|
SDValue Sh1 = DAG.getNode(Op2, dl, NVT, InL, Amt2);
|
||||||
|
// Then shift one bit further to get the right result.
|
||||||
|
SDValue Sh2 = DAG.getNode(Op2, dl, NVT, Sh1, DAG.getConstant(1, ShTy));
|
||||||
|
|
||||||
|
Lo = DAG.getNode(N->getOpcode(), dl, NVT, InL, Amt);
|
||||||
|
Hi = DAG.getNode(ISD::OR, dl, NVT, DAG.getNode(Op1, dl, NVT, InH, Amt),Sh2);
|
||||||
|
|
||||||
|
if (N->getOpcode() != ISD::SHL)
|
||||||
|
std::swap(Hi, Lo);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
; RUN: llc < %s | not grep shrl
|
|
||||||
; Note: this test is really trying to make sure that the shift
|
|
||||||
; returns the right result; shrl is most likely wrong,
|
|
||||||
; but if CodeGen starts legitimately using an shrl here,
|
|
||||||
; please adjust the test appropriately.
|
|
||||||
|
|
||||||
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32"
|
|
||||||
target triple = "i386-pc-linux-gnu"
|
|
||||||
@.str = internal constant [6 x i8] c"%lld\0A\00" ; <[6 x i8]*> [#uses=1]
|
|
||||||
|
|
||||||
define i64 @mebbe_shift(i32 %xx, i32 %test) nounwind {
|
|
||||||
entry:
|
|
||||||
%conv = zext i32 %xx to i64 ; <i64> [#uses=1]
|
|
||||||
%tobool = icmp ne i32 %test, 0 ; <i1> [#uses=1]
|
|
||||||
%shl = select i1 %tobool, i64 3, i64 0 ; <i64> [#uses=1]
|
|
||||||
%x.0 = shl i64 %conv, %shl ; <i64> [#uses=1]
|
|
||||||
ret i64 %x.0
|
|
||||||
}
|
|
||||||
|
|
56
test/CodeGen/X86/legalize-shift-64.ll
Normal file
56
test/CodeGen/X86/legalize-shift-64.ll
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
; RUN: llc -march=x86 < %s | FileCheck %s
|
||||||
|
|
||||||
|
define i64 @test1(i32 %xx, i32 %test) nounwind {
|
||||||
|
%conv = zext i32 %xx to i64
|
||||||
|
%and = and i32 %test, 7
|
||||||
|
%sh_prom = zext i32 %and to i64
|
||||||
|
%shl = shl i64 %conv, %sh_prom
|
||||||
|
ret i64 %shl
|
||||||
|
; CHECK: test1:
|
||||||
|
; CHECK: shll %cl, %eax
|
||||||
|
; CHECK: xorb $31
|
||||||
|
; CHECK: shrl %cl, %edx
|
||||||
|
; CHECK: shrl %edx
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @test2(i64 %xx, i32 %test) nounwind {
|
||||||
|
%and = and i32 %test, 7
|
||||||
|
%sh_prom = zext i32 %and to i64
|
||||||
|
%shl = shl i64 %xx, %sh_prom
|
||||||
|
ret i64 %shl
|
||||||
|
; CHECK: test2:
|
||||||
|
; CHECK: shll %cl, %esi
|
||||||
|
; CHECK: xorb $31
|
||||||
|
; CHECK: shrl %cl, %edx
|
||||||
|
; CHECK: shrl %edx
|
||||||
|
; CHECK: orl %esi, %edx
|
||||||
|
; CHECK: shll %cl, %eax
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @test3(i64 %xx, i32 %test) nounwind {
|
||||||
|
%and = and i32 %test, 7
|
||||||
|
%sh_prom = zext i32 %and to i64
|
||||||
|
%shr = lshr i64 %xx, %sh_prom
|
||||||
|
ret i64 %shr
|
||||||
|
; CHECK: test3:
|
||||||
|
; CHECK: shrl %cl, %esi
|
||||||
|
; CHECK: xorb $31, %cl
|
||||||
|
; CHECK: shll %cl, %eax
|
||||||
|
; CHECK: addl %eax, %eax
|
||||||
|
; CHECK: orl %esi, %eax
|
||||||
|
; CHECK: shrl %cl, %edx
|
||||||
|
}
|
||||||
|
|
||||||
|
define i64 @test4(i64 %xx, i32 %test) nounwind {
|
||||||
|
%and = and i32 %test, 7
|
||||||
|
%sh_prom = zext i32 %and to i64
|
||||||
|
%shr = ashr i64 %xx, %sh_prom
|
||||||
|
ret i64 %shr
|
||||||
|
; CHECK: test4:
|
||||||
|
; CHECK: shrl %cl, %esi
|
||||||
|
; CHECK: xorb $31, %cl
|
||||||
|
; CHECK: shll %cl, %eax
|
||||||
|
; CHECK: addl %eax, %eax
|
||||||
|
; CHECK: orl %esi, %eax
|
||||||
|
; CHECK: sarl %cl, %edx
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user