Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 5 additions & 12 deletions llvm/test/TableGen/HwModeEncodeDecode3.td
Original file line number Diff line number Diff line change
Expand Up @@ -230,28 +230,22 @@ def unrelated: Instruction {
// ENCODER: default: llvm_unreachable("Unhandled HwMode");
// ENCODER: case 0: {
// ENCODER: op = getMachineOpValue(MI, MI.getOperand(0), Fixups, STI);
// ENCODER: op &= UINT64_C(240);
// ENCODER: Value |= op;
// ENCODER: Value |= (op & 0xf0);
// ENCODER: break;
// ENCODER: }
// ENCODER: case 1: {
// ENCODER: op = getMachineOpValue(MI, MI.getOperand(0), Fixups, STI);
// ENCODER: op &= UINT64_C(240);
// ENCODER: Value |= op;
// ENCODER: Value |= (op & 0xf0);
// ENCODER: break;
// ENCODER: }
// ENCODER: case 2: {
// ENCODER: op = getMachineOpValue(MI, MI.getOperand(0), Fixups, STI);
// ENCODER: op &= UINT64_C(255);
// ENCODER: op <<= 8;
// ENCODER: Value |= op;
// ENCODER: Value |= (op & 0xff) << 8;
// ENCODER: break;
// ENCODER: }
// ENCODER: case 3: {
// ENCODER: op = getMachineOpValue(MI, MI.getOperand(0), Fixups, STI);
// ENCODER: op &= UINT64_C(255);
// ENCODER: op <<= 24;
// ENCODER: Value |= op;
// ENCODER: Value |= (op & 0xff) << 24;
// ENCODER: break;
// ENCODER: }
// ENCODER-LABEL: case ::baz: {
Expand All @@ -265,7 +259,6 @@ def unrelated: Instruction {
// ENCODER: default: llvm_unreachable("Unhandled HwMode");
// ENCODER: case 2: {
// ENCODER: op = getMachineOpValue(MI, MI.getOperand(0), Fixups, STI);
// ENCODER: op &= UINT64_C(240);
// ENCODER: Value |= op;
// ENCODER: Value |= (op & 0xf0);
// ENCODER: break;
// ENCODER: }
9 changes: 3 additions & 6 deletions llvm/test/TableGen/RegisterEncoder.td
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ def foo1 : Instruction {

// CHECK: case ::foo1: {
// CHECK: op = barEncoder
// CHECK: op &= UINT64_C(255);
// CHECK: Value |= op;
// CHECK: Value |= (op & 0xff);
// CHECK: break;
// CHECK: }

Expand All @@ -57,10 +56,8 @@ def foo2 : Instruction {

// CHECK: case ::foo2: {
// CHECK: op = barEncoder
// CHECK: op &= UINT64_C(15);
// CHECK: Value |= op;
// CHECK: Value |= (op & 0xf);
// CHECK: op = barEncoder
// CHECK: op &= UINT64_C(15);
// CHECK: Value |= op;
// CHECK: Value |= (op & 0xf) << 4;
// CHECK: break;
// CHECK: }
118 changes: 31 additions & 87 deletions llvm/utils/TableGen/CodeEmitterGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TableGen/Error.h"
Expand Down Expand Up @@ -139,58 +140,28 @@ bool CodeEmitterGen::addCodeToMergeInOperand(const Record *R,
StringRef EncoderMethodName =
CGI.Operands[SO.first].EncoderMethodNames[SO.second];

if (UseAPInt)
Case += " op.clearAllBits();\n";
raw_string_ostream OS(Case);
indent Indent(6);

OS << Indent << "// op: " << VarName << '\n';

Case += " // op: " + VarName + "\n";
if (UseAPInt)
OS << Indent << "op.clearAllBits();\n";

// If the source operand has a custom encoder, use it.
if (!EncoderMethodName.empty()) {
raw_string_ostream CaseOS(Case);
CaseOS << indent(6);
if (UseAPInt)
CaseOS << EncoderMethodName << "(MI, " << OpIdx << ", op";
OS << Indent << EncoderMethodName << "(MI, " << OpIdx
<< ", op, Fixups, STI);\n";
else
CaseOS << "op = " << EncoderMethodName << "(MI, " << OpIdx;
CaseOS << ", Fixups, STI);\n";
OS << Indent << "op = " << EncoderMethodName << "(MI, " << OpIdx
<< ", Fixups, STI);\n";
} else {
if (UseAPInt) {
Case +=
" getMachineOpValue(MI, MI.getOperand(" + utostr(OpIdx) + ")";
Case += ", op, Fixups, STI";
} else {
Case += " op = getMachineOpValue(MI, MI.getOperand(" +
utostr(OpIdx) + ")";
Case += ", Fixups, STI";
}
Case += ");\n";
}

// Precalculate the number of lits this variable contributes to in the
// operand. If there is a single lit (consecutive range of bits) we can use a
// destructive sequence on APInt that reduces memory allocations.
int NumOperandLits = 0;
for (int TmpBit = Bit; TmpBit >= 0;) {
int VarBit = getVariableBit(VarName, BI, TmpBit);

// If this bit isn't from a variable, skip it.
if (VarBit == -1) {
--TmpBit;
continue;
}

// Figure out the consecutive range of bits covered by this operand, in
// order to generate better encoding code.
int BeginVarBit = VarBit;
int N = 1;
for (--TmpBit; TmpBit >= 0;) {
VarBit = getVariableBit(VarName, BI, TmpBit);
if (VarBit == -1 || VarBit != (BeginVarBit - N))
break;
++N;
--TmpBit;
}
++NumOperandLits;
if (UseAPInt)
OS << Indent << "getMachineOpValue(MI, MI.getOperand(" << OpIdx
<< "), op, Fixups, STI);\n";
else
OS << Indent << "op = getMachineOpValue(MI, MI.getOperand(" << OpIdx
<< "), Fixups, STI);\n";
}

unsigned BitOffset = -1;
Expand All @@ -216,52 +187,25 @@ bool CodeEmitterGen::addCodeToMergeInOperand(const Record *R,
--Bit;
}

std::string MaskStr;
int OpShift;

unsigned LoBit = BeginVarBit - N + 1;
unsigned HiBit = LoBit + N;
unsigned LoInstBit = BeginInstBit - N + 1;
BitOffset = LoInstBit;
if (UseAPInt) {
std::string ExtractStr;
if (N >= 64) {
ExtractStr = "op.extractBits(" + itostr(HiBit - LoBit) + ", " +
itostr(LoBit) + ")";
Case += " Value.insertBits(" + ExtractStr + ", " +
itostr(LoInstBit) + ");\n";
} else {
ExtractStr = "op.extractBitsAsZExtValue(" + itostr(HiBit - LoBit) +
", " + itostr(LoBit) + ")";
Case += " Value.insertBits(" + ExtractStr + ", " +
itostr(LoInstBit) + ", " + itostr(HiBit - LoBit) + ");\n";
}
if (N > 64)
OS << Indent << "Value.insertBits(op.extractBits(" << N << ", " << LoBit
<< "), " << LoInstBit << ");\n";
else
OS << Indent << "Value.insertBits(op.extractBitsAsZExtValue(" << N
<< ", " << LoBit << "), " << LoInstBit << ", " << N << ");\n";
} else {
uint64_t OpMask = ~(uint64_t)0 >> (64 - N);
OpShift = BeginVarBit - N + 1;
OpMask <<= OpShift;
MaskStr = "UINT64_C(" + utostr(OpMask) + ")";
OpShift = BeginInstBit - BeginVarBit;

if (NumOperandLits == 1) {
Case += " op &= " + MaskStr + ";\n";
if (OpShift > 0) {
Case += " op <<= " + itostr(OpShift) + ";\n";
} else if (OpShift < 0) {
Case += " op >>= " + itostr(-OpShift) + ";\n";
}
Case += " Value |= op;\n";
} else {
if (OpShift > 0) {
Case += " Value |= (op & " + MaskStr + ") << " +
itostr(OpShift) + ";\n";
} else if (OpShift < 0) {
Case += " Value |= (op & " + MaskStr + ") >> " +
itostr(-OpShift) + ";\n";
} else {
Case += " Value |= (op & " + MaskStr + ");\n";
}
}
uint64_t OpMask = maskTrailingOnes<uint64_t>(N) << LoBit;
OS << Indent << "Value |= (op & " << format_hex(OpMask, 0) << ')';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q: If OpMask is > 32 bits, will the lack of UINT64_C cause issues (i.e, warning and/or the upper bits being lost?)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess not, since op is uint64_t here, so it will get interpreted as a uint64_t.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, the usual promotion rules apply, there should be no warnings or bit losses

int OpShift = BeginInstBit - BeginVarBit;
if (OpShift > 0)
OS << " << " << OpShift;
else if (OpShift < 0)
OS << " >> " << -OpShift;
OS << ";\n";
}
}

Expand Down