aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Laskey <jlaskey@mac.com>2005-08-17 00:39:29 +0000
committerJim Laskey <jlaskey@mac.com>2005-08-17 00:39:29 +0000
commit6269ed125fc492d81dc5e3f48482816fc9d47f49 (patch)
tree2d2a3c50229989feebba0db4c0aa76d1f4bb8407
parent37bfbb47de5381704471af6178bfbba29260297c (diff)
Added generic code expansion for [signed|unsigned] i32 to [f32|f64] casts in the
legalizer. PowerPC now uses this expansion instead of ISel version. Example: // signed integer to double conversion double f1(signed x) { return (double)x; } // unsigned integer to double conversion double f2(unsigned x) { return (double)x; } // signed integer to float conversion float f3(signed x) { return (float)x; } // unsigned integer to float conversion float f4(unsigned x) { return (float)x; } Byte Code: internal fastcc double %_Z2f1i(int %x) { entry: %tmp.1 = cast int %x to double ; <double> [#uses=1] ret double %tmp.1 } internal fastcc double %_Z2f2j(uint %x) { entry: %tmp.1 = cast uint %x to double ; <double> [#uses=1] ret double %tmp.1 } internal fastcc float %_Z2f3i(int %x) { entry: %tmp.1 = cast int %x to float ; <float> [#uses=1] ret float %tmp.1 } internal fastcc float %_Z2f4j(uint %x) { entry: %tmp.1 = cast uint %x to float ; <float> [#uses=1] ret float %tmp.1 } internal fastcc double %_Z2g1i(int %x) { entry: %buffer = alloca [2 x uint] ; <[2 x uint]*> [#uses=3] %tmp.0 = getelementptr [2 x uint]* %buffer, int 0, int 0 ; <uint*> [#uses=1] store uint 1127219200, uint* %tmp.0 %tmp.2 = cast int %x to uint ; <uint> [#uses=1] %tmp.3 = xor uint %tmp.2, 2147483648 ; <uint> [#uses=1] %tmp.5 = getelementptr [2 x uint]* %buffer, int 0, int 1 ; <uint*> [#uses=1] store uint %tmp.3, uint* %tmp.5 %tmp.9 = cast [2 x uint]* %buffer to double* ; <double*> [#uses=1] %tmp.10 = load double* %tmp.9 ; <double> [#uses=1] %tmp.13 = load double* cast (long* %signed_bias to double*) ; <double> [#uses=1] %tmp.14 = sub double %tmp.10, %tmp.13 ; <double> [#uses=1] ret double %tmp.14 } internal fastcc double %_Z2g2j(uint %x) { entry: %buffer = alloca [2 x uint] ; <[2 x uint]*> [#uses=3] %tmp.0 = getelementptr [2 x uint]* %buffer, int 0, int 0 ; <uint*> [#uses=1] store uint 1127219200, uint* %tmp.0 %tmp.1 = getelementptr [2 x uint]* %buffer, int 0, int 1 ; <uint*> [#uses=1] store uint %x, uint* %tmp.1 %tmp.4 = cast [2 x uint]* %buffer to double* ; <double*> [#uses=1] %tmp.5 = load double* %tmp.4 ; <double> [#uses=1] %tmp.8 = load double* cast (long* %unsigned_bias to double*) ; <double> [#uses=1] %tmp.9 = sub double %tmp.5, %tmp.8 ; <double> [#uses=1] ret double %tmp.9 } internal fastcc float %_Z2g3i(int %x) { entry: %buffer = alloca [2 x uint] ; <[2 x uint]*> [#uses=3] %tmp.0 = getelementptr [2 x uint]* %buffer, int 0, int 0 ; <uint*> [#uses=1] store uint 1127219200, uint* %tmp.0 %tmp.2 = cast int %x to uint ; <uint> [#uses=1] %tmp.3 = xor uint %tmp.2, 2147483648 ; <uint> [#uses=1] %tmp.5 = getelementptr [2 x uint]* %buffer, int 0, int 1 ; <uint*> [#uses=1] store uint %tmp.3, uint* %tmp.5 %tmp.9 = cast [2 x uint]* %buffer to double* ; <double*> [#uses=1] %tmp.10 = load double* %tmp.9 ; <double> [#uses=1] %tmp.13 = load double* cast (long* %signed_bias to double*) ; <double> [#uses=1] %tmp.14 = sub double %tmp.10, %tmp.13 ; <double> [#uses=1] %tmp.16 = cast double %tmp.14 to float ; <float> [#uses=1] ret float %tmp.16 } internal fastcc float %_Z2g4j(uint %x) { entry: %buffer = alloca [2 x uint] ; <[2 x uint]*> [#uses=3] %tmp.0 = getelementptr [2 x uint]* %buffer, int 0, int 0 ; <uint*> [#uses=1] store uint 1127219200, uint* %tmp.0 %tmp.1 = getelementptr [2 x uint]* %buffer, int 0, int 1 ; <uint*> [#uses=1] store uint %x, uint* %tmp.1 %tmp.4 = cast [2 x uint]* %buffer to double* ; <double*> [#uses=1] %tmp.5 = load double* %tmp.4 ; <double> [#uses=1] %tmp.8 = load double* cast (long* %unsigned_bias to double*) ; <double> [#uses=1] %tmp.9 = sub double %tmp.5, %tmp.8 ; <double> [#uses=1] %tmp.11 = cast double %tmp.9 to float ; <float> [#uses=1] ret float %tmp.11 } PowerPC Code: .machine ppc970 .const .align 2 .CPIl1__Z2f1i_0: ; float 0x4330000080000000 .long 1501560836 ; float 4.5036e+15 .text .align 2 .globl l1__Z2f1i l1__Z2f1i: .LBBl1__Z2f1i_0: ; entry xoris r2, r3, 32768 stw r2, -4(r1) lis r2, 17200 stw r2, -8(r1) lfd f0, -8(r1) lis r2, ha16(.CPIl1__Z2f1i_0) lfs f1, lo16(.CPIl1__Z2f1i_0)(r2) fsub f1, f0, f1 blr .const .align 2 .CPIl2__Z2f2j_0: ; float 0x4330000000000000 .long 1501560832 ; float 4.5036e+15 .text .align 2 .globl l2__Z2f2j l2__Z2f2j: .LBBl2__Z2f2j_0: ; entry stw r3, -4(r1) lis r2, 17200 stw r2, -8(r1) lfd f0, -8(r1) lis r2, ha16(.CPIl2__Z2f2j_0) lfs f1, lo16(.CPIl2__Z2f2j_0)(r2) fsub f1, f0, f1 blr .const .align 2 .CPIl3__Z2f3i_0: ; float 0x4330000080000000 .long 1501560836 ; float 4.5036e+15 .text .align 2 .globl l3__Z2f3i l3__Z2f3i: .LBBl3__Z2f3i_0: ; entry xoris r2, r3, 32768 stw r2, -4(r1) lis r2, 17200 stw r2, -8(r1) lfd f0, -8(r1) lis r2, ha16(.CPIl3__Z2f3i_0) lfs f1, lo16(.CPIl3__Z2f3i_0)(r2) fsub f0, f0, f1 frsp f1, f0 blr .const .align 2 .CPIl4__Z2f4j_0: ; float 0x4330000000000000 .long 1501560832 ; float 4.5036e+15 .text .align 2 .globl l4__Z2f4j l4__Z2f4j: .LBBl4__Z2f4j_0: ; entry stw r3, -4(r1) lis r2, 17200 stw r2, -8(r1) lfd f0, -8(r1) lis r2, ha16(.CPIl4__Z2f4j_0) lfs f1, lo16(.CPIl4__Z2f4j_0)(r2) fsub f0, f0, f1 frsp f1, f0 blr git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@22814 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeDAG.cpp83
1 files changed, 72 insertions, 11 deletions
diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index 7bb4ce2565..56f93adf9f 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -126,7 +126,9 @@ private:
SDOperand ExpandIntToFP(bool isSigned, MVT::ValueType DestTy,
SDOperand Source);
- SDOperand ExpandLegalUINT_TO_FP(SDOperand LegalOp, MVT::ValueType DestVT);
+ SDOperand ExpandLegalINT_TO_FP(bool isSigned,
+ SDOperand LegalOp,
+ MVT::ValueType DestVT);
SDOperand PromoteLegalINT_TO_FP(SDOperand LegalOp, MVT::ValueType DestVT,
bool isSigned);
SDOperand PromoteLegalFP_TO_INT(SDOperand LegalOp, MVT::ValueType DestVT,
@@ -155,12 +157,71 @@ SelectionDAGLegalize::SelectionDAGLegalize(SelectionDAG &dag)
"Too many value types for ValueTypeActions to hold!");
}
-/// ExpandLegalUINT_TO_FP - This function is responsible for legalizing a
-/// UINT_TO_FP operation of the specified operand when the target requests that
+/// ExpandLegalINT_TO_FP - This function is responsible for legalizing a
+/// INT_TO_FP operation of the specified operand when the target requests that
/// we expand it. At this point, we know that the result and operand types are
/// legal for the target.
-SDOperand SelectionDAGLegalize::ExpandLegalUINT_TO_FP(SDOperand Op0,
- MVT::ValueType DestVT) {
+SDOperand SelectionDAGLegalize::ExpandLegalINT_TO_FP(bool isSigned,
+ SDOperand Op0,
+ MVT::ValueType DestVT) {
+ if (Op0.getValueType() == MVT::i32) {
+ // simple 32-bit [signed|unsigned] integer to float/double expansion
+
+ // get the stack frame index of a 8 byte buffer
+ MachineFunction &MF = DAG.getMachineFunction();
+ int SSFI = MF.getFrameInfo()->CreateStackObject(8, 8);
+ // get address of 8 byte buffer
+ SDOperand StackSlot = DAG.getFrameIndex(SSFI, TLI.getPointerTy());
+ // word offset constant for Hi/Lo address computation
+ SDOperand WordOff = DAG.getConstant(sizeof(int), TLI.getPointerTy());
+ // set up Hi and Lo (into buffer) address based on endian
+ SDOperand Hi, Lo;
+ if (TLI.isLittleEndian()) {
+ Hi = DAG.getNode(ISD::ADD, TLI.getPointerTy(), StackSlot, WordOff);
+ Lo = StackSlot;
+ } else {
+ Hi = StackSlot;
+ Lo = DAG.getNode(ISD::ADD, TLI.getPointerTy(), StackSlot, WordOff);
+ }
+ // if signed map to unsigned space
+ SDOperand Op0Mapped;
+ if (isSigned) {
+ // constant used to invert sign bit (signed to unsigned mapping)
+ SDOperand SignBit = DAG.getConstant(0x80000000u, MVT::i32);
+ Op0Mapped = DAG.getNode(ISD::XOR, MVT::i32, Op0, SignBit);
+ } else {
+ Op0Mapped = Op0;
+ }
+ // store the lo of the constructed double - based on integer input
+ SDOperand Store1 = DAG.getNode(ISD::STORE, MVT::Other, DAG.getEntryNode(),
+ Op0Mapped, Lo, DAG.getSrcValue(NULL));
+ // initial hi portion of constructed double
+ SDOperand InitialHi = DAG.getConstant(0x43300000u, MVT::i32);
+ // store the hi of the constructed double - biased exponent
+ SDOperand Store2 = DAG.getNode(ISD::STORE, MVT::Other, Store1,
+ InitialHi, Hi, DAG.getSrcValue(NULL));
+ // load the constructed double
+ SDOperand Load = DAG.getLoad(MVT::f64, Store2, StackSlot,
+ DAG.getSrcValue(NULL));
+ // FP constant to bias correct the final result
+ SDOperand Bias = DAG.getConstantFP(isSigned ? 0x1.000008p52 : 0x1.000000p52,
+ MVT::f64);
+ // subtract the bias
+ SDOperand Sub = DAG.getNode(ISD::SUB, MVT::f64, Load, Bias);
+ // final result
+ SDOperand Result;
+ // handle final rounding
+ if (DestVT == MVT::f64) {
+ // do nothing
+ Result = Sub;
+ } else {
+ // if f32 then cast to f32
+ Result = DAG.getNode(ISD::FP_ROUND, MVT::f32, Sub);
+ }
+ NeedsAnotherIteration = true;
+ return Result;
+ }
+ assert(!isSigned && "Legalize cannot Expand SINT_TO_FP for i64 yet");
SDOperand Tmp1 = DAG.getNode(ISD::SINT_TO_FP, DestVT, Op0);
SDOperand SignSet = DAG.getSetCC(TLI.getSetCCResultTy(), Op0,
@@ -170,9 +231,9 @@ SDOperand SelectionDAGLegalize::ExpandLegalUINT_TO_FP(SDOperand Op0,
SDOperand CstOffset = DAG.getNode(ISD::SELECT, Zero.getValueType(),
SignSet, Four, Zero);
- // If the sign bit of the integer is set, the large number will be treated as
- // a negative number. To counteract this, the dynamic code adds an offset
- // depending on the data type.
+ // If the sign bit of the integer is set, the large number will be treated
+ // as a negative number. To counteract this, the dynamic code adds an
+ // offset depending on the data type.
uint64_t FF;
switch (Op0.getValueType()) {
default: assert(0 && "Unsupported integer type!");
@@ -1648,9 +1709,9 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
Node->getOperand(0).getValueType())) {
default: assert(0 && "Unknown operation action!");
case TargetLowering::Expand:
- assert(!isSigned && "Legalize cannot Expand SINT_TO_FP yet");
- Result = ExpandLegalUINT_TO_FP(LegalizeOp(Node->getOperand(0)),
- Node->getValueType(0));
+ Result = ExpandLegalINT_TO_FP(isSigned,
+ LegalizeOp(Node->getOperand(0)),
+ Node->getValueType(0));
AddLegalizedOperand(Op, Result);
return Result;
case TargetLowering::Promote: