Processing in the middle of transforming IR to DAG

I have a question about processing in the middle of transforming IR to DAG.

I tried to compile the following C source code.

int main() {
    int n = 1000;
    short A[n];
    short B[n];
    for(int i = 0; i < n; i++) {
        A[i] = i;
        B[i] = i*2;
    }
    return A[0]+B[0];
}

I executed the following command.

$ ../build/bin/clang --target=riscv64-pc_linux-gnu -O2 -S -emit-llvm hoge.c -o hoge.ll

This is the output.

; ModuleID = 'intermediate/hello.ll'
source_filename = "src/main.c"
target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n64-S128"
target triple = "riscv64-pc_linux-unknown-gnu"

; Function Attrs: norecurse nounwind readnone
define dso_local signext i32 @main() local_unnamed_addr #0 {
  %1 = alloca [1000 x i16], align 2
  %2 = alloca [1000 x i16], align 2
  br label %11

3:                                                ; preds = %11
  %4 = getelementptr inbounds [1000 x i16], [1000 x i16]* %2, i64 0, i64 0
  %5 = getelementptr inbounds [1000 x i16], [1000 x i16]* %1, i64 0, i64 0
  %6 = load i16, i16* %5, align 2, !tbaa !4
  %7 = sext i16 %6 to i32
  %8 = load i16, i16* %4, align 2, !tbaa !4
  %9 = sext i16 %8 to i32
  %10 = add nsw i32 %9, %7
  ret i32 %10

11:                                               ; preds = %11, %0
  %12 = phi i64 [ 0, %0 ], [ %18, %11 ]
  %13 = phi i32 [ 0, %0 ], [ %19, %11 ]
  %14 = trunc i32 %13 to i16
  %15 = getelementptr inbounds [1000 x i16], [1000 x i16]* %1, i64 0, i64 %12
  store i16 %14, i16* %15, align 2, !tbaa !4
  %16 = shl nuw nsw i16 %14, 1
  %17 = getelementptr inbounds [1000 x i16], [1000 x i16]* %2, i64 0, i64 %12
  store i16 %16, i16* %17, align 2, !tbaa !4
  %18 = add nuw nsw i64 %12, 1
  %19 = add nuw nsw i32 %13, 1
  %20 = icmp eq i64 %18, 1000
  br i1 %20, label %3, label %11, !llvm.loop !8
}

attributes #0 = { norecurse nounwind readnone "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+a,+c,+m,+relax,-save-restore" "unsafe-fp-math"="false" "use-soft-float"="false" }

!llvm.module.flags = !{!0, !1, !2}
!llvm.ident = !{!3}

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 1, !"target-abi", !"lp64"}
!2 = !{i32 1, !"SmallDataLimit", i32 8}
!3 = !{!"clang version 12.0.1"}
!4 = !{!5, !5, i64 0}
!5 = !{!"short", !6, i64 0}
!6 = !{!"omnipotent char", !7, i64 0}
!7 = !{!"Simple C/C++ TBAA"}
!8 = distinct !{!8, !9, !10}
!9 = !{!"llvm.loop.mustprogress"}
!10 = !{!"llvm.loop.unroll.disable"}

After that, I tried to debug using gdb at vscode while executing the following command.

$ ../build/bin/llc -march=rv64 -O2 hoge.ll 

, and I found that just before executing SelectionDAGBuilder::visit() function in SelectionDAGBuilder.cpp some llvm::Instructions have already been changed to different instructions like the following. This is a dump of instructions in each BasicBlock.

start block: 
alloca
alloca
br
start block: 
bitcast
bitcast
load
sext
load
sext
add
ret
start block: 
phi
phi
bitcast
bitcast
trunc
getelementptr
bitcast
store
shl
getelementptr
bitcast
store
add
add
icmp
br

As you see this, bitcast instructions are inserted. Where are the bitcast instructions inserted to the BasicBlock? If you know about it, please tell me the function which inserts bitcast instructions.

It could be codegenprepare - that’s just a guess though. You can add -print-before-all or -print-after-all to your llc command to print the IR before/after each pass (add -mllvm before each of those flags if you want to do this from clang instead of llc).

1 Like