diff options
author | Chris Lattner <sabre@nondot.org> | 2008-05-31 09:23:55 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2008-05-31 09:23:55 +0000 |
commit | 666d664595219ef12601e98db4c98763a0c977ee (patch) | |
tree | 4008c054a6966c92b09b9240ac570a2385df0ed4 /llvm/lib/Target/CBackend/CBackend.cpp | |
parent | 930e099b9011240122a3e9b79e35cdc9efab859c (diff) | |
download | bcm5719-llvm-666d664595219ef12601e98db4c98763a0c977ee.tar.gz bcm5719-llvm-666d664595219ef12601e98db4c98763a0c977ee.zip |
Fix the CBE's handling of instructions whose result is an i1. Previously,
we did not truncate the value down to i1 with (x&1). This caused a problem
when the computation of x was nontrivial, for example, "add i1 1, 1" would
return 2 instead of 0.
This makes the testcase compile into:
...
llvm_cbe_t = (((llvm_cbe_r == 0u) + (llvm_cbe_r == 0u))&1);
llvm_cbe_u = (((unsigned int )(bool )llvm_cbe_t));
...
instead of:
...
llvm_cbe_t = ((llvm_cbe_r == 0u) + (llvm_cbe_r == 0u));
llvm_cbe_u = (((unsigned int )(bool )llvm_cbe_t));
...
This fixes a miscompilation of mediabench/adpcm/rawdaudio/rawdaudio and
403.gcc with the CBE, regressions from LLVM 2.2. Tanya, please pull
this into the release branch.
llvm-svn: 51813
Diffstat (limited to 'llvm/lib/Target/CBackend/CBackend.cpp')
-rw-r--r-- | llvm/lib/Target/CBackend/CBackend.cpp | 66 |
1 files changed, 46 insertions, 20 deletions
diff --git a/llvm/lib/Target/CBackend/CBackend.cpp b/llvm/lib/Target/CBackend/CBackend.cpp index 2ace6ebd8b6..440ce1cb4a4 100644 --- a/llvm/lib/Target/CBackend/CBackend.cpp +++ b/llvm/lib/Target/CBackend/CBackend.cpp @@ -155,6 +155,7 @@ namespace { void writeOperand(Value *Operand); void writeOperandRaw(Value *Operand); + void writeInstComputationInline(Instruction &I); void writeOperandInternal(Value *Operand); void writeOperandWithCast(Value* Operand, unsigned Opcode); void writeOperandWithCast(Value* Operand, const ICmpInst &I); @@ -1217,12 +1218,32 @@ std::string CWriter::GetValueName(const Value *Operand) { return Name; } +/// writeInstComputationInline - Emit the computation for the specified +/// instruction inline, with no destination provided. +void CWriter::writeInstComputationInline(Instruction &I) { + // If this is a non-trivial bool computation, make sure to truncate down to + // a 1 bit value. This is important because we want "add i1 x, y" to return + // "0" when x and y are true, not "2" for example. + bool NeedBoolTrunc = false; + if (I.getType() == Type::Int1Ty && !isa<ICmpInst>(I) && !isa<FCmpInst>(I)) + NeedBoolTrunc = true; + + if (NeedBoolTrunc) + Out << "(("; + + visit(I); + + if (NeedBoolTrunc) + Out << ")&1)"; +} + + void CWriter::writeOperandInternal(Value *Operand) { if (Instruction *I = dyn_cast<Instruction>(Operand)) + // Should we inline this instruction to build a tree? if (isInlinableInst(*I) && !isDirectAlloca(I)) { - // Should we inline this instruction to build a tree? Out << '('; - visit(*I); + writeInstComputationInline(*I); Out << ')'; return; } @@ -2152,12 +2173,12 @@ void CWriter::printBasicBlock(BasicBlock *BB) { outputLValue(II); else Out << " "; - visit(*II); + writeInstComputationInline(*II); Out << ";\n"; } } - // Don't emit prefix or suffix for the terminator... + // Don't emit prefix or suffix for the terminator. visit(*BB->getTerminator()); } @@ -2481,29 +2502,34 @@ static const char * getFloatBitCastField(const Type *Ty) { void CWriter::visitCastInst(CastInst &I) { const Type *DstTy = I.getType(); const Type *SrcTy = I.getOperand(0)->getType(); - Out << '('; if (isFPIntBitCast(I)) { + Out << '('; // These int<->float and long<->double casts need to be handled specially Out << GetValueName(&I) << "__BITCAST_TEMPORARY." << getFloatBitCastField(I.getOperand(0)->getType()) << " = "; writeOperand(I.getOperand(0)); Out << ", " << GetValueName(&I) << "__BITCAST_TEMPORARY." << getFloatBitCastField(I.getType()); - } else { - printCast(I.getOpcode(), SrcTy, DstTy); - if (I.getOpcode() == Instruction::SExt && SrcTy == Type::Int1Ty) { - // Make sure we really get a sext from bool by subtracing the bool from 0 - Out << "0-"; - } - writeOperand(I.getOperand(0)); - if (DstTy == Type::Int1Ty && - (I.getOpcode() == Instruction::Trunc || - I.getOpcode() == Instruction::FPToUI || - I.getOpcode() == Instruction::FPToSI || - I.getOpcode() == Instruction::PtrToInt)) { - // Make sure we really get a trunc to bool by anding the operand with 1 - Out << "&1u"; - } + Out << ')'; + return; + } + + Out << '('; + printCast(I.getOpcode(), SrcTy, DstTy); + + // Make a sext from i1 work by subtracting the i1 from 0 (an int). + if (SrcTy == Type::Int1Ty && I.getOpcode() == Instruction::SExt) + Out << "0-"; + + writeOperand(I.getOperand(0)); + + if (DstTy == Type::Int1Ty && + (I.getOpcode() == Instruction::Trunc || + I.getOpcode() == Instruction::FPToUI || + I.getOpcode() == Instruction::FPToSI || + I.getOpcode() == Instruction::PtrToInt)) { + // Make sure we really get a trunc to bool by anding the operand with 1 + Out << "&1u"; } Out << ')'; } |