aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorNate Begeman <natebegeman@mac.com>2004-08-29 08:19:32 +0000
committerNate Begeman <natebegeman@mac.com>2004-08-29 08:19:32 +0000
commitf2f0781a109f0a9fe0c3597d2bb1c995de2dab4a (patch)
treea37c12263ecceef9fe1352d69bcb048f03d060b0 /lib
parent67d556567f3fa759bfe5a38f56695c717743f4c4 (diff)
downloadexternal_llvm-f2f0781a109f0a9fe0c3597d2bb1c995de2dab4a.zip
external_llvm-f2f0781a109f0a9fe0c3597d2bb1c995de2dab4a.tar.gz
external_llvm-f2f0781a109f0a9fe0c3597d2bb1c995de2dab4a.tar.bz2
Implement the following missing functionality in the PPC backend:
cast fp->bool cast ulong->fp algebraic right shift long by non-constant value These changes tested across most of the test suite. Fixes Regression/casts git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16081 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/Target/PowerPC/PPC32ISelSimple.cpp179
-rw-r--r--lib/Target/PowerPC/PPCInstrInfo.td1
-rw-r--r--lib/Target/PowerPC/README.txt23
3 files changed, 137 insertions, 66 deletions
diff --git a/lib/Target/PowerPC/PPC32ISelSimple.cpp b/lib/Target/PowerPC/PPC32ISelSimple.cpp
index 814aaf3..923e8d5 100644
--- a/lib/Target/PowerPC/PPC32ISelSimple.cpp
+++ b/lib/Target/PowerPC/PPC32ISelSimple.cpp
@@ -2324,12 +2324,43 @@ void ISel::emitShiftOperation(MachineBasicBlock *MBB,
BuildMI(*MBB, IP, PPC::SLW, 2, DestReg+1).addReg(SrcReg+1)
.addReg(ShiftAmountReg);
} else {
- if (isSigned) {
- // FIXME: Unimplemented
- // Page C-3 of the PowerPC 32bit Programming Environments Manual
- std::cerr << "ERROR: Unimplemented: signed right shift of long\n";
- abort();
- } else {
+ if (isSigned) { // shift right algebraic
+ MachineBasicBlock *TmpMBB =new MachineBasicBlock(BB->getBasicBlock());
+ MachineBasicBlock *PhiMBB =new MachineBasicBlock(BB->getBasicBlock());
+ MachineBasicBlock *OldMBB = BB;
+ ilist<MachineBasicBlock>::iterator It = BB; ++It;
+ F->getBasicBlockList().insert(It, TmpMBB);
+ F->getBasicBlockList().insert(It, PhiMBB);
+ BB->addSuccessor(TmpMBB);
+ BB->addSuccessor(PhiMBB);
+
+ BuildMI(*MBB, IP, PPC::SUBFIC, 2, TmpReg1).addReg(ShiftAmountReg)
+ .addSImm(32);
+ BuildMI(*MBB, IP, PPC::SRW, 2, TmpReg2).addReg(SrcReg+1)
+ .addReg(ShiftAmountReg);
+ BuildMI(*MBB, IP, PPC::SLW, 2, TmpReg3).addReg(SrcReg)
+ .addReg(TmpReg1);
+ BuildMI(*MBB, IP, PPC::OR, 2, TmpReg4).addReg(TmpReg2)
+ .addReg(TmpReg3);
+ BuildMI(*MBB, IP, PPC::ADDICo, 2, TmpReg5).addReg(ShiftAmountReg)
+ .addSImm(-32);
+ BuildMI(*MBB, IP, PPC::SRAW, 2, TmpReg6).addReg(SrcReg)
+ .addReg(TmpReg5);
+ BuildMI(*MBB, IP, PPC::SRAW, 2, DestReg).addReg(SrcReg)
+ .addReg(ShiftAmountReg);
+ BuildMI(*MBB, IP, PPC::BLE, 2).addReg(PPC::CR0).addMBB(PhiMBB);
+
+ // OrMBB:
+ // Select correct least significant half if the shift amount > 32
+ BB = TmpMBB;
+ unsigned OrReg = makeAnotherReg(Type::IntTy);
+ BuildMI(BB, PPC::OR, 2, OrReg).addReg(TmpReg6).addImm(TmpReg6);
+ TmpMBB->addSuccessor(PhiMBB);
+
+ BB = PhiMBB;
+ BuildMI(BB, PPC::PHI, 4, DestReg+1).addReg(TmpReg4).addMBB(OldMBB)
+ .addReg(OrReg).addMBB(TmpMBB);
+ } else { // shift right logical
BuildMI(*MBB, IP, PPC::SUBFIC, 2, TmpReg1).addReg(ShiftAmountReg)
.addSImm(32);
BuildMI(*MBB, IP, PPC::SRW, 2, TmpReg2).addReg(SrcReg+1)
@@ -2654,9 +2685,12 @@ void ISel::emitCastOperation(MachineBasicBlock *MBB,
}
case cFP32:
case cFP64:
- // FSEL perhaps?
- std::cerr << "ERROR: Cast fp-to-bool not implemented!\n";
- abort();
+ unsigned TmpReg = makeAnotherReg(Type::IntTy);
+ unsigned ConstZero = getReg(ConstantFP::get(Type::DoubleTy, 0.0), BB, IP);
+ BuildMI(*MBB, IP, PPC::FCMPU, PPC::CR7).addReg(SrcReg).addReg(ConstZero);
+ BuildMI(*MBB, IP, PPC::MFCR, TmpReg);
+ BuildMI(*MBB, IP, PPC::RLWINM, DestReg).addReg(TmpReg).addImm(31)
+ .addImm(31).addImm(31);
}
return;
}
@@ -2678,13 +2712,70 @@ void ISel::emitCastOperation(MachineBasicBlock *MBB,
// Emit a library call for long to float conversion
if (SrcClass == cLong) {
- std::vector<ValueRecord> Args;
- Args.push_back(ValueRecord(SrcReg, SrcTy));
Function *floatFn = (DestClass == cFP32) ? __floatdisfFn : __floatdidfFn;
- MachineInstr *TheCall =
- BuildMI(PPC::CALLpcrel, 1).addGlobalAddress(floatFn, true);
- doCall(ValueRecord(DestReg, DestTy), TheCall, Args, false);
- TM.CalledFunctions.insert(floatFn);
+ if (SrcTy->isSigned()) {
+ std::vector<ValueRecord> Args;
+ Args.push_back(ValueRecord(SrcReg, SrcTy));
+ MachineInstr *TheCall =
+ BuildMI(PPC::CALLpcrel, 1).addGlobalAddress(floatFn, true);
+ doCall(ValueRecord(DestReg, DestTy), TheCall, Args, false);
+ TM.CalledFunctions.insert(floatFn);
+ } else {
+ std::vector<ValueRecord> CmpArgs, ClrArgs, SetArgs;
+ unsigned ZeroLong = getReg(ConstantUInt::get(SrcTy, 0));
+ unsigned CondReg = makeAnotherReg(Type::IntTy);
+
+ // Update machine-CFG edges
+ MachineBasicBlock *ClrMBB = new MachineBasicBlock(BB->getBasicBlock());
+ MachineBasicBlock *SetMBB = new MachineBasicBlock(BB->getBasicBlock());
+ MachineBasicBlock *PhiMBB = new MachineBasicBlock(BB->getBasicBlock());
+ MachineBasicBlock *OldMBB = BB;
+ ilist<MachineBasicBlock>::iterator It = BB; ++It;
+ F->getBasicBlockList().insert(It, ClrMBB);
+ F->getBasicBlockList().insert(It, SetMBB);
+ F->getBasicBlockList().insert(It, PhiMBB);
+ BB->addSuccessor(ClrMBB);
+ BB->addSuccessor(SetMBB);
+
+ CmpArgs.push_back(ValueRecord(SrcReg, SrcTy));
+ CmpArgs.push_back(ValueRecord(ZeroLong, SrcTy));
+ MachineInstr *TheCall =
+ BuildMI(PPC::CALLpcrel, 1).addGlobalAddress(__cmpdi2Fn, true);
+ doCall(ValueRecord(CondReg, Type::IntTy), TheCall, CmpArgs, false);
+ TM.CalledFunctions.insert(__cmpdi2Fn);
+ BuildMI(*MBB, IP, PPC::CMPWI, 2, PPC::CR0).addReg(CondReg).addSImm(0);
+ BuildMI(*MBB, IP, PPC::BLE, 2).addReg(PPC::CR0).addMBB(SetMBB);
+
+ // ClrMBB
+ BB = ClrMBB;
+ unsigned ClrReg = makeAnotherReg(DestTy);
+ ClrArgs.push_back(ValueRecord(SrcReg, SrcTy));
+ TheCall = BuildMI(PPC::CALLpcrel, 1).addGlobalAddress(floatFn, true);
+ doCall(ValueRecord(ClrReg, DestTy), TheCall, ClrArgs, false);
+ TM.CalledFunctions.insert(floatFn);
+ BuildMI(BB, PPC::B, 1).addMBB(PhiMBB);
+ BB->addSuccessor(PhiMBB);
+
+ // SetMBB
+ BB = SetMBB;
+ unsigned SetReg = makeAnotherReg(DestTy);
+ unsigned CallReg = makeAnotherReg(DestTy);
+ unsigned ShiftedReg = makeAnotherReg(SrcTy);
+ ConstantSInt *Const1 = ConstantSInt::get(Type::IntTy, 1);
+ emitShiftOperation(BB, BB->end(), Src, Const1, false, SrcTy, ShiftedReg);
+ SetArgs.push_back(ValueRecord(ShiftedReg, SrcTy));
+ TheCall = BuildMI(PPC::CALLpcrel, 1).addGlobalAddress(floatFn, true);
+ doCall(ValueRecord(CallReg, DestTy), TheCall, SetArgs, false);
+ TM.CalledFunctions.insert(floatFn);
+ unsigned SetOpcode = (DestClass == cFP32) ? PPC::FADDS : PPC::FADD;
+ BuildMI(BB, SetOpcode, 2, SetReg).addReg(CallReg).addReg(CallReg);
+ BB->addSuccessor(PhiMBB);
+
+ // PhiMBB
+ BB = PhiMBB;
+ BuildMI(BB, PPC::PHI, 4, DestReg).addReg(ClrReg).addMBB(ClrMBB)
+ .addReg(SetReg).addMBB(SetMBB);
+ }
return;
}
@@ -2706,25 +2797,25 @@ void ISel::emitCastOperation(MachineBasicBlock *MBB,
if (!SrcTy->isSigned()) {
ConstantFP *CFP = ConstantFP::get(Type::DoubleTy, 0x1.000000p52);
unsigned ConstF = getReg(CFP, BB, IP);
- BuildMI(*BB, IP, PPC::LIS, 1, constantHi).addSImm(0x4330);
- addFrameReference(BuildMI(*BB, IP, PPC::STW, 3).addReg(constantHi),
+ BuildMI(*MBB, IP, PPC::LIS, 1, constantHi).addSImm(0x4330);
+ addFrameReference(BuildMI(*MBB, IP, PPC::STW, 3).addReg(constantHi),
ValueFrameIdx);
- addFrameReference(BuildMI(*BB, IP, PPC::STW, 3).addReg(SrcReg),
+ addFrameReference(BuildMI(*MBB, IP, PPC::STW, 3).addReg(SrcReg),
ValueFrameIdx, 4);
- addFrameReference(BuildMI(*BB, IP, PPC::LFD, 2, TempF), ValueFrameIdx);
- BuildMI(*BB, IP, PPC::FSUB, 2, DestReg).addReg(TempF).addReg(ConstF);
+ addFrameReference(BuildMI(*MBB, IP, PPC::LFD, 2, TempF), ValueFrameIdx);
+ BuildMI(*MBB, IP, PPC::FSUB, 2, DestReg).addReg(TempF).addReg(ConstF);
} else {
ConstantFP *CFP = ConstantFP::get(Type::DoubleTy, 0x1.000008p52);
unsigned ConstF = getReg(CFP, BB, IP);
unsigned TempLo = makeAnotherReg(Type::IntTy);
- BuildMI(*BB, IP, PPC::LIS, 1, constantHi).addSImm(0x4330);
- addFrameReference(BuildMI(*BB, IP, PPC::STW, 3).addReg(constantHi),
+ BuildMI(*MBB, IP, PPC::LIS, 1, constantHi).addSImm(0x4330);
+ addFrameReference(BuildMI(*MBB, IP, PPC::STW, 3).addReg(constantHi),
ValueFrameIdx);
- BuildMI(*BB, IP, PPC::XORIS, 2, TempLo).addReg(SrcReg).addImm(0x8000);
- addFrameReference(BuildMI(*BB, IP, PPC::STW, 3).addReg(TempLo),
+ BuildMI(*MBB, IP, PPC::XORIS, 2, TempLo).addReg(SrcReg).addImm(0x8000);
+ addFrameReference(BuildMI(*MBB, IP, PPC::STW, 3).addReg(TempLo),
ValueFrameIdx, 4);
- addFrameReference(BuildMI(*BB, IP, PPC::LFD, 2, TempF), ValueFrameIdx);
- BuildMI(*BB, IP, PPC::FSUB, 2, DestReg).addReg(TempF).addReg(ConstF);
+ addFrameReference(BuildMI(*MBB, IP, PPC::LFD, 2, TempF), ValueFrameIdx);
+ BuildMI(*MBB, IP, PPC::FSUB, 2, DestReg).addReg(TempF).addReg(ConstF);
}
return;
}
@@ -2754,8 +2845,8 @@ void ISel::emitCastOperation(MachineBasicBlock *MBB,
unsigned TempReg = makeAnotherReg(Type::DoubleTy);
// Convert to integer in the FP reg and store it to a stack slot
- BuildMI(*BB, IP, PPC::FCTIWZ, 1, TempReg).addReg(SrcReg);
- addFrameReference(BuildMI(*BB, IP, PPC::STFD, 3)
+ BuildMI(*MBB, IP, PPC::FCTIWZ, 1, TempReg).addReg(SrcReg);
+ addFrameReference(BuildMI(*MBB, IP, PPC::STFD, 3)
.addReg(TempReg), ValueFrameIdx);
// There is no load signed byte opcode, so we must emit a sign extend for
@@ -2763,13 +2854,13 @@ void ISel::emitCastOperation(MachineBasicBlock *MBB,
// correct offset.
if (DestClass == cByte) {
unsigned TempReg2 = makeAnotherReg(DestTy);
- addFrameReference(BuildMI(*BB, IP, PPC::LBZ, 2, TempReg2),
+ addFrameReference(BuildMI(*MBB, IP, PPC::LBZ, 2, TempReg2),
ValueFrameIdx, 7);
- BuildMI(*BB, IP, PPC::EXTSB, 1, DestReg).addReg(TempReg2);
+ BuildMI(*MBB, IP, PPC::EXTSB, 1, DestReg).addReg(TempReg2);
} else {
int offset = (DestClass == cShort) ? 6 : 4;
unsigned LoadOp = (DestClass == cShort) ? PPC::LHA : PPC::LWZ;
- addFrameReference(BuildMI(*BB, IP, LoadOp, 2, DestReg),
+ addFrameReference(BuildMI(*MBB, IP, LoadOp, 2, DestReg),
ValueFrameIdx, offset);
}
} else {
@@ -2800,34 +2891,34 @@ void ISel::emitCastOperation(MachineBasicBlock *MBB,
// Convert from floating point to unsigned 32-bit value
// Use 0 if incoming value is < 0.0
- BuildMI(*BB, IP, PPC::FSEL, 3, UseZero).addReg(SrcReg).addReg(SrcReg)
+ BuildMI(*MBB, IP, PPC::FSEL, 3, UseZero).addReg(SrcReg).addReg(SrcReg)
.addReg(Zero);
// Use 2**32 - 1 if incoming value is >= 2**32
- BuildMI(*BB, IP, PPC::FSUB, 2, UseMaxInt).addReg(MaxInt).addReg(SrcReg);
- BuildMI(*BB, IP, PPC::FSEL, 3, UseChoice).addReg(UseMaxInt)
+ BuildMI(*MBB, IP, PPC::FSUB, 2, UseMaxInt).addReg(MaxInt).addReg(SrcReg);
+ BuildMI(*MBB, IP, PPC::FSEL, 3, UseChoice).addReg(UseMaxInt)
.addReg(UseZero).addReg(MaxInt);
// Subtract 2**31
- BuildMI(*BB, IP, PPC::FSUB, 2, TmpReg).addReg(UseChoice).addReg(Border);
+ BuildMI(*MBB, IP, PPC::FSUB, 2, TmpReg).addReg(UseChoice).addReg(Border);
// Use difference if >= 2**31
- BuildMI(*BB, IP, PPC::FCMPU, 2, PPC::CR0).addReg(UseChoice)
+ BuildMI(*MBB, IP, PPC::FCMPU, 2, PPC::CR0).addReg(UseChoice)
.addReg(Border);
- BuildMI(*BB, IP, PPC::FSEL, 3, TmpReg2).addReg(TmpReg).addReg(TmpReg)
+ BuildMI(*MBB, IP, PPC::FSEL, 3, TmpReg2).addReg(TmpReg).addReg(TmpReg)
.addReg(UseChoice);
// Convert to integer
- BuildMI(*BB, IP, PPC::FCTIWZ, 1, ConvReg).addReg(TmpReg2);
- addFrameReference(BuildMI(*BB, IP, PPC::STFD, 3).addReg(ConvReg),
+ BuildMI(*MBB, IP, PPC::FCTIWZ, 1, ConvReg).addReg(TmpReg2);
+ addFrameReference(BuildMI(*MBB, IP, PPC::STFD, 3).addReg(ConvReg),
FrameIdx);
if (DestClass == cByte) {
- addFrameReference(BuildMI(*BB, IP, PPC::LBZ, 2, DestReg),
+ addFrameReference(BuildMI(*MBB, IP, PPC::LBZ, 2, DestReg),
FrameIdx, 7);
} else if (DestClass == cShort) {
- addFrameReference(BuildMI(*BB, IP, PPC::LHZ, 2, DestReg),
+ addFrameReference(BuildMI(*MBB, IP, PPC::LHZ, 2, DestReg),
FrameIdx, 6);
} if (DestClass == cInt) {
- addFrameReference(BuildMI(*BB, IP, PPC::LWZ, 2, IntTmp),
+ addFrameReference(BuildMI(*MBB, IP, PPC::LWZ, 2, IntTmp),
FrameIdx, 4);
- BuildMI(*BB, IP, PPC::BLT, 2).addReg(PPC::CR0).addMBB(PhiMBB);
- BuildMI(*BB, IP, PPC::B, 1).addMBB(XorMBB);
+ BuildMI(*MBB, IP, PPC::BLT, 2).addReg(PPC::CR0).addMBB(PhiMBB);
+ BuildMI(*MBB, IP, PPC::B, 1).addMBB(XorMBB);
// XorMBB:
// add 2**31 if input was >= 2**31
diff --git a/lib/Target/PowerPC/PPCInstrInfo.td b/lib/Target/PowerPC/PPCInstrInfo.td
index 6ef0bdd..8629824 100644
--- a/lib/Target/PowerPC/PPCInstrInfo.td
+++ b/lib/Target/PowerPC/PPCInstrInfo.td
@@ -47,6 +47,7 @@ def SUBI : DForm_2<"subi", 14, 0, 0>;
def LI : DForm_2_r0<"li", 14, 0, 0>;
def LIS : DForm_2_r0<"lis", 15, 0, 0>;
def ADDIC : DForm_2<"addic", 12, 0, 0>;
+def ADDICo : DForm_2<"addic.", 13, 0, 0>;
def ADD : XOForm_1<"add", 31, 266, 0, 0, 0, 0>;
def ADDC : XOForm_1<"addc", 31, 10, 0, 0, 0, 0>;
def ADDE : XOForm_1<"adde", 31, 138, 0, 0, 0, 0>;
diff --git a/lib/Target/PowerPC/README.txt b/lib/Target/PowerPC/README.txt
index ab383df..222780b 100644
--- a/lib/Target/PowerPC/README.txt
+++ b/lib/Target/PowerPC/README.txt
@@ -1,28 +1,10 @@
TODO:
+* switch to auto-generated asm writer
* use stfiwx in float->int
-* implement cast fp to bool
-* implement algebraic shift right long by reg
* implement scheduling info
* implement powerpc-64 for darwin
* implement powerpc-64 for aix
* fix rlwimi generation to be use-and-def
-* fix ulong to double:
- floatdidf assumes signed longs. so if the high but of a ulong
- just happens to be set, you get the wrong sign. The fix for this
- is to call cmpdi2 to compare against zero, if so shift right by one,
- convert to fp, and multiply by (add to itself). the sequence would
- look like:
- {r3:r4} holds ulong a;
- li r5, 0
- li r6, 0 (set r5:r6 to ulong 0)
- call cmpdi2 ==> sets r3 <, =, > 0
- if r3 > 0
- call floatdidf as usual
- else
- shift right ulong a, 1 (we could use emitShift)
- call floatdidf
- fadd f1, f1, f1 (fp left shift by 1)
-* cast elimination pass (uint -> sbyte -> short, kill the byte -> short)
* should hint to the branch select pass that it doesn't need to print the
second unconditional branch, so we don't end up with things like:
b .LBBl42__2E_expand_function_8_674 ; loopentry.24
@@ -30,9 +12,6 @@ TODO:
b .LBBl42__2E_expand_function_8_42 ; NewDefault
Currently failing tests that should pass:
-* SingleSource
- `- Regression
- | `- casts (ulong to fp failure)
* MultiSource
|- Applications
| `- hbd: miscompilation