.Case(".cfi_def_cfa", MIToken::kw_cfi_def_cfa)
.Case("blockaddress", MIToken::kw_blockaddress)
.Case("target-index", MIToken::kw_target_index)
+ .Case("half", MIToken::kw_half)
+ .Case("float", MIToken::kw_float)
+ .Case("double", MIToken::kw_double)
+ .Case("x86_fp80", MIToken::kw_x86_fp80)
+ .Case("fp128", MIToken::kw_fp128)
+ .Case("ppc_fp128", MIToken::kw_ppc_fp128)
.Default(MIToken::Identifier);
}
/*PrefixLength=*/1, ErrorCallback);
}
-static Cursor maybeLexIntegerLiteral(Cursor C, MIToken &Token) {
+static bool isValidHexFloatingPointPrefix(char C) {
+ return C == 'H' || C == 'K' || C == 'L' || C == 'M';
+}
+
+static Cursor maybeLexHexFloatingPointLiteral(Cursor C, MIToken &Token) {
+ if (C.peek() != '0' || C.peek(1) != 'x')
+ return None;
+ Cursor Range = C;
+ C.advance(2); // Skip '0x'
+ if (isValidHexFloatingPointPrefix(C.peek()))
+ C.advance();
+ while (isxdigit(C.peek()))
+ C.advance();
+ Token = MIToken(MIToken::FloatingPointLiteral, Range.upto(C));
+ return C;
+}
+
+static Cursor lexFloatingPointLiteral(Cursor Range, Cursor C, MIToken &Token) {
+ C.advance();
+ // Skip over [0-9]*([eE][-+]?[0-9]+)?
+ while (isdigit(C.peek()))
+ C.advance();
+ if ((C.peek() == 'e' || C.peek() == 'E') &&
+ (isdigit(C.peek(1)) ||
+ ((C.peek(1) == '-' || C.peek(1) == '+') && isdigit(C.peek(2))))) {
+ C.advance(2);
+ while (isdigit(C.peek()))
+ C.advance();
+ }
+ Token = MIToken(MIToken::FloatingPointLiteral, Range.upto(C));
+ return C;
+}
+
+static Cursor maybeLexNumericalLiteral(Cursor C, MIToken &Token) {
if (!isdigit(C.peek()) && (C.peek() != '-' || !isdigit(C.peek(1))))
return None;
auto Range = C;
C.advance();
while (isdigit(C.peek()))
C.advance();
+ if (C.peek() == '.')
+ return lexFloatingPointLiteral(Range, C, Token);
StringRef StrVal = Range.upto(C);
Token = MIToken(MIToken::IntegerLiteral, StrVal, APSInt(StrVal));
return C;
return R.remaining();
if (Cursor R = maybeLexExternalSymbol(C, Token, ErrorCallback))
return R.remaining();
- if (Cursor R = maybeLexIntegerLiteral(C, Token))
+ if (Cursor R = maybeLexHexFloatingPointLiteral(C, Token))
+ return R.remaining();
+ if (Cursor R = maybeLexNumericalLiteral(C, Token))
return R.remaining();
if (Cursor R = maybeLexSymbol(C, Token))
return R.remaining();
kw_cfi_def_cfa,
kw_blockaddress,
kw_target_index,
+ kw_half,
+ kw_float,
+ kw_double,
+ kw_x86_fp80,
+ kw_fp128,
+ kw_ppc_fp128,
// Identifier tokens
Identifier,
// Other tokens
IntegerLiteral,
+ FloatingPointLiteral,
VirtualRegister,
ConstantPoolItem,
JumpTableIndex,
#include "MIParser.h"
#include "MILexer.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/AsmParser/Parser.h"
#include "llvm/AsmParser/SlotMapping.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunction.h"
bool parseSubRegisterIndex(unsigned &SubReg);
bool parseRegisterOperand(MachineOperand &Dest, bool IsDef = false);
bool parseImmediateOperand(MachineOperand &Dest);
+ bool parseFPImmediateOperand(MachineOperand &Dest);
bool parseMBBReference(MachineBasicBlock *&MBB);
bool parseMBBOperand(MachineOperand &Dest);
bool parseStackObjectOperand(MachineOperand &Dest);
return false;
}
+bool MIParser::parseFPImmediateOperand(MachineOperand &Dest) {
+ auto Loc = Token.location();
+ lex();
+ if (Token.isNot(MIToken::FloatingPointLiteral))
+ return error("expected a floating point literal");
+ auto Source = StringRef(Loc, Token.stringValue().end() - Loc).str();
+ lex();
+ SMDiagnostic Err;
+ const Constant *C =
+ parseConstantValue(Source.c_str(), Err, *MF.getFunction()->getParent());
+ if (!C)
+ return error(Loc + Err.getColumnNo(), Err.getMessage());
+ Dest = MachineOperand::CreateFPImm(cast<ConstantFP>(C));
+ return false;
+}
+
bool MIParser::getUnsigned(unsigned &Result) {
assert(Token.hasIntegerValue() && "Expected a token with an integer value");
const uint64_t Limit = uint64_t(std::numeric_limits<unsigned>::max()) + 1;
return parseRegisterOperand(Dest);
case MIToken::IntegerLiteral:
return parseImmediateOperand(Dest);
+ case MIToken::kw_half:
+ case MIToken::kw_float:
+ case MIToken::kw_double:
+ case MIToken::kw_x86_fp80:
+ case MIToken::kw_fp128:
+ case MIToken::kw_ppc_fp128:
+ return parseFPImmediateOperand(Dest);
case MIToken::MachineBasicBlock:
return parseMBBOperand(Dest);
case MIToken::StackObject:
case MachineOperand::MO_Immediate:
OS << Op.getImm();
break;
+ case MachineOperand::MO_FPImmediate:
+ Op.getFPImm()->printAsOperand(OS, /*PrintType=*/true, MST);
+ break;
case MachineOperand::MO_MachineBasicBlock:
printMBBReference(*Op.getMBB());
break;
--- /dev/null
+# RUN: not llc -march=nvptx -mcpu=sm_20 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
+
+--- |
+
+ define float @test(float %k) {
+ entry:
+ %0 = fadd float %k, 3.250000e+00
+ ret float %0
+ }
+
+...
+---
+name: test
+registers:
+ - { id: 0, class: float32regs }
+ - { id: 1, class: float32regs }
+body:
+ - id: 0
+ name: entry
+ instructions:
+ - '%0 = LD_f32_avar 0, 4, 1, 2, 32, $test_param_0'
+# CHECK: [[@LINE+1]]:38: expected a floating point literal
+ - '%1 = FADD_rnf32ri %0, float 3'
+ - 'StoreRetvalF32 %1, 0'
+ - Return
+...
--- /dev/null
+# RUN: llc -march=nvptx -mcpu=sm_20 -start-after branch-folder -stop-after branch-folder -o /dev/null %s | FileCheck %s
+# This test ensures that the MIR parser parses floating point constant operands
+# correctly.
+
+--- |
+
+ define float @test(float %k, i32 %i) {
+ entry:
+ %0 = fpext float %k to double
+ %1 = fadd double %0, 3.250000e+00
+ %2 = fptrunc double %1 to float
+ %3 = sitofp i32 %i to float
+ %4 = fadd float %3, 6.250000e+00
+ %5 = fmul float %4, %2
+ ret float %5
+ }
+
+ define float @test2(float %k, i32 %i) {
+ entry:
+ %0 = fpext float %k to double
+ %1 = fadd double %0, 0x7FF8000000000000
+ %2 = fptrunc double %1 to float
+ %3 = sitofp i32 %i to float
+ %4 = fadd float %3, 0x7FF8000000000000
+ %5 = fmul float %4, %2
+ ret float %5
+ }
+
+...
+---
+name: test
+registers:
+ - { id: 0, class: float32regs }
+ - { id: 1, class: float64regs }
+ - { id: 2, class: int32regs }
+ - { id: 3, class: float64regs }
+ - { id: 4, class: float32regs }
+ - { id: 5, class: float32regs }
+ - { id: 6, class: float32regs }
+ - { id: 7, class: float32regs }
+body:
+ - id: 0
+ name: entry
+ instructions:
+ - '%0 = LD_f32_avar 0, 4, 1, 2, 32, $test_param_0'
+ - '%1 = CVT_f64_f32 %0, 0'
+ - '%2 = LD_i32_avar 0, 4, 1, 0, 32, $test_param_1'
+# CHECK: %3 = FADD_rnf64ri %1, double 3.250000e+00
+ - '%3 = FADD_rnf64ri %1, double 3.250000e+00'
+ - '%4 = CVT_f32_f64 %3, 5'
+ - '%5 = CVT_f32_s32 %2, 5'
+# CHECK: %6 = FADD_rnf32ri %5, float 6.250000e+00
+ - '%6 = FADD_rnf32ri %5, float 6.250000e+00'
+ - '%7 = FMUL_rnf32rr %6, %4'
+ - 'StoreRetvalF32 %7, 0'
+ - Return
+...
+---
+name: test2
+registers:
+ - { id: 0, class: float32regs }
+ - { id: 1, class: float64regs }
+ - { id: 2, class: int32regs }
+ - { id: 3, class: float64regs }
+ - { id: 4, class: float32regs }
+ - { id: 5, class: float32regs }
+ - { id: 6, class: float32regs }
+ - { id: 7, class: float32regs }
+body:
+ - id: 0
+ name: entry
+ instructions:
+ - '%0 = LD_f32_avar 0, 4, 1, 2, 32, $test2_param_0'
+ - '%1 = CVT_f64_f32 %0, 0'
+ - '%2 = LD_i32_avar 0, 4, 1, 0, 32, $test2_param_1'
+# CHECK: %3 = FADD_rnf64ri %1, double 0x7FF8000000000000
+ - '%3 = FADD_rnf64ri %1, double 0x7FF8000000000000'
+ - '%4 = CVT_f32_f64 %3, 5'
+ - '%5 = CVT_f32_s32 %2, 5'
+# CHECK: %6 = FADD_rnf32ri %5, float 0x7FF8000000000000
+ - '%6 = FADD_rnf32ri %5, float 0x7FF8000000000000'
+ - '%7 = FMUL_rnf32rr %6, %4'
+ - 'StoreRetvalF32 %7, 0'
+ - Return
+...
--- /dev/null
+# RUN: not llc -march=nvptx -mcpu=sm_20 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
+
+--- |
+
+ define float @test(float %k) {
+ entry:
+ %0 = fadd float %k, 3.250000e+00
+ ret float %0
+ }
+
+...
+---
+name: test
+registers:
+ - { id: 0, class: float32regs }
+ - { id: 1, class: float32regs }
+body:
+ - id: 0
+ name: entry
+ instructions:
+ - '%0 = LD_f32_avar 0, 4, 1, 2, 32, $test_param_0'
+# CHECK: [[@LINE+1]]:38: floating point constant does not have type 'float'
+ - '%1 = FADD_rnf32ri %0, float 0xH3C00'
+ - 'StoreRetvalF32 %1, 0'
+ - Return
+...
--- /dev/null
+if not 'NVPTX' in config.root.targets:
+ config.unsupported = True