[llvm-dev] Instruction selection problem with type i64 - mistaken as v8i64?
Alex Susu via llvm-dev
llvm-dev at lists.llvm.org
Tue Jun 28 12:43:37 PDT 2016
Hello.
I am writing a back end in which I combined the existing BPF LLVM back end with the
Mips MSA vector extensions (from the Mips back end)
I have encountered an error when compiling with llc: the instruction selector uses a
vector register instead of a scalar register with type i64 .
I have the following part of LLVM IR program:
vector.body.preheader: ; preds = %min.iters.checked
br label %vector.body
vector.body: ; preds = %vector.body.preheader,
%vector.body
%index = phi i64 [ %index.next, %vector.body ], [ 0, %vector.body.preheader ]
%vec.phi = phi <8 x i64> [ %0, %vector.body ], [ zeroinitializer,
%vector.body.preheader ]
The ASM code generated from it is the following:
LBB0_3: // %vector.body.preheader
REGVEC0 = 0
mov r0, 0
std -48(r10), r0
std -128(r10), REGVEC0
jmp LBB0_4
LBB0_4: // %vector.body
ldd REGVEC0, -128(r10)
ldd r0, -48(r10)
I am surprised that the BPF scalar instructions ldd and std use vector register
REGVEC0, which have type v8i64.
For example, the TableGen definition of the LOAD instruction taken from
BPFInstrInfo.td is:
class LOADi64<bits<2> SizeOp, string OpcodeStr, PatFrag OpNode>
: LOAD<SizeOp, OpcodeStr, [(set i64:$dst, (OpNode ADDRri:$addr))]>;
So I am surprised that the instruction selector finds as match for operand i64:$dst
the vector register REGVEC0, which has type v8i64 as defined below, inspired from
lib/Target/Mips/MipsRegisterInfo.td:
def MSA128D: RegisterClass<"Connex", [v8i64], 512,
(sequence "Wd%u", 0, 31)>;
Can anybody help with an idea what I can do to fix this problem?
Below are a few possibly useful lines from the output of llc, related to the instr.
selection and register allocation of the above piece of code:
===== Instruction selection ends:
Selected selection DAG: BB#3 'foo:vector.body.preheader'
SelectionDAG has 11 nodes:
t0: ch = EntryToken
t1: i64 = MOV_ri TargetConstant:i64<0>
t3: ch = CopyToReg t0, Register:i64 %vreg23, t1
t11: v8i64 = VLOAD_D TargetConstant:i64<0>
t6: ch = CopyToReg t0, Register:v8i64 %vreg24, t11
t8: ch = TokenFactor t3, t6
t9: ch = JMP BasicBlock:ch<vector.body 0xa61440>, t8
[...]
Spilling live registers at end of block.
Spilling %vreg31 in %R0 to stack slot #5
Spilling %vreg32 in %Wd0 to stack slot #6
BB#3: derived from LLVM BB %vector.body.preheader
Predecessors according to CFG: BB#2
%Wd0<def> = VLOAD_D 0
%R0<def> = MOV_ri 0
STD %R0<kill>, <fi#5>, 0
STD %Wd0<kill>, <fi#6>, 0
JMP <BB#4>
Successors according to CFG: BB#4(0)
[...]
>> JMP <BB#5>
Regs: R0 R1=%vreg31* R2=%vreg0 Wd0=%vreg32* Wd1
<< JMP <BB#5>
Spilling live registers at end of block.
Spilling %vreg31 in %R1 to stack slot #5
Spilling %vreg32 in %Wd0 to stack slot #6
BB#4: derived from LLVM BB %vector.body
Predecessors according to CFG: BB#3 BB#4
%Wd0<def> = LDD <fi#6>, 0
%R0<def> = LDD <fi#5>, 0
INLINEASM <es:int index;
for (index = 0; index < N - (N % 8); index += 8) {.
_BEGIN_KERNEL(BatchNumber);
EXECUTE_IN_ALL(> [sideeffect] [attdialect]
INLINEASM <es:connex->writeDataToArray(&C[index], /*numVectors*/ 1, /*offset*/
3);> [sideeffect] [attdialect]
%Wd1<def> = LD_D 3; mem:LD64[inttoptr (i64 3 to <8 x i64>*)](align=8)
%Wd0<def> = ADDV_D %Wd1<kill>, %Wd0<kill>
INLINEASM <es: );.
_END_KERNEL(BatchNumber);
connex->executeKernel(TEST_PREFIX + to_string((long long int)BatchNumber));
connex->executeKernel("waitfor");
connex->readReduction();
[...]
BB#6: derived from LLVM BB %for.body.preheader8
Predecessors according to CFG: BB#1 BB#2 BB#5
%R0<def> = LDD <fi#3>, 0
%R1<def> = MOV_ri 0
STD %R0<kill>, <fi#7>, 0
STD %R1<kill>, <fi#8>, 0
JMP <BB#7>
Successors according to CFG: BB#7(0)
Thank you,
Alex
More information about the llvm-dev
mailing list