Skip to content

Commit 0314e89

Browse files
kaz7Simon Moll
authored andcommitted
[VE] Support floating point immediate values
Summary: Add simm7fp/mimmfp to represent floating point immediate values. Also clean multiclasses to define floating point arithmetic instructions to handle simm7fp/mimmfp operands. Also add several regression tests for new operands. Differential Revision: https://reviews.llvm.org/D78887
1 parent 45d9280 commit 0314e89

File tree

4 files changed

+162
-63
lines changed

4 files changed

+162
-63
lines changed

llvm/lib/Target/VE/VEInstrInfo.td

Lines changed: 89 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,47 @@ def mimm : Operand<i32>, PatLeaf<(imm), [{
7070
let PrintMethod = "printMImmOperand";
7171
}
7272

73+
// simm7fp - Generic fp immediate value.
74+
def LO7FP : SDNodeXForm<fpimm, [{
75+
// Get a integer immediate from fpimm
76+
const APInt& imm = N->getValueAPF().bitcastToAPInt();
77+
uint64_t val = imm.getSExtValue();
78+
if (imm.getBitWidth() == 32)
79+
val <<= 32; // Immediate value of float place at higher bits on VE.
80+
return CurDAG->getTargetConstant(SignExtend32(val, 7), SDLoc(N), MVT::i32);
81+
}]>;
82+
def simm7fp : Operand<i32>, PatLeaf<(fpimm), [{
83+
const APInt& imm = N->getValueAPF().bitcastToAPInt();
84+
uint64_t val = imm.getSExtValue();
85+
if (imm.getBitWidth() == 32)
86+
val <<= 32; // Immediate value of float place at higher bits on VE.
87+
return isInt<7>(val);
88+
}], LO7FP> {
89+
let DecoderMethod = "DecodeSIMM7";
90+
}
91+
92+
// mimm - Special fp immediate value of sequential bit stream of 0 or 1.
93+
def MIMMFP : SDNodeXForm<fpimm, [{
94+
const APInt& Imm = N->getValueAPF().bitcastToAPInt();
95+
uint64_t Val = Imm.getSExtValue();
96+
bool M0Flag = isMask_64(Val);
97+
if (Imm.getBitWidth() == 32)
98+
Val <<= 32; // Immediate value of float place at higher bits on VE.
99+
if (M0Flag) {
100+
// bit 6 : If `(m)0`, 1. Otherwise, 0.
101+
Val = countLeadingZeros(Val) | 0x40;
102+
} else
103+
Val = countLeadingOnes(Val);
104+
return CurDAG->getTargetConstant(Val, SDLoc(N), MVT::i32);
105+
}]>;
106+
def mimmfp : Operand<i32>, PatLeaf<(fpimm), [{
107+
const APInt& Imm = N->getValueAPF().bitcastToAPInt();
108+
uint64_t Val = Imm.getSExtValue();
109+
return isMask_64(Val) ||
110+
((Val & (1UL << 63)) && isShiftedMask_64(Val)); }], MIMMFP> {
111+
let PrintMethod = "printMImmOperand";
112+
}
113+
73114
def simm32 : PatLeaf<(imm), [{ return isInt<32>(N->getSExtValue()); }]>;
74115
def uimm32 : PatLeaf<(imm), [{ return isUInt<32>(N->getZExtValue()); }]>;
75116
def lomsbzero : PatLeaf<(imm), [{ return (N->getZExtValue() & 0x80000000)
@@ -357,94 +398,79 @@ def RD_RA : RD_VAL<12>; // Round to Nearest (ties to Away)
357398
// VE Multiclasses for common instruction formats
358399
//===----------------------------------------------------------------------===//
359400

360-
multiclass RRmrr<string opcStr, bits<8>opc,
361-
RegisterClass RCo, ValueType Tyo,
362-
RegisterClass RCi, ValueType Tyi,
363-
SDPatternOperator OpNode=null_frag> {
401+
// Multiclass for generic RR type instructions
402+
let hasSideEffects = 0 in
403+
multiclass RRbm<string opcStr, bits<8>opc,
404+
RegisterClass RCo, ValueType Tyo,
405+
RegisterClass RCi, ValueType Tyi,
406+
SDPatternOperator OpNode = null_frag,
407+
Operand immOp = simm7, Operand mOp = mimm> {
364408
def rr : RR<opc, (outs RCo:$sx), (ins RCi:$sy, RCi:$sz),
365409
!strconcat(opcStr, " $sx, $sy, $sz"),
366-
[(set Tyo:$sx, (OpNode Tyi:$sy, Tyi:$sz))]>
367-
{ let cy = 1; let cz = 1; let hasSideEffects = 0; }
368-
}
369-
370-
multiclass RRmri<string opcStr, bits<8>opc,
371-
RegisterClass RCo, ValueType Tyo,
372-
RegisterClass RCi, ValueType Tyi, Operand immOp,
373-
SDPatternOperator OpNode=null_frag> {
410+
[(set Tyo:$sx, (OpNode Tyi:$sy, Tyi:$sz))]>;
374411
// VE calculates (OpNode $sy, $sz), but llvm requires to have immediate
375412
// in RHS, so we use following definition.
413+
let cy = 0 in
376414
def ri : RR<opc, (outs RCo:$sx), (ins RCi:$sz, immOp:$sy),
377415
!strconcat(opcStr, " $sx, $sy, $sz"),
378-
[(set Tyo:$sx, (OpNode Tyi:$sz, (Tyi simm7:$sy)))]>
379-
{ let cy = 0; let cz = 1; let hasSideEffects = 0; }
380-
}
381-
382-
multiclass RRmir<string opcStr, bits<8>opc,
383-
RegisterClass RCo, ValueType Tyo,
384-
RegisterClass RCi, ValueType Tyi, Operand immOp,
385-
SDPatternOperator OpNode=null_frag> {
386-
def ri : RR<opc, (outs RCo:$sx), (ins immOp:$sy, RCi:$sz),
416+
[(set Tyo:$sx, (OpNode Tyi:$sz, (Tyi immOp:$sy)))]>;
417+
let cz = 0 in
418+
def rm : RR<opc, (outs RCo:$sx), (ins RCi:$sy, mOp:$sz),
387419
!strconcat(opcStr, " $sx, $sy, $sz"),
388-
[(set Tyo:$sx, (OpNode (Tyi simm7:$sy), Tyi:$sz))]>
389-
{ let cy = 0; let cz = 1; let hasSideEffects = 0; }
420+
[(set Tyo:$sx, (OpNode Tyi:$sy, (Tyi mOp:$sz)))]>;
421+
let cy = 0, cz = 0 in
422+
def im : RR<opc, (outs RCo:$sx), (ins immOp:$sy, mOp:$sz),
423+
!strconcat(opcStr, " $sx, $sy, $sz"),
424+
[(set Tyo:$sx, (OpNode (Tyi immOp:$sy), (Tyi mOp:$sz)))]>;
390425
}
391426

392-
multiclass RRNDmrm<string opcStr, bits<8>opc,
393-
RegisterClass RCo, ValueType Tyo,
394-
RegisterClass RCi, ValueType Tyi, Operand mOp,
395-
SDPatternOperator OpNode=null_frag> {
396-
let cy = 1, cz = 0, hasSideEffects = 0 in
427+
// Multiclass for non-commutative RR type instructions
428+
let hasSideEffects = 0 in
429+
multiclass RRNCbm<string opcStr, bits<8>opc,
430+
RegisterClass RCo, ValueType Tyo,
431+
RegisterClass RCi, ValueType Tyi,
432+
SDPatternOperator OpNode = null_frag,
433+
Operand immOp = simm7, Operand mOp = mimm> {
434+
def rr : RR<opc, (outs RCo:$sx), (ins RCi:$sy, RCi:$sz),
435+
!strconcat(opcStr, " $sx, $sy, $sz"),
436+
[(set Tyo:$sx, (OpNode Tyi:$sy, Tyi:$sz))]>;
437+
let cy = 0 in
438+
def ir : RR<opc, (outs RCo:$sx), (ins immOp:$sy, RCi:$sz),
439+
!strconcat(opcStr, " $sx, $sy, $sz"),
440+
[(set Tyo:$sx, (OpNode (Tyi immOp:$sy), Tyi:$sz))]>;
441+
let cz = 0 in
397442
def rm : RR<opc, (outs RCo:$sx), (ins RCi:$sy, mOp:$sz),
398443
!strconcat(opcStr, " $sx, $sy, $sz"),
399444
[(set Tyo:$sx, (OpNode Tyi:$sy, (Tyi mOp:$sz)))]>;
400-
}
401-
402-
multiclass RRNDmim<string opcStr, bits<8>opc,
403-
RegisterClass RCo, ValueType Tyo,
404-
RegisterClass RCi, ValueType Tyi,
405-
Operand immOp, Operand mOp,
406-
SDPatternOperator OpNode=null_frag> {
407-
let cy = 0, cz = 0, hasSideEffects = 0 in
445+
let cy = 0, cz = 0 in
408446
def im : RR<opc, (outs RCo:$sx), (ins immOp:$sy, mOp:$sz),
409447
!strconcat(opcStr, " $sx, $sy, $sz"),
410448
[(set Tyo:$sx, (OpNode (Tyi immOp:$sy), (Tyi mOp:$sz)))]>;
411449
}
412450

413-
// Used by add, mul, div, and similar commutative instructions
414-
// The order of operands are "$sx, $sy, $sz"
415-
451+
// Generic RR multiclass with 2 arguments.
452+
// e.g. ADDUL, ADDSWSX, ADDSWZX, and etc.
416453
multiclass RRm<string opcStr, bits<8>opc,
417454
RegisterClass RC, ValueType Ty,
418455
SDPatternOperator OpNode = null_frag,
419456
Operand immOp = simm7, Operand mOp = mimm> :
420-
RRmrr<opcStr, opc, RC, Ty, RC, Ty, OpNode>,
421-
RRmri<opcStr, opc, RC, Ty, RC, Ty, immOp, OpNode>,
422-
RRNDmrm<opcStr, opc, RC, Ty, RC, Ty, mOp, OpNode>,
423-
RRNDmim<opcStr, opc, RC, Ty, RC, Ty, immOp, mOp, OpNode>;
424-
425-
// Used by sub, and similar not commutative instructions
426-
// The order of operands are "$sx, $sy, $sz"
457+
RRbm<opcStr, opc, RC, Ty, RC, Ty, OpNode, immOp, mOp>;
427458

459+
// Generic RR multiclass for non-commutative instructions with 2 arguments.
460+
// e.g. SUBUL, SUBUW, SUBSWSX, and etc.
428461
multiclass RRNCm<string opcStr, bits<8>opc,
429-
RegisterClass RC, ValueType Ty,
430-
SDPatternOperator OpNode = null_frag,
431-
Operand immOp = simm7, Operand mOp = mimm> :
432-
RRmrr<opcStr, opc, RC, Ty, RC, Ty, OpNode>,
433-
RRmir<opcStr, opc, RC, Ty, RC, Ty, immOp, OpNode>,
434-
RRNDmrm<opcStr, opc, RC, Ty, RC, Ty, mOp, OpNode>,
435-
RRNDmim<opcStr, opc, RC, Ty, RC, Ty, immOp, mOp, OpNode>;
436-
437-
// Used by fadd, fsub, and similar floating point instructions
438-
// The order of operands are "$sx, $sy, $sz"
462+
RegisterClass RC, ValueType Ty,
463+
SDPatternOperator OpNode = null_frag,
464+
Operand immOp = simm7, Operand mOp = mimm> :
465+
RRNCbm<opcStr, opc, RC, Ty, RC, Ty, OpNode, immOp, mOp>;
439466

467+
// Generic RR multiclass for floating point instructions with 2 arguments.
468+
// e.g. FADDD, FADDS, FSUBD, and etc.
440469
multiclass RRFm<string opcStr, bits<8>opc,
441-
RegisterClass RC, ValueType Ty,
442-
SDPatternOperator OpNode = null_frag,
443-
Operand immOp = simm7, Operand mOp = mimm> :
444-
RRmrr<opcStr, opc, RC, Ty, RC, Ty, OpNode>,
445-
RRmir<opcStr, opc, RC, Ty, RC, Ty, immOp, null_frag>,
446-
RRNDmrm<opcStr, opc, RC, Ty, RC, Ty, mOp, null_frag>,
447-
RRNDmim<opcStr, opc, RC, Ty, RC, Ty, immOp, mOp, null_frag>;
470+
RegisterClass RC, ValueType Ty,
471+
SDPatternOperator OpNode = null_frag,
472+
Operand immOp = simm7fp, Operand mOp = mimmfp> :
473+
RRNCbm<opcStr, opc, RC, Ty, RC, Ty, OpNode, immOp, mOp>;
448474

449475
// Generic RR multiclass for shift instructions with 2 arguments.
450476
// e.g. SLL, SRL, SLAWSX, and etc.

llvm/test/CodeGen/VE/fp_add.ll

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,21 @@ define double @func8(double %a) {
6161
%r = fadd double %a, 0x7FEFFFFFFFFFFFFF
6262
ret double %r
6363
}
64+
65+
define float @fadds_imm(float %a) {
66+
; CHECK-LABEL: fadds_imm:
67+
; CHECK: .LBB{{[0-9]+}}_2:
68+
; CHECK-NEXT: fadd.s %s0, %s0, (2)1
69+
; CHECK-NEXT: or %s11, 0, %s9
70+
%r = fadd float %a, -2.e+00
71+
ret float %r
72+
}
73+
74+
define double @faddd_imm(double %a) {
75+
; CHECK-LABEL: faddd_imm:
76+
; CHECK: .LBB{{[0-9]+}}_2:
77+
; CHECK-NEXT: fadd.d %s0, %s0, (2)1
78+
; CHECK-NEXT: or %s11, 0, %s9
79+
%r = fadd double %a, -2.e+00
80+
ret double %r
81+
}

llvm/test/CodeGen/VE/fp_mul.ll

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,40 @@ define double @func8(double %a) {
6161
%r = fmul double %a, 0x7FEFFFFFFFFFFFFF
6262
ret double %r
6363
}
64+
65+
define float @fmuls_ir(float %a) {
66+
; CHECK-LABEL: fmuls_ir:
67+
; CHECK: .LBB{{[0-9]+}}_2:
68+
; CHECK-NEXT: fmul.s %s0, 0, %s0
69+
; CHECK-NEXT: or %s11, 0, %s9
70+
%r = fmul float 0.e+00, %a
71+
ret float %r
72+
}
73+
74+
define float @fmuls_ri(float %a) {
75+
; CHECK-LABEL: fmuls_ri:
76+
; CHECK: .LBB{{[0-9]+}}_2:
77+
; CHECK-NEXT: fmul.s %s0, %s0, (2)1
78+
; CHECK-NEXT: or %s11, 0, %s9
79+
%r = fmul float %a, -2.
80+
ret float %r
81+
}
82+
83+
define float @fmuls_ri2(float %a) {
84+
; CHECK-LABEL: fmuls_ri2:
85+
; CHECK: .LBB{{[0-9]+}}_2:
86+
; CHECK-NEXT: fmul.s %s0, %s0, (3)1
87+
; CHECK-NEXT: or %s11, 0, %s9
88+
%r = fmul float %a, -36893488147419103232.
89+
ret float %r
90+
}
91+
92+
define float @fmuls_ri3(float %a) {
93+
; CHECK-LABEL: fmuls_ri3:
94+
; CHECK: .LBB{{[0-9]+}}_2:
95+
; CHECK-NEXT: fmul.s %s0, %s0, (9)0
96+
; CHECK-NEXT: or %s11, 0, %s9
97+
%r = fmul float %a, 1.175494210692441075487029444849287348827052428745893333857174530571588870475618904265502351336181163787841796875E-38
98+
ret float %r
99+
}
100+

llvm/test/CodeGen/VE/fp_sub.ll

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,21 @@ define double @func8(double %a) {
6161
%r = fadd double %a, 0xFFEFFFFFFFFFFFFF
6262
ret double %r
6363
}
64+
65+
define float @fsubs_ir(float %a) {
66+
; CHECK-LABEL: fsubs_ir:
67+
; CHECK: .LBB{{[0-9]+}}_2:
68+
; CHECK-NEXT: fsub.s %s0, 0, %s0
69+
; CHECK-NEXT: or %s11, 0, %s9
70+
%r = fsub float 0.e+00, %a
71+
ret float %r
72+
}
73+
74+
define float @fsubs_ri(float %a) {
75+
; CHECK-LABEL: fsubs_ri:
76+
; CHECK: .LBB{{[0-9]+}}_2:
77+
; CHECK-NEXT: fadd.s %s0, %s0, (2)1
78+
; CHECK-NEXT: or %s11, 0, %s9
79+
%r = fsub float %a, 2.0e+00
80+
ret float %r
81+
}

0 commit comments

Comments
 (0)