Why does this code get constant-folded, even if I specified "-O0"?

Hi all,

I want to profile some LLVM IR instructions. If this was ARM assembly, I’d just run a single instruction copied, say, 200 times in a loop (so to dampen the jump cost), a-là .rept. In LLVM IR, I thought about doing this:

; Function Attrs: noinline nounwind optnone
define dso_local i32 @main() #0 !dbg !400 {
entry:
  ; some initialization code

  call void @llvm.dbg.declare(metadata ptr %temp, metadata !413, metadata !DIExpression()), !dbg !416
  store i32 269488144, ptr %temp, align 4, !dbg !416
  br label %while.body, !dbg !417

while.body:                                       ; preds = %entry, %while.body
  %0 = load i32, ptr %temp, align 4, !dbg !418
  ; INJECTION SITE
  %1 = add nsw i32 %0, 1
  %2 = add nsw i32 %1, 1
  %3 = add nsw i32 %2, 1
  %4 = add nsw i32 %3, 1
  %5 = add nsw i32 %4, 1
  %6 = add nsw i32 %5, 1
  %7 = add nsw i32 %6, 1
  %8 = add nsw i32 %7, 1
  %9 = add nsw i32 %8, 1
  %10 = add nsw i32 %9, 1
  %11 = add nsw i32 %10, 1
  %12 = add nsw i32 %11, 1
  %13 = add nsw i32 %12, 1
  %14 = add nsw i32 %13, 1
  %15 = add nsw i32 %14, 1
  %16 = add nsw i32 %15, 1
  %17 = add nsw i32 %16, 1
  %18 = add nsw i32 %17, 1
  %19 = add nsw i32 %18, 1
  %20 = add nsw i32 %19, 1
  %21 = add nsw i32 %20, 1
  %22 = add nsw i32 %21, 1
  %23 = add nsw i32 %22, 1
  %24 = add nsw i32 %23, 1
  %25 = add nsw i32 %24, 1
  %26 = add nsw i32 %25, 1
  %27 = add nsw i32 %26, 1
  %28 = add nsw i32 %27, 1
  %29 = add nsw i32 %28, 1
  %30 = add nsw i32 %29, 1
  %31 = add nsw i32 %30, 1
  %32 = add nsw i32 %31, 1
  %33 = add nsw i32 %32, 1
  %34 = add nsw i32 %33, 1
  %35 = add nsw i32 %34, 1
  %36 = add nsw i32 %35, 1
  %37 = add nsw i32 %36, 1
  %38 = add nsw i32 %37, 1
  %39 = add nsw i32 %38, 1
  %40 = add nsw i32 %39, 1
  %41 = add nsw i32 %40, 1
  %42 = add nsw i32 %41, 1
  %43 = add nsw i32 %42, 1
  %44 = add nsw i32 %43, 1
  %45 = add nsw i32 %44, 1
  %46 = add nsw i32 %45, 1
  %47 = add nsw i32 %46, 1
  %48 = add nsw i32 %47, 1
  %49 = add nsw i32 %48, 1
  %50 = add nsw i32 %49, 1
  %51 = add nsw i32 %50, 1
  %52 = add nsw i32 %51, 1
  %53 = add nsw i32 %52, 1
  %54 = add nsw i32 %53, 1
  %55 = add nsw i32 %54, 1
  %56 = add nsw i32 %55, 1
  %57 = add nsw i32 %56, 1
  %58 = add nsw i32 %57, 1
  %59 = add nsw i32 %58, 1
  %60 = add nsw i32 %59, 1
  %61 = add nsw i32 %60, 1
  %62 = add nsw i32 %61, 1
  %63 = add nsw i32 %62, 1
  %64 = add nsw i32 %63, 1
  %65 = add nsw i32 %64, 1
  %66 = add nsw i32 %65, 1
  %67 = add nsw i32 %66, 1
  %68 = add nsw i32 %67, 1
  %69 = add nsw i32 %68, 1
  %70 = add nsw i32 %69, 1
  %71 = add nsw i32 %70, 1
  %72 = add nsw i32 %71, 1
  %73 = add nsw i32 %72, 1
  %74 = add nsw i32 %73, 1
  %75 = add nsw i32 %74, 1
  %76 = add nsw i32 %75, 1
  %77 = add nsw i32 %76, 1
  %78 = add nsw i32 %77, 1
  %79 = add nsw i32 %78, 1
  %80 = add nsw i32 %79, 1
  %81 = add nsw i32 %80, 1
  %82 = add nsw i32 %81, 1
  %83 = add nsw i32 %82, 1
  %84 = add nsw i32 %83, 1
  %85 = add nsw i32 %84, 1
  %86 = add nsw i32 %85, 1
  %87 = add nsw i32 %86, 1
  %88 = add nsw i32 %87, 1
  %89 = add nsw i32 %88, 1
  %90 = add nsw i32 %89, 1
  %91 = add nsw i32 %90, 1
  %92 = add nsw i32 %91, 1
  %93 = add nsw i32 %92, 1
  %94 = add nsw i32 %93, 1
  %95 = add nsw i32 %94, 1
  %96 = add nsw i32 %95, 1
  %97 = add nsw i32 %96, 1
  %98 = add nsw i32 %97, 1
  %99 = add nsw i32 %98, 1
  %100 = add nsw i32 %99, 1
  %101 = add nsw i32 %100, 1
  %102 = add nsw i32 %101, 1
  %103 = add nsw i32 %102, 1
  %104 = add nsw i32 %103, 1
  %105 = add nsw i32 %104, 1
  %106 = add nsw i32 %105, 1
  %107 = add nsw i32 %106, 1
  %108 = add nsw i32 %107, 1
  %109 = add nsw i32 %108, 1
  %110 = add nsw i32 %109, 1
  %111 = add nsw i32 %110, 1
  %112 = add nsw i32 %111, 1
  %113 = add nsw i32 %112, 1
  %114 = add nsw i32 %113, 1
  %115 = add nsw i32 %114, 1
  %116 = add nsw i32 %115, 1
  %117 = add nsw i32 %116, 1
  %118 = add nsw i32 %117, 1
  %119 = add nsw i32 %118, 1
  %120 = add nsw i32 %119, 1
  %121 = add nsw i32 %120, 1
  %122 = add nsw i32 %121, 1
  %123 = add nsw i32 %122, 1
  %124 = add nsw i32 %123, 1
  %125 = add nsw i32 %124, 1
  %126 = add nsw i32 %125, 1
  %127 = add nsw i32 %126, 1
  %128 = add nsw i32 %127, 1
  %129 = add nsw i32 %128, 1
  %130 = add nsw i32 %129, 1
  %131 = add nsw i32 %130, 1
  %132 = add nsw i32 %131, 1
  %133 = add nsw i32 %132, 1
  %134 = add nsw i32 %133, 1
  %135 = add nsw i32 %134, 1
  %136 = add nsw i32 %135, 1
  %137 = add nsw i32 %136, 1
  %138 = add nsw i32 %137, 1
  %139 = add nsw i32 %138, 1
  %140 = add nsw i32 %139, 1
  %141 = add nsw i32 %140, 1
  %142 = add nsw i32 %141, 1
  %143 = add nsw i32 %142, 1
  %144 = add nsw i32 %143, 1
  %145 = add nsw i32 %144, 1
  %146 = add nsw i32 %145, 1
  %147 = add nsw i32 %146, 1
  %148 = add nsw i32 %147, 1
  %149 = add nsw i32 %148, 1
  %150 = add nsw i32 %149, 1
  %151 = add nsw i32 %150, 1
  %152 = add nsw i32 %151, 1
  %153 = add nsw i32 %152, 1
  %154 = add nsw i32 %153, 1
  %155 = add nsw i32 %154, 1
  %156 = add nsw i32 %155, 1
  %157 = add nsw i32 %156, 1
  %158 = add nsw i32 %157, 1
  %159 = add nsw i32 %158, 1
  %160 = add nsw i32 %159, 1
  %161 = add nsw i32 %160, 1
  %162 = add nsw i32 %161, 1
  %163 = add nsw i32 %162, 1
  %164 = add nsw i32 %163, 1
  %165 = add nsw i32 %164, 1
  %166 = add nsw i32 %165, 1
  %167 = add nsw i32 %166, 1
  %168 = add nsw i32 %167, 1
  %169 = add nsw i32 %168, 1
  %170 = add nsw i32 %169, 1
  %171 = add nsw i32 %170, 1
  %172 = add nsw i32 %171, 1
  %173 = add nsw i32 %172, 1
  %174 = add nsw i32 %173, 1
  %175 = add nsw i32 %174, 1
  %176 = add nsw i32 %175, 1
  %177 = add nsw i32 %176, 1
  %178 = add nsw i32 %177, 1
  %179 = add nsw i32 %178, 1
  %180 = add nsw i32 %179, 1
  %181 = add nsw i32 %180, 1
  %182 = add nsw i32 %181, 1
  %183 = add nsw i32 %182, 1
  %184 = add nsw i32 %183, 1
  %185 = add nsw i32 %184, 1
  %186 = add nsw i32 %185, 1
  %187 = add nsw i32 %186, 1
  %188 = add nsw i32 %187, 1
  %189 = add nsw i32 %188, 1
  %190 = add nsw i32 %189, 1
  %191 = add nsw i32 %190, 1
  %192 = add nsw i32 %191, 1
  %193 = add nsw i32 %192, 1
  %194 = add nsw i32 %193, 1
  %195 = add nsw i32 %194, 1
  %196 = add nsw i32 %195, 1
  %197 = add nsw i32 %196, 1
  %198 = add nsw i32 %197, 1
  %199 = add nsw i32 %198, 1
  %200 = add nsw i32 %199, 1
  store i32 %200, ptr %temp, align 4

  ; END INJECTION SITE

