mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-21 21:29:41 +00:00
Followup to r60283: optimize arbitrary width signed divisions as well
as unsigned divisions. Same caveats as before. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@60284 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
201c9776bd
commit
fc69cb475f
@ -2224,7 +2224,7 @@ bool TargetLowering::isLegalAddressingMode(const AddrMode &AM,
|
|||||||
struct mu {
|
struct mu {
|
||||||
APInt m; // magic number
|
APInt m; // magic number
|
||||||
bool a; // add indicator
|
bool a; // add indicator
|
||||||
uint32_t s; // shift amount
|
unsigned s; // shift amount
|
||||||
};
|
};
|
||||||
|
|
||||||
/// magicu - calculate the magic numbers required to codegen an integer udiv as
|
/// magicu - calculate the magic numbers required to codegen an integer udiv as
|
||||||
@ -2273,89 +2273,50 @@ static mu magicu(const APInt& d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Magic for divide replacement
|
// Magic for divide replacement
|
||||||
// FIXME: This should be APInt'ified
|
|
||||||
struct ms {
|
struct ms {
|
||||||
int64_t m; // magic number
|
APInt m; // magic number
|
||||||
int64_t s; // shift amount
|
unsigned s; // shift amount
|
||||||
};
|
};
|
||||||
|
|
||||||
/// magic - calculate the magic numbers required to codegen an integer sdiv as
|
/// magic - calculate the magic numbers required to codegen an integer sdiv as
|
||||||
/// a sequence of multiply and shifts. Requires that the divisor not be 0, 1,
|
/// a sequence of multiply and shifts. Requires that the divisor not be 0, 1,
|
||||||
/// or -1.
|
/// or -1.
|
||||||
static ms magic32(int32_t d) {
|
static ms magic(const APInt& d) {
|
||||||
int32_t p;
|
unsigned p;
|
||||||
uint32_t ad, anc, delta, q1, r1, q2, r2, t;
|
APInt ad, anc, delta, q1, r1, q2, r2, t;
|
||||||
const uint32_t two31 = 0x80000000U;
|
APInt allOnes = APInt::getAllOnesValue(d.getBitWidth());
|
||||||
|
APInt signedMin = APInt::getSignedMinValue(d.getBitWidth());
|
||||||
|
APInt signedMax = APInt::getSignedMaxValue(d.getBitWidth());
|
||||||
struct ms mag;
|
struct ms mag;
|
||||||
|
|
||||||
ad = abs(d);
|
ad = d.abs();
|
||||||
t = two31 + ((uint32_t)d >> 31);
|
t = signedMin + (d.lshr(d.getBitWidth() - 1));
|
||||||
anc = t - 1 - t%ad; // absolute value of nc
|
anc = t - 1 - t.urem(ad); // absolute value of nc
|
||||||
p = 31; // initialize p
|
p = d.getBitWidth() - 1; // initialize p
|
||||||
q1 = two31/anc; // initialize q1 = 2p/abs(nc)
|
q1 = signedMin.udiv(anc); // initialize q1 = 2p/abs(nc)
|
||||||
r1 = two31 - q1*anc; // initialize r1 = rem(2p,abs(nc))
|
r1 = signedMin - q1*anc; // initialize r1 = rem(2p,abs(nc))
|
||||||
q2 = two31/ad; // initialize q2 = 2p/abs(d)
|
q2 = signedMin.udiv(ad); // initialize q2 = 2p/abs(d)
|
||||||
r2 = two31 - q2*ad; // initialize r2 = rem(2p,abs(d))
|
r2 = signedMin - q2*ad; // initialize r2 = rem(2p,abs(d))
|
||||||
do {
|
do {
|
||||||
p = p + 1;
|
p = p + 1;
|
||||||
q1 = 2*q1; // update q1 = 2p/abs(nc)
|
q1 = q1<<1; // update q1 = 2p/abs(nc)
|
||||||
r1 = 2*r1; // update r1 = rem(2p/abs(nc))
|
r1 = r1<<1; // update r1 = rem(2p/abs(nc))
|
||||||
if (r1 >= anc) { // must be unsigned comparison
|
if (r1.uge(anc)) { // must be unsigned comparison
|
||||||
q1 = q1 + 1;
|
q1 = q1 + 1;
|
||||||
r1 = r1 - anc;
|
r1 = r1 - anc;
|
||||||
}
|
}
|
||||||
q2 = 2*q2; // update q2 = 2p/abs(d)
|
q2 = q2<<1; // update q2 = 2p/abs(d)
|
||||||
r2 = 2*r2; // update r2 = rem(2p/abs(d))
|
r2 = r2<<1; // update r2 = rem(2p/abs(d))
|
||||||
if (r2 >= ad) { // must be unsigned comparison
|
if (r2.uge(ad)) { // must be unsigned comparison
|
||||||
q2 = q2 + 1;
|
q2 = q2 + 1;
|
||||||
r2 = r2 - ad;
|
r2 = r2 - ad;
|
||||||
}
|
}
|
||||||
delta = ad - r2;
|
delta = ad - r2;
|
||||||
} while (q1 < delta || (q1 == delta && r1 == 0));
|
} while (q1.ule(delta) || (q1 == delta && r1 == 0));
|
||||||
|
|
||||||
mag.m = (int32_t)(q2 + 1); // make sure to sign extend
|
|
||||||
if (d < 0) mag.m = -mag.m; // resulting magic number
|
|
||||||
mag.s = p - 32; // resulting shift
|
|
||||||
return mag;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// magic - calculate the magic numbers required to codegen an integer sdiv as
|
|
||||||
/// a sequence of multiply and shifts. Requires that the divisor not be 0, 1,
|
|
||||||
/// or -1.
|
|
||||||
static ms magic64(int64_t d) {
|
|
||||||
int64_t p;
|
|
||||||
uint64_t ad, anc, delta, q1, r1, q2, r2, t;
|
|
||||||
const uint64_t two63 = 9223372036854775808ULL; // 2^63
|
|
||||||
struct ms mag;
|
|
||||||
|
|
||||||
ad = d >= 0 ? d : -d;
|
|
||||||
t = two63 + ((uint64_t)d >> 63);
|
|
||||||
anc = t - 1 - t%ad; // absolute value of nc
|
|
||||||
p = 63; // initialize p
|
|
||||||
q1 = two63/anc; // initialize q1 = 2p/abs(nc)
|
|
||||||
r1 = two63 - q1*anc; // initialize r1 = rem(2p,abs(nc))
|
|
||||||
q2 = two63/ad; // initialize q2 = 2p/abs(d)
|
|
||||||
r2 = two63 - q2*ad; // initialize r2 = rem(2p,abs(d))
|
|
||||||
do {
|
|
||||||
p = p + 1;
|
|
||||||
q1 = 2*q1; // update q1 = 2p/abs(nc)
|
|
||||||
r1 = 2*r1; // update r1 = rem(2p/abs(nc))
|
|
||||||
if (r1 >= anc) { // must be unsigned comparison
|
|
||||||
q1 = q1 + 1;
|
|
||||||
r1 = r1 - anc;
|
|
||||||
}
|
|
||||||
q2 = 2*q2; // update q2 = 2p/abs(d)
|
|
||||||
r2 = 2*r2; // update r2 = rem(2p/abs(d))
|
|
||||||
if (r2 >= ad) { // must be unsigned comparison
|
|
||||||
q2 = q2 + 1;
|
|
||||||
r2 = r2 - ad;
|
|
||||||
}
|
|
||||||
delta = ad - r2;
|
|
||||||
} while (q1 < delta || (q1 == delta && r1 == 0));
|
|
||||||
|
|
||||||
mag.m = q2 + 1;
|
mag.m = q2 + 1;
|
||||||
if (d < 0) mag.m = -mag.m; // resulting magic number
|
if (d.isNegative()) mag.m = -mag.m; // resulting magic number
|
||||||
mag.s = p - 64; // resulting shift
|
mag.s = p - d.getBitWidth(); // resulting shift
|
||||||
return mag;
|
return mag;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2368,13 +2329,15 @@ SDValue TargetLowering::BuildSDIV(SDNode *N, SelectionDAG &DAG,
|
|||||||
MVT VT = N->getValueType(0);
|
MVT VT = N->getValueType(0);
|
||||||
|
|
||||||
// Check to see if we can do this.
|
// Check to see if we can do this.
|
||||||
if (!isTypeLegal(VT) || (VT != MVT::i32 && VT != MVT::i64))
|
// FIXME: We should be more aggressive here.
|
||||||
return SDValue(); // BuildSDIV only operates on i32 or i64
|
if (!isTypeLegal(VT))
|
||||||
|
return SDValue();
|
||||||
|
|
||||||
int64_t d = cast<ConstantSDNode>(N->getOperand(1))->getSExtValue();
|
APInt d = cast<ConstantSDNode>(N->getOperand(1))->getAPIntValue();
|
||||||
ms magics = (VT == MVT::i32) ? magic32(d) : magic64(d);
|
ms magics = magic(d);
|
||||||
|
|
||||||
// Multiply the numerator (operand 0) by the magic value
|
// Multiply the numerator (operand 0) by the magic value
|
||||||
|
// FIXME: We should support doing a MUL in a wider type
|
||||||
SDValue Q;
|
SDValue Q;
|
||||||
if (isOperationLegal(ISD::MULHS, VT))
|
if (isOperationLegal(ISD::MULHS, VT))
|
||||||
Q = DAG.getNode(ISD::MULHS, VT, N->getOperand(0),
|
Q = DAG.getNode(ISD::MULHS, VT, N->getOperand(0),
|
||||||
@ -2386,13 +2349,13 @@ SDValue TargetLowering::BuildSDIV(SDNode *N, SelectionDAG &DAG,
|
|||||||
else
|
else
|
||||||
return SDValue(); // No mulhs or equvialent
|
return SDValue(); // No mulhs or equvialent
|
||||||
// If d > 0 and m < 0, add the numerator
|
// If d > 0 and m < 0, add the numerator
|
||||||
if (d > 0 && magics.m < 0) {
|
if (d.isStrictlyPositive() && magics.m.isNegative()) {
|
||||||
Q = DAG.getNode(ISD::ADD, VT, Q, N->getOperand(0));
|
Q = DAG.getNode(ISD::ADD, VT, Q, N->getOperand(0));
|
||||||
if (Created)
|
if (Created)
|
||||||
Created->push_back(Q.getNode());
|
Created->push_back(Q.getNode());
|
||||||
}
|
}
|
||||||
// If d < 0 and m > 0, subtract the numerator.
|
// If d < 0 and m > 0, subtract the numerator.
|
||||||
if (d < 0 && magics.m > 0) {
|
if (d.isNegative() && magics.m.isStrictlyPositive()) {
|
||||||
Q = DAG.getNode(ISD::SUB, VT, Q, N->getOperand(0));
|
Q = DAG.getNode(ISD::SUB, VT, Q, N->getOperand(0));
|
||||||
if (Created)
|
if (Created)
|
||||||
Created->push_back(Q.getNode());
|
Created->push_back(Q.getNode());
|
||||||
|
10
test/CodeGen/X86/2008-11-29-DivideConstant16bitSigned.ll
Normal file
10
test/CodeGen/X86/2008-11-29-DivideConstant16bitSigned.ll
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
; RUN: llvm-as < %s | llc -mtriple=i686-pc-linux-gnu | grep 63551
|
||||||
|
; ModuleID = '<stdin>'
|
||||||
|
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 = "i686-pc-linux-gnu"
|
||||||
|
|
||||||
|
define signext i16 @a(i16 signext %x) nounwind {
|
||||||
|
entry:
|
||||||
|
%div = sdiv i16 %x, 33 ; <i32> [#uses=1]
|
||||||
|
ret i16 %div
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user