aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Gohman <gohman@apple.com>2009-04-14 22:17:14 +0000
committerDan Gohman <gohman@apple.com>2009-04-14 22:17:14 +0000
commit5ec3b427c850d8c61aaa29e3421019bdff9b77f1 (patch)
tree6ab829b839dc3b0819536ed10a746055818457dc
parent0526653956e924304f4c56ff87f72cecbb49fba2 (diff)
downloadexternal_llvm-5ec3b427c850d8c61aaa29e3421019bdff9b77f1.zip
external_llvm-5ec3b427c850d8c61aaa29e3421019bdff9b77f1.tar.gz
external_llvm-5ec3b427c850d8c61aaa29e3421019bdff9b77f1.tar.bz2
When the result of an EXTRACT_SUBREG, INSERT_SUBREG, or SUBREG_TO_REG
operator is used by a CopyToReg to export the value to a different block, don't reuse the CopyToReg's register for the subreg operation result if the register isn't precisely the right class for the subreg operation. Also, rename the h-registers.ll test, now that there are more than one. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@69087 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp39
-rw-r--r--test/CodeGen/X86/h-registers-0.ll (renamed from test/CodeGen/X86/h-registers.ll)0
-rw-r--r--test/CodeGen/X86/h-registers-1.ll39
3 files changed, 58 insertions, 20 deletions
diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp
index 94333d3..42fe1f5 100644
--- a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp
+++ b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp
@@ -402,19 +402,16 @@ void ScheduleDAGSDNodes::EmitSubregNode(SDNode *Node,
const TargetRegisterClass *TRC = MRI.getRegClass(VReg);
const TargetRegisterClass *SRC = getSubRegisterRegClass(TRC, SubIdx);
- if (VRBase) {
- // Grab the destination register
-#ifndef NDEBUG
- const TargetRegisterClass *DRC = MRI.getRegClass(VRBase);
- assert(SRC && DRC && (SRC == DRC || DRC->hasSubClass(SRC)) &&
- "Source subregister and destination must have the same class");
-#endif
- } else {
+ // Figure out the register class to create for the destreg.
+ // Note that if we're going to directly use an existing register,
+ // it must be precisely the required class, and not a subclass
+ // thereof.
+ if (VRBase == 0 || SRC != MRI.getRegClass(VRBase)) {
// Create the reg
assert(SRC && "Couldn't find source register class");
VRBase = MRI.createVirtualRegister(SRC);
}
-
+
// Add def, source, and subreg index
MI->addOperand(MachineOperand::CreateReg(VRBase, true));
AddOperand(MI, Node->getOperand(0), 0, 0, VRBaseMap);
@@ -427,19 +424,21 @@ void ScheduleDAGSDNodes::EmitSubregNode(SDNode *Node,
SDValue N2 = Node->getOperand(2);
unsigned SubReg = getVR(N1, VRBaseMap);
unsigned SubIdx = cast<ConstantSDNode>(N2)->getZExtValue();
-
-
+ const TargetRegisterClass *TRC = MRI.getRegClass(SubReg);
+ const TargetRegisterClass *SRC =
+ getSuperRegisterRegClass(TRC, SubIdx,
+ Node->getValueType(0));
+
// Figure out the register class to create for the destreg.
- const TargetRegisterClass *TRC = 0;
- if (VRBase) {
- TRC = MRI.getRegClass(VRBase);
- } else {
- TRC = getSuperRegisterRegClass(MRI.getRegClass(SubReg), SubIdx,
- Node->getValueType(0));
- assert(TRC && "Couldn't determine register class for insert_subreg");
- VRBase = MRI.createVirtualRegister(TRC); // Create the reg
+ // Note that if we're going to directly use an existing register,
+ // it must be precisely the required class, and not a subclass
+ // thereof.
+ if (VRBase == 0 || SRC != MRI.getRegClass(VRBase)) {
+ // Create the reg
+ assert(SRC && "Couldn't find source register class");
+ VRBase = MRI.createVirtualRegister(SRC);
}
-
+
// Create the insert_subreg or subreg_to_reg machine instruction.
MachineInstr *MI = BuildMI(MF, Node->getDebugLoc(), TII->get(Opc));
MI->addOperand(MachineOperand::CreateReg(VRBase, true));
diff --git a/test/CodeGen/X86/h-registers.ll b/test/CodeGen/X86/h-registers-0.ll
index 2777be9..2777be9 100644
--- a/test/CodeGen/X86/h-registers.ll
+++ b/test/CodeGen/X86/h-registers-0.ll
diff --git a/test/CodeGen/X86/h-registers-1.ll b/test/CodeGen/X86/h-registers-1.ll
new file mode 100644
index 0000000..789f3dd
--- /dev/null
+++ b/test/CodeGen/X86/h-registers-1.ll
@@ -0,0 +1,39 @@
+; RUN: llvm-as < %s | llc -march=x86-64 > %t
+; RUN: grep {movzbl %\[abcd\]h,} %t | count 8
+; RUN: grep {%\[abcd\]h} %t | not grep {%r\[\[:digit:\]\]*d}
+
+; LLVM creates virtual registers for values live across blocks
+; based on the type of the value. Make sure that the extracts
+; here use the GR64_NOREX register class for their result,
+; instead of plain GR64.
+
+define i64 @foo(i64 %a, i64 %b, i64 %c, i64 %d,
+ i64 %e, i64 %f, i64 %g, i64 %h) {
+ %sa = lshr i64 %a, 8
+ %A = and i64 %sa, 255
+ %sb = lshr i64 %b, 8
+ %B = and i64 %sb, 255
+ %sc = lshr i64 %c, 8
+ %C = and i64 %sc, 255
+ %sd = lshr i64 %d, 8
+ %D = and i64 %sd, 255
+ %se = lshr i64 %e, 8
+ %E = and i64 %se, 255
+ %sf = lshr i64 %f, 8
+ %F = and i64 %sf, 255
+ %sg = lshr i64 %g, 8
+ %G = and i64 %sg, 255
+ %sh = lshr i64 %h, 8
+ %H = and i64 %sh, 255
+ br label %next
+
+next:
+ %u = add i64 %A, %B
+ %v = add i64 %C, %D
+ %w = add i64 %E, %F
+ %x = add i64 %G, %H
+ %y = add i64 %u, %v
+ %z = add i64 %w, %x
+ %t = add i64 %y, %z
+ ret i64 %t
+}