; %add = add nsw i32 %0, 1, !dbg !418
  ; store i32 %add, ptr %temp, align 4, !dbg !418
  br label %while.body, !dbg !417, !llvm.loop !420
}

This, however, gets compiled to this binary:

Disassembly of section .text:

08000298 <main>:
 8000298:	b580      	push	{r7, lr}
 800029a:	466f      	mov	r7, sp
 800029c:	b084      	sub	sp, #16
 800029e:	2000      	movs	r0, #0
 80002a0:	9003      	str	r0, [sp, #12]
                        ; some calls
 80002c2:	f04f 3010 	mov.w	r0, #269488144	; 0x10101010
 80002c6:	9002      	str	r0, [sp, #8]
 80002c8:	e7ff      	b.n	80002ca <main+0x32>
 80002ca:	9802      	ldr	r0, [sp, #8]
 80002cc:	30c8      	adds	r0, #200	; 0xc8 ; HERE!
 80002ce:	9002      	str	r0, [sp, #8]
 80002d0:	e7fb      	b.n	80002ca <main+0x32>

Notice that the 200 add instructions get folded into a single adds r0, #200. However, I compiled with -O0, and you can see later in the file

attributes #0 = { noinline nounwind optnone "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="cortex-m4" "target-features"="+armv7e-m,+dsp,+fp16,+hwdiv,+strict-align,+thumb-mode,+vfp2sp,+vfp3d16sp,+vfp4d16sp,-aes,-d32,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16fml,-fp64,-fullfp16,-neon,-sha2,-vfp2,-vfp3,-vfp3d16,-vfp3sp,-vfp4,-vfp4d16,-vfp4sp" }

that optnone is present. Why is that? How can I get the 200 instructions?

Thanks!

I think it depends on the way you compile it. Here we see 200 hundred adds in assembly.

True, but not if I need ARM syntax

Yes, missed that, sorry. It seems that it is ARM specific problem as X86 and AArch64 do not optimize it.

if you check out the LLVM Opt Pipeline view, it shows that the optimization happened in (SelectionDAG) ISel so my guess is that DAGCombiner did something to it, despite in O0.