Fixes LDR and STR instructions. Two types of mistakes were being made.
First, the width was not being correctly defined for non-vector
instructions.
Second, the order of the width/condition was incorrect when the
instruction was prefixed with a V. That is, for V prefixed instructions,
the order is predicate/width while for non-V prefixed instructions the
order is width/predicate.
Also fixes bug in target lowering that did not always convert results
of a compare to i1.
BUG= https://bugs.chromium.org/p/nativeclient/issues/detail?id=4334
R=stichnot@chromium.org
Review URL: https://codereview.chromium.org/1415953007 .
diff --git a/src/IceAssemblerARM32.cpp b/src/IceAssemblerARM32.cpp
index 338022f..1dab8b8 100644
--- a/src/IceAssemblerARM32.cpp
+++ b/src/IceAssemblerARM32.cpp
@@ -705,6 +705,7 @@
// ldr<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0
// ldr<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1
// ldr<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1
+ //
// LDRB (immediate) - ARM section A8.8.68, encoding A1:
// ldrb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0
// ldrb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1
@@ -716,7 +717,7 @@
const Type Ty = OpRt->getType();
if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand?
return setNeedsTextFixup();
- const bool IsByte = typeWidthInBytes(Ty) == 1;
+ const bool IsByte = isByteSizedType(Ty);
// Check conditions of rules violated.
if (getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_pc)
return setNeedsTextFixup();
@@ -873,7 +874,7 @@
const Type Ty = OpRt->getType();
if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand?
return setNeedsTextFixup();
- const bool IsByte = typeWidthInBytes(Ty) == 1;
+ const bool IsByte = isByteSizedType(Ty);
// Check for rule violations.
if ((getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_pc))
return setNeedsTextFixup();
diff --git a/src/IceInstARM32.cpp b/src/IceInstARM32.cpp
index 9e6a480..376a2cf 100644
--- a/src/IceInstARM32.cpp
+++ b/src/IceInstARM32.cpp
@@ -700,15 +700,14 @@
Variable *Dest = getDest();
if (Dest->hasReg()) {
- Type DestTy = Dest->getType();
+ Type Ty = Dest->getType();
Operand *Src0 = getSrc(0);
- const bool DestIsVector = isVectorType(DestTy);
- const bool DestIsScalarFP = isScalarFloatingType(Dest->getType());
+ const bool IsVector = isVectorType(Ty);
+ const bool IsScalarFP = isScalarFloatingType(Ty);
const bool CoreVFPMove = isMoveBetweenCoreAndVFPRegisters(Dest, Src0);
- const char *LoadOpcode =
- DestIsVector ? "vld1" : (DestIsScalarFP ? "vldr" : "ldr");
- const char *RegMovOpcode =
- (DestIsVector || DestIsScalarFP || CoreVFPMove) ? "vmov" : "mov";
+ const char *LoadOpcode = IsVector ? "vld1" : (IsScalarFP ? "vldr" : "ldr");
+ const bool IsVMove = (IsVector || IsScalarFP || CoreVFPMove);
+ const char *RegMovOpcode = IsVMove ? "vmov" : "mov";
const char *ActualOpcode = isMemoryAccess(Src0) ? LoadOpcode : RegMovOpcode;
// when vmov{c}'ing, we need to emit a width string. Otherwise, the
// assembler might be tempted to assume we want a vector vmov{c}, and that
@@ -716,24 +715,36 @@
const char *NoWidthString = "";
const char *WidthString =
isMemoryAccess(Src0)
- ? (DestIsVector ? ".64" : NoWidthString)
- : (!CoreVFPMove ? getVecWidthString(DestTy) : NoWidthString);
-
- Str << "\t" << ActualOpcode << getPredicate() << WidthString << "\t";
+ ? (IsVector ? ".64" : getWidthString(Ty))
+ : (!CoreVFPMove ? getVecWidthString(Ty) : NoWidthString);
+ Str << "\t" << ActualOpcode;
+ const bool IsVInst = IsVMove || IsVector || IsScalarFP;
+ if (IsVInst) {
+ Str << getPredicate() << WidthString;
+ } else {
+ Str << WidthString << getPredicate();
+ }
+ Str << "\t";
Dest->emit(Func);
Str << ", ";
Src0->emit(Func);
} else {
Variable *Src0 = llvm::cast<Variable>(getSrc(0));
assert(Src0->hasReg());
+ Type Ty = Src0->getType();
+ const bool IsVector = isVectorType(Ty);
+ const bool IsScalarFP = isScalarFloatingType(Ty);
const char *ActualOpcode =
- isVectorType(Src0->getType())
- ? "vst1"
- : (isScalarFloatingType(Src0->getType()) ? "vstr" : "str");
- const char *NoWidthString = "";
- const char *WidthString =
- isVectorType(Src0->getType()) ? ".64" : NoWidthString;
- Str << "\t" << ActualOpcode << getPredicate() << WidthString << "\t";
+ IsVector ? "vst1" : (IsScalarFP ? "vstr" : "str");
+ const char *WidthString = IsVector ? ".64" : getWidthString(Ty);
+ Str << "\t" << ActualOpcode;
+ const bool IsVInst = IsVector || IsScalarFP;
+ if (IsVInst) {
+ Str << getPredicate() << WidthString;
+ } else {
+ Str << WidthString << getPredicate();
+ }
+ Str << "\t";
Src0->emit(Func);
Str << ", ";
Dest->emit(Func);
@@ -955,15 +966,21 @@
assert(getSrcSize() == 1);
assert(getDest()->hasReg());
Variable *Dest = getDest();
- Type DestTy = Dest->getType();
- const bool DestIsVector = isVectorType(DestTy);
- const bool DestIsScalarFloat = isScalarFloatingType(DestTy);
+ Type Ty = Dest->getType();
+ const bool IsVector = isVectorType(Ty);
+ const bool IsScalarFloat = isScalarFloatingType(Ty);
const char *ActualOpcode =
- DestIsVector ? "vld1" : (DestIsScalarFloat ? "vldr" : "ldr");
- const char *VectorMarker = DestIsVector ? ".64" : "";
- const char *WidthString = DestIsVector ? "" : getWidthString(DestTy);
- Str << "\t" << ActualOpcode << WidthString << getPredicate() << VectorMarker
- << "\t";
+ IsVector ? "vld1" : (IsScalarFloat ? "vldr" : "ldr");
+ const char *VectorMarker = IsVector ? ".64" : "";
+ const char *WidthString = IsVector ? "" : getWidthString(Ty);
+ Str << "\t" << ActualOpcode;
+ const bool IsVInst = IsVector || IsScalarFloat;
+ if (IsVInst) {
+ Str << getPredicate() << WidthString;
+ } else {
+ Str << WidthString << getPredicate();
+ }
+ Str << VectorMarker << "\t";
getDest()->emit(Func);
Str << ", ";
getSrc(0)->emit(Func);
@@ -1270,11 +1287,18 @@
assert(getSrcSize() == 2);
Type Ty = getSrc(0)->getType();
const bool IsVectorStore = isVectorType(Ty);
+ const bool IsScalarFloat = isScalarFloatingType(Ty);
const char *Opcode =
- IsVectorStore ? "vst1" : (isScalarFloatingType(Ty) ? "vstr" : "str");
+ IsVectorStore ? "vst1" : (IsScalarFloat ? "vstr" : "str");
const char *VecEltWidthString = IsVectorStore ? ".64" : "";
- Str << "\t" << Opcode << getWidthString(Ty) << getPredicate()
- << VecEltWidthString << "\t";
+ Str << "\t" << Opcode;
+ const bool IsVInst = IsVectorStore || IsScalarFloat;
+ if (IsVInst) {
+ Str << getPredicate() << getWidthString(Ty);
+ } else {
+ Str << getWidthString(Ty) << getPredicate();
+ }
+ Str << VecEltWidthString << "\t";
getSrc(0)->emit(Func);
Str << ", ";
getSrc(1)->emit(Func);
diff --git a/src/IceTargetLoweringARM32.cpp b/src/IceTargetLoweringARM32.cpp
index 31ef0c0..d2aa74e 100644
--- a/src/IceTargetLoweringARM32.cpp
+++ b/src/IceTargetLoweringARM32.cpp
@@ -2506,7 +2506,7 @@
return;
}
- Variable *T = makeReg(IceType_i32);
+ Variable *T = makeReg(IceType_i1);
Operand *_1 = Ctx->getConstantInt32(1);
Operand *_0 = Ctx->getConstantZero(IceType_i32);
@@ -2672,7 +2672,7 @@
Constant *_0 = Ctx->getConstantZero(IceType_i32);
Constant *_1 = Ctx->getConstantInt32(1);
- Variable *T = makeReg(IceType_i32);
+ Variable *T = makeReg(IceType_i1);
CondARM32::Cond CondIfTrue, CondIfFalse;
lowerIcmpCond(Inst, &CondIfTrue, &CondIfFalse);
diff --git a/tests_lit/assembler/arm32/branch-mult-fwd.ll b/tests_lit/assembler/arm32/branch-mult-fwd.ll
index b0cf629..89c495d 100644
--- a/tests_lit/assembler/arm32/branch-mult-fwd.ll
+++ b/tests_lit/assembler/arm32/branch-mult-fwd.ll
@@ -57,14 +57,14 @@
; ASM-NEXT: cmp r0, r1
; ASM-NEXT: movge r0, #0
; ASM-NEXT: movlt r0, #1
-; ASM-NEXT: str r0, [sp]
+; ASM-NEXT: strb r0, [sp]
; DIS-NEXT: c: e59d0008
; DIS-NEXT: 10: e59d1004
; DIS-NEXT: 14: e1500001
; DIS-NEXT: 18: a3a00000
; DIS-NEXT: 1c: b3a00001
-; DIS-NEXT: 20: e58d0000
+; DIS-NEXT: 20: e5cd0000
; IASM-NEXT: .byte 0x8
; IASM-NEXT: .byte 0x0
@@ -91,26 +91,23 @@
; IASM-NEXT: .byte 0xa0
; IASM-NEXT: .byte 0xb3
-; IASM-NEXT: .byte 0x0
-; IASM-NEXT: .byte 0x0
-; IASM-NEXT: .byte 0x8d
-; IASM-NEXT: .byte 0xe5
+; IASM-NEXT: strb r0, [sp]
br i1 %cmp, label %then, label %else
-; ASM-NEXT: ldr r0, [sp]
+; ASM-NEXT: ldrb r0, [sp]
; ASM-NEXT: uxtb r0, r0
; ASM-NEXT: cmp r0, #0
; ASM-NEXT: bne .Lmult_fwd_branches$then
; ASM-NEXT: b .Lmult_fwd_branches$else
-; DIS-NEXT: 24: e59d0000
+; DIS-NEXT: 24: e5dd0000
; DIS-NEXT: 28: e6ef0070
; DIS-NEXT: 2c: e3500000
; DIS-NEXT: 30: 1a000000
; DIS-NEXT: 34: ea000000
-; IASM-NEXT: ldr r0, [sp]
+; IASM-NEXT: ldrb r0, [sp]
; IASM-NEXT: uxtb r0, r0
; IASM-NEXT: .byte 0x0
diff --git a/tests_lit/llvm2ice_tests/nacl-atomic-intrinsics.ll b/tests_lit/llvm2ice_tests/nacl-atomic-intrinsics.ll
index d3c228c..0415c25 100644
--- a/tests_lit/llvm2ice_tests/nacl-atomic-intrinsics.ll
+++ b/tests_lit/llvm2ice_tests/nacl-atomic-intrinsics.ll
@@ -1068,7 +1068,7 @@
; ARM32: ldrexb
; ARM32: cmp
; ARM32: strexbeq
-; ARM32: {{str|mov}}ne
+; ARM32: {{strb|mov}}ne
; ARM32: cmpeq
; ARM32: bne
; ARM32: dmb
@@ -1092,7 +1092,7 @@
; ARM32: ldrexh
; ARM32: cmp
; ARM32: strexheq
-; ARM32: {{str|mov}}ne
+; ARM32: {{strh|mov}}ne
; ARM32: cmpeq
; ARM32: bne
; ARM32: dmb