[SubZero] Handle relocatable constants for MIPS
The patch generates HI/LO modifiers for relocatable constants.
R=stichnot@chromium.org
Review URL: https://codereview.chromium.org/2420033002 .
Patch from Jaydeep Patil <jaydeep.patil@imgtec.com>.
diff --git a/src/IceInstMIPS32.h b/src/IceInstMIPS32.h
index e3f1e82..2e367e9 100644
--- a/src/IceInstMIPS32.h
+++ b/src/IceInstMIPS32.h
@@ -983,14 +983,21 @@
public:
static InstMIPS32Imm16 *create(Cfg *Func, Variable *Dest, Operand *Source,
- uint32_t Imm) {
+ uint32_t Imm, RelocOp Reloc = RO_No) {
return new (Func->allocate<InstMIPS32Imm16>())
- InstMIPS32Imm16(Func, Dest, Source, Imm);
+ InstMIPS32Imm16(Func, Dest, Source, Imm, Reloc);
}
- static InstMIPS32Imm16 *create(Cfg *Func, Variable *Dest, uint32_t Imm) {
+ static InstMIPS32Imm16 *create(Cfg *Func, Variable *Dest, uint32_t Imm,
+ RelocOp Reloc = RO_No) {
return new (Func->allocate<InstMIPS32Imm16>())
- InstMIPS32Imm16(Func, Dest, Imm);
+ InstMIPS32Imm16(Func, Dest, Imm, Reloc);
+ }
+
+ static InstMIPS32Imm16 *create(Cfg *Func, Variable *Dest, Operand *Src0,
+ Operand *Src1, RelocOp Reloc) {
+ return new (Func->allocate<InstMIPS32Imm16>())
+ InstMIPS32Imm16(Func, Dest, Src0, Src1, Reloc);
}
void emit(const Cfg *Func) const override {
@@ -1004,10 +1011,18 @@
getSrc(0)->emit(Func);
}
Str << ", ";
- if (Signed)
- Str << (int32_t)Imm;
- else
- Str << Imm;
+ if (Reloc == RO_No) {
+ if (Signed)
+ Str << (int32_t)Imm;
+ else
+ Str << Imm;
+ } else {
+ auto *CR = llvm::dyn_cast<ConstantRelocatable>(getSrc(1));
+ emitRelocOp(Str, Reloc);
+ Str << "(";
+ CR->emitWithoutPrefix(Func->getTarget());
+ Str << ")";
+ }
}
void emitIAS(const Cfg *Func) const override {
@@ -1022,27 +1037,45 @@
Str << " ";
dumpDest(Func);
Str << ", ";
- dumpSources(Func);
- Str << ", ";
- if (Signed)
- Str << (int32_t)Imm;
- else
- Str << Imm;
+ if (Reloc == RO_No) {
+ dumpSources(Func);
+ Str << ", ";
+ if (Signed)
+ Str << (int32_t)Imm;
+ else
+ Str << Imm;
+ } else {
+ getSrc(0)->dump(Func);
+ Str << ",";
+ emitRelocOp(Str, Reloc);
+ Str << "(";
+ getSrc(1)->dump(Func);
+ Str << ")";
+ }
}
static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
private:
- InstMIPS32Imm16(Cfg *Func, Variable *Dest, Operand *Source, uint32_t Imm)
- : InstMIPS32(Func, K, 1, Dest), Imm(Imm) {
+ InstMIPS32Imm16(Cfg *Func, Variable *Dest, Operand *Source, uint32_t Imm,
+ RelocOp Reloc = RO_No)
+ : InstMIPS32(Func, K, 1, Dest), Reloc(Reloc), Imm(Imm) {
addSource(Source);
}
- InstMIPS32Imm16(Cfg *Func, Variable *Dest, uint32_t Imm)
- : InstMIPS32(Func, K, 0, Dest), Imm(Imm) {}
+ InstMIPS32Imm16(Cfg *Func, Variable *Dest, uint32_t Imm,
+ RelocOp Reloc = RO_No)
+ : InstMIPS32(Func, K, 0, Dest), Reloc(Reloc), Imm(Imm) {}
+
+ InstMIPS32Imm16(Cfg *Func, Variable *Dest, Operand *Src0, Operand *Src1,
+ RelocOp Reloc = RO_No)
+ : InstMIPS32(Func, K, 1, Dest), Reloc(Reloc), Imm(0) {
+ addSource(Src0);
+ addSource(Src1);
+ }
static const char *Opcode;
-
+ const RelocOp Reloc;
const uint32_t Imm;
};
diff --git a/src/IceTargetLoweringMIPS32.cpp b/src/IceTargetLoweringMIPS32.cpp
index 624c4a5..b7d36a6 100644
--- a/src/IceTargetLoweringMIPS32.cpp
+++ b/src/IceTargetLoweringMIPS32.cpp
@@ -4961,10 +4961,10 @@
return From;
}
if (auto *C = llvm::dyn_cast<ConstantRelocatable>(From)) {
- (void)C;
- // TODO(reed kotler): complete this case for proper implementation
Variable *Reg = makeReg(Ty, RegNum);
- Context.insert<InstFakeDef>(Reg);
+ Variable *TReg = makeReg(Ty, RegNum);
+ _lui(TReg, C, RO_Hi);
+ _addiu(Reg, TReg, C, RO_Lo);
return Reg;
} else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(From)) {
const uint32_t Value = C32->getValue();
diff --git a/src/IceTargetLoweringMIPS32.h b/src/IceTargetLoweringMIPS32.h
index 6a50b96..09b981b 100644
--- a/src/IceTargetLoweringMIPS32.h
+++ b/src/IceTargetLoweringMIPS32.h
@@ -216,6 +216,10 @@
Context.insert<InstMIPS32Addiu>(Dest, Src, Imm);
}
+ void _addiu(Variable *Dest, Variable *Src0, Operand *Src1, RelocOp Reloc) {
+ Context.insert<InstMIPS32Addiu>(Dest, Src0, Src1, Reloc);
+ }
+
void _c_eq_d(Variable *Src0, Variable *Src1) {
Context.insert<InstMIPS32C_eq_d>(Src0, Src1);
}
diff --git a/tests_lit/llvm2ice_tests/arith.ll b/tests_lit/llvm2ice_tests/arith.ll
index cf8644b..659b30c 100644
--- a/tests_lit/llvm2ice_tests/arith.ll
+++ b/tests_lit/llvm2ice_tests/arith.ll
@@ -276,6 +276,11 @@
; CHECK-LABEL: ShlReloc
; CHECK: shl {{.*}},cl
+; MIPS32-LABEL: ShlReloc
+; MIPS32: lui [[REG:.*]],{{.*}} R_MIPS_HI16 G
+; MIPS32: addiu [[REG]],[[REG]],{{.*}} R_MIPS_LO16 G
+; MIPS32: sllv {{.*}},{{.*}},[[REG]]
+
define internal i32 @LshrReloc(i32 %a) {
entry:
%opnd = ptrtoint [4 x i8]* @G to i32
@@ -285,6 +290,11 @@
; CHECK-LABEL: LshrReloc
; CHECK: shr {{.*}},cl
+; MIPS32-LABEL: LshrReloc
+; MIPS32: lui [[REG:.*]],{{.*}} R_MIPS_HI16 G
+; MIPS32: addiu [[REG]],[[REG]],{{.*}} R_MIPS_LO16 G
+; MIPS32: srlv {{.*}},{{.*}},[[REG]]
+
define internal i32 @AshrReloc(i32 %a) {
entry:
%opnd = ptrtoint [4 x i8]* @G to i32
@@ -293,3 +303,8 @@
}
; CHECK-LABEL: AshrReloc
; CHECK: sar {{.*}},cl
+
+; MIPS32-LABEL: AshrReloc
+; MIPS32: lui [[REG:.*]],{{.*}} R_MIPS_HI16 G
+; MIPS32: addiu [[REG]],[[REG]],{{.*}} R_MIPS_LO16 G
+; MIPS32: srav {{.*}},{{.*}},[[REG]]