llvm.org GIT mirror llvm / 2fee935
[Sparc] Emit large negative adjustments to SP/FP with sethi+xor instead of sethi+or. This generates correct code for both sparc32 and sparc64. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@195576 91177308-0d34-0410-b5e6-96231b3b80d8 Venkatraman Govindaraju 5 years ago
5 changed file(s) with 131 addition(s) and 42 deletion(s). Raw diff Collapse all Expand all
104104 }
105105 llvm_unreachable("Invalid cond code");
106106 }
107
108 inline static unsigned HI22(int64_t imm) {
109 return (unsigned)((imm >> 10) & ((1 << 22)-1));
110 }
111
112 inline static unsigned LO10(int64_t imm) {
113 return (unsigned)(imm & 0x3FF);
114 }
115
116 inline static unsigned HIX22(int64_t imm) {
117 return HI22(~imm);
118 }
119
120 inline static unsigned LOX10(int64_t imm) {
121 return ~LO10(~imm);
122 }
123
107124 } // end namespace llvm
108125 #endif
3232 cl::Hidden);
3333
3434
35 void SparcFrameLowering::emitSPAdjustment(MachineFunction &MF,
36 MachineBasicBlock &MBB,
37 MachineBasicBlock::iterator MBBI,
38 int NumBytes,
39 unsigned ADDrr,
40 unsigned ADDri) const {
41
42 DebugLoc dl = (MBBI != MBB.end()) ? MBBI->getDebugLoc() : DebugLoc();
43 const SparcInstrInfo &TII =
44 *static_cast(MF.getTarget().getInstrInfo());
45
46 if (NumBytes >= -4096 && NumBytes < 4096) {
47 BuildMI(MBB, MBBI, dl, TII.get(ADDri), SP::O6)
48 .addReg(SP::O6).addImm(NumBytes);
49 return;
50 }
51
52 // Emit this the hard way. This clobbers G1 which we always know is
53 // available here.
54 if (NumBytes >= 0) {
55 // Emit nonnegative numbers with sethi + or.
56 // sethi %hi(NumBytes), %g1
57 // or %g1, %lo(NumBytes), %g1
58 // add %sp, %g1, %sp
59 BuildMI(MBB, MBBI, dl, TII.get(SP::SETHIi), SP::G1)
60 .addImm(HI22(NumBytes));
61 BuildMI(MBB, MBBI, dl, TII.get(SP::ORri), SP::G1)
62 .addReg(SP::G1).addImm(LO10(NumBytes));
63 BuildMI(MBB, MBBI, dl, TII.get(ADDrr), SP::O6)
64 .addReg(SP::O6).addReg(SP::G1);
65 return ;
66 }
67
68 // Emit negative numbers with sethi + xor.
69 // sethi %hix(NumBytes), %g1
70 // xor %g1, %lox(NumBytes), %g1
71 // add %sp, %g1, %sp
72 BuildMI(MBB, MBBI, dl, TII.get(SP::SETHIi), SP::G1)
73 .addImm(HIX22(NumBytes));
74 BuildMI(MBB, MBBI, dl, TII.get(SP::XORri), SP::G1)
75 .addReg(SP::G1).addImm(LOX10(NumBytes));
76 BuildMI(MBB, MBBI, dl, TII.get(ADDrr), SP::O6)
77 .addReg(SP::O6).addReg(SP::G1);
78 }
79
3580 void SparcFrameLowering::emitPrologue(MachineFunction &MF) const {
3681 SparcMachineFunctionInfo *FuncInfo = MF.getInfo();
3782
5499 SAVErr = SP::ADDrr;
55100 }
56101 NumBytes = - SubTarget.getAdjustedFrameSize(NumBytes);
57
58 if (NumBytes >= -4096) {
59 BuildMI(MBB, MBBI, dl, TII.get(SAVEri), SP::O6)
60 .addReg(SP::O6).addImm(NumBytes);
61 } else {
62 // Emit this the hard way. This clobbers G1 which we always know is
63 // available here.
64 unsigned OffHi = (unsigned)NumBytes >> 10U;
65 BuildMI(MBB, MBBI, dl, TII.get(SP::SETHIi), SP::G1).addImm(OffHi);
66 // Emit G1 = G1 + I6
67 BuildMI(MBB, MBBI, dl, TII.get(SP::ORri), SP::G1)
68 .addReg(SP::G1).addImm(NumBytes & ((1 << 10)-1));
69 BuildMI(MBB, MBBI, dl, TII.get(SAVErr), SP::O6)
70 .addReg(SP::O6).addReg(SP::G1);
71 }
102 emitSPAdjustment(MF, MBB, MBBI, NumBytes, SAVErr, SAVEri);
103
72104 MachineModuleInfo &MMI = MF.getMMI();
73105 const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo();
74106 MCSymbol *FrameLabel = MMI.getContext().CreateTempSymbol();
99131 int Size = MI.getOperand(0).getImm();
100132 if (MI.getOpcode() == SP::ADJCALLSTACKDOWN)
101133 Size = -Size;
102 const SparcInstrInfo &TII =
103 *static_cast(MF.getTarget().getInstrInfo());
134
104135 if (Size)
105 BuildMI(MBB, I, DL, TII.get(SP::ADDri), SP::O6).addReg(SP::O6)
106 .addImm(Size);
136 emitSPAdjustment(MF, MBB, I, Size, SP::ADDrr, SP::ADDri);
107137 }
108138 MBB.erase(I);
109139 }
130160 return;
131161
132162 NumBytes = SubTarget.getAdjustedFrameSize(NumBytes);
133
134 if (NumBytes < 4096) {
135 BuildMI(MBB, MBBI, dl, TII.get(SP::ADDri), SP::O6)
136 .addReg(SP::O6).addImm(NumBytes);
137 } else {
138 // Emit this the hard way. This clobbers G1 which we always know is
139 // available here.
140 unsigned OffHi = (unsigned)NumBytes >> 10U;
141 BuildMI(MBB, MBBI, dl, TII.get(SP::SETHIi), SP::G1).addImm(OffHi);
142 // Emit G1 = G1 + I6
143 BuildMI(MBB, MBBI, dl, TII.get(SP::ORri), SP::G1)
144 .addReg(SP::G1).addImm(NumBytes & ((1 << 10)-1));
145 BuildMI(MBB, MBBI, dl, TII.get(SP::ADDrr), SP::O6)
146 .addReg(SP::O6).addReg(SP::G1);
147 }
163 emitSPAdjustment(MF, MBB, MBBI, NumBytes, SP::ADDrr, SP::ADDri);
148164 }
149165
150166 bool SparcFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
4848
4949 // Returns true if MF is a leaf procedure.
5050 bool isLeafProc(MachineFunction &MF) const;
51
52
53 // Emits code for adjusting SP in function prologue/epilogue.
54 void emitSPAdjustment(MachineFunction &MF,
55 MachineBasicBlock &MBB,
56 MachineBasicBlock::iterator MBBI,
57 int NumBytes, unsigned ADDrr, unsigned ADDri) const;
58
5159 };
5260
5361 } // End llvm namespace
104104 // encode it.
105105 MI.getOperand(FIOperandNum).ChangeToRegister(FramePtr, false);
106106 MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
107 } else {
108 // Otherwise, emit a G1 = SETHI %hi(offset). FIXME: it would be better to
109 // scavenge a register here instead of reserving G1 all of the time.
110 const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
111 unsigned OffHi = (unsigned)Offset >> 10U;
112 BuildMI(*MI.getParent(), II, dl, TII.get(SP::SETHIi), SP::G1).addImm(OffHi);
107 return;
108 }
109
110 const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
111
112 // FIXME: it would be better to scavenge a register here instead of
113 // reserving G1 all of the time.
114 if (Offset >= 0) {
115 // Emit nonnegaive immediates with sethi + or.
116 // sethi %hi(Offset), %g1
117 // add %g1, %fp, %g1
118 // Insert G1+%lo(offset) into the user.
119 BuildMI(*MI.getParent(), II, dl, TII.get(SP::SETHIi), SP::G1)
120 .addImm(HI22(Offset));
121
122
113123 // Emit G1 = G1 + I6
114124 BuildMI(*MI.getParent(), II, dl, TII.get(SP::ADDrr), SP::G1).addReg(SP::G1)
115125 .addReg(FramePtr);
116126 // Insert: G1+%lo(offset) into the user.
117127 MI.getOperand(FIOperandNum).ChangeToRegister(SP::G1, false);
118 MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset & ((1 << 10)-1));
119 }
128 MI.getOperand(FIOperandNum + 1).ChangeToImmediate(LO10(Offset));
129 return;
130 }
131
132 // Emit Negative numbers with sethi + xor
133 // sethi %hix(Offset), %g1
134 // xor %g1, %lox(offset), %g1
135 // add %g1, %fp, %g1
136 // Insert: G1 + 0 into the user.
137 BuildMI(*MI.getParent(), II, dl, TII.get(SP::SETHIi), SP::G1)
138 .addImm(HIX22(Offset));
139 BuildMI(*MI.getParent(), II, dl, TII.get(SP::XORri), SP::G1)
140 .addReg(SP::G1).addImm(LOX10(Offset));
141
142 BuildMI(*MI.getParent(), II, dl, TII.get(SP::ADDrr), SP::G1).addReg(SP::G1)
143 .addReg(FramePtr);
144 // Insert: G1+%lo(offset) into the user.
145 MI.getOperand(FIOperandNum).ChangeToRegister(SP::G1, false);
146 MI.getOperand(FIOperandNum + 1).ChangeToImmediate(0);
120147 }
121148
122149
389389 %2 = add nsw i32 %0, %1
390390 ret i32 %2
391391 }
392
393 ; CHECK-LABEL: test_large_stack
394
395 ; CHECK: sethi 16, %g1
396 ; CHECK: xor %g1, -176, %g1
397 ; CHECK: save %sp, %g1, %sp
398
399 ; CHECK: sethi 14, %g1
400 ; CHECK: xor %g1, -1, %g1
401 ; CHECK: add %g1, %fp, %g1
402 ; CHECK: call use_buf
403
404 define i32 @test_large_stack() {
405 entry:
406 %buffer1 = alloca [16384 x i8], align 8
407 %buffer1.sub = getelementptr inbounds [16384 x i8]* %buffer1, i32 0, i32 0
408 %0 = call i32 @use_buf(i32 16384, i8* %buffer1.sub)
409 ret i32 %0
410 }
411
412 declare i32 @use_buf(i32, i8*)