2014-03-18 22:07:45 +00:00
|
|
|
Pull in r199187 from upstream llvm trunk (by Jakob Stoklund Olesen):
|
|
|
|
|
|
|
|
Always let value types influence register classes.
|
|
|
|
|
|
|
|
When creating a virtual register for a def, the value type should be
|
|
|
|
used to pick the register class. If we only use the register class
|
|
|
|
constraint on the instruction, we might pick a too large register class.
|
|
|
|
|
|
|
|
Some registers can store values of different sizes. For example, the x86
|
|
|
|
xmm registers can hold f32, f64, and 128-bit vectors. The three
|
|
|
|
different value sizes are represented by register classes with identical
|
|
|
|
register sets: FR32, FR64, and VR128. These register classes have
|
|
|
|
different spill slot sizes, so it is important to use the right one.
|
|
|
|
|
|
|
|
The register class constraint on an instruction doesn't necessarily care
|
|
|
|
about the size of the value its defining. The value type determines
|
|
|
|
that.
|
|
|
|
|
|
|
|
This fixes a problem where InstrEmitter was picking 32-bit register
|
|
|
|
classes for 64-bit values on SPARC.
|
|
|
|
|
2014-05-24 22:27:31 +00:00
|
|
|
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
2014-03-18 22:07:45 +00:00
|
|
|
|
|
|
|
Index: test/CodeGen/SPARC/spillsize.ll
|
|
|
|
===================================================================
|
|
|
|
--- test/CodeGen/SPARC/spillsize.ll
|
|
|
|
+++ test/CodeGen/SPARC/spillsize.ll
|
|
|
|
@@ -0,0 +1,25 @@
|
|
|
|
+; RUN: llc < %s -verify-machineinstrs | FileCheck %s
|
|
|
|
+target datalayout = "E-m:e-i64:64-n32:64-S128"
|
|
|
|
+target triple = "sparcv9"
|
|
|
|
+
|
|
|
|
+; CHECK-LABEL: spill4
|
|
|
|
+; This function spills two values: %p and the materialized large constant.
|
|
|
|
+; Both must use 8-byte spill and fill instructions.
|
|
|
|
+; CHECK: stx %{{..}}, [%fp+
|
|
|
|
+; CHECK: stx %{{..}}, [%fp+
|
|
|
|
+; CHECK: ldx [%fp+
|
|
|
|
+; CHECK: ldx [%fp+
|
|
|
|
+define void @spill4(i64* nocapture %p) {
|
|
|
|
+entry:
|
|
|
|
+ %val0 = load i64* %p
|
|
|
|
+ %cmp0 = icmp ult i64 %val0, 385672958347594845
|
|
|
|
+ %cm80 = zext i1 %cmp0 to i64
|
|
|
|
+ store i64 %cm80, i64* %p, align 8
|
|
|
|
+ tail call void asm sideeffect "", "~{i0},~{i1},~{i2},~{i3},~{i4},~{i5},~{g2},~{g3},~{g4},~{g5},~{l0},~{l1},~{l2},~{l3},~{l4},~{l5},~{l6},~{l7},~{o0},~{o1},~{o2},~{o3},~{o4},~{o5},~{o7}"()
|
|
|
|
+ %arrayidx1 = getelementptr inbounds i64* %p, i64 1
|
|
|
|
+ %val = load i64* %arrayidx1
|
|
|
|
+ %cmp = icmp ult i64 %val, 385672958347594845
|
|
|
|
+ %cm8 = select i1 %cmp, i64 10, i64 20
|
|
|
|
+ store i64 %cm8, i64* %arrayidx1, align 8
|
|
|
|
+ ret void
|
|
|
|
+}
|
|
|
|
Index: lib/CodeGen/SelectionDAG/InstrEmitter.cpp
|
|
|
|
===================================================================
|
|
|
|
--- lib/CodeGen/SelectionDAG/InstrEmitter.cpp
|
|
|
|
+++ lib/CodeGen/SelectionDAG/InstrEmitter.cpp
|
|
|
|
@@ -220,10 +220,19 @@ void InstrEmitter::CreateVirtualRegisters(SDNode *
|
|
|
|
unsigned VRBase = 0;
|
|
|
|
const TargetRegisterClass *RC =
|
|
|
|
TRI->getAllocatableClass(TII->getRegClass(II, i, TRI, *MF));
|
|
|
|
- // If the register class is unknown for the given definition, then try to
|
|
|
|
- // infer one from the value type.
|
|
|
|
- if (!RC && i < NumResults)
|
|
|
|
- RC = TLI->getRegClassFor(Node->getSimpleValueType(i));
|
|
|
|
+ // Always let the value type influence the used register class. The
|
|
|
|
+ // constraints on the instruction may be too lax to represent the value
|
|
|
|
+ // type correctly. For example, a 64-bit float (X86::FR64) can't live in
|
|
|
|
+ // the 32-bit float super-class (X86::FR32).
|
|
|
|
+ if (i < NumResults && TLI->isTypeLegal(Node->getSimpleValueType(i))) {
|
|
|
|
+ const TargetRegisterClass *VTRC =
|
|
|
|
+ TLI->getRegClassFor(Node->getSimpleValueType(i));
|
|
|
|
+ if (RC)
|
|
|
|
+ VTRC = TRI->getCommonSubClass(RC, VTRC);
|
|
|
|
+ if (VTRC)
|
|
|
|
+ RC = VTRC;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
if (II.OpInfo[i].isOptionalDef()) {
|
|
|
|
// Optional def must be a physical register.
|
|
|
|
unsigned NumResults = CountResults(Node);
|