From baldrick at free.fr Mon Mar 16 02:39:47 2009
From: baldrick at free.fr (Duncan Sands)
Date: Mon, 16 Mar 2009 08:39:47 +0100
Subject: [llvm-commits] [llvm] r66976 - in /llvm/trunk:
lib/CodeGen/PHIElimination.cpp
lib/Transforms/Scalar/CodeGenPrepare.cpp
test/CodeGen/X86/2009-03-13-PHIElimBug.ll
test/CodeGen/X86/split-eh-lpad-edges.ll
In-Reply-To:
References: <200903132259.n2DMxEH4018573@zion.cs.uiuc.edu>
<200903141140.49101.baldrick@free.fr>
Message-ID: <200903160839.48588.baldrick@free.fr>
Hi Evan,
> > %reg1031 = MOV32rr %EAX
> > EH_LABEL 2
> > %reg1025 = MOV32rr %reg1031 <= Invoke result, not an
> > EH_LABEL
> > JMP mbb
> >
> > So in this case the logic bails out, putting the copy at the end of
> > the BB,
> > even though it might still need to be before the invoke.
>
> Something seems wrong with this. Who inserted the copy? The copy from
> EAX to reg1031 is the copy lowered by isel. Is PHI elimination
> inserting the copy from reg1031 to reg1025? Then it should have done
> the right thing.
I'm not sure where it's coming from (see testcase below). By the way, what
do you think of the patch I sent? It's more efficient in the common case of
an invoke with one def/use of SrcReg in the basic block, but less efficient
when there is more than one def/use because it has to walk more of the basic
block.
Ciao,
Duncan.
Run: llc -march=x86 -f phi.bc
If I break on WalkPassEHTryRange, then the first time I hit the breakpoint
I see such a register copy after the EH_LABEL. This is the MBB for "cont",
and it is trying to find a place to put the copy for the phi node in the
landing pad.
declare i32 @f()
declare i32 @g()
define i32 @phi() {
entry:
%a = call i32 @f() ; [#uses=1]
%b = invoke i32 @g()
to label %cont unwind label %lpad ; [#uses=1]
cont: ; preds = %entry
%x = phi i32 [ %b, %entry ] ; [#uses=0]
%aa = call i32 @f() ; [#uses=1]
%bb = invoke i32 @g()
to label %cont2 unwind label %lpad ; [#uses=1]
cont2: ; preds = %cont
%xx = phi i32 [ %bb, %cont ] ; [#uses=1]
ret i32 %xx
lpad: ; preds = %cont, %entry
%y = phi i32 [ %a, %entry ], [ %aa, %cont ] ; [#uses=1]
ret i32 %y
}
From baldrick at free.fr Mon Mar 16 04:03:56 2009
From: baldrick at free.fr (Duncan Sands)
Date: Mon, 16 Mar 2009 10:03:56 +0100
Subject: [llvm-commits] [llvm] r66976 - in /llvm/trunk:
lib/CodeGen/PHIElimination.cpp
lib/Transforms/Scalar/CodeGenPrepare.cpp
test/CodeGen/X86/2009-03-13-PHIElimBug.ll
test/CodeGen/X86/split-eh-lpad-edges.ll
In-Reply-To:
References: <200903132259.n2DMxEH4018573@zion.cs.uiuc.edu>
<200903141140.49101.baldrick@free.fr>
Message-ID: <200903161003.57095.baldrick@free.fr>
Hi Evan, here's another testcase. If you compile
with -fast (to avoid critical edge splitting) then
the copy for the phi node is placed before the call,
even though the value being used is the result of
the call. That's because your patch skips over the
definition of SrcReg while looking for the EH_LABELs.
Is it ok with you if I apply my patch? I'm not sure
how to adjust the 2009-03-13-PHIElimBug.ll testcase
though. I guess I can grep on the -debug output...
Ciao,
Duncan.
declare i32 @f()
define i32 @phi() {
entry:
%a = invoke i32 @f()
to label %cont unwind label %lpad ; [#uses=1]
cont: ; preds = %lpad, %entry
%x = phi i32 [ %a, %entry ], [ %b, %lpad ] ; [#uses=1]
ret i32 %x
lpad: ; preds = %entry
%b = invoke i32 @f()
to label %cont unwind label %lpad2 ; [#uses=1]
lpad2: ; preds = %lpad
ret i32 0
}
From asl at math.spbu.ru Mon Mar 16 10:14:23 2009
From: asl at math.spbu.ru (Anton Korobeynikov)
Date: Mon, 16 Mar 2009 10:14:23 -0500
Subject: [llvm-commits] CVS: llvm-www/OpenProjects.html
Message-ID: <200903161514.n2GFENKI010845@zion.cs.uiuc.edu>
Changes in directory llvm-www:
OpenProjects.html updated: 1.44 -> 1.45
---
Log message:
Add VMKit 'OpenProjects' page
---
Diffs of the changes: (+9 -4)
OpenProjects.html | 13 +++++++++----
1 files changed, 9 insertions(+), 4 deletions(-)
Index: llvm-www/OpenProjects.html
diff -u llvm-www/OpenProjects.html:1.44 llvm-www/OpenProjects.html:1.45
--- llvm-www/OpenProjects.html:1.44 Fri Mar 13 10:36:35 2009
+++ llvm-www/OpenProjects.html Mon Mar 16 10:12:27 2009
@@ -4,7 +4,7 @@
-
+
@@ -78,6 +78,11 @@
Projects list.
+
+
@@ -496,7 +501,7 @@
src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01!">
LLVM Compiler Infrastructure
- Last modified: $Date: 2009/03/13 15:36:35 $
+ Last modified: $Date: 2009/03/16 15:12:27 $
From asl at math.spbu.ru Mon Mar 16 10:22:58 2009
From: asl at math.spbu.ru (Anton Korobeynikov)
Date: Mon, 16 Mar 2009 10:22:58 -0500
Subject: [llvm-commits] CVS: llvm-www/OpenProjects.html
Message-ID: <200903161522.n2GFMwlb011348@zion.cs.uiuc.edu>
Changes in directory llvm-www:
OpenProjects.html updated: 1.45 -> 1.46
---
Log message:
More crazy ideas
---
Diffs of the changes: (+6 -1)
OpenProjects.html | 7 ++++++-
1 files changed, 6 insertions(+), 1 deletion(-)
Index: llvm-www/OpenProjects.html
diff -u llvm-www/OpenProjects.html:1.45 llvm-www/OpenProjects.html:1.46
--- llvm-www/OpenProjects.html:1.45 Mon Mar 16 10:12:27 2009
+++ llvm-www/OpenProjects.html Mon Mar 16 10:19:44 2009
@@ -487,6 +487,11 @@
href="/docs/CommandGuide/html/bugpoint.html">bugpoint to reduce the
test case and post it to a website or mailing list. Repeat ad infinitum.
Design a simple, recognizable logo.
+Add sandbox features to the Interpreter: catch invalid memory accesses,
+ potentially unsafe operations (access via arbitrary memory pointer) etc.
+
+Port Valgrind to use LLVM codegeneration
+ and optimization passes instead of its own.
@@ -501,7 +506,7 @@
src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01!">
LLVM Compiler Infrastructure
- Last modified: $Date: 2009/03/16 15:12:27 $
+ Last modified: $Date: 2009/03/16 15:19:44 $
From dgregor at apple.com Mon Mar 16 12:04:15 2009
From: dgregor at apple.com (Douglas Gregor)
Date: Mon, 16 Mar 2009 17:04:15 -0000
Subject: [llvm-commits] [llvm] r67042 -
/llvm/trunk/utils/TableGen/CMakeLists.txt
Message-ID: <200903161704.n2GH4Fgp015797@zion.cs.uiuc.edu>
Author: dgregor
Date: Mon Mar 16 12:04:14 2009
New Revision: 67042
URL: http://llvm.org/viewvc/llvm-project?rev=67042&view=rev
Log:
Add TGSourceMgr.cpp to CMake build, sort lines
Modified:
llvm/trunk/utils/TableGen/CMakeLists.txt
Modified: llvm/trunk/utils/TableGen/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CMakeLists.txt?rev=67042&r1=67041&r2=67042&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/CMakeLists.txt (original)
+++ llvm/trunk/utils/TableGen/CMakeLists.txt Mon Mar 16 12:04:14 2009
@@ -1,11 +1,13 @@
add_executable(tblgen
AsmWriterEmitter.cpp
CallingConvEmitter.cpp
+ ClangDiagnosticsEmitter.cpp
CodeEmitterGen.cpp
CodeGenDAGPatterns.cpp
CodeGenInstruction.cpp
CodeGenTarget.cpp
DAGISelEmitter.cpp
+ FastISelEmitter.cpp
InstrEnumEmitter.cpp
InstrInfoEmitter.cpp
IntrinsicEmitter.cpp
@@ -15,11 +17,10 @@
SubtargetEmitter.cpp
TGLexer.cpp
TGParser.cpp
+ TGSourceMgr.cpp
TGValueTypes.cpp
TableGen.cpp
TableGenBackend.cpp
- FastISelEmitter.cpp
- ClangDiagnosticsEmitter.cpp
)
target_link_libraries(tblgen LLVMSupport LLVMSystem)
From isanbard at gmail.com Mon Mar 16 13:08:54 2009
From: isanbard at gmail.com (Bill Wendling)
Date: Mon, 16 Mar 2009 18:08:54 -0000
Subject: [llvm-commits] [llvm] r67044 - in /llvm/branches/Apple/Dib:
include/llvm/CodeGen/FastISel.h lib/CodeGen/SelectionDAG/FastISel.cpp
lib/Target/X86/X86FastISel.cpp test/CodeGen/X86/fast-isel-i1.ll
test/CodeGen/X86/fast-isel-phys.ll test/CodeGen/X86/fast-isel-trunc.ll
test/CodeGen/X86/fast-isel.ll
Message-ID: <200903161808.n2GI8sJN018071@zion.cs.uiuc.edu>
Author: void
Date: Mon Mar 16 13:08:53 2009
New Revision: 67044
URL: http://llvm.org/viewvc/llvm-project?rev=67044&view=rev
Log:
--- Merging (from foreign repository) r66941 into '.':
A test/CodeGen/X86/fast-isel-i1.ll
U include/llvm/CodeGen/FastISel.h
U lib/CodeGen/SelectionDAG/FastISel.cpp
U lib/Target/X86/X86FastISel.cpp
--- Merging (from foreign repository) r66988 into '.':
U test/CodeGen/X86/fast-isel-phys.ll
U test/CodeGen/X86/fast-isel.ll
U test/CodeGen/X86/fast-isel-trunc.ll
G lib/CodeGen/SelectionDAG/FastISel.cpp
G lib/Target/X86/X86FastISel.cpp
Added:
llvm/branches/Apple/Dib/test/CodeGen/X86/fast-isel-i1.ll
Modified:
llvm/branches/Apple/Dib/include/llvm/CodeGen/FastISel.h
llvm/branches/Apple/Dib/lib/CodeGen/SelectionDAG/FastISel.cpp
llvm/branches/Apple/Dib/lib/Target/X86/X86FastISel.cpp
llvm/branches/Apple/Dib/test/CodeGen/X86/fast-isel-phys.ll
llvm/branches/Apple/Dib/test/CodeGen/X86/fast-isel-trunc.ll
llvm/branches/Apple/Dib/test/CodeGen/X86/fast-isel.ll
Modified: llvm/branches/Apple/Dib/include/llvm/CodeGen/FastISel.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Dib/include/llvm/CodeGen/FastISel.h?rev=67044&r1=67043&r2=67044&view=diff
==============================================================================
--- llvm/branches/Apple/Dib/include/llvm/CodeGen/FastISel.h (original)
+++ llvm/branches/Apple/Dib/include/llvm/CodeGen/FastISel.h Mon Mar 16 13:08:53 2009
@@ -269,6 +269,11 @@
unsigned FastEmitInst_extractsubreg(MVT::SimpleValueType RetVT,
unsigned Op0, uint32_t Idx);
+ /// FastEmitZExtFromI1 - Emit MachineInstrs to compute the value of Op
+ /// with all but the least significant bit set to zero.
+ unsigned FastEmitZExtFromI1(MVT::SimpleValueType VT,
+ unsigned Op);
+
/// FastEmitBranch - Emit an unconditional branch to the given block,
/// unless it is the immediate (fall-through) successor, and update
/// the CFG.
Modified: llvm/branches/Apple/Dib/lib/CodeGen/SelectionDAG/FastISel.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Dib/lib/CodeGen/SelectionDAG/FastISel.cpp?rev=67044&r1=67043&r2=67044&view=diff
==============================================================================
--- llvm/branches/Apple/Dib/lib/CodeGen/SelectionDAG/FastISel.cpp (original)
+++ llvm/branches/Apple/Dib/lib/CodeGen/SelectionDAG/FastISel.cpp Mon Mar 16 13:08:53 2009
@@ -477,27 +477,42 @@
MVT DstVT = TLI.getValueType(I->getType());
if (SrcVT == MVT::Other || !SrcVT.isSimple() ||
- DstVT == MVT::Other || !DstVT.isSimple() ||
- !TLI.isTypeLegal(DstVT))
+ DstVT == MVT::Other || !DstVT.isSimple())
// Unhandled type. Halt "fast" selection and bail.
return false;
+ // Check if the destination type is legal. Or as a special case,
+ // it may be i1 if we're doing a truncate because that's
+ // easy and somewhat common.
+ if (!TLI.isTypeLegal(DstVT))
+ if (DstVT != MVT::i1 || Opcode != ISD::TRUNCATE)
+ // Unhandled type. Halt "fast" selection and bail.
+ return false;
+
// Check if the source operand is legal. Or as a special case,
// it may be i1 if we're doing zero-extension because that's
- // trivially easy and somewhat common.
- if (!TLI.isTypeLegal(SrcVT)) {
- if (SrcVT == MVT::i1 && Opcode == ISD::ZERO_EXTEND)
- SrcVT = TLI.getTypeToTransformTo(SrcVT);
- else
+ // easy and somewhat common.
+ if (!TLI.isTypeLegal(SrcVT))
+ if (SrcVT != MVT::i1 || Opcode != ISD::ZERO_EXTEND)
// Unhandled type. Halt "fast" selection and bail.
return false;
- }
-
+
unsigned InputReg = getRegForValue(I->getOperand(0));
if (!InputReg)
// Unhandled operand. Halt "fast" selection and bail.
return false;
-
+
+ // If the operand is i1, arrange for the high bits in the register to be zero.
+ if (SrcVT == MVT::i1) {
+ SrcVT = TLI.getTypeToTransformTo(SrcVT);
+ InputReg = FastEmitZExtFromI1(SrcVT.getSimpleVT(), InputReg);
+ if (!InputReg)
+ return false;
+ }
+ // If the result is i1, truncate to the target's type for i1 first.
+ if (DstVT == MVT::i1)
+ DstVT = TLI.getTypeToTransformTo(DstVT);
+
unsigned ResultReg = FastEmit_r(SrcVT.getSimpleVT(),
DstVT.getSimpleVT(),
Opcode,
@@ -970,3 +985,9 @@
}
return ResultReg;
}
+
+/// FastEmitZExtFromI1 - Emit MachineInstrs to compute the value of Op
+/// with all but the least significant bit set to zero.
+unsigned FastISel::FastEmitZExtFromI1(MVT::SimpleValueType VT, unsigned Op) {
+ return FastEmit_ri(VT, VT, ISD::AND, Op, 1);
+}
Modified: llvm/branches/Apple/Dib/lib/Target/X86/X86FastISel.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Dib/lib/Target/X86/X86FastISel.cpp?rev=67044&r1=67043&r2=67044&view=diff
==============================================================================
--- llvm/branches/Apple/Dib/lib/Target/X86/X86FastISel.cpp (original)
+++ llvm/branches/Apple/Dib/lib/Target/X86/X86FastISel.cpp Mon Mar 16 13:08:53 2009
@@ -662,12 +662,14 @@
}
bool X86FastISel::X86SelectZExt(Instruction *I) {
- // Special-case hack: The only i1 values we know how to produce currently
- // set the upper bits of an i8 value to zero.
+ // Handle zero-extension from i1 to i8, which is common.
if (I->getType() == Type::Int8Ty &&
I->getOperand(0)->getType() == Type::Int1Ty) {
unsigned ResultReg = getRegForValue(I->getOperand(0));
if (ResultReg == 0) return false;
+ // Set the high bits to zero.
+ ResultReg = FastEmitZExtFromI1(MVT::i8, ResultReg);
+ if (ResultReg == 0) return false;
UpdateValueMap(I, ResultReg);
return true;
}
@@ -1402,6 +1404,19 @@
return X86SelectFPTrunc(I);
case Instruction::ExtractValue:
return X86SelectExtractValue(I);
+ case Instruction::IntToPtr: // Deliberate fall-through.
+ case Instruction::PtrToInt: {
+ MVT SrcVT = TLI.getValueType(I->getOperand(0)->getType());
+ MVT DstVT = TLI.getValueType(I->getType());
+ if (DstVT.bitsGT(SrcVT))
+ return X86SelectZExt(I);
+ if (DstVT.bitsLT(SrcVT))
+ return X86SelectTrunc(I);
+ unsigned Reg = getRegForValue(I->getOperand(0));
+ if (Reg == 0) return false;
+ UpdateValueMap(I, Reg);
+ return true;
+ }
}
return false;
Added: llvm/branches/Apple/Dib/test/CodeGen/X86/fast-isel-i1.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Dib/test/CodeGen/X86/fast-isel-i1.ll?rev=67044&view=auto
==============================================================================
--- llvm/branches/Apple/Dib/test/CodeGen/X86/fast-isel-i1.ll (added)
+++ llvm/branches/Apple/Dib/test/CodeGen/X86/fast-isel-i1.ll Mon Mar 16 13:08:53 2009
@@ -0,0 +1,19 @@
+; RUN: llvm-as < %s | llc -march=x86 -fast-isel | grep {andb \$1, %}
+
+declare i64 @bar(i64)
+
+define i32 @foo(i64 %x) nounwind {
+ %y = add i64 %x, -3 ; [#uses=1]
+ %t = call i64 @bar(i64 %y) ; [#uses=1]
+ %s = mul i64 %t, 77 ; [#uses=1]
+ %z = trunc i64 %s to i1 ; [#uses=1]
+ br label %next
+
+next: ; preds = %0
+ %u = zext i1 %z to i32 ; [#uses=1]
+ %v = add i32 %u, 1999 ; [#uses=1]
+ br label %exit
+
+exit: ; preds = %next
+ ret i32 %v
+}
Modified: llvm/branches/Apple/Dib/test/CodeGen/X86/fast-isel-phys.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Dib/test/CodeGen/X86/fast-isel-phys.ll?rev=67044&r1=67043&r2=67044&view=diff
==============================================================================
--- llvm/branches/Apple/Dib/test/CodeGen/X86/fast-isel-phys.ll (original)
+++ llvm/branches/Apple/Dib/test/CodeGen/X86/fast-isel-phys.ll Mon Mar 16 13:08:53 2009
@@ -1,4 +1,4 @@
-; RUN: llvm-as < %s | llc -fast-isel -march=x86
+; RUN: llvm-as < %s | llc -fast-isel -fast-isel-abort -march=x86
define i8 @t2(i8 %a, i8 %c) nounwind {
%tmp = shl i8 %a, %c
Modified: llvm/branches/Apple/Dib/test/CodeGen/X86/fast-isel-trunc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Dib/test/CodeGen/X86/fast-isel-trunc.ll?rev=67044&r1=67043&r2=67044&view=diff
==============================================================================
--- llvm/branches/Apple/Dib/test/CodeGen/X86/fast-isel-trunc.ll (original)
+++ llvm/branches/Apple/Dib/test/CodeGen/X86/fast-isel-trunc.ll Mon Mar 16 13:08:53 2009
@@ -1,5 +1,5 @@
-; RUN: llvm-as < %s | llc -march=x86 -fast-isel
-; RUN: llvm-as < %s | llc -march=x86-64 -fast-isel
+; RUN: llvm-as < %s | llc -march=x86 -fast-isel -fast-isel-abort
+; RUN: llvm-as < %s | llc -march=x86-64 -fast-isel -fast-isel-abort
define i8 @t1(i32 %x) signext nounwind {
%tmp1 = trunc i32 %x to i8
Modified: llvm/branches/Apple/Dib/test/CodeGen/X86/fast-isel.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Dib/test/CodeGen/X86/fast-isel.ll?rev=67044&r1=67043&r2=67044&view=diff
==============================================================================
--- llvm/branches/Apple/Dib/test/CodeGen/X86/fast-isel.ll (original)
+++ llvm/branches/Apple/Dib/test/CodeGen/X86/fast-isel.ll Mon Mar 16 13:08:53 2009
@@ -1,4 +1,4 @@
-; RUN: llvm-as < %s | llc -fast-isel -march=x86 -mattr=sse2
+; RUN: llvm-as < %s | llc -fast-isel -fast-isel-abort -march=x86 -mattr=sse2
; This tests very minimal fast-isel functionality.
@@ -47,3 +47,12 @@
%tmp2 = bitcast i32 0 to i32
ret i32 %tmp2
}
+
+define i1 @ptrtoint(i8* %p) nounwind {
+ %t = ptrtoint i8* %p to i1
+ ret i1 %t
+}
+define i8* @inttoptr(i1 %p) nounwind {
+ %t = inttoptr i1 %p to i8*
+ ret i8* %t
+}
From sabre at nondot.org Mon Mar 16 13:28:28 2009
From: sabre at nondot.org (Chris Lattner)
Date: Mon, 16 Mar 2009 18:28:28 -0000
Subject: [llvm-commits] [llvm] r67046 -
/llvm/trunk/test/Analysis/BasicAA/2009-03-04-GEPNoalias.ll
Message-ID: <200903161828.n2GISSTi018952@zion.cs.uiuc.edu>
Author: lattner
Date: Mon Mar 16 13:28:27 2009
New Revision: 67046
URL: http://llvm.org/viewvc/llvm-project?rev=67046&view=rev
Log:
change this to test for an alias result more directly.
Modified:
llvm/trunk/test/Analysis/BasicAA/2009-03-04-GEPNoalias.ll
Modified: llvm/trunk/test/Analysis/BasicAA/2009-03-04-GEPNoalias.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/BasicAA/2009-03-04-GEPNoalias.ll?rev=67046&r1=67045&r2=67046&view=diff
==============================================================================
--- llvm/trunk/test/Analysis/BasicAA/2009-03-04-GEPNoalias.ll (original)
+++ llvm/trunk/test/Analysis/BasicAA/2009-03-04-GEPNoalias.ll Mon Mar 16 13:28:27 2009
@@ -1,9 +1,13 @@
-; RUN: llvm-as < %s | opt -aa-eval -basicaa |& grep {0 no alias}
+; RUN: llvm-as < %s | opt -basicaa -gvn | llvm-dis | grep load
declare noalias i32* @noalias()
-define void @test(i32 %x) {
+define i32 @test(i32 %x) {
%a = call i32* @noalias()
+ store i32 1, i32* %a
%b = getelementptr i32* %a, i32 %x
- ret void
+ store i32 2, i32* %b
+
+ %c = load i32* %a
+ ret i32 %c
}
From scottm at aero.org Mon Mar 16 13:47:25 2009
From: scottm at aero.org (Scott Michel)
Date: Mon, 16 Mar 2009 18:47:25 -0000
Subject: [llvm-commits] [llvm] r67048 - in /llvm/trunk:
lib/Target/CellSPU/SPUISelLowering.cpp lib/Target/CellSPU/SPUInstrInfo.cpp
lib/Target/CellSPU/SPUInstrInfo.td test/CodeGen/CellSPU/trunc.ll
Message-ID: <200903161847.n2GIlPBU019873@zion.cs.uiuc.edu>
Author: pingbak
Date: Mon Mar 16 13:47:25 2009
New Revision: 67048
URL: http://llvm.org/viewvc/llvm-project?rev=67048&view=rev
Log:
CellSPU:
Incorporate Tilmann's 128-bit operation patch. Evidently, it gets the
llvm-gcc bootstrap a bit further along.
Modified:
llvm/trunk/lib/Target/CellSPU/SPUISelLowering.cpp
llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.cpp
llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.td
llvm/trunk/test/CodeGen/CellSPU/trunc.ll
Modified: llvm/trunk/lib/Target/CellSPU/SPUISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/CellSPU/SPUISelLowering.cpp?rev=67048&r1=67047&r2=67048&view=diff
==============================================================================
--- llvm/trunk/lib/Target/CellSPU/SPUISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/CellSPU/SPUISelLowering.cpp Mon Mar 16 13:47:25 2009
@@ -779,7 +779,7 @@
result = DAG.getNode(SPUISD::SHUFB, dl, vecVT,
vectorizeOp, alignLoadVec,
- DAG.getNode(ISD::BIT_CONVERT, dl,
+ DAG.getNode(ISD::BIT_CONVERT, dl,
MVT::v4i32, insertEltOp));
result = DAG.getStore(the_chain, dl, result, basePtr,
@@ -1035,7 +1035,7 @@
ArgOffset += StackSlotSize;
}
if (!MemOps.empty())
- Root = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
+ Root = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
&MemOps[0], MemOps.size());
}
@@ -1156,7 +1156,7 @@
// and flag operands which copy the outgoing args into the appropriate regs.
SDValue InFlag;
for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
- Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
+ Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
RegsToPass[i].second, InFlag);
InFlag = Chain.getValue(1);
}
@@ -1239,7 +1239,7 @@
case MVT::Other: break;
case MVT::i32:
if (TheCall->getValueType(1) == MVT::i32) {
- Chain = DAG.getCopyFromReg(Chain, dl, SPU::R4,
+ Chain = DAG.getCopyFromReg(Chain, dl, SPU::R4,
MVT::i32, InFlag).getValue(1);
ResultVals[0] = Chain.getValue(0);
Chain = DAG.getCopyFromReg(Chain, dl, SPU::R3, MVT::i32,
@@ -1247,20 +1247,20 @@
ResultVals[1] = Chain.getValue(0);
NumResults = 2;
} else {
- Chain = DAG.getCopyFromReg(Chain, dl, SPU::R3, MVT::i32,
+ Chain = DAG.getCopyFromReg(Chain, dl, SPU::R3, MVT::i32,
InFlag).getValue(1);
ResultVals[0] = Chain.getValue(0);
NumResults = 1;
}
break;
case MVT::i64:
- Chain = DAG.getCopyFromReg(Chain, dl, SPU::R3, MVT::i64,
+ Chain = DAG.getCopyFromReg(Chain, dl, SPU::R3, MVT::i64,
InFlag).getValue(1);
ResultVals[0] = Chain.getValue(0);
NumResults = 1;
break;
case MVT::i128:
- Chain = DAG.getCopyFromReg(Chain, dl, SPU::R3, MVT::i128,
+ Chain = DAG.getCopyFromReg(Chain, dl, SPU::R3, MVT::i128,
InFlag).getValue(1);
ResultVals[0] = Chain.getValue(0);
NumResults = 1;
@@ -1860,7 +1860,7 @@
DAG.getTargetConstant(V2Elt, MVT::i32),
DAG.getCopyFromReg(InitTempReg, dl, VReg, PtrVT));
// Use shuffle mask in SHUFB synthetic instruction:
- return DAG.getNode(SPUISD::SHUFB, dl, V1.getValueType(), V2, V1,
+ return DAG.getNode(SPUISD::SHUFB, dl, V1.getValueType(), V2, V1,
ShufMaskOp);
} else if (rotate) {
int rotamt = (MaxElts - V0Elt) * EltVT.getSizeInBits()/8;
@@ -2401,7 +2401,7 @@
SDValue Comp1 =
DAG.getNode(ISD::SRL, dl, MVT::i32,
- DAG.getCopyFromReg(CNTB_rescopy, dl, CNTB_reg, MVT::i32),
+ DAG.getCopyFromReg(CNTB_rescopy, dl, CNTB_reg, MVT::i32),
Shift1);
SDValue Sum1 =
@@ -2588,7 +2588,7 @@
}
SDValue result =
- DAG.getSetCC(dl, ccResultVT, lhsSelect, rhsSelect,
+ DAG.getSetCC(dl, ccResultVT, lhsSelect, rhsSelect,
(ISD::CondCode) compareOp);
if ((CC->get() & 0x8) == 0) {
@@ -2649,14 +2649,15 @@
//! Custom lower ISD::TRUNCATE
static SDValue LowerTRUNCATE(SDValue Op, SelectionDAG &DAG)
{
+ // Type to truncate to
MVT VT = Op.getValueType();
MVT::SimpleValueType simpleVT = VT.getSimpleVT();
MVT VecVT = MVT::getVectorVT(VT, (128 / VT.getSizeInBits()));
DebugLoc dl = Op.getDebugLoc();
+ // Type to truncate from
SDValue Op0 = Op.getOperand(0);
MVT Op0VT = Op0.getValueType();
- MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
if (Op0VT.getSimpleVT() == MVT::i128 && simpleVT == MVT::i64) {
// Create shuffle mask, least significant doubleword of quadword
@@ -2669,15 +2670,10 @@
DAG.getConstant(maskHigh, MVT::i32),
DAG.getConstant(maskLow, MVT::i32));
+ SDValue truncShuffle = DAG.getNode(SPUISD::SHUFB, dl, VecVT,
+ Op0, Op0, shufMask);
- SDValue PromoteScalar = DAG.getNode(SPUISD::PREFSLOT2VEC, dl,
- Op0VecVT, Op0);
-
- SDValue truncShuffle = DAG.getNode(SPUISD::SHUFB, dl, Op0VecVT,
- PromoteScalar, PromoteScalar, shufMask);
-
- return DAG.getNode(SPUISD::VEC2PREFSLOT, dl, VT,
- DAG.getNode(ISD::BIT_CONVERT, dl, VecVT, truncShuffle));
+ return DAG.getNode(SPUISD::VEC2PREFSLOT, dl, VT, truncShuffle);
}
return SDValue(); // Leave the truncate unmolested
Modified: llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.cpp?rev=67048&r1=67047&r2=67048&view=diff
==============================================================================
--- llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.cpp Mon Mar 16 13:47:25 2009
@@ -133,18 +133,22 @@
case SPU::ORi128_f32:
case SPU::ORi128_r16:
case SPU::ORi128_r8:
+*/
case SPU::ORi128_vec:
+/*
case SPU::ORr64_i128:
case SPU::ORf64_i128:
case SPU::ORr32_i128:
case SPU::ORf32_i128:
case SPU::ORr16_i128:
case SPU::ORr8_i128:
- case SPU::ORvec_i128:
*/
+ case SPU::ORvec_i128:
/*
case SPU::ORr16_r32:
case SPU::ORr8_r32:
+ case SPU::ORf32_r32:
+ case SPU::ORr32_f32:
case SPU::ORr32_r16:
case SPU::ORr32_r8:
case SPU::ORr16_r64:
@@ -177,6 +181,7 @@
case SPU::ORr16:
case SPU::ORr32:
case SPU::ORr64:
+ case SPU::ORr128:
case SPU::ORf32:
case SPU::ORf64:
assert(MI.getNumOperands() == 3 &&
Modified: llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.td?rev=67048&r1=67047&r2=67048&view=diff
==============================================================================
--- llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.td (original)
+++ llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.td Mon Mar 16 13:47:25 2009
@@ -1429,9 +1429,6 @@
/* class ORCvtRegGPRC:
ORCvtForm<(outs GPRC:$rT), (ins rclass:$rA)>; */
-/* class ORCvtVecGPRC:
- ORCvtForm<(outs GPRC:$rT), (ins VECREG:$rA)>; */
-
/* class ORCvtGPRCReg:
ORCvtForm<(outs rclass:$rT), (ins GPRC:$rA)>; */
@@ -1447,8 +1444,11 @@
class ORCvtFormRegR64 pattern = [ ]>:
ORCvtForm<(outs R64C:$rT), (ins rclass:$rA), pattern>;
-/* class ORCvtGPRCVec:
- ORCvtForm<(outs VECREG:$rT), (ins GPRC:$rA)>; */
+class ORCvtGPRCVec:
+ ORCvtForm<(outs VECREG:$rT), (ins GPRC:$rA)>;
+
+class ORCvtVecGPRC:
+ ORCvtForm<(outs GPRC:$rT), (ins VECREG:$rA)>;
multiclass BitwiseOr
{
@@ -1496,8 +1496,14 @@
def f32_v4f32: ORExtractElt;
def f64_v2f64: ORExtractElt;
+ // Conversion from vector to GPRC
+ def i128_vec: ORCvtVecGPRC;
+
+ // Conversion from GPRC to vector
+ def vec_i128: ORCvtGPRCVec;
+
/*
- // Conversion from GPRC to register
+ // Conversion from register to GPRC
def i128_r64: ORCvtRegGPRC;
def i128_f64: ORCvtRegGPRC;
def i128_r32: ORCvtRegGPRC;
@@ -1505,36 +1511,30 @@
def i128_r16: ORCvtRegGPRC;
def i128_r8: ORCvtRegGPRC;
- // Conversion from GPRC to vector
- def i128_vec: ORCvtVecGPRC;
-
- // Conversion from register to GPRC
+ // Conversion from GPRC to register
def r64_i128: ORCvtGPRCReg;
def f64_i128: ORCvtGPRCReg;
def r32_i128: ORCvtGPRCReg;
def f32_i128: ORCvtGPRCReg;
def r16_i128: ORCvtGPRCReg;
def r8_i128: ORCvtGPRCReg;
-
- // Conversion from vector to GPRC
- def vec_i128: ORCvtGPRCVec;
*/
/*
// Conversion from register to R32C:
- def r16_r32: ORCvtFormRegR32;
- def r8_r32: ORCvtFormRegR32;
+ def r32_r16: ORCvtFormRegR32;
+ def r32_r8: ORCvtFormRegR32;
// Conversion from R32C to register
def r32_r16: ORCvtFormR32Reg;
def r32_r8: ORCvtFormR32Reg;
*/
- // Conversion to register from R64C:
+ // Conversion from R64C to register:
def r32_r64: ORCvtFormR64Reg;
// def r16_r64: ORCvtFormR64Reg;
// def r8_r64: ORCvtFormR64Reg;
- // Conversion to R64C from register
+ // Conversion to R64C from register:
def r64_r32: ORCvtFormRegR64;
// def r64_r16: ORCvtFormRegR64;
// def r64_r8: ORCvtFormRegR64;
@@ -1659,6 +1659,7 @@
def v4i32: ORCVecInst;
def v2i64: ORCVecInst;
+ def r128: ORCRegInst;
def r64: ORCRegInst;
def r32: ORCRegInst;
def r16: ORCRegInst;
@@ -1840,72 +1841,64 @@
[(set R32C:$rT, (xor R32C:$rA, i32ImmSExt10:$val))]>;
// NAND:
-def NANDv16i8:
- RRForm<0b10010010000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
- "nand\t$rT, $rA, $rB", IntegerOp,
- [(set (v16i8 VECREG:$rT), (vnot (and (v16i8 VECREG:$rA),
- (v16i8 VECREG:$rB))))]>;
-def NANDv8i16:
- RRForm<0b10010010000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
- "nand\t$rT, $rA, $rB", IntegerOp,
- [(set (v8i16 VECREG:$rT), (vnot (and (v8i16 VECREG:$rA),
- (v8i16 VECREG:$rB))))]>;
+class NANDInst pattern>:
+ RRForm<0b10010011000, OOL, IOL, "nand\t$rT, $rA, $rB",
+ IntegerOp, pattern>;
-def NANDv4i32:
- RRForm<0b10010010000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
- "nand\t$rT, $rA, $rB", IntegerOp,
- [(set (v4i32 VECREG:$rT), (vnot (and (v4i32 VECREG:$rA),
- (v4i32 VECREG:$rB))))]>;
-
-def NANDr32:
- RRForm<0b10010010000, (outs R32C:$rT), (ins R32C:$rA, R32C:$rB),
- "nand\t$rT, $rA, $rB", IntegerOp,
- [(set R32C:$rT, (not (and R32C:$rA, R32C:$rB)))]>;
-
-def NANDr16:
- RRForm<0b10010010000, (outs R16C:$rT), (ins R16C:$rA, R16C:$rB),
- "nand\t$rT, $rA, $rB", IntegerOp,
- [(set R16C:$rT, (not (and R16C:$rA, R16C:$rB)))]>;
-
-def NANDr8:
- RRForm<0b10010010000, (outs R8C:$rT), (ins R8C:$rA, R8C:$rB),
- "nand\t$rT, $rA, $rB", IntegerOp,
- [(set R8C:$rT, (not (and R8C:$rA, R8C:$rB)))]>;
+class NANDVecInst:
+ NANDInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ [(set (vectype VECREG:$rT), (vnot (and (vectype VECREG:$rA),
+ (vectype VECREG:$rB))))]>;
+class NANDRegInst:
+ NANDInst<(outs rclass:$rT), (ins rclass:$rA, rclass:$rB),
+ [(set rclass:$rT, (not (and rclass:$rA, rclass:$rB)))]>;
+
+multiclass BitwiseNand
+{
+ def v16i8: NANDVecInst;
+ def v8i16: NANDVecInst;
+ def v4i32: NANDVecInst;
+ def v2i64: NANDVecInst;
+
+ def r128: NANDRegInst;
+ def r64: NANDRegInst;
+ def r32: NANDRegInst;
+ def r16: NANDRegInst;
+ def r8: NANDRegInst;
+}
+
+defm NAND : BitwiseNand;
// NOR:
-def NORv16i8:
- RRForm<0b10010010000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
- "nor\t$rT, $rA, $rB", IntegerOp,
- [(set (v16i8 VECREG:$rT), (vnot (or (v16i8 VECREG:$rA),
- (v16i8 VECREG:$rB))))]>;
-def NORv8i16:
- RRForm<0b10010010000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
- "nor\t$rT, $rA, $rB", IntegerOp,
- [(set (v8i16 VECREG:$rT), (vnot (or (v8i16 VECREG:$rA),
- (v8i16 VECREG:$rB))))]>;
+class NORInst pattern>:
+ RRForm<0b10010010000, OOL, IOL, "nor\t$rT, $rA, $rB",
+ IntegerOp, pattern>;
-def NORv4i32:
- RRForm<0b10010010000, (outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
- "nor\t$rT, $rA, $rB", IntegerOp,
- [(set (v4i32 VECREG:$rT), (vnot (or (v4i32 VECREG:$rA),
- (v4i32 VECREG:$rB))))]>;
-
-def NORr32:
- RRForm<0b10010010000, (outs R32C:$rT), (ins R32C:$rA, R32C:$rB),
- "nor\t$rT, $rA, $rB", IntegerOp,
- [(set R32C:$rT, (not (or R32C:$rA, R32C:$rB)))]>;
-
-def NORr16:
- RRForm<0b10010010000, (outs R16C:$rT), (ins R16C:$rA, R16C:$rB),
- "nor\t$rT, $rA, $rB", IntegerOp,
- [(set R16C:$rT, (not (or R16C:$rA, R16C:$rB)))]>;
-
-def NORr8:
- RRForm<0b10010010000, (outs R8C:$rT), (ins R8C:$rA, R8C:$rB),
- "nor\t$rT, $rA, $rB", IntegerOp,
- [(set R8C:$rT, (not (or R8C:$rA, R8C:$rB)))]>;
+class NORVecInst:
+ NORInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ [(set (vectype VECREG:$rT), (vnot (or (vectype VECREG:$rA),
+ (vectype VECREG:$rB))))]>;
+class NORRegInst:
+ NORInst<(outs rclass:$rT), (ins rclass:$rA, rclass:$rB),
+ [(set rclass:$rT, (not (or rclass:$rA, rclass:$rB)))]>;
+
+multiclass BitwiseNor
+{
+ def v16i8: NORVecInst;
+ def v8i16: NORVecInst;
+ def v4i32: NORVecInst;
+ def v2i64: NORVecInst;
+
+ def r128: NORRegInst;
+ def r64: NORRegInst;
+ def r32: NORRegInst;
+ def r16: NORRegInst;
+ def r8: NORRegInst;
+}
+
+defm NOR : BitwiseNor;
// Select bits:
class SELBInst pattern>:
@@ -4361,8 +4354,7 @@
//===----------------------------------------------------------------------===//
// Bit conversions (type conversions between vector/packed types)
-// NOTE: Promotions are handled using the XS* instructions. Truncation
-// is not handled.
+// NOTE: Promotions are handled using the XS* instructions.
//===----------------------------------------------------------------------===//
def : Pat<(v16i8 (bitconvert (v8i16 VECREG:$src))), (v16i8 VECREG:$src)>;
def : Pat<(v16i8 (bitconvert (v4i32 VECREG:$src))), (v16i8 VECREG:$src)>;
@@ -4400,8 +4392,31 @@
def : Pat<(v2f64 (bitconvert (v2i64 VECREG:$src))), (v2f64 VECREG:$src)>;
def : Pat<(v2f64 (bitconvert (v2f64 VECREG:$src))), (v2f64 VECREG:$src)>;
-def : Pat<(f32 (bitconvert (i32 R32C:$src))), (f32 R32FP:$src)>;
-def : Pat<(f64 (bitconvert (i64 R64C:$src))), (f64 R64FP:$src)>;
+def : Pat<(i128 (bitconvert (v16i8 VECREG:$src))),
+ (ORi128_vec VECREG:$src)>;
+def : Pat<(i128 (bitconvert (v8i16 VECREG:$src))),
+ (ORi128_vec VECREG:$src)>;
+def : Pat<(i128 (bitconvert (v4i32 VECREG:$src))),
+ (ORi128_vec VECREG:$src)>;
+def : Pat<(i128 (bitconvert (v2i64 VECREG:$src))),
+ (ORi128_vec VECREG:$src)>;
+def : Pat<(i128 (bitconvert (v4f32 VECREG:$src))),
+ (ORi128_vec VECREG:$src)>;
+def : Pat<(i128 (bitconvert (v2f64 VECREG:$src))),
+ (ORi128_vec VECREG:$src)>;
+
+def : Pat<(v16i8 (bitconvert (i128 GPRC:$src))),
+ (v16i8 (ORvec_i128 GPRC:$src))>;
+def : Pat<(v8i16 (bitconvert (i128 GPRC:$src))),
+ (v8i16 (ORvec_i128 GPRC:$src))>;
+def : Pat<(v4i32 (bitconvert (i128 GPRC:$src))),
+ (v4i32 (ORvec_i128 GPRC:$src))>;
+def : Pat<(v2i64 (bitconvert (i128 GPRC:$src))),
+ (v2i64 (ORvec_i128 GPRC:$src))>;
+def : Pat<(v4f32 (bitconvert (i128 GPRC:$src))),
+ (v4f32 (ORvec_i128 GPRC:$src))>;
+def : Pat<(v2f64 (bitconvert (i128 GPRC:$src))),
+ (v2f64 (ORvec_i128 GPRC:$src))>;
//===----------------------------------------------------------------------===//
// Instruction patterns:
@@ -4598,7 +4613,7 @@
def : Pat<(add (SPUhi tconstpool:$in, 0), (SPUlo tconstpool:$in, 0)),
(IOHLlo (ILHUhi tconstpool:$in), tconstpool:$in)>;
-// Instrinsics:
+// Intrinsics:
include "CellSDKIntrinsics.td"
// Various math operator instruction sequences
include "SPUMathInstr.td"
Modified: llvm/trunk/test/CodeGen/CellSPU/trunc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/CellSPU/trunc.ll?rev=67048&r1=67047&r2=67048&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/CellSPU/trunc.ll (original)
+++ llvm/trunk/test/CodeGen/CellSPU/trunc.ll Mon Mar 16 13:47:25 2009
@@ -1,76 +1,94 @@
; RUN: llvm-as -o - %s | llc -march=cellspu > %t1.s
-; RUN: grep shufb %t1.s | count 10
+; RUN: grep shufb %t1.s | count 19
; RUN: grep {ilhu.*1799} %t1.s | count 1
-; RUN: grep {ilhu.*771} %t1.s | count 1
+; RUN: grep {ilhu.*771} %t1.s | count 2
; RUN: grep {ilhu.*1543} %t1.s | count 1
; RUN: grep {ilhu.*1029} %t1.s | count 1
-; RUN: grep {ilhu.*515} %t1.s | count 2
-; RUN: grep xsbh %t1.s | count 2
-; RUN: grep sfh %t1.s | count 1
+; RUN: grep {ilhu.*515} %t1.s | count 1
+; RUN: grep {ilhu.*3855} %t1.s | count 1
+; RUN: grep {ilhu.*3599} %t1.s | count 1
+; RUN: grep {ilhu.*3085} %t1.s | count 1
+; RUN: grep {iohl.*3855} %t1.s | count 1
+; RUN: grep {iohl.*3599} %t1.s | count 2
+; RUN: grep {iohl.*1543} %t1.s | count 2
+; RUN: grep {iohl.*771} %t1.s | count 2
+; RUN: grep {iohl.*515} %t1.s | count 1
+; RUN: grep {iohl.*1799} %t1.s | count 1
+; RUN: grep lqa %t1.s | count 1
+; RUN: grep cbd %t1.s | count 4
+; RUN: grep chd %t1.s | count 3
+; RUN: grep cwd %t1.s | count 1
+; RUN: grep cdd %t1.s | count 1
; ModuleID = 'trunc.bc'
target datalayout = "E-p:32:32:128-i1:8:128-i8:8:128-i16:16:128-i32:32:128-i64:32:128-f32:32:128-f64:64:128-v64:64:64-v128:128:128-a0:0:128-s0:128:128"
target triple = "spu"
-; codegen for i128 arguments is not implemented yet on CellSPU
-; once this changes uncomment the functions below
-; and update the expected results accordingly
-
-;define i8 @trunc_i128_i8(i128 %u) nounwind readnone {
-;entry:
-; %0 = trunc i128 %u to i8
-; ret i8 %0
-;}
-;define i16 @trunc_i128_i16(i128 %u) nounwind readnone {
-;entry:
-; %0 = trunc i128 %u to i16
-; ret i16 %0
-;}
-;define i32 @trunc_i128_i32(i128 %u) nounwind readnone {
-;entry:
-; %0 = trunc i128 %u to i32
-; ret i32 %0
-;}
-;define i64 @trunc_i128_i64(i128 %u) nounwind readnone {
-;entry:
-; %0 = trunc i128 %u to i64
-; ret i64 %0
-;}
-
-define <16 x i8> @trunc_i64_i8(i64 %u, <16 x i8> %v) nounwind readnone {
-entry:
- %0 = trunc i64 %u to i8
- %tmp1 = insertelement <16 x i8> %v, i8 %0, i32 10
- ret <16 x i8> %tmp1
-}
-define <8 x i16> @trunc_i64_i16(i64 %u, <8 x i16> %v) nounwind readnone {
-entry:
- %0 = trunc i64 %u to i16
- %tmp1 = insertelement <8 x i16> %v, i16 %0, i32 6
- ret <8 x i16> %tmp1
-}
-define i32 @trunc_i64_i32(i64 %u, i32 %v) nounwind readnone {
-entry:
- %0 = trunc i64 %u to i32
- ret i32 %0
-}
-
-define i8 @trunc_i32_i8(i32 %u, i8 %v) nounwind readnone {
-entry:
- %0 = trunc i32 %u to i8
- %1 = sub i8 %0, %v
- ret i8 %1
-}
-define <8 x i16> @trunc_i32_i16(i32 %u, <8 x i16> %v) nounwind readnone {
-entry:
- %0 = trunc i32 %u to i16
- %tmp1 = insertelement <8 x i16> %v, i16 %0, i32 3
- ret <8 x i16> %tmp1
-}
-
-define <16 x i8> @trunc_i16_i8(i16 %u, <16 x i8> %v) nounwind readnone {
-entry:
- %0 = trunc i16 %u to i8
- %tmp1 = insertelement <16 x i8> %v, i8 %0, i32 5
- ret <16 x i8> %tmp1
+define <16 x i8> @trunc_i128_i8(i128 %u, <16 x i8> %v) {
+entry:
+ %0 = trunc i128 %u to i8
+ %tmp1 = insertelement <16 x i8> %v, i8 %0, i32 15
+ ret <16 x i8> %tmp1
+}
+
+define <8 x i16> @trunc_i128_i16(i128 %u, <8 x i16> %v) {
+entry:
+ %0 = trunc i128 %u to i16
+ %tmp1 = insertelement <8 x i16> %v, i16 %0, i32 8
+ ret <8 x i16> %tmp1
+}
+
+define <4 x i32> @trunc_i128_i32(i128 %u, <4 x i32> %v) {
+entry:
+ %0 = trunc i128 %u to i32
+ %tmp1 = insertelement <4 x i32> %v, i32 %0, i32 2
+ ret <4 x i32> %tmp1
+}
+
+define <2 x i64> @trunc_i128_i64(i128 %u, <2 x i64> %v) {
+entry:
+ %0 = trunc i128 %u to i64
+ %tmp1 = insertelement <2 x i64> %v, i64 %0, i32 1
+ ret <2 x i64> %tmp1
+}
+
+define <16 x i8> @trunc_i64_i8(i64 %u, <16 x i8> %v) {
+entry:
+ %0 = trunc i64 %u to i8
+ %tmp1 = insertelement <16 x i8> %v, i8 %0, i32 10
+ ret <16 x i8> %tmp1
+}
+
+define <8 x i16> @trunc_i64_i16(i64 %u, <8 x i16> %v) {
+entry:
+ %0 = trunc i64 %u to i16
+ %tmp1 = insertelement <8 x i16> %v, i16 %0, i32 6
+ ret <8 x i16> %tmp1
+}
+
+define i32 @trunc_i64_i32(i64 %u) {
+entry:
+ %0 = trunc i64 %u to i32
+ ret i32 %0
+}
+
+define <16 x i8> @trunc_i32_i8(i32 %u, <16 x i8> %v) {
+entry:
+ %0 = trunc i32 %u to i8
+ %tmp1 = insertelement <16 x i8> %v, i8 %0, i32 7
+ ret <16 x i8> %tmp1
+}
+
+define <8 x i16> @trunc_i32_i16(i32 %u, <8 x i16> %v) {
+entry:
+ %0 = trunc i32 %u to i16
+ %tmp1 = insertelement <8 x i16> %v, i16 %0, i32 3
+ ret <8 x i16> %tmp1
+}
+
+define <16 x i8> @trunc_i16_i8(i16 %u, <16 x i8> %v) {
+entry:
+ %0 = trunc i16 %u to i8
+ %tmp1 = insertelement <16 x i8> %v, i8 %0, i32 5
+ ret <16 x i8> %tmp1
}
From echeng at apple.com Mon Mar 16 13:57:50 2009
From: echeng at apple.com (Evan Cheng)
Date: Mon, 16 Mar 2009 11:57:50 -0700
Subject: [llvm-commits] [llvm] r66976 - in /llvm/trunk:
lib/CodeGen/PHIElimination.cpp
lib/Transforms/Scalar/CodeGenPrepare.cpp
test/CodeGen/X86/2009-03-13-PHIElimBug.ll
test/CodeGen/X86/split-eh-lpad-edges.ll
In-Reply-To: <200903160839.48588.baldrick@free.fr>
References: <200903132259.n2DMxEH4018573@zion.cs.uiuc.edu>
<200903141140.49101.baldrick@free.fr>
<200903160839.48588.baldrick@free.fr>
Message-ID: <71169C44-EE22-4514-BE6B-088598194AE3@apple.com>
On Mar 16, 2009, at 12:39 AM, Duncan Sands wrote:
> Hi Evan,
>
>>> %reg1031 = MOV32rr %EAX
>>> EH_LABEL 2
>>> %reg1025 = MOV32rr %reg1031 <= Invoke result, not an
>>> EH_LABEL
>>> JMP mbb
>>>
>>> So in this case the logic bails out, putting the copy at the end of
>>> the BB,
>>> even though it might still need to be before the invoke.
>>
>> Something seems wrong with this. Who inserted the copy? The copy from
>> EAX to reg1031 is the copy lowered by isel. Is PHI elimination
>> inserting the copy from reg1031 to reg1025? Then it should have done
>> the right thing.
>
> I'm not sure where it's coming from (see testcase below). By the
> way, what
> do you think of the patch I sent? It's more efficient in the common
> case of
> an invoke with one def/use of SrcReg in the basic block, but less
> efficient
> when there is more than one def/use because it has to walk more of
> the basic
> block.
That looks good unless there is some assumptions of placement of
copies introduced by PHI elim (I surely hope not). This needs to go
through lots of testing.
Also, I really want to know where the above mentioned copy copies
from. But I haven't found the time to look at it.
Evan
>
> Ciao,
>
> Duncan.
>
> Run: llc -march=x86 -f phi.bc
>
> If I break on WalkPassEHTryRange, then the first time I hit the
> breakpoint
> I see such a register copy after the EH_LABEL. This is the MBB for
> "cont",
> and it is trying to find a place to put the copy for the phi node in
> the
> landing pad.
>
> declare i32 @f()
>
> declare i32 @g()
>
> define i32 @phi() {
> entry:
> %a = call i32 @f() ; [#uses=1]
> %b = invoke i32 @g()
> to label %cont unwind label %lpad ; [#uses=1]
>
> cont: ; preds = %entry
> %x = phi i32 [ %b, %entry ] ; [#uses=0]
> %aa = call i32 @f() ; [#uses=1]
> %bb = invoke i32 @g()
> to label %cont2 unwind label %lpad ; [#uses=1]
>
> cont2: ; preds = %cont
> %xx = phi i32 [ %bb, %cont ] ; [#uses=1]
> ret i32 %xx
>
> lpad: ; preds = %cont, %entry
> %y = phi i32 [ %a, %entry ], [ %aa, %cont ] ; [#uses=1]
> ret i32 %y
> }
From baldrick at free.fr Mon Mar 16 14:58:39 2009
From: baldrick at free.fr (Duncan Sands)
Date: Mon, 16 Mar 2009 19:58:39 -0000
Subject: [llvm-commits] [llvm] r67049 - in /llvm/trunk:
lib/CodeGen/PHIElimination.cpp test/CodeGen/X86/2009-03-13-PHIElimBug.ll
test/CodeGen/X86/2009-03-16-PHIElimInLPad.ll
Message-ID: <200903161958.n2GJwdD6022601@zion.cs.uiuc.edu>
Author: baldrick
Date: Mon Mar 16 14:58:38 2009
New Revision: 67049
URL: http://llvm.org/viewvc/llvm-project?rev=67049&view=rev
Log:
Tweak the fix for PR3784: be less sensitive about just
how invokes are set up. The fix could be disturbed by
register copies coming after the EH_LABEL, and also didn't
behave quite right when it was the invoke result that
was used in a phi node. Also (see new testcase) fix
another phi elimination bug while there: register copies
in the landing pad need to come after the EH_LABEL, because
that's where execution branches to when unwinding. If they
come before the EH_LABEL then they will never be executed...
Also tweak the original testcase so it doesn't use a no-longer
existing counter.
The accumulated phi elimination changes fix two of seven Ada
testsuite failures that turned up after landing pad critical
edge splitting was turned off. So there's probably more to come.
Added:
llvm/trunk/test/CodeGen/X86/2009-03-16-PHIElimInLPad.ll
Modified:
llvm/trunk/lib/CodeGen/PHIElimination.cpp
llvm/trunk/test/CodeGen/X86/2009-03-13-PHIElimBug.ll
Modified: llvm/trunk/lib/CodeGen/PHIElimination.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/PHIElimination.cpp?rev=67049&r1=67048&r2=67049&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/PHIElimination.cpp (original)
+++ llvm/trunk/lib/CodeGen/PHIElimination.cpp Mon Mar 16 14:58:38 2009
@@ -14,6 +14,8 @@
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "phielim"
+#include "llvm/BasicBlock.h"
+#include "llvm/Instructions.h"
#include "llvm/CodeGen/LiveVariables.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
@@ -31,7 +33,6 @@
using namespace llvm;
STATISTIC(NumAtomic, "Number of atomic phis lowered");
-STATISTIC(NumEH, "Number of EH try blocks skipped");
namespace {
class VISIBILITY_HIDDEN PNE : public MachineFunctionPass {
@@ -66,8 +67,25 @@
///
void analyzePHINodes(const MachineFunction& Fn);
- void WalkPassEHTryRange(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator &I, unsigned SrcReg);
+ // FindCopyInsertPoint - Find a safe place in MBB to insert a copy from
+ // SrcReg. This needs to be after any def or uses of SrcReg, but before
+ // any subsequent point where control flow might jump out of the basic
+ // block.
+ MachineBasicBlock::iterator FindCopyInsertPoint(MachineBasicBlock &MBB,
+ unsigned SrcReg);
+
+ // SkipPHIsAndLabels - Copies need to be inserted after phi nodes and
+ // also after any exception handling labels: in landing pads execution
+ // starts at the label, so any copies placed before it won't be executed!
+ MachineBasicBlock::iterator SkipPHIsAndLabels(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator I) {
+ // Rather than assuming that EH labels come before other kinds of labels,
+ // just skip all labels.
+ while (I != MBB.end() &&
+ (I->getOpcode() == TargetInstrInfo::PHI || I->isLabel()))
+ ++I;
+ return I;
+ }
typedef std::pair BBVRegPair;
typedef std::map VRegPHIUse;
@@ -120,10 +138,7 @@
// Get an iterator to the first instruction after the last PHI node (this may
// also be the end of the basic block).
- MachineBasicBlock::iterator AfterPHIsIt = MBB.begin();
- while (AfterPHIsIt != MBB.end() &&
- AfterPHIsIt->getOpcode() == TargetInstrInfo::PHI)
- ++AfterPHIsIt; // Skip over all of the PHI nodes...
+ MachineBasicBlock::iterator AfterPHIsIt = SkipPHIsAndLabels(MBB, MBB.begin());
while (MBB.front().getOpcode() == TargetInstrInfo::PHI)
LowerAtomicPHINode(MBB, AfterPHIsIt);
@@ -144,37 +159,47 @@
return true;
}
-void PNE::WalkPassEHTryRange(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator &I, unsigned SrcReg) {
- if (I == MBB.begin())
- return;
- MachineBasicBlock::iterator PI = prior(I);
- if (PI->getOpcode() != TargetInstrInfo::EH_LABEL)
- return;
-
- // Trying to walk pass the EH try range. If we run into a use instruction,
- // we want to insert the copy there.
- SmallPtrSet UsesInMBB;
- for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(SrcReg),
- UE = MRI->use_end(); UI != UE; ++UI) {
- MachineInstr *UseMI = &*UI;
- if (UseMI->getParent() == &MBB)
- UsesInMBB.insert(UseMI);
+// FindCopyInsertPoint - Find a safe place in MBB to insert a copy from SrcReg.
+// This needs to be after any def or uses of SrcReg, but before any subsequent
+// point where control flow might jump out of the basic block.
+MachineBasicBlock::iterator PNE::FindCopyInsertPoint(MachineBasicBlock &MBB,
+ unsigned SrcReg) {
+ // Handle the trivial case trivially.
+ if (MBB.empty())
+ return MBB.begin();
+
+ // If this basic block does not contain an invoke, then control flow always
+ // reaches the end of it, so place the copy there. The logic below works in
+ // this case too, but is more expensive.
+ if (!isa(MBB.getBasicBlock()->getTerminator()))
+ return MBB.getFirstTerminator();
+
+ // Discover any definition/uses in this basic block.
+ SmallPtrSet DefUsesInMBB;
+ for (MachineRegisterInfo::reg_iterator RI = MRI->reg_begin(SrcReg),
+ RE = MRI->reg_end(); RI != RE; ++RI) {
+ MachineInstr *DefUseMI = &*RI;
+ if (DefUseMI->getParent() == &MBB)
+ DefUsesInMBB.insert(DefUseMI);
}
- while (PI != MBB.begin()) {
- --PI;
- if (PI->getOpcode() == TargetInstrInfo::EH_LABEL) {
- ++NumEH;
- I = PI;
- return;
- } else if (UsesInMBB.count(&*PI)) {
- ++NumEH;
- I = next(PI);
- return;
- }
+ MachineBasicBlock::iterator InsertPoint;
+ if (DefUsesInMBB.empty()) {
+ // No def/uses. Insert the copy at the start of the basic block.
+ InsertPoint = MBB.begin();
+ } else if (DefUsesInMBB.size() == 1) {
+ // Insert the copy immediately after the definition/use.
+ InsertPoint = *DefUsesInMBB.begin();
+ ++InsertPoint;
+ } else {
+ // Insert the copy immediately after the last definition/use.
+ InsertPoint = MBB.end();
+ while (!DefUsesInMBB.count(&*--InsertPoint)) {}
+ ++InsertPoint;
}
- return;
+
+ // Make sure the copy goes after any phi nodes however.
+ return SkipPHIsAndLabels(MBB, InsertPoint);
}
/// LowerAtomicPHINode - Lower the PHI node at the top of the specified block,
@@ -273,10 +298,7 @@
// Find a safe location to insert the copy, this may be the first terminator
// in the block (or end()).
- MachineBasicBlock::iterator InsertPos = opBlock.getFirstTerminator();
-
- // Walk pass EH try range if needed.
- WalkPassEHTryRange(opBlock, InsertPos, SrcReg);
+ MachineBasicBlock::iterator InsertPos = FindCopyInsertPoint(opBlock, SrcReg);
// Insert the copy.
TII->copyRegToReg(opBlock, InsertPos, IncomingReg, SrcReg, RC, RC);
Modified: llvm/trunk/test/CodeGen/X86/2009-03-13-PHIElimBug.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2009-03-13-PHIElimBug.ll?rev=67049&r1=67048&r2=67049&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/2009-03-13-PHIElimBug.ll (original)
+++ llvm/trunk/test/CodeGen/X86/2009-03-13-PHIElimBug.ll Mon Mar 16 14:58:38 2009
@@ -1,37 +1,28 @@
-; RUN: llvm-as < %s | llc -mtriple=i386-pc-linux-gnu -stats |& grep phielim | grep {Number of EH try blocks skipped} | grep 4
+; RUN: llvm-as < %s | llc -march=x86 | grep -A 2 {call f} | grep movl
+; Check the register copy comes after the call to f and before the call to g
; PR3784
- %struct.c38002a__arr___XUB = type { i32, i32 }
- %struct.c38002a__arr_name = type { [0 x i32]*, %struct.c38002a__arr___XUB* }
- %struct.c38002a__rec = type { i32, %struct.c38002a__arr_name }
+declare i32 @f()
-define void @_ada_c38002a() {
-entry:
- %0 = invoke i8* @__gnat_malloc(i32 12)
- to label %invcont unwind label %lpad ; [#uses=0]
+declare i32 @g()
-invcont: ; preds = %entry
- %1 = invoke i8* @__gnat_malloc(i32 20)
- to label %invcont1 unwind label %lpad ; [#uses=0]
-
-invcont1: ; preds = %invcont
- %2 = invoke i32 @report__ident_int(i32 2)
- to label %.noexc unwind label %lpad ; [#uses=0]
-
-.noexc: ; preds = %invcont1
- %3 = invoke i32 @report__ident_int(i32 3)
- to label %.noexc88 unwind label %lpad ; [#uses=0]
-
-.noexc88: ; preds = %.noexc
- unreachable
-
-lpad: ; preds = %.noexc, %invcont1, %invcont, %entry
- %r.0 = phi %struct.c38002a__rec* [ null, %entry ], [ null, %invcont ], [ null, %invcont1 ], [ null, %.noexc ] ; <%struct.c38002a__rec*> [#uses=1]
- %4 = getelementptr %struct.c38002a__rec* %r.0, i32 0, i32 0 ; [#uses=1]
- %5 = load i32* %4, align 4 ; [#uses=0]
- ret void
+define i32 @phi() {
+entry:
+ %a = call i32 @f() ; [#uses=1]
+ %b = invoke i32 @g()
+ to label %cont unwind label %lpad ; [#uses=1]
+
+cont: ; preds = %entry
+ %x = phi i32 [ %b, %entry ] ; [#uses=0]
+ %aa = call i32 @g() ; [#uses=1]
+ %bb = invoke i32 @g()
+ to label %cont2 unwind label %lpad ; [#uses=1]
+
+cont2: ; preds = %cont
+ %xx = phi i32 [ %bb, %cont ] ; [#uses=1]
+ ret i32 %xx
+
+lpad: ; preds = %cont, %entry
+ %y = phi i32 [ %a, %entry ], [ %aa, %cont ] ; [#uses=1]
+ ret i32 %y
}
-
-declare i32 @report__ident_int(i32)
-
-declare i8* @__gnat_malloc(i32)
Added: llvm/trunk/test/CodeGen/X86/2009-03-16-PHIElimInLPad.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2009-03-16-PHIElimInLPad.ll?rev=67049&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/2009-03-16-PHIElimInLPad.ll (added)
+++ llvm/trunk/test/CodeGen/X86/2009-03-16-PHIElimInLPad.ll Mon Mar 16 14:58:38 2009
@@ -0,0 +1,21 @@
+; RUN: llvm-as < %s | llc -march=x86 | grep -A 1 lpad | grep Llabel
+; Check that register copies in the landing pad come after the EH_LABEL
+
+declare i32 @f()
+
+define i32 @phi(i32 %x) {
+entry:
+ %a = invoke i32 @f()
+ to label %cont unwind label %lpad ; [#uses=1]
+
+cont: ; preds = %entry
+ %b = invoke i32 @f()
+ to label %cont2 unwind label %lpad ; [#uses=1]
+
+cont2: ; preds = %cont
+ ret i32 %b
+
+lpad: ; preds = %cont, %entry
+ %v = phi i32 [ %x, %entry ], [ %a, %cont ] ; [#uses=1]
+ ret i32 %v
+}
From isanbard at gmail.com Mon Mar 16 15:23:40 2009
From: isanbard at gmail.com (Bill Wendling)
Date: Mon, 16 Mar 2009 12:23:40 -0800
Subject: [llvm-commits] [llvm] r67049 - in /llvm/trunk:
lib/CodeGen/PHIElimination.cpp
test/CodeGen/X86/2009-03-13-PHIElimBug.ll
test/CodeGen/X86/2009-03-16-PHIElimInLPad.ll
In-Reply-To: <200903161958.n2GJwdD6022601@zion.cs.uiuc.edu>
References: <200903161958.n2GJwdD6022601@zion.cs.uiuc.edu>
Message-ID: <16e5fdf90903161323r3ea5f54l4384f6265dc261f4@mail.gmail.com>
Duncan,
This test failed because of this patch. I'm going to temporarily
revert it. Please investigate it.
Thanks!
-bw
Running /Volumes/Sandbox/Buildbot/llvm/full-llvm/build/llvm.src/test/CodeGen/X86/dg.exp
...
FAIL: /Volumes/Sandbox/Buildbot/llvm/full-llvm/build/llvm.src/test/CodeGen/X86/2009-03-13-PHIElimBug.ll
for PR3784
Failed with exit(1) at line 1
while running: llvm-as <
/Volumes/Sandbox/Buildbot/llvm/full-llvm/build/llvm.src/test/CodeGen/X86/2009-03-13-PHIElimBug.ll
| llc -march=x86 | /usr/bin/grep -A 2 {call f} | /usr/bin/grep movl
child process exited abnormally
On Mon, Mar 16, 2009 at 11:58 AM, Duncan Sands wrote:
> Author: baldrick
> Date: Mon Mar 16 14:58:38 2009
> New Revision: 67049
>
> URL: http://llvm.org/viewvc/llvm-project?rev=67049&view=rev
> Log:
> Tweak the fix for PR3784: be less sensitive about just
> how invokes are set up. ?The fix could be disturbed by
> register copies coming after the EH_LABEL, and also didn't
> behave quite right when it was the invoke result that
> was used in a phi node. ?Also (see new testcase) fix
> another phi elimination bug while there: register copies
> in the landing pad need to come after the EH_LABEL, because
> that's where execution branches to when unwinding. ?If they
> come before the EH_LABEL then they will never be executed...
> Also tweak the original testcase so it doesn't use a no-longer
> existing counter.
> The accumulated phi elimination changes fix two of seven Ada
> testsuite failures that turned up after landing pad critical
> edge splitting was turned off. ?So there's probably more to come.
>
> Added:
> ? ?llvm/trunk/test/CodeGen/X86/2009-03-16-PHIElimInLPad.ll
> Modified:
> ? ?llvm/trunk/lib/CodeGen/PHIElimination.cpp
> ? ?llvm/trunk/test/CodeGen/X86/2009-03-13-PHIElimBug.ll
>
> Modified: llvm/trunk/lib/CodeGen/PHIElimination.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/PHIElimination.cpp?rev=67049&r1=67048&r2=67049&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/PHIElimination.cpp (original)
> +++ llvm/trunk/lib/CodeGen/PHIElimination.cpp Mon Mar 16 14:58:38 2009
> @@ -14,6 +14,8 @@
> ?//===----------------------------------------------------------------------===//
>
> ?#define DEBUG_TYPE "phielim"
> +#include "llvm/BasicBlock.h"
> +#include "llvm/Instructions.h"
> ?#include "llvm/CodeGen/LiveVariables.h"
> ?#include "llvm/CodeGen/Passes.h"
> ?#include "llvm/CodeGen/MachineFunctionPass.h"
> @@ -31,7 +33,6 @@
> ?using namespace llvm;
>
> ?STATISTIC(NumAtomic, "Number of atomic phis lowered");
> -STATISTIC(NumEH, ? ? "Number of EH try blocks skipped");
>
> ?namespace {
> ? class VISIBILITY_HIDDEN PNE : public MachineFunctionPass {
> @@ -66,8 +67,25 @@
> ? ? ///
> ? ? void analyzePHINodes(const MachineFunction& Fn);
>
> - ? ?void WalkPassEHTryRange(MachineBasicBlock &MBB,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ?MachineBasicBlock::iterator &I, unsigned SrcReg);
> + ? ?// FindCopyInsertPoint - Find a safe place in MBB to insert a copy from
> + ? ?// SrcReg. ?This needs to be after any def or uses of SrcReg, but before
> + ? ?// any subsequent point where control flow might jump out of the basic
> + ? ?// block.
> + ? ?MachineBasicBlock::iterator FindCopyInsertPoint(MachineBasicBlock &MBB,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?unsigned SrcReg);
> +
> + ? ?// SkipPHIsAndLabels - Copies need to be inserted after phi nodes and
> + ? ?// also after any exception handling labels: in landing pads execution
> + ? ?// starts at the label, so any copies placed before it won't be executed!
> + ? ?MachineBasicBlock::iterator SkipPHIsAndLabels(MachineBasicBlock &MBB,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?MachineBasicBlock::iterator I) {
> + ? ? ?// Rather than assuming that EH labels come before other kinds of labels,
> + ? ? ?// just skip all labels.
> + ? ? ?while (I != MBB.end() &&
> + ? ? ? ? ? ? (I->getOpcode() == TargetInstrInfo::PHI || I->isLabel()))
> + ? ? ? ?++I;
> + ? ? ?return I;
> + ? ?}
>
> ? ? typedef std::pair BBVRegPair;
> ? ? typedef std::map VRegPHIUse;
> @@ -120,10 +138,7 @@
>
> ? // Get an iterator to the first instruction after the last PHI node (this may
> ? // also be the end of the basic block).
> - ?MachineBasicBlock::iterator AfterPHIsIt = MBB.begin();
> - ?while (AfterPHIsIt != MBB.end() &&
> - ? ? ? ? AfterPHIsIt->getOpcode() == TargetInstrInfo::PHI)
> - ? ?++AfterPHIsIt; ? ?// Skip over all of the PHI nodes...
> + ?MachineBasicBlock::iterator AfterPHIsIt = SkipPHIsAndLabels(MBB, MBB.begin());
>
> ? while (MBB.front().getOpcode() == TargetInstrInfo::PHI)
> ? ? LowerAtomicPHINode(MBB, AfterPHIsIt);
> @@ -144,37 +159,47 @@
> ? return true;
> ?}
>
> -void PNE::WalkPassEHTryRange(MachineBasicBlock &MBB,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? MachineBasicBlock::iterator &I, unsigned SrcReg) {
> - ?if (I == MBB.begin())
> - ? ?return;
> - ?MachineBasicBlock::iterator PI = prior(I);
> - ?if (PI->getOpcode() != TargetInstrInfo::EH_LABEL)
> - ? ?return;
> -
> - ?// Trying to walk pass the EH try range. If we run into a use instruction,
> - ?// we want to insert the copy there.
> - ?SmallPtrSet UsesInMBB;
> - ?for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(SrcReg),
> - ? ? ? ? UE = MRI->use_end(); UI != UE; ++UI) {
> - ? ?MachineInstr *UseMI = &*UI;
> - ? ?if (UseMI->getParent() == &MBB)
> - ? ? ?UsesInMBB.insert(UseMI);
> +// FindCopyInsertPoint - Find a safe place in MBB to insert a copy from SrcReg.
> +// This needs to be after any def or uses of SrcReg, but before any subsequent
> +// point where control flow might jump out of the basic block.
> +MachineBasicBlock::iterator PNE::FindCopyInsertPoint(MachineBasicBlock &MBB,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? unsigned SrcReg) {
> + ?// Handle the trivial case trivially.
> + ?if (MBB.empty())
> + ? ?return MBB.begin();
> +
> + ?// If this basic block does not contain an invoke, then control flow always
> + ?// reaches the end of it, so place the copy there. ?The logic below works in
> + ?// this case too, but is more expensive.
> + ?if (!isa(MBB.getBasicBlock()->getTerminator()))
> + ? ?return MBB.getFirstTerminator();
> +
> + ?// Discover any definition/uses in this basic block.
> + ?SmallPtrSet DefUsesInMBB;
> + ?for (MachineRegisterInfo::reg_iterator RI = MRI->reg_begin(SrcReg),
> + ? ? ? RE = MRI->reg_end(); RI != RE; ++RI) {
> + ? ?MachineInstr *DefUseMI = &*RI;
> + ? ?if (DefUseMI->getParent() == &MBB)
> + ? ? ?DefUsesInMBB.insert(DefUseMI);
> ? }
>
> - ?while (PI != MBB.begin()) {
> - ? ?--PI;
> - ? ?if (PI->getOpcode() == TargetInstrInfo::EH_LABEL) {
> - ? ? ?++NumEH;
> - ? ? ?I = PI;
> - ? ? ?return;
> - ? ?} else if (UsesInMBB.count(&*PI)) {
> - ? ? ?++NumEH;
> - ? ? ?I = next(PI);
> - ? ? ?return;
> - ? ?}
> + ?MachineBasicBlock::iterator InsertPoint;
> + ?if (DefUsesInMBB.empty()) {
> + ? ?// No def/uses. ?Insert the copy at the start of the basic block.
> + ? ?InsertPoint = MBB.begin();
> + ?} else if (DefUsesInMBB.size() == 1) {
> + ? ?// Insert the copy immediately after the definition/use.
> + ? ?InsertPoint = *DefUsesInMBB.begin();
> + ? ?++InsertPoint;
> + ?} else {
> + ? ?// Insert the copy immediately after the last definition/use.
> + ? ?InsertPoint = MBB.end();
> + ? ?while (!DefUsesInMBB.count(&*--InsertPoint)) {}
> + ? ?++InsertPoint;
> ? }
> - ?return;
> +
> + ?// Make sure the copy goes after any phi nodes however.
> + ?return SkipPHIsAndLabels(MBB, InsertPoint);
> ?}
>
> ?/// LowerAtomicPHINode - Lower the PHI node at the top of the specified block,
> @@ -273,10 +298,7 @@
>
> ? ? // Find a safe location to insert the copy, this may be the first terminator
> ? ? // in the block (or end()).
> - ? ?MachineBasicBlock::iterator InsertPos = opBlock.getFirstTerminator();
> -
> - ? ?// Walk pass EH try range if needed.
> - ? ?WalkPassEHTryRange(opBlock, InsertPos, SrcReg);
> + ? ?MachineBasicBlock::iterator InsertPos = FindCopyInsertPoint(opBlock, SrcReg);
>
> ? ? // Insert the copy.
> ? ? TII->copyRegToReg(opBlock, InsertPos, IncomingReg, SrcReg, RC, RC);
>
> Modified: llvm/trunk/test/CodeGen/X86/2009-03-13-PHIElimBug.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2009-03-13-PHIElimBug.ll?rev=67049&r1=67048&r2=67049&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/2009-03-13-PHIElimBug.ll (original)
> +++ llvm/trunk/test/CodeGen/X86/2009-03-13-PHIElimBug.ll Mon Mar 16 14:58:38 2009
> @@ -1,37 +1,28 @@
> -; RUN: llvm-as < %s | llc -mtriple=i386-pc-linux-gnu -stats |& grep phielim | grep {Number of EH try blocks skipped} | grep 4
> +; RUN: llvm-as < %s | llc -march=x86 | grep -A 2 {call f} | grep movl
> +; Check the register copy comes after the call to f and before the call to g
> ?; PR3784
>
> - ? ? ? %struct.c38002a__arr___XUB = type { i32, i32 }
> - ? ? ? %struct.c38002a__arr_name = type { [0 x i32]*, %struct.c38002a__arr___XUB* }
> - ? ? ? %struct.c38002a__rec = type { i32, %struct.c38002a__arr_name }
> +declare i32 @f()
>
> -define void @_ada_c38002a() {
> -entry:
> - ? ? ? %0 = invoke i8* @__gnat_malloc(i32 12)
> - ? ? ? ? ? ? ? ? ? ? ? to label %invcont unwind label %lpad ? ? ? ? ? ?; [#uses=0]
> +declare i32 @g()
>
> -invcont: ? ? ? ? ? ? ? ; preds = %entry
> - ? ? ? %1 = invoke i8* @__gnat_malloc(i32 20)
> - ? ? ? ? ? ? ? ? ? ? ? to label %invcont1 unwind label %lpad ? ? ? ? ? ; [#uses=0]
> -
> -invcont1: ? ? ? ? ? ? ?; preds = %invcont
> - ? ? ? %2 = invoke i32 @report__ident_int(i32 2)
> - ? ? ? ? ? ? ? ? ? ? ? to label %.noexc unwind label %lpad ? ? ? ? ? ? ; [#uses=0]
> -
> -.noexc: ? ? ? ? ? ? ? ?; preds = %invcont1
> - ? ? ? %3 = invoke i32 @report__ident_int(i32 3)
> - ? ? ? ? ? ? ? ? ? ? ? to label %.noexc88 unwind label %lpad ? ? ? ? ? ; [#uses=0]
> -
> -.noexc88: ? ? ? ? ? ? ?; preds = %.noexc
> - ? ? ? unreachable
> -
> -lpad: ? ? ? ? ?; preds = %.noexc, %invcont1, %invcont, %entry
> - ? ? ? %r.0 = phi %struct.c38002a__rec* [ null, %entry ], [ null, %invcont ], [ null, %invcont1 ], [ null, %.noexc ] ? ? ? ? ? ; <%struct.c38002a__rec*> [#uses=1]
> - ? ? ? %4 = getelementptr %struct.c38002a__rec* %r.0, i32 0, i32 0 ? ? ? ? ? ? ; [#uses=1]
> - ? ? ? %5 = load i32* %4, align 4 ? ? ? ? ? ? ?; [#uses=0]
> - ? ? ? ret void
> +define i32 @phi() {
> +entry:
> + ? ? ? %a = call i32 @f() ? ? ? ? ? ? ?; [#uses=1]
> + ? ? ? %b = invoke i32 @g()
> + ? ? ? ? ? ? ? ? ? ? ? to label %cont unwind label %lpad ? ? ? ? ? ? ? ; [#uses=1]
> +
> +cont: ? ? ? ? ?; preds = %entry
> + ? ? ? %x = phi i32 [ %b, %entry ] ? ? ? ? ? ? ; [#uses=0]
> + ? ? ? %aa = call i32 @g() ? ? ? ? ? ? ; [#uses=1]
> + ? ? ? %bb = invoke i32 @g()
> + ? ? ? ? ? ? ? ? ? ? ? to label %cont2 unwind label %lpad ? ? ? ? ? ? ?; [#uses=1]
> +
> +cont2: ? ? ? ? ; preds = %cont
> + ? ? ? %xx = phi i32 [ %bb, %cont ] ? ? ? ? ? ?; [#uses=1]
> + ? ? ? ret i32 %xx
> +
> +lpad: ? ? ? ? ?; preds = %cont, %entry
> + ? ? ? %y = phi i32 [ %a, %entry ], [ %aa, %cont ] ? ? ? ? ? ? ; [#uses=1]
> + ? ? ? ret i32 %y
> ?}
> -
> -declare i32 @report__ident_int(i32)
> -
> -declare i8* @__gnat_malloc(i32)
>
> Added: llvm/trunk/test/CodeGen/X86/2009-03-16-PHIElimInLPad.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2009-03-16-PHIElimInLPad.ll?rev=67049&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/2009-03-16-PHIElimInLPad.ll (added)
> +++ llvm/trunk/test/CodeGen/X86/2009-03-16-PHIElimInLPad.ll Mon Mar 16 14:58:38 2009
> @@ -0,0 +1,21 @@
> +; RUN: llvm-as < %s | llc -march=x86 | grep -A 1 lpad | grep Llabel
> +; Check that register copies in the landing pad come after the EH_LABEL
> +
> +declare i32 @f()
> +
> +define i32 @phi(i32 %x) {
> +entry:
> + ? ? ? %a = invoke i32 @f()
> + ? ? ? ? ? ? ? ? ? ? ? to label %cont unwind label %lpad ? ? ? ? ? ? ? ; [#uses=1]
> +
> +cont: ? ? ? ? ?; preds = %entry
> + ? ? ? %b = invoke i32 @f()
> + ? ? ? ? ? ? ? ? ? ? ? to label %cont2 unwind label %lpad ? ? ? ? ? ? ?; [#uses=1]
> +
> +cont2: ? ? ? ? ; preds = %cont
> + ? ? ? ret i32 %b
> +
> +lpad: ? ? ? ? ?; preds = %cont, %entry
> + ? ? ? %v = phi i32 [ %x, %entry ], [ %a, %cont ] ? ? ? ? ? ? ?; [#uses=1]
> + ? ? ? ret i32 %v
> +}
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
From isanbard at gmail.com Mon Mar 16 15:27:21 2009
From: isanbard at gmail.com (Bill Wendling)
Date: Mon, 16 Mar 2009 20:27:21 -0000
Subject: [llvm-commits] [llvm] r67051 - in /llvm/trunk:
lib/CodeGen/PHIElimination.cpp test/CodeGen/X86/2009-03-13-PHIElimBug.ll
test/CodeGen/X86/2009-03-16-PHIElimInLPad.ll
Message-ID: <200903162027.n2GKRLTi023588@zion.cs.uiuc.edu>
Author: void
Date: Mon Mar 16 15:27:20 2009
New Revision: 67051
URL: http://llvm.org/viewvc/llvm-project?rev=67051&view=rev
Log:
--- Reverse-merging (from foreign repository) r67049 into '.':
U test/CodeGen/X86/2009-03-13-PHIElimBug.ll
D test/CodeGen/X86/2009-03-16-PHIElimInLPad.ll
U lib/CodeGen/PHIElimination.cpp
r67049 was causing this failure:
Running /Volumes/Sandbox/Buildbot/llvm/full-llvm/build/llvm.src/test/CodeGen/X86/dg.exp ...
FAIL: /Volumes/Sandbox/Buildbot/llvm/full-llvm/build/llvm.src/test/CodeGen/X86/2009-03-13-PHIElimBug.ll for PR3784
Failed with exit(1) at line 1
while running: llvm-as < /Volumes/Sandbox/Buildbot/llvm/full-llvm/build/llvm.src/test/CodeGen/X86/2009-03-13-PHIElimBug.ll | llc -march=x86 | /usr/bin/grep -A 2 {call f} | /usr/bin/grep movl
child process exited abnormally
Removed:
llvm/trunk/test/CodeGen/X86/2009-03-16-PHIElimInLPad.ll
Modified:
llvm/trunk/lib/CodeGen/PHIElimination.cpp
llvm/trunk/test/CodeGen/X86/2009-03-13-PHIElimBug.ll
Modified: llvm/trunk/lib/CodeGen/PHIElimination.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/PHIElimination.cpp?rev=67051&r1=67050&r2=67051&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/PHIElimination.cpp (original)
+++ llvm/trunk/lib/CodeGen/PHIElimination.cpp Mon Mar 16 15:27:20 2009
@@ -14,8 +14,6 @@
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "phielim"
-#include "llvm/BasicBlock.h"
-#include "llvm/Instructions.h"
#include "llvm/CodeGen/LiveVariables.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
@@ -33,6 +31,7 @@
using namespace llvm;
STATISTIC(NumAtomic, "Number of atomic phis lowered");
+STATISTIC(NumEH, "Number of EH try blocks skipped");
namespace {
class VISIBILITY_HIDDEN PNE : public MachineFunctionPass {
@@ -67,25 +66,8 @@
///
void analyzePHINodes(const MachineFunction& Fn);
- // FindCopyInsertPoint - Find a safe place in MBB to insert a copy from
- // SrcReg. This needs to be after any def or uses of SrcReg, but before
- // any subsequent point where control flow might jump out of the basic
- // block.
- MachineBasicBlock::iterator FindCopyInsertPoint(MachineBasicBlock &MBB,
- unsigned SrcReg);
-
- // SkipPHIsAndLabels - Copies need to be inserted after phi nodes and
- // also after any exception handling labels: in landing pads execution
- // starts at the label, so any copies placed before it won't be executed!
- MachineBasicBlock::iterator SkipPHIsAndLabels(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator I) {
- // Rather than assuming that EH labels come before other kinds of labels,
- // just skip all labels.
- while (I != MBB.end() &&
- (I->getOpcode() == TargetInstrInfo::PHI || I->isLabel()))
- ++I;
- return I;
- }
+ void WalkPassEHTryRange(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator &I, unsigned SrcReg);
typedef std::pair BBVRegPair;
typedef std::map VRegPHIUse;
@@ -138,7 +120,10 @@
// Get an iterator to the first instruction after the last PHI node (this may
// also be the end of the basic block).
- MachineBasicBlock::iterator AfterPHIsIt = SkipPHIsAndLabels(MBB, MBB.begin());
+ MachineBasicBlock::iterator AfterPHIsIt = MBB.begin();
+ while (AfterPHIsIt != MBB.end() &&
+ AfterPHIsIt->getOpcode() == TargetInstrInfo::PHI)
+ ++AfterPHIsIt; // Skip over all of the PHI nodes...
while (MBB.front().getOpcode() == TargetInstrInfo::PHI)
LowerAtomicPHINode(MBB, AfterPHIsIt);
@@ -159,47 +144,37 @@
return true;
}
-// FindCopyInsertPoint - Find a safe place in MBB to insert a copy from SrcReg.
-// This needs to be after any def or uses of SrcReg, but before any subsequent
-// point where control flow might jump out of the basic block.
-MachineBasicBlock::iterator PNE::FindCopyInsertPoint(MachineBasicBlock &MBB,
- unsigned SrcReg) {
- // Handle the trivial case trivially.
- if (MBB.empty())
- return MBB.begin();
-
- // If this basic block does not contain an invoke, then control flow always
- // reaches the end of it, so place the copy there. The logic below works in
- // this case too, but is more expensive.
- if (!isa(MBB.getBasicBlock()->getTerminator()))
- return MBB.getFirstTerminator();
-
- // Discover any definition/uses in this basic block.
- SmallPtrSet DefUsesInMBB;
- for (MachineRegisterInfo::reg_iterator RI = MRI->reg_begin(SrcReg),
- RE = MRI->reg_end(); RI != RE; ++RI) {
- MachineInstr *DefUseMI = &*RI;
- if (DefUseMI->getParent() == &MBB)
- DefUsesInMBB.insert(DefUseMI);
+void PNE::WalkPassEHTryRange(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator &I, unsigned SrcReg) {
+ if (I == MBB.begin())
+ return;
+ MachineBasicBlock::iterator PI = prior(I);
+ if (PI->getOpcode() != TargetInstrInfo::EH_LABEL)
+ return;
+
+ // Trying to walk pass the EH try range. If we run into a use instruction,
+ // we want to insert the copy there.
+ SmallPtrSet UsesInMBB;
+ for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(SrcReg),
+ UE = MRI->use_end(); UI != UE; ++UI) {
+ MachineInstr *UseMI = &*UI;
+ if (UseMI->getParent() == &MBB)
+ UsesInMBB.insert(UseMI);
}
- MachineBasicBlock::iterator InsertPoint;
- if (DefUsesInMBB.empty()) {
- // No def/uses. Insert the copy at the start of the basic block.
- InsertPoint = MBB.begin();
- } else if (DefUsesInMBB.size() == 1) {
- // Insert the copy immediately after the definition/use.
- InsertPoint = *DefUsesInMBB.begin();
- ++InsertPoint;
- } else {
- // Insert the copy immediately after the last definition/use.
- InsertPoint = MBB.end();
- while (!DefUsesInMBB.count(&*--InsertPoint)) {}
- ++InsertPoint;
+ while (PI != MBB.begin()) {
+ --PI;
+ if (PI->getOpcode() == TargetInstrInfo::EH_LABEL) {
+ ++NumEH;
+ I = PI;
+ return;
+ } else if (UsesInMBB.count(&*PI)) {
+ ++NumEH;
+ I = next(PI);
+ return;
+ }
}
-
- // Make sure the copy goes after any phi nodes however.
- return SkipPHIsAndLabels(MBB, InsertPoint);
+ return;
}
/// LowerAtomicPHINode - Lower the PHI node at the top of the specified block,
@@ -298,7 +273,10 @@
// Find a safe location to insert the copy, this may be the first terminator
// in the block (or end()).
- MachineBasicBlock::iterator InsertPos = FindCopyInsertPoint(opBlock, SrcReg);
+ MachineBasicBlock::iterator InsertPos = opBlock.getFirstTerminator();
+
+ // Walk pass EH try range if needed.
+ WalkPassEHTryRange(opBlock, InsertPos, SrcReg);
// Insert the copy.
TII->copyRegToReg(opBlock, InsertPos, IncomingReg, SrcReg, RC, RC);
Modified: llvm/trunk/test/CodeGen/X86/2009-03-13-PHIElimBug.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2009-03-13-PHIElimBug.ll?rev=67051&r1=67050&r2=67051&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/2009-03-13-PHIElimBug.ll (original)
+++ llvm/trunk/test/CodeGen/X86/2009-03-13-PHIElimBug.ll Mon Mar 16 15:27:20 2009
@@ -1,28 +1,37 @@
-; RUN: llvm-as < %s | llc -march=x86 | grep -A 2 {call f} | grep movl
-; Check the register copy comes after the call to f and before the call to g
+; RUN: llvm-as < %s | llc -mtriple=i386-pc-linux-gnu -stats |& grep phielim | grep {Number of EH try blocks skipped} | grep 4
; PR3784
-declare i32 @f()
+ %struct.c38002a__arr___XUB = type { i32, i32 }
+ %struct.c38002a__arr_name = type { [0 x i32]*, %struct.c38002a__arr___XUB* }
+ %struct.c38002a__rec = type { i32, %struct.c38002a__arr_name }
-declare i32 @g()
-
-define i32 @phi() {
+define void @_ada_c38002a() {
entry:
- %a = call i32 @f() ; [#uses=1]
- %b = invoke i32 @g()
- to label %cont unwind label %lpad ; [#uses=1]
-
-cont: ; preds = %entry
- %x = phi i32 [ %b, %entry ] ; [#uses=0]
- %aa = call i32 @g() ; [#uses=1]
- %bb = invoke i32 @g()
- to label %cont2 unwind label %lpad ; [#uses=1]
-
-cont2: ; preds = %cont
- %xx = phi i32 [ %bb, %cont ] ; [#uses=1]
- ret i32 %xx
-
-lpad: ; preds = %cont, %entry
- %y = phi i32 [ %a, %entry ], [ %aa, %cont ] ; [#uses=1]
- ret i32 %y
+ %0 = invoke i8* @__gnat_malloc(i32 12)
+ to label %invcont unwind label %lpad ; [#uses=0]
+
+invcont: ; preds = %entry
+ %1 = invoke i8* @__gnat_malloc(i32 20)
+ to label %invcont1 unwind label %lpad ; [#uses=0]
+
+invcont1: ; preds = %invcont
+ %2 = invoke i32 @report__ident_int(i32 2)
+ to label %.noexc unwind label %lpad ; [#uses=0]
+
+.noexc: ; preds = %invcont1
+ %3 = invoke i32 @report__ident_int(i32 3)
+ to label %.noexc88 unwind label %lpad ; [#uses=0]
+
+.noexc88: ; preds = %.noexc
+ unreachable
+
+lpad: ; preds = %.noexc, %invcont1, %invcont, %entry
+ %r.0 = phi %struct.c38002a__rec* [ null, %entry ], [ null, %invcont ], [ null, %invcont1 ], [ null, %.noexc ] ; <%struct.c38002a__rec*> [#uses=1]
+ %4 = getelementptr %struct.c38002a__rec* %r.0, i32 0, i32 0 ; [#uses=1]
+ %5 = load i32* %4, align 4 ; [#uses=0]
+ ret void
}
+
+declare i32 @report__ident_int(i32)
+
+declare i8* @__gnat_malloc(i32)
Removed: llvm/trunk/test/CodeGen/X86/2009-03-16-PHIElimInLPad.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2009-03-16-PHIElimInLPad.ll?rev=67050&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/2009-03-16-PHIElimInLPad.ll (original)
+++ llvm/trunk/test/CodeGen/X86/2009-03-16-PHIElimInLPad.ll (removed)
@@ -1,21 +0,0 @@
-; RUN: llvm-as < %s | llc -march=x86 | grep -A 1 lpad | grep Llabel
-; Check that register copies in the landing pad come after the EH_LABEL
-
-declare i32 @f()
-
-define i32 @phi(i32 %x) {
-entry:
- %a = invoke i32 @f()
- to label %cont unwind label %lpad ; [#uses=1]
-
-cont: ; preds = %entry
- %b = invoke i32 @f()
- to label %cont2 unwind label %lpad ; [#uses=1]
-
-cont2: ; preds = %cont
- ret i32 %b
-
-lpad: ; preds = %cont, %entry
- %v = phi i32 [ %x, %entry ], [ %a, %cont ] ; [#uses=1]
- ret i32 %v
-}
From dgregor at apple.com Mon Mar 16 16:35:18 2009
From: dgregor at apple.com (Douglas Gregor)
Date: Mon, 16 Mar 2009 21:35:18 -0000
Subject: [llvm-commits] [llvm] r67052 -
/llvm/trunk/cmake/modules/TableGen.cmake
Message-ID: <200903162135.n2GLZIC7025906@zion.cs.uiuc.edu>
Author: dgregor
Date: Mon Mar 16 16:35:18 2009
New Revision: 67052
URL: http://llvm.org/viewvc/llvm-project?rev=67052&view=rev
Log:
CMake: Make sure to build TableGen'd files in the binary directory
Modified:
llvm/trunk/cmake/modules/TableGen.cmake
Modified: llvm/trunk/cmake/modules/TableGen.cmake
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/cmake/modules/TableGen.cmake?rev=67052&r1=67051&r2=67052&view=diff
==============================================================================
--- llvm/trunk/cmake/modules/TableGen.cmake (original)
+++ llvm/trunk/cmake/modules/TableGen.cmake Mon Mar 16 16:35:18 2009
@@ -4,15 +4,18 @@
macro(tablegen ofn)
file(GLOB all_tds "*.td")
+
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.tmp
COMMAND ${LLVM_TABLEGEN} ${ARGN} -I ${CMAKE_CURRENT_SOURCE_DIR}
-I ${LLVM_MAIN_SRC_DIR}/lib/Target -I ${LLVM_MAIN_INCLUDE_DIR}
- ${CMAKE_CURRENT_SOURCE_DIR}/${LLVM_TARGET_DEFINITIONS} -o ${ofn}.tmp
+ ${CMAKE_CURRENT_SOURCE_DIR}/${LLVM_TARGET_DEFINITIONS}
+ -o ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.tmp
DEPENDS ${LLVM_TABLEGEN} ${all_tds}
COMMENT "Building ${ofn}.tmp..."
)
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ofn}
- COMMAND ${CMAKE_COMMAND} -E copy_if_different ${ofn}.tmp ${ofn}
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.tmp ${CMAKE_CURRENT_BINARY_DIR}/${ofn}
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.tmp
COMMENT "Building ${ofn}..."
)
From daniel at zuster.org Mon Mar 16 17:00:17 2009
From: daniel at zuster.org (Daniel Dunbar)
Date: Mon, 16 Mar 2009 22:00:17 -0000
Subject: [llvm-commits] [llvm] r67053 - in /llvm/trunk:
include/llvm/Support/raw_ostream.h lib/Support/raw_ostream.cpp
Message-ID: <200903162200.n2GM0HKJ026916@zion.cs.uiuc.edu>
Author: ddunbar
Date: Mon Mar 16 17:00:17 2009
New Revision: 67053
URL: http://llvm.org/viewvc/llvm-project?rev=67053&view=rev
Log:
Add slow path for single character write, and use exclusively for
single characters writes outside of the fast path in raw_ostream.h
Modified:
llvm/trunk/include/llvm/Support/raw_ostream.h
llvm/trunk/lib/Support/raw_ostream.cpp
Modified: llvm/trunk/include/llvm/Support/raw_ostream.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/raw_ostream.h?rev=67053&r1=67052&r2=67053&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/raw_ostream.h (original)
+++ llvm/trunk/include/llvm/Support/raw_ostream.h Mon Mar 16 17:00:17 2009
@@ -82,7 +82,7 @@
raw_ostream &operator<<(char C) {
if (OutBufCur >= OutBufEnd)
- flush_impl();
+ return write(C);
*OutBufCur++ = C;
if (Unbuffered)
flush_impl();
@@ -91,7 +91,7 @@
raw_ostream &operator<<(unsigned char C) {
if (OutBufCur >= OutBufEnd)
- flush_impl();
+ return write(C);
*OutBufCur++ = C;
if (Unbuffered)
flush_impl();
@@ -100,7 +100,7 @@
raw_ostream &operator<<(signed char C) {
if (OutBufCur >= OutBufEnd)
- flush_impl();
+ return write(C);
*OutBufCur++ = C;
if (Unbuffered)
flush_impl();
@@ -132,6 +132,7 @@
return this->operator<<(ftostr(N));
}
+ raw_ostream &write(unsigned char C);
raw_ostream &write(const char *Ptr, unsigned Size);
// Formatted output, see the format() function in Support/Format.h.
Modified: llvm/trunk/lib/Support/raw_ostream.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/raw_ostream.cpp?rev=67053&r1=67052&r2=67053&view=diff
==============================================================================
--- llvm/trunk/lib/Support/raw_ostream.cpp (original)
+++ llvm/trunk/lib/Support/raw_ostream.cpp Mon Mar 16 17:00:17 2009
@@ -63,10 +63,7 @@
raw_ostream &raw_ostream::operator<<(long N) {
if (N < 0) {
- if (OutBufCur >= OutBufEnd)
- flush_impl();
- *OutBufCur++ = '-';
-
+ *this << '-';
N = -N;
}
@@ -91,10 +88,7 @@
raw_ostream &raw_ostream::operator<<(long long N) {
if (N < 0) {
- if (OutBufCur >= OutBufEnd)
- flush_impl();
- *OutBufCur++ = '-';
-
+ *this << '-';
N = -N;
}
@@ -106,6 +100,12 @@
return *this << format("%p", P);
}
+raw_ostream &raw_ostream::write(unsigned char C) {
+ if (OutBufCur >= OutBufEnd)
+ flush_impl();
+
+ *OutBufCur++ = C;
+}
raw_ostream &raw_ostream::write(const char *Ptr, unsigned Size) {
if (OutBufCur+Size > OutBufEnd)
From daniel at zuster.org Mon Mar 16 17:08:44 2009
From: daniel at zuster.org (Daniel Dunbar)
Date: Mon, 16 Mar 2009 22:08:44 -0000
Subject: [llvm-commits] [llvm] r67054 -
/llvm/trunk/lib/Support/raw_ostream.cpp
Message-ID: <200903162208.n2GM8iRP027219@zion.cs.uiuc.edu>
Author: ddunbar
Date: Mon Mar 16 17:08:44 2009
New Revision: 67054
URL: http://llvm.org/viewvc/llvm-project?rev=67054&view=rev
Log:
Make raw_ostream::operator<<(const void *) fast; it doesn't matter but
it is easy.
Modified:
llvm/trunk/lib/Support/raw_ostream.cpp
Modified: llvm/trunk/lib/Support/raw_ostream.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/raw_ostream.cpp?rev=67054&r1=67053&r2=67054&view=diff
==============================================================================
--- llvm/trunk/lib/Support/raw_ostream.cpp (original)
+++ llvm/trunk/lib/Support/raw_ostream.cpp Mon Mar 16 17:08:44 2009
@@ -96,8 +96,24 @@
}
raw_ostream &raw_ostream::operator<<(const void *P) {
- // FIXME: This could be much faster if it matters.
- return *this << format("%p", P);
+ uintptr_t N = (uintptr_t) P;
+ *this << '0' << 'x';
+
+ // Zero is a special case.
+ if (N == 0)
+ return *this << '0';
+
+ char NumberBuffer[20];
+ char *EndPtr = NumberBuffer+sizeof(NumberBuffer);
+ char *CurPtr = EndPtr;
+
+ while (N) {
+ unsigned x = N % 16;
+ *--CurPtr = (x < 10 ? '0' + x : 'a' + x - 10);
+ N /= 16;
+ }
+
+ return write(CurPtr, EndPtr-CurPtr);
}
raw_ostream &raw_ostream::write(unsigned char C) {
@@ -105,6 +121,7 @@
flush_impl();
*OutBufCur++ = C;
+ return *this;
}
raw_ostream &raw_ostream::write(const char *Ptr, unsigned Size) {
From gohman at apple.com Mon Mar 16 17:22:33 2009
From: gohman at apple.com (Dan Gohman)
Date: Mon, 16 Mar 2009 15:22:33 -0700
Subject: [llvm-commits] embedded metadata preview
In-Reply-To: <49BB6E93.9050802@mxc.ca>
References: <49BB6E93.9050802@mxc.ca>
Message-ID:
Hi Nick,
Here are a few review comments.
> Index: lib/Bitcode/Writer/BitcodeWriter.cpp
> ===================================================================
> --- lib/Bitcode/Writer/BitcodeWriter.cpp (revision 66999)
> +++ lib/Bitcode/Writer/BitcodeWriter.cpp (working copy)
> @@ -677,6 +677,17 @@
> Record.push_back(CE->getPredicate());
> break;
> }
> + } else if (const MDString *S = dyn_cast(C)) {
> + Code = bitc::CST_CODE_MDSTRING;
> + Record.push_back(S->length());
> + for (unsigned i = 0, e = S->length(); i != e; ++i)
> + Record.push_back(S->begin()[i]);
It seems pretty inefficient to put each char in a uint64_t.
Forgive me for prematurely optimizing :-).
> Index: lib/Bitcode/Reader/BitcodeReader.cpp
> ===================================================================
> --- lib/Bitcode/Reader/BitcodeReader.cpp (revision 66999)
> +++ lib/Bitcode/Reader/BitcodeReader.cpp (working copy)
> @@ -283,10 +283,12 @@
> UserCS->getType()->isPacked());
> } else if (isa(UserC)) {
> NewC = ConstantVector::get(&NewOps[0], NewOps.size());
> - } else {
> - // Must be a constant expression.
> + } else if (isa(UserC)) {
> NewC = cast(UserC)-
>getWithOperands(&NewOps[0],
>
NewOps.size());
> + } else {
> + // Must be a metadata node.
> + NewC = MDNode::get(&NewOps[0], NewOps.size());
> }
>
Can you add an assert(isa) here to verify the assertion in
the comment?
> Index: docs/LangRef.html
> ===================================================================
> --- docs/LangRef.html (revision 66999)
> +++ docs/LangRef.html (working copy)
> @@ -1847,6 +1848,14 @@
> large arrays) and is always exactly equivalent to using explicit
zero
> initializers.
>
> +
> + Metadata node
> +
> + A metadata node is a structure-like constant with the type
of an empty
> + struct. For example: "{ } !{ i32 0, { } !"test" }".
Unlike other
> + constants that are meant to be interpreted as part of the
instruction stream,
> + metadata is a place to attach additional information such as
debug info.
It would be helpful to mention that this is also expected to be used for
encoding information that will be used by optimizations.
MDString and MDNode have protected constructors. Do you anticipate
these classes having subclasses? If so, what would they be like?
Why do MDString and MDNode inherit from Constant instead of, say,
User? I
see that ConstantLastVal is moved to include MDStringVal and MDNodeVal,
presumably for the same reason.
Dan
On Mar 14, 2009, at 1:45 AM, Nick Lewycky wrote:
> I took a stab at implementing embedded metadata. The idea is to
> allow LLVM's user to attach meaningful data to the instruction
> stream that isn't really relevant to the execution of the
> instructions. This comes from Chris' notes:
>
> http://nondot.org/sabre/LLVMNotes/EmbeddedMetadata.txt
>
> which I deviated a little. The major thing missing from this patch
> is any verifier support. My current plan is to add support to the
> verifier for ensuring that MDNode and MDString are only used from a)
> initializers to globals named starting with "llvm." b) calls to
> intrinsic functions, then commit it.
>
> The attached patch implements MDString and MDNode as new types of
> Constant, .ll/.bc reader/writer support and a LangRef update. I'd
> appreciate any review comments!
>
> Nick
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
From isanbard at gmail.com Mon Mar 16 17:45:55 2009
From: isanbard at gmail.com (Bill Wendling)
Date: Mon, 16 Mar 2009 22:45:55 -0000
Subject: [llvm-commits] [llvm-gcc-4.2] r67055 - in
/llvm-gcc-4.2/branches/Apple/Dib/gcc: llvm-convert.cpp llvm-debug.cpp
llvm-debug.h
Message-ID: <200903162245.n2GMjtEr028771@zion.cs.uiuc.edu>
Author: void
Date: Mon Mar 16 17:45:54 2009
New Revision: 67055
URL: http://llvm.org/viewvc/llvm-project?rev=67055&view=rev
Log:
--- Reverse-merging (from foreign repository) r66919 into '.':
U gcc/llvm-convert.cpp
U gcc/llvm-debug.cpp
U gcc/llvm-debug.h
Modified:
llvm-gcc-4.2/branches/Apple/Dib/gcc/llvm-convert.cpp
llvm-gcc-4.2/branches/Apple/Dib/gcc/llvm-debug.cpp
llvm-gcc-4.2/branches/Apple/Dib/gcc/llvm-debug.h
Modified: llvm-gcc-4.2/branches/Apple/Dib/gcc/llvm-convert.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/branches/Apple/Dib/gcc/llvm-convert.cpp?rev=67055&r1=67054&r2=67055&view=diff
==============================================================================
--- llvm-gcc-4.2/branches/Apple/Dib/gcc/llvm-convert.cpp (original)
+++ llvm-gcc-4.2/branches/Apple/Dib/gcc/llvm-convert.cpp Mon Mar 16 17:45:54 2009
@@ -898,9 +898,6 @@
}
Function *TreeToLLVM::EmitFunction() {
- if (TheDebugInfo)
- TheDebugInfo->ClearVarCache();
-
// Set up parameters and prepare for return, for the function.
StartFunctionBody();
@@ -908,41 +905,12 @@
basic_block bb;
edge e;
edge_iterator ei;
- tree stmt_block = NULL_TREE;
FOR_EACH_BB (bb) {
for (block_stmt_iterator bsi = bsi_start (bb); !bsi_end_p (bsi);
bsi_next (&bsi)) {
MemRef DestLoc;
tree stmt = bsi_stmt (bsi);
- // FIXME : Optimizer and code generator are not doing the right thing yet
- // while dealing with variable's debug info locations.
- tree new_stmt_block = TREE_BLOCK (stmt);
- if (TheDebugInfo && new_stmt_block && !optimize) {
- if (stmt_block == NULL_TREE)
- // This is beginning of function. llvm.dbg.func.start is emitted so
- // no need to emit llvm.dbg.region.start here.
- stmt_block = new_stmt_block;
- else {
- if (stmt_block != new_stmt_block) {
- if (BLOCK_SUPERCONTEXT (new_stmt_block) == stmt_block)
- // Entering new scope. Emit llvm.dbg.func.start.
- TheDebugInfo->EmitRegionStart(Builder.GetInsertBlock());
- else if (BLOCK_SUPERCONTEXT (new_stmt_block) ==
- BLOCK_SUPERCONTEXT (stmt_block)) {
- // Entering new scope at the same level. End previous current
- // region by emitting llvm.dbg.region.end. And emit
- // llvm.dbg.region.start to start new region.
- TheDebugInfo->EmitRegionEnd(Builder.GetInsertBlock());
- TheDebugInfo->EmitRegionStart(Builder.GetInsertBlock());
- } else
- // Leaving current scop.e Emit llvm.dbg.region.end.
- TheDebugInfo->EmitRegionEnd(Builder.GetInsertBlock());
-
- stmt_block = new_stmt_block;
- }
- }
- }
-
+
// If this stmt returns an aggregate value (e.g. a call whose result is
// ignored), create a temporary to receive the value. Note that we don't
// do this for MODIFY_EXPRs as an efficiency hack.
@@ -1779,6 +1747,17 @@
Builder.CreateStore(Constant::getNullValue(T), AI);
}
+ if (TheDebugInfo) {
+ if (DECL_NAME(decl)) {
+ TheDebugInfo->EmitDeclare(decl, dwarf::DW_TAG_auto_variable,
+ Name, TREE_TYPE(decl), AI,
+ Builder.GetInsertBlock());
+ } else if (TREE_CODE(decl) == RESULT_DECL) {
+ TheDebugInfo->EmitDeclare(decl, dwarf::DW_TAG_return_variable,
+ Name, TREE_TYPE(decl), AI,
+ Builder.GetInsertBlock());
+ }
+ }
}
//===----------------------------------------------------------------------===//
@@ -5892,7 +5871,6 @@
//===----------------------------------------------------------------------===//
LValue TreeToLLVM::EmitLV_DECL(tree exp) {
-
if (TREE_CODE(exp) == PARM_DECL || TREE_CODE(exp) == VAR_DECL ||
TREE_CODE(exp) == CONST_DECL) {
// If a static var's type was incomplete when the decl was written,
@@ -5970,14 +5948,6 @@
Alignment = DECL_ALIGN(exp) / 8;
}
- if (TheDebugInfo) {
- if (DECL_NAME(exp))
- TheDebugInfo->EmitDeclare(exp, dwarf::DW_TAG_auto_variable,
- IDENTIFIER_POINTER (DECL_NAME (exp)),
- TREE_TYPE(exp), Decl,
- Builder.GetInsertBlock());
- }
-
return LValue(BitCastToType(Decl, PTy), Alignment);
}
Modified: llvm-gcc-4.2/branches/Apple/Dib/gcc/llvm-debug.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/branches/Apple/Dib/gcc/llvm-debug.cpp?rev=67055&r1=67054&r2=67055&view=diff
==============================================================================
--- llvm-gcc-4.2/branches/Apple/Dib/gcc/llvm-debug.cpp (original)
+++ llvm-gcc-4.2/branches/Apple/Dib/gcc/llvm-debug.cpp Mon Mar 16 17:45:54 2009
@@ -293,11 +293,6 @@
assert(!RegionStack.empty() && "Region stack mismatch, stack empty!");
- // Check to see if the compile unit already has created this type.
- llvm::DIVariable &Slot = VarCache[decl];
- if (!Slot.isNull())
- return;
-
expanded_location Loc = GetNodeLocation(decl, false);
// Construct variable.
@@ -306,8 +301,6 @@
getOrCreateCompileUnit(Loc.file),
Loc.line, getOrCreateType(type));
- VarCache[decl] = D;
-
// Insert an llvm.dbg.declare into the current block.
DebugFactory.InsertDeclare(AI, D, CurBB);
}
@@ -848,11 +841,6 @@
getOrCreateCompileUnit(main_input_filename, true);
}
-/// ClearDeclCache - Clear variable debug info cache.
-void DebugInfo::ClearVarCache() {
- VarCache.clear();
-}
-
/// getOrCreateCompileUnit - Get the compile unit from the cache or
/// create a new one if necessary.
DICompileUnit DebugInfo::getOrCreateCompileUnit(const char *FullPath,
Modified: llvm-gcc-4.2/branches/Apple/Dib/gcc/llvm-debug.h
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/branches/Apple/Dib/gcc/llvm-debug.h?rev=67055&r1=67054&r2=67055&view=diff
==============================================================================
--- llvm-gcc-4.2/branches/Apple/Dib/gcc/llvm-debug.h (original)
+++ llvm-gcc-4.2/branches/Apple/Dib/gcc/llvm-debug.h Mon Mar 16 17:45:54 2009
@@ -63,9 +63,6 @@
std::map TypeCache;
// Cache of previously constructed
// Types.
- std::map VarCache;
- // Cache of previously constructed
- // vars in this function.
std::vector RegionStack;
// Stack to track declarative scopes.
@@ -78,9 +75,6 @@
/// initialization is done.
void Initialize();
- /// ClearDeclCache - Clear variable debug info cache.
- void ClearVarCache();
-
// Accessors.
void setLocationFile(const char *FullPath) { CurFullPath = FullPath; }
void setLocationLine(int LineNo) { CurLineNo = LineNo; }
From dgregor at apple.com Mon Mar 16 17:53:26 2009
From: dgregor at apple.com (Douglas Gregor)
Date: Mon, 16 Mar 2009 22:53:26 -0000
Subject: [llvm-commits] [llvm] r67056 - in /llvm/trunk:
cmake/modules/AddPartiallyLinkedObject.cmake cmake/modules/LLVMConfig.cmake
tools/llvm-config/CMakeLists.txt
Message-ID: <200903162253.n2GMrQ8J029072@zion.cs.uiuc.edu>
Author: dgregor
Date: Mon Mar 16 17:53:26 2009
New Revision: 67056
URL: http://llvm.org/viewvc/llvm-project?rev=67056&view=rev
Log:
CMake: Build system fixes for XCode. llvm-config still causes us some serious trouble, but it's less serious than it used to be
Modified:
llvm/trunk/cmake/modules/AddPartiallyLinkedObject.cmake
llvm/trunk/cmake/modules/LLVMConfig.cmake
llvm/trunk/tools/llvm-config/CMakeLists.txt
Modified: llvm/trunk/cmake/modules/AddPartiallyLinkedObject.cmake
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/cmake/modules/AddPartiallyLinkedObject.cmake?rev=67056&r1=67055&r2=67056&view=diff
==============================================================================
--- llvm/trunk/cmake/modules/AddPartiallyLinkedObject.cmake (original)
+++ llvm/trunk/cmake/modules/AddPartiallyLinkedObject.cmake Mon Mar 16 17:53:26 2009
@@ -13,7 +13,7 @@
if( MSVC )
add_llvm_library( ${lib} ${ARGN})
else( MSVC )
- set(pll ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/${lib}.o)
+ set(pll ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}/${lib}.o)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/temp_lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/temp_lib)
llvm_process_sources( ALL_FILES ${ARGN} )
@@ -27,7 +27,7 @@
add_custom_command(OUTPUT ${pll}
COMMENT "Building ${lib}.o..."
DEPENDS ${lib}
- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/temp_lib
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/temp_lib/${CMAKE_CFG_INTDIR}
COMMAND ar x ${CMAKE_STATIC_LIBRARY_PREFIX}${lib}${CMAKE_STATIC_LIBRARY_SUFFIX}
COMMAND ${CMAKE_LINKER} "${LLVM_PLO_FLAGS}" -r "*${CMAKE_CXX_OUTPUT_EXTENSION}" -o ${pll}
COMMAND ${CMAKE_COMMAND} -E remove -f *${CMAKE_CXX_OUTPUT_EXTENSION}
Modified: llvm/trunk/cmake/modules/LLVMConfig.cmake
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/cmake/modules/LLVMConfig.cmake?rev=67056&r1=67055&r2=67056&view=diff
==============================================================================
--- llvm/trunk/cmake/modules/LLVMConfig.cmake (original)
+++ llvm/trunk/cmake/modules/LLVMConfig.cmake Mon Mar 16 17:53:26 2009
@@ -131,7 +131,7 @@
if(c MATCHES ".*\\.o")
get_filename_component(fn ${c} NAME)
target_link_libraries(${executable}
- ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/${fn})
+ ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}/${fn})
else(c MATCHES ".*\\.o")
string(REPLACE "-l" "" fn ${c})
target_link_libraries(${executable} ${fn})
Modified: llvm/trunk/tools/llvm-config/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-config/CMakeLists.txt?rev=67056&r1=67055&r2=67056&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-config/CMakeLists.txt (original)
+++ llvm/trunk/tools/llvm-config/CMakeLists.txt Mon Mar 16 17:53:26 2009
@@ -68,7 +68,7 @@
endif()
add_custom_command(OUTPUT ${LIBDEPS_TMP}
- COMMAND ${PERL_EXECUTABLE} ${LLVM_MAIN_SRC_DIR}/utils/GenLibDeps.pl -flat ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} ${NM_PATH} > ${LIBDEPS_TMP}
+ COMMAND ${PERL_EXECUTABLE} ${LLVM_MAIN_SRC_DIR}/utils/GenLibDeps.pl -flat ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR} ${NM_PATH} > ${LIBDEPS_TMP}
DEPENDS ${llvm_libs}
COMMENT "Regenerating ${LIBDEPS_TMP}")
From daniel at zuster.org Mon Mar 16 17:55:06 2009
From: daniel at zuster.org (Daniel Dunbar)
Date: Mon, 16 Mar 2009 22:55:06 -0000
Subject: [llvm-commits] [llvm] r67057 - in /llvm/trunk:
include/llvm/Support/raw_ostream.h lib/Support/raw_ostream.cpp
Message-ID: <200903162255.n2GMt7B4029182@zion.cs.uiuc.edu>
Author: ddunbar
Date: Mon Mar 16 17:55:06 2009
New Revision: 67057
URL: http://llvm.org/viewvc/llvm-project?rev=67057&view=rev
Log:
raw_ostream: Lift out flush_nonempty.
- Flush a known non-empty buffers; enforces the interface to
flush_impl and kills off HandleFlush (which I saw no reason to be
an inline method, Chris?).
- Clarify invariant that flush_impl is only called with OutBufCur >
OutBufStart.
- This also cleary collects all places where we have to deal with the
buffer possibly not existing.
- A few more comments and fixing the unbuffered behavior remain in
this commit sequence.
Modified:
llvm/trunk/include/llvm/Support/raw_ostream.h
llvm/trunk/lib/Support/raw_ostream.cpp
Modified: llvm/trunk/include/llvm/Support/raw_ostream.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/raw_ostream.h?rev=67057&r1=67056&r2=67057&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/raw_ostream.h (original)
+++ llvm/trunk/include/llvm/Support/raw_ostream.h Mon Mar 16 17:55:06 2009
@@ -31,6 +31,10 @@
/// a chunk at a time.
class raw_ostream {
protected:
+ /// \invariant { The buffer is uninitialized (OutBufStart,
+ /// OutBufEnd, and OutBufCur are non-zero), or none of them are zero
+ /// and there are at least 64 total bytes in the buffer. }
+
char *OutBufStart, *OutBufEnd, *OutBufCur;
bool Unbuffered;
@@ -77,7 +81,7 @@
void flush() {
if (OutBufCur != OutBufStart)
- flush_impl();
+ flush_nonempty();
}
raw_ostream &operator<<(char C) {
@@ -85,7 +89,7 @@
return write(C);
*OutBufCur++ = C;
if (Unbuffered)
- flush_impl();
+ flush_nonempty();
return *this;
}
@@ -94,7 +98,7 @@
return write(C);
*OutBufCur++ = C;
if (Unbuffered)
- flush_impl();
+ flush_nonempty();
return *this;
}
@@ -103,7 +107,7 @@
return write(C);
*OutBufCur++ = C;
if (Unbuffered)
- flush_impl();
+ flush_nonempty();
return *this;
}
@@ -142,23 +146,25 @@
// Subclass Interface
//===--------------------------------------------------------------------===//
-protected:
-
+private:
/// flush_impl - The is the piece of the class that is implemented by
- /// subclasses. This outputs the currently buffered data and resets the
- /// buffer to empty.
+ /// subclasses. This only outputs the currently buffered data.
+ ///
+ /// raw_ostream guarantees to only call this routine when there is
+ /// buffered data, i.e. OutBufStart != OutBufCur.
virtual void flush_impl() = 0;
- /// HandleFlush - A stream's implementation of flush should call this after
- /// emitting the bytes to the data sink.
- void HandleFlush() {
- if (OutBufStart == 0)
- SetBufferSize(4096);
- OutBufCur = OutBufStart;
- }
-private:
// An out of line virtual method to provide a home for the class vtable.
virtual void handle();
+
+ //===--------------------------------------------------------------------===//
+ // Private Interface
+ //===--------------------------------------------------------------------===//
+private:
+ /// flush_nonempty - Flush the current buffer, which is known to be
+ /// non-empty. This outputs the currently buffered data and resets
+ /// the buffer to empty.
+ void flush_nonempty();
};
//===----------------------------------------------------------------------===//
@@ -192,8 +198,10 @@
~raw_fd_ostream();
/// flush_impl - The is the piece of the class that is implemented by
- /// subclasses. This outputs the currently buffered data and resets the
- /// buffer to empty.
+ /// subclasses. This only outputs the currently buffered data.
+ ///
+ /// raw_ostream guarantees to only call this routine when there is
+ /// buffered data, i.e. OutBufStart != OutBufCur.
virtual void flush_impl();
/// close - Manually flush the stream and close the file.
@@ -249,8 +257,10 @@
~raw_os_ostream();
/// flush_impl - The is the piece of the class that is implemented by
- /// subclasses. This outputs the currently buffered data and resets the
- /// buffer to empty.
+ /// subclasses. This only outputs the currently buffered data.
+ ///
+ /// raw_ostream guarantees to only call this routine when there is
+ /// buffered data, i.e. OutBufStart != OutBufCur.
virtual void flush_impl();
};
@@ -270,8 +280,10 @@
}
/// flush_impl - The is the piece of the class that is implemented by
- /// subclasses. This outputs the currently buffered data and resets the
- /// buffer to empty.
+ /// subclasses. This only outputs the currently buffered data.
+ ///
+ /// raw_ostream guarantees to only call this routine when there is
+ /// buffered data, i.e. OutBufStart != OutBufCur.
virtual void flush_impl();
};
@@ -284,8 +296,10 @@
~raw_svector_ostream();
/// flush_impl - The is the piece of the class that is implemented by
- /// subclasses. This outputs the currently buffered data and resets the
- /// buffer to empty.
+ /// subclasses. This only outputs the currently buffered data.
+ ///
+ /// raw_ostream guarantees to only call this routine when there is
+ /// buffered data, i.e. OutBufStart != OutBufCur.
virtual void flush_impl();
};
Modified: llvm/trunk/lib/Support/raw_ostream.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/raw_ostream.cpp?rev=67057&r1=67056&r2=67057&view=diff
==============================================================================
--- llvm/trunk/lib/Support/raw_ostream.cpp (original)
+++ llvm/trunk/lib/Support/raw_ostream.cpp Mon Mar 16 17:55:06 2009
@@ -116,17 +116,27 @@
return write(CurPtr, EndPtr-CurPtr);
}
+void raw_ostream::flush_nonempty() {
+ assert(OutBufCur > OutBufStart && "Invalid call to flush_nonempty.");
+ flush_impl();
+ OutBufCur = OutBufStart;
+}
+
raw_ostream &raw_ostream::write(unsigned char C) {
- if (OutBufCur >= OutBufEnd)
- flush_impl();
+ if (!OutBufStart)
+ SetBufferSize(4096);
+ else if (OutBufCur >= OutBufEnd)
+ flush_nonempty();
*OutBufCur++ = C;
return *this;
}
raw_ostream &raw_ostream::write(const char *Ptr, unsigned Size) {
- if (OutBufCur+Size > OutBufEnd)
- flush_impl();
+ if (!OutBufStart)
+ SetBufferSize(4096);
+ else if (OutBufCur+Size > OutBufEnd)
+ flush_nonempty();
// Handle short strings specially, memcpy isn't very good at very short
// strings.
@@ -153,14 +163,14 @@
Ptr += NumToEmit;
Size -= NumToEmit;
OutBufCur = OutBufStart + NumToEmit;
- flush_impl();
+ flush_nonempty();
}
break;
}
OutBufCur += Size;
if (Unbuffered)
- flush_impl();
+ flush();
return *this;
}
@@ -260,11 +270,8 @@
void raw_fd_ostream::flush_impl() {
assert (FD >= 0 && "File already closed.");
- if (OutBufCur-OutBufStart) {
- pos += (OutBufCur - OutBufStart);
- ::write(FD, OutBufStart, OutBufCur-OutBufStart);
- }
- HandleFlush();
+ pos += (OutBufCur - OutBufStart);
+ ::write(FD, OutBufStart, OutBufCur-OutBufStart);
}
void raw_fd_ostream::close() {
@@ -319,9 +326,7 @@
/// subclasses. This outputs the currently buffered data and resets the
/// buffer to empty.
void raw_os_ostream::flush_impl() {
- if (OutBufCur-OutBufStart)
- OS.write(OutBufStart, OutBufCur-OutBufStart);
- HandleFlush();
+ OS.write(OutBufStart, OutBufCur-OutBufStart);
}
//===----------------------------------------------------------------------===//
@@ -336,9 +341,7 @@
/// subclasses. This outputs the currently buffered data and resets the
/// buffer to empty.
void raw_string_ostream::flush_impl() {
- if (OutBufCur-OutBufStart)
- OS.append(OutBufStart, OutBufCur-OutBufStart);
- HandleFlush();
+ OS.append(OutBufStart, OutBufCur-OutBufStart);
}
//===----------------------------------------------------------------------===//
@@ -353,8 +356,6 @@
/// subclasses. This outputs the currently buffered data and resets the
/// buffer to empty.
void raw_svector_ostream::flush_impl() {
- if (OutBufCur-OutBufStart)
- OS.append(OutBufStart, OutBufCur);
- HandleFlush();
+ OS.append(OutBufStart, OutBufCur);
}
From daniel at zuster.org Mon Mar 16 18:29:32 2009
From: daniel at zuster.org (Daniel Dunbar)
Date: Mon, 16 Mar 2009 23:29:32 -0000
Subject: [llvm-commits] [llvm] r67060 - in /llvm/trunk:
include/llvm/Support/raw_ostream.h lib/Support/raw_ostream.cpp
Message-ID: <200903162329.n2GNTWl3030433@zion.cs.uiuc.edu>
Author: ddunbar
Date: Mon Mar 16 18:29:31 2009
New Revision: 67060
URL: http://llvm.org/viewvc/llvm-project?rev=67060&view=rev
Log:
raw_ostream: Replace flush_impl with write_impl, which takes data to
write as arguments.
- Add raw_ostream::GetNumBytesInBuffer.
- Privatize buffer pointers.
- Get rid of slow and unnecessary code for writing out large strings.
Modified:
llvm/trunk/include/llvm/Support/raw_ostream.h
llvm/trunk/lib/Support/raw_ostream.cpp
Modified: llvm/trunk/include/llvm/Support/raw_ostream.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/raw_ostream.h?rev=67060&r1=67059&r2=67060&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/raw_ostream.h (original)
+++ llvm/trunk/include/llvm/Support/raw_ostream.h Mon Mar 16 18:29:31 2009
@@ -30,7 +30,7 @@
/// rewinding, line buffered disciplines etc. It is a simple buffer that outputs
/// a chunk at a time.
class raw_ostream {
-protected:
+private:
/// \invariant { The buffer is uninitialized (OutBufStart,
/// OutBufEnd, and OutBufCur are non-zero), or none of them are zero
/// and there are at least 64 total bytes in the buffer. }
@@ -75,6 +75,10 @@
flush();
}
+ unsigned GetNumBytesInBuffer() const {
+ return OutBufCur - OutBufStart;
+ }
+
//===--------------------------------------------------------------------===//
// Data Output Interface
//===--------------------------------------------------------------------===//
@@ -147,12 +151,12 @@
//===--------------------------------------------------------------------===//
private:
- /// flush_impl - The is the piece of the class that is implemented by
- /// subclasses. This only outputs the currently buffered data.
- ///
- /// raw_ostream guarantees to only call this routine when there is
- /// buffered data, i.e. OutBufStart != OutBufCur.
- virtual void flush_impl() = 0;
+ /// write_impl - The is the piece of the class that is implemented
+ /// by subclasses. This writes the \args Size bytes starting at
+ /// \arg Ptr to the underlying stream.
+ ///
+ /// \invariant { Size > 0 }
+ virtual void write_impl(const char *Ptr, unsigned Size) = 0;
// An out of line virtual method to provide a home for the class vtable.
virtual void handle();
@@ -177,6 +181,9 @@
int FD;
bool ShouldClose;
uint64_t pos;
+
+ /// write_impl - See raw_ostream::write_impl.
+ virtual void write_impl(const char *Ptr, unsigned Size);
public:
/// raw_fd_ostream - Open the specified file for writing. If an
/// error occurs, information about the error is put into ErrorInfo,
@@ -197,20 +204,11 @@
~raw_fd_ostream();
- /// flush_impl - The is the piece of the class that is implemented by
- /// subclasses. This only outputs the currently buffered data.
- ///
- /// raw_ostream guarantees to only call this routine when there is
- /// buffered data, i.e. OutBufStart != OutBufCur.
- virtual void flush_impl();
-
/// close - Manually flush the stream and close the file.
void close();
/// tell - Return the current offset with the file.
- uint64_t tell() {
- return pos + (OutBufCur - OutBufStart);
- }
+ uint64_t tell() { return pos + GetNumBytesInBuffer(); }
/// seek - Flushes the stream and repositions the underlying file descriptor
/// positition to the offset specified from the beginning of the file.
@@ -252,22 +250,21 @@
/// simple adaptor class.
class raw_os_ostream : public raw_ostream {
std::ostream &OS;
+
+ /// write_impl - See raw_ostream::write_impl.
+ virtual void write_impl(const char *Ptr, unsigned Size);
public:
raw_os_ostream(std::ostream &O) : OS(O) {}
~raw_os_ostream();
-
- /// flush_impl - The is the piece of the class that is implemented by
- /// subclasses. This only outputs the currently buffered data.
- ///
- /// raw_ostream guarantees to only call this routine when there is
- /// buffered data, i.e. OutBufStart != OutBufCur.
- virtual void flush_impl();
};
/// raw_string_ostream - A raw_ostream that writes to an std::string. This is a
/// simple adaptor class.
class raw_string_ostream : public raw_ostream {
std::string &OS;
+
+ /// write_impl - See raw_ostream::write_impl.
+ virtual void write_impl(const char *Ptr, unsigned Size);
public:
raw_string_ostream(std::string &O) : OS(O) {}
~raw_string_ostream();
@@ -278,29 +275,18 @@
flush();
return OS;
}
-
- /// flush_impl - The is the piece of the class that is implemented by
- /// subclasses. This only outputs the currently buffered data.
- ///
- /// raw_ostream guarantees to only call this routine when there is
- /// buffered data, i.e. OutBufStart != OutBufCur.
- virtual void flush_impl();
};
/// raw_svector_ostream - A raw_ostream that writes to an SmallVector or
/// SmallString. This is a simple adaptor class.
class raw_svector_ostream : public raw_ostream {
SmallVectorImpl &OS;
+
+ /// write_impl - See raw_ostream::write_impl.
+ virtual void write_impl(const char *Ptr, unsigned Size);
public:
raw_svector_ostream(SmallVectorImpl &O) : OS(O) {}
~raw_svector_ostream();
-
- /// flush_impl - The is the piece of the class that is implemented by
- /// subclasses. This only outputs the currently buffered data.
- ///
- /// raw_ostream guarantees to only call this routine when there is
- /// buffered data, i.e. OutBufStart != OutBufCur.
- virtual void flush_impl();
};
} // end llvm namespace
Modified: llvm/trunk/lib/Support/raw_ostream.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/raw_ostream.cpp?rev=67060&r1=67059&r2=67060&view=diff
==============================================================================
--- llvm/trunk/lib/Support/raw_ostream.cpp (original)
+++ llvm/trunk/lib/Support/raw_ostream.cpp Mon Mar 16 18:29:31 2009
@@ -118,7 +118,7 @@
void raw_ostream::flush_nonempty() {
assert(OutBufCur > OutBufStart && "Invalid call to flush_nonempty.");
- flush_impl();
+ write_impl(OutBufStart, OutBufCur - OutBufStart);
OutBufCur = OutBufStart;
}
@@ -151,20 +151,12 @@
if (Size <= unsigned(OutBufEnd-OutBufStart)) {
memcpy(OutBufCur, Ptr, Size);
break;
- }
+ }
- // If emitting a string larger than our buffer, emit in chunks. In this
- // case we know that we just flushed the buffer.
- while (Size) {
- unsigned NumToEmit = OutBufEnd-OutBufStart;
- if (Size < NumToEmit) NumToEmit = Size;
- assert(OutBufCur == OutBufStart);
- memcpy(OutBufStart, Ptr, NumToEmit);
- Ptr += NumToEmit;
- Size -= NumToEmit;
- OutBufCur = OutBufStart + NumToEmit;
- flush_nonempty();
- }
+ // Otherwise we are emitting a string larger than our buffer. We
+ // know we already flushed, so just write it out directly.
+ write_impl(Ptr, Size);
+ Size = 0;
break;
}
OutBufCur += Size;
@@ -268,10 +260,10 @@
}
}
-void raw_fd_ostream::flush_impl() {
+void raw_fd_ostream::write_impl(const char *Ptr, unsigned Size) {
assert (FD >= 0 && "File already closed.");
- pos += (OutBufCur - OutBufStart);
- ::write(FD, OutBufStart, OutBufCur-OutBufStart);
+ pos += Size;
+ ::write(FD, Ptr, Size);
}
void raw_fd_ostream::close() {
@@ -322,11 +314,8 @@
flush();
}
-/// flush_impl - The is the piece of the class that is implemented by
-/// subclasses. This outputs the currently buffered data and resets the
-/// buffer to empty.
-void raw_os_ostream::flush_impl() {
- OS.write(OutBufStart, OutBufCur-OutBufStart);
+void raw_os_ostream::write_impl(const char *Ptr, unsigned Size) {
+ OS.write(Ptr, Size);
}
//===----------------------------------------------------------------------===//
@@ -337,11 +326,8 @@
flush();
}
-/// flush_impl - The is the piece of the class that is implemented by
-/// subclasses. This outputs the currently buffered data and resets the
-/// buffer to empty.
-void raw_string_ostream::flush_impl() {
- OS.append(OutBufStart, OutBufCur-OutBufStart);
+void raw_string_ostream::write_impl(const char *Ptr, unsigned Size) {
+ OS.append(Ptr, Size);
}
//===----------------------------------------------------------------------===//
@@ -352,10 +338,7 @@
flush();
}
-/// flush_impl - The is the piece of the class that is implemented by
-/// subclasses. This outputs the currently buffered data and resets the
-/// buffer to empty.
-void raw_svector_ostream::flush_impl() {
- OS.append(OutBufStart, OutBufCur);
+void raw_svector_ostream::write_impl(const char *Ptr, unsigned Size) {
+ OS.append(Ptr, Ptr + Size);
}
From dalej at apple.com Mon Mar 16 19:38:25 2009
From: dalej at apple.com (Dale Johannesen)
Date: Tue, 17 Mar 2009 00:38:25 -0000
Subject: [llvm-commits] [llvm] r67064 -
/llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp
Message-ID: <200903170038.n2H0cPnf000398@zion.cs.uiuc.edu>
Author: johannes
Date: Mon Mar 16 19:38:24 2009
New Revision: 67064
URL: http://llvm.org/viewvc/llvm-project?rev=67064&view=rev
Log:
Fix a debug info dependency in jump threading.
Modified:
llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp
Modified: llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp?rev=67064&r1=67063&r2=67064&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp Mon Mar 16 19:38:24 2009
@@ -432,10 +432,13 @@
// If DESTBB *just* contains the switch, then we can forward edges from PREDBB
// directly to their destination. This does not introduce *any* code size
- // growth.
+ // growth. Skip debug info first.
+ BasicBlock::iterator BBI = DestBB->begin();
+ while (isa(BBI))
+ BBI++;
// FIXME: Thread if it just contains a PHI.
- if (isa(DestBB->begin())) {
+ if (isa(BBI)) {
bool MadeChange = false;
// Ignore the default edge for now.
for (unsigned i = 1, e = DestSI->getNumSuccessors(); i != e; ++i) {
From isanbard at gmail.com Mon Mar 16 19:48:33 2009
From: isanbard at gmail.com (Bill Wendling)
Date: Tue, 17 Mar 2009 00:48:33 -0000
Subject: [llvm-commits] [llvm] r67065 -
/llvm/branches/Apple/Dib/lib/Transforms/Scalar/JumpThreading.cpp
Message-ID: <200903170048.n2H0mXfg000853@zion.cs.uiuc.edu>
Author: void
Date: Mon Mar 16 19:48:33 2009
New Revision: 67065
URL: http://llvm.org/viewvc/llvm-project?rev=67065&view=rev
Log:
--- Merging (from foreign repository) r67064 into '.':
U lib/Transforms/Scalar/JumpThreading.cpp
Fix a debug info dependency in jump threading.
Modified:
llvm/branches/Apple/Dib/lib/Transforms/Scalar/JumpThreading.cpp
Modified: llvm/branches/Apple/Dib/lib/Transforms/Scalar/JumpThreading.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Dib/lib/Transforms/Scalar/JumpThreading.cpp?rev=67065&r1=67064&r2=67065&view=diff
==============================================================================
--- llvm/branches/Apple/Dib/lib/Transforms/Scalar/JumpThreading.cpp (original)
+++ llvm/branches/Apple/Dib/lib/Transforms/Scalar/JumpThreading.cpp Mon Mar 16 19:48:33 2009
@@ -432,10 +432,13 @@
// If DESTBB *just* contains the switch, then we can forward edges from PREDBB
// directly to their destination. This does not introduce *any* code size
- // growth.
+ // growth. Skip debug info first.
+ BasicBlock::iterator BBI = DestBB->begin();
+ while (isa(BBI))
+ BBI++;
// FIXME: Thread if it just contains a PHI.
- if (isa(DestBB->begin())) {
+ if (isa(BBI)) {
bool MadeChange = false;
// Ignore the default edge for now.
for (unsigned i = 1, e = DestSI->getNumSuccessors(); i != e; ++i) {
From daniel at zuster.org Mon Mar 16 20:13:35 2009
From: daniel at zuster.org (Daniel Dunbar)
Date: Tue, 17 Mar 2009 01:13:35 -0000
Subject: [llvm-commits] [llvm] r67066 - in /llvm/trunk:
include/llvm/Support/raw_ostream.h lib/Support/raw_ostream.cpp
Message-ID: <200903170113.n2H1DaUH001958@zion.cs.uiuc.edu>
Author: ddunbar
Date: Mon Mar 16 20:13:35 2009
New Revision: 67066
URL: http://llvm.org/viewvc/llvm-project?rev=67066&view=rev
Log:
raw_ostream: Rework implementation of unbuffered streams so outputting
a single character requires only one branch to follow slow path.
- Never use a buffer when writing on an unbuffered stream.
- Move default buffer size to header.
Modified:
llvm/trunk/include/llvm/Support/raw_ostream.h
llvm/trunk/lib/Support/raw_ostream.cpp
Modified: llvm/trunk/include/llvm/Support/raw_ostream.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/raw_ostream.h?rev=67066&r1=67065&r2=67066&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/raw_ostream.h (original)
+++ llvm/trunk/include/llvm/Support/raw_ostream.h Mon Mar 16 20:13:35 2009
@@ -31,10 +31,16 @@
/// a chunk at a time.
class raw_ostream {
private:
- /// \invariant { The buffer is uninitialized (OutBufStart,
- /// OutBufEnd, and OutBufCur are non-zero), or none of them are zero
- /// and there are at least 64 total bytes in the buffer. }
-
+ /// The buffer is handled in such a way that the buffer is
+ /// uninitialized, unbuffered, or out of space when OutBufCur >=
+ /// OutBufEnd. Thus a single comparison suffices to determine if we
+ /// need to take the slow path to write a single character.
+ ///
+ /// The buffer is in one of three states:
+ /// 1. Unbuffered (Unbuffered == true)
+ /// 1. Uninitialized (Unbuffered == false && OutBufStart == 0).
+ /// 2. Buffered (Unbuffered == false && OutBufStart != 0 &&
+ /// OutBufEnd - OutBufStart >= 64).
char *OutBufStart, *OutBufEnd, *OutBufCur;
bool Unbuffered;
@@ -54,7 +60,7 @@
/// SetBufferSize - Set the internal buffer size to the specified amount
/// instead of the default.
- void SetBufferSize(unsigned Size) {
+ void SetBufferSize(unsigned Size=4096) {
assert(Size >= 64 &&
"Buffer size must be somewhat large for invariants to hold");
flush();
@@ -63,16 +69,19 @@
OutBufStart = new char[Size];
OutBufEnd = OutBufStart+Size;
OutBufCur = OutBufStart;
+ Unbuffered = false;
}
/// SetUnbuffered - Set the streams buffering status. When
/// unbuffered the stream will flush after every write. This routine
/// will also flush the buffer immediately when the stream is being
/// set to unbuffered.
- void SetUnbuffered(bool unbuffered) {
- Unbuffered = unbuffered;
- if (Unbuffered)
- flush();
+ void SetUnbuffered() {
+ flush();
+
+ delete [] OutBufStart;
+ OutBufStart = OutBufEnd = OutBufCur = 0;
+ Unbuffered = true;
}
unsigned GetNumBytesInBuffer() const {
@@ -92,8 +101,6 @@
if (OutBufCur >= OutBufEnd)
return write(C);
*OutBufCur++ = C;
- if (Unbuffered)
- flush_nonempty();
return *this;
}
@@ -101,8 +108,6 @@
if (OutBufCur >= OutBufEnd)
return write(C);
*OutBufCur++ = C;
- if (Unbuffered)
- flush_nonempty();
return *this;
}
@@ -110,8 +115,6 @@
if (OutBufCur >= OutBufEnd)
return write(C);
*OutBufCur++ = C;
- if (Unbuffered)
- flush_nonempty();
return *this;
}
Modified: llvm/trunk/lib/Support/raw_ostream.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/raw_ostream.cpp?rev=67066&r1=67065&r2=67066&view=diff
==============================================================================
--- llvm/trunk/lib/Support/raw_ostream.cpp (original)
+++ llvm/trunk/lib/Support/raw_ostream.cpp Mon Mar 16 20:13:35 2009
@@ -123,8 +123,13 @@
}
raw_ostream &raw_ostream::write(unsigned char C) {
+ if (Unbuffered) {
+ write_impl(reinterpret_cast(&C), 1);
+ return *this;
+ }
+
if (!OutBufStart)
- SetBufferSize(4096);
+ SetBufferSize();
else if (OutBufCur >= OutBufEnd)
flush_nonempty();
@@ -133,8 +138,13 @@
}
raw_ostream &raw_ostream::write(const char *Ptr, unsigned Size) {
+ if (Unbuffered) {
+ write_impl(Ptr, Size);
+ return *this;
+ }
+
if (!OutBufStart)
- SetBufferSize(4096);
+ SetBufferSize();
else if (OutBufCur+Size > OutBufEnd)
flush_nonempty();
@@ -161,8 +171,6 @@
}
OutBufCur += Size;
- if (Unbuffered)
- flush();
return *this;
}
From scottm at aero.org Mon Mar 16 20:15:46 2009
From: scottm at aero.org (Scott Michel)
Date: Tue, 17 Mar 2009 01:15:46 -0000
Subject: [llvm-commits] [llvm] r67067 - in /llvm/trunk:
lib/Target/CellSPU/SPUISelDAGToDAG.cpp
lib/Target/CellSPU/SPUISelLowering.cpp lib/Target/CellSPU/SPUISelLowering.h
lib/Target/CellSPU/SPUInstrInfo.cpp lib/Target/CellSPU/SPUInstrInfo.td
test/CodeGen/CellSPU/2009-01-01-BrCond.ll test/CodeGen/CellSPU/fneg-fabs.ll
Message-ID: <200903170115.n2H1Fkfp002036@zion.cs.uiuc.edu>
Author: pingbak
Date: Mon Mar 16 20:15:45 2009
New Revision: 67067
URL: http://llvm.org/viewvc/llvm-project?rev=67067&view=rev
Log:
CellSPU:
- Fix fabs, fneg for f32 and f64.
- Use BuildVectorSDNode.isConstantSplat, now that the functionality exists
- Continue to improve i64 constant lowering. Lower certain special constants
to the constant pool when they correspond to SPU's shufb instruction's
special mask values. This avoids the overhead of performing a shuffle on a
zero-filled vector just to get the special constant when the memory load
suffices.
Modified:
llvm/trunk/lib/Target/CellSPU/SPUISelDAGToDAG.cpp
llvm/trunk/lib/Target/CellSPU/SPUISelLowering.cpp
llvm/trunk/lib/Target/CellSPU/SPUISelLowering.h
llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.cpp
llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.td
llvm/trunk/test/CodeGen/CellSPU/2009-01-01-BrCond.ll
llvm/trunk/test/CodeGen/CellSPU/fneg-fabs.ll
Modified: llvm/trunk/lib/Target/CellSPU/SPUISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/CellSPU/SPUISelDAGToDAG.cpp?rev=67067&r1=67066&r2=67067&view=diff
==============================================================================
--- llvm/trunk/lib/Target/CellSPU/SPUISelDAGToDAG.cpp (original)
+++ llvm/trunk/lib/Target/CellSPU/SPUISelDAGToDAG.cpp Mon Mar 16 20:15:45 2009
@@ -200,182 +200,212 @@
return retval;
}
-}
-namespace {
+ //! Generate the carry-generate shuffle mask.
+ SDValue getCarryGenerateShufMask(SelectionDAG &DAG, DebugLoc dl) {
+ SmallVector ShufBytes;
+
+ // Create the shuffle mask for "rotating" the borrow up one register slot
+ // once the borrow is generated.
+ ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
+ ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
+ ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
+ ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
-//===--------------------------------------------------------------------===//
-/// SPUDAGToDAGISel - Cell SPU-specific code to select SPU machine
-/// instructions for SelectionDAG operations.
-///
-class SPUDAGToDAGISel :
- public SelectionDAGISel
-{
- SPUTargetMachine &TM;
- SPUTargetLowering &SPUtli;
- unsigned GlobalBaseReg;
-
-public:
- explicit SPUDAGToDAGISel(SPUTargetMachine &tm) :
- SelectionDAGISel(tm),
- TM(tm),
- SPUtli(*tm.getTargetLowering())
- { }
-
- virtual bool runOnFunction(Function &Fn) {
- // Make sure we re-emit a set of the global base reg if necessary
- GlobalBaseReg = 0;
- SelectionDAGISel::runOnFunction(Fn);
- return true;
+ return DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
+ &ShufBytes[0], ShufBytes.size());
}
- /// getI32Imm - Return a target constant with the specified value, of type
- /// i32.
- inline SDValue getI32Imm(uint32_t Imm) {
- return CurDAG->getTargetConstant(Imm, MVT::i32);
- }
-
- /// getI64Imm - Return a target constant with the specified value, of type
- /// i64.
- inline SDValue getI64Imm(uint64_t Imm) {
- return CurDAG->getTargetConstant(Imm, MVT::i64);
- }
-
- /// getSmallIPtrImm - Return a target constant of pointer type.
- inline SDValue getSmallIPtrImm(unsigned Imm) {
- return CurDAG->getTargetConstant(Imm, SPUtli.getPointerTy());
- }
-
- SDNode *emitBuildVector(SDValue build_vec) {
- MVT vecVT = build_vec.getValueType();
- SDNode *bvNode = build_vec.getNode();
- DebugLoc dl = bvNode->getDebugLoc();
-
- // Check to see if this vector can be represented as a CellSPU immediate
- // constant by invoking all of the instruction selection predicates:
- if (((vecVT == MVT::v8i16) &&
- (SPU::get_vec_i16imm(bvNode, *CurDAG, MVT::i16).getNode() != 0)) ||
- ((vecVT == MVT::v4i32) &&
- ((SPU::get_vec_i16imm(bvNode, *CurDAG, MVT::i32).getNode() != 0) ||
- (SPU::get_ILHUvec_imm(bvNode, *CurDAG, MVT::i32).getNode() != 0) ||
- (SPU::get_vec_u18imm(bvNode, *CurDAG, MVT::i32).getNode() != 0) ||
- (SPU::get_v4i32_imm(bvNode, *CurDAG).getNode() != 0))) ||
- ((vecVT == MVT::v2i64) &&
- ((SPU::get_vec_i16imm(bvNode, *CurDAG, MVT::i64).getNode() != 0) ||
- (SPU::get_ILHUvec_imm(bvNode, *CurDAG, MVT::i64).getNode() != 0) ||
- (SPU::get_vec_u18imm(bvNode, *CurDAG, MVT::i64).getNode() != 0))))
- return Select(build_vec);
-
- // No, need to emit a constant pool spill:
- std::vector CV;
-
- for (size_t i = 0; i < build_vec.getNumOperands(); ++i) {
- ConstantSDNode *V = dyn_cast (build_vec.getOperand(i));
- CV.push_back(const_cast (V->getConstantIntValue()));
- }
-
- Constant *CP = ConstantVector::get(CV);
- SDValue CPIdx = CurDAG->getConstantPool(CP, SPUtli.getPointerTy());
- unsigned Alignment = cast(CPIdx)->getAlignment();
- SDValue CGPoolOffset =
- SPU::LowerConstantPool(CPIdx, *CurDAG,
- SPUtli.getSPUTargetMachine());
- return SelectCode(CurDAG->getLoad(build_vec.getValueType(), dl,
- CurDAG->getEntryNode(), CGPoolOffset,
- PseudoSourceValue::getConstantPool(), 0,
- false, Alignment));
- }
-
- /// Select - Convert the specified operand from a target-independent to a
- /// target-specific node if it hasn't already been changed.
- SDNode *Select(SDValue Op);
-
- //! Emit the instruction sequence for i64 shl
- SDNode *SelectSHLi64(SDValue &Op, MVT OpVT);
-
- //! Emit the instruction sequence for i64 srl
- SDNode *SelectSRLi64(SDValue &Op, MVT OpVT);
-
- //! Emit the instruction sequence for i64 sra
- SDNode *SelectSRAi64(SDValue &Op, MVT OpVT);
-
- //! Emit the necessary sequence for loading i64 constants:
- SDNode *SelectI64Constant(SDValue &Op, MVT OpVT);
-
- //! Returns true if the address N is an A-form (local store) address
- bool SelectAFormAddr(SDValue Op, SDValue N, SDValue &Base,
- SDValue &Index);
-
- //! D-form address predicate
- bool SelectDFormAddr(SDValue Op, SDValue N, SDValue &Base,
- SDValue &Index);
-
- /// Alternate D-form address using i7 offset predicate
- bool SelectDForm2Addr(SDValue Op, SDValue N, SDValue &Disp,
- SDValue &Base);
-
- /// D-form address selection workhorse
- bool DFormAddressPredicate(SDValue Op, SDValue N, SDValue &Disp,
- SDValue &Base, int minOffset, int maxOffset);
-
- //! Address predicate if N can be expressed as an indexed [r+r] operation.
- bool SelectXFormAddr(SDValue Op, SDValue N, SDValue &Base,
- SDValue &Index);
-
- /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
- /// inline asm expressions.
- virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op,
- char ConstraintCode,
- std::vector &OutOps) {
- SDValue Op0, Op1;
- switch (ConstraintCode) {
- default: return true;
- case 'm': // memory
- if (!SelectDFormAddr(Op, Op, Op0, Op1)
- && !SelectAFormAddr(Op, Op, Op0, Op1))
- SelectXFormAddr(Op, Op, Op0, Op1);
- break;
- case 'o': // offsetable
- if (!SelectDFormAddr(Op, Op, Op0, Op1)
- && !SelectAFormAddr(Op, Op, Op0, Op1)) {
- Op0 = Op;
- Op1 = getSmallIPtrImm(0);
+ //! Generate the borrow-generate shuffle mask
+ SDValue getBorrowGenerateShufMask(SelectionDAG &DAG, DebugLoc dl) {
+ SmallVector ShufBytes;
+
+ // Create the shuffle mask for "rotating" the borrow up one register slot
+ // once the borrow is generated.
+ ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
+ ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
+ ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
+ ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
+
+ return DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
+ &ShufBytes[0], ShufBytes.size());
+ }
+
+ //===------------------------------------------------------------------===//
+ /// SPUDAGToDAGISel - Cell SPU-specific code to select SPU machine
+ /// instructions for SelectionDAG operations.
+ ///
+ class SPUDAGToDAGISel :
+ public SelectionDAGISel
+ {
+ SPUTargetMachine &TM;
+ SPUTargetLowering &SPUtli;
+ unsigned GlobalBaseReg;
+
+ public:
+ explicit SPUDAGToDAGISel(SPUTargetMachine &tm) :
+ SelectionDAGISel(tm),
+ TM(tm),
+ SPUtli(*tm.getTargetLowering())
+ { }
+
+ virtual bool runOnFunction(Function &Fn) {
+ // Make sure we re-emit a set of the global base reg if necessary
+ GlobalBaseReg = 0;
+ SelectionDAGISel::runOnFunction(Fn);
+ return true;
+ }
+
+ /// getI32Imm - Return a target constant with the specified value, of type
+ /// i32.
+ inline SDValue getI32Imm(uint32_t Imm) {
+ return CurDAG->getTargetConstant(Imm, MVT::i32);
+ }
+
+ /// getI64Imm - Return a target constant with the specified value, of type
+ /// i64.
+ inline SDValue getI64Imm(uint64_t Imm) {
+ return CurDAG->getTargetConstant(Imm, MVT::i64);
+ }
+
+ /// getSmallIPtrImm - Return a target constant of pointer type.
+ inline SDValue getSmallIPtrImm(unsigned Imm) {
+ return CurDAG->getTargetConstant(Imm, SPUtli.getPointerTy());
}
- break;
- case 'v': // not offsetable
+
+ SDNode *emitBuildVector(SDValue build_vec) {
+ MVT vecVT = build_vec.getValueType();
+ MVT eltVT = vecVT.getVectorElementType();
+ SDNode *bvNode = build_vec.getNode();
+ DebugLoc dl = bvNode->getDebugLoc();
+
+ // Check to see if this vector can be represented as a CellSPU immediate
+ // constant by invoking all of the instruction selection predicates:
+ if (((vecVT == MVT::v8i16) &&
+ (SPU::get_vec_i16imm(bvNode, *CurDAG, MVT::i16).getNode() != 0)) ||
+ ((vecVT == MVT::v4i32) &&
+ ((SPU::get_vec_i16imm(bvNode, *CurDAG, MVT::i32).getNode() != 0) ||
+ (SPU::get_ILHUvec_imm(bvNode, *CurDAG, MVT::i32).getNode() != 0) ||
+ (SPU::get_vec_u18imm(bvNode, *CurDAG, MVT::i32).getNode() != 0) ||
+ (SPU::get_v4i32_imm(bvNode, *CurDAG).getNode() != 0))) ||
+ ((vecVT == MVT::v2i64) &&
+ ((SPU::get_vec_i16imm(bvNode, *CurDAG, MVT::i64).getNode() != 0) ||
+ (SPU::get_ILHUvec_imm(bvNode, *CurDAG, MVT::i64).getNode() != 0) ||
+ (SPU::get_vec_u18imm(bvNode, *CurDAG, MVT::i64).getNode() != 0))))
+ return Select(build_vec);
+
+ // No, need to emit a constant pool spill:
+ std::vector CV;
+
+ for (size_t i = 0; i < build_vec.getNumOperands(); ++i) {
+ ConstantSDNode *V = dyn_cast (build_vec.getOperand(i));
+ CV.push_back(const_cast (V->getConstantIntValue()));
+ }
+
+ Constant *CP = ConstantVector::get(CV);
+ SDValue CPIdx = CurDAG->getConstantPool(CP, SPUtli.getPointerTy());
+ unsigned Alignment = cast(CPIdx)->getAlignment();
+ SDValue CGPoolOffset =
+ SPU::LowerConstantPool(CPIdx, *CurDAG,
+ SPUtli.getSPUTargetMachine());
+ return SelectCode(CurDAG->getLoad(build_vec.getValueType(), dl,
+ CurDAG->getEntryNode(), CGPoolOffset,
+ PseudoSourceValue::getConstantPool(), 0,
+ false, Alignment));
+ }
+
+ /// Select - Convert the specified operand from a target-independent to a
+ /// target-specific node if it hasn't already been changed.
+ SDNode *Select(SDValue Op);
+
+ //! Emit the instruction sequence for i64 shl
+ SDNode *SelectSHLi64(SDValue &Op, MVT OpVT);
+
+ //! Emit the instruction sequence for i64 srl
+ SDNode *SelectSRLi64(SDValue &Op, MVT OpVT);
+
+ //! Emit the instruction sequence for i64 sra
+ SDNode *SelectSRAi64(SDValue &Op, MVT OpVT);
+
+ //! Emit the necessary sequence for loading i64 constants:
+ SDNode *SelectI64Constant(SDValue &Op, MVT OpVT, DebugLoc dl);
+
+ //! Alternate instruction emit sequence for loading i64 constants
+ SDNode *SelectI64Constant(uint64_t i64const, MVT OpVT, DebugLoc dl);
+
+ //! Returns true if the address N is an A-form (local store) address
+ bool SelectAFormAddr(SDValue Op, SDValue N, SDValue &Base,
+ SDValue &Index);
+
+ //! D-form address predicate
+ bool SelectDFormAddr(SDValue Op, SDValue N, SDValue &Base,
+ SDValue &Index);
+
+ /// Alternate D-form address using i7 offset predicate
+ bool SelectDForm2Addr(SDValue Op, SDValue N, SDValue &Disp,
+ SDValue &Base);
+
+ /// D-form address selection workhorse
+ bool DFormAddressPredicate(SDValue Op, SDValue N, SDValue &Disp,
+ SDValue &Base, int minOffset, int maxOffset);
+
+ //! Address predicate if N can be expressed as an indexed [r+r] operation.
+ bool SelectXFormAddr(SDValue Op, SDValue N, SDValue &Base,
+ SDValue &Index);
+
+ /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
+ /// inline asm expressions.
+ virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op,
+ char ConstraintCode,
+ std::vector &OutOps) {
+ SDValue Op0, Op1;
+ switch (ConstraintCode) {
+ default: return true;
+ case 'm': // memory
+ if (!SelectDFormAddr(Op, Op, Op0, Op1)
+ && !SelectAFormAddr(Op, Op, Op0, Op1))
+ SelectXFormAddr(Op, Op, Op0, Op1);
+ break;
+ case 'o': // offsetable
+ if (!SelectDFormAddr(Op, Op, Op0, Op1)
+ && !SelectAFormAddr(Op, Op, Op0, Op1)) {
+ Op0 = Op;
+ Op1 = getSmallIPtrImm(0);
+ }
+ break;
+ case 'v': // not offsetable
#if 1
- assert(0 && "InlineAsmMemoryOperand 'v' constraint not handled.");
+ assert(0 && "InlineAsmMemoryOperand 'v' constraint not handled.");
#else
- SelectAddrIdxOnly(Op, Op, Op0, Op1);
+ SelectAddrIdxOnly(Op, Op, Op0, Op1);
#endif
- break;
- }
+ break;
+ }
- OutOps.push_back(Op0);
- OutOps.push_back(Op1);
- return false;
- }
+ OutOps.push_back(Op0);
+ OutOps.push_back(Op1);
+ return false;
+ }
- /// InstructionSelect - This callback is invoked by
- /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
- virtual void InstructionSelect();
+ /// InstructionSelect - This callback is invoked by
+ /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
+ virtual void InstructionSelect();
- virtual const char *getPassName() const {
- return "Cell SPU DAG->DAG Pattern Instruction Selection";
- }
+ virtual const char *getPassName() const {
+ return "Cell SPU DAG->DAG Pattern Instruction Selection";
+ }
- /// CreateTargetHazardRecognizer - Return the hazard recognizer to use for
- /// this target when scheduling the DAG.
- virtual ScheduleHazardRecognizer *CreateTargetHazardRecognizer() {
- const TargetInstrInfo *II = TM.getInstrInfo();
- assert(II && "No InstrInfo?");
- return new SPUHazardRecognizer(*II);
- }
+ /// CreateTargetHazardRecognizer - Return the hazard recognizer to use for
+ /// this target when scheduling the DAG.
+ virtual ScheduleHazardRecognizer *CreateTargetHazardRecognizer() {
+ const TargetInstrInfo *II = TM.getInstrInfo();
+ assert(II && "No InstrInfo?");
+ return new SPUHazardRecognizer(*II);
+ }
- // Include the pieces autogenerated from the target description.
+ // Include the pieces autogenerated from the target description.
#include "SPUGenDAGISel.inc"
-};
-
+ };
}
/// InstructionSelect - This callback is invoked by
@@ -689,7 +719,7 @@
// Catch the i64 constants that end up here. Note: The backend doesn't
// attempt to legalize the constant (it's useless because DAGCombiner
// will insert 64-bit constants and we can't stop it).
- return SelectI64Constant(Op, OpVT);
+ return SelectI64Constant(Op, OpVT, Op.getDebugLoc());
} else if ((Opc == ISD::ZERO_EXTEND || Opc == ISD::ANY_EXTEND)
&& OpVT == MVT::i64) {
SDValue Op0 = Op.getOperand(0);
@@ -747,21 +777,21 @@
zextShuffle));
} else if (Opc == ISD::ADD && (OpVT == MVT::i64 || OpVT == MVT::v2i64)) {
SDNode *CGLoad =
- emitBuildVector(SPU::getCarryGenerateShufMask(*CurDAG, dl));
+ emitBuildVector(getCarryGenerateShufMask(*CurDAG, dl));
return SelectCode(CurDAG->getNode(SPUISD::ADD64_MARKER, dl, OpVT,
Op.getOperand(0), Op.getOperand(1),
SDValue(CGLoad, 0)));
} else if (Opc == ISD::SUB && (OpVT == MVT::i64 || OpVT == MVT::v2i64)) {
SDNode *CGLoad =
- emitBuildVector(SPU::getBorrowGenerateShufMask(*CurDAG, dl));
+ emitBuildVector(getBorrowGenerateShufMask(*CurDAG, dl));
return SelectCode(CurDAG->getNode(SPUISD::SUB64_MARKER, dl, OpVT,
Op.getOperand(0), Op.getOperand(1),
SDValue(CGLoad, 0)));
} else if (Opc == ISD::MUL && (OpVT == MVT::i64 || OpVT == MVT::v2i64)) {
SDNode *CGLoad =
- emitBuildVector(SPU::getCarryGenerateShufMask(*CurDAG, dl));
+ emitBuildVector(getCarryGenerateShufMask(*CurDAG, dl));
return SelectCode(CurDAG->getNode(SPUISD::MUL64_MARKER, dl, OpVT,
Op.getOperand(0), Op.getOperand(1),
@@ -813,6 +843,54 @@
if (OpVT == MVT::i64) {
return SelectSRAi64(Op, OpVT);
}
+ } else if (Opc == ISD::FNEG
+ && (OpVT == MVT::f64 || OpVT == MVT::v2f64)) {
+ DebugLoc dl = Op.getDebugLoc();
+ // Check if the pattern is a special form of DFNMS:
+ // (fneg (fsub (fmul R64FP:$rA, R64FP:$rB), R64FP:$rC))
+ SDValue Op0 = Op.getOperand(0);
+ if (Op0.getOpcode() == ISD::FSUB) {
+ SDValue Op00 = Op0.getOperand(0);
+ if (Op00.getOpcode() == ISD::FMUL) {
+ unsigned Opc = SPU::DFNMSf64;
+ if (OpVT == MVT::v2f64)
+ Opc = SPU::DFNMSv2f64;
+
+ return CurDAG->getTargetNode(Opc, dl, OpVT,
+ Op00.getOperand(0),
+ Op00.getOperand(1),
+ Op0.getOperand(1));
+ }
+ }
+
+ SDValue negConst = CurDAG->getConstant(0x8000000000000000ULL, MVT::i64);
+ SDNode *signMask = 0;
+ unsigned Opc = SPU::ORfneg64;
+
+ if (OpVT == MVT::f64) {
+ signMask = SelectI64Constant(negConst, MVT::i64, dl);
+ } else if (OpVT == MVT::v2f64) {
+ Opc = SPU::ORfnegvec;
+ signMask = emitBuildVector(CurDAG->getNode(ISD::BUILD_VECTOR, dl,
+ MVT::v2i64,
+ negConst, negConst));
+ }
+
+ return CurDAG->getTargetNode(Opc, dl, OpVT,
+ Op.getOperand(0), SDValue(signMask, 0));
+ } else if (Opc == ISD::FABS) {
+ if (OpVT == MVT::f64) {
+ SDNode *signMask = SelectI64Constant(0x7fffffffffffffffULL, MVT::i64, dl);
+ return CurDAG->getTargetNode(SPU::ANDfabs64, dl, OpVT,
+ Op.getOperand(0), SDValue(signMask, 0));
+ } else if (OpVT == MVT::v2f64) {
+ SDValue absConst = CurDAG->getConstant(0x7fffffffffffffffULL, MVT::i64);
+ SDValue absVec = CurDAG->getNode(ISD::BUILD_VECTOR, dl, MVT::v2i64,
+ absConst, absConst);
+ SDNode *signMask = emitBuildVector(absVec);
+ return CurDAG->getTargetNode(SPU::ANDfabsvec, dl, OpVT,
+ Op.getOperand(0), SDValue(signMask, 0));
+ }
} else if (Opc == SPUISD::LDRESULT) {
// Custom select instructions for LDRESULT
MVT VT = N->getValueType(0);
@@ -1087,13 +1165,17 @@
/*!
Do the necessary magic necessary to load a i64 constant
*/
-SDNode *SPUDAGToDAGISel::SelectI64Constant(SDValue& Op, MVT OpVT) {
+SDNode *SPUDAGToDAGISel::SelectI64Constant(SDValue& Op, MVT OpVT,
+ DebugLoc dl) {
ConstantSDNode *CN = cast(Op.getNode());
- // Currently there's no DL on the input, but won't hurt to pretend.
- DebugLoc dl = Op.getDebugLoc();
+ return SelectI64Constant(CN->getZExtValue(), OpVT, dl);
+}
+
+SDNode *SPUDAGToDAGISel::SelectI64Constant(uint64_t Value64, MVT OpVT,
+ DebugLoc dl) {
MVT OpVecVT = MVT::getVectorVT(OpVT, 2);
SDValue i64vec =
- SPU::LowerSplat_v2i64(OpVecVT, *CurDAG, CN->getZExtValue(), dl);
+ SPU::LowerV2I64Splat(OpVecVT, *CurDAG, Value64, dl);
// Here's where it gets interesting, because we have to parse out the
// subtree handed back in i64vec:
@@ -1143,8 +1225,11 @@
SDValue(lhsNode, 0), SDValue(rhsNode, 0),
SDValue(shufMaskNode, 0)));
- return CurDAG->getTargetNode(SPU::ORi64_v2i64, dl, OpVT,
+ return CurDAG->getTargetNode(SPU::ORi64_v2i64, dl, OpVT,
SDValue(shufNode, 0));
+ } else if (i64vec.getOpcode() == ISD::BUILD_VECTOR) {
+ return CurDAG->getTargetNode(SPU::ORi64_v2i64, dl, OpVT,
+ SDValue(emitBuildVector(i64vec), 0));
} else {
cerr << "SPUDAGToDAGISel::SelectI64Constant: Unhandled i64vec condition\n";
abort();
Modified: llvm/trunk/lib/Target/CellSPU/SPUISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/CellSPU/SPUISelLowering.cpp?rev=67067&r1=67066&r2=67067&view=diff
==============================================================================
--- llvm/trunk/lib/Target/CellSPU/SPUISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/CellSPU/SPUISelLowering.cpp Mon Mar 16 20:15:45 2009
@@ -1,5 +1,5 @@
-//===-- SPUISelLowering.cpp - Cell SPU DAG Lowering Implementation --------===//
//
+//===-- SPUISelLowering.cpp - Cell SPU DAG Lowering Implementation --------===//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
@@ -1353,7 +1353,7 @@
}
}
- return 0; // All UNDEF: use implicit def.; not Constant node
+ return 0;
}
/// get_vec_i18imm - Test if this vector is a vector filled with the same value
@@ -1480,131 +1480,30 @@
return SDValue();
}
-// If this is a vector of constants or undefs, get the bits. A bit in
-// UndefBits is set if the corresponding element of the vector is an
-// ISD::UNDEF value. For undefs, the corresponding VectorBits values are
-// zero. Return true if this is not an array of constants, false if it is.
-//
-static bool GetConstantBuildVectorBits(SDNode *BV, uint64_t VectorBits[2],
- uint64_t UndefBits[2]) {
- // Start with zero'd results.
- VectorBits[0] = VectorBits[1] = UndefBits[0] = UndefBits[1] = 0;
-
- unsigned EltBitSize = BV->getOperand(0).getValueType().getSizeInBits();
- for (unsigned i = 0, e = BV->getNumOperands(); i != e; ++i) {
- SDValue OpVal = BV->getOperand(i);
-
- unsigned PartNo = i >= e/2; // In the upper 128 bits?
- unsigned SlotNo = e/2 - (i & (e/2-1))-1; // Which subpiece of the uint64_t.
-
- uint64_t EltBits = 0;
- if (OpVal.getOpcode() == ISD::UNDEF) {
- uint64_t EltUndefBits = ~0ULL >> (64-EltBitSize);
- UndefBits[PartNo] |= EltUndefBits << (SlotNo*EltBitSize);
- continue;
- } else if (ConstantSDNode *CN = dyn_cast(OpVal)) {
- EltBits = CN->getZExtValue() & (~0ULL >> (64-EltBitSize));
- } else if (ConstantFPSDNode *CN = dyn_cast(OpVal)) {
- const APFloat &apf = CN->getValueAPF();
- EltBits = (CN->getValueType(0) == MVT::f32
- ? FloatToBits(apf.convertToFloat())
- : DoubleToBits(apf.convertToDouble()));
- } else {
- // Nonconstant element.
- return true;
- }
-
- VectorBits[PartNo] |= EltBits << (SlotNo*EltBitSize);
- }
-
- //printf("%llx %llx %llx %llx\n",
- // VectorBits[0], VectorBits[1], UndefBits[0], UndefBits[1]);
- return false;
-}
-
-/// If this is a splat (repetition) of a value across the whole vector, return
-/// the smallest size that splats it. For example, "0x01010101010101..." is a
-/// splat of 0x01, 0x0101, and 0x01010101. We return SplatBits = 0x01 and
-/// SplatSize = 1 byte.
-static bool isConstantSplat(const uint64_t Bits128[2],
- const uint64_t Undef128[2],
- int MinSplatBits,
- uint64_t &SplatBits, uint64_t &SplatUndef,
- int &SplatSize) {
- // Don't let undefs prevent splats from matching. See if the top 64-bits are
- // the same as the lower 64-bits, ignoring undefs.
- uint64_t Bits64 = Bits128[0] | Bits128[1];
- uint64_t Undef64 = Undef128[0] & Undef128[1];
- uint32_t Bits32 = uint32_t(Bits64) | uint32_t(Bits64 >> 32);
- uint32_t Undef32 = uint32_t(Undef64) & uint32_t(Undef64 >> 32);
- uint16_t Bits16 = uint16_t(Bits32) | uint16_t(Bits32 >> 16);
- uint16_t Undef16 = uint16_t(Undef32) & uint16_t(Undef32 >> 16);
-
- if ((Bits128[0] & ~Undef128[1]) == (Bits128[1] & ~Undef128[0])) {
- if (MinSplatBits < 64) {
-
- // Check that the top 32-bits are the same as the lower 32-bits, ignoring
- // undefs.
- if ((Bits64 & (~Undef64 >> 32)) == ((Bits64 >> 32) & ~Undef64)) {
- if (MinSplatBits < 32) {
-
- // If the top 16-bits are different than the lower 16-bits, ignoring
- // undefs, we have an i32 splat.
- if ((Bits32 & (~Undef32 >> 16)) == ((Bits32 >> 16) & ~Undef32)) {
- if (MinSplatBits < 16) {
- // If the top 8-bits are different than the lower 8-bits, ignoring
- // undefs, we have an i16 splat.
- if ((Bits16 & (uint16_t(~Undef16) >> 8))
- == ((Bits16 >> 8) & ~Undef16)) {
- // Otherwise, we have an 8-bit splat.
- SplatBits = uint8_t(Bits16) | uint8_t(Bits16 >> 8);
- SplatUndef = uint8_t(Undef16) & uint8_t(Undef16 >> 8);
- SplatSize = 1;
- return true;
- }
- } else {
- SplatBits = Bits16;
- SplatUndef = Undef16;
- SplatSize = 2;
- return true;
- }
- }
- } else {
- SplatBits = Bits32;
- SplatUndef = Undef32;
- SplatSize = 4;
- return true;
- }
- }
- } else {
- SplatBits = Bits128[0];
- SplatUndef = Undef128[0];
- SplatSize = 8;
- return true;
- }
- }
-
- return false; // Can't be a splat if two pieces don't match.
-}
-
//! Lower a BUILD_VECTOR instruction creatively:
SDValue
LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
MVT VT = Op.getValueType();
+ MVT EltVT = VT.getVectorElementType();
DebugLoc dl = Op.getDebugLoc();
- // If this is a vector of constants or undefs, get the bits. A bit in
- // UndefBits is set if the corresponding element of the vector is an
- // ISD::UNDEF value. For undefs, the corresponding VectorBits values are
- // zero.
- uint64_t VectorBits[2];
- uint64_t UndefBits[2];
- uint64_t SplatBits, SplatUndef;
- int SplatSize;
- if (GetConstantBuildVectorBits(Op.getNode(), VectorBits, UndefBits)
- || !isConstantSplat(VectorBits, UndefBits,
- VT.getVectorElementType().getSizeInBits(),
- SplatBits, SplatUndef, SplatSize))
- return SDValue(); // Not a constant vector, not a splat.
+ BuildVectorSDNode *BCN = dyn_cast(Op.getNode());
+ assert(BCN != 0 && "Expected BuildVectorSDNode in SPU LowerBUILD_VECTOR");
+ unsigned minSplatBits = EltVT.getSizeInBits();
+
+ if (minSplatBits < 16)
+ minSplatBits = 16;
+
+ APInt APSplatBits, APSplatUndef;
+ unsigned SplatBitSize;
+ bool HasAnyUndefs;
+
+ if (!BCN->isConstantSplat(APSplatBits, APSplatUndef, SplatBitSize,
+ HasAnyUndefs, minSplatBits)
+ || minSplatBits < SplatBitSize)
+ return SDValue(); // Wasn't a constant vector or splat exceeded min
+
+ uint64_t SplatBits = APSplatBits.getZExtValue();
+ unsigned SplatSize = SplatBitSize / 8;
switch (VT.getSimpleVT()) {
default:
@@ -1620,8 +1519,7 @@
// NOTE: pretend the constant is an integer. LLVM won't load FP constants
SDValue T = DAG.getConstant(Value32, MVT::i32);
return DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v4f32,
- DAG.getNode(ISD::BUILD_VECTOR, dl,
- MVT::v4i32, T, T, T, T));
+ DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32, T, T, T, T));
break;
}
case MVT::v2f64: {
@@ -1636,45 +1534,42 @@
}
case MVT::v16i8: {
// 8-bit constants have to be expanded to 16-bits
- unsigned short Value16 = SplatBits | (SplatBits << 8);
- SDValue Ops[8];
- for (int i = 0; i < 8; ++i)
- Ops[i] = DAG.getConstant(Value16, MVT::i16);
+ unsigned short Value16 = SplatBits /* | (SplatBits << 8) */;
+ SmallVector Ops;
+
+ Ops.assign(8, DAG.getConstant(Value16, MVT::i16));
return DAG.getNode(ISD::BIT_CONVERT, dl, VT,
- DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v8i16, Ops, 8));
+ DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v8i16, &Ops[0], Ops.size()));
}
case MVT::v8i16: {
- unsigned short Value16;
- if (SplatSize == 2)
- Value16 = (unsigned short) (SplatBits & 0xffff);
- else
- Value16 = (unsigned short) (SplatBits | (SplatBits << 8));
- SDValue T = DAG.getConstant(Value16, VT.getVectorElementType());
- SDValue Ops[8];
- for (int i = 0; i < 8; ++i) Ops[i] = T;
- return DAG.getNode(ISD::BUILD_VECTOR, dl, VT, Ops, 8);
+ unsigned short Value16 = SplatBits;
+ SDValue T = DAG.getConstant(Value16, EltVT);
+ SmallVector Ops;
+
+ Ops.assign(8, T);
+ return DAG.getNode(ISD::BUILD_VECTOR, dl, VT, &Ops[0], Ops.size());
}
case MVT::v4i32: {
- unsigned int Value = SplatBits;
- SDValue T = DAG.getConstant(Value, VT.getVectorElementType());
+ SDValue T = DAG.getConstant(unsigned(SplatBits), VT.getVectorElementType());
return DAG.getNode(ISD::BUILD_VECTOR, dl, VT, T, T, T, T);
}
case MVT::v2i32: {
- unsigned int Value = SplatBits;
- SDValue T = DAG.getConstant(Value, VT.getVectorElementType());
+ SDValue T = DAG.getConstant(unsigned(SplatBits), VT.getVectorElementType());
return DAG.getNode(ISD::BUILD_VECTOR, dl, VT, T, T);
}
case MVT::v2i64: {
- return SPU::LowerSplat_v2i64(VT, DAG, SplatBits, dl);
+ return SPU::LowerV2I64Splat(VT, DAG, SplatBits, dl);
}
}
return SDValue();
}
+/*!
+ */
SDValue
-SPU::LowerSplat_v2i64(MVT OpVT, SelectionDAG& DAG, uint64_t SplatVal,
- DebugLoc dl) {
+SPU::LowerV2I64Splat(MVT OpVT, SelectionDAG& DAG, uint64_t SplatVal,
+ DebugLoc dl) {
uint32_t upper = uint32_t(SplatVal >> 32);
uint32_t lower = uint32_t(SplatVal);
@@ -1685,10 +1580,6 @@
DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
Val, Val, Val, Val));
} else {
- SDValue LO32;
- SDValue HI32;
- SmallVector ShufBytes;
- SDValue Result;
bool upper_special, lower_special;
// NOTE: This code creates common-case shuffle masks that can be easily
@@ -1699,6 +1590,18 @@
upper_special = (upper == 0 || upper == 0xffffffff || upper == 0x80000000);
lower_special = (lower == 0 || lower == 0xffffffff || lower == 0x80000000);
+ // Both upper and lower are special, lower to a constant pool load:
+ if (lower_special && upper_special) {
+ SDValue SplatValCN = DAG.getConstant(SplatVal, MVT::i64);
+ return DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v2i64,
+ SplatValCN, SplatValCN);
+ }
+
+ SDValue LO32;
+ SDValue HI32;
+ SmallVector ShufBytes;
+ SDValue Result;
+
// Create lower vector if not a special pattern
if (!lower_special) {
SDValue LO32C = DAG.getConstant(lower, MVT::i32);
@@ -1721,13 +1624,6 @@
LO32 = HI32;
if (upper_special)
HI32 = LO32;
- if (lower_special && upper_special) {
- // Unhappy situation... both upper and lower are special, so punt with
- // a target constant:
- SDValue Zero = DAG.getConstant(0, MVT::i32);
- HI32 = LO32 = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32, Zero, Zero,
- Zero, Zero);
- }
for (int i = 0; i < 4; ++i) {
uint64_t val = 0;
@@ -2022,9 +1918,9 @@
ShufMask[i] = DAG.getConstant(bits, MVT::i32);
}
- SDValue ShufMaskVec = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
- &ShufMask[0],
- sizeof(ShufMask) / sizeof(ShufMask[0]));
+ SDValue ShufMaskVec =
+ DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
+ &ShufMask[0], sizeof(ShufMask)/sizeof(ShufMask[0]));
retval = DAG.getNode(SPUISD::VEC2PREFSLOT, dl, VT,
DAG.getNode(SPUISD::SHUFB, dl, N.getValueType(),
@@ -2067,28 +1963,28 @@
/*NOTREACHED*/
case MVT::i8: {
SDValue factor = DAG.getConstant(0x00000000, MVT::i32);
- replicate = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32, factor, factor,
- factor, factor);
+ replicate = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
+ factor, factor, factor, factor);
break;
}
case MVT::i16: {
SDValue factor = DAG.getConstant(0x00010001, MVT::i32);
- replicate = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32, factor, factor,
- factor, factor);
+ replicate = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
+ factor, factor, factor, factor);
break;
}
case MVT::i32:
case MVT::f32: {
SDValue factor = DAG.getConstant(0x00010203, MVT::i32);
- replicate = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32, factor, factor,
- factor, factor);
+ replicate = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
+ factor, factor, factor, factor);
break;
}
case MVT::i64:
case MVT::f64: {
SDValue loFactor = DAG.getConstant(0x00010203, MVT::i32);
SDValue hiFactor = DAG.getConstant(0x04050607, MVT::i32);
- replicate = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
+ replicate = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
loFactor, hiFactor, loFactor, hiFactor);
break;
}
@@ -2164,71 +2060,65 @@
case ISD::ROTR:
case ISD::ROTL: {
SDValue N1 = Op.getOperand(1);
- unsigned N1Opc;
- N0 = (N0.getOpcode() != ISD::Constant
- ? DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i16, N0)
- : DAG.getConstant(cast(N0)->getZExtValue(),
- MVT::i16));
- N1Opc = N1.getValueType().bitsLT(ShiftVT)
- ? ISD::ZERO_EXTEND
- : ISD::TRUNCATE;
- N1 = (N1.getOpcode() != ISD::Constant
- ? DAG.getNode(N1Opc, dl, ShiftVT, N1)
- : DAG.getConstant(cast(N1)->getZExtValue(),
- TLI.getShiftAmountTy()));
+ MVT N1VT = N1.getValueType();
+
+ N0 = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i16, N0);
+ if (!N1VT.bitsEq(ShiftVT)) {
+ unsigned N1Opc = N1.getValueType().bitsLT(ShiftVT)
+ ? ISD::ZERO_EXTEND
+ : ISD::TRUNCATE;
+ N1 = DAG.getNode(N1Opc, dl, ShiftVT, N1);
+ }
+
+ // Replicate lower 8-bits into upper 8:
SDValue ExpandArg =
DAG.getNode(ISD::OR, dl, MVT::i16, N0,
DAG.getNode(ISD::SHL, dl, MVT::i16,
N0, DAG.getConstant(8, MVT::i32)));
+
+ // Truncate back down to i8
return DAG.getNode(ISD::TRUNCATE, dl, MVT::i8,
DAG.getNode(Opc, dl, MVT::i16, ExpandArg, N1));
}
case ISD::SRL:
case ISD::SHL: {
SDValue N1 = Op.getOperand(1);
- unsigned N1Opc;
- N0 = (N0.getOpcode() != ISD::Constant
- ? DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i16, N0)
- : DAG.getConstant(cast(N0)->getZExtValue(),
- MVT::i32));
- N1Opc = N1.getValueType().bitsLT(ShiftVT)
- ? ISD::ZERO_EXTEND
- : ISD::TRUNCATE;
- N1 = (N1.getOpcode() != ISD::Constant
- ? DAG.getNode(N1Opc, dl, ShiftVT, N1)
- : DAG.getConstant(cast(N1)->getZExtValue(), ShiftVT));
+ MVT N1VT = N1.getValueType();
+
+ N0 = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i16, N0);
+ if (!N1VT.bitsEq(ShiftVT)) {
+ unsigned N1Opc = ISD::ZERO_EXTEND;
+
+ if (N1.getValueType().bitsGT(ShiftVT))
+ N1Opc = ISD::TRUNCATE;
+
+ N1 = DAG.getNode(N1Opc, dl, ShiftVT, N1);
+ }
+
return DAG.getNode(ISD::TRUNCATE, dl, MVT::i8,
DAG.getNode(Opc, dl, MVT::i16, N0, N1));
}
case ISD::SRA: {
SDValue N1 = Op.getOperand(1);
- unsigned N1Opc;
- N0 = (N0.getOpcode() != ISD::Constant
- ? DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i16, N0)
- : DAG.getConstant(cast(N0)->getSExtValue(),
- MVT::i16));
- N1Opc = N1.getValueType().bitsLT(ShiftVT)
- ? ISD::SIGN_EXTEND
- : ISD::TRUNCATE;
- N1 = (N1.getOpcode() != ISD::Constant
- ? DAG.getNode(N1Opc, dl, ShiftVT, N1)
- : DAG.getConstant(cast(N1)->getZExtValue(),
- ShiftVT));
+ MVT N1VT = N1.getValueType();
+
+ N0 = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i16, N0);
+ if (!N1VT.bitsEq(ShiftVT)) {
+ unsigned N1Opc = ISD::SIGN_EXTEND;
+
+ if (N1VT.bitsGT(ShiftVT))
+ N1Opc = ISD::TRUNCATE;
+ N1 = DAG.getNode(N1Opc, dl, ShiftVT, N1);
+ }
+
return DAG.getNode(ISD::TRUNCATE, dl, MVT::i8,
DAG.getNode(Opc, dl, MVT::i16, N0, N1));
}
case ISD::MUL: {
SDValue N1 = Op.getOperand(1);
- unsigned N1Opc;
- N0 = (N0.getOpcode() != ISD::Constant
- ? DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i16, N0)
- : DAG.getConstant(cast(N0)->getZExtValue(),
- MVT::i16));
- N1Opc = N1.getValueType().bitsLT(MVT::i16) ? ISD::SIGN_EXTEND : ISD::TRUNCATE;
- N1 = (N1.getOpcode() != ISD::Constant
- ? DAG.getNode(N1Opc, dl, MVT::i16, N1)
- : DAG.getConstant(cast(N1)->getSExtValue(),
- MVT::i16));
+
+ N0 = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i16, N0);
+ N1 = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i16, N1);
return DAG.getNode(ISD::TRUNCATE, dl, MVT::i8,
DAG.getNode(Opc, dl, MVT::i16, N0, N1));
break;
@@ -2238,36 +2128,6 @@
return SDValue();
}
-//! Generate the carry-generate shuffle mask.
-SDValue SPU::getCarryGenerateShufMask(SelectionDAG &DAG, DebugLoc dl) {
- SmallVector ShufBytes;
-
- // Create the shuffle mask for "rotating" the borrow up one register slot
- // once the borrow is generated.
- ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
- ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
- ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
- ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
-
- return DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
- &ShufBytes[0], ShufBytes.size());
-}
-
-//! Generate the borrow-generate shuffle mask
-SDValue SPU::getBorrowGenerateShufMask(SelectionDAG &DAG, DebugLoc dl) {
- SmallVector ShufBytes;
-
- // Create the shuffle mask for "rotating" the borrow up one register slot
- // once the borrow is generated.
- ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
- ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
- ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
- ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
-
- return DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
- &ShufBytes[0], ShufBytes.size());
-}
-
//! Lower byte immediate operations for v16i8 vectors:
static SDValue
LowerByteImmed(SDValue Op, SelectionDAG &DAG) {
@@ -2291,26 +2151,24 @@
}
if (ConstVec.getNode()->getOpcode() == ISD::BUILD_VECTOR) {
- uint64_t VectorBits[2];
- uint64_t UndefBits[2];
- uint64_t SplatBits, SplatUndef;
- int SplatSize;
-
- if (!GetConstantBuildVectorBits(ConstVec.getNode(), VectorBits, UndefBits)
- && isConstantSplat(VectorBits, UndefBits,
- VT.getVectorElementType().getSizeInBits(),
- SplatBits, SplatUndef, SplatSize)) {
- SDValue tcVec[16];
- SDValue tc = DAG.getTargetConstant(SplatBits & 0xff, MVT::i8);
- const size_t tcVecSize = sizeof(tcVec) / sizeof(tcVec[0]);
+ BuildVectorSDNode *BCN = dyn_cast(ConstVec.getNode());
+ assert(BCN != 0 && "Expected BuildVectorSDNode in SPU LowerByteImmed");
- // Turn the BUILD_VECTOR into a set of target constants:
- for (size_t i = 0; i < tcVecSize; ++i)
- tcVec[i] = tc;
+ APInt APSplatBits, APSplatUndef;
+ unsigned SplatBitSize;
+ bool HasAnyUndefs;
+ unsigned minSplatBits = VT.getVectorElementType().getSizeInBits();
+
+ if (BCN->isConstantSplat(APSplatBits, APSplatUndef, SplatBitSize,
+ HasAnyUndefs, minSplatBits)
+ && minSplatBits <= SplatBitSize) {
+ uint64_t SplatBits = APSplatBits.getZExtValue();
+ SDValue tc = DAG.getTargetConstant(SplatBits & 0xff, MVT::i8);
+ SmallVector tcVec;
+ tcVec.assign(16, tc);
return DAG.getNode(Op.getNode()->getOpcode(), dl, VT, Arg,
- DAG.getNode(ISD::BUILD_VECTOR, dl, VT,
- tcVec, tcVecSize));
+ DAG.getNode(ISD::BUILD_VECTOR, dl, VT, &tcVec[0], tcVec.size()));
}
}
@@ -2452,7 +2310,7 @@
return ExpandLibCall(LC, Op, DAG, false, Dummy, TLI);
}
- return Op; // return unmolested, legalized op
+ return SDValue();
}
//! Lower ISD::SINT_TO_FP, ISD::UINT_TO_FP for i32
@@ -2478,7 +2336,7 @@
return ExpandLibCall(LC, Op, DAG, false, Dummy, TLI);
}
- return Op; // return unmolested, legalized
+ return SDValue();
}
//! Lower ISD::SETCC
Modified: llvm/trunk/lib/Target/CellSPU/SPUISelLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/CellSPU/SPUISelLowering.h?rev=67067&r1=67066&r2=67067&view=diff
==============================================================================
--- llvm/trunk/lib/Target/CellSPU/SPUISelLowering.h (original)
+++ llvm/trunk/lib/Target/CellSPU/SPUISelLowering.h Mon Mar 16 20:15:45 2009
@@ -78,11 +78,9 @@
SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG,
const SPUTargetMachine &TM);
- SDValue LowerSplat_v2i64(MVT OpVT, SelectionDAG &DAG, uint64_t splat,
+ //! Simplify a MVT::v2i64 constant splat to CellSPU-ready form
+ SDValue LowerV2I64Splat(MVT OpVT, SelectionDAG &DAG, uint64_t splat,
DebugLoc dl);
-
- SDValue getBorrowGenerateShufMask(SelectionDAG &DAG, DebugLoc dl);
- SDValue getCarryGenerateShufMask(SelectionDAG &DAG, DebugLoc dl);
}
class SPUTargetMachine; // forward dec'l.
Modified: llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.cpp?rev=67067&r1=67066&r2=67067&view=diff
==============================================================================
--- llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.cpp Mon Mar 16 20:15:45 2009
@@ -60,9 +60,6 @@
unsigned& SrcSR, unsigned& DstSR) const {
SrcSR = DstSR = 0; // No sub-registers.
- // Primarily, ORI and OR are generated by copyRegToReg. But, there are other
- // cases where we can safely say that what's being done is really a move
- // (see how PowerPC does this -- it's the model for this code too.)
switch (MI.getOpcode()) {
default:
break;
@@ -167,7 +164,7 @@
MI.getOperand(1).isReg() &&
"invalid SPU OR_ or LR instruction!");
if (MI.getOperand(0).getReg() == MI.getOperand(1).getReg()) {
- sourceReg = MI.getOperand(0).getReg();
+ sourceReg = MI.getOperand(1).getReg();
destReg = MI.getOperand(0).getReg();
return true;
}
Modified: llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.td?rev=67067&r1=67066&r2=67067&view=diff
==============================================================================
--- llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.td (original)
+++ llvm/trunk/lib/Target/CellSPU/SPUInstrInfo.td Mon Mar 16 20:15:45 2009
@@ -1258,10 +1258,9 @@
def fabs32: ANDInst<(outs R32FP:$rT), (ins R32FP:$rA, R32C:$rB),
[/* Intentionally does not match a pattern */]>;
- def fabs64: ANDInst<(outs R64FP:$rT), (ins R64FP:$rA, VECREG:$rB),
+ def fabs64: ANDInst<(outs R64FP:$rT), (ins R64FP:$rA, R64C:$rB),
[/* Intentionally does not match a pattern */]>;
- // Could use v4i32, but won't for clarity
def fabsvec: ANDInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
[/* Intentionally does not match a pattern */]>;
@@ -1288,10 +1287,11 @@
RRForm<0b10000011010, OOL, IOL, "andc\t$rT, $rA, $rB",
IntegerOp, pattern>;
-class ANDCVecInst:
+class ANDCVecInst:
ANDCInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
- [(set (vectype VECREG:$rT), (and (vectype VECREG:$rA),
- (vnot (vectype VECREG:$rB))))]>;
+ [(set (vectype VECREG:$rT),
+ (and (vectype VECREG:$rA),
+ (vnot_frag (vectype VECREG:$rB))))]>;
class ANDCRegInst:
ANDCInst<(outs rclass:$rT), (ins rclass:$rA, rclass:$rB),
@@ -1309,6 +1309,9 @@
def r32: ANDCRegInst;
def r16: ANDCRegInst;
def r8: ANDCRegInst;
+
+ // Sometimes, the xor pattern has a bitcast constant:
+ def v16i8_conv: ANDCVecInst;
}
defm ANDC : AndComplement;
@@ -1480,6 +1483,17 @@
def f64: ORInst<(outs R64FP:$rT), (ins R64FP:$rA, R64FP:$rB),
[/* no pattern */]>;
+ // OR instructions used to negate f32 and f64 quantities.
+
+ def fneg32: ORInst<(outs R32FP:$rT), (ins R32FP:$rA, R32C:$rB),
+ [/* no pattern */]>;
+
+ def fneg64: ORInst<(outs R64FP:$rT), (ins R64FP:$rA, R64C:$rB),
+ [/* no pattern */]>;
+
+ def fnegvec: ORInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
+ [/* no pattern, see fneg{32,64} */]>;
+
// scalar->vector promotion, prefslot2vec:
def v16i8_i8: ORPromoteScalar;
def v8i16_i16: ORPromoteScalar;
@@ -1783,18 +1797,6 @@
def r32: XORRegInst;
def r16: XORRegInst;
def r8: XORRegInst;
-
- // Special forms for floating point instructions.
- // fneg and fabs require bitwise logical ops to manipulate the sign bit.
-
- def fneg32: XORInst<(outs R32FP:$rT), (ins R32FP:$rA, R32C:$rB),
- [/* no pattern */]>;
-
- def fneg64: XORInst<(outs R64FP:$rT), (ins R64FP:$rA, VECREG:$rB),
- [/* no pattern */]>;
-
- def fnegvec: XORInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB),
- [/* no pattern, see fneg{32,64} */]>;
}
defm XOR : BitwiseExclusiveOr;
@@ -4239,33 +4241,36 @@
(fsub (fmul (v2f64 VECREG:$rA), (v2f64 VECREG:$rB)),
(v2f64 VECREG:$rC)))]>;
-// FNMS: - (a * b - c)
+// DFNMS: - (a * b - c)
// - (a * b) + c => c - (a * b)
-def FNMSf64 :
- RRForm<0b01111010110, (outs R64FP:$rT),
- (ins R64FP:$rA, R64FP:$rB, R64FP:$rC),
- "dfnms\t$rT, $rA, $rB", DPrecFP,
- [(set R64FP:$rT, (fsub R64FP:$rC, (fmul R64FP:$rA, R64FP:$rB)))]>,
+
+class DFNMSInst pattern>:
+ RRForm<0b01111010110, OOL, IOL, "dfnms\t$rT, $rA, $rB",
+ DPrecFP, pattern>,
RegConstraint<"$rC = $rT">,
NoEncode<"$rC">;
-def : Pat<(fneg (fsub (fmul R64FP:$rA, R64FP:$rB), R64FP:$rC)),
- (FNMSf64 R64FP:$rA, R64FP:$rB, R64FP:$rC)>;
+class DFNMSVecInst pattern>:
+ DFNMSInst<(outs VECREG:$rT), (ins VECREG:$rA, VECREG:$rB, VECREG:$rC),
+ pattern>;
-def FNMSv2f64 :
- RRForm<0b01111010110, (outs VECREG:$rT),
- (ins VECREG:$rA, VECREG:$rB, VECREG:$rC),
- "dfnms\t$rT, $rA, $rB", DPrecFP,
- [(set (v2f64 VECREG:$rT),
- (fsub (v2f64 VECREG:$rC),
- (fmul (v2f64 VECREG:$rA),
- (v2f64 VECREG:$rB))))]>,
- RegConstraint<"$rC = $rT">,
- NoEncode<"$rC">;
+class DFNMSRegInst pattern>:
+ DFNMSInst<(outs R64FP:$rT), (ins R64FP:$rA, R64FP:$rB, R64FP:$rC),
+ pattern>;
-def : Pat<(fneg (fsub (fmul (v2f64 VECREG:$rA), (v2f64 VECREG:$rB)),
- (v2f64 VECREG:$rC))),
- (FNMSv2f64 VECREG:$rA, VECREG:$rB, VECREG:$rC)>;
+multiclass DFMultiplySubtract
+{
+ def v2f64 : DFNMSVecInst<[(set (v2f64 VECREG:$rT),
+ (fsub (v2f64 VECREG:$rC),
+ (fmul (v2f64 VECREG:$rA),
+ (v2f64 VECREG:$rB))))]>;
+
+ def f64 : DFNMSRegInst<[(set R64FP:$rT,
+ (fsub R64FP:$rC,
+ (fmul R64FP:$rA, R64FP:$rB)))]>;
+}
+
+defm DFNMS : DFMultiplySubtract;
// - (a * b + c)
// - (a * b) - c
@@ -4293,35 +4298,21 @@
//===----------------------------------------------------------------------==//
def : Pat<(fneg (v4f32 VECREG:$rA)),
- (XORfnegvec (v4f32 VECREG:$rA),
- (v4f32 (ILHUv4i32 0x8000)))>;
+ (ORfnegvec (v4f32 VECREG:$rA),
+ (v4f32 (ILHUv4i32 0x8000)))>;
def : Pat<(fneg R32FP:$rA),
- (XORfneg32 R32FP:$rA, (ILHUr32 0x8000))>;
-
-def : Pat<(fneg (v2f64 VECREG:$rA)),
- (XORfnegvec (v2f64 VECREG:$rA),
- (v2f64 (ANDBIv16i8 (FSMBIv16i8 0x8080), 0x80)))>;
-
-def : Pat<(fneg R64FP:$rA),
- (XORfneg64 R64FP:$rA,
- (ANDBIv16i8 (FSMBIv16i8 0x8080), 0x80))>;
+ (ORfneg32 R32FP:$rA, (ILHUr32 0x8000))>;
// Floating point absolute value
+// Note: f64 fabs is custom-selected.
def : Pat<(fabs R32FP:$rA),
(ANDfabs32 R32FP:$rA, (IOHLr32 (ILHUr32 0x7fff), 0xffff))>;
def : Pat<(fabs (v4f32 VECREG:$rA)),
(ANDfabsvec (v4f32 VECREG:$rA),
- (v4f32 (ANDBIv16i8 (FSMBIv16i8 0xffff), 0x7f)))>;
-
-def : Pat<(fabs R64FP:$rA),
- (ANDfabs64 R64FP:$rA, (ANDBIv16i8 (FSMBIv16i8 0xffff), 0x7f))>;
-
-def : Pat<(fabs (v2f64 VECREG:$rA)),
- (ANDfabsvec (v2f64 VECREG:$rA),
- (v2f64 (ANDBIv16i8 (FSMBIv16i8 0xffff), 0x7f)))>;
+ (IOHLv4i32 (ILHUv4i32 0x7fff), 0xffff))>;
//===----------------------------------------------------------------------===//
// Hint for branch instructions:
Modified: llvm/trunk/test/CodeGen/CellSPU/2009-01-01-BrCond.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/CellSPU/2009-01-01-BrCond.ll?rev=67067&r1=67066&r2=67067&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/CellSPU/2009-01-01-BrCond.ll (original)
+++ llvm/trunk/test/CodeGen/CellSPU/2009-01-01-BrCond.ll Mon Mar 16 20:15:45 2009
@@ -8,11 +8,11 @@
define double @__floatunsidf(i32 %arg_a) nounwind {
entry:
- %in = alloca %struct.fp_number_type, align 8 ; <%struct.fp_number_type*> [#uses=5]
- %0 = getelementptr %struct.fp_number_type* %in, i32 0, i32 1 ; [#uses=1]
+ %in = alloca %struct.fp_number_type, align 16
+ %0 = getelementptr %struct.fp_number_type* %in, i32 0, i32 1
store i32 0, i32* %0, align 4
- %1 = icmp eq i32 %arg_a, 0 ; [#uses=1]
- %2 = getelementptr %struct.fp_number_type* %in, i32 0, i32 0 ; [#uses=2]
+ %1 = icmp eq i32 %arg_a, 0
+ %2 = getelementptr %struct.fp_number_type* %in, i32 0, i32 0
br i1 %1, label %bb, label %bb1
bb: ; preds = %entry
@@ -26,6 +26,6 @@
ret double 1.0
}
-declare i32 @llvm.ctlz.i32(i32) nounwind readnone
+; declare i32 @llvm.ctlz.i32(i32) nounwind readnone
declare double @__pack_d(%struct.fp_number_type*)
Modified: llvm/trunk/test/CodeGen/CellSPU/fneg-fabs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/CellSPU/fneg-fabs.ll?rev=67067&r1=67066&r2=67067&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/CellSPU/fneg-fabs.ll (original)
+++ llvm/trunk/test/CodeGen/CellSPU/fneg-fabs.ll Mon Mar 16 20:15:45 2009
@@ -1,9 +1,7 @@
; RUN: llvm-as -o - %s | llc -march=cellspu > %t1.s
-; RUN: grep fsmbi %t1.s | count 3
; RUN: grep 32768 %t1.s | count 2
-; RUN: grep xor %t1.s | count 4
-; RUN: grep and %t1.s | count 5
-; RUN: grep andbi %t1.s | count 3
+; RUN: grep or %t1.s | count 4
+; RUN: grep and %t1.s | count 2
target datalayout = "E-p:32:32:128-f64:64:128-f32:32:128-i64:32:128-i32:32:128-i16:16:128-i8:8:128-i1:8:128-a0:0:128-v128:128:128-s0:128:128"
target triple = "spu"
From evan.cheng at apple.com Mon Mar 16 20:23:09 2009
From: evan.cheng at apple.com (Evan Cheng)
Date: Tue, 17 Mar 2009 01:23:09 -0000
Subject: [llvm-commits] [llvm] r67068 - in /llvm/trunk:
lib/CodeGen/Spiller.cpp lib/CodeGen/Spiller.h
test/CodeGen/X86/2009-03-16-SpillerBug.ll
Message-ID: <200903170123.n2H1N9tX002333@zion.cs.uiuc.edu>
Author: evancheng
Date: Mon Mar 16 20:23:09 2009
New Revision: 67068
URL: http://llvm.org/viewvc/llvm-project?rev=67068&view=rev
Log:
Spiller may unfold load / mod / store instructions as an optimization when the would be loaded value is available in a register. It needs to check if it's legal to clobber the register. Also, the register can contain values of multiple spill slots, make sure to check all instead of just the one being unfolded.
Added:
llvm/trunk/test/CodeGen/X86/2009-03-16-SpillerBug.ll
Modified:
llvm/trunk/lib/CodeGen/Spiller.cpp
llvm/trunk/lib/CodeGen/Spiller.h
Modified: llvm/trunk/lib/CodeGen/Spiller.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/Spiller.cpp?rev=67068&r1=67067&r2=67068&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/Spiller.cpp (original)
+++ llvm/trunk/lib/CodeGen/Spiller.cpp Mon Mar 16 20:23:09 2009
@@ -28,6 +28,7 @@
STATISTIC(NumLoads , "Number of loads added");
STATISTIC(NumReused , "Number of values reused");
STATISTIC(NumDCE , "Number of copies elided");
+STATISTIC(NumSUnfold , "Number of stores unfolded");
namespace {
enum SpillerName { simple, local };
@@ -1172,8 +1173,8 @@
// Okay, we have a two address operand. We can reuse this physreg as
// long as we are allowed to clobber the value and there isn't an
// earlier def that has already clobbered the physreg.
- CanReuse = Spills.canClobberPhysReg(ReuseSlot) &&
- !ReusedOperands.isClobbered(PhysReg);
+ CanReuse = !ReusedOperands.isClobbered(PhysReg) &&
+ Spills.canClobberPhysReg(PhysReg);
}
if (CanReuse) {
@@ -1408,6 +1409,7 @@
DOUT << "Removing now-noop copy: " << MI;
// Unset last kill since it's being reused.
InvalidateKill(InReg, RegKills, KillOps);
+ Spills.disallowClobberPhysReg(InReg);
}
InvalidateKills(MI, RegKills, KillOps);
@@ -1446,6 +1448,8 @@
// the value and there isn't an earlier def that has already clobbered
// the physreg.
if (PhysReg &&
+ !ReusedOperands.isClobbered(PhysReg) &&
+ Spills.canClobberPhysReg(PhysReg) &&
!TII->isStoreToStackSlot(&MI, SS)) { // Not profitable!
MachineOperand *KillOpnd =
DeadStore->findRegisterUseOperand(PhysReg, true);
@@ -1453,7 +1457,7 @@
// super-register is needed below.
if (KillOpnd && !KillOpnd->getSubReg() &&
TII->unfoldMemoryOperand(MF, &MI, PhysReg, false, true,NewMIs)){
- MBB.insert(MII, NewMIs[0]);
+ MBB.insert(MII, NewMIs[0]);
NewStore = NewMIs[1];
MBB.insert(MII, NewStore);
VRM.addSpillSlotUse(SS, NewStore);
@@ -1465,6 +1469,7 @@
--NextMII; // backtrack to the unfolded instruction.
BackTracked = true;
isDead = true;
+ ++NumSUnfold;
}
}
}
@@ -1519,7 +1524,7 @@
// If the stack slot value was previously available in some other
// register, change it now. Otherwise, make the register
// available in PhysReg.
- Spills.addAvailable(StackSlot, SrcReg, false/*!clobber*/);
+ Spills.addAvailable(StackSlot, SrcReg, MI.killsRegister(SrcReg));
}
}
}
Modified: llvm/trunk/lib/CodeGen/Spiller.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/Spiller.h?rev=67068&r1=67067&r2=67068&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/Spiller.h (original)
+++ llvm/trunk/lib/CodeGen/Spiller.h Mon Mar 16 20:23:09 2009
@@ -127,15 +127,31 @@
DOUT << " in physreg " << TRI->getName(Reg) << "\n";
}
- /// canClobberPhysReg - Return true if the spiller is allowed to change the
- /// value of the specified stackslot register if it desires. The specified
- /// stack slot must be available in a physreg for this query to make sense.
- bool canClobberPhysReg(int SlotOrReMat) const {
+ /// canClobberPhysRegForSS - Return true if the spiller is allowed to change
+ /// the value of the specified stackslot register if it desires. The
+ /// specified stack slot must be available in a physreg for this query to
+ /// make sense.
+ bool canClobberPhysRegForSS(int SlotOrReMat) const {
assert(SpillSlotsOrReMatsAvailable.count(SlotOrReMat) &&
"Value not available!");
return SpillSlotsOrReMatsAvailable.find(SlotOrReMat)->second & 1;
}
+ /// canClobberPhysReg - Return true if the spiller is allowed to clobber the
+ /// physical register where values for some stack slot(s) might be
+ /// available.
+ bool canClobberPhysReg(unsigned PhysReg) const {
+ std::multimap::const_iterator I =
+ PhysRegsAvailable.lower_bound(PhysReg);
+ while (I != PhysRegsAvailable.end() && I->first == PhysReg) {
+ int SlotOrReMat = I->second;
+ I++;
+ if (!canClobberPhysRegForSS(SlotOrReMat))
+ return false;
+ }
+ return true;
+ }
+
/// disallowClobberPhysReg - Unset the CanClobber bit of the specified
/// stackslot register. The register is still available but is no longer
/// allowed to be modifed.
@@ -305,4 +321,4 @@
};
}
-#endif
\ No newline at end of file
+#endif
Added: llvm/trunk/test/CodeGen/X86/2009-03-16-SpillerBug.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2009-03-16-SpillerBug.ll?rev=67068&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/2009-03-16-SpillerBug.ll (added)
+++ llvm/trunk/test/CodeGen/X86/2009-03-16-SpillerBug.ll Mon Mar 16 20:23:09 2009
@@ -0,0 +1,167 @@
+; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin -stats |& grep spiller | not grep {stores unfolded}
+; rdar://6682365
+
+; Do not clobber a register if another spill slot is available in it and it's marked "do not clobber".
+
+ %struct.CAST_KEY = type { [32 x i32], i32 }
+ at CAST_S_table0 = constant [2 x i32] [i32 821772500, i32 -1616838901], align 32 ; <[2 x i32]*> [#uses=0]
+ at CAST_S_table4 = constant [2 x i32] [i32 2127105028, i32 745436345], align 32 ; <[2 x i32]*> [#uses=6]
+ at CAST_S_table5 = constant [2 x i32] [i32 -151351395, i32 749497569], align 32 ; <[2 x i32]*> [#uses=5]
+ at CAST_S_table6 = constant [2 x i32] [i32 -2048901095, i32 858518887], align 32 ; <[2 x i32]*> [#uses=4]
+ at CAST_S_table7 = constant [2 x i32] [i32 -501862387, i32 -1143078916], align 32 ; <[2 x i32]*> [#uses=5]
+ at CAST_S_table1 = constant [2 x i32] [i32 522195092, i32 -284448933], align 32 ; <[2 x i32]*> [#uses=0]
+ at CAST_S_table2 = constant [2 x i32] [i32 -1913667008, i32 637164959], align 32 ; <[2 x i32]*> [#uses=0]
+ at CAST_S_table3 = constant [2 x i32] [i32 -1649212384, i32 532081118], align 32 ; <[2 x i32]*> [#uses=0]
+
+define void @CAST_set_key(%struct.CAST_KEY* nocapture %key, i32 %len, i8* nocapture %data) nounwind ssp {
+bb1.thread:
+ %0 = getelementptr [16 x i32]* null, i32 0, i32 5 ; [#uses=1]
+ %1 = getelementptr [16 x i32]* null, i32 0, i32 8 ; [#uses=1]
+ %2 = load i32* null, align 4 ; [#uses=1]
+ %3 = shl i32 %2, 24 ; [#uses=1]
+ %4 = load i32* null, align 4 ; [#uses=1]
+ %5 = shl i32 %4, 16 ; [#uses=1]
+ %6 = load i32* null, align 4 ; [#uses=1]
+ %7 = or i32 %5, %3 ; [#uses=1]
+ %8 = or i32 %7, %6 ; [#uses=1]
+ %9 = or i32 %8, 0 ; [#uses=1]
+ %10 = load i32* null, align 4 ; [#uses=1]
+ %11 = shl i32 %10, 24 ; [#uses=1]
+ %12 = load i32* %0, align 4 ; [#uses=1]
+ %13 = shl i32 %12, 16 ; [#uses=1]
+ %14 = load i32* null, align 4 ; [#uses=1]
+ %15 = or i32 %13, %11 ; [#uses=1]
+ %16 = or i32 %15, %14 ; [#uses=1]
+ %17 = or i32 %16, 0 ; [#uses=1]
+ br label %bb11
+
+bb11: ; preds = %bb11, %bb1.thread
+ %18 = phi i32 [ %110, %bb11 ], [ 0, %bb1.thread ] ; [#uses=1]
+ %19 = phi i32 [ %112, %bb11 ], [ 0, %bb1.thread ] ; [#uses=0]
+ %20 = phi i32 [ 0, %bb11 ], [ 0, %bb1.thread ] ; [#uses=0]
+ %21 = phi i32 [ %113, %bb11 ], [ 0, %bb1.thread ] ; [#uses=1]
+ %X.0.0 = phi i32 [ %9, %bb1.thread ], [ %92, %bb11 ] ; [#uses=0]
+ %X.1.0 = phi i32 [ %17, %bb1.thread ], [ 0, %bb11 ] ; [#uses=0]
+ %22 = getelementptr [2 x i32]* @CAST_S_table6, i32 0, i32 %21 ; [#uses=0]
+ %23 = getelementptr [2 x i32]* @CAST_S_table5, i32 0, i32 %18 ; [#uses=0]
+ %24 = load i32* null, align 4 ; [#uses=1]
+ %25 = xor i32 0, %24 ; [#uses=1]
+ %26 = xor i32 %25, 0 ; [#uses=1]
+ %27 = xor i32 %26, 0 ; [#uses=4]
+ %28 = and i32 %27, 255 ; [#uses=2]
+ %29 = lshr i32 %27, 8 ; [#uses=1]
+ %30 = and i32 %29, 255 ; [#uses=2]
+ %31 = lshr i32 %27, 16 ; [#uses=1]
+ %32 = and i32 %31, 255 ; [#uses=1]
+ %33 = getelementptr [2 x i32]* @CAST_S_table4, i32 0, i32 %28 ; [#uses=1]
+ %34 = load i32* %33, align 4 ; [#uses=2]
+ %35 = getelementptr [2 x i32]* @CAST_S_table5, i32 0, i32 %30 ; [#uses=1]
+ %36 = load i32* %35, align 4 ; [#uses=2]
+ %37 = xor i32 %34, 0 ; [#uses=1]
+ %38 = xor i32 %37, %36 ;