From 425ff24bb3cd74a46cad98688547d33a12ea0ab6 Mon Sep 17 00:00:00 2001 From: Misha Brukman Date: Thu, 1 Jul 2004 21:34:10 +0000 Subject: [PATCH] * Get rid of constant-expr handling code: we use the ConstantExpr lowering pass * Use the SetCC handling code in the format of Brian's V8 * Add FIXMEs where calls to functions are being made without adding them to the Module first... they cause missing symbols at assembly-time. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@14553 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/PowerPC/PPC32ISelSimple.cpp | 182 ++++++++++------------- lib/Target/PowerPC/PowerPCISelSimple.cpp | 182 ++++++++++------------- 2 files changed, 164 insertions(+), 200 deletions(-) diff --git a/lib/Target/PowerPC/PPC32ISelSimple.cpp b/lib/Target/PowerPC/PPC32ISelSimple.cpp index b5651c87661..d2d14aed8b9 100644 --- a/lib/Target/PowerPC/PPC32ISelSimple.cpp +++ b/lib/Target/PowerPC/PPC32ISelSimple.cpp @@ -424,63 +424,6 @@ unsigned ISel::getFixedSizedAllocaFI(AllocaInst *AI) { void ISel::copyConstantToRegister(MachineBasicBlock *MBB, MachineBasicBlock::iterator IP, Constant *C, unsigned R) { - if (ConstantExpr *CE = dyn_cast(C)) { - unsigned Class = 0; - switch (CE->getOpcode()) { - case Instruction::GetElementPtr: - emitGEPOperation(MBB, IP, CE->getOperand(0), - CE->op_begin()+1, CE->op_end(), R); - return; - case Instruction::Cast: - emitCastOperation(MBB, IP, CE->getOperand(0), CE->getType(), R); - return; - - case Instruction::Xor: ++Class; // FALL THROUGH - case Instruction::Or: ++Class; // FALL THROUGH - case Instruction::And: ++Class; // FALL THROUGH - case Instruction::Sub: ++Class; // FALL THROUGH - case Instruction::Add: - emitSimpleBinaryOperation(MBB, IP, CE->getOperand(0), CE->getOperand(1), - Class, R); - return; - - case Instruction::Mul: - emitMultiply(MBB, IP, CE->getOperand(0), CE->getOperand(1), R); - return; - - case Instruction::Div: - case Instruction::Rem: - emitDivRemOperation(MBB, IP, CE->getOperand(0), CE->getOperand(1), - CE->getOpcode() == Instruction::Div, R); - return; - - case Instruction::SetNE: - case Instruction::SetEQ: - case Instruction::SetLT: - case Instruction::SetGT: - case Instruction::SetLE: - case Instruction::SetGE: - emitSetCCOperation(MBB, IP, CE->getOperand(0), CE->getOperand(1), - CE->getOpcode(), R); - return; - - case Instruction::Shl: - case Instruction::Shr: - emitShiftOperation(MBB, IP, CE->getOperand(0), CE->getOperand(1), - CE->getOpcode() == Instruction::Shl, CE->getType(), R); - return; - - case Instruction::Select: - emitSelectOperation(MBB, IP, CE->getOperand(0), CE->getOperand(1), - CE->getOperand(2), R); - return; - - default: - std::cerr << "Offending expr: " << C << "\n"; - assert(0 && "Constant expression not yet handled!\n"); - } - } - if (C->getType()->isIntegral()) { unsigned Class = getClassB(C->getType()); @@ -852,15 +795,6 @@ unsigned ISel::EmitComparison(unsigned OpNum, Value *Op0, Value *Op1, //BuildMI(*MBB, IP, PPC32::CMPLI, 2, PPC32::CR0).addReg(FinalTmp).addImm(0); return OpNum; } else { - // Emit a sequence of code which compares the high and low parts once - // each, then uses a conditional move to handle the overflow case. For - // example, a setlt for long would generate code like this: - // - // AL = lo(op1) < lo(op2) // Always unsigned comparison - // BL = hi(op1) < hi(op2) // Signedness depends on operands - // dest = hi(op1) == hi(op2) ? BL : AL; - // - // FIXME: Not Yet Implemented std::cerr << "EmitComparison unimplemented: Opnum >= 2\n"; abort(); @@ -893,15 +827,6 @@ unsigned ISel::EmitComparison(unsigned OpNum, Value *Op0, Value *Op1, //BuildMI(*MBB, IP, PPC32::CMPLI, 2, PPC32::CR0).addReg(FinalTmp).addImm(0); break; // Allow the sete or setne to be generated from flags set by OR } else { - // Emit a sequence of code which compares the high and low parts once - // each, then uses a conditional move to handle the overflow case. For - // example, a setlt for long would generate code like this: - // - // AL = lo(op1) < lo(op2) // Signedness depends on operands - // BL = hi(op1) < hi(op2) // Always unsigned comparison - // dest = hi(op1) == hi(op2) ? BL : AL; - // - // FIXME: Not Yet Implemented std::cerr << "EmitComparison (cLong) unimplemented: Opnum >= 2\n"; abort(); @@ -911,35 +836,89 @@ unsigned ISel::EmitComparison(unsigned OpNum, Value *Op0, Value *Op1, return OpNum; } -/// SetCC instructions - Here we just emit boilerplate code to set a byte-sized -/// register, then move it to wherever the result should be. +/// visitSetCondInst - /// void ISel::visitSetCondInst(SetCondInst &I) { - if (canFoldSetCCIntoBranchOrSelect(&I)) - return; // Fold this into a branch or select. - + unsigned Op0Reg = getReg(I.getOperand(0)); + unsigned Op1Reg = getReg(I.getOperand(1)); unsigned DestReg = getReg(I); - MachineBasicBlock::iterator MII = BB->end(); - emitSetCCOperation(BB, MII, I.getOperand(0), I.getOperand(1), I.getOpcode(), - DestReg); + const Type *Ty = I.getOperand (0)->getType(); + + assert(getClass(Ty) < cLong && "can't setcc on longs or fp yet"); + // Compare the two values. + BuildMI(BB, PPC32::CMPW, 2, PPC32::CR0).addReg(Op0Reg).addReg(Op1Reg); + + unsigned BranchIdx; + switch (I.getOpcode()) { + default: assert(0 && "Unknown setcc instruction!"); + case Instruction::SetEQ: BranchIdx = 0; break; + case Instruction::SetNE: BranchIdx = 1; break; + case Instruction::SetLT: BranchIdx = 2; break; + case Instruction::SetGT: BranchIdx = 3; break; + case Instruction::SetLE: BranchIdx = 4; break; + case Instruction::SetGE: BranchIdx = 5; break; + } + static unsigned OpcodeTab[] = { + PPC32::BEQ, PPC32::BNE, PPC32::BLT, PPC32::BGT, PPC32::BLE, PPC32::BGE + }; + unsigned Opcode = OpcodeTab[BranchIdx]; + + MachineBasicBlock *thisMBB = BB; + const BasicBlock *LLVM_BB = BB->getBasicBlock(); + // thisMBB: + // ... + // cmpTY cr0, r1, r2 + // bCC copy1MBB + // b copy0MBB + + // FIXME: we wouldn't need copy0MBB (we could fold it into thisMBB) + // if we could insert other, non-terminator instructions after the + // bCC. But MBB->getFirstTerminator() can't understand this. + MachineBasicBlock *copy1MBB = new MachineBasicBlock(LLVM_BB); + F->getBasicBlockList().push_back(copy1MBB); + BuildMI(BB, Opcode, 2).addReg(PPC32::CR0).addMBB(copy1MBB); + MachineBasicBlock *copy0MBB = new MachineBasicBlock(LLVM_BB); + F->getBasicBlockList().push_back(copy0MBB); + BuildMI(BB, PPC32::B, 1).addMBB(copy0MBB); + // Update machine-CFG edges + BB->addSuccessor(copy1MBB); + BB->addSuccessor(copy0MBB); + + // copy0MBB: + // %FalseValue = li 0 + // ba sinkMBB + BB = copy0MBB; + unsigned FalseValue = makeAnotherReg(I.getType()); + BuildMI(BB, PPC32::LI, 1, FalseValue).addZImm(0); + MachineBasicBlock *sinkMBB = new MachineBasicBlock(LLVM_BB); + F->getBasicBlockList().push_back(sinkMBB); + BuildMI(BB, PPC32::B, 1).addMBB(sinkMBB); + // Update machine-CFG edges + BB->addSuccessor(sinkMBB); + + DEBUG(std::cerr << "thisMBB is at " << (void*)thisMBB << "\n"); + DEBUG(std::cerr << "copy1MBB is at " << (void*)copy1MBB << "\n"); + DEBUG(std::cerr << "copy0MBB is at " << (void*)copy0MBB << "\n"); + DEBUG(std::cerr << "sinkMBB is at " << (void*)sinkMBB << "\n"); + + // copy1MBB: + // %TrueValue = li 1 + // ba sinkMBB + BB = copy1MBB; + unsigned TrueValue = makeAnotherReg (I.getType ()); + BuildMI(BB, PPC32::LI, 1, TrueValue).addZImm(1); + BuildMI(BB, PPC32::B, 1).addMBB(sinkMBB); + // Update machine-CFG edges + BB->addSuccessor(sinkMBB); + + // sinkMBB: + // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, copy1MBB ] + // ... + BB = sinkMBB; + BuildMI(BB, PPC32::PHI, 4, DestReg).addReg(FalseValue) + .addMBB(copy0MBB).addReg(TrueValue).addMBB(copy1MBB); } -/// emitSetCCOperation - Common code shared between visitSetCondInst and -/// constant expression support. -/// -/// FIXME: this is wrong. we should figure out a way to guarantee -/// TargetReg is a CR and then make it a no-op -void ISel::emitSetCCOperation(MachineBasicBlock *MBB, - MachineBasicBlock::iterator IP, - Value *Op0, Value *Op1, unsigned Opcode, - unsigned TargetReg) { - unsigned OpNum = getSetCCNumber(Opcode); - OpNum = EmitComparison(OpNum, Op0, Op1, MBB, IP); - - // The value is already in CR0 at this point, do nothing. -} - - void ISel::visitSelectInst(SelectInst &SI) { unsigned DestReg = getReg(SI); MachineBasicBlock::iterator MII = BB->end(); @@ -1930,6 +1909,8 @@ void ISel::emitDivRemOperation(MachineBasicBlock *BB, } else { // Floating point remainder... unsigned Op0Reg = getReg(Op0, BB, IP); unsigned Op1Reg = getReg(Op1, BB, IP); + // FIXME: Make sure the module has external function + // double fmod(double, double) MachineInstr *TheCall = BuildMI(PPC32::CALLpcrel, 1).addExternalSymbol("fmod", true); std::vector Args; @@ -1939,7 +1920,8 @@ void ISel::emitDivRemOperation(MachineBasicBlock *BB, } return; case cLong: { - static const char *FnName[] = + // FIXME: Make sure the module has external function + static const char *FnName[] = { "__moddi3", "__divdi3", "__umoddi3", "__udivdi3" }; unsigned Op0Reg = getReg(Op0, BB, IP); unsigned Op1Reg = getReg(Op1, BB, IP); diff --git a/lib/Target/PowerPC/PowerPCISelSimple.cpp b/lib/Target/PowerPC/PowerPCISelSimple.cpp index b5651c87661..d2d14aed8b9 100644 --- a/lib/Target/PowerPC/PowerPCISelSimple.cpp +++ b/lib/Target/PowerPC/PowerPCISelSimple.cpp @@ -424,63 +424,6 @@ unsigned ISel::getFixedSizedAllocaFI(AllocaInst *AI) { void ISel::copyConstantToRegister(MachineBasicBlock *MBB, MachineBasicBlock::iterator IP, Constant *C, unsigned R) { - if (ConstantExpr *CE = dyn_cast(C)) { - unsigned Class = 0; - switch (CE->getOpcode()) { - case Instruction::GetElementPtr: - emitGEPOperation(MBB, IP, CE->getOperand(0), - CE->op_begin()+1, CE->op_end(), R); - return; - case Instruction::Cast: - emitCastOperation(MBB, IP, CE->getOperand(0), CE->getType(), R); - return; - - case Instruction::Xor: ++Class; // FALL THROUGH - case Instruction::Or: ++Class; // FALL THROUGH - case Instruction::And: ++Class; // FALL THROUGH - case Instruction::Sub: ++Class; // FALL THROUGH - case Instruction::Add: - emitSimpleBinaryOperation(MBB, IP, CE->getOperand(0), CE->getOperand(1), - Class, R); - return; - - case Instruction::Mul: - emitMultiply(MBB, IP, CE->getOperand(0), CE->getOperand(1), R); - return; - - case Instruction::Div: - case Instruction::Rem: - emitDivRemOperation(MBB, IP, CE->getOperand(0), CE->getOperand(1), - CE->getOpcode() == Instruction::Div, R); - return; - - case Instruction::SetNE: - case Instruction::SetEQ: - case Instruction::SetLT: - case Instruction::SetGT: - case Instruction::SetLE: - case Instruction::SetGE: - emitSetCCOperation(MBB, IP, CE->getOperand(0), CE->getOperand(1), - CE->getOpcode(), R); - return; - - case Instruction::Shl: - case Instruction::Shr: - emitShiftOperation(MBB, IP, CE->getOperand(0), CE->getOperand(1), - CE->getOpcode() == Instruction::Shl, CE->getType(), R); - return; - - case Instruction::Select: - emitSelectOperation(MBB, IP, CE->getOperand(0), CE->getOperand(1), - CE->getOperand(2), R); - return; - - default: - std::cerr << "Offending expr: " << C << "\n"; - assert(0 && "Constant expression not yet handled!\n"); - } - } - if (C->getType()->isIntegral()) { unsigned Class = getClassB(C->getType()); @@ -852,15 +795,6 @@ unsigned ISel::EmitComparison(unsigned OpNum, Value *Op0, Value *Op1, //BuildMI(*MBB, IP, PPC32::CMPLI, 2, PPC32::CR0).addReg(FinalTmp).addImm(0); return OpNum; } else { - // Emit a sequence of code which compares the high and low parts once - // each, then uses a conditional move to handle the overflow case. For - // example, a setlt for long would generate code like this: - // - // AL = lo(op1) < lo(op2) // Always unsigned comparison - // BL = hi(op1) < hi(op2) // Signedness depends on operands - // dest = hi(op1) == hi(op2) ? BL : AL; - // - // FIXME: Not Yet Implemented std::cerr << "EmitComparison unimplemented: Opnum >= 2\n"; abort(); @@ -893,15 +827,6 @@ unsigned ISel::EmitComparison(unsigned OpNum, Value *Op0, Value *Op1, //BuildMI(*MBB, IP, PPC32::CMPLI, 2, PPC32::CR0).addReg(FinalTmp).addImm(0); break; // Allow the sete or setne to be generated from flags set by OR } else { - // Emit a sequence of code which compares the high and low parts once - // each, then uses a conditional move to handle the overflow case. For - // example, a setlt for long would generate code like this: - // - // AL = lo(op1) < lo(op2) // Signedness depends on operands - // BL = hi(op1) < hi(op2) // Always unsigned comparison - // dest = hi(op1) == hi(op2) ? BL : AL; - // - // FIXME: Not Yet Implemented std::cerr << "EmitComparison (cLong) unimplemented: Opnum >= 2\n"; abort(); @@ -911,35 +836,89 @@ unsigned ISel::EmitComparison(unsigned OpNum, Value *Op0, Value *Op1, return OpNum; } -/// SetCC instructions - Here we just emit boilerplate code to set a byte-sized -/// register, then move it to wherever the result should be. +/// visitSetCondInst - /// void ISel::visitSetCondInst(SetCondInst &I) { - if (canFoldSetCCIntoBranchOrSelect(&I)) - return; // Fold this into a branch or select. - + unsigned Op0Reg = getReg(I.getOperand(0)); + unsigned Op1Reg = getReg(I.getOperand(1)); unsigned DestReg = getReg(I); - MachineBasicBlock::iterator MII = BB->end(); - emitSetCCOperation(BB, MII, I.getOperand(0), I.getOperand(1), I.getOpcode(), - DestReg); + const Type *Ty = I.getOperand (0)->getType(); + + assert(getClass(Ty) < cLong && "can't setcc on longs or fp yet"); + // Compare the two values. + BuildMI(BB, PPC32::CMPW, 2, PPC32::CR0).addReg(Op0Reg).addReg(Op1Reg); + + unsigned BranchIdx; + switch (I.getOpcode()) { + default: assert(0 && "Unknown setcc instruction!"); + case Instruction::SetEQ: BranchIdx = 0; break; + case Instruction::SetNE: BranchIdx = 1; break; + case Instruction::SetLT: BranchIdx = 2; break; + case Instruction::SetGT: BranchIdx = 3; break; + case Instruction::SetLE: BranchIdx = 4; break; + case Instruction::SetGE: BranchIdx = 5; break; + } + static unsigned OpcodeTab[] = { + PPC32::BEQ, PPC32::BNE, PPC32::BLT, PPC32::BGT, PPC32::BLE, PPC32::BGE + }; + unsigned Opcode = OpcodeTab[BranchIdx]; + + MachineBasicBlock *thisMBB = BB; + const BasicBlock *LLVM_BB = BB->getBasicBlock(); + // thisMBB: + // ... + // cmpTY cr0, r1, r2 + // bCC copy1MBB + // b copy0MBB + + // FIXME: we wouldn't need copy0MBB (we could fold it into thisMBB) + // if we could insert other, non-terminator instructions after the + // bCC. But MBB->getFirstTerminator() can't understand this. + MachineBasicBlock *copy1MBB = new MachineBasicBlock(LLVM_BB); + F->getBasicBlockList().push_back(copy1MBB); + BuildMI(BB, Opcode, 2).addReg(PPC32::CR0).addMBB(copy1MBB); + MachineBasicBlock *copy0MBB = new MachineBasicBlock(LLVM_BB); + F->getBasicBlockList().push_back(copy0MBB); + BuildMI(BB, PPC32::B, 1).addMBB(copy0MBB); + // Update machine-CFG edges + BB->addSuccessor(copy1MBB); + BB->addSuccessor(copy0MBB); + + // copy0MBB: + // %FalseValue = li 0 + // ba sinkMBB + BB = copy0MBB; + unsigned FalseValue = makeAnotherReg(I.getType()); + BuildMI(BB, PPC32::LI, 1, FalseValue).addZImm(0); + MachineBasicBlock *sinkMBB = new MachineBasicBlock(LLVM_BB); + F->getBasicBlockList().push_back(sinkMBB); + BuildMI(BB, PPC32::B, 1).addMBB(sinkMBB); + // Update machine-CFG edges + BB->addSuccessor(sinkMBB); + + DEBUG(std::cerr << "thisMBB is at " << (void*)thisMBB << "\n"); + DEBUG(std::cerr << "copy1MBB is at " << (void*)copy1MBB << "\n"); + DEBUG(std::cerr << "copy0MBB is at " << (void*)copy0MBB << "\n"); + DEBUG(std::cerr << "sinkMBB is at " << (void*)sinkMBB << "\n"); + + // copy1MBB: + // %TrueValue = li 1 + // ba sinkMBB + BB = copy1MBB; + unsigned TrueValue = makeAnotherReg (I.getType ()); + BuildMI(BB, PPC32::LI, 1, TrueValue).addZImm(1); + BuildMI(BB, PPC32::B, 1).addMBB(sinkMBB); + // Update machine-CFG edges + BB->addSuccessor(sinkMBB); + + // sinkMBB: + // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, copy1MBB ] + // ... + BB = sinkMBB; + BuildMI(BB, PPC32::PHI, 4, DestReg).addReg(FalseValue) + .addMBB(copy0MBB).addReg(TrueValue).addMBB(copy1MBB); } -/// emitSetCCOperation - Common code shared between visitSetCondInst and -/// constant expression support. -/// -/// FIXME: this is wrong. we should figure out a way to guarantee -/// TargetReg is a CR and then make it a no-op -void ISel::emitSetCCOperation(MachineBasicBlock *MBB, - MachineBasicBlock::iterator IP, - Value *Op0, Value *Op1, unsigned Opcode, - unsigned TargetReg) { - unsigned OpNum = getSetCCNumber(Opcode); - OpNum = EmitComparison(OpNum, Op0, Op1, MBB, IP); - - // The value is already in CR0 at this point, do nothing. -} - - void ISel::visitSelectInst(SelectInst &SI) { unsigned DestReg = getReg(SI); MachineBasicBlock::iterator MII = BB->end(); @@ -1930,6 +1909,8 @@ void ISel::emitDivRemOperation(MachineBasicBlock *BB, } else { // Floating point remainder... unsigned Op0Reg = getReg(Op0, BB, IP); unsigned Op1Reg = getReg(Op1, BB, IP); + // FIXME: Make sure the module has external function + // double fmod(double, double) MachineInstr *TheCall = BuildMI(PPC32::CALLpcrel, 1).addExternalSymbol("fmod", true); std::vector Args; @@ -1939,7 +1920,8 @@ void ISel::emitDivRemOperation(MachineBasicBlock *BB, } return; case cLong: { - static const char *FnName[] = + // FIXME: Make sure the module has external function + static const char *FnName[] = { "__moddi3", "__divdi3", "__umoddi3", "__udivdi3" }; unsigned Op0Reg = getReg(Op0, BB, IP); unsigned Op1Reg = getReg(Op1, BB, IP);