mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-30 19:35:54 +00:00
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@51813 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
7e2dd6628e
commit
e56d946a38
@ -155,6 +155,7 @@ namespace {
|
|||||||
|
|
||||||
void writeOperand(Value *Operand);
|
void writeOperand(Value *Operand);
|
||||||
void writeOperandRaw(Value *Operand);
|
void writeOperandRaw(Value *Operand);
|
||||||
|
void writeInstComputationInline(Instruction &I);
|
||||||
void writeOperandInternal(Value *Operand);
|
void writeOperandInternal(Value *Operand);
|
||||||
void writeOperandWithCast(Value* Operand, unsigned Opcode);
|
void writeOperandWithCast(Value* Operand, unsigned Opcode);
|
||||||
void writeOperandWithCast(Value* Operand, const ICmpInst &I);
|
void writeOperandWithCast(Value* Operand, const ICmpInst &I);
|
||||||
@ -1217,12 +1218,32 @@ std::string CWriter::GetValueName(const Value *Operand) {
|
|||||||
return Name;
|
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) {
|
void CWriter::writeOperandInternal(Value *Operand) {
|
||||||
if (Instruction *I = dyn_cast<Instruction>(Operand))
|
if (Instruction *I = dyn_cast<Instruction>(Operand))
|
||||||
|
// Should we inline this instruction to build a tree?
|
||||||
if (isInlinableInst(*I) && !isDirectAlloca(I)) {
|
if (isInlinableInst(*I) && !isDirectAlloca(I)) {
|
||||||
// Should we inline this instruction to build a tree?
|
|
||||||
Out << '(';
|
Out << '(';
|
||||||
visit(*I);
|
writeInstComputationInline(*I);
|
||||||
Out << ')';
|
Out << ')';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2152,12 +2173,12 @@ void CWriter::printBasicBlock(BasicBlock *BB) {
|
|||||||
outputLValue(II);
|
outputLValue(II);
|
||||||
else
|
else
|
||||||
Out << " ";
|
Out << " ";
|
||||||
visit(*II);
|
writeInstComputationInline(*II);
|
||||||
Out << ";\n";
|
Out << ";\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't emit prefix or suffix for the terminator...
|
// Don't emit prefix or suffix for the terminator.
|
||||||
visit(*BB->getTerminator());
|
visit(*BB->getTerminator());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2481,29 +2502,34 @@ static const char * getFloatBitCastField(const Type *Ty) {
|
|||||||
void CWriter::visitCastInst(CastInst &I) {
|
void CWriter::visitCastInst(CastInst &I) {
|
||||||
const Type *DstTy = I.getType();
|
const Type *DstTy = I.getType();
|
||||||
const Type *SrcTy = I.getOperand(0)->getType();
|
const Type *SrcTy = I.getOperand(0)->getType();
|
||||||
Out << '(';
|
|
||||||
if (isFPIntBitCast(I)) {
|
if (isFPIntBitCast(I)) {
|
||||||
|
Out << '(';
|
||||||
// These int<->float and long<->double casts need to be handled specially
|
// These int<->float and long<->double casts need to be handled specially
|
||||||
Out << GetValueName(&I) << "__BITCAST_TEMPORARY."
|
Out << GetValueName(&I) << "__BITCAST_TEMPORARY."
|
||||||
<< getFloatBitCastField(I.getOperand(0)->getType()) << " = ";
|
<< getFloatBitCastField(I.getOperand(0)->getType()) << " = ";
|
||||||
writeOperand(I.getOperand(0));
|
writeOperand(I.getOperand(0));
|
||||||
Out << ", " << GetValueName(&I) << "__BITCAST_TEMPORARY."
|
Out << ", " << GetValueName(&I) << "__BITCAST_TEMPORARY."
|
||||||
<< getFloatBitCastField(I.getType());
|
<< getFloatBitCastField(I.getType());
|
||||||
} else {
|
Out << ')';
|
||||||
printCast(I.getOpcode(), SrcTy, DstTy);
|
return;
|
||||||
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-";
|
Out << '(';
|
||||||
}
|
printCast(I.getOpcode(), SrcTy, DstTy);
|
||||||
writeOperand(I.getOperand(0));
|
|
||||||
if (DstTy == Type::Int1Ty &&
|
// Make a sext from i1 work by subtracting the i1 from 0 (an int).
|
||||||
(I.getOpcode() == Instruction::Trunc ||
|
if (SrcTy == Type::Int1Ty && I.getOpcode() == Instruction::SExt)
|
||||||
I.getOpcode() == Instruction::FPToUI ||
|
Out << "0-";
|
||||||
I.getOpcode() == Instruction::FPToSI ||
|
|
||||||
I.getOpcode() == Instruction::PtrToInt)) {
|
writeOperand(I.getOperand(0));
|
||||||
// Make sure we really get a trunc to bool by anding the operand with 1
|
|
||||||
Out << "&1u";
|
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 << ')';
|
Out << ')';
|
||||||
}
|
}
|
||||||
|
14
test/CodeGen/CBackend/2008-05-31-BoolOverflow.ll
Normal file
14
test/CodeGen/CBackend/2008-05-31-BoolOverflow.ll
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
; RUN: llvm-as < %s | llc -march=c | grep {llvm_cbe_t.*&1}
|
||||||
|
define i32 @test(i32 %r) {
|
||||||
|
%s = icmp eq i32 %r, 0
|
||||||
|
%t = add i1 %s, %s
|
||||||
|
%u = zext i1 %t to i32
|
||||||
|
br i1 %t, label %A, label %B
|
||||||
|
A:
|
||||||
|
|
||||||
|
ret i32 %u
|
||||||
|
B:
|
||||||
|
|
||||||
|
%v = select i1 %t, i32 %r, i32 %u
|
||||||
|
ret i32 %v
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user