From: Dan Gohman Date: Tue, 14 Apr 2009 22:17:14 +0000 (+0000) Subject: When the result of an EXTRACT_SUBREG, INSERT_SUBREG, or SUBREG_TO_REG X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=5ec3b427c850d8c61aaa29e3421019bdff9b77f1;p=oota-llvm.git 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 --- diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp index 94333d34454..42fe1f5fbf4 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(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-0.ll b/test/CodeGen/X86/h-registers-0.ll new file mode 100644 index 00000000000..2777be9cc3e --- /dev/null +++ b/test/CodeGen/X86/h-registers-0.ll @@ -0,0 +1,48 @@ +; RUN: llvm-as < %s | llc -march=x86-64 | grep {movzbl %\[abcd\]h,} | count 4 +; RUN: llvm-as < %s | llc -march=x86 > %t +; RUN: grep {incb %ah} %t | count 3 +; RUN: grep {movzbl %ah,} %t | count 3 + +; Use h registers. On x86-64, codegen doesn't support general allocation +; of h registers yet, due to x86 encoding complications. + +define void @bar64(i64 inreg %x, i8* inreg %p) nounwind { + %t0 = lshr i64 %x, 8 + %t1 = trunc i64 %t0 to i8 + %t2 = add i8 %t1, 1 + store i8 %t2, i8* %p + ret void +} + +define void @bar32(i32 inreg %x, i8* inreg %p) nounwind { + %t0 = lshr i32 %x, 8 + %t1 = trunc i32 %t0 to i8 + %t2 = add i8 %t1, 1 + store i8 %t2, i8* %p + ret void +} + +define void @bar16(i16 inreg %x, i8* inreg %p) nounwind { + %t0 = lshr i16 %x, 8 + %t1 = trunc i16 %t0 to i8 + %t2 = add i8 %t1, 1 + store i8 %t2, i8* %p + ret void +} + +define i64 @qux64(i64 inreg %x) nounwind { + %t0 = lshr i64 %x, 8 + %t1 = and i64 %t0, 255 + ret i64 %t1 +} + +define i32 @qux32(i32 inreg %x) nounwind { + %t0 = lshr i32 %x, 8 + %t1 = and i32 %t0, 255 + ret i32 %t1 +} + +define i16 @qux16(i16 inreg %x) nounwind { + %t0 = lshr i16 %x, 8 + ret i16 %t0 +} diff --git a/test/CodeGen/X86/h-registers-1.ll b/test/CodeGen/X86/h-registers-1.ll new file mode 100644 index 00000000000..789f3dd18f0 --- /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 +} diff --git a/test/CodeGen/X86/h-registers.ll b/test/CodeGen/X86/h-registers.ll deleted file mode 100644 index 2777be9cc3e..00000000000 --- a/test/CodeGen/X86/h-registers.ll +++ /dev/null @@ -1,48 +0,0 @@ -; RUN: llvm-as < %s | llc -march=x86-64 | grep {movzbl %\[abcd\]h,} | count 4 -; RUN: llvm-as < %s | llc -march=x86 > %t -; RUN: grep {incb %ah} %t | count 3 -; RUN: grep {movzbl %ah,} %t | count 3 - -; Use h registers. On x86-64, codegen doesn't support general allocation -; of h registers yet, due to x86 encoding complications. - -define void @bar64(i64 inreg %x, i8* inreg %p) nounwind { - %t0 = lshr i64 %x, 8 - %t1 = trunc i64 %t0 to i8 - %t2 = add i8 %t1, 1 - store i8 %t2, i8* %p - ret void -} - -define void @bar32(i32 inreg %x, i8* inreg %p) nounwind { - %t0 = lshr i32 %x, 8 - %t1 = trunc i32 %t0 to i8 - %t2 = add i8 %t1, 1 - store i8 %t2, i8* %p - ret void -} - -define void @bar16(i16 inreg %x, i8* inreg %p) nounwind { - %t0 = lshr i16 %x, 8 - %t1 = trunc i16 %t0 to i8 - %t2 = add i8 %t1, 1 - store i8 %t2, i8* %p - ret void -} - -define i64 @qux64(i64 inreg %x) nounwind { - %t0 = lshr i64 %x, 8 - %t1 = and i64 %t0, 255 - ret i64 %t1 -} - -define i32 @qux32(i32 inreg %x) nounwind { - %t0 = lshr i32 %x, 8 - %t1 = and i32 %t0, 255 - ret i32 %t1 -} - -define i16 @qux16(i16 inreg %x) nounwind { - %t0 = lshr i16 %x, 8 - ret i16 %t0 -}