[WebAssembly] Create new registers instead of reusing old ones in RegStackify.

This avoids some complications updating LiveIntervals to be aware of the new
register lifetimes, because we can just compute new intervals from scratch
rather than describe how the old ones have been changed.

llvm-svn: 260971
This commit is contained in:
Dan Gohman 2016-02-16 15:17:21 +00:00
parent 944f655e05
commit 8aa237c3ca
3 changed files with 82 additions and 37 deletions

View File

@ -237,13 +237,13 @@ RematerializeCheapDef(unsigned Reg, MachineOperand &Op, MachineInstr *Def,
///
/// to this:
///
/// Reg = INST ... // Def (to become the new Insert)
/// TeeReg, NewReg = TEE_LOCAL_... Reg
/// DefReg = INST ... // Def (to become the new Insert)
/// TeeReg, NewReg = TEE_LOCAL_... DefReg
/// INST ..., TeeReg, ... // Insert
/// INST ..., NewReg, ...
/// INST ..., NewReg, ...
///
/// with Reg and TeeReg stackified. This eliminates a get_local from the
/// with DefReg and TeeReg stackified. This eliminates a get_local from the
/// resulting code.
static MachineInstr *MoveAndTeeForMultiUse(
unsigned Reg, MachineOperand &Op, MachineInstr *Def, MachineBasicBlock &MBB,
@ -254,18 +254,20 @@ static MachineInstr *MoveAndTeeForMultiUse(
const auto *RegClass = MRI.getRegClass(Reg);
unsigned NewReg = MRI.createVirtualRegister(RegClass);
unsigned TeeReg = MRI.createVirtualRegister(RegClass);
unsigned DefReg = MRI.createVirtualRegister(RegClass);
MRI.replaceRegWith(Reg, NewReg);
MachineInstr *Tee = BuildMI(MBB, Insert, Insert->getDebugLoc(),
TII->get(GetTeeLocalOpcode(RegClass)), TeeReg)
.addReg(NewReg, RegState::Define)
.addReg(Reg);
.addReg(DefReg);
Op.setReg(TeeReg);
Def->getOperand(0).setReg(Reg);
Def->getOperand(0).setReg(DefReg);
LIS.InsertMachineInstrInMaps(Tee);
LIS.shrinkToUses(&LIS.getInterval(Reg));
LIS.removeInterval(Reg);
LIS.createAndComputeVirtRegInterval(NewReg);
LIS.createAndComputeVirtRegInterval(TeeReg);
MFI.stackifyVReg(Reg);
LIS.createAndComputeVirtRegInterval(DefReg);
MFI.stackifyVReg(DefReg);
MFI.stackifyVReg(TeeReg);
ImposeStackOrdering(Def);
ImposeStackOrdering(Tee);

View File

@ -96,12 +96,12 @@ false:
; CHECK-NEXT: .param i32, i32, i32{{$}}
; CHECK-NEXT: .local i32{{$}}
; CHECK-NEXT: block{{$}}
; CHECK-NEXT: i32.load $push0=, 0($2){{$}}
; CHECK-NEXT: tee_local $push3=, $3=, $pop0{{$}}
; CHECK-NEXT: i32.ge_u $push1=, $pop3, $1{{$}}
; CHECK-NEXT: br_if 0, $pop1{{$}}
; CHECK-NEXT: i32.lt_u $push2=, $3, $0{{$}}
; CHECK-NEXT: br_if 0, $pop2{{$}}
; CHECK-NEXT: i32.load $push[[NUM0:[0-9]+]]=, 0($2){{$}}
; CHECK-NEXT: tee_local $push[[NUM1:[0-9]+]]=, $3=, $pop[[NUM0]]{{$}}
; CHECK-NEXT: i32.ge_u $push[[NUM2:[0-9]+]]=, $pop[[NUM1]], $1{{$}}
; CHECK-NEXT: br_if 0, $pop[[NUM2]]{{$}}
; CHECK-NEXT: i32.lt_u $push[[NUM3:[0-9]+]]=, $3, $0{{$}}
; CHECK-NEXT: br_if 0, $pop[[NUM3]]{{$}}
; CHECK-NEXT: i32.store $discard=, 0($2), $3{{$}}
; CHECK-NEXT: .LBB5_3:
; CHECK-NEXT: end_block{{$}}
@ -193,9 +193,9 @@ entry:
; CHECK-LABEL: simple_multiple_use:
; CHECK-NEXT: .param i32, i32{{$}}
; CHECK-NEXT: i32.mul $push0=, $1, $0{{$}}
; CHECK-NEXT: tee_local $push1=, $0=, $pop0{{$}}
; CHECK-NEXT: call use_a@FUNCTION, $pop1{{$}}
; CHECK-NEXT: i32.mul $push[[NUM0:[0-9]+]]=, $1, $0{{$}}
; CHECK-NEXT: tee_local $push[[NUM1:[0-9]+]]=, $0=, $pop[[NUM0]]{{$}}
; CHECK-NEXT: call use_a@FUNCTION, $pop[[NUM1]]{{$}}
; CHECK-NEXT: call use_b@FUNCTION, $0{{$}}
; CHECK-NEXT: return{{$}}
declare void @use_a(i32)
@ -211,9 +211,9 @@ define void @simple_multiple_use(i32 %x, i32 %y) {
; CHECK-LABEL: multiple_uses_in_same_insn:
; CHECK-NEXT: .param i32, i32{{$}}
; CHECK-NEXT: i32.mul $push0=, $1, $0{{$}}
; CHECK-NEXT: tee_local $push1=, $0=, $pop0{{$}}
; CHECK-NEXT: call use_2@FUNCTION, $pop1, $0{{$}}
; CHECK-NEXT: i32.mul $push[[NUM0:[0-9]+]]=, $1, $0{{$}}
; CHECK-NEXT: tee_local $push[[NUM1:[0-9]+]]=, $0=, $pop[[NUM0]]{{$}}
; CHECK-NEXT: call use_2@FUNCTION, $pop[[NUM1]], $0{{$}}
; CHECK-NEXT: return{{$}}
declare void @use_2(i32, i32)
define void @multiple_uses_in_same_insn(i32 %x, i32 %y) {
@ -265,4 +265,47 @@ define i32 @no_stackify_past_use(i32 %arg) {
ret i32 %tmp6
}
; Stackify individual defs of virtual registers with multiple defs.
; CHECK-LABEL: multiple_defs:
; CHECK: f64.add $push[[NUM0:[0-9]+]]=, ${{[0-9]+}}, $pop{{[0-9]+}}{{$}}
; CHECK-NEXT: tee_local $push[[NUM1:[0-9]+]]=, $[[NUM2:[0-9]+]]=, $pop[[NUM0]]{{$}}
; CHECK-NEXT: f64.select $push{{[0-9]+}}=, $pop{{[0-9]+}}, $pop[[NUM1]], ${{[0-9]+}}{{$}}
; CHECK: $[[NUM2]]=,
; CHECK: $[[NUM2]]=,
define void @multiple_defs(i32 %arg, i32 %arg1, i1 %arg2, i1 %arg3, i1 %arg4) {
bb:
br label %bb5
bb5: ; preds = %bb21, %bb
%tmp = phi double [ 0.000000e+00, %bb ], [ %tmp22, %bb21 ]
%tmp6 = phi double [ 0.000000e+00, %bb ], [ %tmp23, %bb21 ]
%tmp7 = fcmp olt double %tmp6, 2.323450e+01
br i1 %tmp7, label %bb8, label %bb21
bb8: ; preds = %bb17, %bb5
%tmp9 = phi double [ %tmp19, %bb17 ], [ %tmp, %bb5 ]
%tmp10 = fadd double %tmp6, -1.000000e+00
%tmp11 = select i1 %arg2, double -1.135357e+04, double %tmp10
%tmp12 = fadd double %tmp11, %tmp9
br i1 %arg3, label %bb17, label %bb13
bb13: ; preds = %bb8
%tmp14 = or i32 %arg1, 2
%tmp15 = icmp eq i32 %tmp14, 14
%tmp16 = select i1 %tmp15, double -1.135357e+04, double 0xBFCE147AE147B000
br label %bb17
bb17: ; preds = %bb13, %bb8
%tmp18 = phi double [ %tmp16, %bb13 ], [ %tmp10, %bb8 ]
%tmp19 = fadd double %tmp18, %tmp12
%tmp20 = fcmp olt double %tmp6, 2.323450e+01
br i1 %tmp20, label %bb8, label %bb21
bb21: ; preds = %bb17, %bb5
%tmp22 = phi double [ %tmp, %bb5 ], [ %tmp9, %bb17 ]
%tmp23 = fadd double %tmp6, 1.000000e+00
br label %bb5
}
!0 = !{}

View File

@ -53,13 +53,13 @@ entry:
; CHECK-NEXT: .param i32{{$}}
; CHECK-NEXT: .result i32{{$}}
; CHECK-NEXT: .local i32{{$}}
; CHECK-NEXT: i32.load $push0=, 0($0){{$}}
; CHECK-NEXT: tee_local $push4=, $1=, $pop0{{$}}
; CHECK-NEXT: i32.const $push1=, 4{{$}}
; CHECK-NEXT: i32.add $push2=, $pop4, $pop1{{$}}
; CHECK-NEXT: i32.store $discard=, 0($0), $pop2{{$}}
; CHECK-NEXT: i32.load $push3=, 0($1){{$}}
; CHECK-NEXT: return $pop3{{$}}
; CHECK-NEXT: i32.load $push[[NUM0:[0-9]+]]=, 0($0){{$}}
; CHECK-NEXT: tee_local $push[[NUM1:[0-9]+]]=, $1=, $pop[[NUM0]]{{$}}
; CHECK-NEXT: i32.const $push[[NUM2:[0-9]+]]=, 4{{$}}
; CHECK-NEXT: i32.add $push[[NUM3:[0-9]+]]=, $pop[[NUM1]], $pop[[NUM2]]{{$}}
; CHECK-NEXT: i32.store $discard=, 0($0), $pop[[NUM3]]{{$}}
; CHECK-NEXT: i32.load $push[[NUM4:[0-9]+]]=, 0($1){{$}}
; CHECK-NEXT: return $pop[[NUM4]]{{$}}
define i8 @arg_i8(i8** %ap) {
entry:
%t = va_arg i8** %ap, i8
@ -72,17 +72,17 @@ entry:
; CHECK-NEXT: .param i32{{$}}
; CHECK-NEXT: .result i32{{$}}
; CHECK-NEXT: .local i32{{$}}
; CHECK-NEXT: i32.load $push0=, 0($0){{$}}
; CHECK-NEXT: i32.const $push1=, 3{{$}}
; CHECK-NEXT: i32.add $push2=, $pop0, $pop1{{$}}
; CHECK-NEXT: i32.const $push3=, -4{{$}}
; CHECK-NEXT: i32.and $push4=, $pop2, $pop3{{$}}
; CHECK-NEXT: tee_local $push8=, $1=, $pop4{{$}}
; CHECK-NEXT: i32.const $push5=, 4{{$}}
; CHECK-NEXT: i32.add $push6=, $pop8, $pop5{{$}}
; CHECK-NEXT: i32.store $discard=, 0($0), $pop6{{$}}
; CHECK-NEXT: i32.load $push7=, 0($1){{$}}
; CHECK-NEXT: return $pop7{{$}}
; CHECK-NEXT: i32.load $push[[NUM0:[0-9]+]]=, 0($0){{$}}
; CHECK-NEXT: i32.const $push[[NUM1:[0-9]+]]=, 3{{$}}
; CHECK-NEXT: i32.add $push[[NUM2:[0-9]+]]=, $pop[[NUM0]], $pop[[NUM1]]{{$}}
; CHECK-NEXT: i32.const $push[[NUM3:[0-9]+]]=, -4{{$}}
; CHECK-NEXT: i32.and $push[[NUM4:[0-9]+]]=, $pop[[NUM2]], $pop[[NUM3]]{{$}}
; CHECK-NEXT: tee_local $push[[NUM5:[0-9]+]]=, $1=, $pop[[NUM4]]{{$}}
; CHECK-NEXT: i32.const $push[[NUM6:[0-9]+]]=, 4{{$}}
; CHECK-NEXT: i32.add $push[[NUM7:[0-9]+]]=, $pop[[NUM5]], $pop[[NUM6]]{{$}}
; CHECK-NEXT: i32.store $discard=, 0($0), $pop[[NUM7]]{{$}}
; CHECK-NEXT: i32.load $push[[NUM8:[0-9]+]]=, 0($1){{$}}
; CHECK-NEXT: return $pop[[NUM8]]{{$}}
define i32 @arg_i32(i8** %ap) {
entry:
%t = va_arg i8** %ap, i32