cornell-zhang / heterocl

HeteroCL: A Multi-Paradigm Programming Infrastructure for Software-Defined Heterogeneous Computing
https://cornell-zhang.github.io/heterocl/
Apache License 2.0
322 stars 92 forks source link

Wrong IR generated from nested condition statements #224

Closed hecmay closed 4 years ago

hecmay commented 4 years ago

I was trying to write a gradient boost decision tree example in HeteroCL using imperative programing model. Here is a simple example of a single decision tree in HeteroCL DSL:

def kernel(inputs):
    pred_mat = hcl.compute((3*3,), lambda *args:0, "output")

    with hcl.for_(0,3) as x:
        with hcl.if_(inputs[((x*3) + 0)] <= 0.800000011920929):
            pred_mat[((x*3) + 0)] += 2.051282051282052
        with hcl.else_():
            pred_mat[((x*3) + 0)] += -0.9876543209876546

        # tree (1):
        with hcl.if_(inputs[((x*3) + 0)] <= 0.800000011920929):
            pred_mat[((x*3) + 1)] += -0.9638554216867468
        with hcl.else_():
            with hcl.if_(inputs[((x*3) + 0)] <= 1.75):
                with hcl.if_(inputs[((x*3) + 3)] <= 4.950000047683716):
                    with hcl.if_(inputs[((x*3) + 0)] <= 1.6500000357627869):
                        pred_mat[((x*3) + 1)] += 2.162162162162162
                    with hcl.else_():
                        pred_mat[((x*3) + 1)] += -0.963855421686747
                with hcl.else_():
                    with hcl.if_(inputs[((x*3) + 0)] <= 1.550000011920929):
                        pred_mat[((x*3) + 1)] += -0.963855421686747
                    with hcl.else_():
                        pred_mat[((x*3) + 1)] += 1.1201563008791924
            with hcl.else_():
                with hcl.if_(inputs[((x*3) + 3)] <= 4.8500001430511475):
                    with hcl.if_(inputs[((x*3) + 11)] <= 3.100000023841858):
                        pred_mat[((x*3) + 1)] += -0.963855421686747
                    with hcl.else_():
                        pred_mat[((x*3) + 1)] += 2.162162162162162
                with hcl.else_():
                    pred_mat[((x*3) + 1)] += -0.9638554216867468
    return pred_mat

hcl.init(hcl.Float())
inputs = hcl.placeholder((3*3,), "inputs")
s = hcl.create_schedule([inputs], kernel)
print(hcl.lower(s))

The IR generated from the HeteroCL program: As you can see, HeteroCL generates many else_if statements, which is not declared in the program at all.

// attr [_top] storage_scope = "global"
allocate _top[float32 * 1]
produce _top {
  // attr [0] extern_scope = 0
  produce output {
    // attr [0] extern_scope = 0
    for (args, 0, 9) {
      output[args] = 0.000000f
    }
  }
  for (i, 0, 3) {
    if ((inputs[(i*3)] <= 0.800000f)) {
      output[(i*3)] = (output[(i*3)] + 2.051282f)
      output[((i*3) + 1)] = (output[((i*3) + 1)] + -0.963855f)
    } else {
      output[(i*3)] = (output[(i*3)] + -0.987654f)
      if ((inputs[(i*3)] <= 1.750000f)) {
        if ((inputs[((i*3) + 3)] <= 4.950000f)) {
          if ((inputs[(i*3)] <= 1.650000f)) {
            output[((i*3) + 1)] = (output[((i*3) + 1)] + 2.162162f)
          } else {
            output[((i*3) + 1)] = (output[((i*3) + 1)] + -0.963855f)
          }
        } else if ((inputs[(i*3)] <= 1.550000f)) {
          output[((i*3) + 1)] = (output[((i*3) + 1)] + -0.963855f)
        } else {
          output[((i*3) + 1)] = (output[((i*3) + 1)] + 1.120156f)
        }
      } else if ((inputs[((i*3) + 3)] <= 4.850000f)) {
        if ((inputs[((i*3) + 11)] <= 3.100000f)) {
          output[((i*3) + 1)] = (output[((i*3) + 1)] + -0.963855f)
        } else {
          output[((i*3) + 1)] = (output[((i*3) + 1)] + 2.162162f)
        }
      } else {
        output[((i*3) + 1)] = (output[((i*3) + 1)] + -0.963855f)
      }
    }
  }
}
hecmay commented 4 years ago

The IR is correct. The nested else and if statements are merged into a new else_if statement here, so the functionality is the same.